diff options
author | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-07 14:17:44 +0000 |
---|---|---|
committer | oshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-07 14:17:44 +0000 |
commit | fb4d20935c35d913ab639e272a595a32e06f716e (patch) | |
tree | efb2af7a5fc6b3dce989aa028abaef09755a1d51 | |
parent | 488e650f46fa312273e6a12c5a5097881b1db755 (diff) | |
download | chromium_src-fb4d20935c35d913ab639e272a595a32e06f716e.zip chromium_src-fb4d20935c35d913ab639e272a595a32e06f716e.tar.gz chromium_src-fb4d20935c35d913ab639e272a595a32e06f716e.tar.bz2 |
Convert the mouse event's location that is captured by aura correctly
BUG=145173
TEST=manual. see bug for repro step.
Review URL: https://chromiumcodereview.appspot.com/10916121
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155382 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ash/display/mouse_cursor_event_filter.cc | 3 | ||||
-rw-r--r-- | ash/display/multi_display_manager.cc | 20 | ||||
-rw-r--r-- | ash/display/multi_display_manager.h | 6 | ||||
-rw-r--r-- | ash/screen_ash.cc | 11 | ||||
-rw-r--r-- | ash/screen_ash.h | 5 | ||||
-rw-r--r-- | ash/screensaver/screensaver_view_unittest.cc | 1 | ||||
-rw-r--r-- | ash/wm/coordinate_conversion.cc | 95 | ||||
-rw-r--r-- | ui/gfx/display.h | 3 |
8 files changed, 110 insertions, 34 deletions
diff --git a/ash/display/mouse_cursor_event_filter.cc b/ash/display/mouse_cursor_event_filter.cc index fafe897..2973ef8 100644 --- a/ash/display/mouse_cursor_event_filter.cc +++ b/ash/display/mouse_cursor_event_filter.cc @@ -140,7 +140,8 @@ bool MouseCursorEventFilter::WarpMouseCursorIfNecessary( point_in_dst_screen.Offset(offset_x, offset_y); aura::RootWindow* dst_root = wm::GetRootWindowAt(point_in_dst_screen); - // Warp the mouse cursor only if the location is in the indicator bounds. + // Warp the mouse cursor only if the location is in the indicator bounds + // or the mouse pointer is in the destination root. if (mouse_warp_mode_ == WARP_DRAG && dst_root != drag_source_root_ && !src_indicator_bounds_.Contains(point_in_screen)) { diff --git a/ash/display/multi_display_manager.cc b/ash/display/multi_display_manager.cc index fa39ace..f31c9a8 100644 --- a/ash/display/multi_display_manager.cc +++ b/ash/display/multi_display_manager.cc @@ -81,6 +81,17 @@ bool MultiDisplayManager::UpdateWorkAreaOfDisplayNearestWindow( return old_work_area != display.work_area(); } +const gfx::Display& MultiDisplayManager::FindDisplayContainingPoint( + const gfx::Point& point_in_screen) const { + for (std::vector<gfx::Display>::const_iterator iter = displays_.begin(); + iter != displays_.end(); ++iter) { + const gfx::Display& display = *iter; + if (display.bounds().Contains(point_in_screen)) + return display; + } + return GetInvalidDisplay(); +} + void MultiDisplayManager::OnNativeDisplaysChanged( const std::vector<gfx::Display>& new_displays) { size_t min = std::min(displays_.size(), new_displays.size()); @@ -157,15 +168,10 @@ const gfx::Display& MultiDisplayManager::GetDisplayNearestWindow( const gfx::Display& MultiDisplayManager::GetDisplayNearestPoint( const gfx::Point& point) const { - for (std::vector<gfx::Display>::const_iterator iter = displays_.begin(); - iter != displays_.end(); ++iter) { - const gfx::Display& display = *iter; - if (display.bounds().Contains(point)) - return display; - } // Fallback to the primary display if there is no root display containing // the |point|. - return displays_[0]; + gfx::Display display = FindDisplayContainingPoint(point); + return display.is_valid() ? display : displays_[0]; } const gfx::Display& MultiDisplayManager::GetDisplayMatching( diff --git a/ash/display/multi_display_manager.h b/ash/display/multi_display_manager.h index c702dfb..61e1163 100644 --- a/ash/display/multi_display_manager.h +++ b/ash/display/multi_display_manager.h @@ -45,6 +45,12 @@ class ASH_EXPORT MultiDisplayManager : public aura::DisplayManager, bool UpdateWorkAreaOfDisplayNearestWindow(const aura::Window* window, const gfx::Insets& insets); + // Finds the display that contains |point| in screeen coordinates. + // Returns invalid display if there is no display that can satisfy + // the condition. + const gfx::Display& FindDisplayContainingPoint( + const gfx::Point& point_in_screen) const; + // DisplayManager overrides: virtual void OnNativeDisplaysChanged( const std::vector<gfx::Display>& displays) OVERRIDE; diff --git a/ash/screen_ash.cc b/ash/screen_ash.cc index 231b806..74a6f96f 100644 --- a/ash/screen_ash.cc +++ b/ash/screen_ash.cc @@ -4,6 +4,7 @@ #include "ash/screen_ash.h" +#include "ash/display/multi_display_manager.h" #include "ash/shell.h" #include "ash/wm/coordinate_conversion.h" #include "ash/wm/shelf_layout_manager.h" @@ -18,8 +19,9 @@ namespace ash { namespace { -aura::DisplayManager* GetDisplayManager() { - return aura::Env::GetInstance()->display_manager(); +internal::MultiDisplayManager* GetDisplayManager() { + return static_cast<internal::MultiDisplayManager*>( + aura::Env::GetInstance()->display_manager()); } } // namespace @@ -30,6 +32,11 @@ ScreenAsh::~ScreenAsh() { } // static +gfx::Display ScreenAsh::FindDisplayContainingPoint(const gfx::Point& point) { + return GetDisplayManager()->FindDisplayContainingPoint(point); +} + +// static gfx::Rect ScreenAsh::GetMaximizedWindowBoundsInParent(aura::Window* window) { if (window->GetRootWindow() == Shell::GetPrimaryRootWindow()) return Shell::GetInstance()->shelf()->GetMaximizedWindowBounds(window); diff --git a/ash/screen_ash.h b/ash/screen_ash.h index 8c57322..cf2f221 100644 --- a/ash/screen_ash.h +++ b/ash/screen_ash.h @@ -22,6 +22,11 @@ class ASH_EXPORT ScreenAsh : public gfx::ScreenImpl { ScreenAsh(); virtual ~ScreenAsh(); + // Finds the display that contains |point| in screeen coordinates. + // Returns invalid display if there is no display that can satisfy + // the condition. + static gfx::Display FindDisplayContainingPoint(const gfx::Point& point); + // Returns the bounds for maximized windows in parent coordinates. // Maximized windows trigger auto-hiding the shelf. static gfx::Rect GetMaximizedWindowBoundsInParent(aura::Window* window); diff --git a/ash/screensaver/screensaver_view_unittest.cc b/ash/screensaver/screensaver_view_unittest.cc index 25cfb6d..55789e1 100644 --- a/ash/screensaver/screensaver_view_unittest.cc +++ b/ash/screensaver/screensaver_view_unittest.cc @@ -29,6 +29,7 @@ class ScreensaverViewTest : public ash::test::AshTestBase { } virtual void TearDown() OVERRIDE { + RunAllPendingInMessageLoop(); AshTestBase::TearDown(); } diff --git a/ash/wm/coordinate_conversion.cc b/ash/wm/coordinate_conversion.cc index 68681e7..306d55f 100644 --- a/ash/wm/coordinate_conversion.cc +++ b/ash/wm/coordinate_conversion.cc @@ -5,6 +5,7 @@ #include "ash/wm/coordinate_conversion.h" #include "ash/display/display_controller.h" +#include "ash/screen_ash.h" #include "ash/shell.h" #include "ui/aura/client/screen_position_client.h" #include "ui/aura/root_window.h" @@ -38,32 +39,78 @@ std::pair<aura::RootWindow*, gfx::Point> GetRootWindowRelativeToWindow( aura::Window::ConvertPointToTarget(window, root_window, &location_in_root); #if defined(USE_X11) - // This conversion is necessary for dealing with the "pointer warp" feature in - // ash/display/display_controller.cc. For example, if we have two displays, - // say 1000x1000 (primary) and 500x500 (extended one on the right), and start - // dragging a window at (999, 123), and then move the pointer to the right, - // the pointer suddenly warps to the extended display. The destination is - // (0, 123) in the secondary root window's coordinates, or (1000, 123) in the - // screen coordinates. However, since the mouse is captured during drag, a - // weird LocatedEvent, something like (0, 1123) in the *primary* root window's - // coordinates, is sent to Chrome (Remember that in the native X11 world, the - // two root windows are always stacked vertically regardless of the display - // layout in Ash). We need to figure out that (0, 1123) in the primary root - // window's coordinates is actually (0, 123) in the extended root window's - // coordinates. if (!root_window->ContainsPointInRoot(location_in_root)) { - gfx::Point location_in_native = location_in_root; - root_window->ConvertPointToNativeScreen(&location_in_native); + // This is to translate an out of bounds mouse pointer location in + // its root window coordinate into correct screen coordinates. + // There are two scenarios that a target root window receives an + // out of bounds mouse event. + // + // 1) When aura's input is captured by an aura window, and the + // mouse pointer is on another root window. Typical example is + // when you open a menu and move the mouse to another display (which is + // another root window). X's mouse event is sent to the window + // where mouse is on, but the aura event is sent to the window + // that has a capture, which is on a different root window. + // This is covered in the is_valid block below. + // + // 2) When X's native input is captured by a drag operation. When + // you press a button on a window, X automatically grabs the + // mouse input (passive grab + // http://www.x.org/wiki/development/documentation/grabprocessing) + // and keeps sending mouse events to the window where the drag + // operation started until the mouse button is released. This is + // covered in the else block below. - Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); - for (size_t i = 0; i < root_windows.size(); ++i) { - const gfx::Rect native_bounds(root_windows[i]->GetHostOrigin(), - root_windows[i]->GetHostSize()); // in px. - if (native_bounds.Contains(location_in_native)) { - root_window = root_windows[i]; - location_in_root = location_in_native; - root_window->ConvertPointFromNativeScreen(&location_in_root); - break; + gfx::Point location_in_screen = location_in_root; + aura::client::ScreenPositionClient* client = + aura::client::GetScreenPositionClient(root_window); + client->ConvertPointToScreen(root_window, &location_in_screen); + gfx::Display display = + ScreenAsh::FindDisplayContainingPoint(location_in_screen); + if (display.is_valid()) { + // This conversion is necessary to warp the mouse pointer + // correctly while aura's input capture is in effect. In this + // case, the location is already translated relative to the root + // (but it's outside of the root window), so all we have to do + // is to find a root window containing the point in screen + // coordinate. + aura::RootWindow* root = Shell::GetInstance()->display_controller()-> + GetRootWindowForDisplayId(display.id()); + DCHECK(root); + client->ConvertPointFromScreen(root, &location_in_screen); + root_window = root; + location_in_root = location_in_screen; + } else { + // This conversion is necessary to deal with X's passive input + // grab while dragging window. For example, if we have two + // displays, say 1000x1000 (primary) and 500x500 (extended one + // on the right), and start dragging a window at (999, 123), and + // then move the pointer to the right, the pointer suddenly + // warps to the extended display. The destination is (0, 123) in + // the secondary root window's coordinates, or (1000, 123) in + // the screen coordinates. However, since the mouse is captured + // by X during drag, a weird LocatedEvent, something like (0, 1123) + // in the *primary* root window's coordinates, is sent to Chrome + // (Remember that in the native X11 world, the two root windows + // are always stacked vertically regardless of the display + // layout in Ash). We need to figure out that (0, 1123) in the + // primary root window's coordinates is actually (0, 123) in the + // extended root window's coordinates. + + gfx::Point location_in_native(location_in_root); + root_window->ConvertPointToNativeScreen(&location_in_native); + + Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); + for (size_t i = 0; i < root_windows.size(); ++i) { + const gfx::Rect native_bounds( + root_windows[i]->GetHostOrigin(), + root_windows[i]->GetHostSize()); // in px. + if (native_bounds.Contains(location_in_native)) { + root_window = root_windows[i]; + location_in_root = location_in_native; + root_window->ConvertPointFromNativeScreen(&location_in_root); + break; + } } } } diff --git a/ui/gfx/display.h b/ui/gfx/display.h index c91e52d..5abe1be 100644 --- a/ui/gfx/display.h +++ b/ui/gfx/display.h @@ -87,6 +87,9 @@ class UI_EXPORT Display { // Returns a string representation of the display; std::string ToString() const; + // True if the display contains valid display id. + bool is_valid() const { return id_ != kInvalidDisplayID; } + static const int64 kInvalidDisplayID; private: |