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

Side by Side Diff: ash/display/extended_mouse_warp_controller.cc

Issue 1601383002: Support moving the cursor and dragging windows to 3+ displays. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Fix windows build warnings, change method placement in cc file, remove/add comments Created 4 years, 11 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ash/display/extended_mouse_warp_controller.h" 5 #include "ash/display/extended_mouse_warp_controller.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "ash/display/display_manager.h" 9 #include "ash/display/display_manager.h"
10 #include "ash/display/display_util.h" 10 #include "ash/display/display_util.h"
11 #include "ash/display/shared_display_edge_indicator.h" 11 #include "ash/display/shared_display_edge_indicator.h"
12 #include "ash/display/window_tree_host_manager.h"
12 #include "ash/root_window_controller.h" 13 #include "ash/root_window_controller.h"
13 #include "ash/screen_util.h" 14 #include "ash/screen_util.h"
14 #include "ash/shell.h" 15 #include "ash/shell.h"
15 #include "ui/aura/window.h" 16 #include "ui/aura/window.h"
16 #include "ui/events/event_utils.h" 17 #include "ui/events/event_utils.h"
17 #include "ui/gfx/screen.h" 18 #include "ui/gfx/screen.h"
18 #include "ui/wm/core/coordinate_conversion.h" 19 #include "ui/wm/core/coordinate_conversion.h"
19 20
20 namespace ash { 21 namespace ash {
21 22
22 namespace { 23 namespace {
23 24
24 // Maximum size on the display edge that initiate snapping phantom window, 25 // Maximum size on the display edge that initiate snapping phantom window,
25 // from the corner of the display. 26 // from the corner of the display.
26 const int kMaximumSnapHeight = 16; 27 const int kMaximumSnapHeight = 16;
27 28
28 // Minimum height of an indicator on the display edge that allows 29 // Minimum height of an indicator on the display edge that allows
29 // dragging a window. If two displays shares the edge smaller than 30 // dragging a window. If two displays shares the edge smaller than
30 // this, entire edge will be used as a draggable space. 31 // this, entire edge will be used as a draggable space.
31 const int kMinimumIndicatorHeight = 200; 32 const int kMinimumIndicatorHeight = 200;
32 33
33 const int kIndicatorThickness = 1; 34 const int kIndicatorThickness = 1;
34 35
36 // Helper method that maps a gfx::Display to an aura::Window.
37 aura::Window* GetRootWindowForDisplayId(int64_t display_id) {
38 return Shell::GetInstance()
39 ->window_tree_host_manager()
40 ->GetRootWindowForDisplayId(display_id);
41 }
42
43 // Helper method that maps an aura::Window to a gfx::Display.
44 gfx::Display GetDisplayFromWindow(aura::Window* window) {
45 return Shell::GetScreen()->GetDisplayNearestWindow(window);
46 }
47
35 } // namespace 48 } // namespace
36 49
50 ExtendedMouseWarpController::WarpRegion::WarpRegion(
51 int64_t a_display_id,
52 int64_t b_display_id,
53 const gfx::Rect& a_indicator_bounds,
54 const gfx::Rect& b_indicator_bounds)
55 : a_display_id(a_display_id),
56 b_display_id(b_display_id),
57 a_indicator_bounds(a_indicator_bounds),
58 b_indicator_bounds(b_indicator_bounds),
59 shared_display_edge_indicator(nullptr) {
60 // Initialize edge bounds from indicator bounds.
61 aura::Window* a_window = GetRootWindowForDisplayId(a_display_id);
62 aura::Window* b_window = GetRootWindowForDisplayId(b_display_id);
63
64 AshWindowTreeHost* a_ash_host = GetRootWindowController(a_window)->ash_host();
65 AshWindowTreeHost* b_ash_host = GetRootWindowController(b_window)->ash_host();
66
67 a_edge_bounds_in_native = GetNativeEdgeBounds(a_ash_host, a_indicator_bounds);
68 b_edge_bounds_in_native = GetNativeEdgeBounds(b_ash_host, b_indicator_bounds);
69 }
70
71 ExtendedMouseWarpController::WarpRegion::~WarpRegion() {}
72
37 ExtendedMouseWarpController::ExtendedMouseWarpController( 73 ExtendedMouseWarpController::ExtendedMouseWarpController(
38 aura::Window* drag_source) 74 aura::Window* drag_source)
39 : drag_source_root_(drag_source), 75 : drag_source_root_(drag_source),
40 shared_display_edge_indicator_(new SharedDisplayEdgeIndicator),
41 allow_non_native_event_(false) { 76 allow_non_native_event_(false) {
42 DisplayLayout::Position position = Shell::GetInstance() 77 ash::DisplayManager* display_manager =
43 ->display_manager() 78 Shell::GetInstance()->display_manager();
44 ->GetCurrentDisplayLayout() 79
45 .position; 80 // For the time being, 3 or more displays are always always laid out
46 // TODO(oshima): Use ComputeBondary instead. 81 // horizontally, with each display being RIGHT of the previous one.
47 if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) 82 if (display_manager->GetNumDisplays() > 2) {
48 UpdateHorizontalEdgeBounds(); 83 for (size_t i = 1; i < display_manager->GetNumDisplays(); ++i) {
49 else 84 const gfx::Display& left = display_manager->GetDisplayAt(i - 1);
50 UpdateVerticalEdgeBounds(); 85 const gfx::Display& right = display_manager->GetDisplayAt(i);
51 if (drag_source) { 86
52 shared_display_edge_indicator_->Show(src_indicator_bounds_, 87 AddWarpRegion(CreateVerticalEdgeBounds(left, right, DisplayLayout::RIGHT),
53 dst_indicator_bounds_); 88 drag_source != nullptr);
89 }
90 }
91
92 else {
oshima 2016/01/20 18:35:55 style nit: } else {
jdufault 2016/01/20 23:37:15 Done.
93 DisplayLayout::Position position =
94 display_manager->GetCurrentDisplayLayout().position;
95 const gfx::Display& a = display_manager->GetDisplayAt(0);
96 const gfx::Display& b = display_manager->GetDisplayAt(1);
97
98 // TODO(oshima): Use ComputeBondary instead.
99 if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM)
100 AddWarpRegion(CreateHorizontalEdgeBounds(a, b, position),
101 drag_source != nullptr);
102 else
103 AddWarpRegion(CreateVerticalEdgeBounds(a, b, position),
104 drag_source != nullptr);
54 } 105 }
55 } 106 }
56 107
57 ExtendedMouseWarpController::~ExtendedMouseWarpController() { 108 ExtendedMouseWarpController::~ExtendedMouseWarpController() {
58 } 109 }
59 110
60 bool ExtendedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) { 111 bool ExtendedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) {
61 if (Shell::GetScreen()->GetNumDisplays() <= 1 || !enabled_) 112 if (Shell::GetScreen()->GetNumDisplays() <= 1 || !enabled_)
62 return false; 113 return false;
63 114
(...skipping 26 matching lines...) Expand all
90 target->GetHost()->GetBounds().y()); 141 target->GetHost()->GetBounds().y());
91 #endif 142 #endif
92 143
93 return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, false); 144 return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, false);
94 } 145 }
95 146
96 void ExtendedMouseWarpController::SetEnabled(bool enabled) { 147 void ExtendedMouseWarpController::SetEnabled(bool enabled) {
97 enabled_ = enabled; 148 enabled_ = enabled;
98 } 149 }
99 150
151 void ExtendedMouseWarpController::AddWarpRegion(
152 scoped_ptr<WarpRegion> warp_region,
153 bool drag_source) {
154 if (drag_source) {
155 warp_region->shared_display_edge_indicator.reset(
156 new SharedDisplayEdgeIndicator);
157 warp_region->shared_display_edge_indicator->Show(
158 warp_region->a_indicator_bounds, warp_region->b_indicator_bounds);
159 }
160
161 warp_regions_.emplace_back(std::move(warp_region));
162 }
163
100 bool ExtendedMouseWarpController::WarpMouseCursorInNativeCoords( 164 bool ExtendedMouseWarpController::WarpMouseCursorInNativeCoords(
101 const gfx::Point& point_in_native, 165 const gfx::Point& point_in_native,
102 const gfx::Point& point_in_screen, 166 const gfx::Point& point_in_screen,
103 bool update_mouse_location_now) { 167 bool update_mouse_location_now) {
104 bool in_src_edge = src_edge_bounds_in_native_.Contains(point_in_native); 168 for (const scoped_ptr<WarpRegion>& warp : warp_regions_) {
105 bool in_dst_edge = dst_edge_bounds_in_native_.Contains(point_in_native); 169 bool in_a_edge = warp->a_edge_bounds_in_native.Contains(point_in_native);
106 if (!in_src_edge && !in_dst_edge) 170 bool in_b_edge = warp->b_edge_bounds_in_native.Contains(point_in_native);
107 return false; 171 if (!in_a_edge && !in_b_edge)
172 continue;
108 173
109 // The mouse must move. 174 // The mouse must move.
110 aura::Window* src_root = nullptr; 175 aura::Window* dst_window = GetRootWindowForDisplayId(
111 aura::Window* dst_root = nullptr; 176 in_a_edge ? warp->b_display_id : warp->a_display_id);
112 GetSrcAndDstRootWindows(&src_root, &dst_root); 177 AshWindowTreeHost* target_ash_host =
113 AshWindowTreeHost* target_ash_host = 178 GetRootWindowController(dst_window)->ash_host();
114 GetRootWindowController(in_src_edge ? dst_root : src_root)->ash_host();
115 179
116 MoveCursorTo(target_ash_host, point_in_screen, update_mouse_location_now); 180 MoveCursorTo(target_ash_host, point_in_screen, update_mouse_location_now);
117 return true; 181 return true;
182 }
183
184 return false;
118 } 185 }
119 186
120 void ExtendedMouseWarpController::UpdateHorizontalEdgeBounds() { 187 scoped_ptr<ExtendedMouseWarpController::WarpRegion>
121 bool from_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; 188 ExtendedMouseWarpController::CreateHorizontalEdgeBounds(
122 // GetPrimaryDisplay returns an object on stack, so copy the bounds 189 const gfx::Display& a,
123 // instead of using reference. 190 const gfx::Display& b,
124 const gfx::Rect primary_bounds = 191 DisplayLayout::Position position) {
125 Shell::GetScreen()->GetPrimaryDisplay().bounds(); 192 bool from_a = a.id() == GetDisplayFromWindow(drag_source_root_).id();
126 const gfx::Rect secondary_bounds = ScreenUtil::GetSecondaryDisplay().bounds();
127 DisplayLayout::Position position = Shell::GetInstance()
128 ->display_manager()
129 ->GetCurrentDisplayLayout()
130 .position;
131 193
132 src_indicator_bounds_.set_x( 194 const gfx::Rect& a_bounds = a.bounds();
133 std::max(primary_bounds.x(), secondary_bounds.x())); 195 const gfx::Rect& b_bounds = b.bounds();
134 src_indicator_bounds_.set_width( 196
135 std::min(primary_bounds.right(), secondary_bounds.right()) - 197 gfx::Rect a_indicator_bounds;
136 src_indicator_bounds_.x()); 198 a_indicator_bounds.set_x(std::max(a_bounds.x(), b_bounds.x()));
137 src_indicator_bounds_.set_height(kIndicatorThickness); 199 a_indicator_bounds.set_width(std::min(a_bounds.right(), b_bounds.right()) -
138 src_indicator_bounds_.set_y( 200 a_indicator_bounds.x());
201 a_indicator_bounds.set_height(kIndicatorThickness);
202 a_indicator_bounds.set_y(
139 position == DisplayLayout::TOP 203 position == DisplayLayout::TOP
140 ? primary_bounds.y() - (from_primary ? 0 : kIndicatorThickness) 204 ? a_bounds.y() - (from_a ? 0 : kIndicatorThickness)
141 : primary_bounds.bottom() - (from_primary ? kIndicatorThickness : 0)); 205 : a_bounds.bottom() - (from_a ? kIndicatorThickness : 0));
142 206
143 dst_indicator_bounds_ = src_indicator_bounds_; 207 gfx::Rect b_indicator_bounds;
144 dst_indicator_bounds_.set_height(kIndicatorThickness); 208 b_indicator_bounds = a_indicator_bounds;
145 dst_indicator_bounds_.set_y( 209 b_indicator_bounds.set_height(kIndicatorThickness);
210 b_indicator_bounds.set_y(
146 position == DisplayLayout::TOP 211 position == DisplayLayout::TOP
147 ? primary_bounds.y() - (from_primary ? kIndicatorThickness : 0) 212 ? a_bounds.y() - (from_a ? kIndicatorThickness : 0)
148 : primary_bounds.bottom() - (from_primary ? 0 : kIndicatorThickness)); 213 : a_bounds.bottom() - (from_a ? 0 : kIndicatorThickness));
149 214
150 aura::Window* src_root = nullptr; 215 return make_scoped_ptr(
151 aura::Window* dst_root = nullptr; 216 new WarpRegion(a.id(), b.id(), a_indicator_bounds, b_indicator_bounds));
152 GetSrcAndDstRootWindows(&src_root, &dst_root);
153
154 src_edge_bounds_in_native_ = GetNativeEdgeBounds(
155 GetRootWindowController(src_root)->ash_host(), src_indicator_bounds_);
156 dst_edge_bounds_in_native_ = GetNativeEdgeBounds(
157 GetRootWindowController(dst_root)->ash_host(), dst_indicator_bounds_);
158 } 217 }
159 218
160 void ExtendedMouseWarpController::UpdateVerticalEdgeBounds() { 219 scoped_ptr<ExtendedMouseWarpController::WarpRegion>
220 ExtendedMouseWarpController::CreateVerticalEdgeBounds(
221 const gfx::Display& a,
222 const gfx::Display& b,
223 DisplayLayout::Position position) {
161 int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0; 224 int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0;
162 bool in_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; 225 bool in_a = a.id() == GetDisplayFromWindow(drag_source_root_).id();
163 // GetPrimaryDisplay returns an object on stack, so copy the bounds
164 // instead of using reference.
165 const gfx::Rect primary_bounds =
166 Shell::GetScreen()->GetPrimaryDisplay().bounds();
167 const gfx::Rect secondary_bounds = ScreenUtil::GetSecondaryDisplay().bounds();
168 DisplayLayout::Position position = Shell::GetInstance()
169 ->display_manager()
170 ->GetCurrentDisplayLayout()
171 .position;
172 226
173 int upper_shared_y = std::max(primary_bounds.y(), secondary_bounds.y()); 227 const gfx::Rect& a_bounds = a.bounds();
174 int lower_shared_y = 228 const gfx::Rect& b_bounds = b.bounds();
175 std::min(primary_bounds.bottom(), secondary_bounds.bottom()); 229
230 int upper_shared_y = std::max(a_bounds.y(), b_bounds.y());
231 int lower_shared_y = std::min(a_bounds.bottom(), b_bounds.bottom());
176 int shared_height = lower_shared_y - upper_shared_y; 232 int shared_height = lower_shared_y - upper_shared_y;
177 233
178 int dst_x = 234 gfx::Rect a_indicator_bounds;
179 position == DisplayLayout::LEFT 235 gfx::Rect b_indicator_bounds;
180 ? primary_bounds.x() - (in_primary ? kIndicatorThickness : 0) 236
181 : primary_bounds.right() - (in_primary ? 0 : kIndicatorThickness); 237 int dst_x = position == DisplayLayout::LEFT
182 dst_indicator_bounds_.SetRect(dst_x, upper_shared_y, kIndicatorThickness, 238 ? a_bounds.x() - (in_a ? kIndicatorThickness : 0)
183 shared_height); 239 : a_bounds.right() - (in_a ? 0 : kIndicatorThickness);
240 b_indicator_bounds.SetRect(dst_x, upper_shared_y, kIndicatorThickness,
241 shared_height);
184 242
185 // The indicator on the source display. 243 // The indicator on the source display.
186 src_indicator_bounds_.set_width(kIndicatorThickness); 244 a_indicator_bounds.set_width(kIndicatorThickness);
187 src_indicator_bounds_.set_x( 245 a_indicator_bounds.set_x(position == DisplayLayout::LEFT
188 position == DisplayLayout::LEFT 246 ? a_bounds.x() - (in_a ? 0 : kIndicatorThickness)
189 ? primary_bounds.x() - (in_primary ? 0 : kIndicatorThickness) 247 : a_bounds.right() -
190 : primary_bounds.right() - (in_primary ? kIndicatorThickness : 0)); 248 (in_a ? kIndicatorThickness : 0));
191 249
192 const gfx::Rect& source_bounds = 250 const gfx::Rect& source_bounds = in_a ? a_bounds : b_bounds;
193 in_primary ? primary_bounds : secondary_bounds;
194 int upper_indicator_y = source_bounds.y() + snap_height; 251 int upper_indicator_y = source_bounds.y() + snap_height;
195 int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y); 252 int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y);
196 253
197 // This gives a hight that can be used without sacrifying the snap space. 254 // This gives a hight that can be used without sacrifying the snap space.
198 int available_space = 255 int available_space =
199 lower_indicator_y - std::max(upper_shared_y, upper_indicator_y); 256 lower_indicator_y - std::max(upper_shared_y, upper_indicator_y);
200 257
201 if (shared_height < kMinimumIndicatorHeight) { 258 if (shared_height < kMinimumIndicatorHeight) {
202 // If the shared height is smaller than minimum height, use the 259 // If the shared height is smaller than minimum height, use the
203 // entire height. 260 // entire height.
204 upper_indicator_y = upper_shared_y; 261 upper_indicator_y = upper_shared_y;
205 } else if (available_space < kMinimumIndicatorHeight) { 262 } else if (available_space < kMinimumIndicatorHeight) {
206 // Snap to the bottom. 263 // Snap to the bottom.
207 upper_indicator_y = 264 upper_indicator_y =
208 std::max(upper_shared_y, lower_indicator_y + kMinimumIndicatorHeight); 265 std::max(upper_shared_y, lower_indicator_y + kMinimumIndicatorHeight);
209 } else { 266 } else {
210 upper_indicator_y = std::max(upper_indicator_y, upper_shared_y); 267 upper_indicator_y = std::max(upper_indicator_y, upper_shared_y);
211 } 268 }
212 src_indicator_bounds_.set_y(upper_indicator_y); 269 a_indicator_bounds.set_y(upper_indicator_y);
213 src_indicator_bounds_.set_height(lower_indicator_y - upper_indicator_y); 270 a_indicator_bounds.set_height(lower_indicator_y - upper_indicator_y);
214 271
215 aura::Window* src_root = nullptr; 272 return make_scoped_ptr(
216 aura::Window* dst_root = nullptr; 273 new WarpRegion(a.id(), b.id(), a_indicator_bounds, b_indicator_bounds));
217 GetSrcAndDstRootWindows(&src_root, &dst_root);
218
219 // Native
220 src_edge_bounds_in_native_ = GetNativeEdgeBounds(
221 GetRootWindowController(src_root)->ash_host(), src_indicator_bounds_);
222 dst_edge_bounds_in_native_ = GetNativeEdgeBounds(
223 GetRootWindowController(dst_root)->ash_host(), dst_indicator_bounds_);
224 }
225
226 void ExtendedMouseWarpController::GetSrcAndDstRootWindows(
227 aura::Window** src_root,
228 aura::Window** dst_root) {
229 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
230 *src_root = drag_source_root_ ? drag_source_root_
231 : Shell::GetInstance()->GetPrimaryRootWindow();
232 *dst_root = root_windows[0] == *src_root ? root_windows[1] : root_windows[0];
233 } 274 }
234 275
235 } // namespace ash 276 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698