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

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

Issue 149303003: [Refactor] Move the logic to update bounds for show type from WorkspaceLayoutManager to DefaultState (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
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_util.h" 9 #include "ash/screen_util.h"
10 #include "ash/session_state_delegate.h" 10 #include "ash/session_state_delegate.h"
11 #include "ash/shelf/shelf_layout_manager.h" 11 #include "ash/shelf/shelf_layout_manager.h"
12 #include "ash/shell.h" 12 #include "ash/shell.h"
13 #include "ash/wm/always_on_top_controller.h" 13 #include "ash/wm/always_on_top_controller.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 "ash/wm/workspace/workspace_window_resizer.h"
20 #include "ui/aura/client/activation_client.h" 19 #include "ui/aura/client/activation_client.h"
21 #include "ui/aura/client/aura_constants.h" 20 #include "ui/aura/client/aura_constants.h"
22 #include "ui/aura/window.h" 21 #include "ui/aura/window.h"
23 #include "ui/aura/window_observer.h" 22 #include "ui/aura/window_observer.h"
24 #include "ui/base/ui_base_types.h" 23 #include "ui/base/ui_base_types.h"
25 #include "ui/compositor/layer.h" 24 #include "ui/compositor/layer.h"
26 #include "ui/compositor/scoped_layer_animation_settings.h"
27 #include "ui/events/event.h" 25 #include "ui/events/event.h"
28 #include "ui/gfx/screen.h" 26 #include "ui/gfx/screen.h"
29 #include "ui/views/corewm/window_util.h" 27 #include "ui/views/corewm/window_util.h"
30 28
31 using aura::Window; 29 using aura::Window;
32 30
33 namespace ash { 31 namespace ash {
34 32
35 namespace internal { 33 namespace internal {
36 34
37 namespace { 35 namespace {
38 36
39 // This specifies how much percent 30% of a window rect (width / height) 37 // This specifies how much percent 30% of a window rect (width / height)
40 // must be visible when the window is added to the workspace. 38 // must be visible when the window is added to the workspace.
41 const float kMinimumPercentOnScreenArea = 0.3f; 39 const float kMinimumPercentOnScreenArea = 0.3f;
42 40
43 void MoveToDisplayForRestore(wm::WindowState* window_state) {
44 if (!window_state->HasRestoreBounds())
45 return;
46 const gfx::Rect& restore_bounds = window_state->GetRestoreBoundsInScreen();
47
48 // Move only if the restore bounds is outside of
49 // the display. There is no information about in which
50 // display it should be restored, so this is best guess.
51 // TODO(oshima): Restore information should contain the
52 // work area information like WindowResizer does for the
53 // last window location.
54 gfx::Rect display_area = Shell::GetScreen()->GetDisplayNearestWindow(
55 window_state->window()).bounds();
56
57 if (!display_area.Intersects(restore_bounds)) {
58 const gfx::Display& display =
59 Shell::GetScreen()->GetDisplayMatching(restore_bounds);
60 DisplayController* display_controller =
61 Shell::GetInstance()->display_controller();
62 aura::Window* new_root =
63 display_controller->GetRootWindowForDisplayId(display.id());
64 if (new_root != window_state->window()->GetRootWindow()) {
65 aura::Window* new_container =
66 Shell::GetContainer(new_root, window_state->window()->parent()->id());
67 new_container->AddChild(window_state->window());
68 }
69 }
70 }
71
72 gfx::Rect BoundsWithScreenEdgeVisible(
73 aura::Window* window,
74 const gfx::Rect& restore_bounds) {
75 gfx::Rect max_bounds =
76 ash::ScreenUtil::GetMaximizedWindowBoundsInParent(window);
77 // If the restore_bounds are more than 1 grid step away from the size the
78 // window would be when maximized, inset it.
79 max_bounds.Inset(ash::internal::WorkspaceWindowResizer::kScreenEdgeInset,
80 ash::internal::WorkspaceWindowResizer::kScreenEdgeInset);
81 if (restore_bounds.Contains(max_bounds))
82 return max_bounds;
83 return restore_bounds;
84 }
85
86 } // namespace 41 } // namespace
87 42
88 WorkspaceLayoutManager::WorkspaceLayoutManager(aura::Window* window) 43 WorkspaceLayoutManager::WorkspaceLayoutManager(aura::Window* window)
89 : shelf_(NULL), 44 : shelf_(NULL),
90 window_(window), 45 window_(window),
91 root_window_(window->GetRootWindow()), 46 root_window_(window->GetRootWindow()),
92 work_area_in_parent_(ScreenUtil::ConvertRectFromScreen( 47 work_area_in_parent_(ScreenUtil::ConvertRectFromScreen(
93 window_, 48 window_,
94 Shell::GetScreen()->GetDisplayNearestWindow(window_).work_area())), 49 Shell::GetScreen()->GetDisplayNearestWindow(window_).work_area())),
95 is_fullscreen_(GetRootWindowController( 50 is_fullscreen_(GetRootWindowController(
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 SetChildBoundsDirect(child, requested_bounds); 132 SetChildBoundsDirect(child, requested_bounds);
178 } else if (!SetMaximizedOrFullscreenBounds(window_state)) { 133 } else if (!SetMaximizedOrFullscreenBounds(window_state)) {
179 // Some windows rely on this to set their initial bounds. 134 // Some windows rely on this to set their initial bounds.
180 // Non-maximized/full-screen windows have their size constrained to the 135 // Non-maximized/full-screen windows have their size constrained to the
181 // work-area. 136 // work-area.
182 gfx::Rect child_bounds(requested_bounds); 137 gfx::Rect child_bounds(requested_bounds);
183 child_bounds.set_width(std::min(work_area_in_parent_.width(), 138 child_bounds.set_width(std::min(work_area_in_parent_.width(),
184 child_bounds.width())); 139 child_bounds.width()));
185 child_bounds.set_height(std::min(work_area_in_parent_.height(), 140 child_bounds.set_height(std::min(work_area_in_parent_.height(),
186 child_bounds.height())); 141 child_bounds.height()));
187 AdjustSnappedBounds(window_state, &child_bounds); 142 window_state->AdjustSnappedBounds(&child_bounds);
188 SetChildBoundsDirect(child, child_bounds); 143 SetChildBoundsDirect(child, child_bounds);
189 } 144 }
190 UpdateShelfVisibility(); 145 UpdateShelfVisibility();
191 } 146 }
192 147
193 ////////////////////////////////////////////////////////////////////////////// 148 //////////////////////////////////////////////////////////////////////////////
194 // WorkspaceLayoutManager, ash::ShellObserver implementation: 149 // WorkspaceLayoutManager, ash::ShellObserver implementation:
195 150
196 void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() { 151 void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() {
197 const gfx::Rect work_area(ScreenUtil::ConvertRectFromScreen( 152 const gfx::Rect work_area(ScreenUtil::ConvertRectFromScreen(
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 if (window_state && window_state->IsMinimized() && 200 if (window_state && window_state->IsMinimized() &&
246 !gained_active->IsVisible()) { 201 !gained_active->IsVisible()) {
247 window_state->Unminimize(); 202 window_state->Unminimize();
248 DCHECK(!window_state->IsMinimized()); 203 DCHECK(!window_state->IsMinimized());
249 } 204 }
250 } 205 }
251 206
252 ////////////////////////////////////////////////////////////////////////////// 207 //////////////////////////////////////////////////////////////////////////////
253 // WorkspaceLayoutManager, wm::WindowStateObserver implementation: 208 // WorkspaceLayoutManager, wm::WindowStateObserver implementation:
254 209
255 void WorkspaceLayoutManager::OnWindowShowTypeChanged( 210 void WorkspaceLayoutManager::OnPostWindowShowTypeChange(
256 wm::WindowState* window_state, 211 wm::WindowState* window_state,
257 wm::WindowShowType old_type) { 212 wm::WindowShowType old_type) {
258 if (old_type != wm::SHOW_TYPE_MINIMIZED &&
259 !window_state->HasRestoreBounds() &&
260 window_state->IsMaximizedOrFullscreen() &&
261 !wm::IsMaximizedOrFullscreenWindowShowType(old_type)) {
262 window_state->SaveCurrentBoundsForRestore();
263 }
264 // When restoring from a minimized state, we want to restore to the previous
265 // bounds. However, we want to maintain the restore bounds. (The restore
266 // bounds are set if a user maximized the window in one axis by double
267 // clicking the window border for example).
268 gfx::Rect restore;
269 if (old_type == wm::SHOW_TYPE_MINIMIZED &&
270 window_state->IsNormalShowState() &&
271 window_state->HasRestoreBounds() &&
272 !window_state->unminimize_to_restore_bounds()) {
273 restore = window_state->GetRestoreBoundsInScreen();
274 window_state->SaveCurrentBoundsForRestore();
275 }
276
277 UpdateBoundsFromShowType(window_state, old_type);
278 ShowTypeChanged(window_state, old_type);
279
280 if (window_state->IsNormalShowState())
281 window_state->ClearRestoreBounds();
282
283 // Set the restore rectangle to the previously set restore rectangle.
284 if (!restore.IsEmpty())
285 window_state->SetRestoreBoundsInScreen(restore);
286 213
287 // Notify observers that fullscreen state may be changing. 214 // Notify observers that fullscreen state may be changing.
288 if (window_state->IsFullscreen() || old_type == wm::SHOW_TYPE_FULLSCREEN) 215 if (window_state->IsFullscreen() || old_type == wm::SHOW_TYPE_FULLSCREEN)
289 UpdateFullscreenState(); 216 UpdateFullscreenState();
290 217
291 UpdateShelfVisibility(); 218 UpdateShelfVisibility();
292 } 219 }
293 220
294 void WorkspaceLayoutManager::ShowTypeChanged(
295 wm::WindowState* window_state,
296 wm::WindowShowType last_show_type) {
297 if (window_state->IsMinimized()) {
298 // Save the previous show state so that we can correctly restore it.
299 window_state->window()->SetProperty(aura::client::kRestoreShowStateKey,
300 wm::ToWindowShowState(last_show_type));
301 views::corewm::SetWindowVisibilityAnimationType(
302 window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
303
304 // Hide the window.
305 window_state->window()->Hide();
306 // Activate another window.
307 if (window_state->IsActive())
308 window_state->Deactivate();
309 } else if ((window_state->window()->TargetVisibility() ||
310 last_show_type == wm::SHOW_TYPE_MINIMIZED) &&
311 !window_state->window()->layer()->visible()) {
312 // The layer may be hidden if the window was previously minimized. Make
313 // sure it's visible.
314 window_state->window()->Show();
315 if (last_show_type == wm::SHOW_TYPE_MINIMIZED &&
316 !window_state->IsMaximizedOrFullscreen()) {
317 window_state->set_unminimize_to_restore_bounds(false);
318 }
319 }
320 }
321
322 ////////////////////////////////////////////////////////////////////////////// 221 //////////////////////////////////////////////////////////////////////////////
323 // WorkspaceLayoutManager, private: 222 // WorkspaceLayoutManager, private:
324 223
325 void WorkspaceLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange( 224 void WorkspaceLayoutManager::AdjustAllWindowsBoundsForWorkAreaChange(
326 AdjustWindowReason reason) { 225 AdjustWindowReason reason) {
327 work_area_in_parent_ = ScreenUtil::ConvertRectFromScreen( 226 work_area_in_parent_ = ScreenUtil::ConvertRectFromScreen(
328 window_, 227 window_,
329 Shell::GetScreen()->GetDisplayNearestWindow(window_).work_area()); 228 Shell::GetScreen()->GetDisplayNearestWindow(window_).work_area());
330 229
331 // Don't do any adjustments of the insets while we are in screen locked mode. 230 // Don't do any adjustments of the insets while we are in screen locked mode.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 case ADJUST_WINDOW_DISPLAY_SIZE_CHANGED: 272 case ADJUST_WINDOW_DISPLAY_SIZE_CHANGED:
374 // The work area may be smaller than the full screen. Put as much of the 273 // The work area may be smaller than the full screen. Put as much of the
375 // window as possible within the display area. 274 // window as possible within the display area.
376 bounds.AdjustToFit(work_area_in_parent_); 275 bounds.AdjustToFit(work_area_in_parent_);
377 break; 276 break;
378 case ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED: 277 case ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED:
379 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( 278 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(
380 work_area_in_parent_, &bounds); 279 work_area_in_parent_, &bounds);
381 break; 280 break;
382 } 281 }
383 //AdjustSnappedBounds(window_state, &bounds); 282 window_state->AdjustSnappedBounds(&bounds);
384 if (window_state->window()->bounds() != bounds) 283 if (window_state->window()->bounds() != bounds)
385 SetChildBoundsAnimated(window_state->window(), bounds); 284 window_state->SetBoundsDirectAnimated(bounds);
386 } 285 }
387 286
388 void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded( 287 void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded(
389 wm::WindowState* window_state) { 288 wm::WindowState* window_state) {
390 // Don't adjust window bounds if the bounds are empty as this 289 // Don't adjust window bounds if the bounds are empty as this
391 // happens when a new views::Widget is created. 290 // happens when a new views::Widget is created.
392 // When a window is dragged and dropped onto a different 291 // When a window is dragged and dropped onto a different
393 // root window, the bounds will be updated after they are added 292 // root window, the bounds will be updated after they are added
394 // to the root window. 293 // to the root window.
395 if (window_state->window()->bounds().IsEmpty() || 294 if (window_state->window()->bounds().IsEmpty() ||
396 window_state->is_dragged() || 295 window_state->is_dragged() ||
397 SetMaximizedOrFullscreenBounds(window_state)) { 296 SetMaximizedOrFullscreenBounds(window_state)) {
398 return; 297 return;
399 } 298 }
400 299
401 Window* window = window_state->window(); 300 Window* window = window_state->window();
402 gfx::Rect bounds = window->bounds(); 301 gfx::Rect bounds = window->bounds();
403 302
404 // Use entire display instead of workarea because the workarea can 303 // Use entire display instead of workarea because the workarea can
405 // be further shrunk by the docked area. The logic ensures 30% 304 // be further shrunk by the docked area. The logic ensures 30%
406 // visibility which should be enough to see where the window gets 305 // visibility which should be enough to see where the window gets
407 // moved. 306 // moved.
408 gfx::Rect display_area = ScreenUtil::GetDisplayBoundsInParent(window); 307 gfx::Rect display_area = ScreenUtil::GetDisplayBoundsInParent(window);
409 308
410 int min_width = bounds.width() * kMinimumPercentOnScreenArea; 309 int min_width = bounds.width() * kMinimumPercentOnScreenArea;
411 int min_height = bounds.height() * kMinimumPercentOnScreenArea; 310 int min_height = bounds.height() * kMinimumPercentOnScreenArea;
412 ash::wm::AdjustBoundsToEnsureWindowVisibility( 311 ash::wm::AdjustBoundsToEnsureWindowVisibility(
413 display_area, min_width, min_height, &bounds); 312 display_area, min_width, min_height, &bounds);
414 AdjustSnappedBounds(window_state, &bounds); 313 window_state->AdjustSnappedBounds(&bounds);
415 if (window->bounds() != bounds) 314 if (window->bounds() != bounds)
416 window->SetBounds(bounds); 315 window->SetBounds(bounds);
417 } 316 }
418 317
419 void WorkspaceLayoutManager::UpdateShelfVisibility() { 318 void WorkspaceLayoutManager::UpdateShelfVisibility() {
420 if (shelf_) 319 if (shelf_)
421 shelf_->UpdateVisibilityState(); 320 shelf_->UpdateVisibilityState();
422 } 321 }
423 322
424 void WorkspaceLayoutManager::UpdateFullscreenState() { 323 void WorkspaceLayoutManager::UpdateFullscreenState() {
425 bool is_fullscreen = GetRootWindowController( 324 bool is_fullscreen = GetRootWindowController(
426 window_->GetRootWindow())->GetWindowForFullscreenMode() != NULL; 325 window_->GetRootWindow())->GetWindowForFullscreenMode() != NULL;
427 if (is_fullscreen != is_fullscreen_) { 326 if (is_fullscreen != is_fullscreen_) {
428 ash::Shell::GetInstance()->NotifyFullscreenStateChange( 327 ash::Shell::GetInstance()->NotifyFullscreenStateChange(
429 is_fullscreen, window_->GetRootWindow()); 328 is_fullscreen, window_->GetRootWindow());
430 is_fullscreen_ = is_fullscreen; 329 is_fullscreen_ = is_fullscreen;
431 } 330 }
432 } 331 }
433 332
434 void WorkspaceLayoutManager::UpdateBoundsFromShowType(
435 wm::WindowState* window_state,
436 wm::WindowShowType old_show_type) {
437 aura::Window* window = window_state->window();
438 if (window_state->IsMaximizedOrFullscreen())
439 MoveToDisplayForRestore(window_state);
440
441 wm::WindowShowType show_type = window_state->window_show_type();
442 gfx::Rect bounds_in_parent;
443 switch (show_type) {
444 case wm::SHOW_TYPE_DEFAULT:
445 case wm::SHOW_TYPE_NORMAL:
446 case wm::SHOW_TYPE_LEFT_SNAPPED:
447 case wm::SHOW_TYPE_RIGHT_SNAPPED:
448 if (window_state->HasRestoreBounds())
449 bounds_in_parent = window_state->GetRestoreBoundsInParent();
450 else
451 bounds_in_parent = window->bounds();
452 // Make sure that part of the window is always visible.
453 wm::AdjustBoundsToEnsureMinimumWindowVisibility(
454 work_area_in_parent_, &bounds_in_parent);
455
456 if (show_type == wm::SHOW_TYPE_LEFT_SNAPPED ||
457 show_type == wm::SHOW_TYPE_RIGHT_SNAPPED) {
458 AdjustSnappedBounds(window_state, &bounds_in_parent);
459 } else {
460 bounds_in_parent = BoundsWithScreenEdgeVisible(
461 window,
462 bounds_in_parent);
463 }
464 break;
465
466 case wm::SHOW_TYPE_MAXIMIZED:
467 bounds_in_parent = ScreenUtil::GetMaximizedWindowBoundsInParent(window);
468 break;
469
470 case wm::SHOW_TYPE_FULLSCREEN:
471 bounds_in_parent = ScreenUtil::GetDisplayBoundsInParent(window);
472 break;
473
474 case wm::SHOW_TYPE_MINIMIZED:
475 case wm::SHOW_TYPE_INACTIVE:
476 case wm::SHOW_TYPE_DETACHED:
477 case wm::SHOW_TYPE_END:
478 case wm::SHOW_TYPE_AUTO_POSITIONED:
479 return;
480 }
481
482 if (old_show_type == wm::SHOW_TYPE_MINIMIZED ||
483 (window_state->IsFullscreen() &&
484 !window_state->animate_to_fullscreen())) {
485 SetChildBoundsDirect(window, bounds_in_parent);
486 } else if (window_state->IsMaximizedOrFullscreen() ||
487 IsMaximizedOrFullscreenWindowShowType(old_show_type)) {
488 CrossFadeToBounds(window, bounds_in_parent);
489 } else {
490 SetChildBoundsAnimated(window, bounds_in_parent);
491 }
492 }
493
494 bool WorkspaceLayoutManager::SetMaximizedOrFullscreenBounds( 333 bool WorkspaceLayoutManager::SetMaximizedOrFullscreenBounds(
495 wm::WindowState* window_state) { 334 wm::WindowState* window_state) {
496 DCHECK(!window_state->is_dragged()); 335 DCHECK(!window_state->is_dragged());
497 336
498 if (window_state->IsMaximized()) { 337 if (window_state->IsMaximized()) {
499 SetChildBoundsDirect( 338 SetChildBoundsDirect(
500 window_state->window(), ScreenUtil::GetMaximizedWindowBoundsInParent( 339 window_state->window(), ScreenUtil::GetMaximizedWindowBoundsInParent(
501 window_state->window())); 340 window_state->window()));
502 return true; 341 return true;
503 } 342 }
504 if (window_state->IsFullscreen()) { 343 if (window_state->IsFullscreen()) {
505 SetChildBoundsDirect( 344 SetChildBoundsDirect(
506 window_state->window(), 345 window_state->window(),
507 ScreenUtil::GetDisplayBoundsInParent(window_state->window())); 346 ScreenUtil::GetDisplayBoundsInParent(window_state->window()));
508 return true; 347 return true;
509 } 348 }
510 return false; 349 return false;
511 } 350 }
512 351
513 void WorkspaceLayoutManager::AdjustSnappedBounds(wm::WindowState* window_state,
514 gfx::Rect* bounds) {
515 if (window_state->is_dragged() || !window_state->IsSnapped())
516 return;
517 gfx::Rect maximized_bounds = ScreenUtil::GetMaximizedWindowBoundsInParent(
518 window_state->window());
519 if (window_state->window_show_type() == wm::SHOW_TYPE_LEFT_SNAPPED)
520 bounds->set_x(maximized_bounds.x());
521 else if (window_state->window_show_type() == wm::SHOW_TYPE_RIGHT_SNAPPED)
522 bounds->set_x(maximized_bounds.right() - bounds->width());
523 bounds->set_y(maximized_bounds.y());
524 // TODO(varkha): Set width to 50% here for snapped windows.
525 bounds->set_height(maximized_bounds.height());
526 }
527
528 void WorkspaceLayoutManager::SetChildBoundsAnimated(Window* child,
529 const gfx::Rect& bounds) {
530 const int kBoundsChangeSlideDurationMs = 120;
531
532 ui::Layer* layer = child->layer();
533 ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator());
534 slide_settings.SetPreemptionStrategy(
535 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
536 slide_settings.SetTransitionDuration(
537 base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs));
538 SetChildBoundsDirect(child, bounds);
539 }
540
541 } // namespace internal 352 } // namespace internal
542 } // namespace ash 353 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698