summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpkotwicz <pkotwicz@chromium.org>2015-03-11 15:48:17 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-11 22:49:05 +0000
commit21a9d207e9e1f861bbd0e33e5b72481e4876a2e1 (patch)
tree04c85b1983abfa70dd9dd6fe8e198e473510a769
parent7364f80c3ba3c77f66ae06b6f4cc36c7c159d905 (diff)
downloadchromium_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.gyp1
-rw-r--r--ash/display/cursor_window_controller.cc12
-rw-r--r--ash/display/cursor_window_controller.h3
-rw-r--r--ash/display/cursor_window_controller_unittest.cc108
-rw-r--r--ash/display/display_controller.cc4
-rw-r--r--ash/display/display_controller.h2
-rw-r--r--ash/display/display_controller_unittest.cc196
-rw-r--r--ash/display/display_manager_unittest.cc84
-rw-r--r--ash/display/mirror_window_controller_unittest.cc131
-rw-r--r--ash/test/mirror_window_test_api.cc5
-rw-r--r--ash/test/mirror_window_test_api.h8
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;