diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-14 20:22:31 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-14 20:22:31 +0000 |
commit | cf562b77683aeb8458aa3040a45f35475b59b763 (patch) | |
tree | ab7cacd23c436d5594d049449a1cf0546f0f58b8 | |
parent | dc9df8abc079c3040d47d6b9bdd284d82766ab27 (diff) | |
download | chromium_src-cf562b77683aeb8458aa3040a45f35475b59b763.zip chromium_src-cf562b77683aeb8458aa3040a45f35475b59b763.tar.gz chromium_src-cf562b77683aeb8458aa3040a45f35475b59b763.tar.bz2 |
Rotate Cursor when the display is rotated
- moved Rotation enum from ash to gfx::Display so that
views/ui can use it.
- rotate image and hot point.
BUG=119268
TEST=covered by unit tests, and also test on device.
Review URL: https://chromiumcodereview.appspot.com/12666006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188174 0039d316-1c4b-4281-b951-d872f2087c98
32 files changed, 216 insertions, 140 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc index 62b33ba..c3a84fe 100644 --- a/ash/accelerators/accelerator_controller.cc +++ b/ash/accelerators/accelerator_controller.cc @@ -154,19 +154,19 @@ bool HandleRotateActiveWindow() { return true; } -const DisplayInfo::Rotation GetNextRotation(DisplayInfo::Rotation current) { +const gfx::Display::Rotation GetNextRotation(gfx::Display::Rotation current) { switch (current) { - case DisplayInfo::ROTATE_0: - return DisplayInfo::ROTATE_90; - case DisplayInfo::ROTATE_90: - return DisplayInfo::ROTATE_180; - case DisplayInfo::ROTATE_180: - return DisplayInfo::ROTATE_270; - case DisplayInfo::ROTATE_270: - return DisplayInfo::ROTATE_0; + case gfx::Display::ROTATE_0: + return gfx::Display::ROTATE_90; + case gfx::Display::ROTATE_90: + return gfx::Display::ROTATE_180; + case gfx::Display::ROTATE_180: + return gfx::Display::ROTATE_270; + case gfx::Display::ROTATE_270: + return gfx::Display::ROTATE_0; } NOTREACHED() << "Unknown rotation:" << current; - return DisplayInfo::ROTATE_0; + return gfx::Display::ROTATE_0; } // Rotates the screen. diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc index 60529eb..d48f306 100644 --- a/ash/display/display_controller.cc +++ b/ash/display/display_controller.cc @@ -38,13 +38,13 @@ #include "ui/base/x/x11_util.h" #endif // defined(OS_CHROMEOS) -DECLARE_WINDOW_PROPERTY_TYPE(ash::internal::DisplayInfo::Rotation); +DECLARE_WINDOW_PROPERTY_TYPE(gfx::Display::Rotation); namespace ash { namespace { -DEFINE_WINDOW_PROPERTY_KEY(internal::DisplayInfo::Rotation, kRotationKey, - internal::DisplayInfo::ROTATE_0); +DEFINE_WINDOW_PROPERTY_KEY(gfx::Display::Rotation, kRotationKey, + gfx::Display::ROTATE_0); // Primary display stored in global object as it can be // accessed after Shell is deleted. A separate display instance is created @@ -126,17 +126,17 @@ void RotateRootWindow(aura::RootWindow* root_window, #endif gfx::Transform rotate; switch (info.rotation()) { - case internal::DisplayInfo::ROTATE_0: + case gfx::Display::ROTATE_0: break; - case internal::DisplayInfo::ROTATE_90: + case gfx::Display::ROTATE_90: rotate.Translate(display.bounds().height(), 0); rotate.Rotate(90); break; - case internal::DisplayInfo::ROTATE_270: + case gfx::Display::ROTATE_270: rotate.Translate(0, display.bounds().width()); rotate.Rotate(270); break; - case internal::DisplayInfo::ROTATE_180: + case gfx::Display::ROTATE_180: rotate.Translate(display.bounds().width(), display.bounds().height()); rotate.Rotate(180); break; diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc index 628258ff..bd83e4d 100644 --- a/ash/display/display_controller_unittest.cc +++ b/ash/display/display_controller_unittest.cc @@ -496,11 +496,11 @@ TEST_F(DisplayControllerTest, CursorDeviceScaleFactorSwapPrimary) { EXPECT_EQ(1.0f, primary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); primary_root->MoveCursorTo(gfx::Point(50, 50)); - EXPECT_EQ(1.0f, test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); EXPECT_EQ(2.0f, secondary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); secondary_root->MoveCursorTo(gfx::Point(50, 50)); - EXPECT_EQ(2.0f, test_api.GetDeviceScaleFactor()); + EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor()); // Switch primary and secondary display_controller->SetPrimaryDisplay(secondary_display); @@ -510,23 +510,23 @@ TEST_F(DisplayControllerTest, CursorDeviceScaleFactorSwapPrimary) { EXPECT_EQ(1.0f, secondary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); secondary_root->MoveCursorTo(gfx::Point(50, 50)); - EXPECT_EQ(1.0f, test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); primary_root->MoveCursorTo(gfx::Point(50, 50)); EXPECT_EQ(2.0f, primary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); - EXPECT_EQ(2.0f, test_api.GetDeviceScaleFactor()); + EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor()); // Deleting 2nd display. UpdateDisplay("200x200"); RunAllPendingInMessageLoop(); // RootWindow is deleted in a posted task. // Cursor's device scale factor should be updated even without moving cursor. - EXPECT_EQ(1.0f, test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); primary_root->MoveCursorTo(gfx::Point(50, 50)); EXPECT_EQ(1.0f, primary_root->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); - EXPECT_EQ(1.0f, test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); } #if defined(OS_WIN) @@ -640,7 +640,7 @@ TEST_F(DisplayControllerTest, MAYBE_Rotate) { EXPECT_EQ("50,40", event_handler.GetLocationAndReset()); display_manager->SetDisplayRotation(display1.id(), - internal::DisplayInfo::ROTATE_90); + gfx::Display::ROTATE_90); EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); EXPECT_EQ("200,0 150x200", @@ -654,7 +654,7 @@ TEST_F(DisplayControllerTest, MAYBE_Rotate) { ScreenAsh::GetSecondaryDisplay().bounds().ToString()); display_manager->SetDisplayRotation(display2_id, - internal::DisplayInfo::ROTATE_270); + gfx::Display::ROTATE_270); EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); EXPECT_EQ("50,120 200x150", @@ -664,7 +664,7 @@ TEST_F(DisplayControllerTest, MAYBE_Rotate) { generator2.MoveMouseTo(50, 40); EXPECT_EQ("180,25", event_handler.GetLocationAndReset()); display_manager->SetDisplayRotation(display1.id(), - internal::DisplayInfo::ROTATE_180); + gfx::Display::ROTATE_180); EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); diff --git a/ash/display/display_info.cc b/ash/display/display_info.cc index 6a7fbcb..7715c82 100644 --- a/ash/display/display_info.cc +++ b/ash/display/display_info.cc @@ -56,7 +56,7 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec, } size_t count = Tokenize(main_spec, "/", &parts); - Rotation rotation(ROTATE_0); + gfx::Display::Rotation rotation(gfx::Display::ROTATE_0); bool has_overscan = false; if (count) { main_spec = parts[0]; @@ -69,13 +69,13 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec, has_overscan = true; break; case 'r': // rotate 90 degrees to 'right'. - rotation = ROTATE_90; + rotation = gfx::Display::ROTATE_90; break; case 'u': // 180 degrees, 'u'pside-down. - rotation = ROTATE_180; + rotation = gfx::Display::ROTATE_180; break; case 'l': // rotate 90 degrees to 'left'. - rotation = ROTATE_270; + rotation = gfx::Display::ROTATE_270; break; } } @@ -106,7 +106,7 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec, DisplayInfo::DisplayInfo() : id_(gfx::Display::kInvalidDisplayID), has_overscan_(false), - rotation_(ROTATE_0), + rotation_(gfx::Display::ROTATE_0), device_scale_factor_(1.0f), overscan_insets_in_dip_(0, 0, 0, 0), has_custom_overscan_insets_(false), @@ -119,7 +119,7 @@ DisplayInfo::DisplayInfo(int64 id, : id_(id), name_(name), has_overscan_(has_overscan), - rotation_(ROTATE_0), + rotation_(gfx::Display::ROTATE_0), device_scale_factor_(1.0f), overscan_insets_in_dip_(0, 0, 0, 0), has_custom_overscan_insets_(false), @@ -172,7 +172,8 @@ void DisplayInfo::UpdateDisplaySize() { overscan_insets_in_dip_.Set(0, 0, 0, 0); } - if (rotation_ == ROTATE_90 || rotation_ == ROTATE_270) + if (rotation_ == gfx::Display::ROTATE_90 || + rotation_ == gfx::Display::ROTATE_270) size_in_pixel_.SetSize(size_in_pixel_.height(), size_in_pixel_.width()); gfx::SizeF size_f(size_in_pixel_); size_f.Scale(ui_scale_); diff --git a/ash/display/display_info.h b/ash/display/display_info.h index 9a13a54..520a8f7 100644 --- a/ash/display/display_info.h +++ b/ash/display/display_info.h @@ -9,13 +9,10 @@ #include "ash/ash_export.h" #include "base/gtest_prod_util.h" +#include "ui/gfx/display.h" #include "ui/gfx/insets.h" #include "ui/gfx/rect.h" -namespace gfx { -class Display; -} - namespace ash { namespace internal { @@ -25,15 +22,6 @@ namespace internal { // This class is intentionally made copiable. class ASH_EXPORT DisplayInfo { public: - // Screen Rotation in clock-wise degrees. - // TODO(oshima): move his to gfx::Display. - enum Rotation { - ROTATE_0 = 0, - ROTATE_90, - ROTATE_180, - ROTATE_270, - }; - // Creates a DisplayInfo from string spec. 100+200-1440x800 creates display // whose size is 1440x800 at the location (100, 200) in host coordinates. // The format is @@ -81,8 +69,8 @@ class ASH_EXPORT DisplayInfo { // True if the display has overscan. bool has_overscan() const { return has_overscan_; } - void set_rotation(Rotation rotation) { rotation_ = rotation; } - Rotation rotation() const { return rotation_; } + void set_rotation(gfx::Display::Rotation rotation) { rotation_ = rotation; } + gfx::Display::Rotation rotation() const { return rotation_; } // Gets/Sets the device scale factor of the display. float device_scale_factor() const { return device_scale_factor_; } @@ -146,7 +134,7 @@ class ASH_EXPORT DisplayInfo { int64 id_; std::string name_; bool has_overscan_; - Rotation rotation_; + gfx::Display::Rotation rotation_; float device_scale_factor_; gfx::Rect bounds_in_pixel_; // The size of the display in use. The size can be different from the size diff --git a/ash/display/display_info_unittest.cc b/ash/display/display_info_unittest.cc index f77d2b5..6806915 100644 --- a/ash/display/display_info_unittest.cc +++ b/ash/display/display_info_unittest.cc @@ -16,32 +16,32 @@ TEST_F(DisplayInfoTest, CreateFromSpec) { EXPECT_EQ(10, info.id()); EXPECT_EQ("0,0 200x100", info.bounds_in_pixel().ToString()); EXPECT_EQ("200x100", info.size_in_pixel().ToString()); - EXPECT_EQ(DisplayInfo::ROTATE_0, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, info.rotation()); EXPECT_EQ("0,0,0,0", info.overscan_insets_in_dip().ToString()); EXPECT_EQ(1.0f, info.ui_scale()); info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/o", 10); EXPECT_EQ("10,20 300x400", info.bounds_in_pixel().ToString()); EXPECT_EQ("286x380", info.size_in_pixel().ToString()); - EXPECT_EQ(DisplayInfo::ROTATE_0, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, info.rotation()); EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString()); info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/ob", 10); EXPECT_EQ("10,20 300x400", info.bounds_in_pixel().ToString()); EXPECT_EQ("286x380", info.size_in_pixel().ToString()); - EXPECT_EQ(DisplayInfo::ROTATE_0, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_0, info.rotation()); EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString()); info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/or", 10); EXPECT_EQ("10,20 300x400", info.bounds_in_pixel().ToString()); EXPECT_EQ("380x286", info.size_in_pixel().ToString()); - EXPECT_EQ(DisplayInfo::ROTATE_90, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_90, info.rotation()); // TODO(oshima): This should be rotated too. Fix this. EXPECT_EQ("5,3,5,3", info.overscan_insets_in_dip().ToString()); info = DisplayInfo::CreateFromSpecWithID("10+20-300x400*2/l@1.5", 10); EXPECT_EQ("10,20 300x400", info.bounds_in_pixel().ToString()); - EXPECT_EQ(DisplayInfo::ROTATE_270, info.rotation()); + EXPECT_EQ(gfx::Display::ROTATE_270, info.rotation()); EXPECT_EQ(1.5f, info.ui_scale()); } diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc index b0d43db..ff9748d 100644 --- a/ash/display/display_manager.cc +++ b/ash/display/display_manager.cc @@ -172,7 +172,7 @@ void DisplayManager::ClearCustomOverscanInsets(int64 display_id) { } void DisplayManager::SetDisplayRotation(int64 display_id, - DisplayInfo::Rotation rotation) { + gfx::Display::Rotation rotation) { DisplayInfoList display_info_list; for (DisplayList::const_iterator iter = displays_.begin(); iter != displays_.end(); ++iter) { @@ -606,6 +606,7 @@ gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) { // by |DisplayController::UpdateDisplayBoundsForLayout|. new_display.SetScaleAndBounds( display_info.device_scale_factor(), gfx::Rect(bounds_in_pixel.size())); + new_display.set_rotation(display_info.rotation()); return new_display; } diff --git a/ash/display/display_manager.h b/ash/display/display_manager.h index e154e6f..cfc0cb6 100644 --- a/ash/display/display_manager.h +++ b/ash/display/display_manager.h @@ -84,7 +84,7 @@ class ASH_EXPORT DisplayManager : public aura::RootWindowObserver { void ClearCustomOverscanInsets(int64 display_id); // Sets the display's rotation. - void SetDisplayRotation(int64 display_id, DisplayInfo::Rotation rotation); + void SetDisplayRotation(int64 display_id, gfx::Display::Rotation rotation); // Returns the current overscan insets for the specified |display_id|. // Returns an empty insets (0, 0, 0, 0) if no insets are specified for diff --git a/ash/display/mouse_cursor_event_filter_unittest.cc b/ash/display/mouse_cursor_event_filter_unittest.cc index 1812944..a53fe76 100644 --- a/ash/display/mouse_cursor_event_filter_unittest.cc +++ b/ash/display/mouse_cursor_event_filter_unittest.cc @@ -321,13 +321,13 @@ TEST_F(MouseCursorEventFilterTest, CursorDeviceScaleFactor) { MouseCursorEventFilter* event_filter = Shell::GetInstance()->mouse_cursor_filter(); - EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); event_filter->WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200)); - EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); event_filter->WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200)); - EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); } } // namespace internal diff --git a/ash/shell.cc b/ash/shell.cc index 5588706..366d2e3 100644 --- a/ash/shell.cc +++ b/ash/shell.cc @@ -467,8 +467,7 @@ void Shell::Init() { aura::RootWindow* root_window = display_controller_->GetPrimaryRootWindow(); active_root_window_ = root_window; - cursor_manager_.SetDeviceScaleFactor( - root_window->AsRootWindowHostDelegate()->GetDeviceScaleFactor()); + cursor_manager_.SetDisplay(DisplayController::GetPrimaryDisplay()); #if !defined(OS_MACOSX) nested_dispatcher_controller_.reset(new NestedDispatcherController); diff --git a/ash/test/cursor_manager_test_api.cc b/ash/test/cursor_manager_test_api.cc index d3cf8f1..9de728b 100644 --- a/ash/test/cursor_manager_test_api.cc +++ b/ash/test/cursor_manager_test_api.cc @@ -8,6 +8,7 @@ #include "ash/test/shell_test_api.h" #include "ash/wm/ash_native_cursor_manager.h" #include "ash/wm/image_cursors.h" +#include "ui/gfx/display.h" #include "ui/views/corewm/cursor_manager.h" namespace ash { @@ -26,9 +27,9 @@ gfx::NativeCursor CursorManagerTestApi::GetCurrentCursor() const { cursor_manager_)->GetCurrentCursor(); } -float CursorManagerTestApi::GetDeviceScaleFactor() const { +gfx::Display CursorManagerTestApi::GetDisplay() const { return ShellTestApi(Shell::GetInstance()).ash_native_cursor_manager()-> - image_cursors_->GetDeviceScaleFactor(); + image_cursors_->GetDisplay(); } } // namespace test diff --git a/ash/test/cursor_manager_test_api.h b/ash/test/cursor_manager_test_api.h index 8299822..254be4f 100644 --- a/ash/test/cursor_manager_test_api.h +++ b/ash/test/cursor_manager_test_api.h @@ -8,6 +8,10 @@ #include "base/basictypes.h" #include "ui/gfx/native_widget_types.h" +namespace gfx { +class Display; +} + namespace views { namespace corewm { class CursorManager; @@ -24,7 +28,7 @@ class CursorManagerTestApi { ~CursorManagerTestApi(); gfx::NativeCursor GetCurrentCursor() const; - float GetDeviceScaleFactor() const; + gfx::Display GetDisplay() const; private: views::corewm::CursorManager* cursor_manager_; diff --git a/ash/wm/ash_native_cursor_manager.cc b/ash/wm/ash_native_cursor_manager.cc index 94a08bf..b02cf6a 100644 --- a/ash/wm/ash_native_cursor_manager.cc +++ b/ash/wm/ash_native_cursor_manager.cc @@ -52,10 +52,10 @@ AshNativeCursorManager::AshNativeCursorManager() AshNativeCursorManager::~AshNativeCursorManager() { } -void AshNativeCursorManager::SetDeviceScaleFactor( - float device_scale_factor, +void AshNativeCursorManager::SetDisplay( + const gfx::Display& display, views::corewm::NativeCursorManagerDelegate* delegate) { - if (image_cursors_->SetDeviceScaleFactor(device_scale_factor)) + if (image_cursors_->SetDisplay(display)) SetCursor(delegate->GetCurrentCursor(), delegate); } @@ -64,7 +64,8 @@ void AshNativeCursorManager::SetCursor( views::corewm::NativeCursorManagerDelegate* delegate) { gfx::NativeCursor new_cursor = cursor; image_cursors_->SetPlatformCursor(&new_cursor); - new_cursor.set_device_scale_factor(image_cursors_->GetDeviceScaleFactor()); + new_cursor.set_device_scale_factor( + image_cursors_->GetDisplay().device_scale_factor()); delegate->CommitCursor(new_cursor); diff --git a/ash/wm/ash_native_cursor_manager.h b/ash/wm/ash_native_cursor_manager.h index 2364c70..07a7168 100644 --- a/ash/wm/ash_native_cursor_manager.h +++ b/ash/wm/ash_native_cursor_manager.h @@ -36,8 +36,8 @@ class ASH_EXPORT AshNativeCursorManager friend class test::CursorManagerTestApi; // Overridden from views::corewm::NativeCursorManager: - virtual void SetDeviceScaleFactor( - float device_scale_factor, + virtual void SetDisplay( + const gfx::Display& display, views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; virtual void SetCursor( gfx::NativeCursor cursor, diff --git a/ash/wm/ash_native_cursor_manager_unittest.cc b/ash/wm/ash_native_cursor_manager_unittest.cc index 2312cab..7697621 100644 --- a/ash/wm/ash_native_cursor_manager_unittest.cc +++ b/ash/wm/ash_native_cursor_manager_unittest.cc @@ -48,11 +48,15 @@ typedef test::AshTestBase AshNativeCursorManagerTest; TEST_F(AshNativeCursorManagerTest, LockCursor) { CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager(); CursorManagerTestApi test_api(cursor_manager); + gfx::Display display(0); cursor_manager->SetCursor(ui::kCursorCopy); EXPECT_EQ(ui::kCursorCopy, test_api.GetCurrentCursor().native_type()); - cursor_manager->SetDeviceScaleFactor(2.0f); - EXPECT_EQ(2.0f, test_api.GetDeviceScaleFactor()); + display.set_device_scale_factor(2.0f); + display.set_rotation(gfx::Display::ROTATE_90); + cursor_manager->SetDisplay(display); + EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetDisplay().rotation()); EXPECT_TRUE(test_api.GetCurrentCursor().platform()); cursor_manager->LockCursor(); @@ -62,16 +66,19 @@ TEST_F(AshNativeCursorManagerTest, LockCursor) { cursor_manager->SetCursor(ui::kCursorPointer); EXPECT_EQ(ui::kCursorCopy, test_api.GetCurrentCursor().native_type()); - // Device scale factor does change even while cursor is locked. - cursor_manager->SetDeviceScaleFactor(1.0f); - EXPECT_EQ(1.0f, test_api.GetDeviceScaleFactor()); + // Device scale factor and rotation do change even while cursor is locked. + display.set_device_scale_factor(1.0f); + display.set_rotation(gfx::Display::ROTATE_180); + cursor_manager->SetDisplay(display); + EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_180, test_api.GetDisplay().rotation()); cursor_manager->UnlockCursor(); EXPECT_FALSE(cursor_manager->is_cursor_locked()); // Cursor type changes to the one specified while cursor is locked. EXPECT_EQ(ui::kCursorPointer, test_api.GetCurrentCursor().native_type()); - EXPECT_EQ(1.0f, test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); EXPECT_TRUE(test_api.GetCurrentCursor().platform()); } @@ -87,14 +94,21 @@ TEST_F(AshNativeCursorManagerTest, SetCursor) { EXPECT_TRUE(test_api.GetCurrentCursor().platform()); } -TEST_F(AshNativeCursorManagerTest, SetDeviceScaleFactor) { +TEST_F(AshNativeCursorManagerTest, SetDeviceScaleFactorAndRotation) { CursorManager* cursor_manager = Shell::GetInstance()->cursor_manager(); CursorManagerTestApi test_api(cursor_manager); - cursor_manager->SetDeviceScaleFactor(2.0f); - EXPECT_EQ(2.0f, test_api.GetDeviceScaleFactor()); - cursor_manager->SetDeviceScaleFactor(1.0f); - EXPECT_EQ(1.0f, test_api.GetDeviceScaleFactor()); + gfx::Display display(0); + display.set_device_scale_factor(2.0f); + cursor_manager->SetDisplay(display); + EXPECT_EQ(2.0f, test_api.GetDisplay().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetDisplay().rotation()); + + display.set_device_scale_factor(1.0f); + display.set_rotation(gfx::Display::ROTATE_270); + cursor_manager->SetDisplay(display); + EXPECT_EQ(1.0f, test_api.GetDisplay().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_270, test_api.GetDisplay().rotation()); } #if defined(OS_WIN) diff --git a/ash/wm/drag_window_resizer_unittest.cc b/ash/wm/drag_window_resizer_unittest.cc index f3c9124..29e166a 100644 --- a/ash/wm/drag_window_resizer_unittest.cc +++ b/ash/wm/drag_window_resizer_unittest.cc @@ -360,14 +360,14 @@ TEST_F(DragWindowResizerTest, CursorDeviceScaleFactor) { // Grab (0, 0) of the window. scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer( window_.get(), gfx::Point(), HTCAPTION)); - EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, 399, 200), 0); event_filter->WarpMouseCursorIfNecessary(root_windows[0], gfx::Point(399, 200)); - EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); resizer->CompleteDrag(0); - EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); } // Move window from the root window with 2.0 device scale factor to the root @@ -380,14 +380,14 @@ TEST_F(DragWindowResizerTest, CursorDeviceScaleFactor) { // Grab (0, 0) of the window. scoped_ptr<DragWindowResizer> resizer(CreateDragWindowResizer( window_.get(), gfx::Point(), HTCAPTION)); - EXPECT_EQ(2.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(2.0f, cursor_test_api.GetDisplay().device_scale_factor()); ASSERT_TRUE(resizer.get()); resizer->Drag(CalculateDragPoint(*resizer, -200, 200), 0); event_filter->WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(400, 200)); - EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); resizer->CompleteDrag(0); - EXPECT_EQ(1.0f, cursor_test_api.GetDeviceScaleFactor()); + EXPECT_EQ(1.0f, cursor_test_api.GetDisplay().device_scale_factor()); } } diff --git a/ash/wm/image_cursors.cc b/ash/wm/image_cursors.cc index ea05b0d..74bf358 100644 --- a/ash/wm/image_cursors.cc +++ b/ash/wm/image_cursors.cc @@ -7,6 +7,7 @@ #include "base/logging.h" #include "ui/base/cursor/cursor_loader.h" #include "ui/base/cursor/cursor.h" +#include "ui/gfx/display.h" #include "ui/gfx/point.h" #include "grit/ash_resources.h" #include "grit/ui_resources.h" @@ -88,24 +89,28 @@ ImageCursors::ImageCursors() { ImageCursors::~ImageCursors() { } -float ImageCursors::GetDeviceScaleFactor() const { +gfx::Display ImageCursors::GetDisplay() const { if (!cursor_loader_.get()) { NOTREACHED(); - // Returning 1.0f on release build as it's not serious enough to crash + // Returning default on release build as it's not serious enough to crash // even if this ever happens. - return 1.0f; + return gfx::Display(); } - return cursor_loader_->device_scale_factor(); + return cursor_loader_->display(); } -bool ImageCursors::SetDeviceScaleFactor(float device_scale_factor) { - if (!cursor_loader_.get()) +bool ImageCursors::SetDisplay(const gfx::Display& display) { + float device_scale_factor = display.device_scale_factor(); + if (!cursor_loader_.get()) { cursor_loader_.reset(ui::CursorLoader::Create()); - else if (GetDeviceScaleFactor() == device_scale_factor) + } else if (cursor_loader_->display().rotation() == display.rotation() && + cursor_loader_->display().device_scale_factor() == + device_scale_factor) { return false; + } cursor_loader_->UnloadAll(); - cursor_loader_->set_device_scale_factor(device_scale_factor); + cursor_loader_->set_display(display); for (size_t i = 0; i < arraysize(kImageCursors); ++i) { const HotPoint& hot = device_scale_factor == 1.0f ? diff --git a/ash/wm/image_cursors.h b/ash/wm/image_cursors.h index 61169a9..59c7b82 100644 --- a/ash/wm/image_cursors.h +++ b/ash/wm/image_cursors.h @@ -9,6 +9,10 @@ #include "base/memory/scoped_ptr.h" #include "ui/gfx/native_widget_types.h" +namespace gfx { +class Display; +} + namespace ui { class CursorLoader; } @@ -22,14 +26,15 @@ class ASH_EXPORT ImageCursors { ImageCursors(); ~ImageCursors(); - // Returns the device scale factor of cursors. The device scale factor must - // be set by SetDeviceScaleFactor at least once before using this. - float GetDeviceScaleFactor() const; + // Returns the display the cursors are loaded for. The display must + // be set by SetDisplay before using this. + gfx::Display GetDisplay() const; - // Sets the device scale factor of the cursors with |device_scale_factor| and - // reloads the cursor images if necessary. Returns true if the cursor image - // is reloaded. - bool SetDeviceScaleFactor(float device_scale_factor); + // Sets the display the cursors are loaded for. The device scale factor + // determines the size of the image to load, and the rotation of the display + // determines if the image and its host point has to be retated. + // Returns true if the cursor image is reloaded. + bool SetDisplay(const gfx::Display& display); // Sets the platform cursor based on the native type of |cursor|. void SetPlatformCursor(gfx::NativeCursor* cursor); diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index 58e2571..59cb87b 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc @@ -1156,7 +1156,7 @@ class DifferentDeviceScaleFactorDisplayTabDragControllerTest float GetCursorDeviceScaleFactor() const { ash::test::CursorManagerTestApi cursor_test_api( ash::Shell::GetInstance()->cursor_manager()); - return cursor_test_api.GetDeviceScaleFactor(); + return cursor_test_api.GetDisplay().device_scale_factor(); } private: diff --git a/ui/aura/client/cursor_client.h b/ui/aura/client/cursor_client.h index 9eadfbe..8f48430 100644 --- a/ui/aura/client/cursor_client.h +++ b/ui/aura/client/cursor_client.h @@ -8,6 +8,10 @@ #include "ui/aura/aura_export.h" #include "ui/gfx/native_widget_types.h" +namespace gfx { +class Display; +} + namespace aura { class Window; namespace client { @@ -38,8 +42,8 @@ class AURA_EXPORT CursorClient { // Returns true if mouse events are enabled. virtual bool IsMouseEventsEnabled() const = 0; - // Sets the device scale factor of the cursor. - virtual void SetDeviceScaleFactor(float device_scale_factor) = 0; + // Sets the display for the cursor. + virtual void SetDisplay(const gfx::Display& display) = 0; // Locks the cursor change. The cursor type, cursor visibility, and mouse // events enable state never change as long as lock is held by anyone. diff --git a/ui/aura/root_window.cc b/ui/aura/root_window.cc index c2a63a5..13988b2 100644 --- a/ui/aura/root_window.cc +++ b/ui/aura/root_window.cc @@ -248,8 +248,11 @@ void RootWindow::MoveCursorTo(const gfx::Point& location_in_dip) { host_->MoveCursorTo(ui::ConvertPointToPixel(layer(), location)); SetLastMouseLocation(this, location_in_dip); client::CursorClient* cursor_client = client::GetCursorClient(this); - if (cursor_client) - cursor_client->SetDeviceScaleFactor(GetDeviceScaleFactor()); + if (cursor_client) { + const gfx::Display& display = + gfx::Screen::GetScreenFor(this)->GetDisplayNearestWindow(this); + cursor_client->SetDisplay(display); + } } bool RootWindow::ConfineCursorToWindow() { @@ -557,8 +560,11 @@ void RootWindow::OnDeviceScaleFactorChanged( // Update the device scale factor of the cursor client only when the last // mouse location is on this root window. if (cursor_is_in_bounds) { - if (cursor_client) - cursor_client->SetDeviceScaleFactor(device_scale_factor); + if (cursor_client) { + const gfx::Display& display = + gfx::Screen::GetScreenFor(this)->GetDisplayNearestWindow(this); + cursor_client->SetDisplay(display); + } } if (cursor_is_in_bounds && cursor_client && cursor_visible) cursor_client->ShowCursor(); diff --git a/ui/base/cursor/cursor_loader.h b/ui/base/cursor/cursor_loader.h index 1a87a42..661ab08 100644 --- a/ui/base/cursor/cursor_loader.h +++ b/ui/base/cursor/cursor_loader.h @@ -7,6 +7,7 @@ #include "base/logging.h" #include "ui/base/ui_export.h" +#include "ui/gfx/display.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/point.h" @@ -14,17 +15,17 @@ namespace ui { class UI_EXPORT CursorLoader { public: - CursorLoader() : device_scale_factor_(1.0f) {} + CursorLoader() {} virtual ~CursorLoader() {} - // Returns the device scale factor used by the loader. - float device_scale_factor() const { - return device_scale_factor_; + // Returns the display the loader loads images for. + const gfx::Display& display() const { + return display_; } - // Sets the device scale factor used by the loader. - void set_device_scale_factor(float device_scale_factor) { - device_scale_factor_ = device_scale_factor; + // Sets the display the loader loads images for. + void set_display(const gfx::Display& display) { + display_ = display; } // Creates a cursor from an image resource and puts it in the cursor map. @@ -52,8 +53,8 @@ class UI_EXPORT CursorLoader { static CursorLoader* Create(); private: - // The device scale factor used by the loader. - float device_scale_factor_; + // The display the loader loads images for. + gfx::Display display_; }; } // namespace ui diff --git a/ui/base/cursor/cursor_loader_x11.cc b/ui/base/cursor/cursor_loader_x11.cc index 006f8ec..c4d3fd3 100644 --- a/ui/base/cursor/cursor_loader_x11.cc +++ b/ui/base/cursor/cursor_loader_x11.cc @@ -14,6 +14,7 @@ #include "ui/base/x/x11_util.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_skia.h" +#include "ui/gfx/skbitmap_operations.h" namespace { @@ -156,9 +157,29 @@ void CursorLoaderX11::LoadImageCursor(int id, const gfx::ImageSkia* image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); const gfx::ImageSkiaRep& image_rep = image->GetRepresentation( - GetScaleFactorFromScale(device_scale_factor())); - XcursorImage* x_image = - SkBitmapToXcursorImage(&image_rep.sk_bitmap(), hot); + GetScaleFactorFromScale(display().device_scale_factor())); + SkBitmap bitmap = image_rep.sk_bitmap(); + gfx::Point hotpoint = hot; + switch (display().rotation()) { + case gfx::Display::ROTATE_0: + break; + case gfx::Display::ROTATE_90: + hotpoint.SetPoint(bitmap.height() - hot.y(), hot.x()); + bitmap = SkBitmapOperations::Rotate( + bitmap, SkBitmapOperations::ROTATION_90_CW); + break; + case gfx::Display::ROTATE_180: + hotpoint.SetPoint(bitmap.width() - hot.x(), bitmap.height() - hot.y()); + bitmap = SkBitmapOperations::Rotate( + bitmap, SkBitmapOperations::ROTATION_180_CW); + break; + case gfx::Display::ROTATE_270: + hotpoint.SetPoint(hot.y(), bitmap.width() - hot.x()); + bitmap = SkBitmapOperations::Rotate( + bitmap, SkBitmapOperations::ROTATION_270_CW); + break; + } + XcursorImage* x_image = SkBitmapToXcursorImage(&bitmap, hotpoint); cursors_[id] = CreateReffedCustomXCursor(x_image); // |image_rep| is owned by the resource bundle. So we do not need to free it. } @@ -170,7 +191,7 @@ void CursorLoaderX11::LoadAnimatedCursor(int id, const gfx::ImageSkia* image = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); const gfx::ImageSkiaRep& image_rep = image->GetRepresentation( - GetScaleFactorFromScale(device_scale_factor())); + GetScaleFactorFromScale(display().device_scale_factor())); const SkBitmap bitmap = image_rep.sk_bitmap(); DCHECK_EQ(bitmap.config(), SkBitmap::kARGB_8888_Config); int frame_width = bitmap.height(); @@ -227,10 +248,12 @@ void CursorLoaderX11::SetPlatformCursor(gfx::NativeCursor* cursor) { xcursor = invisible_cursor_.get(); else if (*cursor == kCursorCustom) xcursor = cursor->platform(); - else if (device_scale_factor() == 1.0f) + else if (display().device_scale_factor() == 1.0f && + display().rotation() == gfx::Display::ROTATE_0) { xcursor = GetXCursor(CursorShapeFromNative(*cursor)); - else + } else { xcursor = ImageCursorFromNative(kCursorPointer); + } cursor->SetPlatformCursor(xcursor); } diff --git a/ui/gfx/display.cc b/ui/gfx/display.cc index f5cefa1..79e32d2 100644 --- a/ui/gfx/display.cc +++ b/ui/gfx/display.cc @@ -64,19 +64,22 @@ int64 Display::GetID(uint16 manufacturer_id, Display::Display() : id_(kInvalidDisplayID), - device_scale_factor_(GetForcedDeviceScaleFactor()) { + device_scale_factor_(GetForcedDeviceScaleFactor()), + rotation_(ROTATE_0) { } Display::Display(int64 id) : id_(id), - device_scale_factor_(GetForcedDeviceScaleFactor()) { + device_scale_factor_(GetForcedDeviceScaleFactor()), + rotation_(ROTATE_0) { } Display::Display(int64 id, const gfx::Rect& bounds) : id_(id), bounds_(bounds), work_area_(bounds), - device_scale_factor_(GetForcedDeviceScaleFactor()) { + device_scale_factor_(GetForcedDeviceScaleFactor()), + rotation_(ROTATE_0) { #if defined(USE_AURA) SetScaleAndBounds(device_scale_factor_, bounds); #endif diff --git a/ui/gfx/display.h b/ui/gfx/display.h index 81963f2..59ee1d3 100644 --- a/ui/gfx/display.h +++ b/ui/gfx/display.h @@ -18,6 +18,14 @@ namespace gfx { // system, not in backing pixels. class UI_EXPORT Display { public: + // Screen Rotation in clock-wise degrees. + enum Rotation { + ROTATE_0 = 0, + ROTATE_90, + ROTATE_180, + ROTATE_270, + }; + // Creates a display with kInvalidDisplayID as default. Display(); explicit Display(int64 id); @@ -63,6 +71,9 @@ class UI_EXPORT Display { float device_scale_factor() const { return device_scale_factor_; } void set_device_scale_factor(float scale) { device_scale_factor_ = scale; } + Rotation rotation() const { return rotation_; } + void set_rotation(Rotation rotation) { rotation_ = rotation; } + // Utility functions that just return the size of display and // work area. const Size& size() const { return bounds_.size(); } @@ -108,6 +119,7 @@ class UI_EXPORT Display { Rect bounds_; Rect work_area_; float device_scale_factor_; + Rotation rotation_; }; } // namespace gfx diff --git a/ui/views/corewm/compound_event_filter_unittest.cc b/ui/views/corewm/compound_event_filter_unittest.cc index 52d825a..1dd743f 100644 --- a/ui/views/corewm/compound_event_filter_unittest.cc +++ b/ui/views/corewm/compound_event_filter_unittest.cc @@ -53,7 +53,7 @@ class TestCursorClient : public aura::client::CursorClient { return mouse_events_enabled_; } - virtual void SetDeviceScaleFactor(float scale_factor) OVERRIDE { + virtual void SetDisplay(const gfx::Display& display) OVERRIDE { } virtual void LockCursor() OVERRIDE { diff --git a/ui/views/corewm/cursor_manager.cc b/ui/views/corewm/cursor_manager.cc index 7b3865f..39b7ee9 100644 --- a/ui/views/corewm/cursor_manager.cc +++ b/ui/views/corewm/cursor_manager.cc @@ -123,8 +123,8 @@ bool CursorManager::IsMouseEventsEnabled() const { return current_state_->mouse_events_enabled(); } -void CursorManager::SetDeviceScaleFactor(float device_scale_factor) { - delegate_->SetDeviceScaleFactor(device_scale_factor, this); +void CursorManager::SetDisplay(const gfx::Display& display) { + delegate_->SetDisplay(display, this); } void CursorManager::LockCursor() { diff --git a/ui/views/corewm/cursor_manager.h b/ui/views/corewm/cursor_manager.h index 49cb1ec..d7784b3 100644 --- a/ui/views/corewm/cursor_manager.h +++ b/ui/views/corewm/cursor_manager.h @@ -14,6 +14,10 @@ #include "ui/views/corewm/native_cursor_manager_delegate.h" #include "ui/views/views_export.h" +namespace gfx { +class Display; +} + namespace views { namespace corewm { @@ -43,7 +47,7 @@ class VIEWS_EXPORT CursorManager : public aura::client::CursorClient, virtual void EnableMouseEvents() OVERRIDE; virtual void DisableMouseEvents() OVERRIDE; virtual bool IsMouseEventsEnabled() const OVERRIDE; - virtual void SetDeviceScaleFactor(float device_scale_factor) OVERRIDE; + virtual void SetDisplay(const gfx::Display& display) OVERRIDE; virtual void LockCursor() OVERRIDE; virtual void UnlockCursor() OVERRIDE; diff --git a/ui/views/corewm/cursor_manager_unittest.cc b/ui/views/corewm/cursor_manager_unittest.cc index f5eb9e4..f1e24a5 100644 --- a/ui/views/corewm/cursor_manager_unittest.cc +++ b/ui/views/corewm/cursor_manager_unittest.cc @@ -14,8 +14,8 @@ class TestingCursorManager : public views::corewm::NativeCursorManager { gfx::NativeCursor current_cursor() { return cursor_; } // Overridden from views::corewm::NativeCursorManager: - virtual void SetDeviceScaleFactor( - float device_scale_factor, + virtual void SetDisplay( + const gfx::Display& display, views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE {} virtual void SetCursor( diff --git a/ui/views/corewm/native_cursor_manager.h b/ui/views/corewm/native_cursor_manager.h index fc51f43..bb28b01 100644 --- a/ui/views/corewm/native_cursor_manager.h +++ b/ui/views/corewm/native_cursor_manager.h @@ -8,6 +8,10 @@ #include "ui/views/corewm/native_cursor_manager_delegate.h" #include "ui/views/views_export.h" +namespace gfx { +class Display; +} + namespace views { namespace corewm { @@ -20,8 +24,8 @@ class VIEWS_EXPORT NativeCursorManager { virtual ~NativeCursorManager() {} // A request to set the screen DPI. Can cause changes in the current cursor. - virtual void SetDeviceScaleFactor( - float device_scale_factor, + virtual void SetDisplay( + const gfx::Display& display, views::corewm::NativeCursorManagerDelegate* delegate) = 0; // A request to set the cursor to |cursor|. At minimum, implementer should diff --git a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc index 8482feb81..9ce2da9 100644 --- a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc +++ b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc @@ -18,11 +18,11 @@ DesktopNativeCursorManager::DesktopNativeCursorManager( DesktopNativeCursorManager::~DesktopNativeCursorManager() { } -void DesktopNativeCursorManager::SetDeviceScaleFactor( - float device_scale_factor, +void DesktopNativeCursorManager::SetDisplay( + const gfx::Display& display, views::corewm::NativeCursorManagerDelegate* delegate) { cursor_loader_->UnloadAll(); - cursor_loader_->set_device_scale_factor(device_scale_factor); + cursor_loader_->set_display(display); SetCursor(delegate->GetCurrentCursor(), delegate); } diff --git a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h index aa7847b..cbb73a1 100644 --- a/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h +++ b/ui/views/widget/desktop_aura/desktop_native_cursor_manager.h @@ -34,8 +34,8 @@ class VIEWS_EXPORT DesktopNativeCursorManager private: // Overridden from views::corewm::NativeCursorManager: - virtual void SetDeviceScaleFactor( - float device_scale_factor, + virtual void SetDisplay( + const gfx::Display& display, views::corewm::NativeCursorManagerDelegate* delegate) OVERRIDE; virtual void SetCursor( gfx::NativeCursor cursor, |