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

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.
pkotwicz 2013/11/27 20:24:43 Nit: Can we move the constant to the body of Work
varkha 2013/11/28 01:09:37 Done.
40 const int kBoundsChangeSlideDurationMs = 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 if (window_state->IsSnapped()) {
pkotwicz 2013/11/27 20:24:43 As I mentioned in the comment in wm::WindowState,
varkha 2013/11/28 01:09:37 Done.
139 AdjustSnappedBounds(window_state, &child_bounds);
140 SetChildBoundsAnimated(child, child_bounds);
141 } else {
142 SetChildBoundsDirect(child, child_bounds);
143 }
134 } 144 }
135 UpdateDesktopVisibility(); 145 UpdateDesktopVisibility();
136 } 146 }
137 147
138 void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() { 148 void WorkspaceLayoutManager::OnDisplayWorkAreaInsetsChanged() {
139 const gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent( 149 const gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(
140 window_->parent())); 150 window_->parent()));
141 if (work_area != work_area_in_parent_) { 151 if (work_area != work_area_in_parent_) {
142 AdjustAllWindowsBoundsForWorkAreaChange( 152 AdjustAllWindowsBoundsForWorkAreaChange(
143 ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED); 153 ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED);
144 } 154 }
145 } 155 }
146 156
147 void WorkspaceLayoutManager::OnWindowPropertyChanged(Window* window, 157 void WorkspaceLayoutManager::OnWindowPropertyChanged(Window* window,
148 const void* key, 158 const void* key,
149 intptr_t old) { 159 intptr_t old) {
150 if (key == aura::client::kAlwaysOnTopKey && 160 if (key == aura::client::kAlwaysOnTopKey &&
151 window->GetProperty(aura::client::kAlwaysOnTopKey)) { 161 window->GetProperty(aura::client::kAlwaysOnTopKey)) {
152 GetRootWindowController(window->GetRootWindow())-> 162 GetRootWindowController(window->GetRootWindow())->
153 always_on_top_controller()->GetContainer(window)->AddChild(window); 163 always_on_top_controller()->GetContainer(window)->AddChild(window);
154 } 164 }
155 } 165 }
156 166
157 void WorkspaceLayoutManager::OnTrackedByWorkspaceChanged( 167 void WorkspaceLayoutManager::OnTrackedByWorkspaceChanged(
158 wm::WindowState* window_state, 168 wm::WindowState* window_state,
159 bool old){ 169 bool old){
160 if (window_state->tracked_by_workspace()) 170 if (window_state->tracked_by_workspace())
161 SetMaximizedOrFullscreenBounds(window_state); 171 SetMaximizedOrFullscreenBounds(window_state);
pkotwicz 2013/11/27 20:24:43 Shouldn't we call AdjustSnappedBounds() here for c
varkha 2013/11/28 01:09:37 Done.
162 } 172 }
163 173
164 void WorkspaceLayoutManager::OnWindowShowTypeChanged( 174 void WorkspaceLayoutManager::OnWindowShowTypeChanged(
165 wm::WindowState* window_state, 175 wm::WindowState* window_state,
166 wm::WindowShowType old_type) { 176 wm::WindowShowType old_type) {
167 ui::WindowShowState old_state = ToWindowShowState(old_type); 177 ui::WindowShowState old_state = ToWindowShowState(old_type);
168 ui::WindowShowState new_state = window_state->GetShowState(); 178 ui::WindowShowState new_state = window_state->GetShowState();
169 if (old_state != ui::SHOW_STATE_MINIMIZED && 179 if (old_state != ui::SHOW_STATE_MINIMIZED &&
170 !window_state->HasRestoreBounds() && 180 !window_state->HasRestoreBounds() &&
171 window_state->IsMaximizedOrFullscreen() && 181 window_state->IsMaximizedOrFullscreen() &&
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 case ADJUST_WINDOW_DISPLAY_SIZE_CHANGED: 252 case ADJUST_WINDOW_DISPLAY_SIZE_CHANGED:
243 // The work area may be smaller than the full screen. Put as much of the 253 // The work area may be smaller than the full screen. Put as much of the
244 // window as possible within the display area. 254 // window as possible within the display area.
245 bounds.AdjustToFit(work_area_in_parent_); 255 bounds.AdjustToFit(work_area_in_parent_);
246 break; 256 break;
247 case ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED: 257 case ADJUST_WINDOW_WORK_AREA_INSETS_CHANGED:
248 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( 258 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(
249 work_area_in_parent_, &bounds); 259 work_area_in_parent_, &bounds);
250 break; 260 break;
251 } 261 }
262 AdjustSnappedBounds(window_state, &bounds);
252 if (window_state->window()->bounds() != bounds) 263 if (window_state->window()->bounds() != bounds)
253 window_state->window()->SetBounds(bounds); 264 SetChildBoundsAnimated(window_state->window(), bounds);
pkotwicz 2013/11/27 20:24:43 Is the comment about mirroring relevant for non cr
varkha 2013/11/28 01:09:37 I don't think so since we are not changing the lay
254 } 265 }
255 266
256 void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded( 267 void WorkspaceLayoutManager::AdjustWindowBoundsWhenAdded(
257 wm::WindowState* window_state) { 268 wm::WindowState* window_state) {
258 // Don't adjust window bounds if the bounds are empty as this 269 // Don't adjust window bounds if the bounds are empty as this
259 // happens when a new views::Widget is created. 270 // happens when a new views::Widget is created.
260 // When a window is dragged and dropped onto a different 271 // When a window is dragged and dropped onto a different
261 // root window, the bounds will be updated after they are added 272 // root window, the bounds will be updated after they are added
262 // to the root window. 273 // to the root window.
263 if (window_state->window()->bounds().IsEmpty()) 274 if (window_state->window()->bounds().IsEmpty())
(...skipping 10 matching lines...) Expand all
274 int min_width = bounds.width() * kMinimumPercentOnScreenArea; 285 int min_width = bounds.width() * kMinimumPercentOnScreenArea;
275 int min_height = bounds.height() * kMinimumPercentOnScreenArea; 286 int min_height = bounds.height() * kMinimumPercentOnScreenArea;
276 // Use entire display instead of workarea because the workarea can 287 // Use entire display instead of workarea because the workarea can
277 // be further shrunk by the docked area. The logic ensures 30% 288 // be further shrunk by the docked area. The logic ensures 30%
278 // visibility which should be enough to see where the window gets 289 // visibility which should be enough to see where the window gets
279 // moved. 290 // moved.
280 gfx::Rect display_area = ScreenAsh::GetDisplayBoundsInParent(window); 291 gfx::Rect display_area = ScreenAsh::GetDisplayBoundsInParent(window);
281 292
282 ash::wm::AdjustBoundsToEnsureWindowVisibility( 293 ash::wm::AdjustBoundsToEnsureWindowVisibility(
283 display_area, min_width, min_height, &bounds); 294 display_area, min_width, min_height, &bounds);
295 AdjustSnappedBounds(window_state, &bounds);
284 if (window->bounds() != bounds) 296 if (window->bounds() != bounds)
285 window->SetBounds(bounds); 297 window->SetBounds(bounds);
286 } 298 }
287 299
288 void WorkspaceLayoutManager::UpdateDesktopVisibility() { 300 void WorkspaceLayoutManager::UpdateDesktopVisibility() {
289 if (shelf_) 301 if (shelf_)
290 shelf_->UpdateVisibilityState(); 302 shelf_->UpdateVisibilityState();
291 } 303 }
292 304
293 void WorkspaceLayoutManager::UpdateBoundsFromShowState( 305 void WorkspaceLayoutManager::UpdateBoundsFromShowState(
294 wm::WindowState* window_state, 306 wm::WindowState* window_state,
295 ui::WindowShowState last_show_state) { 307 ui::WindowShowState last_show_state) {
296 aura::Window* window = window_state->window(); 308 aura::Window* window = window_state->window();
297 // See comment in SetMaximizedOrFullscreenBounds() as to why we use parent in 309 // See comment in SetMaximizedOrFullscreenBounds() as to why we use parent in
298 // these calculation. 310 // these calculation.
311 // TODO(varkha): Change the switch statement below to use wm::WindowShowType.
299 switch (window_state->GetShowState()) { 312 switch (window_state->GetShowState()) {
300 case ui::SHOW_STATE_DEFAULT: 313 case ui::SHOW_STATE_DEFAULT:
301 case ui::SHOW_STATE_NORMAL: { 314 case ui::SHOW_STATE_NORMAL: {
302 // Make sure that the part of the window is always visible 315 // Make sure that the part of the window is always visible
303 // when restored. 316 // when restored.
304 gfx::Rect bounds_in_parent; 317 gfx::Rect bounds_in_parent;
305 if (window_state->HasRestoreBounds()) { 318 if (window_state->HasRestoreBounds()) {
306 bounds_in_parent = window_state->GetRestoreBoundsInParent(); 319 bounds_in_parent = window_state->GetRestoreBoundsInParent();
307 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( 320 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(
308 work_area_in_parent_, &bounds_in_parent); 321 work_area_in_parent_, &bounds_in_parent);
309 } else { 322 } else {
310 // Minimized windows have no restore bounds. 323 // Minimized windows have no restore bounds.
311 // Use the current bounds instead. 324 // Use the current bounds instead.
312 bounds_in_parent = window->bounds(); 325 bounds_in_parent = window->bounds();
313 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility( 326 ash::wm::AdjustBoundsToEnsureMinimumWindowVisibility(
314 work_area_in_parent_, &bounds_in_parent); 327 work_area_in_parent_, &bounds_in_parent);
315 // Don't start animation if the bounds didn't change. 328 // Don't start animation if the bounds didn't change.
316 if (bounds_in_parent == window->bounds()) 329 if (bounds_in_parent == window->bounds())
317 bounds_in_parent.SetRect(0, 0, 0, 0); 330 bounds_in_parent.SetRect(0, 0, 0, 0);
318 } 331 }
332 AdjustSnappedBounds(window_state, &bounds_in_parent);
319 if (!bounds_in_parent.IsEmpty()) { 333 if (!bounds_in_parent.IsEmpty()) {
320 gfx::Rect new_bounds = BaseLayoutManager::BoundsWithScreenEdgeVisible( 334 gfx::Rect new_bounds = BaseLayoutManager::BoundsWithScreenEdgeVisible(
321 window->parent()->parent(), 335 window->parent()->parent(),
322 bounds_in_parent); 336 bounds_in_parent);
323 if (last_show_state == ui::SHOW_STATE_MINIMIZED) 337 if ((last_show_state == ui::SHOW_STATE_DEFAULT ||
338 last_show_state == ui::SHOW_STATE_NORMAL) &&
339 window_state->IsSnapped()) {
pkotwicz 2013/11/27 20:24:43 Can you put the check for "last_show_state == ui::
varkha 2013/11/28 01:09:37 Done.
340 SetChildBoundsAnimated(window, new_bounds);
341 } else if (last_show_state == ui::SHOW_STATE_MINIMIZED) {
324 SetChildBoundsDirect(window, new_bounds); 342 SetChildBoundsDirect(window, new_bounds);
325 else 343 } else {
326 CrossFadeToBounds(window, new_bounds); 344 CrossFadeToBounds(window, new_bounds);
345 }
327 } 346 }
328 window_state->ClearRestoreBounds(); 347 window_state->ClearRestoreBounds();
329 break; 348 break;
330 } 349 }
331 350
332 case ui::SHOW_STATE_MAXIMIZED: { 351 case ui::SHOW_STATE_MAXIMIZED: {
333 MoveToDisplayForRestore(window_state); 352 MoveToDisplayForRestore(window_state);
334 gfx::Rect new_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent( 353 gfx::Rect new_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent(
335 window->parent()->parent()); 354 window->parent()->parent());
336 // If the window is restored from minimized state, do not make the cross 355 // 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()) { 397 if (window_state->IsFullscreen()) {
379 SetChildBoundsDirect( 398 SetChildBoundsDirect(
380 window_state->window(), 399 window_state->window(),
381 ScreenAsh::GetDisplayBoundsInParent( 400 ScreenAsh::GetDisplayBoundsInParent(
382 window_state->window()->parent()->parent())); 401 window_state->window()->parent()->parent()));
383 return true; 402 return true;
384 } 403 }
385 return false; 404 return false;
386 } 405 }
387 406
407 void WorkspaceLayoutManager::AdjustSnappedBounds(wm::WindowState* window_state,
408 gfx::Rect* bounds) {
409 if (!window_state->tracked_by_workspace() ||
410 !window_state->IsNormalShowState() ||
pkotwicz 2013/11/27 20:24:43 Can you remove the check for the normal show state
varkha 2013/11/28 01:09:37 Done.
411 !window_state->IsSnapped()) {
412 return;
413 }
414 gfx::Rect maximized_bounds = ScreenAsh::GetMaximizedWindowBoundsInParent(
415 window_state->window()->parent()->parent());
416 if (window_state->window_show_type() == wm::SHOW_TYPE_LEFT_SNAPPED)
417 bounds->set_x(maximized_bounds.x());
418 else if (window_state->window_show_type() == wm::SHOW_TYPE_RIGHT_SNAPPED)
419 bounds->set_x(maximized_bounds.right() - bounds->width());
420 bounds->set_y(maximized_bounds.y());
421 // TODO(varkha): Set width to 50% here for snapped windows.
422 bounds->set_height(maximized_bounds.height());
423 }
424
425 void WorkspaceLayoutManager::SetChildBoundsAnimated(Window* child,
426 const gfx::Rect& bounds) {
427 ui::Layer* layer = child->layer();
428 ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator());
429 slide_settings.SetPreemptionStrategy(
430 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
431 slide_settings.SetTransitionDuration(
432 base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs));
433 SetChildBoundsDirect(child, bounds);
434 }
435
388 } // namespace internal 436 } // namespace internal
389 } // namespace ash 437 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698