Chromium Code Reviews| OLD | NEW |
|---|---|
| 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; | |
|
pkotwicz
2013/11/27 06:21:57
How about kBoundsChangeSlideDurationMs
varkha
2013/11/27 06:38:54
Done.
| |
| 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 Loading... | |
| 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()) | |
|
pkotwicz
2013/11/27 06:21:57
Can you move AdjustSnappedBounds() within the IsSn
varkha
2013/11/27 06:38:54
Done.
| |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |