summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ash/display/mouse_cursor_event_filter.cc3
-rw-r--r--ash/display/multi_display_manager.cc20
-rw-r--r--ash/display/multi_display_manager.h6
-rw-r--r--ash/screen_ash.cc11
-rw-r--r--ash/screen_ash.h5
-rw-r--r--ash/screensaver/screensaver_view_unittest.cc1
-rw-r--r--ash/wm/coordinate_conversion.cc95
-rw-r--r--ui/gfx/display.h3
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: