Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2189)

Unified Diff: ash/display/mouse_cursor_event_filter.cc

Issue 270863005: Use native coordinates to warp the cursor to another display. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ash/display/mouse_cursor_event_filter.h ('k') | ash/display/mouse_cursor_event_filter_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « ash/display/mouse_cursor_event_filter.h ('k') | ash/display/mouse_cursor_event_filter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698