Index: ash/display/mouse_cursor_event_filter.cc |
diff --git a/ash/display/mouse_cursor_event_filter.cc b/ash/display/mouse_cursor_event_filter.cc |
index 8807f9900af4c5fcdbb79521ec969cd96d4c20ca..ba770452aad02c93a02ee1ce85a373b726550b82 100644 |
--- a/ash/display/mouse_cursor_event_filter.cc |
+++ b/ash/display/mouse_cursor_event_filter.cc |
@@ -4,10 +4,13 @@ |
#include "ash/display/mouse_cursor_event_filter.h" |
+#include <cmath> |
+ |
#include "ash/display/cursor_window_controller.h" |
#include "ash/display/display_controller.h" |
#include "ash/display/display_manager.h" |
#include "ash/display/shared_display_edge_indicator.h" |
+#include "ash/host/ash_window_tree_host.h" |
#include "ash/root_window_controller.h" |
#include "ash/screen_util.h" |
#include "ash/shell.h" |
@@ -16,9 +19,11 @@ |
#include "ui/aura/env.h" |
#include "ui/aura/window.h" |
#include "ui/aura/window_event_dispatcher.h" |
+#include "ui/aura/window_tree_host.h" |
#include "ui/base/layout.h" |
#include "ui/compositor/dip_util.h" |
#include "ui/events/event.h" |
+#include "ui/events/event_utils.h" |
#include "ui/gfx/screen.h" |
namespace ash { |
@@ -34,6 +39,106 @@ const int kMaximumSnapHeight = 16; |
const int kMinimumIndicatorHeight = 200; |
const int kIndicatorThickness = 1; |
+ |
+// This is to disable the new mouse warp logic in case |
+// it caused the problem in the branch. |
+bool enable_mouse_warp_in_native_coords = true; |
+ |
+void ConvertPointFromScreenToNative(const aura::Window* root_window, |
+ gfx::Point* point) { |
+ wm::ConvertPointFromScreen(root_window, point); |
+ root_window->GetHost()->ConvertPointToNativeScreen(point); |
+} |
+ |
+gfx::Rect GetNativeEdgeBounds(const aura::Window* root_window, |
+ gfx::Point start, |
+ gfx::Point end) { |
+ gfx::Rect native_bounds = root_window->GetHost()->GetBounds(); |
+ native_bounds.Inset( |
+ GetRootWindowController(root_window)->ash_host()->GetHostInsets()); |
+ |
+ ConvertPointFromScreenToNative(root_window, &start); |
+ ConvertPointFromScreenToNative(root_window, &end); |
+ if (start.x() == end.x()) { |
+ // vertical in native |
+ int x = std::abs(native_bounds.x() - start.x()) < |
+ std::abs(native_bounds.right() - start.x()) |
+ ? native_bounds.x() |
+ : native_bounds.right() - 1; |
+ return gfx::Rect( |
+ x, std::min(start.y(), end.y()), 1, std::abs(start.y() - end.y())); |
+ } else { |
+ // horizontal in native |
+ int y = std::abs(native_bounds.y() - start.y()) < |
+ std::abs(native_bounds.bottom() - start.y()) |
+ ? native_bounds.y() |
+ : native_bounds.bottom() - 1; |
+ return gfx::Rect( |
+ std::min(start.x(), end.x()), y, std::abs(start.x() - end.x()), 1); |
+ } |
+} |
+ |
+// Creates edge bounds from indicator bounds that fits the edge |
+// of the native window for |root_window|. |
+gfx::Rect CreateVerticalEdgeBoundsInNative(const aura::Window* root_window, |
+ const gfx::Rect& indicator_bounds) { |
+ gfx::Point start = indicator_bounds.origin(); |
+ gfx::Point end = start; |
+ end.set_y(indicator_bounds.bottom()); |
+ return GetNativeEdgeBounds(root_window, start, end); |
+} |
+ |
+gfx::Rect CreateHorizontalEdgeBoundsInNative( |
+ const aura::Window* root_window, |
+ const gfx::Rect& indicator_bounds) { |
+ gfx::Point start = indicator_bounds.origin(); |
+ gfx::Point end = start; |
+ end.set_x(indicator_bounds.right()); |
+ return GetNativeEdgeBounds(root_window, start, end); |
+} |
+ |
+void MovePointInside(const gfx::Rect& native_bounds, |
+ gfx::Point* point_in_native) { |
+ if (native_bounds.x() > point_in_native->x()) |
+ point_in_native->set_x(native_bounds.x()); |
+ if (native_bounds.right() < point_in_native->x()) |
+ point_in_native->set_x(native_bounds.right()); |
+ |
+ if (native_bounds.y() > point_in_native->y()) |
+ point_in_native->set_y(native_bounds.y()); |
+ if (native_bounds.bottom() < point_in_native->y()) |
+ point_in_native->set_y(native_bounds.bottom()); |
+} |
+ |
+// Moves the cursor to the point inside the root that is closest to |
+// the point_in_screen, which is outside of the root window. |
+void MoveCursorTo(aura::Window* root, const gfx::Point& point_in_screen) { |
+ gfx::Point point_in_native = point_in_screen; |
+ wm::ConvertPointFromScreen(root, &point_in_native); |
+ root->GetHost()->ConvertPointToNativeScreen(&point_in_native); |
+ |
+ // now fit the point inside the native bounds. |
+ gfx::Rect native_bounds = root->GetHost()->GetBounds(); |
+ gfx::Point native_origin = native_bounds.origin(); |
+ native_bounds.Inset( |
+ GetRootWindowController(root)->ash_host()->GetHostInsets()); |
+ // Shrink further so that the mouse doesn't warp on the |
+ // edge. The right/bottom needs to be shrink by 2 to subtract |
+ // the 1 px from width/height value. |
+ native_bounds.Inset(1, 1, 2, 2); |
+ |
+ MovePointInside(native_bounds, &point_in_native); |
+ gfx::Point point_in_host = point_in_native; |
+ |
+ point_in_host.Offset(-native_origin.x(), -native_origin.y()); |
+ root->GetHost()->MoveCursorToHostLocation(point_in_host); |
+} |
+ |
+} // namespace |
+ |
+// static |
+bool MouseCursorEventFilter::IsMouseWarpInNativeCoordsEnabled() { |
+ return enable_mouse_warp_in_native_coords; |
} |
MouseCursorEventFilter::MouseCursorEventFilter() |
@@ -42,14 +147,15 @@ MouseCursorEventFilter::MouseCursorEventFilter() |
drag_source_root_(NULL), |
scale_when_drag_started_(1.0f), |
shared_display_edge_indicator_(new SharedDisplayEdgeIndicator) { |
+ Shell::GetInstance()->display_controller()->AddObserver(this); |
} |
MouseCursorEventFilter::~MouseCursorEventFilter() { |
HideSharedEdgeIndicator(); |
+ Shell::GetInstance()->display_controller()->RemoveObserver(this); |
} |
-void MouseCursorEventFilter::ShowSharedEdgeIndicator( |
- const aura::Window* from) { |
+void MouseCursorEventFilter::ShowSharedEdgeIndicator(aura::Window* from) { |
HideSharedEdgeIndicator(); |
if (Shell::GetScreen()->GetNumDisplays() <= 1 || from == NULL) { |
src_indicator_bounds_.SetRect(0, 0, 0, 0); |
@@ -62,9 +168,9 @@ void MouseCursorEventFilter::ShowSharedEdgeIndicator( |
DisplayLayout::Position position = Shell::GetInstance()-> |
display_manager()->GetCurrentDisplayLayout().position; |
if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) |
- UpdateHorizontalIndicatorWindowBounds(); |
+ UpdateHorizontalEdgeBounds(); |
else |
- UpdateVerticalIndicatorWindowBounds(); |
+ UpdateVerticalEdgeBounds(); |
shared_display_edge_indicator_->Show(src_indicator_bounds_, |
dst_indicator_bounds_); |
@@ -72,6 +178,34 @@ void MouseCursorEventFilter::ShowSharedEdgeIndicator( |
void MouseCursorEventFilter::HideSharedEdgeIndicator() { |
shared_display_edge_indicator_->Hide(); |
+ OnDisplayConfigurationChanged(); |
+} |
+ |
+void MouseCursorEventFilter::OnDisplaysInitialized() { |
+ OnDisplayConfigurationChanged(); |
+} |
+ |
+void MouseCursorEventFilter::OnDisplayConfigurationChanged() { |
+ // Extra check for |num_connected_displays()| is for SystemDisplayApiTest |
+ // that injects MockScreen. |
+ if (Shell::GetScreen()->GetNumDisplays() <= 1 || |
+ Shell::GetInstance()->display_manager()->num_connected_displays() <= 1 || |
+ !enable_mouse_warp_in_native_coords) { |
+ src_edge_bounds_in_native_.SetRect(0, 0, 0, 0); |
+ dst_edge_bounds_in_native_.SetRect(0, 0, 0, 0); |
+ return; |
+ } |
+ |
+ drag_source_root_ = NULL; |
+ DisplayLayout::Position position = Shell::GetInstance() |
+ ->display_manager() |
+ ->GetCurrentDisplayLayout() |
+ .position; |
+ |
+ if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) |
+ UpdateHorizontalEdgeBounds(); |
+ else |
+ UpdateVerticalEdgeBounds(); |
} |
void MouseCursorEventFilter::OnMouseEvent(ui::MouseEvent* event) { |
@@ -101,13 +235,58 @@ void MouseCursorEventFilter::OnMouseEvent(ui::MouseEvent* event) { |
Shell::GetInstance()->display_controller()-> |
cursor_window_controller()->UpdateLocation(); |
- gfx::Point point_in_screen(event->location()); |
- wm::ConvertPointToScreen(target, &point_in_screen); |
- if (WarpMouseCursorIfNecessary(target->GetRootWindow(), point_in_screen)) |
+ if (WarpMouseCursorIfNecessary(event)) |
event->StopPropagation(); |
} |
-bool MouseCursorEventFilter::WarpMouseCursorIfNecessary( |
+bool MouseCursorEventFilter::WarpMouseCursorIfNecessary(ui::MouseEvent* event) { |
+ if (enable_mouse_warp_in_native_coords) { |
+ if (!event->HasNativeEvent()) |
+ return false; |
+ |
+ gfx::Point point_in_native = |
+ ui::EventSystemLocationFromNative(event->native_event()); |
+ |
+ gfx::Point point_in_screen = event->location(); |
+ aura::Window* target = static_cast<aura::Window*>(event->target()); |
+ wm::ConvertPointToScreen(target, &point_in_screen); |
+ |
+ return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen); |
+ } else { |
+ gfx::Point point_in_screen(event->location()); |
+ aura::Window* target = static_cast<aura::Window*>(event->target()); |
+ wm::ConvertPointToScreen(target, &point_in_screen); |
+ return WarpMouseCursorInScreenCoords(target->GetRootWindow(), |
+ point_in_screen); |
+ } |
+} |
+ |
+bool MouseCursorEventFilter::WarpMouseCursorInNativeCoords( |
+ const gfx::Point& point_in_native, |
+ const gfx::Point& point_in_screen) { |
+ if (Shell::GetScreen()->GetNumDisplays() <= 1 || |
+ mouse_warp_mode_ == WARP_NONE) |
+ return false; |
+ |
+ bool in_src_edge = src_edge_bounds_in_native_.Contains(point_in_native); |
+ bool in_dst_edge = dst_edge_bounds_in_native_.Contains(point_in_native); |
+ if (!in_src_edge && !in_dst_edge) |
+ return false; |
+ |
+ // The mouse must move. |
+ aura::Window* src_root = NULL; |
+ aura::Window* dst_root = NULL; |
+ GetSrcAndDstRootWindows(&src_root, &dst_root); |
+ |
+ if (in_src_edge) |
+ MoveCursorTo(dst_root, point_in_screen); |
+ else |
+ MoveCursorTo(src_root, point_in_screen); |
+ |
+ return true; |
+} |
+ |
+bool MouseCursorEventFilter::WarpMouseCursorInScreenCoords( |
aura::Window* target_root, |
const gfx::Point& point_in_screen) { |
if (Shell::GetScreen()->GetNumDisplays() <= 1 || |
@@ -178,7 +357,7 @@ bool MouseCursorEventFilter::WarpMouseCursorIfNecessary( |
return false; |
} |
-void MouseCursorEventFilter::UpdateHorizontalIndicatorWindowBounds() { |
+void MouseCursorEventFilter::UpdateHorizontalEdgeBounds() { |
bool from_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; |
// GetPrimaryDisplay returns an object on stack, so copy the bounds |
// instead of using reference. |
@@ -205,9 +384,19 @@ void MouseCursorEventFilter::UpdateHorizontalIndicatorWindowBounds() { |
position == DisplayLayout::TOP ? |
primary_bounds.y() - (from_primary ? kIndicatorThickness : 0) : |
primary_bounds.bottom() - (from_primary ? 0 : kIndicatorThickness)); |
+ |
+ aura::Window* src_root = NULL; |
+ aura::Window* dst_root = NULL; |
+ GetSrcAndDstRootWindows(&src_root, &dst_root); |
+ |
+ src_edge_bounds_in_native_ = |
+ CreateHorizontalEdgeBoundsInNative(src_root, src_indicator_bounds_); |
+ dst_edge_bounds_in_native_ = |
+ CreateHorizontalEdgeBoundsInNative(dst_root, dst_indicator_bounds_); |
} |
-void MouseCursorEventFilter::UpdateVerticalIndicatorWindowBounds() { |
+void MouseCursorEventFilter::UpdateVerticalEdgeBounds() { |
+ int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0; |
bool in_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; |
// GetPrimaryDisplay returns an object on stack, so copy the bounds |
// instead of using reference. |
@@ -237,7 +426,7 @@ void MouseCursorEventFilter::UpdateVerticalIndicatorWindowBounds() { |
const gfx::Rect& source_bounds = |
in_primary ? primary_bounds : secondary_bounds; |
- int upper_indicator_y = source_bounds.y() + kMaximumSnapHeight; |
+ int upper_indicator_y = source_bounds.y() + snap_height; |
int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y); |
// This gives a hight that can be used without sacrifying the snap space. |
@@ -257,6 +446,38 @@ void MouseCursorEventFilter::UpdateVerticalIndicatorWindowBounds() { |
} |
src_indicator_bounds_.set_y(upper_indicator_y); |
src_indicator_bounds_.set_height(lower_indicator_y - upper_indicator_y); |
+ |
+ aura::Window* src_root = NULL; |
+ aura::Window* dst_root = NULL; |
+ GetSrcAndDstRootWindows(&src_root, &dst_root); |
+ |
+ // Native |
+ src_edge_bounds_in_native_ = |
+ CreateVerticalEdgeBoundsInNative(src_root, src_indicator_bounds_); |
+ dst_edge_bounds_in_native_ = |
+ CreateVerticalEdgeBoundsInNative(dst_root, dst_indicator_bounds_); |
+} |
+ |
+void MouseCursorEventFilter::GetSrcAndDstRootWindows(aura::Window** src_root, |
+ aura::Window** dst_root) { |
+ aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
+ *src_root = drag_source_root_ ? drag_source_root_ |
+ : Shell::GetInstance()->GetPrimaryRootWindow(); |
+ *dst_root = root_windows[0] == *src_root ? root_windows[1] : root_windows[0]; |
+} |
+ |
+bool MouseCursorEventFilter::WarpMouseCursorIfNecessaryForTest( |
+ aura::Window* target_root, |
+ const gfx::Point& point_in_screen) { |
+ if (enable_mouse_warp_in_native_coords) { |
+ gfx::Point native = point_in_screen; |
+ wm::ConvertPointFromScreen(target_root, &native); |
+ target_root->GetHost()->ConvertPointToNativeScreen(&native); |
+ return WarpMouseCursorInNativeCoords(native, point_in_screen); |
+ } else { |
+ return WarpMouseCursorInScreenCoords(target_root, point_in_screen); |
+ } |
+ return true; |
} |
} // namespace ash |