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. | |
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 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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |