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 #ifndef ASH_WM_WINDOW_STATE_H_ 6 #define ASH_WM_WINDOW_STATE_H_ 7 8 #include "ash/ash_export.h" 9 #include "ash/wm/drag_details.h" 10 #include "ash/wm/wm_types.h" 11 #include "base/basictypes.h" 12 #include "base/gtest_prod_util.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/observer_list.h" 15 #include "ui/aura/window_observer.h" 16 #include "ui/base/ui_base_types.h" 17 18 namespace aura { 19 class Window; 20 } 21 22 namespace gfx { 23 class Rect; 24 } 25 26 namespace ash { 27 class WorkspaceLayoutManager; 28 class LockWindowState; 29 class MaximizeModeWindowState; 30 31 namespace wm { 32 class WindowStateDelegate; 33 class WindowStateObserver; 34 class WMEvent; 35 36 // WindowState manages and defines ash specific window state and 37 // behavior. Ash specific per-window state (such as ones that controls 38 // window manager behavior) and ash specific window behavior (such as 39 // maximize, minimize, snap sizing etc) should be added here instead 40 // of defining separate functions (like |MaximizeWindow(aura::Window* 41 // window)|) or using aura Window property. 42 // The WindowState gets created when first accessed by 43 // |wm::GetWindowState|, and deleted when the window is deleted. 44 // Prefer using this class instead of passing aura::Window* around in 45 // ash code as this is often what you need to interact with, and 46 // accessing the window using |window()| is cheap. 47 class ASH_EXPORT WindowState : public aura::WindowObserver { 48 public: 49 50 // A subclass of State class represents one of the window's states 51 // that corresponds to WindowStateType in Ash environment, e.g. 52 // maximized, minimized or side snapped, as subclass. 53 // Each subclass defines its own behavior and transition for each WMEvent. 54 class State { 55 public: State()56 State() {} ~State()57 virtual ~State() {} 58 59 // Update WindowState based on |event|. 60 virtual void OnWMEvent(WindowState* window_state, const WMEvent* event) = 0; 61 62 virtual WindowStateType GetType() const = 0; 63 64 // Gets called when the state object became active and the managed window 65 // needs to be adjusted to the State's requirement. 66 // The passed |previous_state| may be used to properly implement state 67 // transitions such as bound animations from the previous state. 68 // Note: This only gets called when the state object gets changed. 69 virtual void AttachState(WindowState* window_state, 70 State* previous_state) = 0; 71 72 // Gets called before the state objects gets deactivated / detached from the 73 // window, so that it can save the various states it is interested in. 74 // Note: This only gets called when the state object gets changed. 75 virtual void DetachState(WindowState* window_state) = 0; 76 77 private: 78 DISALLOW_COPY_AND_ASSIGN(State); 79 }; 80 81 // Call GetWindowState() to instantiate this class. 82 virtual ~WindowState(); 83 window()84 aura::Window* window() { return window_; } window()85 const aura::Window* window() const { return window_; } 86 87 bool HasDelegate() const; 88 void SetDelegate(scoped_ptr<WindowStateDelegate> delegate); 89 90 // Returns the window's current ash state type. 91 // Refer to WindowStateType definition in wm_types.h as for why Ash 92 // has its own state type. 93 WindowStateType GetStateType() const; 94 95 // Predicates to check window state. 96 bool IsMinimized() const; 97 bool IsMaximized() const; 98 bool IsFullscreen() const; 99 bool IsMaximizedOrFullscreen() const; 100 bool IsSnapped() const; 101 102 // True if the window's state type is WINDOW_STATE_TYPE_NORMAL or 103 // WINDOW_STATE_TYPE_DEFAULT. 104 bool IsNormalStateType() const; 105 106 bool IsNormalOrSnapped() const; 107 108 bool IsActive() const; 109 bool IsDocked() const; 110 111 // Checks if the window can change its state accordingly. 112 bool CanMaximize() const; 113 bool CanMinimize() const; 114 bool CanResize() const; 115 bool CanSnap() const; 116 bool CanActivate() const; 117 118 // Returns true if the window has restore bounds. 119 bool HasRestoreBounds() const; 120 121 // These methods use aura::WindowProperty to change the window's state 122 // instead of using WMEvent directly. This is to use the same mechanism as 123 // what views::Widget is using. 124 void Maximize(); 125 void Minimize(); 126 void Unminimize(); 127 128 void Activate(); 129 void Deactivate(); 130 131 // Set the window state to normal. 132 // TODO(oshima): Change to use RESTORE event. 133 void Restore(); 134 135 // Invoked when a WMevent occurs, which drives the internal 136 // state machine. 137 void OnWMEvent(const WMEvent* event); 138 139 // TODO(oshima): Try hiding these methods and making them accessible only to 140 // state impl. State changes should happen through events (as much 141 // as possible). 142 143 // Saves the current bounds to be used as a restore bounds. 144 void SaveCurrentBoundsForRestore(); 145 146 // Same as |GetRestoreBoundsInScreen| except that it returns the 147 // bounds in the parent's coordinates. 148 gfx::Rect GetRestoreBoundsInParent() const; 149 150 // Returns the restore bounds property on the window in the virtual screen 151 // coordinates. The bounds can be NULL if the bounds property does not 152 // exist for the window. The window owns the bounds object. 153 gfx::Rect GetRestoreBoundsInScreen() const; 154 155 // Same as |SetRestoreBoundsInScreen| except that the bounds is in the 156 // parent's coordinates. 157 void SetRestoreBoundsInParent(const gfx::Rect& bounds_in_parent); 158 159 // Sets the restore bounds property on the window in the virtual screen 160 // coordinates. Deletes existing bounds value if exists. 161 void SetRestoreBoundsInScreen(const gfx::Rect& bounds_in_screen); 162 163 // Deletes and clears the restore bounds property on the window. 164 void ClearRestoreBounds(); 165 166 // Replace the State object of a window with a state handler which can 167 // implement a new window manager type. The passed object will be owned 168 // by this object and the returned object will be owned by the caller. 169 scoped_ptr<State> SetStateObject(scoped_ptr<State> new_state); 170 171 // True if the window should be unminimized to the restore bounds, as 172 // opposed to the window's current bounds. |unminimized_to_restore_bounds_| is 173 // reset to the default value after the window is unminimized. unminimize_to_restore_bounds()174 bool unminimize_to_restore_bounds() const { 175 return unminimize_to_restore_bounds_; 176 } set_unminimize_to_restore_bounds(bool value)177 void set_unminimize_to_restore_bounds(bool value) { 178 unminimize_to_restore_bounds_ = value; 179 } 180 181 // Gets/sets whether the shelf should be hidden when this window is 182 // fullscreen. hide_shelf_when_fullscreen()183 bool hide_shelf_when_fullscreen() const { 184 return hide_shelf_when_fullscreen_; 185 } 186 set_hide_shelf_when_fullscreen(bool value)187 void set_hide_shelf_when_fullscreen(bool value) { 188 hide_shelf_when_fullscreen_ = value; 189 } 190 191 // If the minimum visibilty is true, ash will try to keep a 192 // minimum amount of the window is always visible on the work area 193 // when shown. 194 // TODO(oshima): Consolidate this and window_position_managed 195 // into single parameter to control the window placement. minimum_visibility()196 bool minimum_visibility() const { 197 return minimum_visibility_; 198 } set_minimum_visibility(bool minimum_visibility)199 void set_minimum_visibility(bool minimum_visibility) { 200 minimum_visibility_ = minimum_visibility; 201 } 202 203 // Specifies if the window can be dragged by the user via the caption or not. can_be_dragged()204 bool can_be_dragged() const { 205 return can_be_dragged_; 206 } set_can_be_dragged(bool can_be_dragged)207 void set_can_be_dragged(bool can_be_dragged) { 208 can_be_dragged_ = can_be_dragged; 209 } 210 211 // Gets/Sets the bounds of the window before it was moved by the auto window 212 // management. As long as it was not auto-managed, it will return NULL. pre_auto_manage_window_bounds()213 const gfx::Rect* pre_auto_manage_window_bounds() const { 214 return pre_auto_manage_window_bounds_.get(); 215 } 216 void SetPreAutoManageWindowBounds(const gfx::Rect& bounds); 217 218 // Layout related properties 219 220 void AddObserver(WindowStateObserver* observer); 221 void RemoveObserver(WindowStateObserver* observer); 222 223 // Whether the window is being dragged. is_dragged()224 bool is_dragged() const { 225 return drag_details_; 226 } 227 228 // Whether or not the window's position can be managed by the 229 // auto management logic. window_position_managed()230 bool window_position_managed() const { return window_position_managed_; } set_window_position_managed(bool window_position_managed)231 void set_window_position_managed(bool window_position_managed) { 232 window_position_managed_ = window_position_managed; 233 } 234 235 // Whether or not the window's position or size was changed by a user. bounds_changed_by_user()236 bool bounds_changed_by_user() const { return bounds_changed_by_user_; } 237 void set_bounds_changed_by_user(bool bounds_changed_by_user); 238 239 // True if this window is an attached panel. panel_attached()240 bool panel_attached() const { 241 return panel_attached_; 242 } set_panel_attached(bool panel_attached)243 void set_panel_attached(bool panel_attached) { 244 panel_attached_ = panel_attached; 245 } 246 247 // True if the window is ignored by the shelf layout manager for 248 // purposes of darkening the shelf. ignored_by_shelf()249 bool ignored_by_shelf() const { return ignored_by_shelf_; } set_ignored_by_shelf(bool ignored_by_shelf)250 void set_ignored_by_shelf(bool ignored_by_shelf) { 251 ignored_by_shelf_ = ignored_by_shelf; 252 } 253 254 // True if the window should be offered a chance to consume special system 255 // keys such as brightness, volume, etc. that are usually handled by the 256 // shell. can_consume_system_keys()257 bool can_consume_system_keys() const { return can_consume_system_keys_; } set_can_consume_system_keys(bool can_consume_system_keys)258 void set_can_consume_system_keys(bool can_consume_system_keys) { 259 can_consume_system_keys_ = can_consume_system_keys; 260 } 261 262 // True if this window has requested that the top-row keys (back, forward, 263 // brightness, volume) should be treated as function keys. top_row_keys_are_function_keys()264 bool top_row_keys_are_function_keys() const { 265 return top_row_keys_are_function_keys_; 266 } set_top_row_keys_are_function_keys(bool value)267 void set_top_row_keys_are_function_keys(bool value) { 268 top_row_keys_are_function_keys_ = value; 269 } 270 271 // True if the window is in "immersive full screen mode" which is slightly 272 // different from the normal fullscreen mode by allowing the user to reveal 273 // the top portion of the window through a touch / mouse gesture. It might 274 // also allow the shelf to be shown in some situations. in_immersive_fullscreen()275 bool in_immersive_fullscreen() const { 276 return in_immersive_fullscreen_; 277 } set_in_immersive_fullscreen(bool enable)278 void set_in_immersive_fullscreen(bool enable) { 279 in_immersive_fullscreen_ = enable; 280 } 281 282 // Creates and takes ownership of a pointer to DragDetails when resizing is 283 // active. This should be done before a resizer gets created. 284 void CreateDragDetails(aura::Window* window, 285 const gfx::Point& point_in_parent, 286 int window_component, 287 aura::client::WindowMoveSource source); 288 289 // Deletes and clears a pointer to DragDetails. This should be done when the 290 // resizer gets destroyed. 291 void DeleteDragDetails(); 292 293 // Sets the currently stored restore bounds and clears the restore bounds. 294 void SetAndClearRestoreBounds(); 295 296 // Returns a pointer to DragDetails during drag operations. drag_details()297 const DragDetails* drag_details() const { return drag_details_.get(); } drag_details()298 DragDetails* drag_details() { return drag_details_.get(); } 299 300 // aura::WindowObserver overrides: 301 virtual void OnWindowPropertyChanged(aura::Window* window, 302 const void* key, 303 intptr_t old) OVERRIDE; 304 305 private: 306 friend class DefaultState; 307 friend class ash::LockWindowState; 308 friend class ash::MaximizeModeWindowState; 309 friend ASH_EXPORT WindowState* GetWindowState(aura::Window*); 310 FRIEND_TEST_ALL_PREFIXES(WindowAnimationsTest, CrossFadeToBounds); 311 312 explicit WindowState(aura::Window* window); 313 delegate()314 WindowStateDelegate* delegate() { return delegate_.get(); } 315 316 // Returns the window's current show state. 317 ui::WindowShowState GetShowState() const; 318 319 // Sets the window's bounds in screen coordinates. 320 void SetBoundsInScreen(const gfx::Rect& bounds_in_screen); 321 322 // Adjusts the |bounds| so that they are flush with the edge of the 323 // workspace if the window represented by |window_state| is side snapped. 324 void AdjustSnappedBounds(gfx::Rect* bounds); 325 326 // Updates the window show state according to the current window state type. 327 // Note that this does not update the window bounds. 328 void UpdateWindowShowStateFromStateType(); 329 330 void NotifyPreStateTypeChange(WindowStateType old_window_state_type); 331 void NotifyPostStateTypeChange(WindowStateType old_window_state_type); 332 333 // Sets |bounds| as is and ensure the layer is aligned with pixel boundary. 334 void SetBoundsDirect(const gfx::Rect& bounds); 335 336 // Sets the window's |bounds| with constraint where the size of the 337 // new bounds will not exceeds the size of the work area. 338 void SetBoundsConstrained(const gfx::Rect& bounds); 339 340 // Sets the wndow's |bounds| and transitions to the new bounds with 341 // a scale animation. 342 void SetBoundsDirectAnimated(const gfx::Rect& bounds); 343 344 // Sets the window's |bounds| and transition to the new bounds with 345 // a cross fade animation. 346 void SetBoundsDirectCrossFade(const gfx::Rect& bounds); 347 348 // The owner of this window settings. 349 aura::Window* window_; 350 scoped_ptr<WindowStateDelegate> delegate_; 351 352 bool window_position_managed_; 353 bool bounds_changed_by_user_; 354 bool panel_attached_; 355 bool ignored_by_shelf_; 356 bool can_consume_system_keys_; 357 bool top_row_keys_are_function_keys_; 358 scoped_ptr<DragDetails> drag_details_; 359 360 bool unminimize_to_restore_bounds_; 361 bool in_immersive_fullscreen_; 362 bool hide_shelf_when_fullscreen_; 363 bool minimum_visibility_; 364 bool can_be_dragged_; 365 366 // A property to remember the window position which was set before the 367 // auto window position manager changed the window bounds, so that it can get 368 // restored when only this one window gets shown. 369 scoped_ptr<gfx::Rect> pre_auto_manage_window_bounds_; 370 371 ObserverList<WindowStateObserver> observer_list_; 372 373 // True to ignore a property change event to avoid reentrance in 374 // UpdateWindowStateType() 375 bool ignore_property_change_; 376 377 scoped_ptr<State> current_state_; 378 379 DISALLOW_COPY_AND_ASSIGN(WindowState); 380 }; 381 382 // Returns the WindowState for active window. Returns |NULL| 383 // if there is no active window. 384 ASH_EXPORT WindowState* GetActiveWindowState(); 385 386 // Returns the WindowState for |window|. Creates WindowState 387 // if it didn't exist. The settings object is owned by |window|. 388 ASH_EXPORT WindowState* GetWindowState(aura::Window* window); 389 390 // const version of GetWindowState. 391 ASH_EXPORT const WindowState* 392 GetWindowState(const aura::Window* window); 393 394 } // namespace wm 395 } // namespace ash 396 397 #endif // ASH_WM_WINDOW_STATE_H_ 398