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

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

Powered by Google App Engine
This is Rietveld 408576698