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

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

Powered by Google App Engine
This is Rietveld 408576698