Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/window_state.h" | 5 #include "ash/wm/window_state.h" |
| 6 | 6 |
| 7 #include "ash/ash_switches.h" | 7 #include "ash/ash_switches.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/shell_window_ids.h" | 10 #include "ash/shell_window_ids.h" |
| 11 #include "ash/wm/default_state.h" | 11 #include "ash/wm/default_state.h" |
| 12 #include "ash/wm/window_properties.h" | 12 #include "ash/wm/window_properties.h" |
| 13 #include "ash/wm/window_state_delegate.h" | 13 #include "ash/wm/window_state_delegate.h" |
| 14 #include "ash/wm/window_state_observer.h" | 14 #include "ash/wm/window_state_observer.h" |
| 15 #include "ash/wm/window_util.h" | 15 #include "ash/wm/window_util.h" |
| 16 #include "ash/wm/wm_types.h" | 16 #include "ash/wm/wm_types.h" |
| 17 #include "base/auto_reset.h" | 17 #include "base/auto_reset.h" |
| 18 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 19 #include "ui/aura/client/aura_constants.h" | 19 #include "ui/aura/client/aura_constants.h" |
| 20 #include "ui/aura/layout_manager.h" | |
| 20 #include "ui/aura/window.h" | 21 #include "ui/aura/window.h" |
| 21 #include "ui/aura/window_delegate.h" | 22 #include "ui/aura/window_delegate.h" |
| 23 #include "ui/compositor/scoped_layer_animation_settings.h" | |
| 22 #include "ui/gfx/display.h" | 24 #include "ui/gfx/display.h" |
| 23 #include "ui/views/corewm/window_util.h" | 25 #include "ui/views/corewm/window_util.h" |
| 24 | 26 |
| 25 namespace ash { | 27 namespace ash { |
| 26 namespace wm { | 28 namespace wm { |
| 27 | 29 |
| 30 namespace { | |
| 31 | |
| 32 // A tentative class to set the bounds on the window. | |
| 33 // TODO(oshima): Once all logic are cleaned up, move this to the real layout | |
|
pkotwicz
2014/02/12 22:27:27
Nit: all logic are cleaned up -> all logic is clea
oshima
2014/02/13 14:52:34
Done.
| |
| 34 // manager with proper friendship. | |
| 35 class BoundsSetter : public aura::LayoutManager { | |
| 36 public: | |
| 37 BoundsSetter() {} | |
| 38 virtual ~BoundsSetter() {} | |
| 39 | |
| 40 // aura::LayoutManager overrides: | |
| 41 virtual void OnWindowResized() OVERRIDE {} | |
| 42 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {} | |
| 43 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {} | |
| 44 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {} | |
| 45 virtual void OnChildWindowVisibilityChanged( | |
| 46 aura::Window* child, bool visible) OVERRIDE {} | |
| 47 virtual void SetChildBounds( | |
| 48 aura::Window* child, const gfx::Rect& requested_bounds) OVERRIDE {} | |
| 49 | |
| 50 void SetBounds(aura::Window* window, const gfx::Rect& bounds) { | |
| 51 SetChildBoundsDirect(window, bounds); | |
| 52 } | |
| 53 | |
| 54 private: | |
| 55 DISALLOW_COPY_AND_ASSIGN(BoundsSetter); | |
| 56 }; | |
| 57 | |
| 58 WMEvent WMEventFromShowState(ui::WindowShowState requested_show_state) { | |
| 59 switch (requested_show_state) { | |
| 60 case ui::SHOW_STATE_DEFAULT: | |
| 61 case ui::SHOW_STATE_NORMAL: | |
| 62 return NORMAL; | |
| 63 case ui::SHOW_STATE_MINIMIZED: | |
| 64 return MINIMIZE; | |
| 65 case ui::SHOW_STATE_MAXIMIZED: | |
| 66 return MAXIMIZE; | |
| 67 case ui::SHOW_STATE_FULLSCREEN: | |
| 68 return FULLSCREEN; | |
| 69 case ui::SHOW_STATE_INACTIVE: | |
| 70 case ui::SHOW_STATE_DETACHED: | |
| 71 case ui::SHOW_STATE_END: | |
| 72 NOTREACHED() << "No WMEvent defined for the show type:" | |
| 73 << requested_show_state; | |
| 74 } | |
| 75 return NORMAL; | |
| 76 } | |
| 77 | |
| 78 } // namespace | |
| 79 | |
| 28 WindowState::WindowState(aura::Window* window) | 80 WindowState::WindowState(aura::Window* window) |
| 29 : window_(window), | 81 : window_(window), |
| 30 window_position_managed_(false), | 82 window_position_managed_(false), |
| 31 bounds_changed_by_user_(false), | 83 bounds_changed_by_user_(false), |
| 32 panel_attached_(true), | 84 panel_attached_(true), |
| 33 continue_drag_after_reparent_(false), | 85 continue_drag_after_reparent_(false), |
| 34 ignored_by_shelf_(false), | 86 ignored_by_shelf_(false), |
| 35 can_consume_system_keys_(false), | 87 can_consume_system_keys_(false), |
| 36 top_row_keys_are_function_keys_(false), | 88 top_row_keys_are_function_keys_(false), |
| 37 unminimize_to_restore_bounds_(false), | 89 unminimize_to_restore_bounds_(false), |
| 38 hide_shelf_when_fullscreen_(true), | 90 hide_shelf_when_fullscreen_(true), |
| 39 animate_to_fullscreen_(true), | 91 animate_to_fullscreen_(true), |
| 40 minimum_visibility_(false), | 92 minimum_visibility_(false), |
| 41 in_set_window_show_type_(false), | 93 ignore_property_change_(false), |
| 42 window_show_type_(ToWindowShowType(GetShowState())), | 94 window_show_type_(ToWindowShowType(GetShowState())), |
| 43 current_state_(new DefaultState) { | 95 current_state_(new DefaultState) { |
| 44 window_->AddObserver(this); | 96 window_->AddObserver(this); |
| 45 | |
| 46 #if defined(OS_CHROMEOS) | 97 #if defined(OS_CHROMEOS) |
| 47 // NOTE(pkotwicz): Animating to immersive fullscreen does not look good. When | 98 // NOTE(pkotwicz): Animating to immersive fullscreen does not look good. When |
| 48 // switches::UseImmersiveFullscreenForAllWindows() returns true, most windows | 99 // switches::UseImmersiveFullscreenForAllWindows() returns true, most windows |
| 49 // can be put into immersive fullscreen. It is not worth the added complexity | 100 // can be put into immersive fullscreen. It is not worth the added complexity |
| 50 // to only animate to fullscreen if the window is put into immersive | 101 // to only animate to fullscreen if the window is put into immersive |
| 51 // fullscreen. | 102 // fullscreen. |
| 52 animate_to_fullscreen_ = !switches::UseImmersiveFullscreenForAllWindows(); | 103 animate_to_fullscreen_ = !switches::UseImmersiveFullscreenForAllWindows(); |
| 53 #endif | 104 #endif |
| 54 } | 105 } |
| 55 | 106 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 bool WindowState::IsDocked() const { | 155 bool WindowState::IsDocked() const { |
| 105 return window_->parent() && | 156 return window_->parent() && |
| 106 window_->parent()->id() == internal::kShellWindowId_DockedContainer; | 157 window_->parent()->id() == internal::kShellWindowId_DockedContainer; |
| 107 } | 158 } |
| 108 | 159 |
| 109 bool WindowState::IsSnapped() const { | 160 bool WindowState::IsSnapped() const { |
| 110 return window_show_type_ == SHOW_TYPE_LEFT_SNAPPED || | 161 return window_show_type_ == SHOW_TYPE_LEFT_SNAPPED || |
| 111 window_show_type_ == SHOW_TYPE_RIGHT_SNAPPED; | 162 window_show_type_ == SHOW_TYPE_RIGHT_SNAPPED; |
| 112 } | 163 } |
| 113 | 164 |
| 165 bool WindowState::IsPanel() const { | |
| 166 return window_->parent() && | |
| 167 window_->parent()->id() == internal::kShellWindowId_PanelContainer; | |
| 168 } | |
| 169 | |
| 114 bool WindowState::CanMaximize() const { | 170 bool WindowState::CanMaximize() const { |
| 115 return window_->GetProperty(aura::client::kCanMaximizeKey); | 171 return window_->GetProperty(aura::client::kCanMaximizeKey); |
| 116 } | 172 } |
| 117 | 173 |
| 118 bool WindowState::CanMinimize() const { | 174 bool WindowState::CanMinimize() const { |
| 119 internal::RootWindowController* controller = | 175 internal::RootWindowController* controller = |
| 120 internal::RootWindowController::ForWindow(window_); | 176 internal::RootWindowController::ForWindow(window_); |
| 121 if (!controller) | 177 if (!controller) |
| 122 return false; | 178 return false; |
| 123 aura::Window* lockscreen = controller->GetContainer( | 179 aura::Window* lockscreen = controller->GetContainer( |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 175 void WindowState::Activate() { | 231 void WindowState::Activate() { |
| 176 ActivateWindow(window_); | 232 ActivateWindow(window_); |
| 177 } | 233 } |
| 178 | 234 |
| 179 void WindowState::Deactivate() { | 235 void WindowState::Deactivate() { |
| 180 DeactivateWindow(window_); | 236 DeactivateWindow(window_); |
| 181 } | 237 } |
| 182 | 238 |
| 183 void WindowState::Restore() { | 239 void WindowState::Restore() { |
| 184 if (!IsNormalShowType()) | 240 if (!IsNormalShowType()) |
| 185 SetWindowShowType(SHOW_TYPE_NORMAL); | 241 OnWMEvent(NORMAL); |
| 186 } | 242 } |
| 187 | 243 |
| 188 void WindowState::ToggleFullscreen() { | 244 void WindowState::ToggleFullscreen() { |
| 189 // Window which cannot be maximized should not be fullscreened. | 245 OnWMEvent(TOGGLE_FULLSCREEN); |
| 190 // It can, however, be restored if it was fullscreened. | |
| 191 bool is_fullscreen = IsFullscreen(); | |
| 192 if (!is_fullscreen && !CanMaximize()) | |
| 193 return; | |
| 194 if (delegate_ && delegate_->ToggleFullscreen(this)) | |
| 195 return; | |
| 196 if (is_fullscreen) { | |
| 197 Restore(); | |
| 198 } else { | |
| 199 window_->SetProperty(aura::client::kShowStateKey, | |
| 200 ui::SHOW_STATE_FULLSCREEN); | |
| 201 } | |
| 202 } | 246 } |
| 203 | 247 |
| 204 void WindowState::OnWMEvent(WMEvent event) { | 248 void WindowState::OnWMEvent(WMEvent event) { |
| 205 current_state_->OnWMEvent(this, event); | 249 current_state_->OnWMEvent(this, event); |
| 206 } | 250 } |
| 207 | 251 |
| 208 void WindowState::SetBoundsInScreen( | 252 void WindowState::SetBoundsInScreen( |
| 209 const gfx::Rect& bounds_in_screen) { | 253 const gfx::Rect& bounds_in_screen) { |
| 210 gfx::Rect bounds_in_parent = | 254 gfx::Rect bounds_in_parent = |
| 211 ScreenUtil::ConvertRectFromScreen(window_->parent(), | 255 ScreenUtil::ConvertRectFromScreen(window_->parent(), |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 void WindowState::DeleteDragDetails() { | 310 void WindowState::DeleteDragDetails() { |
| 267 drag_details_.reset(); | 311 drag_details_.reset(); |
| 268 } | 312 } |
| 269 | 313 |
| 270 void WindowState::SetAndClearRestoreBounds() { | 314 void WindowState::SetAndClearRestoreBounds() { |
| 271 DCHECK(HasRestoreBounds()); | 315 DCHECK(HasRestoreBounds()); |
| 272 SetBoundsInScreen(GetRestoreBoundsInScreen()); | 316 SetBoundsInScreen(GetRestoreBoundsInScreen()); |
| 273 ClearRestoreBounds(); | 317 ClearRestoreBounds(); |
| 274 } | 318 } |
| 275 | 319 |
| 320 void WindowState::AdjustSnappedBounds(gfx::Rect* bounds) { | |
| 321 if (is_dragged() || !IsSnapped()) | |
|
pkotwicz
2014/02/12 22:27:27
AdjustSnappedBounds() is suboptimal but is ok for
oshima
2014/02/13 14:52:34
yes this is temporal. This method should not be ex
| |
| 322 return; | |
| 323 gfx::Rect maximized_bounds = ScreenUtil::GetMaximizedWindowBoundsInParent( | |
| 324 window_); | |
| 325 if (window_show_type() == wm::SHOW_TYPE_LEFT_SNAPPED) | |
| 326 bounds->set_x(maximized_bounds.x()); | |
| 327 else if (window_show_type() == wm::SHOW_TYPE_RIGHT_SNAPPED) | |
| 328 bounds->set_x(maximized_bounds.right() - bounds->width()); | |
| 329 bounds->set_y(maximized_bounds.y()); | |
| 330 bounds->set_height(maximized_bounds.height()); | |
| 331 } | |
| 332 | |
| 276 void WindowState::OnWindowPropertyChanged(aura::Window* window, | 333 void WindowState::OnWindowPropertyChanged(aura::Window* window, |
| 277 const void* key, | 334 const void* key, |
| 278 intptr_t old) { | 335 intptr_t old) { |
| 279 DCHECK_EQ(window, window_); | 336 DCHECK_EQ(window, window_); |
| 280 if (key == aura::client::kShowStateKey) | 337 if (key == aura::client::kShowStateKey && !ignore_property_change_) |
| 281 SetWindowShowType(ToWindowShowType(GetShowState())); | 338 OnWMEvent(WMEventFromShowState(GetShowState())); |
| 282 } | 339 } |
| 283 | 340 |
| 284 void WindowState::SnapWindow(WindowShowType left_or_right, | 341 void WindowState::SnapWindow(WindowShowType left_or_right, |
| 285 const gfx::Rect& bounds) { | 342 const gfx::Rect& bounds) { |
| 286 if (window_show_type_ == left_or_right) { | 343 if (window_show_type_ == left_or_right) { |
| 287 window_->SetBounds(bounds); | 344 window_->SetBounds(bounds); |
| 288 return; | 345 return; |
| 289 } | 346 } |
| 290 | 347 |
| 291 // Compute the bounds that the window will restore to. If the window does not | 348 // Compute the bounds that the window will restore to. If the window does not |
| 292 // already have restore bounds, it will be restored (when un-snapped) to the | 349 // already have restore bounds, it will be restored (when un-snapped) to the |
| 293 // last bounds that it had before getting snapped. | 350 // last bounds that it had before getting snapped. |
| 294 gfx::Rect restore_bounds_in_screen(HasRestoreBounds() ? | 351 gfx::Rect restore_bounds_in_screen(HasRestoreBounds() ? |
| 295 GetRestoreBoundsInScreen() : window_->GetBoundsInScreen()); | 352 GetRestoreBoundsInScreen() : window_->GetBoundsInScreen()); |
| 296 // Set the window's restore bounds so that WorkspaceLayoutManager knows | 353 // Set the window's restore bounds so that WorkspaceLayoutManager knows |
| 297 // which width to use when the snapped window is moved to the edge. | 354 // which width to use when the snapped window is moved to the edge. |
| 298 SetRestoreBoundsInParent(bounds); | 355 SetRestoreBoundsInParent(bounds); |
| 299 | 356 |
| 300 DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED || | 357 DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED || |
| 301 left_or_right == SHOW_TYPE_RIGHT_SNAPPED); | 358 left_or_right == SHOW_TYPE_RIGHT_SNAPPED); |
| 302 SetWindowShowType(left_or_right); | 359 OnWMEvent(left_or_right == SHOW_TYPE_LEFT_SNAPPED ? |
| 360 SNAP_LEFT : SNAP_RIGHT); | |
| 361 | |
| 303 // TODO(varkha): Ideally the bounds should be changed in a LayoutManager upon | 362 // TODO(varkha): Ideally the bounds should be changed in a LayoutManager upon |
| 304 // observing the WindowShowType change. | 363 // observing the WindowShowType change. |
| 305 // If the window is a child of kShellWindowId_DockedContainer such as during | 364 // If the window is a child of kShellWindowId_DockedContainer such as during |
| 306 // a drag, the window's bounds are not set in | 365 // a drag, the window's bounds are not set in |
| 307 // WorkspaceLayoutManager::OnWindowShowTypeChanged(). Set them here. Skip | 366 // WorkspaceLayoutManager::OnWindowShowTypeChanged(). Set them here. Skip |
| 308 // setting the bounds otherwise to avoid stopping the slide animation which | 367 // setting the bounds otherwise to avoid stopping the slide animation which |
| 309 // was started as a result of OnWindowShowTypeChanged(). | 368 // was started as a result of OnWindowShowTypeChanged(). |
| 310 if (IsDocked()) | 369 if (IsDocked()) |
| 311 window_->SetBounds(bounds); | 370 window_->SetBounds(bounds); |
| 312 SetRestoreBoundsInScreen(restore_bounds_in_screen); | 371 SetRestoreBoundsInScreen(restore_bounds_in_screen); |
| 313 } | 372 } |
| 314 | 373 |
| 315 void WindowState::SetWindowShowType(WindowShowType new_window_show_type) { | 374 void WindowState::UpdateWindowShowType(WindowShowType new_window_show_type) { |
| 316 if (in_set_window_show_type_) | |
| 317 return; | |
| 318 base::AutoReset<bool> resetter(&in_set_window_show_type_, true); | |
| 319 | |
| 320 ui::WindowShowState new_window_state = | 375 ui::WindowShowState new_window_state = |
| 321 ToWindowShowState(new_window_show_type); | 376 ToWindowShowState(new_window_show_type); |
| 377 base::AutoReset<bool> resetter(&ignore_property_change_, true); | |
|
pkotwicz
2014/02/12 22:27:27
Can you move |resetter| within the if statement?
oshima
2014/02/13 14:52:34
Done.
| |
| 322 if (new_window_state != GetShowState()) | 378 if (new_window_state != GetShowState()) |
| 323 window_->SetProperty(aura::client::kShowStateKey, new_window_state); | 379 window_->SetProperty(aura::client::kShowStateKey, new_window_state); |
| 324 WindowShowType old_window_show_type = window_show_type_; | |
| 325 window_show_type_ = new_window_show_type; | 380 window_show_type_ = new_window_show_type; |
| 326 if (old_window_show_type != window_show_type_) { | 381 } |
| 327 FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, | 382 |
| 328 OnWindowShowTypeChanged(this, old_window_show_type)); | 383 void WindowState::NotifyPreShowTypeChange(WindowShowType old_window_show_type) { |
| 329 } | 384 FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, |
| 385 OnPreWindowShowTypeChange(this, old_window_show_type)); | |
| 386 } | |
| 387 | |
| 388 void WindowState::NotifyPostShowTypeChange( | |
| 389 WindowShowType old_window_show_type) { | |
| 390 FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, | |
| 391 OnPostWindowShowTypeChange(this, old_window_show_type)); | |
| 392 } | |
| 393 | |
| 394 void WindowState::SetBoundsDirect(const gfx::Rect& bounds) { | |
| 395 BoundsSetter().SetBounds(window_, bounds); | |
| 396 } | |
| 397 | |
| 398 void WindowState::SetBoundsDirectAnimated(const gfx::Rect& bounds) { | |
| 399 const int kBoundsChangeSlideDurationMs = 120; | |
| 400 | |
| 401 ui::Layer* layer = window_->layer(); | |
| 402 ui::ScopedLayerAnimationSettings slide_settings(layer->GetAnimator()); | |
| 403 slide_settings.SetPreemptionStrategy( | |
| 404 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); | |
| 405 slide_settings.SetTransitionDuration( | |
| 406 base::TimeDelta::FromMilliseconds(kBoundsChangeSlideDurationMs)); | |
| 407 SetBoundsDirect(bounds); | |
| 330 } | 408 } |
| 331 | 409 |
| 332 WindowState* GetActiveWindowState() { | 410 WindowState* GetActiveWindowState() { |
| 333 aura::Window* active = GetActiveWindow(); | 411 aura::Window* active = GetActiveWindow(); |
| 334 return active ? GetWindowState(active) : NULL; | 412 return active ? GetWindowState(active) : NULL; |
| 335 } | 413 } |
| 336 | 414 |
| 337 WindowState* GetWindowState(aura::Window* window) { | 415 WindowState* GetWindowState(aura::Window* window) { |
| 338 if (!window) | 416 if (!window) |
| 339 return NULL; | 417 return NULL; |
| 340 WindowState* settings = window->GetProperty(internal::kWindowStateKey); | 418 WindowState* settings = window->GetProperty(internal::kWindowStateKey); |
| 341 if(!settings) { | 419 if(!settings) { |
| 342 settings = new WindowState(window); | 420 settings = new WindowState(window); |
| 343 window->SetProperty(internal::kWindowStateKey, settings); | 421 window->SetProperty(internal::kWindowStateKey, settings); |
| 344 } | 422 } |
| 345 return settings; | 423 return settings; |
| 346 } | 424 } |
| 347 | 425 |
| 348 const WindowState* GetWindowState(const aura::Window* window) { | 426 const WindowState* GetWindowState(const aura::Window* window) { |
| 349 return GetWindowState(const_cast<aura::Window*>(window)); | 427 return GetWindowState(const_cast<aura::Window*>(window)); |
| 350 } | 428 } |
| 351 | 429 |
| 352 } // namespace wm | 430 } // namespace wm |
| 353 } // namespace ash | 431 } // namespace ash |
| OLD | NEW |