Commit 8ab613cf authored by oshima@chromium.org's avatar oshima@chromium.org

Use native coordinates to warp the cursor to another display.

This is roughly how this works.
- Takes the bounds of the edge indicator in screen coords
  and convert to native coords
- If the location of mouse in native coords moves into this
  bounds, we need to warp the mouse.
- Convert the current mouse location in screen coords to the
  destination window's host coords. Adjust so that the location is inside the host window's bounds.

No flag. I'll simply flip the flag if I need to disable this on branch.

BUG=321699,306632
TEST=TBD

Review URL: https://codereview.chromium.org/270863005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269758 0039d316-1c4b-4281-b951-d872f2087c98
parent bbd72ec9
...@@ -247,8 +247,6 @@ void DisplayController::Start() { ...@@ -247,8 +247,6 @@ void DisplayController::Start() {
new VirtualKeyboardWindowController); new VirtualKeyboardWindowController);
Shell::GetScreen()->AddObserver(this); Shell::GetScreen()->AddObserver(this);
Shell::GetInstance()->display_manager()->set_delegate(this); Shell::GetInstance()->display_manager()->set_delegate(this);
FOR_EACH_OBSERVER(Observer, observers_, OnDisplaysInitialized());
} }
void DisplayController::Shutdown() { void DisplayController::Shutdown() {
...@@ -294,6 +292,8 @@ void DisplayController::InitDisplays() { ...@@ -294,6 +292,8 @@ void DisplayController::InitDisplays() {
} }
} }
UpdateHostWindowNames(); UpdateHostWindowNames();
FOR_EACH_OBSERVER(Observer, observers_, OnDisplaysInitialized());
} }
void DisplayController::AddObserver(Observer* observer) { void DisplayController::AddObserver(Observer* observer) {
......
...@@ -4,10 +4,13 @@ ...@@ -4,10 +4,13 @@
#include "ash/display/mouse_cursor_event_filter.h" #include "ash/display/mouse_cursor_event_filter.h"
#include <cmath>
#include "ash/display/cursor_window_controller.h" #include "ash/display/cursor_window_controller.h"
#include "ash/display/display_controller.h" #include "ash/display/display_controller.h"
#include "ash/display/display_manager.h" #include "ash/display/display_manager.h"
#include "ash/display/shared_display_edge_indicator.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/root_window_controller.h"
#include "ash/screen_util.h" #include "ash/screen_util.h"
#include "ash/shell.h" #include "ash/shell.h"
...@@ -16,9 +19,11 @@ ...@@ -16,9 +19,11 @@
#include "ui/aura/env.h" #include "ui/aura/env.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h" #include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/layout.h" #include "ui/base/layout.h"
#include "ui/compositor/dip_util.h" #include "ui/compositor/dip_util.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/screen.h" #include "ui/gfx/screen.h"
namespace ash { namespace ash {
...@@ -34,6 +39,106 @@ const int kMaximumSnapHeight = 16; ...@@ -34,6 +39,106 @@ const int kMaximumSnapHeight = 16;
const int kMinimumIndicatorHeight = 200; const int kMinimumIndicatorHeight = 200;
const int kIndicatorThickness = 1; 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() MouseCursorEventFilter::MouseCursorEventFilter()
...@@ -42,14 +147,15 @@ MouseCursorEventFilter::MouseCursorEventFilter() ...@@ -42,14 +147,15 @@ MouseCursorEventFilter::MouseCursorEventFilter()
drag_source_root_(NULL), drag_source_root_(NULL),
scale_when_drag_started_(1.0f), scale_when_drag_started_(1.0f),
shared_display_edge_indicator_(new SharedDisplayEdgeIndicator) { shared_display_edge_indicator_(new SharedDisplayEdgeIndicator) {
Shell::GetInstance()->display_controller()->AddObserver(this);
} }
MouseCursorEventFilter::~MouseCursorEventFilter() { MouseCursorEventFilter::~MouseCursorEventFilter() {
HideSharedEdgeIndicator(); HideSharedEdgeIndicator();
Shell::GetInstance()->display_controller()->RemoveObserver(this);
} }
void MouseCursorEventFilter::ShowSharedEdgeIndicator( void MouseCursorEventFilter::ShowSharedEdgeIndicator(aura::Window* from) {
const aura::Window* from) {
HideSharedEdgeIndicator(); HideSharedEdgeIndicator();
if (Shell::GetScreen()->GetNumDisplays() <= 1 || from == NULL) { if (Shell::GetScreen()->GetNumDisplays() <= 1 || from == NULL) {
src_indicator_bounds_.SetRect(0, 0, 0, 0); src_indicator_bounds_.SetRect(0, 0, 0, 0);
...@@ -62,9 +168,9 @@ void MouseCursorEventFilter::ShowSharedEdgeIndicator( ...@@ -62,9 +168,9 @@ void MouseCursorEventFilter::ShowSharedEdgeIndicator(
DisplayLayout::Position position = Shell::GetInstance()-> DisplayLayout::Position position = Shell::GetInstance()->
display_manager()->GetCurrentDisplayLayout().position; display_manager()->GetCurrentDisplayLayout().position;
if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM)
UpdateHorizontalIndicatorWindowBounds(); UpdateHorizontalEdgeBounds();
else else
UpdateVerticalIndicatorWindowBounds(); UpdateVerticalEdgeBounds();
shared_display_edge_indicator_->Show(src_indicator_bounds_, shared_display_edge_indicator_->Show(src_indicator_bounds_,
dst_indicator_bounds_); dst_indicator_bounds_);
...@@ -72,6 +178,34 @@ void MouseCursorEventFilter::ShowSharedEdgeIndicator( ...@@ -72,6 +178,34 @@ void MouseCursorEventFilter::ShowSharedEdgeIndicator(
void MouseCursorEventFilter::HideSharedEdgeIndicator() { void MouseCursorEventFilter::HideSharedEdgeIndicator() {
shared_display_edge_indicator_->Hide(); 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) { void MouseCursorEventFilter::OnMouseEvent(ui::MouseEvent* event) {
...@@ -101,13 +235,58 @@ void MouseCursorEventFilter::OnMouseEvent(ui::MouseEvent* event) { ...@@ -101,13 +235,58 @@ void MouseCursorEventFilter::OnMouseEvent(ui::MouseEvent* event) {
Shell::GetInstance()->display_controller()-> Shell::GetInstance()->display_controller()->
cursor_window_controller()->UpdateLocation(); cursor_window_controller()->UpdateLocation();
gfx::Point point_in_screen(event->location()); if (WarpMouseCursorIfNecessary(event))
wm::ConvertPointToScreen(target, &point_in_screen);
if (WarpMouseCursorIfNecessary(target->GetRootWindow(), point_in_screen))
event->StopPropagation(); 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, aura::Window* target_root,
const gfx::Point& point_in_screen) { const gfx::Point& point_in_screen) {
if (Shell::GetScreen()->GetNumDisplays() <= 1 || if (Shell::GetScreen()->GetNumDisplays() <= 1 ||
...@@ -178,7 +357,7 @@ bool MouseCursorEventFilter::WarpMouseCursorIfNecessary( ...@@ -178,7 +357,7 @@ bool MouseCursorEventFilter::WarpMouseCursorIfNecessary(
return false; return false;
} }
void MouseCursorEventFilter::UpdateHorizontalIndicatorWindowBounds() { void MouseCursorEventFilter::UpdateHorizontalEdgeBounds() {
bool from_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; bool from_primary = Shell::GetPrimaryRootWindow() == drag_source_root_;
// GetPrimaryDisplay returns an object on stack, so copy the bounds // GetPrimaryDisplay returns an object on stack, so copy the bounds
// instead of using reference. // instead of using reference.
...@@ -205,9 +384,19 @@ void MouseCursorEventFilter::UpdateHorizontalIndicatorWindowBounds() { ...@@ -205,9 +384,19 @@ void MouseCursorEventFilter::UpdateHorizontalIndicatorWindowBounds() {
position == DisplayLayout::TOP ? position == DisplayLayout::TOP ?
primary_bounds.y() - (from_primary ? kIndicatorThickness : 0) : primary_bounds.y() - (from_primary ? kIndicatorThickness : 0) :
primary_bounds.bottom() - (from_primary ? 0 : kIndicatorThickness)); 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_; bool in_primary = Shell::GetPrimaryRootWindow() == drag_source_root_;
// GetPrimaryDisplay returns an object on stack, so copy the bounds // GetPrimaryDisplay returns an object on stack, so copy the bounds
// instead of using reference. // instead of using reference.
...@@ -237,7 +426,7 @@ void MouseCursorEventFilter::UpdateVerticalIndicatorWindowBounds() { ...@@ -237,7 +426,7 @@ void MouseCursorEventFilter::UpdateVerticalIndicatorWindowBounds() {
const gfx::Rect& source_bounds = const gfx::Rect& source_bounds =
in_primary ? primary_bounds : secondary_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); 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. // This gives a hight that can be used without sacrifying the snap space.
...@@ -257,6 +446,38 @@ void MouseCursorEventFilter::UpdateVerticalIndicatorWindowBounds() { ...@@ -257,6 +446,38 @@ void MouseCursorEventFilter::UpdateVerticalIndicatorWindowBounds() {
} }
src_indicator_bounds_.set_y(upper_indicator_y); src_indicator_bounds_.set_y(upper_indicator_y);
src_indicator_bounds_.set_height(lower_indicator_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 } // namespace ash
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#define ASH_DISPLAY_MOUSE_CURSOR_EVENT_FILTER_H #define ASH_DISPLAY_MOUSE_CURSOR_EVENT_FILTER_H
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/display/display_controller.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
...@@ -18,13 +19,15 @@ class Window; ...@@ -18,13 +19,15 @@ class Window;
} }
namespace ash { namespace ash {
class DisplayController;
class SharedDisplayEdgeIndicator; class SharedDisplayEdgeIndicator;
// An event filter that controls mouse location in extended desktop // An event filter that controls mouse location in extended desktop
// environment. // environment.
class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler { class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler,
public DisplayController::Observer {
public: public:
static bool IsMouseWarpInNativeCoordsEnabled();
enum MouseWarpMode { enum MouseWarpMode {
WARP_ALWAYS, // Always warp the mouse when possible. WARP_ALWAYS, // Always warp the mouse when possible.
WARP_DRAG, // Used when dragging a window. Top and bottom WARP_DRAG, // Used when dragging a window. Top and bottom
...@@ -42,10 +45,14 @@ class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler { ...@@ -42,10 +45,14 @@ class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler {
// Shows/Hide the indicator for window dragging. The |from| // Shows/Hide the indicator for window dragging. The |from|
// is the window where the dragging started. // is the window where the dragging started.
void ShowSharedEdgeIndicator(const aura::Window* from); void ShowSharedEdgeIndicator(aura::Window* from);
void HideSharedEdgeIndicator(); void HideSharedEdgeIndicator();
// Overridden from ui::EventHandler: // DisplayController::Observer:
virtual void OnDisplaysInitialized() OVERRIDE;
virtual void OnDisplayConfigurationChanged() OVERRIDE;
// ui::EventHandler:
virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
private: private:
...@@ -59,20 +66,39 @@ class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler { ...@@ -59,20 +66,39 @@ class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler {
IndicatorBoundsTestOnLeft); IndicatorBoundsTestOnLeft);
FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest, FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest,
IndicatorBoundsTestOnTopBottom); IndicatorBoundsTestOnTopBottom);
FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, WarpMousePointer); FRIEND_TEST_ALL_PREFIXES(MouseCursorEventFilterTest,
WarpMouseDifferentScaleDisplaysInNative);
void reset_was_mouse_warped_for_test() { was_mouse_warped_ = false; } FRIEND_TEST_ALL_PREFIXES(DragWindowResizerTest, WarpMousePointer);
// Warps the mouse cursor to an alternate root window when the // Warps the mouse cursor to an alternate root window when the
// |point_in_screen|, which is the location of the mouse cursor, // mouse location in |event|, hits the edge of the event target's root and
// hits or exceeds the edge of the |target_root| and the mouse cursor // the mouse cursor is considered to be in an alternate display.
// is considered to be in an alternate display. Returns true if // Returns true if/ the cursor was moved.
// the cursor was moved. bool WarpMouseCursorIfNecessary(ui::MouseEvent* event);
bool WarpMouseCursorIfNecessary(aura::Window* target_root,
const gfx::Point& point_in_screen); bool WarpMouseCursorInNativeCoords(const gfx::Point& point_in_native,
const gfx::Point& point_in_screen);
bool WarpMouseCursorInScreenCoords(aura::Window* target_root,
const gfx::Point& point_in_screen);
// Update the edge/indicator bounds based on the current
// display configuration.
void UpdateHorizontalEdgeBounds();
void UpdateVerticalEdgeBounds();
// Returns the source and destination window. When the
// mouse_warp_mode_ is WARP_DRAG, src_window is the root window
// where the drag starts. When the mouse_warp_mode_ is WARP_ALWAYS,
// the src_window is always the primary root window, because there
// is no difference between moving src to dst and moving dst to src.
void GetSrcAndDstRootWindows(aura::Window** src_window,
aura::Window** dst_window);
void reset_was_mouse_warped_for_test() { was_mouse_warped_ = false; }
void UpdateHorizontalIndicatorWindowBounds(); bool WarpMouseCursorIfNecessaryForTest(aura::Window* target_root,
void UpdateVerticalIndicatorWindowBounds(); const gfx::Point& point_in_screen);
MouseWarpMode mouse_warp_mode_; MouseWarpMode mouse_warp_mode_;
...@@ -85,8 +111,11 @@ class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler { ...@@ -85,8 +111,11 @@ class ASH_EXPORT MouseCursorEventFilter : public ui::EventHandler {
gfx::Rect src_indicator_bounds_; gfx::Rect src_indicator_bounds_;
gfx::Rect dst_indicator_bounds_; gfx::Rect dst_indicator_bounds_;
gfx::Rect src_edge_bounds_in_native_;
gfx::Rect dst_edge_bounds_in_native_;
// The root window in which the dragging started. // The root window in which the dragging started.
const aura::Window* drag_source_root_; aura::Window* drag_source_root_;
float scale_when_drag_started_; float scale_when_drag_started_;
......
...@@ -28,7 +28,7 @@ class MouseCursorEventFilterTest : public test::AshTestBase { ...@@ -28,7 +28,7 @@ class MouseCursorEventFilterTest : public test::AshTestBase {
bool WarpMouseCursorIfNecessary(aura::Window* target_root, bool WarpMouseCursorIfNecessary(aura::Window* target_root,
gfx::Point point_in_screen) { gfx::Point point_in_screen) {
bool is_warped = event_filter()->WarpMouseCursorIfNecessary( bool is_warped = event_filter()->WarpMouseCursorIfNecessaryForTest(
target_root, point_in_screen); target_root, point_in_screen);
event_filter()->reset_was_mouse_warped_for_test(); event_filter()->reset_was_mouse_warped_for_test();
return is_warped; return is_warped;
...@@ -43,7 +43,7 @@ class MouseCursorEventFilterTest : public test::AshTestBase { ...@@ -43,7 +43,7 @@ class MouseCursorEventFilterTest : public test::AshTestBase {
location, 0, 0); location, 0, 0);
ui::Event::DispatcherApi(&pressed).set_target(drag_source_root); ui::Event::DispatcherApi(&pressed).set_target(drag_source_root);
event_filter()->OnMouseEvent(&pressed); event_filter()->OnMouseEvent(&pressed);
bool is_warped = event_filter()->WarpMouseCursorIfNecessary( bool is_warped = event_filter()->WarpMouseCursorIfNecessaryForTest(
target_root, point_in_screen); target_root, point_in_screen);
event_filter()->reset_was_mouse_warped_for_test(); event_filter()->reset_was_mouse_warped_for_test();
...@@ -127,16 +127,19 @@ TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentSizeDisplays) { ...@@ -127,16 +127,19 @@ TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentSizeDisplays) {
aura::Env::GetInstance()->last_mouse_location().ToString()); aura::Env::GetInstance()->last_mouse_location().ToString());
// Touch the left edge of the secondary root window. Pointer should warp // Touch the left edge of the secondary root window. Pointer should warp
// because 1px left of (0, 499) is inside the primary root window. // because 1px left of (0, 480) is inside the primary root window.
EXPECT_TRUE(WarpMouseCursorIfNecessary(root_windows[1], EXPECT_TRUE(
gfx::Point(500, 499))); WarpMouseCursorIfNecessary(root_windows[1], gfx::Point(500, 480)));
EXPECT_EQ("498,499", // by 2px. EXPECT_EQ("498,480", // by 2px.
aura::Env::GetInstance()->last_mouse_location().ToString()); aura::Env::GetInstance()->last_mouse_location().ToString());
} }
// Verifies if the mouse pointer correctly moves between displays with // Verifies if the mouse pointer correctly moves between displays with
// different scale factors. // different scale factors.
TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplays) { TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplays) {
if (MouseCursorEventFilter::IsMouseWarpInNativeCoordsEnabled())
return;
if (!SupportsMultipleDisplays()) if (!SupportsMultipleDisplays())
return; return;
...@@ -179,7 +182,46 @@ TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplays) { ...@@ -179,7 +182,46 @@ TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplays) {
aura::Env::GetInstance()->last_mouse_location().ToString()); aura::Env::GetInstance()->last_mouse_location().ToString());
} }
// Verifies if the mouse pointer correctly moves between displays with
// different scale factors. In native coords mode, there is no
// difference between drag and move.
TEST_F(MouseCursorEventFilterTest, WarpMouseDifferentScaleDisplaysInNative) {
if (!MouseCursorEventFilter::IsMouseWarpInNativeCoordsEnabled())
return;
if (!SupportsMultipleDisplays())
return;
UpdateDisplay("500x500,600x600*2");
ASSERT_EQ(DisplayLayout::RIGHT,
Shell::GetInstance()
->display_manager()
->GetCurrentDisplayLayout()
.position);
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(900, 123));
EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest(
root_windows[0], gfx::Point(499, 123)));
EXPECT_EQ("500,123",
aura::Env::GetInstance()->last_mouse_location().ToString());
event_filter()->reset_was_mouse_warped_for_test();
// Touch the edge of 2nd display again and make sure it warps to
// 1st dislay.
EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest(
root_windows[1], gfx::Point(500, 123)));
EXPECT_EQ("498,123",
aura::Env::GetInstance()->last_mouse_location().ToString());
}
TEST_F(MouseCursorEventFilterTest, DoNotWarpTwice) { TEST_F(MouseCursorEventFilterTest, DoNotWarpTwice) {
if (MouseCursorEventFilter::IsMouseWarpInNativeCoordsEnabled())
return;
if (!SupportsMultipleDisplays()) if (!SupportsMultipleDisplays())
return; return;
...@@ -189,20 +231,20 @@ TEST_F(MouseCursorEventFilterTest, DoNotWarpTwice) { ...@@ -189,20 +231,20 @@ TEST_F(MouseCursorEventFilterTest, DoNotWarpTwice) {
aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(623, 123)); aura::Env::GetInstance()->set_last_mouse_location(gfx::Point(623, 123));
// Touch the right edge of the primary root window. Pointer should warp. // Touch the right edge of the primary root window. Pointer should warp.
EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessary(root_windows[0], EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest(
gfx::Point(499, 11))); root_windows[0], gfx::Point(499, 11)));
EXPECT_EQ("501,11", // by 2px. EXPECT_EQ("501,11", // by 2px.
aura::Env::GetInstance()->last_mouse_location().ToString()); aura::Env::GetInstance()->last_mouse_location().ToString());
// Touch the left edge of the secondary root window immediately. This should // Touch the left edge of the secondary root window immediately. This should
// be ignored. // be ignored.
EXPECT_FALSE(event_filter()->WarpMouseCursorIfNecessary(root_windows[1], EXPECT_FALSE(event_filter()->WarpMouseCursorIfNecessaryForTest(
gfx::Point(500, 11))); root_windows[1], gfx::Point(500, 11)));
// Touch the left edge of the secondary root window again, pointer should // Touch the left edge of the secondary root window again, pointer should
// warp for this time. // warp for this time.
EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessary(root_windows[1], EXPECT_TRUE(event_filter()->WarpMouseCursorIfNecessaryForTest(
gfx::Point(500, 11))); root_windows[1], gfx::Point(500, 11)));
EXPECT_EQ("498,11", // by 2px. EXPECT_EQ("498,11", // by 2px.
aura::Env::GetInstance()->last_mouse_location().ToString()); aura::Env::GetInstance()->last_mouse_location().ToString());
} }
......
...@@ -47,6 +47,10 @@ void AshRemoteWindowTreeHostWin::SetRootWindowTransformer( ...@@ -47,6 +47,10 @@ void AshRemoteWindowTreeHostWin::SetRootWindowTransformer(
transformer_helper_.SetRootWindowTransformer(transformer.Pass()); transformer_helper_.SetRootWindowTransformer(transformer.Pass());
} }
gfx::Insets AshRemoteWindowTreeHostWin::GetHostInsets() const {
return gfx::Insets();
}
aura::WindowTreeHost* AshRemoteWindowTreeHostWin::AsWindowTreeHost() { aura::WindowTreeHost* AshRemoteWindowTreeHostWin::AsWindowTreeHost() {
return this; return this;
} }
......
...@@ -35,6 +35,7 @@ class ASH_EXPORT AshRemoteWindowTreeHostWin ...@@ -35,6 +35,7 @@ class ASH_EXPORT AshRemoteWindowTreeHostWin
virtual void UnConfineCursor() OVERRIDE; virtual void UnConfineCursor() OVERRIDE;
virtual void SetRootWindowTransformer( virtual void SetRootWindowTransformer(
scoped_ptr<RootWindowTransformer> transformer) OVERRIDE; scoped_ptr<RootWindowTransformer> transformer) OVERRIDE;
virtual gfx::Insets GetHostInsets() const OVERRIDE;
virtual aura::WindowTreeHost* AsWindowTreeHost() OVERRIDE; virtual aura::WindowTreeHost* AsWindowTreeHost() OVERRIDE;
// WindowTreeHostWin: // WindowTreeHostWin:
......
...@@ -14,6 +14,7 @@ class WindowTreeHost; ...@@ -14,6 +14,7 @@ class WindowTreeHost;
} }
namespace gfx { namespace gfx {
class Insets;
class Rect; class Rect;
} }
...@@ -41,6 +42,8 @@ class ASH_EXPORT AshWindowTreeHost { ...@@ -41,6 +42,8 @@ class ASH_EXPORT AshWindowTreeHost {
virtual void SetRootWindowTransformer( virtual void SetRootWindowTransformer(
scoped_ptr<RootWindowTransformer> transformer) = 0; scoped_ptr<RootWindowTransformer> transformer) = 0;
virtual gfx::Insets GetHostInsets() const = 0;
virtual aura::WindowTreeHost* AsWindowTreeHost() = 0; virtual aura::WindowTreeHost* AsWindowTreeHost() = 0;
}; };
......
...@@ -71,6 +71,9 @@ class ASH_EXPORT AshWindowTreeHostWin : public AshWindowTreeHost, ...@@ -71,6 +71,9 @@ class ASH_EXPORT AshWindowTreeHostWin : public AshWindowTreeHost,
scoped_ptr<RootWindowTransformer> transformer) { scoped_ptr<RootWindowTransformer> transformer) {
transformer_helper_.SetRootWindowTransformer(transformer.Pass()); transformer_helper_.SetRootWindowTransformer(transformer.Pass());
} }
virtual gfx::Insets GetHostInsets() const OVERRIDE {
return transformer_helper_.GetHostInsets();
}
virtual aura::WindowTreeHost* AsWindowTreeHost() OVERRIDE { return this; } virtual aura::WindowTreeHost* AsWindowTreeHost() OVERRIDE { return this; }
// WindowTreeHostWin: // WindowTreeHostWin:
......
...@@ -254,6 +254,10 @@ void AshWindowTreeHostX11::SetRootWindowTransformer( ...@@ -254,6 +254,10 @@ void AshWindowTreeHostX11::SetRootWindowTransformer(
} }
} }
gfx::Insets AshWindowTreeHostX11::GetHostInsets() const {
return transformer_helper_.GetHostInsets();
}
aura::WindowTreeHost* AshWindowTreeHostX11::AsWindowTreeHost() { return this; } aura::WindowTreeHost* AshWindowTreeHostX11::AsWindowTreeHost() { return this; }
void AshWindowTreeHostX11::SetBounds(const gfx::Rect& bounds) { void AshWindowTreeHostX11::SetBounds(const gfx::Rect& bounds) {
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
namespace ash { namespace ash {
class RootWindowTransformer; class RootWindowTransformer;
class MouseCursorEventFilter;
class ASH_EXPORT AshWindowTreeHostX11 : public AshWindowTreeHost, class ASH_EXPORT AshWindowTreeHostX11 : public AshWindowTreeHost,
public aura::WindowTreeHostX11, public aura::WindowTreeHostX11,
...@@ -29,6 +30,7 @@ class ASH_EXPORT AshWindowTreeHostX11 : public AshWindowTreeHost, ...@@ -29,6 +30,7 @@ class ASH_EXPORT AshWindowTreeHostX11 : public AshWindowTreeHost,
virtual void UnConfineCursor() OVERRIDE; virtual void UnConfineCursor() OVERRIDE;
virtual void SetRootWindowTransformer( virtual void SetRootWindowTransformer(
scoped_ptr<RootWindowTransformer> transformer) OVERRIDE; scoped_ptr<RootWindowTransformer> transformer) OVERRIDE;
virtual gfx::Insets GetHostInsets() const OVERRIDE;
virtual aura::WindowTreeHost* AsWindowTreeHost() OVERRIDE; virtual aura::WindowTreeHost* AsWindowTreeHost() OVERRIDE;
// aura::WindowTreehost: // aura::WindowTreehost:
......
...@@ -663,8 +663,7 @@ Shell::~Shell() { ...@@ -663,8 +663,7 @@ Shell::~Shell() {
RemovePostTargetHandler(toplevel_window_event_handler_.get()); RemovePostTargetHandler(toplevel_window_event_handler_.get());
RemovePreTargetHandler(system_gesture_filter_.get()); RemovePreTargetHandler(system_gesture_filter_.get());
RemovePreTargetHandler(keyboard_metrics_filter_.get()); RemovePreTargetHandler(keyboard_metrics_filter_.get());
if (mouse_cursor_filter_) RemovePreTargetHandler(mouse_cursor_filter_.get());
RemovePreTargetHandler(mouse_cursor_filter_.get());
// TooltipController is deleted with the Shell so removing its references. // TooltipController is deleted with the Shell so removing its references.
RemovePreTargetHandler(tooltip_controller_.get()); RemovePreTargetHandler(tooltip_controller_.get());
...@@ -755,6 +754,7 @@ Shell::~Shell() { ...@@ -755,6 +754,7 @@ Shell::~Shell() {
resolution_notification_controller_.reset(); resolution_notification_controller_.reset();
#endif #endif
desktop_background_controller_.reset(); desktop_background_controller_.reset();
mouse_cursor_filter_.reset();
// This also deletes all RootWindows. Note that we invoke Shutdown() on // This also deletes all RootWindows. Note that we invoke Shutdown() on
// DisplayController before resetting |display_controller_|, since destruction // DisplayController before resetting |display_controller_|, since destruction
......
...@@ -31,7 +31,7 @@ aura::Window* GetRootWindowMatching(const gfx::Rect& rect) { ...@@ -31,7 +31,7 @@ aura::Window* GetRootWindowMatching(const gfx::Rect& rect) {
GetRootWindowForDisplayId(display.id()); GetRootWindowForDisplayId(display.id());
} }
void ConvertPointToScreen(aura::Window* window, gfx::Point* point) { void ConvertPointToScreen(const aura::Window* window, gfx::Point* point) {
CHECK(window); CHECK(window);
CHECK(window->GetRootWindow()); CHECK(window->GetRootWindow());
CHECK(aura::client::GetScreenPositionClient(window->GetRootWindow())); CHECK(aura::client::GetScreenPositionClient(window->GetRootWindow()));
...@@ -39,7 +39,7 @@ void ConvertPointToScreen(aura::Window* window, gfx::Point* point) { ...@@ -39,7 +39,7 @@ void ConvertPointToScreen(aura::Window* window, gfx::Point* point) {
ConvertPointToScreen(window, point); ConvertPointToScreen(window, point);
} }
void ConvertPointFromScreen(aura::Window* window, void ConvertPointFromScreen(const aura::Window* window,
gfx::Point* point_in_screen) { gfx::Point* point_in_screen) {
aura::client::GetScreenPositionClient(window->GetRootWindow())-> aura::client::GetScreenPositionClient(window->GetRootWindow())->
ConvertPointFromScreen(window, point_in_screen); ConvertPointFromScreen(window, point_in_screen);
......
...@@ -30,11 +30,12 @@ ASH_EXPORT aura::Window* GetRootWindowMatching(const gfx::Rect& rect); ...@@ -30,11 +30,12 @@ ASH_EXPORT aura::Window* GetRootWindowMatching(const gfx::Rect& rect);
// Converts the |point| from a given |window|'s coordinates into the screen // Converts the |point| from a given |window|'s coordinates into the screen
// coordinates. // coordinates.
ASH_EXPORT void ConvertPointToScreen(aura::Window* window, gfx::Point* point); ASH_EXPORT void ConvertPointToScreen(const aura::Window* window,
gfx::Point* point);
// Converts the |point| from the screen coordinates to a given |window|'s // Converts the |point| from the screen coordinates to a given |window|'s
// coordinates. // coordinates.
ASH_EXPORT void ConvertPointFromScreen(aura::Window* window, ASH_EXPORT void ConvertPointFromScreen(const aura::Window* window,
gfx::Point* point_in_screen); gfx::Point* point_in_screen);
} // namespace wm } // namespace wm
......
...@@ -125,8 +125,8 @@ class DragWindowResizerTest : public test::AshTestBase { ...@@ -125,8 +125,8 @@ class DragWindowResizerTest : public test::AshTestBase {
const gfx::Point& point_in_screen) { const gfx::Point& point_in_screen) {
MouseCursorEventFilter* event_filter = MouseCursorEventFilter* event_filter =
Shell::GetInstance()->mouse_cursor_filter(); Shell::GetInstance()->mouse_cursor_filter();
bool is_warped = event_filter->WarpMouseCursorIfNecessary(target_root, bool is_warped = event_filter->WarpMouseCursorIfNecessaryForTest(
point_in_screen); target_root, point_in_screen);
event_filter->reset_was_mouse_warped_for_test(); event_filter->reset_was_mouse_warped_for_test();
return is_warped; return is_warped;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ash/wm/immersive_fullscreen_controller.h" #include "ash/wm/immersive_fullscreen_controller.h"
#include "ash/display/display_manager.h" #include "ash/display/display_manager.h"
#include "ash/display/mouse_cursor_event_filter.h"
#include "ash/root_window_controller.h" #include "ash/root_window_controller.h"
#include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_types.h" #include "ash/shelf/shelf_types.h"
...@@ -540,8 +541,12 @@ TEST_F(ImmersiveFullscreenControllerTest, MouseEventsVerticalDisplayLayout) { ...@@ -540,8 +541,12 @@ TEST_F(ImmersiveFullscreenControllerTest, MouseEventsVerticalDisplayLayout) {
// edge even though the mouse is warped to the secondary display. // edge even though the mouse is warped to the secondary display.
event_generator.MoveMouseTo(x, y_top_edge); event_generator.MoveMouseTo(x, y_top_edge);
EXPECT_TRUE(top_edge_hover_timer_running()); EXPECT_TRUE(top_edge_hover_timer_running());
EXPECT_NE(y_top_edge,
aura::Env::GetInstance()->last_mouse_location().y()); // TODO(oshima): Provide a test API to handle mouse warp more easily.
if (!MouseCursorEventFilter::IsMouseWarpInNativeCoordsEnabled()) {
EXPECT_NE(y_top_edge,
aura::Env::GetInstance()->last_mouse_location().y());
}
// The timer should continue running if the user overshoots the top edge // The timer should continue running if the user overshoots the top edge
// a bit. // a bit.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment