| Index: ash/display/mouse_cursor_event_filter_ozone.cc
|
| diff --git a/ash/display/mouse_cursor_event_filter_ozone.cc b/ash/display/mouse_cursor_event_filter_ozone.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8c0487156bc2fbe677a3716de619d04900266737
|
| --- /dev/null
|
| +++ b/ash/display/mouse_cursor_event_filter_ozone.cc
|
| @@ -0,0 +1,107 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ash/display/mouse_cursor_event_filter.h"
|
| +
|
| +#include "ash/shell.h"
|
| +#include "ash/wm/coordinate_conversion.h"
|
| +#include "ash/wm/window_util.h"
|
| +#include "ui/wm/core/coordinate_conversion.h"
|
| +
|
| +namespace ash {
|
| +
|
| +void MouseCursorEventFilter::OnDisplayConfigurationChanged() {
|
| + src_edge_bounds_in_native_.SetRect(0, 0, 0, 0);
|
| + dst_edge_bounds_in_native_.SetRect(0, 0, 0, 0);
|
| +}
|
| +
|
| +bool MouseCursorEventFilter::WarpMouseCursorIfNecessary(ui::MouseEvent* event) {
|
| + if (event->flags() & ui::EF_IS_SYNTHESIZED)
|
| + return false;
|
| +
|
| + 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::WarpMouseCursorInScreenCoords(
|
| + aura::Window* target_root,
|
| + const gfx::Point& point_in_screen) {
|
| + if (Shell::GetScreen()->GetNumDisplays() <= 1 ||
|
| + mouse_warp_mode_ == WARP_NONE)
|
| + return false;
|
| +
|
| + // Do not warp again right after the cursor was warped. Sometimes the offset
|
| + // is not long enough and the cursor moves at the edge of the destination
|
| + // display. See crbug.com/278885
|
| + // TODO(mukai): simplify the offset calculation below, it would not be
|
| + // necessary anymore with this flag.
|
| + if (was_mouse_warped_) {
|
| + was_mouse_warped_ = false;
|
| + return false;
|
| + }
|
| +
|
| + aura::Window* root_at_point = wm::GetRootWindowAt(point_in_screen);
|
| + gfx::Point point_in_root = point_in_screen;
|
| + ::wm::ConvertPointFromScreen(root_at_point, &point_in_root);
|
| + gfx::Rect root_bounds = root_at_point->bounds();
|
| + int offset_x = 0;
|
| + int offset_y = 0;
|
| +
|
| + // If the window is dragged between 2x display and 1x display,
|
| + // staring from 2x display, pointer location is rounded by the
|
| + // source scale factor (2x) so it will never reach the edge (which
|
| + // is odd). Shrink by scale factor of the display where the dragging
|
| + // started instead. Only integral scale factor is supported for now.
|
| + int shrink = scale_when_drag_started_;
|
| + // Make the bounds inclusive to detect the edge.
|
| + root_bounds.Inset(0, 0, shrink, shrink);
|
| + gfx::Rect src_indicator_bounds = src_indicator_bounds_;
|
| + src_indicator_bounds.Inset(-shrink, -shrink, -shrink, -shrink);
|
| +
|
| + if (point_in_root.x() <= root_bounds.x()) {
|
| + // Use -2, not -1, to avoid infinite loop of pointer warp.
|
| + offset_x = -2 * scale_when_drag_started_;
|
| + } else if (point_in_root.x() >= root_bounds.right()) {
|
| + offset_x = 2 * scale_when_drag_started_;
|
| + } else if (point_in_root.y() <= root_bounds.y()) {
|
| + offset_y = -2 * scale_when_drag_started_;
|
| + } else if (point_in_root.y() >= root_bounds.bottom()) {
|
| + offset_y = 2 * scale_when_drag_started_;
|
| + } else {
|
| + return false;
|
| + }
|
| +
|
| + gfx::Point point_in_dst_screen(point_in_screen);
|
| + point_in_dst_screen.Offset(offset_x, offset_y);
|
| + aura::Window* dst_root = wm::GetRootWindowAt(point_in_dst_screen);
|
| +
|
| + // 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)) {
|
| + return false;
|
| + }
|
| +
|
| + ::wm::ConvertPointFromScreen(dst_root, &point_in_dst_screen);
|
| +
|
| + if (dst_root->bounds().Contains(point_in_dst_screen)) {
|
| + DCHECK_NE(dst_root, root_at_point);
|
| + was_mouse_warped_ = true;
|
| + dst_root->MoveCursorTo(point_in_dst_screen);
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +bool MouseCursorEventFilter::WarpMouseCursorIfNecessaryForTest(
|
| + aura::Window* target_root,
|
| + const gfx::Point& point_in_screen) {
|
| + return WarpMouseCursorInScreenCoords(target_root, point_in_screen);
|
| +}
|
| +
|
| +} // namespac
|
|
|