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

Side by Side Diff: ash/wm/workspace/workspace_layout_manager.cc

Issue 68033003: Undocks window first before side-snapping bounds (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Undocks window first before side-snapping bounds (comments) Created 7 years 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/workspace/workspace_layout_manager.h" 5 #include "ash/wm/workspace/workspace_layout_manager.h"
6 6
7 #include "ash/display/display_controller.h" 7 #include "ash/display/display_controller.h"
8 #include "ash/root_window_controller.h" 8 #include "ash/root_window_controller.h"
9 #include "ash/screen_ash.h" 9 #include "ash/screen_ash.h"
10 #include "ash/shelf/shelf_layout_manager.h" 10 #include "ash/shelf/shelf_layout_manager.h"
11 #include "ash/shell.h" 11 #include "ash/shell.h"
12 #include "ash/wm/always_on_top_controller.h" 12 #include "ash/wm/always_on_top_controller.h"
13 #include "ash/wm/base_layout_manager.h" 13 #include "ash/wm/base_layout_manager.h"
14 #include "ash/wm/window_animations.h" 14 #include "ash/wm/window_animations.h"
15 #include "ash/wm/window_positioner.h" 15 #include "ash/wm/window_positioner.h"
16 #include "ash/wm/window_properties.h" 16 #include "ash/wm/window_properties.h"
17 #include "ash/wm/window_state.h" 17 #include "ash/wm/window_state.h"
18 #include "ash/wm/window_util.h" 18 #include "ash/wm/window_util.h"
19 #include "ui/aura/client/aura_constants.h" 19 #include "ui/aura/client/aura_constants.h"
20 #include "ui/aura/window.h" 20 #include "ui/aura/window.h"
21 #include "ui/aura/window_observer.h" 21 #include "ui/aura/window_observer.h"
22 #include "ui/base/ui_base_types.h" 22 #include "ui/base/ui_base_types.h"
23 #include "ui/compositor/scoped_layer_animation_settings.h"
23 #include "ui/events/event.h" 24 #include "ui/events/event.h"
24 #include "ui/views/corewm/window_util.h" 25 #include "ui/views/corewm/window_util.h"
25 26
26 using aura::Window; 27 using aura::Window;
27 28
28 namespace ash { 29 namespace ash {
29 30
30 namespace internal { 31 namespace internal {
31 32
32 namespace { 33 namespace {
33 34
34 // This specifies how much percent 30% of a window rect (width / height) 35 // This specifies how much percent 30% of a window rect (width / height)
35 // must be visible when the window is added to the workspace. 36 // must be visible when the window is added to the workspace.
36 const float kMinimumPercentOnScreenArea = 0.3f; 37 const float kMinimumPercentOnScreenArea = 0.3f;
37 38
39 // Duration of slide animation used when a snapped window is adjusted.
40 const int kSlideDurationMs = 120;
41
38 void MoveToDisplayForRestore(wm::WindowState* window_state) { 42 void MoveToDisplayForRestore(wm::WindowState* window_state) {
39 if (!window_state->HasRestoreBounds()) 43 if (!window_state->HasRestoreBounds())
40 return; 44 return;
41 const gfx::Rect& restore_bounds = window_state->GetRestoreBoundsInScreen(); 45 const gfx::Rect& restore_bounds = window_state->GetRestoreBoundsInScreen();
42 46
43 // Move only if the restore bounds is outside of 47 // Move only if the restore bounds is outside of
44 // the display. There is no information about in which 48 // the display. There is no information about in which
45 // display it should be restored, so this is best guess. 49 // display it should be restored, so this is best guess.
46 // TODO(oshima): Restore information should contain the 50 // TODO(oshima): Restore information should contain the
47 // work area information like WindowResizer does for the 51 // work area information like WindowResizer does for the
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 false, child->GetRootWindow()); 114 false, child->GetRootWindow());
111 } 115 }
112 WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child); 116 WindowPositioner::RearrangeVisibleWindowOnHideOrRemove(child);
113 } 117 }
114 UpdateDesktopVisibility(); 118 UpdateDesktopVisibility();
115 } 119 }
116 120
117 void WorkspaceLayoutManager::SetChildBounds( 121 void WorkspaceLayoutManager::SetChildBounds(
118 Window* child, 122 Window* child,
119 const gfx::Rect& requested_bounds) { 123 const gfx::Rect& requested_bounds) {
120 if (!wm::GetWindowState(child)->tracked_by_workspace()) { 124 wm::WindowState* window_state = wm::GetWindowState(child);
125 if (!window_state->tracked_by_workspace()) {
121 SetChildBoundsDirect(child, requested_bounds); 126 SetChildBoundsDirect(child, requested_bounds);
122 return; 127 return;
123 } 128 }
124 gfx::Rect child_bounds(requested_bounds); 129 gfx::Rect child_bounds(requested_bounds);
125 // Some windows rely on this to set their initial bounds. 130 // Some windows rely on this to set their initial bounds.
126 if (!SetMaximizedOrFullscreenBounds(wm::GetWindowState(child))) { 131 if (!SetMaximizedOrFullscreenBounds(window_state)) {
127 // Non-maximized/full-screen windows have their size constrained to the 132 // Non-maximized/full-screen windows have their size constrained to the
128 // work-area. 133 // work-area.
129 child_bounds.set_width(std::min(work_area_in_parent_.width(), 134 child_bounds.set_width(std::min(work_area_in_parent_.width(),
130 child_bounds.width())); 135 child_bounds.width()));
131 child_bounds.set_height( 136 child_bounds.set_height(
132 std::min(work_area_in_parent_.height(), child_bounds.height())); 137 std::min(work_area_in_parent_.height(), child_bounds.height()));
133 SetChildBoundsDirect(child, child_bounds); 138 AdjustSnappedBounds(window_state, &child_bounds);
139 if (window_state->IsSnapped())
140 SetChildBoundsAnimated(child, child_bounds);
141 else
142 SetChildBoundsDirect(child, child_bounds);
134 } 143 }
135 UpdateDesktopVisibility(); 144 UpdateDesktopVisibility();
136 } 145 }
137 146
138 void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() { 147 void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() {
139 const gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( 148 const gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
140 window_->parent())); 149 window_->parent()));
141 if (work_area != work_area_in_parent_) { 150 if (work_area != work_area_in_parent_) {
142 AdjustAllWindowsBoundsForWorkAreaChange( 151 AdjustAllWindowsBoundsForWorkAreaChange(
143 ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED); 152 ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 case ADJUST_WINDOW_DISPLAY_SIZE_CHANGED: 251 case ADJUST_WINDOW_DISPLAY_SIZE_CHANGED:
243 // The work area may be smaller than the full screen. Put as much of the 252 // The work area may be smaller than the full screen. Put as much of the
244 // window as possible within the display area. 253 // window as possible within the display area.
245 bounds.AdjustToFit(work_area_in_parent_); 254 bounds.AdjustToFit(work_area_in_parent_);
246 break; 255 break;
247 case ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED: 256 case ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED:
248 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( 257 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(
249 work_area_in_parent_, &bounds); 258 work_area_in_parent_, &bounds);
250 break; 259 break;
251 } 260 }
261 AdjustSnappedBounds(window_state, &bounds);
252 if (window_state->window()->bounds() != bounds) 262 if (window_state->window()->bounds() != bounds)
253 window_state->window()->SetBounds(bounds); 263 SetChildBoundsAnimated(window_state->window(), bounds);
254 } 264 }
255 265
256 void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded( 266 void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded(
257 wm::WindowState* window_state) { 267 wm::WindowState* window_state) {
258 // Don't adjust window bounds if the bounds are empty as this 268 // Don't adjust window bounds if the bounds are empty as this
259 // happens when a new views::Widget is created. 269 // happens when a new views::Widget is created.
260 // When a window is dragged and dropped onto a different 270 // When a window is dragged and dropped onto a different
261 // root window, the bounds will be updated after they are added 271 // root window, the bounds will be updated after they are added
262 // to the root window. 272 // to the root window.
263 if (window_state->window()->bounds().IsEmpty()) 273 if (window_state->window()->bounds().IsEmpty())
(...skipping 10 matching lines...) Expand all
274 int min_width = bounds.width() * kMinimumPercentOnScreenArea; 284 int min_width = bounds.width() * kMinimumPercentOnScreenArea;
275 int min_height = bounds.height() * kMinimumPercentOnScreenArea; 285 int min_height = bounds.height() * kMinimumPercentOnScreenArea;
276 // Use entire display instead of workarea because the workarea can 286 // Use entire display instead of workarea because the workarea can
277 // be further shrunk by the docked area. The logic ensures 30% 287 // be further shrunk by the docked area. The logic ensures 30%
278 // visibility which should be enough to see where the window gets 288 // visibility which should be enough to see where the window gets
279 // moved. 289 // moved.
280 gfx::Rect display_area = ScreenAsh::GetDisplayBoundsInParent(window); 290 gfx::Rect display_area = ScreenAsh::GetDisplayBoundsInParent(window);
281 291
282 ash::wm::AdjustBoundsToEnsureWindowVisibility( 292 ash::wm::AdjustBoundsToEnsureWindowVisibility(
283 display_area, min_width, min_height, &bounds); 293 display_area, min_width, min_height, &bounds);
294 AdjustSnappedBounds(window_state, &bounds);
284 if (window->bounds() != bounds) 295 if (window->bounds() != bounds)
285 window->SetBounds(bounds); 296 window->SetBounds(bounds);
286 } 297 }
287 298
288 void WorkspaceLayoutManager::UpdateDesktopVisibility() { 299 void WorkspaceLayoutManager::UpdateDesktopVisibility() {
289 if (shelf_) 300 if (shelf_)
290 shelf_->UpdateVisibilityState(); 301 shelf_->UpdateVisibilityState();
291 } 302 }
292 303
293 void WorkspaceLayoutManager::UpdateBoundsFromShowState( 304 void WorkspaceLayoutManager::UpdateBoundsFromShowState(
294 wm::WindowState* window_state, 305 wm::WindowState* window_state,
295 ui::WindowShowState last_show_state) { 306 ui::WindowShowState last_show_state) {
296 aura::Window* window = window_state->window(); 307 aura::Window* window = window_state->window();
297 // See comment in SetMaximizedOrFullscreenBounds() as to why we use parent in 308 // See comment in SetMaximizedOrFullscreenBounds() as to why we use parent in
298 // these calculation. 309 // these calculation.
310 // TODO(varkha): Change the switch statement below to use wm::WindowShowType.
299 switch (window_state->GetShowState()) { 311 switch (window_state->GetShowState()) {
300 case ui::SHOW_STATE_DEFAULT: 312 case ui::SHOW_STATE_DEFAULT:
301 case ui::SHOW_STATE_NORMAL: { 313 case ui::SHOW_STATE_NORMAL: {
302 // Make sure that the part of the window is always visible 314 // Make sure that the part of the window is always visible
303 // when restored. 315 // when restored.
304 gfx::Rect bounds_in_parent; 316 gfx::Rect bounds_in_parent;
305 if (window_state->HasRestoreBounds()) { 317 if (window_state->HasRestoreBounds()) {
306 bounds_in_parent = window_state->GetRestoreBoundsInParent(); 318 bounds_in_parent = window_state->GetRestoreBoundsInParent();
307 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( 319 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(
308 work_area_in_parent_, &bounds_in_parent); 320 work_area_in_parent_, &bounds_in_parent);
309 } else { 321 } else {
310 // Minimized windows have no restore bounds. 322 // Minimized windows have no restore bounds.
311 // Use the current bounds instead. 323 // Use the current bounds instead.
312 bounds_in_parent = window->bounds(); 324 bounds_in_parent = window->bounds();
313 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( 325 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(
314 work_area_in_parent_, &bounds_in_parent); 326 work_area_in_parent_, &bounds_in_parent);
315 // Don't start animation if the bounds didn't change. 327 // Don't start animation if the bounds didn't change.
316 if (bounds_in_parent == window->bounds()) 328 if (bounds_in_parent == window->bounds())
317 bounds_in_parent.SetRect(0, 0, 0, 0); 329 bounds_in_parent.SetRect(0, 0, 0, 0);
318 } 330 }
331 AdjustSnappedBounds(window_state, &bounds_in_parent);
319 if (!bounds_in_parent.IsEmpty()) { 332 if (!bounds_in_parent.IsEmpty()) {
320 gfx::Rect new_bounds = BaseLayoutManager::BoundsWithScreenEdgeVisible( 333 gfx::Rect new_bounds = BaseLayoutManager::BoundsWithScreenEdgeVisible(
321 window->parent()->parent(), 334 window->parent()->parent(),
322 bounds_in_parent); 335 bounds_in_parent);
323 if (last_show_state == ui::SHOW_STATE_MINIMIZED) 336 if ((last_show_state == ui::SHOW_STATE_DEFAULT ||
337 last_show_state == ui::SHOW_STATE_NORMAL) &&
338 window_state->IsSnapped()) {
339 SetChildBoundsAnimated(window, new_bounds);
340 } else if (last_show_state == ui::SHOW_STATE_MINIMIZED) {
324 SetChildBoundsDirect(window, new_bounds); 341 SetChildBoundsDirect(window, new_bounds);
325 else 342 } else {
326 CrossFadeToBounds(window, new_bounds); 343 CrossFadeToBounds(window, new_bounds);
344 }
327 } 345 }
328 window_state->ClearRestoreBounds(); 346 window_state->ClearRestoreBounds();
329 break; 347 break;
330 } 348 }
331 349
332 case ui::SHOW_STATE_MAXIMIZED: { 350 case ui::SHOW_STATE_MAXIMIZED: {
333 MoveToDisplayForRestore(window_state); 351 MoveToDisplayForRestore(window_state);
334 gfx::Rect new_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent( 352 gfx::Rect new_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent(
335 window->parent()->parent()); 353 window->parent()->parent());
336 // If the window is restored from minimized state, do not make the cross 354 // If the window is restored from minimized state, do not make the cross
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 if (window_state->IsFullscreen()) { 396 if (window_state->IsFullscreen()) {
379 SetChildBoundsDirect( 397 SetChildBoundsDirect(
380 window_state->window(), 398 window_state->window(),
381 ScreenAsh::GetDisplayBoundsInParent( 399 ScreenAsh::GetDisplayBoundsInParent(
382 window_state->window()->parent()->parent())); 400 window_state->window()->parent()->parent()));
383 return true; 401 return true;
384 } 402 }
385 return false; 403 return false;
386 } 404 }
387 405
406 void WorkspaceLayoutManager::AdjustSnappedBounds(wm::WindowState* window_state,
407 gfx::Rect* bounds) {
408 if (!window_state->tracked_by_workspace() ||
409 !window_state->IsNormalShowState() ||
410 !window_state->IsSnapped()) {
411 return;
412 }
413 gfx::Rect maximized_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent(
414 window_state->window()->parent()->parent());
415 if (window_state->window_show_type() == wm::SHOW_TYPE_LEFT_SNAPPED)
416 bounds->set_x(maximized_bounds.x());
417 else if (window_state->window_show_type() == wm::SHOW_TYPE_RIGHT_SNAPPED)
418 bounds->set_x(maximized_bounds.right() - bounds->width());
419 bounds->set_y(maximized_bounds.y());
420 // TODO(varkha): Set width to 50% here for snapped windows.
421 bounds->set_height(maximized_bounds.height());
422 }
423
424 void WorkspaceLayoutManager::SetChildBoundsAnimated(Window* child,
425 const gfx::Rect& bounds) {
426 ui::Layer* layer = child->layer();
427 ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator());
428 slide_settings.SetPreemptionStrategy(
429 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
430 slide_settings.SetTransitionDuration(
431 base::TimeDelta::FromMilliseconds(kSlideDurationMs));
432 SetChildBoundsDirect(child, bounds);
433 }
434
388 } // namespace internal 435 } // namespace internal
389 } // namespace ash 436 } // namespace ash
OLDNEW
« no previous file with comments | « ash/wm/workspace/workspace_layout_manager.h ('k') | ash/wm/workspace/workspace_layout_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698