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

Side by Side Diff: ash/wm/dock/docked_window_resizer.cc

Issue 23431009: Windows docking should get triggered by pressing against the screen edge (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Windows docking should get triggered by pressing against the screen edge (comments) Created 7 years, 3 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/wm/dock/docked_window_resizer.h" 5 #include "ash/wm/dock/docked_window_resizer.h"
6 6
7 #include "ash/ash_switches.h" 7 #include "ash/ash_switches.h"
8 #include "ash/display/display_controller.h"
8 #include "ash/launcher/launcher.h" 9 #include "ash/launcher/launcher.h"
9 #include "ash/root_window_controller.h" 10 #include "ash/root_window_controller.h"
10 #include "ash/screen_ash.h" 11 #include "ash/screen_ash.h"
11 #include "ash/shelf/shelf_types.h" 12 #include "ash/shelf/shelf_types.h"
12 #include "ash/shelf/shelf_widget.h" 13 #include "ash/shelf/shelf_widget.h"
13 #include "ash/shell.h" 14 #include "ash/shell.h"
14 #include "ash/shell_window_ids.h" 15 #include "ash/shell_window_ids.h"
15 #include "ash/wm/coordinate_conversion.h" 16 #include "ash/wm/coordinate_conversion.h"
16 #include "ash/wm/dock/docked_window_layout_manager.h" 17 #include "ash/wm/dock/docked_window_layout_manager.h"
17 #include "ash/wm/property_util.h" 18 #include "ash/wm/property_util.h"
18 #include "ash/wm/window_properties.h" 19 #include "ash/wm/window_properties.h"
19 #include "ash/wm/workspace/magnetism_matcher.h" 20 #include "ash/wm/workspace/magnetism_matcher.h"
20 #include "ash/wm/workspace/phantom_window_controller.h"
21 #include "ash/wm/workspace/workspace_window_resizer.h" 21 #include "ash/wm/workspace/workspace_window_resizer.h"
22 #include "base/command_line.h" 22 #include "base/command_line.h"
23 #include "ui/aura/client/aura_constants.h" 23 #include "ui/aura/client/aura_constants.h"
24 #include "ui/aura/env.h" 24 #include "ui/aura/env.h"
25 #include "ui/aura/root_window.h" 25 #include "ui/aura/root_window.h"
26 #include "ui/aura/window.h" 26 #include "ui/aura/window.h"
27 #include "ui/aura/window_delegate.h" 27 #include "ui/aura/window_delegate.h"
28 #include "ui/base/hit_test.h" 28 #include "ui/base/hit_test.h"
29 #include "ui/base/ui_base_types.h" 29 #include "ui/base/ui_base_types.h"
30 #include "ui/gfx/screen.h" 30 #include "ui/gfx/screen.h"
31 #include "ui/views/widget/widget.h" 31 #include "ui/views/widget/widget.h"
32 32
33 namespace ash { 33 namespace ash {
34 namespace internal { 34 namespace internal {
35 35
36 namespace { 36 namespace {
37 37
38 DockedWindowLayoutManager* GetDockedLayoutManagerAtPoint( 38 DockedWindowLayoutManager* GetDockedLayoutManagerAtPoint(
39 const gfx::Point& point) { 39 const gfx::Point& point) {
40 gfx::Display display = ScreenAsh::FindDisplayContainingPoint(point);
41 if (!display.is_valid())
42 return NULL;
43 aura::RootWindow* root = Shell::GetInstance()->display_controller()->
44 GetRootWindowForDisplayId(display.id());
40 aura::Window* dock_container = Shell::GetContainer( 45 aura::Window* dock_container = Shell::GetContainer(
41 wm::GetRootWindowAt(point), 46 root, kShellWindowId_DockedContainer);
42 kShellWindowId_DockedContainer);
43 return static_cast<DockedWindowLayoutManager*>( 47 return static_cast<DockedWindowLayoutManager*>(
44 dock_container->layout_manager()); 48 dock_container->layout_manager());
45 } 49 }
46 50
47 } // namespace 51 } // namespace
48 52
49 DockedWindowResizer::~DockedWindowResizer() { 53 DockedWindowResizer::~DockedWindowResizer() {
50 if (destroyed_) 54 if (destroyed_)
51 *destroyed_ = true; 55 *destroyed_ = true;
52 } 56 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 // resizers to avoid the awkward pattern here for checking if 94 // resizers to avoid the awkward pattern here for checking if
91 // next_window_resizer_ destroys the resizer object. 95 // next_window_resizer_ destroys the resizer object.
92 if (destroyed) 96 if (destroyed)
93 return; 97 return;
94 destroyed_ = NULL; 98 destroyed_ = NULL;
95 if (set_tracked_by_workspace) 99 if (set_tracked_by_workspace)
96 SetTrackedByWorkspace(GetTarget(), tracked_by_workspace); 100 SetTrackedByWorkspace(GetTarget(), tracked_by_workspace);
97 101
98 DockedWindowLayoutManager* new_dock_layout = 102 DockedWindowLayoutManager* new_dock_layout =
99 GetDockedLayoutManagerAtPoint(last_location_); 103 GetDockedLayoutManagerAtPoint(last_location_);
100 if (new_dock_layout != dock_layout_) { 104 if (new_dock_layout && new_dock_layout != dock_layout_) {
101 // The window is being dragged to a new display. If the previous 105 // The window is being dragged to a new display. If the previous
102 // container is the current parent of the window it will be informed of 106 // container is the current parent of the window it will be informed of
103 // the end of drag when the window is reparented, otherwise let the 107 // the end of drag when the window is reparented, otherwise let the
104 // previous container know the drag is complete. If we told the 108 // previous container know the drag is complete. If we told the
105 // window's parent that the drag was complete it would begin 109 // window's parent that the drag was complete it would begin
106 // positioning the window. 110 // positioning the window.
107 if (is_docked_) 111 if (is_docked_)
108 dock_layout_->UndockDraggedWindow(); 112 dock_layout_->UndockDraggedWindow();
109 if (dock_layout_ != initial_dock_layout_) 113 if (dock_layout_ != initial_dock_layout_)
110 dock_layout_->FinishDragging(); 114 dock_layout_->FinishDragging();
111 is_docked_ = false; 115 is_docked_ = false;
112 dock_layout_ = new_dock_layout; 116 dock_layout_ = new_dock_layout;
113 // The window's initial layout manager already knows that the drag is 117 // The window's initial layout manager already knows that the drag is
114 // in progress for this window. 118 // in progress for this window.
115 if (new_dock_layout != initial_dock_layout_) 119 if (new_dock_layout != initial_dock_layout_)
116 new_dock_layout->StartDragging(GetTarget()); 120 new_dock_layout->StartDragging(GetTarget());
117 } 121 }
118 122 // Window could get marked as docked by the SnapSizer, so update the state.
119 // Show snapping animation when a window touches a screen edge or when 123 is_docked_ = dock_layout_->is_dragged_window_docked();
120 // it is about to get docked.
121 DockedAlignment new_docked_alignment = GetDraggedWindowAlignment();
122 if (new_docked_alignment != DOCKED_ALIGNMENT_NONE) {
123 if (!is_docked_) {
124 dock_layout_->DockDraggedWindow(GetTarget());
125 is_docked_ = true;
126 }
127 UpdateSnapPhantomWindow();
128 } else {
129 if (is_docked_) {
130 dock_layout_->UndockDraggedWindow();
131 is_docked_ = false;
132 }
133 // Clear phantom window when a window gets undocked.
134 snap_phantom_window_controller_.reset();
135 }
136 } 124 }
137 125
138 void DockedWindowResizer::CompleteDrag(int event_flags) { 126 void DockedWindowResizer::CompleteDrag(int event_flags) {
139 snap_phantom_window_controller_.reset();
140
141 // Temporarily clear kWindowTrackedByWorkspaceKey for panels so that they 127 // Temporarily clear kWindowTrackedByWorkspaceKey for panels so that they
142 // don't get forced into the workspace that may be shrunken because of docked 128 // don't get forced into the workspace that may be shrunken because of docked
143 // windows. 129 // windows.
144 bool tracked_by_workspace = GetTrackedByWorkspace(GetTarget()); 130 bool tracked_by_workspace = GetTrackedByWorkspace(GetTarget());
145 bool set_tracked_by_workspace = was_docked_; 131 bool set_tracked_by_workspace = was_docked_;
146 if (set_tracked_by_workspace) 132 if (set_tracked_by_workspace)
147 SetTrackedByWorkspace(GetTarget(), false); 133 SetTrackedByWorkspace(GetTarget(), false);
148 // The root window can change when dragging into a different screen. 134 // The root window can change when dragging into a different screen.
149 next_window_resizer_->CompleteDrag(event_flags); 135 next_window_resizer_->CompleteDrag(event_flags);
150 FinishedDragging(); 136 FinishedDragging();
151 if (set_tracked_by_workspace) 137 if (set_tracked_by_workspace)
152 SetTrackedByWorkspace(GetTarget(), tracked_by_workspace); 138 SetTrackedByWorkspace(GetTarget(), tracked_by_workspace);
153 } 139 }
154 140
155 void DockedWindowResizer::RevertDrag() { 141 void DockedWindowResizer::RevertDrag() {
156 snap_phantom_window_controller_.reset();
157
158 // Temporarily clear kWindowTrackedByWorkspaceKey for panels so that they 142 // Temporarily clear kWindowTrackedByWorkspaceKey for panels so that they
159 // don't get forced into the workspace that may be shrunken because of docked 143 // don't get forced into the workspace that may be shrunken because of docked
160 // windows. 144 // windows.
161 bool tracked_by_workspace = GetTrackedByWorkspace(GetTarget()); 145 bool tracked_by_workspace = GetTrackedByWorkspace(GetTarget());
162 bool set_tracked_by_workspace = was_docked_; 146 bool set_tracked_by_workspace = was_docked_;
163 if (set_tracked_by_workspace) 147 if (set_tracked_by_workspace)
164 SetTrackedByWorkspace(GetTarget(), false); 148 SetTrackedByWorkspace(GetTarget(), false);
165 next_window_resizer_->RevertDrag(); 149 next_window_resizer_->RevertDrag();
150 // Restore docked state to what it was before the drag if necessary.
151 if (was_docked_ && !is_docked_) {
152 dock_layout_->DockDraggedWindow(GetTarget());
153 is_docked_ = was_docked_;
154 }
166 FinishedDragging(); 155 FinishedDragging();
167 if (set_tracked_by_workspace) 156 if (set_tracked_by_workspace)
168 SetTrackedByWorkspace(GetTarget(), tracked_by_workspace); 157 SetTrackedByWorkspace(GetTarget(), tracked_by_workspace);
169 } 158 }
170 159
171 aura::Window* DockedWindowResizer::GetTarget() { 160 aura::Window* DockedWindowResizer::GetTarget() {
172 return next_window_resizer_->GetTarget(); 161 return next_window_resizer_->GetTarget();
173 } 162 }
174 163
175 const gfx::Point& DockedWindowResizer::GetInitialLocation() const { 164 const gfx::Point& DockedWindowResizer::GetInitialLocation() const {
(...skipping 14 matching lines...) Expand all
190 aura::Window* dock_container = Shell::GetContainer( 179 aura::Window* dock_container = Shell::GetContainer(
191 details.window->GetRootWindow(), 180 details.window->GetRootWindow(),
192 kShellWindowId_DockedContainer); 181 kShellWindowId_DockedContainer);
193 dock_layout_ = static_cast<DockedWindowLayoutManager*>( 182 dock_layout_ = static_cast<DockedWindowLayoutManager*>(
194 dock_container->layout_manager()); 183 dock_container->layout_manager());
195 initial_dock_layout_ = dock_layout_; 184 initial_dock_layout_ = dock_layout_;
196 was_docked_ = details.window->parent() == dock_container; 185 was_docked_ = details.window->parent() == dock_container;
197 is_docked_ = was_docked_; 186 is_docked_ = was_docked_;
198 } 187 }
199 188
200 DockedAlignment DockedWindowResizer::GetDraggedWindowAlignment() {
201 aura::Window* window = GetTarget();
202 DockedWindowLayoutManager* layout_manager =
203 GetDockedLayoutManagerAtPoint(last_location_);
204 const DockedAlignment alignment = layout_manager->CalculateAlignment();
205 const gfx::Rect& bounds(window->GetBoundsInScreen());
206
207 // Check if the window is touching the edge - it may need to get docked.
208 if (alignment == DOCKED_ALIGNMENT_NONE)
209 return layout_manager->GetAlignmentOfWindow(window);
210
211 // Both bounds and pointer location are checked because some drags involve
212 // stickiness at the workspace-to-dock boundary and so the |location| may be
213 // outside of the |bounds|.
214 // It is also possible that all the docked windows are minimized or hidden
215 // in which case the dragged window needs to be exactly touching the same
216 // edge that those docked windows were aligned before they got minimized.
217 // TODO(varkha): Consider eliminating sticky behavior on that boundary when
218 // a pointer enters docked area.
219 if ((layout_manager->docked_bounds().Intersects(bounds) &&
220 layout_manager->docked_bounds().Contains(last_location_)) ||
221 alignment == layout_manager->GetAlignmentOfWindow(window)) {
222 // A window is being added to other docked windows (on the same side).
223 return alignment;
224 }
225 return DOCKED_ALIGNMENT_NONE;
226 }
227
228 bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds, 189 bool DockedWindowResizer::MaybeSnapToEdge(const gfx::Rect& bounds,
229 gfx::Point* offset) { 190 gfx::Point* offset) {
230 aura::Window* dock_container = Shell::GetContainer( 191 // Windows only snap magnetically when they were previously docked.
231 wm::GetRootWindowAt(last_location_), 192 if (!was_docked_)
232 kShellWindowId_DockedContainer); 193 return false;
233 DockedAlignment dock_alignment = 194 DockedAlignment dock_alignment = dock_layout_->CalculateAlignment();
234 GetDockedLayoutManagerAtPoint(last_location_)->CalculateAlignment();
235 gfx::Rect dock_bounds = ScreenAsh::ConvertRectFromScreen( 195 gfx::Rect dock_bounds = ScreenAsh::ConvertRectFromScreen(
236 GetTarget()->parent(), dock_container->GetBoundsInScreen()); 196 GetTarget()->parent(),
237 // Windows only snap magnetically when they are close to the edge of the 197 dock_layout_->dock_container()->GetBoundsInScreen());
238 // screen and when the cursor is over other docked windows.
239 // When a window being dragged is the last window that was previously
240 // docked it is still allowed to magnetically snap to either side.
241 bool can_snap = was_docked_ ||
242 (GetDraggedWindowAlignment() != DOCKED_ALIGNMENT_NONE);
243 if (!can_snap)
244 return false;
245 198
246 // Distance in pixels that the cursor must move past an edge for a window 199 // Distance in pixels that the cursor must move past an edge for a window
247 // to move beyond that edge. Same constant as in WorkspaceWindowResizer 200 // to move beyond that edge. Same constant as in WorkspaceWindowResizer
248 // is used for consistency. 201 // is used for consistency.
249 const int kStickyDistance = WorkspaceWindowResizer::kStickyDistancePixels; 202 const int kStickyDistance = WorkspaceWindowResizer::kStickyDistancePixels;
250 203
251 // Short-range magnetism when retaining docked state. Same constant as in 204 // Short-range magnetism when retaining docked state. Same constant as in
252 // MagnetismMatcher is used for consistency. 205 // MagnetismMatcher is used for consistency.
253 const int kSnapToDockDistance = MagnetismMatcher::kMagneticDistance; 206 const int kSnapToDockDistance = MagnetismMatcher::kMagneticDistance;
254 207
255 if (dock_alignment == DOCKED_ALIGNMENT_LEFT || 208 if (dock_alignment == DOCKED_ALIGNMENT_LEFT ||
256 (dock_alignment == DOCKED_ALIGNMENT_NONE && was_docked_)) { 209 dock_alignment == DOCKED_ALIGNMENT_NONE) {
257 const int distance = bounds.x() - dock_bounds.x(); 210 const int distance = bounds.x() - dock_bounds.x();
258 if (distance < (was_docked_ ? kSnapToDockDistance : 0) && 211 if (distance < kSnapToDockDistance && distance > -kStickyDistance) {
259 distance > -kStickyDistance) {
260 offset->set_x(-distance); 212 offset->set_x(-distance);
261 return true; 213 return true;
262 } 214 }
263 } 215 }
264 if (dock_alignment == DOCKED_ALIGNMENT_RIGHT || 216 if (dock_alignment == DOCKED_ALIGNMENT_RIGHT ||
265 (dock_alignment == DOCKED_ALIGNMENT_NONE && was_docked_)) { 217 dock_alignment == DOCKED_ALIGNMENT_NONE) {
266 const int distance = dock_bounds.right() - bounds.right(); 218 const int distance = dock_bounds.right() - bounds.right();
267 if (distance < (was_docked_ ? kSnapToDockDistance : 0) && 219 if (distance < kSnapToDockDistance && distance > -kStickyDistance) {
268 distance > -kStickyDistance) {
269 offset->set_x(distance); 220 offset->set_x(distance);
270 return true; 221 return true;
271 } 222 }
272 } 223 }
273 return false; 224 return false;
274 } 225 }
275 226
276 void DockedWindowResizer::StartedDragging() { 227 void DockedWindowResizer::StartedDragging() {
277 // Tell the dock layout manager that we are dragging this window. 228 // Tell the dock layout manager that we are dragging this window.
278 // At this point we are not yet animating the window as it may not be 229 // At this point we are not yet animating the window as it may not be
(...skipping 16 matching lines...) Expand all
295 } 246 }
296 if (is_docked_) 247 if (is_docked_)
297 dock_layout_->DockDraggedWindow(GetTarget()); 248 dock_layout_->DockDraggedWindow(GetTarget());
298 } 249 }
299 250
300 void DockedWindowResizer::FinishedDragging() { 251 void DockedWindowResizer::FinishedDragging() {
301 if (!did_move_or_resize_) 252 if (!did_move_or_resize_)
302 return; 253 return;
303 254
304 aura::Window* window = GetTarget(); 255 aura::Window* window = GetTarget();
305 bool should_dock = was_docked_; 256 bool attached_panel = false;
306 const bool attached_panel = 257 if (details_.bounds_change & WindowResizer::kBoundsChange_Resizes) {
307 window->type() == aura::client::WINDOW_TYPE_PANEL && 258 // No longer restore to pre-docked bounds if a window has been resized.
308 window->GetProperty(kPanelAttachedKey); 259 if (is_docked_)
309 // If a window was previously docked then keep it docked if it is resized and 260 ClearRestoreBounds(window);
310 // still aligned at the screen edge. 261 } else {
311 if ((was_docked_ || 262 attached_panel =
312 ((details_.bounds_change & WindowResizer::kBoundsChange_Repositions) && 263 window->type() == aura::client::WINDOW_TYPE_PANEL &&
313 !(details_.bounds_change & WindowResizer::kBoundsChange_Resizes)))) { 264 window->GetProperty(kPanelAttachedKey);
314 should_dock = GetDraggedWindowAlignment() != DOCKED_ALIGNMENT_NONE;
315 } 265 }
316 266
317 // Check if the window needs to be docked or returned to workspace. 267 // Check if the window needs to be docked or returned to workspace.
318 aura::Window* dock_container = Shell::GetContainer( 268 aura::Window* dock_container = Shell::GetContainer(
319 window->GetRootWindow(), 269 window->GetRootWindow(),
320 kShellWindowId_DockedContainer); 270 kShellWindowId_DockedContainer);
321 if (!attached_panel && 271 if (!attached_panel && is_docked_ != (window->parent() == dock_container)) {
322 should_dock != (window->parent() == dock_container)) { 272 if (is_docked_) {
323 if (should_dock) {
324 dock_container->AddChild(window); 273 dock_container->AddChild(window);
325 } else if (window->parent()->id() == kShellWindowId_DockedContainer) { 274 } else if (window->parent()->id() == kShellWindowId_DockedContainer) {
326 // Reparent the window back to workspace. 275 // Reparent the window back to workspace.
327 // We need to be careful to give SetDefaultParentByRootWindow location in 276 // We need to be careful to give SetDefaultParentByRootWindow location in
328 // the right root window (matching the logic in DragWindowResizer) based 277 // the right root window (matching the logic in DragWindowResizer) based
329 // on which root window a mouse pointer is in. We want to undock into the 278 // on which root window a mouse pointer is in. We want to undock into the
330 // right screen near the edge of a multiscreen setup (based on where the 279 // right screen near the edge of a multiscreen setup (based on where the
331 // mouse is). 280 // mouse is).
332 gfx::Rect near_last_location(last_location_, gfx::Size()); 281 gfx::Rect near_last_location(last_location_, gfx::Size());
333 // Reparenting will cause Relayout and possible dock shrinking. 282 // Reparenting will cause Relayout and possible dock shrinking.
334 window->SetDefaultParentByRootWindow(window->GetRootWindow(), 283 window->SetDefaultParentByRootWindow(window->GetRootWindow(),
335 near_last_location); 284 near_last_location);
336 } 285 }
337 } 286 }
338 dock_layout_->FinishDragging(); 287 dock_layout_->FinishDragging();
339 288
340 // If we started the drag in one root window and moved into another root 289 // If we started the drag in one root window and moved into another root
341 // but then canceled the drag we may need to inform the original layout 290 // but then canceled the drag we may need to inform the original layout
342 // manager that the drag is finished. 291 // manager that the drag is finished.
343 if (initial_dock_layout_ != dock_layout_) 292 if (initial_dock_layout_ != dock_layout_)
344 initial_dock_layout_->FinishDragging(); 293 initial_dock_layout_->FinishDragging();
345 is_docked_ = false; 294 is_docked_ = false;
346 } 295 // Retain restore bounds when dragging inside the docked area.
347 296 if (was_docked_ &&
348 void DockedWindowResizer::UpdateSnapPhantomWindow() { 297 window->parent()->id() == kShellWindowId_DockedContainer &&
349 if (!did_move_or_resize_ || details_.window_component != HTCAPTION) 298 !(details_.bounds_change & WindowResizer::kBoundsChange_Resizes)) {
350 return; 299 gfx::Rect initial_bounds = ScreenAsh::ConvertRectToScreen(
351 300 window->parent(), details_.initial_bounds_in_parent);
352 if (!snap_phantom_window_controller_) { 301 SetRestoreBoundsInScreen(window, details_.restore_bounds.IsEmpty() ?
353 snap_phantom_window_controller_.reset( 302 initial_bounds :
354 new PhantomWindowController(GetTarget())); 303 details_.restore_bounds);
355 } 304 }
356 snap_phantom_window_controller_->Show(dock_layout_->dragged_bounds());
357 } 305 }
358 306
359 } // namespace internal 307 } // namespace internal
360 } // namespace ash 308 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698