diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-26 23:47:14 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-26 23:47:14 +0000 |
commit | 9c0cbfdcf94cedd7be9a1e64ffc6bdea6cdb7ba6 (patch) | |
tree | fda491d190454005201cb0daa109c1521de5d4de /ash | |
parent | 48542312f33e38c1e7f754b1a8029b53e50fcc59 (diff) | |
download | chromium_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.cc | 38 | ||||
-rw-r--r-- | ash/display/multi_display_manager.h | 4 | ||||
-rw-r--r-- | ash/display/multi_display_manager_unittest.cc | 74 |
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 |