diff options
author | pkotwicz <pkotwicz@chromium.org> | 2015-03-11 15:48:17 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-11 22:49:05 +0000 |
commit | 21a9d207e9e1f861bbd0e33e5b72481e4876a2e1 (patch) | |
tree | 04c85b1983abfa70dd9dd6fe8e198e473510a769 | |
parent | 7364f80c3ba3c77f66ae06b6f4cc36c7c159d905 (diff) | |
download | chromium_src-21a9d207e9e1f861bbd0e33e5b72481e4876a2e1.zip chromium_src-21a9d207e9e1f861bbd0e33e5b72481e4876a2e1.tar.gz chromium_src-21a9d207e9e1f861bbd0e33e5b72481e4876a2e1.tar.bz2 |
Add more tests for mouse rotation,scale&position after display change
This CL also makes CursorWindowController::SetDisplay() update the cursor
rotation. This is consistent with the behavior of native cursors when
AshNativeCursorManager::SetDisplay() is called.
BUG=450860
TEST=See CL
Review URL: https://codereview.chromium.org/948583005
Cr-Commit-Position: refs/heads/master@{#320173}
-rw-r--r-- | ash/ash.gyp | 1 | ||||
-rw-r--r-- | ash/display/cursor_window_controller.cc | 12 | ||||
-rw-r--r-- | ash/display/cursor_window_controller.h | 3 | ||||
-rw-r--r-- | ash/display/cursor_window_controller_unittest.cc | 108 | ||||
-rw-r--r-- | ash/display/display_controller.cc | 4 | ||||
-rw-r--r-- | ash/display/display_controller.h | 2 | ||||
-rw-r--r-- | ash/display/display_controller_unittest.cc | 196 | ||||
-rw-r--r-- | ash/display/display_manager_unittest.cc | 84 | ||||
-rw-r--r-- | ash/display/mirror_window_controller_unittest.cc | 131 | ||||
-rw-r--r-- | ash/test/mirror_window_test_api.cc | 5 | ||||
-rw-r--r-- | ash/test/mirror_window_test_api.h | 8 |
11 files changed, 354 insertions, 200 deletions
diff --git a/ash/ash.gyp b/ash/ash.gyp index 61a576f..65de957 100644 --- a/ash/ash.gyp +++ b/ash/ash.gyp @@ -753,6 +753,7 @@ 'content/display/screen_orientation_controller_chromeos_unittest.cc', 'desktop_background/desktop_background_controller_unittest.cc', 'dip_unittest.cc', + 'display/cursor_window_controller_unittest.cc', 'display/display_change_observer_chromeos_unittest.cc', 'display/display_controller_unittest.cc', 'display/display_error_observer_chromeos_unittest.cc', diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc index ee6b565..11c2bf1 100644 --- a/ash/display/cursor_window_controller.cc +++ b/ash/display/cursor_window_controller.cc @@ -95,7 +95,6 @@ CursorWindowController::CursorWindowController() cursor_type_(ui::kCursorNone), visible_(true), cursor_set_(ui::CURSOR_SET_NORMAL), - cursor_rotation_(gfx::Display::ROTATE_0), delegate_(new CursorWindowDelegate()) { } @@ -129,7 +128,7 @@ void CursorWindowController::UpdateContainer() { display_ = Shell::GetScreen()->GetPrimaryDisplay(); SetContainer(mirror_window); } - // Updates the hot point based on the current display/container. + // Updates the hot point based on the current display. UpdateCursorImage(); } @@ -146,6 +145,8 @@ void CursorWindowController::SetDisplay(const gfx::Display& display) { SetContainer(GetRootWindowController(root_window)->GetContainer( kShellWindowId_MouseCursorContainer)); SetBoundsInScreen(display.bounds()); + // Updates the hot point based on the current display. + UpdateCursorImage(); } void CursorWindowController::UpdateLocation() { @@ -164,11 +165,9 @@ void CursorWindowController::UpdateLocation() { } void CursorWindowController::SetCursor(gfx::NativeCursor cursor) { - if (cursor_type_ == cursor.native_type() && - cursor_rotation_ == display_.rotation()) + if (cursor_type_ == cursor.native_type()) return; cursor_type_ = cursor.native_type(); - cursor_rotation_ = display_.rotation(); UpdateCursorImage(); UpdateCursorVisibility(); } @@ -201,6 +200,7 @@ void CursorWindowController::SetContainer(aura::Window* container) { cursor_window_->Init(aura::WINDOW_LAYER_TEXTURED); cursor_window_->set_ignore_events(true); cursor_window_->set_owned_by_parent(false); + // Call UpdateCursorImage() to figure out |cursor_window_|'s desired size. UpdateCursorImage(); container->AddChild(cursor_window_.get()); @@ -227,7 +227,7 @@ void CursorWindowController::UpdateCursorImage() { ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id); gfx::ImageSkia rotated = *image; if (!is_cursor_compositing_enabled_) { - switch (cursor_rotation_) { + switch (display_.rotation()) { case gfx::Display::ROTATE_0: break; case gfx::Display::ROTATE_90: diff --git a/ash/display/cursor_window_controller.h b/ash/display/cursor_window_controller.h index 8af6906..8ce1a5b 100644 --- a/ash/display/cursor_window_controller.h +++ b/ash/display/cursor_window_controller.h @@ -15,6 +15,7 @@ namespace test { class MirrorWindowTestApi; } +class CursorWindowControllerTest; class CursorWindowDelegate; // Draws a mouse cursor on a given container window. @@ -48,6 +49,7 @@ class ASH_EXPORT CursorWindowController { void SetVisibility(bool visible); private: + friend class CursorWindowControllerTest; friend class test::MirrorWindowTestApi; // Sets the container window for the cursor window controller. @@ -76,7 +78,6 @@ class ASH_EXPORT CursorWindowController { bool visible_; ui::CursorSetType cursor_set_; - gfx::Display::Rotation cursor_rotation_; gfx::Point hot_point_; // The display on which the cursor is drawn. diff --git a/ash/display/cursor_window_controller_unittest.cc b/ash/display/cursor_window_controller_unittest.cc new file mode 100644 index 0000000..8298604 --- /dev/null +++ b/ash/display/cursor_window_controller_unittest.cc @@ -0,0 +1,108 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/display/cursor_window_controller.h" + +#include "ash/display/display_controller.h" +#include "ash/screen_util.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "ui/aura/window.h" +#include "ui/aura/window_tree_host.h" +#include "ui/base/cursor/cursor.h" +#include "ui/events/test/event_generator.h" +#include "ui/gfx/display.h" +#include "ui/wm/core/coordinate_conversion.h" + +namespace ash { + +class CursorWindowControllerTest : public test::AshTestBase { + public: + CursorWindowControllerTest() {} + ~CursorWindowControllerTest() override {} + + // test::AshTestBase: + void SetUp() override { + AshTestBase::SetUp(); + cursor_window_controller_ = + Shell::GetInstance()->display_controller()->cursor_window_controller(); + cursor_window_controller_->SetCursorCompositingEnabled(true); + } + + int GetCursorType() const { return cursor_window_controller_->cursor_type_; } + + const gfx::Point& GetCursorHotPoint() const { + return cursor_window_controller_->hot_point_; + } + + aura::Window* GetCursorWindow() const { + return cursor_window_controller_->cursor_window_.get(); + } + + int64 GetCursorDisplayId() const { + return cursor_window_controller_->display_.id(); + } + + private: + // Not owned. + CursorWindowController* cursor_window_controller_; + + DISALLOW_COPY_AND_ASSIGN(CursorWindowControllerTest); +}; + +// Test that the composited cursor moves to another display when the real cursor +// moves to another display. +TEST_F(CursorWindowControllerTest, MoveToDifferentDisplay) { + if (!SupportsMultipleDisplays()) + return; + + UpdateDisplay("200x200,200x200*2/r"); + + DisplayController* display_controller = + Shell::GetInstance()->display_controller(); + int64 primary_display_id = display_controller->GetPrimaryDisplayId(); + int64 secondary_display_id = ScreenUtil::GetSecondaryDisplay().id(); + aura::Window* primary_root = + display_controller->GetRootWindowForDisplayId(primary_display_id); + aura::Window* secondary_root = + display_controller->GetRootWindowForDisplayId(secondary_display_id); + + ui::test::EventGenerator primary_generator(primary_root); + primary_generator.MoveMouseToInHost(20, 50); + + EXPECT_TRUE(primary_root->Contains(GetCursorWindow())); + EXPECT_EQ(primary_display_id, GetCursorDisplayId()); + EXPECT_EQ(ui::kCursorNull, GetCursorType()); + gfx::Point hot_point = GetCursorHotPoint(); + EXPECT_EQ("4,4", hot_point.ToString()); + gfx::Rect cursor_bounds = GetCursorWindow()->GetBoundsInScreen(); + EXPECT_EQ(20, cursor_bounds.x() + hot_point.x()); + EXPECT_EQ(50, cursor_bounds.y() + hot_point.y()); + + // The cursor can only be moved between displays via + // WindowTreeHost::MoveCursorTo(). EventGenerator uses a hack to move the + // cursor between displays. + // Screen location: 220, 50 + // Root location: 20, 50 + secondary_root->MoveCursorTo(gfx::Point(20, 50)); + + // Chrome relies on WindowTreeHost::MoveCursorTo() dispatching a mouse move + // asynchronously. This is implemented in a platform specific way. Generate a + // fake mouse move instead of waiting. + gfx::Point new_cursor_position_in_host(20, 50); + secondary_root->GetHost()->ConvertPointToHost(&new_cursor_position_in_host); + ui::test::EventGenerator secondary_generator(secondary_root); + secondary_generator.MoveMouseToInHost(new_cursor_position_in_host); + + EXPECT_TRUE(secondary_root->Contains(GetCursorWindow())); + EXPECT_EQ(secondary_display_id, GetCursorDisplayId()); + EXPECT_EQ(ui::kCursorNull, GetCursorType()); + hot_point = GetCursorHotPoint(); + EXPECT_EQ("8,9", hot_point.ToString()); + cursor_bounds = GetCursorWindow()->GetBoundsInScreen(); + EXPECT_EQ(220, cursor_bounds.x() + hot_point.x()); + EXPECT_EQ(50, cursor_bounds.y() + hot_point.y()); +} + +} // namespace ash diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc index 5d5144b..cc5a8b4 100644 --- a/ash/display/display_controller.cc +++ b/ash/display/display_controller.cc @@ -538,7 +538,7 @@ void DisplayController::SetPrimaryDisplay( GetDisplayManager()->set_force_bounds_changed(false); } -void DisplayController::EnsurePointerInDisplays() { +void DisplayController::UpdateMouseLocationAfterDisplayChange() { // If the mouse is currently on a display in native location, // use the same native location. Otherwise find the display closest // to the current cursor location in screen coordinates. @@ -781,7 +781,7 @@ void DisplayController::PostDisplayConfigurationChange() { } FOR_EACH_OBSERVER(Observer, observers_, OnDisplayConfigurationChanged()); UpdateHostWindowNames(); - EnsurePointerInDisplays(); + UpdateMouseLocationAfterDisplayChange(); } AshWindowTreeHost* DisplayController::AddWindowTreeHostForDisplay( diff --git a/ash/display/display_controller.h b/ash/display/display_controller.h index d9b2d63..e795d77 100644 --- a/ash/display/display_controller.h +++ b/ash/display/display_controller.h @@ -138,7 +138,7 @@ class ASH_EXPORT DisplayController : public gfx::DisplayObserver, // Checks if the mouse pointer is on one of displays, and moves to // the center of the nearest display if it's outside of all displays. - void EnsurePointerInDisplays(); + void UpdateMouseLocationAfterDisplayChange(); // Sets the work area's |insets| to the display assigned to |window|. bool UpdateWorkAreaOfDisplayNearestWindow(const aura::Window* window, diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc index d298eee..a753d1b 100644 --- a/ash/display/display_controller_unittest.cc +++ b/ash/display/display_controller_unittest.cc @@ -961,61 +961,6 @@ TEST_F(DisplayControllerTest, SwapPrimaryById) { EXPECT_TRUE(primary_root->Contains(shelf_window)); } -TEST_F(DisplayControllerTest, CursorDeviceScaleFactorSwapPrimary) { - if (!SupportsMultipleDisplays()) - return; - - DisplayController* display_controller = - Shell::GetInstance()->display_controller(); - - UpdateDisplay("200x200,200x200*2"); - gfx::Display primary_display = Shell::GetScreen()->GetPrimaryDisplay(); - gfx::Display secondary_display = ScreenUtil::GetSecondaryDisplay(); - - aura::Window* primary_root = - display_controller->GetRootWindowForDisplayId(primary_display.id()); - aura::Window* secondary_root = - display_controller->GetRootWindowForDisplayId(secondary_display.id()); - EXPECT_NE(primary_root, secondary_root); - - test::CursorManagerTestApi test_api(Shell::GetInstance()->cursor_manager()); - - EXPECT_EQ(1.0f, primary_root->GetHost()->compositor()-> - device_scale_factor()); - primary_root->MoveCursorTo(gfx::Point(50, 50)); - EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor()); - EXPECT_EQ(2.0f, secondary_root->GetHost()->compositor()-> - device_scale_factor()); - secondary_root->MoveCursorTo(gfx::Point(50, 50)); - EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor()); - - // Switch primary and secondary - display_controller->SetPrimaryDisplay(secondary_display); - - // Cursor's device scale factor should be updated accroding to the swap of - // primary and secondary. - EXPECT_EQ(1.0f, secondary_root->GetHost()->compositor()-> - device_scale_factor()); - secondary_root->MoveCursorTo(gfx::Point(50, 50)); - EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor()); - primary_root->MoveCursorTo(gfx::Point(50, 50)); - EXPECT_EQ(2.0f, primary_root->GetHost()->compositor()-> - device_scale_factor()); - EXPECT_EQ(2.0f, test_api.GetCurrentCursor().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.GetCurrentCursor().device_scale_factor()); - - primary_root->MoveCursorTo(gfx::Point(50, 50)); - EXPECT_EQ(1.0f, primary_root->GetHost()->compositor()-> - device_scale_factor()); - EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor()); -} - TEST_F(DisplayControllerTest, OverscanInsets) { if (!SupportsMultipleDisplays()) return; @@ -1374,4 +1319,145 @@ TEST_F(DisplayControllerTest, XWidowNameForRootWindow) { } #endif +TEST_F(DisplayControllerTest, UpdateMouseLocationAfterDisplayChange) { + if (!SupportsMultipleDisplays()) + return; + + UpdateDisplay("200x200,300x300"); + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + + aura::Env* env = aura::Env::GetInstance(); + + ui::test::EventGenerator generator(root_windows[0]); + + // Set the initial position. + generator.MoveMouseToInHost(350, 150); + EXPECT_EQ("350,150", env->last_mouse_location().ToString()); + + // A mouse pointer will stay in the 2nd display. + UpdateDisplay("300x300,200x200"); + EXPECT_EQ("450,50", env->last_mouse_location().ToString()); + + // A mouse pointer will be outside of displays and move to the + // center of 2nd display. + UpdateDisplay("300x300,100x100"); + EXPECT_EQ("350,50", env->last_mouse_location().ToString()); + + // 2nd display was disconnected, and the cursor is + // now in the 1st display. + UpdateDisplay("400x400"); + EXPECT_EQ("50,350", env->last_mouse_location().ToString()); + + // 1st display's resolution has changed, and the mouse pointer is + // now outside. Move the mouse pointer to the center of 1st display. + UpdateDisplay("300x300"); + EXPECT_EQ("150,150", env->last_mouse_location().ToString()); + + // Move the mouse pointer to the bottom of 1st display. + generator.MoveMouseToInHost(150, 290); + EXPECT_EQ("150,290", env->last_mouse_location().ToString()); + + // The mouse pointer is now on 2nd display. + UpdateDisplay("300x280,200x200"); + EXPECT_EQ("450,10", env->last_mouse_location().ToString()); +} + +TEST_F(DisplayControllerTest, UpdateMouseLocationAfterDisplayChange_2ndOnLeft) { + if (!SupportsMultipleDisplays()) + return; + + // Set the 2nd display on the left. + DisplayLayoutStore* layout_store = + Shell::GetInstance()->display_manager()->layout_store(); + DisplayLayout layout = layout_store->default_display_layout(); + layout.position = DisplayLayout::LEFT; + layout_store->SetDefaultDisplayLayout(layout); + + UpdateDisplay("200x200,300x300"); + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + + EXPECT_EQ("-300,0 300x300", + ScreenUtil::GetSecondaryDisplay().bounds().ToString()); + + aura::Env* env = aura::Env::GetInstance(); + + // Set the initial position. + root_windows[0]->MoveCursorTo(gfx::Point(-150, 250)); + EXPECT_EQ("-150,250", env->last_mouse_location().ToString()); + + // A mouse pointer will stay in 2nd display. + UpdateDisplay("300x300,200x300"); + EXPECT_EQ("-50,150", env->last_mouse_location().ToString()); + + // A mouse pointer will be outside of displays and move to the + // center of 2nd display. + UpdateDisplay("300x300,200x100"); + EXPECT_EQ("-100,50", env->last_mouse_location().ToString()); + + // 2nd display was disconnected. Mouse pointer should move to + // 1st display. + UpdateDisplay("300x300"); + EXPECT_EQ("150,150", env->last_mouse_location().ToString()); +} + +// Test that the cursor swaps displays and that its scale factor and rotation +// are updated when the primary display is swapped. +TEST_F(DisplayControllerTest, + UpdateMouseLocationAfterDisplayChange_SwapPrimary) { + if (!SupportsMultipleDisplays()) + return; + + UpdateDisplay("200x200,200x200*2/r"); + + aura::Env* env = aura::Env::GetInstance(); + Shell* shell = Shell::GetInstance(); + DisplayController* display_controller = shell->display_controller(); + test::CursorManagerTestApi test_api(shell->cursor_manager()); + + display_controller->GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(20, 50)); + + EXPECT_EQ("20,50", env->last_mouse_location().ToString()); + EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetCurrentCursorRotation()); + + display_controller->SwapPrimaryDisplay(); + + EXPECT_EQ("20,50", env->last_mouse_location().ToString()); + EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetCurrentCursorRotation()); +} + +// Test that the cursor moves to the other display and that its scale factor +// and rotation are updated when the primary display is disconnected. +TEST_F(DisplayControllerTest, + UpdateMouseLocationAfterDisplayChange_PrimaryDisconnected) { + if (!SupportsMultipleDisplays()) + return; + + aura::Env* env = aura::Env::GetInstance(); + Shell* shell = Shell::GetInstance(); + DisplayController* display_controller = shell->display_controller(); + test::CursorManagerTestApi test_api(shell->cursor_manager()); + + UpdateDisplay("300x300*2/r,200x200"); + // Swap the primary display to make it possible to remove the primary display + // via UpdateDisplay(). + display_controller->SwapPrimaryDisplay(); + int primary_display_id = display_controller->GetPrimaryDisplayId(); + + display_controller->GetPrimaryRootWindow()->MoveCursorTo(gfx::Point(20, 50)); + + EXPECT_EQ("20,50", env->last_mouse_location().ToString()); + EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_0, test_api.GetCurrentCursorRotation()); + + UpdateDisplay("300x300*2/r"); + ASSERT_NE(primary_display_id, display_controller->GetPrimaryDisplayId()); + + // Cursor should be centered on the remaining display. + EXPECT_EQ("75,75", env->last_mouse_location().ToString()); + EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_90, test_api.GetCurrentCursorRotation()); +} + } // namespace ash diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc index 3d3bbec..fe240c6 100644 --- a/ash/display/display_manager_unittest.cc +++ b/ash/display/display_manager_unittest.cc @@ -701,90 +701,6 @@ TEST_F(DisplayManagerTest, MAYBE_TestNativeDisplaysChangedNoInternal) { GetBounds().size().ToString()); } -#if defined(OS_WIN) -// Tests that rely on the actual host size/location does not work on windows. -#define MAYBE_EnsurePointerInDisplays DISABLED_EnsurePointerInDisplays -#define MAYBE_EnsurePointerInDisplays_2ndOnLeft DISABLED_EnsurePointerInDisplays_2ndOnLeft -#else -#define MAYBE_EnsurePointerInDisplays EnsurePointerInDisplays -#define MAYBE_EnsurePointerInDisplays_2ndOnLeft EnsurePointerInDisplays_2ndOnLeft -#endif - -TEST_F(DisplayManagerTest, MAYBE_EnsurePointerInDisplays) { - UpdateDisplay("200x200,300x300"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - aura::Env* env = aura::Env::GetInstance(); - - ui::test::EventGenerator generator(root_windows[0]); - - // Set the initial position. - generator.MoveMouseToInHost(350, 150); - EXPECT_EQ("350,150", env->last_mouse_location().ToString()); - - // A mouse pointer will stay in the 2nd display. - UpdateDisplay("300x300,200x200"); - EXPECT_EQ("450,50", env->last_mouse_location().ToString()); - - // A mouse pointer will be outside of displays and move to the - // center of 2nd display. - UpdateDisplay("300x300,100x100"); - EXPECT_EQ("350,50", env->last_mouse_location().ToString()); - - // 2nd display was disconnected, and the cursor is - // now in the 1st display. - UpdateDisplay("400x400"); - EXPECT_EQ("50,350", env->last_mouse_location().ToString()); - - // 1st display's resolution has changed, and the mouse pointer is - // now outside. Move the mouse pointer to the center of 1st display. - UpdateDisplay("300x300"); - EXPECT_EQ("150,150", env->last_mouse_location().ToString()); - - // Move the mouse pointer to the bottom of 1st display. - generator.MoveMouseToInHost(150, 290); - EXPECT_EQ("150,290", env->last_mouse_location().ToString()); - - // The mouse pointer is now on 2nd display. - UpdateDisplay("300x280,200x200"); - EXPECT_EQ("450,10", env->last_mouse_location().ToString()); -} - -TEST_F(DisplayManagerTest, MAYBE_EnsurePointerInDisplays_2ndOnLeft) { - // Set the 2nd display on the left. - DisplayLayoutStore* layout_store = - Shell::GetInstance()->display_manager()->layout_store(); - DisplayLayout layout = layout_store->default_display_layout(); - layout.position = DisplayLayout::LEFT; - layout_store->SetDefaultDisplayLayout(layout); - - UpdateDisplay("200x200,300x300"); - aura::Window::Windows root_windows = Shell::GetAllRootWindows(); - - EXPECT_EQ("-300,0 300x300", - ScreenUtil::GetSecondaryDisplay().bounds().ToString()); - - aura::Env* env = aura::Env::GetInstance(); - - // Set the initial position. - root_windows[0]->MoveCursorTo(gfx::Point(-150, 250)); - EXPECT_EQ("-150,250", env->last_mouse_location().ToString()); - - // A mouse pointer will stay in 2nd display. - UpdateDisplay("300x300,200x300"); - EXPECT_EQ("-50,150", env->last_mouse_location().ToString()); - - // A mouse pointer will be outside of displays and move to the - // center of 2nd display. - UpdateDisplay("300x300,200x100"); - EXPECT_EQ("-100,50", env->last_mouse_location().ToString()); - - // 2nd display was disconnected. Mouse pointer should move to - // 1st display. - UpdateDisplay("300x300"); - EXPECT_EQ("150,150", env->last_mouse_location().ToString()); -} - TEST_F(DisplayManagerTest, NativeDisplaysChangedAfterPrimaryChange) { if (!SupportsMultipleDisplays()) return; diff --git a/ash/display/mirror_window_controller_unittest.cc b/ash/display/mirror_window_controller_unittest.cc index 06e233e..15bdefa 100644 --- a/ash/display/mirror_window_controller_unittest.cc +++ b/ash/display/mirror_window_controller_unittest.cc @@ -5,13 +5,17 @@ #include "ash/display/mirror_window_controller.h" #include "ash/ash_switches.h" +#include "ash/display/display_controller.h" #include "ash/display/display_manager.h" +#include "ash/screen_util.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" +#include "ash/test/cursor_manager_test_api.h" #include "ash/test/display_manager_test_api.h" #include "ash/test/mirror_window_test_api.h" #include "base/command_line.h" #include "base/strings/stringprintf.h" +#include "ui/aura/env.h" #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" @@ -54,12 +58,14 @@ typedef test::AshTestBase MirrorWindowControllerTest; // Software mirroring does not work on win. #define MAYBE_MirrorCursorBasic DISABLED_MirrorCursorBasic #define MAYBE_MirrorCursorLocations DISABLED_MirrorCursorLocations +#define MAYBE_MirrorCursorMoveOnEnter DISABLED_MirrorCursorMoveOnEnter #define MAYBE_MirrorCursorRotate DISABLED_MirrorCursorRotate #define MAYBE_DockMode DISABLED_DockMode #define MAYBE_MirrorOnBoot DISABLED_MirrorOnBoot #else #define MAYBE_MirrorCursorBasic MirrorCursorBasic #define MAYBE_MirrorCursorLocations MirrorCursorLocations +#define MAYBE_MirrorCursorMoveOnEnter MirrorCursorMoveOnEnter #define MAYBE_MirrorCursorRotate MirrorCursorRotate #define MAYBE_DockMode DockMode #define MAYBE_MirrorOnBoot MirrorOnBoot @@ -89,21 +95,16 @@ TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorBasic) { generator.MoveMouseTo(10, 10); // Test if cursor movement is propertly reflected in mirror window. - gfx::Point hot_point = test_api.GetCursorHotPoint(); - gfx::Point cursor_window_origin = - test_api.GetCursorWindow()->bounds().origin(); - EXPECT_EQ("4,4", hot_point.ToString()); - EXPECT_EQ(10 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(10 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("4,4", test_api.GetCursorHotPoint().ToString()); + EXPECT_EQ("10,10", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); EXPECT_EQ(ui::kCursorNull, test_api.GetCurrentCursorType()); EXPECT_TRUE(test_api.GetCursorWindow()->IsVisible()); // Test if cursor type change is propertly reflected in mirror window. generator.MoveMouseTo(100, 100); - hot_point = test_api.GetCursorHotPoint(); - cursor_window_origin = test_api.GetCursorWindow()->bounds().origin(); - EXPECT_EQ(100 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(100 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("100,100", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType()); // Test if visibility change is propertly reflected in mirror window. @@ -114,10 +115,8 @@ TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorBasic) { // Mouse event makes it visible again. generator.MoveMouseTo(300, 300); - hot_point = test_api.GetCursorHotPoint(); - cursor_window_origin = test_api.GetCursorWindow()->bounds().origin(); - EXPECT_EQ(300 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(300 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("300,300", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); EXPECT_EQ(ui::kCursorNull, test_api.GetCurrentCursorType()); EXPECT_TRUE(test_api.GetCursorWindow()->IsVisible()); } @@ -146,44 +145,35 @@ TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorRotate) { generator.MoveMouseToInHost(100, 100); // Test if cursor movement is propertly reflected in mirror window. - gfx::Point hot_point = test_api.GetCursorHotPoint(); - gfx::Point cursor_window_origin = - test_api.GetCursorWindow()->bounds().origin(); - EXPECT_EQ("11,12", hot_point.ToString()); - EXPECT_EQ(100 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(100 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("11,12", test_api.GetCursorHotPoint().ToString()); + EXPECT_EQ("100,100", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType()); UpdateDisplay("400x400/r,400x400"); // 90 degrees. generator.MoveMouseToInHost(300, 100); - hot_point = test_api.GetCursorHotPoint(); - cursor_window_origin = test_api.GetCursorWindow()->bounds().origin(); EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType()); // The size of cursor image is 25x25, so the rotated hot point must // be (25-12, 11). - EXPECT_EQ("13,11", hot_point.ToString()); - EXPECT_EQ(300 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(100 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("13,11", test_api.GetCursorHotPoint().ToString()); + EXPECT_EQ("300,100", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); UpdateDisplay("400x400/u,400x400"); // 180 degrees. generator.MoveMouseToInHost(300, 300); - hot_point = test_api.GetCursorHotPoint(); - cursor_window_origin = test_api.GetCursorWindow()->bounds().origin(); EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType()); // Rotated hot point must be (25-11, 25-12). - EXPECT_EQ("14,13", hot_point.ToString()); - EXPECT_EQ(300 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(300 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("14,13", test_api.GetCursorHotPoint().ToString()); + EXPECT_EQ("300,300", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); UpdateDisplay("400x400/l,400x400"); // 270 degrees. generator.MoveMouseToInHost(100, 300); - hot_point = test_api.GetCursorHotPoint(); - cursor_window_origin = test_api.GetCursorWindow()->bounds().origin(); EXPECT_EQ(ui::kCursorNorthResize, test_api.GetCurrentCursorType()); // Rotated hot point must be (12, 25-11). - EXPECT_EQ("12,14", hot_point.ToString()); - EXPECT_EQ(100 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(300 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("12,14", test_api.GetCursorHotPoint().ToString()); + EXPECT_EQ("100,300", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); } // Make sure that the mirror cursor's location is same as @@ -201,32 +191,71 @@ TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorLocations) { ui::test::EventGenerator generator(root); generator.MoveMouseToInHost(10, 20); - gfx::Point hot_point = test_api.GetCursorHotPoint(); - EXPECT_EQ("8,9", hot_point.ToString()); - gfx::Point cursor_window_origin = - test_api.GetCursorWindow()->bounds().origin(); - EXPECT_EQ(10 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(20 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("8,9", test_api.GetCursorHotPoint().ToString()); + EXPECT_EQ("10,20", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); // Test with ui scale UpdateDisplay("400x600*0.5,400x600"); generator.MoveMouseToInHost(20, 30); - hot_point = test_api.GetCursorHotPoint(); - EXPECT_EQ("4,4", hot_point.ToString()); - cursor_window_origin = test_api.GetCursorWindow()->bounds().origin(); - EXPECT_EQ(20 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(30 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("4,4", test_api.GetCursorHotPoint().ToString()); + EXPECT_EQ("20,30", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); // Test with rotation UpdateDisplay("400x600/r,400x600"); generator.MoveMouseToInHost(30, 40); - hot_point = test_api.GetCursorHotPoint(); - EXPECT_EQ("21,4", hot_point.ToString()); - cursor_window_origin = test_api.GetCursorWindow()->bounds().origin(); - EXPECT_EQ(30 - hot_point.x(), cursor_window_origin.x()); - EXPECT_EQ(40 - hot_point.y(), cursor_window_origin.y()); + EXPECT_EQ("21,4", test_api.GetCursorHotPoint().ToString()); + EXPECT_EQ("30,40", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); +} + +// Test the behavior of the cursor when entering software mirror mode swaps the +// cursor's display. +TEST_F(MirrorWindowControllerTest, MAYBE_MirrorCursorMoveOnEnter) { + aura::Env* env = aura::Env::GetInstance(); + Shell* shell = Shell::GetInstance(); + DisplayController* display_controller = shell->display_controller(); + DisplayManager* display_manager = shell->display_manager(); + + UpdateDisplay("400x400*2/r,400x400"); + int64 primary_display_id = display_controller->GetPrimaryDisplayId(); + int64 secondary_display_id = ScreenUtil::GetSecondaryDisplay().id(); + test::DisplayManagerTestApi(display_manager) + .SetInternalDisplayId(primary_display_id); + + // Chrome uses the internal display as the source display for software mirror + // mode. Move the cursor to the external display. + aura::Window* secondary_root_window = + display_controller->GetRootWindowForDisplayId(secondary_display_id); + secondary_root_window->MoveCursorTo(gfx::Point(100, 200)); + EXPECT_EQ("300,200", env->last_mouse_location().ToString()); + test::CursorManagerTestApi cursor_test_api(shell->cursor_manager()); + EXPECT_EQ(1.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_0, cursor_test_api.GetCurrentCursorRotation()); + + display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING); + UpdateDisplay("400x400*2/r,400x400"); + + // Entering mirror mode should have centered the cursor on the primary display + // because the cursor's previous position is out of bounds. + // Check real cursor's position and properties. + EXPECT_EQ("100,100", env->last_mouse_location().ToString()); + EXPECT_EQ(2.0f, cursor_test_api.GetCurrentCursor().device_scale_factor()); + EXPECT_EQ(gfx::Display::ROTATE_90, + cursor_test_api.GetCurrentCursorRotation()); + + // Check mirrored cursor's location. + test::MirrorWindowTestApi test_api; + gfx::Point hot_point = test_api.GetCursorHotPoint(); + // Rotated hot point must be (25-9, 8). + EXPECT_EQ("16,8", test_api.GetCursorHotPoint().ToString()); + // New coordinates are not (200,200) because (200,200) is not the center of + // the display. + EXPECT_EQ("199,200", + test_api.GetCursorHotPointLocationInRootWindow().ToString()); } // Make sure that the compositor based mirroring can switch diff --git a/ash/test/mirror_window_test_api.cc b/ash/test/mirror_window_test_api.cc index cd1926a..30e5624 100644 --- a/ash/test/mirror_window_test_api.cc +++ b/ash/test/mirror_window_test_api.cc @@ -32,6 +32,11 @@ const gfx::Point& MirrorWindowTestApi::GetCursorHotPoint() const { cursor_window_controller()->hot_point_; } +gfx::Point MirrorWindowTestApi::GetCursorHotPointLocationInRootWindow() const { + return GetCursorWindow()->GetBoundsInRootWindow().origin() + + GetCursorHotPoint().OffsetFromOrigin(); +} + const aura::Window* MirrorWindowTestApi::GetCursorWindow() const { return Shell::GetInstance()->display_controller()-> cursor_window_controller()->cursor_window_.get(); diff --git a/ash/test/mirror_window_test_api.h b/ash/test/mirror_window_test_api.h index b675860..1dd73aa 100644 --- a/ash/test/mirror_window_test_api.h +++ b/ash/test/mirror_window_test_api.h @@ -30,7 +30,15 @@ class MirrorWindowTestApi { const aura::WindowTreeHost* GetHost() const; int GetCurrentCursorType() const; + + // Returns the position of the hot point within the cursor. This is + // unaffected by the cursor location. const gfx::Point& GetCursorHotPoint() const; + + // Returns the position of the cursor hot point in root window coordinates. + // This should be the same as the native cursor location. + gfx::Point GetCursorHotPointLocationInRootWindow() const; + const aura::Window* GetCursorWindow() const; gfx::Point GetCursorLocation() const; |