summaryrefslogtreecommitdiffstats
path: root/ash
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-26 23:47:14 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-26 23:47:14 +0000
commit9c0cbfdcf94cedd7be9a1e64ffc6bdea6cdb7ba6 (patch)
treefda491d190454005201cb0daa109c1521de5d4de /ash
parent48542312f33e38c1e7f754b1a8029b53e50fcc59 (diff)
downloadchromium_src-9c0cbfdcf94cedd7be9a1e64ffc6bdea6cdb7ba6.zip
chromium_src-9c0cbfdcf94cedd7be9a1e64ffc6bdea6cdb7ba6.tar.gz
chromium_src-9c0cbfdcf94cedd7be9a1e64ffc6bdea6cdb7ba6.tar.bz2
Make sure the mouse pointer is always in one of displays
after display configuration change. BUG=157658 TEST=covered by test. tested manually on the device. Review URL: https://codereview.chromium.org/11263002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164452 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash')
-rw-r--r--ash/display/multi_display_manager.cc38
-rw-r--r--ash/display/multi_display_manager.h4
-rw-r--r--ash/display/multi_display_manager_unittest.cc74
3 files changed, 116 insertions, 0 deletions
diff --git a/ash/display/multi_display_manager.cc b/ash/display/multi_display_manager.cc
index 4f200ee..3fc4ea5 100644
--- a/ash/display/multi_display_manager.cc
+++ b/ash/display/multi_display_manager.cc
@@ -16,6 +16,7 @@
#include "base/utf_string_conversions.h"
#include "grit/ash_strings.h"
#include "ui/aura/aura_switches.h"
+#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h"
#include "ui/aura/root_window.h"
#include "ui/aura/root_window_host.h"
@@ -291,6 +292,7 @@ void MultiDisplayManager::OnNativeDisplaysChanged(
NotifyDisplayRemoved(displays_.back());
displays_.pop_back();
}
+ EnsurePointerInDisplays();
}
RootWindow* MultiDisplayManager::CreateRootWindowForDisplay(
@@ -495,6 +497,42 @@ int64 MultiDisplayManager::SetFirstDisplayAsInternalDisplayForTest() {
return internal_display_id_;
}
+void MultiDisplayManager::EnsurePointerInDisplays() {
+ // Don't try to move the pointer during the boot/startup.
+ if (!Shell::HasInstance())
+ return;
+ gfx::Point location_in_screen = Shell::GetScreen()->GetCursorScreenPoint();
+ gfx::Point target_location;
+ int64 closest_distance = -1;
+
+ for (DisplayList::const_iterator iter = displays_.begin();
+ iter != displays_.end(); ++iter) {
+ const gfx::Rect& display_bounds = iter->bounds();
+
+ if (display_bounds.Contains(location_in_screen)) {
+ target_location = location_in_screen;
+ break;
+ }
+ gfx::Point center = display_bounds.CenterPoint();
+ gfx::Point diff = center.Subtract(location_in_screen);
+ // Use the distance from the center of the dislay. This is not
+ // exactly "closest" display, but good enough to pick one
+ // appropriate (and there are at most two displays).
+ int64 distance = diff.x() * diff.x() + diff.y() * diff.y();
+ if (closest_distance < 0 || closest_distance > distance) {
+ target_location = center;
+ closest_distance = distance;
+ }
+ }
+
+ aura::RootWindow* root_window = Shell::GetPrimaryRootWindow();
+ aura::client::ScreenPositionClient* client =
+ aura::client::GetScreenPositionClient(root_window);
+ client->ConvertPointFromScreen(root_window, &target_location);
+
+ root_window->MoveCursorTo(target_location);
+}
+
void MultiDisplayManager::SetDisplayIdsForTest(DisplayList* to_update) const {
DisplayList::iterator iter_to_update = to_update->begin();
DisplayList::const_iterator iter = displays_.begin();
diff --git a/ash/display/multi_display_manager.h b/ash/display/multi_display_manager.h
index d82b0dd..0767e01 100644
--- a/ash/display/multi_display_manager.h
+++ b/ash/display/multi_display_manager.h
@@ -128,6 +128,10 @@ class ASH_EXPORT MultiDisplayManager : public aura::DisplayManager,
// the internal display.
int64 SetFirstDisplayAsInternalDisplayForTest();
+ // 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();
+
// Update the display's id in the |display_list| to match the ones
// stored in this display manager's |displays_|. This is used to
// emulate display change behavior during the test byn creating the
diff --git a/ash/display/multi_display_manager_unittest.cc b/ash/display/multi_display_manager_unittest.cc
index b7e293a..8962bcb 100644
--- a/ash/display/multi_display_manager_unittest.cc
+++ b/ash/display/multi_display_manager_unittest.cc
@@ -5,6 +5,7 @@
#include "ash/display/multi_display_manager.h"
#include "ash/display/display_controller.h"
+#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "base/format_macros.h"
@@ -387,5 +388,78 @@ TEST_F(MultiDisplayManagerTest, MAYBE_TestNativeDisplaysChanged) {
FindDisplayForId(internal_display_id).bounds().ToString());
}
+TEST_F(MultiDisplayManagerTest, EnsurePointerInDisplays) {
+ UpdateDisplay("200x200,300x300");
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+
+ aura::Env* env = aura::Env::GetInstance();
+
+ // Set the initial position.
+ root_windows[0]->MoveCursorTo(gfx::Point(350, 150));
+ EXPECT_EQ("350,150", env->last_mouse_location().ToString());
+
+ // A mouse pointer will be inside 2nd display.
+ UpdateDisplay("300x300,200x200");
+ EXPECT_EQ("350,150", 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, but the mouse pointer says in the
+ // 1st display.
+ UpdateDisplay("400x400");
+ EXPECT_EQ("350,50", 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.
+ root_windows[0]->MoveCursorTo(gfx::Point(150, 290));
+ EXPECT_EQ("150,290", env->last_mouse_location().ToString());
+
+ // The mouse pointer is outside and closest display is 1st one.
+ UpdateDisplay("300x280,200x200");
+ EXPECT_EQ("150,140", env->last_mouse_location().ToString());
+}
+
+TEST_F(MultiDisplayManagerTest, EnsurePointerInDisplays_2ndOnLeft) {
+ UpdateDisplay("200x200,300x300");
+ Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
+
+ // Set the 2nd display on the left.
+ DisplayController* display_controller =
+ Shell::GetInstance()->display_controller();
+ DisplayLayout layout = display_controller->default_display_layout();
+ layout.position = DisplayLayout::LEFT;
+ display_controller->SetDefaultDisplayLayout(layout);
+
+ EXPECT_EQ("-300,0 300x300",
+ ScreenAsh::GetSecondaryDisplay().bounds().ToString());
+
+ aura::Env* env = aura::Env::GetInstance();
+
+ // Set the initial position.
+ root_windows[0]->MoveCursorTo(gfx::Point(-150, 150));
+ EXPECT_EQ("-150,150", env->last_mouse_location().ToString());
+
+ // A mouse pointer will be in 2nd display.
+ UpdateDisplay("300x300,200x200");
+ EXPECT_EQ("-150,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());
+}
+
} // namespace internal
} // namespace ash