OLD | NEW |
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 } else { |
| 91 DisplayLayout::Position position = |
| 92 display_manager->GetCurrentDisplayLayout().position; |
| 93 const gfx::Display& a = display_manager->GetDisplayAt(0); |
| 94 const gfx::Display& b = display_manager->GetDisplayAt(1); |
| 95 |
| 96 // TODO(oshima): Use ComputeBondary instead. |
| 97 if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) |
| 98 AddWarpRegion(CreateHorizontalEdgeBounds(a, b, position), |
| 99 drag_source != nullptr); |
| 100 else |
| 101 AddWarpRegion(CreateVerticalEdgeBounds(a, b, position), |
| 102 drag_source != nullptr); |
54 } | 103 } |
55 } | 104 } |
56 | 105 |
57 ExtendedMouseWarpController::~ExtendedMouseWarpController() { | 106 ExtendedMouseWarpController::~ExtendedMouseWarpController() { |
58 } | 107 } |
59 | 108 |
60 bool ExtendedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) { | 109 bool ExtendedMouseWarpController::WarpMouseCursor(ui::MouseEvent* event) { |
61 if (Shell::GetScreen()->GetNumDisplays() <= 1 || !enabled_) | 110 if (Shell::GetScreen()->GetNumDisplays() <= 1 || !enabled_) |
62 return false; | 111 return false; |
63 | 112 |
(...skipping 26 matching lines...) Expand all Loading... |
90 target->GetHost()->GetBounds().y()); | 139 target->GetHost()->GetBounds().y()); |
91 #endif | 140 #endif |
92 | 141 |
93 return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, false); | 142 return WarpMouseCursorInNativeCoords(point_in_native, point_in_screen, false); |
94 } | 143 } |
95 | 144 |
96 void ExtendedMouseWarpController::SetEnabled(bool enabled) { | 145 void ExtendedMouseWarpController::SetEnabled(bool enabled) { |
97 enabled_ = enabled; | 146 enabled_ = enabled; |
98 } | 147 } |
99 | 148 |
| 149 void ExtendedMouseWarpController::AddWarpRegion( |
| 150 scoped_ptr<WarpRegion> warp_region, |
| 151 bool drag_source) { |
| 152 if (drag_source) { |
| 153 warp_region->shared_display_edge_indicator.reset( |
| 154 new SharedDisplayEdgeIndicator); |
| 155 warp_region->shared_display_edge_indicator->Show( |
| 156 warp_region->a_indicator_bounds, warp_region->b_indicator_bounds); |
| 157 } |
| 158 |
| 159 warp_regions_.emplace_back(std::move(warp_region)); |
| 160 } |
| 161 |
100 bool ExtendedMouseWarpController::WarpMouseCursorInNativeCoords( | 162 bool ExtendedMouseWarpController::WarpMouseCursorInNativeCoords( |
101 const gfx::Point& point_in_native, | 163 const gfx::Point& point_in_native, |
102 const gfx::Point& point_in_screen, | 164 const gfx::Point& point_in_screen, |
103 bool update_mouse_location_now) { | 165 bool update_mouse_location_now) { |
104 bool in_src_edge = src_edge_bounds_in_native_.Contains(point_in_native); | 166 for (const scoped_ptr<WarpRegion>& warp : warp_regions_) { |
105 bool in_dst_edge = dst_edge_bounds_in_native_.Contains(point_in_native); | 167 bool in_a_edge = warp->a_edge_bounds_in_native.Contains(point_in_native); |
106 if (!in_src_edge && !in_dst_edge) | 168 bool in_b_edge = warp->b_edge_bounds_in_native.Contains(point_in_native); |
107 return false; | 169 if (!in_a_edge && !in_b_edge) |
| 170 continue; |
108 | 171 |
109 // The mouse must move. | 172 // The mouse must move. |
110 aura::Window* src_root = nullptr; | 173 aura::Window* dst_window = GetRootWindowForDisplayId( |
111 aura::Window* dst_root = nullptr; | 174 in_a_edge ? warp->b_display_id : warp->a_display_id); |
112 GetSrcAndDstRootWindows(&src_root, &dst_root); | 175 AshWindowTreeHost* target_ash_host = |
113 AshWindowTreeHost* target_ash_host = | 176 GetRootWindowController(dst_window)->ash_host(); |
114 GetRootWindowController(in_src_edge ? dst_root : src_root)->ash_host(); | |
115 | 177 |
116 MoveCursorTo(target_ash_host, point_in_screen, update_mouse_location_now); | 178 MoveCursorTo(target_ash_host, point_in_screen, update_mouse_location_now); |
117 return true; | 179 return true; |
| 180 } |
| 181 |
| 182 return false; |
118 } | 183 } |
119 | 184 |
120 void ExtendedMouseWarpController::UpdateHorizontalEdgeBounds() { | 185 scoped_ptr<ExtendedMouseWarpController::WarpRegion> |
121 bool from_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; | 186 ExtendedMouseWarpController::CreateHorizontalEdgeBounds( |
122 // GetPrimaryDisplay returns an object on stack, so copy the bounds | 187 const gfx::Display& a, |
123 // instead of using reference. | 188 const gfx::Display& b, |
124 const gfx::Rect primary_bounds = | 189 DisplayLayout::Position position) { |
125 Shell::GetScreen()->GetPrimaryDisplay().bounds(); | 190 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 | 191 |
132 src_indicator_bounds_.set_x( | 192 const gfx::Rect& a_bounds = a.bounds(); |
133 std::max(primary_bounds.x(), secondary_bounds.x())); | 193 const gfx::Rect& b_bounds = b.bounds(); |
134 src_indicator_bounds_.set_width( | 194 |
135 std::min(primary_bounds.right(), secondary_bounds.right()) - | 195 gfx::Rect a_indicator_bounds; |
136 src_indicator_bounds_.x()); | 196 a_indicator_bounds.set_x(std::max(a_bounds.x(), b_bounds.x())); |
137 src_indicator_bounds_.set_height(kIndicatorThickness); | 197 a_indicator_bounds.set_width(std::min(a_bounds.right(), b_bounds.right()) - |
138 src_indicator_bounds_.set_y( | 198 a_indicator_bounds.x()); |
| 199 a_indicator_bounds.set_height(kIndicatorThickness); |
| 200 a_indicator_bounds.set_y( |
139 position == DisplayLayout::TOP | 201 position == DisplayLayout::TOP |
140 ? primary_bounds.y() - (from_primary ? 0 : kIndicatorThickness) | 202 ? a_bounds.y() - (from_a ? 0 : kIndicatorThickness) |
141 : primary_bounds.bottom() - (from_primary ? kIndicatorThickness : 0)); | 203 : a_bounds.bottom() - (from_a ? kIndicatorThickness : 0)); |
142 | 204 |
143 dst_indicator_bounds_ = src_indicator_bounds_; | 205 gfx::Rect b_indicator_bounds; |
144 dst_indicator_bounds_.set_height(kIndicatorThickness); | 206 b_indicator_bounds = a_indicator_bounds; |
145 dst_indicator_bounds_.set_y( | 207 b_indicator_bounds.set_height(kIndicatorThickness); |
| 208 b_indicator_bounds.set_y( |
146 position == DisplayLayout::TOP | 209 position == DisplayLayout::TOP |
147 ? primary_bounds.y() - (from_primary ? kIndicatorThickness : 0) | 210 ? a_bounds.y() - (from_a ? kIndicatorThickness : 0) |
148 : primary_bounds.bottom() - (from_primary ? 0 : kIndicatorThickness)); | 211 : a_bounds.bottom() - (from_a ? 0 : kIndicatorThickness)); |
149 | 212 |
150 aura::Window* src_root = nullptr; | 213 return make_scoped_ptr( |
151 aura::Window* dst_root = nullptr; | 214 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 } | 215 } |
159 | 216 |
160 void ExtendedMouseWarpController::UpdateVerticalEdgeBounds() { | 217 scoped_ptr<ExtendedMouseWarpController::WarpRegion> |
| 218 ExtendedMouseWarpController::CreateVerticalEdgeBounds( |
| 219 const gfx::Display& a, |
| 220 const gfx::Display& b, |
| 221 DisplayLayout::Position position) { |
161 int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0; | 222 int snap_height = drag_source_root_ ? kMaximumSnapHeight : 0; |
162 bool in_primary = Shell::GetPrimaryRootWindow() == drag_source_root_; | 223 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 | 224 |
173 int upper_shared_y = std::max(primary_bounds.y(), secondary_bounds.y()); | 225 const gfx::Rect& a_bounds = a.bounds(); |
174 int lower_shared_y = | 226 const gfx::Rect& b_bounds = b.bounds(); |
175 std::min(primary_bounds.bottom(), secondary_bounds.bottom()); | 227 |
| 228 int upper_shared_y = std::max(a_bounds.y(), b_bounds.y()); |
| 229 int lower_shared_y = std::min(a_bounds.bottom(), b_bounds.bottom()); |
176 int shared_height = lower_shared_y - upper_shared_y; | 230 int shared_height = lower_shared_y - upper_shared_y; |
177 | 231 |
178 int dst_x = | 232 gfx::Rect a_indicator_bounds; |
179 position == DisplayLayout::LEFT | 233 gfx::Rect b_indicator_bounds; |
180 ? primary_bounds.x() - (in_primary ? kIndicatorThickness : 0) | 234 |
181 : primary_bounds.right() - (in_primary ? 0 : kIndicatorThickness); | 235 int dst_x = position == DisplayLayout::LEFT |
182 dst_indicator_bounds_.SetRect(dst_x, upper_shared_y, kIndicatorThickness, | 236 ? a_bounds.x() - (in_a ? kIndicatorThickness : 0) |
183 shared_height); | 237 : a_bounds.right() - (in_a ? 0 : kIndicatorThickness); |
| 238 b_indicator_bounds.SetRect(dst_x, upper_shared_y, kIndicatorThickness, |
| 239 shared_height); |
184 | 240 |
185 // The indicator on the source display. | 241 // The indicator on the source display. |
186 src_indicator_bounds_.set_width(kIndicatorThickness); | 242 a_indicator_bounds.set_width(kIndicatorThickness); |
187 src_indicator_bounds_.set_x( | 243 a_indicator_bounds.set_x(position == DisplayLayout::LEFT |
188 position == DisplayLayout::LEFT | 244 ? a_bounds.x() - (in_a ? 0 : kIndicatorThickness) |
189 ? primary_bounds.x() - (in_primary ? 0 : kIndicatorThickness) | 245 : a_bounds.right() - |
190 : primary_bounds.right() - (in_primary ? kIndicatorThickness : 0)); | 246 (in_a ? kIndicatorThickness : 0)); |
191 | 247 |
192 const gfx::Rect& source_bounds = | 248 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; | 249 int upper_indicator_y = source_bounds.y() + snap_height; |
195 int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y); | 250 int lower_indicator_y = std::min(source_bounds.bottom(), lower_shared_y); |
196 | 251 |
197 // This gives a hight that can be used without sacrifying the snap space. | 252 // This gives a hight that can be used without sacrifying the snap space. |
198 int available_space = | 253 int available_space = |
199 lower_indicator_y - std::max(upper_shared_y, upper_indicator_y); | 254 lower_indicator_y - std::max(upper_shared_y, upper_indicator_y); |
200 | 255 |
201 if (shared_height < kMinimumIndicatorHeight) { | 256 if (shared_height < kMinimumIndicatorHeight) { |
202 // If the shared height is smaller than minimum height, use the | 257 // If the shared height is smaller than minimum height, use the |
203 // entire height. | 258 // entire height. |
204 upper_indicator_y = upper_shared_y; | 259 upper_indicator_y = upper_shared_y; |
205 } else if (available_space < kMinimumIndicatorHeight) { | 260 } else if (available_space < kMinimumIndicatorHeight) { |
206 // Snap to the bottom. | 261 // Snap to the bottom. |
207 upper_indicator_y = | 262 upper_indicator_y = |
208 std::max(upper_shared_y, lower_indicator_y + kMinimumIndicatorHeight); | 263 std::max(upper_shared_y, lower_indicator_y + kMinimumIndicatorHeight); |
209 } else { | 264 } else { |
210 upper_indicator_y = std::max(upper_indicator_y, upper_shared_y); | 265 upper_indicator_y = std::max(upper_indicator_y, upper_shared_y); |
211 } | 266 } |
212 src_indicator_bounds_.set_y(upper_indicator_y); | 267 a_indicator_bounds.set_y(upper_indicator_y); |
213 src_indicator_bounds_.set_height(lower_indicator_y - upper_indicator_y); | 268 a_indicator_bounds.set_height(lower_indicator_y - upper_indicator_y); |
214 | 269 |
215 aura::Window* src_root = nullptr; | 270 return make_scoped_ptr( |
216 aura::Window* dst_root = nullptr; | 271 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 } | 272 } |
234 | 273 |
235 } // namespace ash | 274 } // namespace ash |
OLD | NEW |