UnifiedDesktop: mouse warp support
[chromium-blink-merge.git] / ash / display / unified_mouse_warp_controller.cc
blob468d4f0e118afc46524695a373c20b424ef55ab5
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/display/unified_mouse_warp_controller.h"
7 #include <cmath>
9 #include "ash/display/display_controller.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/display/display_util.h"
12 #include "ash/display/mirror_window_controller.h"
13 #include "ash/host/ash_window_tree_host.h"
14 #include "ash/shell.h"
15 #include "ui/aura/window.h"
16 #include "ui/aura/window_tree_host.h"
17 #include "ui/base/layout.h"
18 #include "ui/events/event_utils.h"
19 #include "ui/gfx/screen.h"
20 #include "ui/wm/core/coordinate_conversion.h"
22 namespace ash {
24 namespace {
26 AshWindowTreeHost* GetMirroringAshWindowTreeHostForDisplayId(int64 display_id) {
27 return Shell::GetInstance()
28 ->display_controller()
29 ->mirror_window_controller()
30 ->GetAshWindowTreeHostForDisplayId(display_id);
33 // Find a WindowTreeHost used for mirroring displays that contains
34 // the |point_in_screen|. Returns nullptr if such WTH does not exist.
35 aura::WindowTreeHost* FindMirroringWindowTreeHostFromScreenPoint(
36 const gfx::Point& point_in_screen) {
37 DisplayManager::DisplayList mirroring_display_list =
38 Shell::GetInstance()
39 ->display_manager()
40 ->software_mirroring_display_list();
41 int index =
42 FindDisplayIndexContainingPoint(mirroring_display_list, point_in_screen);
43 if (index < 0)
44 return nullptr;
45 return GetMirroringAshWindowTreeHostForDisplayId(
46 mirroring_display_list[index].id())->AsWindowTreeHost();
49 } // namespace
51 UnifiedMouseWarpController::UnifiedMouseWarpController()
52 : allow_non_native_event_(false) {
55 UnifiedMouseWarpController::~UnifiedMouseWarpController() {
58 bool UnifiedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) {
59 // Mirroring windows are created asynchronously, so compute the edge
60 // beounds when we received an event instead of in constructor.
61 if (first_edge_bounds_in_native_.IsEmpty())
62 ComputeBounds();
64 aura::Window* target = static_cast<aura::Window*>(event->target());
65 gfx::Point point_in_screen = event->location();
66 ::wm::ConvertPointToScreen(target, &point_in_screen);
68 // A native event may not exist in unit test. Generate the native point
69 // from the screen point instead.
70 if (!event->HasNativeEvent()) {
71 if (!allow_non_native_event_)
72 return false;
73 aura::Window* target_root = target->GetRootWindow();
74 gfx::Point point_in_native = point_in_screen;
75 ::wm::ConvertPointFromScreen(target_root, &point_in_native);
76 aura::WindowTreeHost* host =
77 FindMirroringWindowTreeHostFromScreenPoint(point_in_screen);
78 DCHECK(host);
79 host->ConvertPointToNativeScreen(&point_in_native);
80 return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen,
81 true);
84 gfx::Point point_in_native =
85 ui::EventSystemLocationFromNative(event->native_event());
87 #if defined(USE_OZONE)
88 // TODO(dnicoara): crbug.com/415680 Move cursor warping into Ozone once Ozone
89 // has access to the logical display layout.
90 // Native events in Ozone are in the native window coordinate system. We need
91 // to translate them to get the global position.
92 aura::WindowTreeHost* host =
93 FindMirroringWindowTreeHostFromScreenPoint(point_in_screen);
94 if (!host)
95 return false;
96 point_in_native.Offset(host->GetBounds().x(), host->GetBounds().y());
97 #endif
99 return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, false);
102 void UnifiedMouseWarpController::SetEnabled(bool enabled) {
103 // Mouse warp shuld be always on in Unified mode.
106 void UnifiedMouseWarpController::ComputeBounds() {
107 DisplayManager::DisplayList display_list =
108 Shell::GetInstance()
109 ->display_manager()
110 ->software_mirroring_display_list();
112 if (display_list.size() < 2) {
113 LOG(ERROR) << "Mirroring Display lost during re-configuration";
114 return;
116 LOG_IF(ERROR, display_list.size() > 2) << "Only two displays are supported";
118 const gfx::Display& first = display_list[0];
119 const gfx::Display& second = display_list[1];
120 ComputeBoundary(first, second, DisplayLayout::RIGHT,
121 &first_edge_bounds_in_native_,
122 &second_edge_bounds_in_native_);
124 first_edge_bounds_in_native_ =
125 GetNativeEdgeBounds(GetMirroringAshWindowTreeHostForDisplayId(first.id()),
126 first_edge_bounds_in_native_);
128 second_edge_bounds_in_native_ = GetNativeEdgeBounds(
129 GetMirroringAshWindowTreeHostForDisplayId(second.id()),
130 second_edge_bounds_in_native_);
133 bool UnifiedMouseWarpController::WarpMouseCursorInNativeCoords(
134 const gfx::Point& point_in_native,
135 const gfx::Point& point_in_screen,
136 bool update_mouse_location_now) {
137 bool in_first_edge = first_edge_bounds_in_native_.Contains(point_in_native);
138 bool in_second_edge = second_edge_bounds_in_native_.Contains(point_in_native);
139 if (!in_first_edge && !in_second_edge)
140 return false;
141 DisplayManager::DisplayList display_list =
142 Shell::GetInstance()
143 ->display_manager()
144 ->software_mirroring_display_list();
145 AshWindowTreeHost* target_ash_host =
146 GetMirroringAshWindowTreeHostForDisplayId(
147 in_first_edge ? display_list[1].id() : display_list[0].id());
148 MoveCursorTo(target_ash_host, point_in_screen, update_mouse_location_now);
149 return true;
152 } // namespace ash