window_state.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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 3// found in the LICENSE file. 4 5#include "ash/wm/window_state.h" 6 7#include "ash/root_window_controller.h" 8#include "ash/screen_ash.h" 9#include "ash/shell_window_ids.h" 10#include "ash/wm/window_properties.h" 11#include "ash/wm/window_state_delegate.h" 12#include "ash/wm/window_state_observer.h" 13#include "ash/wm/window_util.h" 14#include "ash/wm/wm_types.h" 15#include "ui/aura/client/aura_constants.h" 16#include "ui/aura/window.h" 17#include "ui/aura/window_delegate.h" 18#include "ui/gfx/display.h" 19#include "ui/views/corewm/window_util.h" 20 21namespace ash { 22namespace wm { 23 24// static 25bool WindowState::IsMaximizedOrFullscreenState(ui::WindowShowState show_state) { 26 return show_state == ui::SHOW_STATE_FULLSCREEN || 27 show_state == ui::SHOW_STATE_MAXIMIZED; 28} 29 30WindowState::WindowState(aura::Window* window) 31 : window_(window), 32 tracked_by_workspace_(true), 33 window_position_managed_(false), 34 bounds_changed_by_user_(false), 35 panel_attached_(true), 36 continue_drag_after_reparent_(false), 37 ignored_by_shelf_(false), 38 can_consume_system_keys_(false), 39 top_row_keys_are_function_keys_(false), 40 window_resizer_(NULL), 41 always_restores_to_restore_bounds_(false), 42 hide_shelf_when_fullscreen_(true), 43 animate_to_fullscreen_(true), 44 window_show_type_(ToWindowShowType(GetShowState())) { 45 window_->AddObserver(this); 46} 47 48WindowState::~WindowState() { 49} 50 51void WindowState::SetDelegate(scoped_ptr<WindowStateDelegate> delegate) { 52 DCHECK(!delegate_.get()); 53 delegate_ = delegate.Pass(); 54} 55 56ui::WindowShowState WindowState::GetShowState() const { 57 return window_->GetProperty(aura::client::kShowStateKey); 58} 59 60bool WindowState::IsMinimized() const { 61 return GetShowState() == ui::SHOW_STATE_MINIMIZED; 62} 63 64bool WindowState::IsMaximized() const { 65 return GetShowState() == ui::SHOW_STATE_MAXIMIZED; 66} 67 68bool WindowState::IsFullscreen() const { 69 return GetShowState() == ui::SHOW_STATE_FULLSCREEN; 70} 71 72bool WindowState::IsMaximizedOrFullscreen() const { 73 return IsMaximizedOrFullscreenState(GetShowState()); 74} 75 76bool WindowState::IsNormalShowState() const { 77 ui::WindowShowState state = window_->GetProperty(aura::client::kShowStateKey); 78 return state == ui::SHOW_STATE_NORMAL || state == ui::SHOW_STATE_DEFAULT; 79} 80 81bool WindowState::IsActive() const { 82 return IsActiveWindow(window_); 83} 84 85bool WindowState::IsDocked() const { 86 return window_->parent() && 87 window_->parent()->id() == internal::kShellWindowId_DockedContainer; 88} 89 90bool WindowState::CanMaximize() const { 91 return window_->GetProperty(aura::client::kCanMaximizeKey); 92} 93 94bool WindowState::CanMinimize() const { 95 internal::RootWindowController* controller = 96 internal::RootWindowController::ForWindow(window_); 97 if (!controller) 98 return false; 99 aura::Window* lockscreen = controller->GetContainer( 100 internal::kShellWindowId_LockScreenContainersContainer); 101 if (lockscreen->Contains(window_)) 102 return false; 103 104 return true; 105} 106 107bool WindowState::CanResize() const { 108 return window_->GetProperty(aura::client::kCanResizeKey); 109} 110 111bool WindowState::CanActivate() const { 112 return views::corewm::CanActivateWindow(window_); 113} 114 115bool WindowState::CanSnap() const { 116 if (!CanResize() || 117 window_->type() == aura::client::WINDOW_TYPE_PANEL || 118 window_->transient_parent()) 119 return false; 120 // If a window has a maximum size defined, snapping may make it too big. 121 return window_->delegate() ? window_->delegate()->GetMaximumSize().IsEmpty() : 122 true; 123} 124 125bool WindowState::HasRestoreBounds() const { 126 return window_->GetProperty(aura::client::kRestoreBoundsKey) != NULL; 127} 128 129void WindowState::Maximize() { 130 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED); 131} 132 133void WindowState::SnapLeft(const gfx::Rect& bounds) { 134 SnapWindow(SHOW_TYPE_LEFT_SNAPPED, bounds); 135} 136 137void WindowState::SnapRight(const gfx::Rect& bounds) { 138 SnapWindow(SHOW_TYPE_LEFT_SNAPPED, bounds); 139} 140 141void WindowState::Minimize() { 142 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED); 143} 144 145void WindowState::Unminimize() { 146 window_->SetProperty( 147 aura::client::kShowStateKey, 148 window_->GetProperty(aura::client::kRestoreShowStateKey)); 149 window_->ClearProperty(aura::client::kRestoreShowStateKey); 150} 151 152void WindowState::Activate() { 153 ActivateWindow(window_); 154} 155 156void WindowState::Deactivate() { 157 DeactivateWindow(window_); 158} 159 160void WindowState::Restore() { 161 window_->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL); 162} 163 164void WindowState::ToggleMaximized() { 165 if (IsMaximized()) 166 Restore(); 167 else if (CanMaximize()) 168 Maximize(); 169} 170 171void WindowState::ToggleFullscreen() { 172 // Window which cannot be maximized should not be fullscreened. 173 // It can, however, be restored if it was fullscreened. 174 bool is_fullscreen = IsFullscreen(); 175 if (!is_fullscreen && !CanMaximize()) 176 return; 177 if (delegate_ && delegate_->ToggleFullscreen(this)) 178 return; 179 if (is_fullscreen) { 180 Restore(); 181 } else { 182 window_->SetProperty(aura::client::kShowStateKey, 183 ui::SHOW_STATE_FULLSCREEN); 184 } 185} 186 187void WindowState::SetBoundsInScreen( 188 const gfx::Rect& bounds_in_screen) { 189 gfx::Rect bounds_in_parent = 190 ScreenAsh::ConvertRectFromScreen(window_->parent(), 191 bounds_in_screen); 192 window_->SetBounds(bounds_in_parent); 193} 194 195void WindowState::SaveCurrentBoundsForRestore() { 196 gfx::Rect bounds_in_screen = 197 ScreenAsh::ConvertRectToScreen(window_->parent(), 198 window_->bounds()); 199 SetRestoreBoundsInScreen(bounds_in_screen); 200} 201 202gfx::Rect WindowState::GetRestoreBoundsInScreen() const { 203 return *window_->GetProperty(aura::client::kRestoreBoundsKey); 204} 205 206gfx::Rect WindowState::GetRestoreBoundsInParent() const { 207 return ScreenAsh::ConvertRectFromScreen(window_->parent(), 208 GetRestoreBoundsInScreen()); 209} 210 211void WindowState::SetRestoreBoundsInScreen(const gfx::Rect& bounds) { 212 window_->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds)); 213} 214 215void WindowState::SetRestoreBoundsInParent(const gfx::Rect& bounds) { 216 SetRestoreBoundsInScreen( 217 ScreenAsh::ConvertRectToScreen(window_->parent(), bounds)); 218} 219 220void WindowState::ClearRestoreBounds() { 221 window_->ClearProperty(aura::client::kRestoreBoundsKey); 222} 223 224void WindowState::SetPreAutoManageWindowBounds( 225 const gfx::Rect& bounds) { 226 pre_auto_manage_window_bounds_.reset(new gfx::Rect(bounds)); 227} 228 229void WindowState::AddObserver(WindowStateObserver* observer) { 230 observer_list_.AddObserver(observer); 231} 232 233void WindowState::RemoveObserver(WindowStateObserver* observer) { 234 observer_list_.RemoveObserver(observer); 235} 236 237void WindowState::SetTrackedByWorkspace(bool tracked_by_workspace) { 238 if (tracked_by_workspace_ == tracked_by_workspace) 239 return; 240 bool old = tracked_by_workspace_; 241 tracked_by_workspace_ = tracked_by_workspace; 242 FOR_EACH_OBSERVER(WindowStateObserver, observer_list_, 243 OnTrackedByWorkspaceChanged(this, old)); 244} 245 246void WindowState::OnWindowPropertyChanged(aura::Window* window, 247 const void* key, 248 intptr_t old) { 249 DCHECK_EQ(window, window_); 250 if (key == aura::client::kShowStateKey) { 251 window_show_type_ = ToWindowShowType(GetShowState()); 252 ui::WindowShowState old_state = static_cast<ui::WindowShowState>(old); 253 // TODO(oshima): Notify only when the state has changed. 254 // Doing so break a few tests now. 255 FOR_EACH_OBSERVER( 256 WindowStateObserver, observer_list_, 257 OnWindowShowTypeChanged(this, ToWindowShowType(old_state))); 258 } 259} 260 261void WindowState::OnWindowDestroying(aura::Window* window) { 262 window_->RemoveObserver(this); 263} 264 265void WindowState::SnapWindow(WindowShowType left_or_right, 266 const gfx::Rect& bounds) { 267 if (IsMaximizedOrFullscreen()) { 268 // Before we can set the bounds we need to restore the window. 269 // Restoring the window will set the window to its restored bounds. 270 // To avoid an unnecessary bounds changes (which may have side effects) 271 // we set the restore bounds to the bounds we want, restore the window, 272 // then reset the restore bounds. This way no unnecessary bounds 273 // changes occurs and the original restore bounds is remembered. 274 gfx::Rect restore_bounds_in_screen = 275 GetRestoreBoundsInScreen(); 276 SetRestoreBoundsInParent(bounds); 277 Restore(); 278 SetRestoreBoundsInScreen(restore_bounds_in_screen); 279 } else { 280 window_->SetBounds(bounds); 281 } 282 DCHECK(left_or_right == SHOW_TYPE_LEFT_SNAPPED || 283 left_or_right == SHOW_TYPE_RIGHT_SNAPPED); 284 window_show_type_ = left_or_right; 285} 286 287WindowState* GetActiveWindowState() { 288 aura::Window* active = GetActiveWindow(); 289 return active ? GetWindowState(active) : NULL; 290} 291 292WindowState* GetWindowState(aura::Window* window) { 293 if (!window) 294 return NULL; 295 WindowState* settings = window->GetProperty(internal::kWindowStateKey); 296 if(!settings) { 297 settings = new WindowState(window); 298 window->SetProperty(internal::kWindowStateKey, settings); 299 } 300 return settings; 301} 302 303const WindowState* GetWindowState(const aura::Window* window) { 304 return GetWindowState(const_cast<aura::Window*>(window)); 305} 306 307} // namespace wm 308} // namespace ash 309