Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / ash / display / unified_mouse_warp_controller.cc
blob7ee731485741f240b3300c4ba87d0d91d9421c38
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_manager.h"
10 #include "ash/display/display_util.h"
11 #include "ash/display/mirror_window_controller.h"
12 #include "ash/display/window_tree_host_manager.h"
13 #include "ash/host/ash_window_tree_host.h"
14 #include "ash/shell.h"
15 #include "ui/aura/client/cursor_client.h"
16 #include "ui/aura/window.h"
17 #include "ui/aura/window_tree_host.h"
18 #include "ui/base/layout.h"
19 #include "ui/events/event_utils.h"
20 #include "ui/gfx/screen.h"
21 #include "ui/wm/core/coordinate_conversion.h"
23 namespace ash {
25 namespace {
27 AshWindowTreeHost* GetMirroringAshWindowTreeHostForDisplayId(int64 display_id) {
28 return Shell::GetInstance()
29 ->window_tree_host_manager()
30 ->mirror_window_controller()
31 ->GetAshWindowTreeHostForDisplayId(display_id);
34 // Find a WindowTreeHost used for mirroring displays that contains
35 // the |point_in_screen|. Returns nullptr if such WTH does not exist.
36 aura::WindowTreeHost* FindMirroringWindowTreeHostFromScreenPoint(
37 const gfx::Point& point_in_screen) {
38 DisplayManager::DisplayList mirroring_display_list =
39 Shell::GetInstance()
40 ->display_manager()
41 ->software_mirroring_display_list();
42 int index =
43 FindDisplayIndexContainingPoint(mirroring_display_list, point_in_screen);
44 if (index < 0)
45 return nullptr;
46 return GetMirroringAshWindowTreeHostForDisplayId(
47 mirroring_display_list[index].id())->AsWindowTreeHost();
50 } // namespace
52 UnifiedMouseWarpController::UnifiedMouseWarpController()
53 : current_cursor_display_id_(gfx::Display::kInvalidDisplayID),
54 allow_non_native_event_(false) {}
56 UnifiedMouseWarpController::~UnifiedMouseWarpController() {
59 bool UnifiedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) {
60 // Mirroring windows are created asynchronously, so compute the edge
61 // beounds when we received an event instead of in constructor.
62 if (first_edge_bounds_in_native_.IsEmpty())
63 ComputeBounds();
65 aura::Window* target = static_cast<aura::Window*>(event->target());
66 gfx::Point point_in_unified_host = event->location();
67 ::wm::ConvertPointToScreen(target, &point_in_unified_host);
68 // The display bounds of the mirroring windows isn't scaled, so
69 // transform back to the host coordinates.
70 target->GetHost()->GetRootTransform().TransformPoint(&point_in_unified_host);
72 if (current_cursor_display_id_ != gfx::Display::kInvalidDisplayID) {
73 aura::client::CursorClient* cursor_client =
74 aura::client::GetCursorClient(target->GetRootWindow());
75 if (cursor_client) {
76 DisplayManager::DisplayList mirroring_display_list =
77 Shell::GetInstance()
78 ->display_manager()
79 ->software_mirroring_display_list();
80 int index = FindDisplayIndexContainingPoint(mirroring_display_list,
81 point_in_unified_host);
82 if (index >= 0) {
83 const gfx::Display& new_display = mirroring_display_list[index];
84 if (current_cursor_display_id_ != new_display.id()) {
85 cursor_client->SetDisplay(new_display);
86 current_cursor_display_id_ = gfx::Display::kInvalidDisplayID;
92 // A native event may not exist in unit test. Generate the native point
93 // from the screen point instead.
94 if (!event->HasNativeEvent()) {
95 if (!allow_non_native_event_)
96 return false;
97 gfx::Point point_in_native = point_in_unified_host;
98 aura::WindowTreeHost* host =
99 FindMirroringWindowTreeHostFromScreenPoint(point_in_unified_host);
100 DCHECK(host);
101 host->ConvertPointToNativeScreen(&point_in_native);
102 return WarpMouseCursorInNativeCoords(point_in_native, point_in_unified_host,
103 true);
106 gfx::Point point_in_native =
107 ui::EventSystemLocationFromNative(event->native_event());
109 #if defined(USE_OZONE)
110 // TODO(dnicoara): crbug.com/415680 Move cursor warping into Ozone once Ozone
111 // has access to the logical display layout.
112 // Native events in Ozone are in the native window coordinate system. We need
113 // to translate them to get the global position.
114 aura::WindowTreeHost* host =
115 FindMirroringWindowTreeHostFromScreenPoint(point_in_unified_host);
116 if (!host)
117 return false;
118 point_in_native.Offset(host->GetBounds().x(), host->GetBounds().y());
119 #endif
121 return WarpMouseCursorInNativeCoords(point_in_native, point_in_unified_host,
122 false);
125 void UnifiedMouseWarpController::SetEnabled(bool enabled) {
126 // Mouse warp shuld be always on in Unified mode.
129 void UnifiedMouseWarpController::ComputeBounds() {
130 DisplayManager::DisplayList display_list =
131 Shell::GetInstance()
132 ->display_manager()
133 ->software_mirroring_display_list();
135 if (display_list.size() < 2) {
136 LOG(ERROR) << "Mirroring Display lost during re-configuration";
137 return;
139 LOG_IF(ERROR, display_list.size() > 2) << "Only two displays are supported";
141 const gfx::Display& first = display_list[0];
142 const gfx::Display& second = display_list[1];
143 ComputeBoundary(first, second, DisplayLayout::RIGHT,
144 &first_edge_bounds_in_native_,
145 &second_edge_bounds_in_native_);
147 first_edge_bounds_in_native_ =
148 GetNativeEdgeBounds(GetMirroringAshWindowTreeHostForDisplayId(first.id()),
149 first_edge_bounds_in_native_);
151 second_edge_bounds_in_native_ = GetNativeEdgeBounds(
152 GetMirroringAshWindowTreeHostForDisplayId(second.id()),
153 second_edge_bounds_in_native_);
156 bool UnifiedMouseWarpController::WarpMouseCursorInNativeCoords(
157 const gfx::Point& point_in_native,
158 const gfx::Point& point_in_unified_host,
159 bool update_mouse_location_now) {
160 bool in_first_edge = first_edge_bounds_in_native_.Contains(point_in_native);
161 bool in_second_edge = second_edge_bounds_in_native_.Contains(point_in_native);
162 if (!in_first_edge && !in_second_edge)
163 return false;
164 DisplayManager::DisplayList display_list =
165 Shell::GetInstance()
166 ->display_manager()
167 ->software_mirroring_display_list();
168 // Wait updating the cursor until the cursor moves to the new display
169 // to avoid showing the wrong sized cursor at the source display.
170 current_cursor_display_id_ =
171 in_first_edge ? display_list[0].id() : display_list[1].id();
172 AshWindowTreeHost* target_ash_host =
173 GetMirroringAshWindowTreeHostForDisplayId(
174 in_first_edge ? display_list[1].id() : display_list[0].id());
175 MoveCursorTo(target_ash_host, point_in_unified_host,
176 update_mouse_location_now);
177 return true;
180 } // namespace ash