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.
5 #ifndef ASH_WM_WINDOW_STATE_H_
6 #define ASH_WM_WINDOW_STATE_H_
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"
27 class WorkspaceLayoutManager
;
28 class LockWindowState
;
29 class MaximizeModeWindowState
;
32 class WindowStateDelegate
;
33 class WindowStateObserver
;
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
{
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.
59 // Update WindowState based on |event|.
60 virtual void OnWMEvent(WindowState
* window_state
, const WMEvent
* event
) = 0;
62 virtual WindowStateType
GetType() const = 0;
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;
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;
78 DISALLOW_COPY_AND_ASSIGN(State
);
81 // Call GetWindowState() to instantiate this class.
82 ~WindowState() override
;
84 aura::Window
* window() { return window_
; }
85 const aura::Window
* window() const { return window_
; }
87 bool HasDelegate() const;
88 void SetDelegate(scoped_ptr
<WindowStateDelegate
> delegate
);
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;
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;
102 // True if the window's state type is WINDOW_STATE_TYPE_NORMAL or
103 // WINDOW_STATE_TYPE_DEFAULT.
104 bool IsNormalStateType() const;
106 bool IsNormalOrSnapped() const;
108 bool IsActive() const;
109 bool IsDocked() const;
111 // Returns true if the window's location can be controlled by the user.
112 bool IsUserPositionable() const;
114 // Checks if the window can change its state accordingly.
115 bool CanMaximize() const;
116 bool CanMinimize() const;
117 bool CanResize() const;
118 bool CanSnap() const;
119 bool CanActivate() const;
121 // Returns true if the window has restore bounds.
122 bool HasRestoreBounds() const;
124 // These methods use aura::WindowProperty to change the window's state
125 // instead of using WMEvent directly. This is to use the same mechanism as
126 // what views::Widget is using.
134 // Set the window state to normal.
135 // TODO(oshima): Change to use RESTORE event.
138 // Caches, then disables always on top state and then stacks |window_| below
139 // |window_on_top| if a |window_| is currently in always on top state.
140 void DisableAlwaysOnTop(aura::Window
* window_on_top
);
142 // Restores always on top state that a window might have cached.
143 void RestoreAlwaysOnTop();
145 // Invoked when a WMevent occurs, which drives the internal
147 void OnWMEvent(const WMEvent
* event
);
149 // TODO(oshima): Try hiding these methods and making them accessible only to
150 // state impl. State changes should happen through events (as much
153 // Saves the current bounds to be used as a restore bounds.
154 void SaveCurrentBoundsForRestore();
156 // Same as |GetRestoreBoundsInScreen| except that it returns the
157 // bounds in the parent's coordinates.
158 gfx::Rect
GetRestoreBoundsInParent() const;
160 // Returns the restore bounds property on the window in the virtual screen
161 // coordinates. The bounds can be NULL if the bounds property does not
162 // exist for the window. The window owns the bounds object.
163 gfx::Rect
GetRestoreBoundsInScreen() const;
165 // Same as |SetRestoreBoundsInScreen| except that the bounds is in the
166 // parent's coordinates.
167 void SetRestoreBoundsInParent(const gfx::Rect
& bounds_in_parent
);
169 // Sets the restore bounds property on the window in the virtual screen
170 // coordinates. Deletes existing bounds value if exists.
171 void SetRestoreBoundsInScreen(const gfx::Rect
& bounds_in_screen
);
173 // Deletes and clears the restore bounds property on the window.
174 void ClearRestoreBounds();
176 // Replace the State object of a window with a state handler which can
177 // implement a new window manager type. The passed object will be owned
178 // by this object and the returned object will be owned by the caller.
179 scoped_ptr
<State
> SetStateObject(scoped_ptr
<State
> new_state
);
181 // True if the window should be unminimized to the restore bounds, as
182 // opposed to the window's current bounds. |unminimized_to_restore_bounds_| is
183 // reset to the default value after the window is unminimized.
184 bool unminimize_to_restore_bounds() const {
185 return unminimize_to_restore_bounds_
;
187 void set_unminimize_to_restore_bounds(bool value
) {
188 unminimize_to_restore_bounds_
= value
;
191 // Gets/sets whether the shelf should be hidden when this window is
193 bool hide_shelf_when_fullscreen() const {
194 return hide_shelf_when_fullscreen_
;
197 void set_hide_shelf_when_fullscreen(bool value
) {
198 hide_shelf_when_fullscreen_
= value
;
201 // If the minimum visibilty is true, ash will try to keep a
202 // minimum amount of the window is always visible on the work area
204 // TODO(oshima): Consolidate this and window_position_managed
205 // into single parameter to control the window placement.
206 bool minimum_visibility() const {
207 return minimum_visibility_
;
209 void set_minimum_visibility(bool minimum_visibility
) {
210 minimum_visibility_
= minimum_visibility
;
213 // Specifies if the window can be dragged by the user via the caption or not.
214 bool can_be_dragged() const {
215 return can_be_dragged_
;
217 void set_can_be_dragged(bool can_be_dragged
) {
218 can_be_dragged_
= can_be_dragged
;
221 // Gets/Sets the bounds of the window before it was moved by the auto window
222 // management. As long as it was not auto-managed, it will return NULL.
223 const gfx::Rect
* pre_auto_manage_window_bounds() const {
224 return pre_auto_manage_window_bounds_
.get();
226 void SetPreAutoManageWindowBounds(const gfx::Rect
& bounds
);
228 // Layout related properties
230 void AddObserver(WindowStateObserver
* observer
);
231 void RemoveObserver(WindowStateObserver
* observer
);
233 // Whether the window is being dragged.
234 bool is_dragged() const {
235 return drag_details_
;
238 // Whether or not the window's position can be managed by the
239 // auto management logic.
240 bool window_position_managed() const { return window_position_managed_
; }
241 void set_window_position_managed(bool window_position_managed
) {
242 window_position_managed_
= window_position_managed
;
245 // Whether or not the window's position or size was changed by a user.
246 bool bounds_changed_by_user() const { return bounds_changed_by_user_
; }
247 void set_bounds_changed_by_user(bool bounds_changed_by_user
);
249 // True if this window is an attached panel.
250 bool panel_attached() const {
251 return panel_attached_
;
253 void set_panel_attached(bool panel_attached
) {
254 panel_attached_
= panel_attached
;
257 // True if the window is ignored by the shelf layout manager for
258 // purposes of darkening the shelf.
259 bool ignored_by_shelf() const { return ignored_by_shelf_
; }
260 void set_ignored_by_shelf(bool ignored_by_shelf
) {
261 ignored_by_shelf_
= ignored_by_shelf
;
264 // True if the window should be offered a chance to consume special system
265 // keys such as brightness, volume, etc. that are usually handled by the
267 bool can_consume_system_keys() const { return can_consume_system_keys_
; }
268 void set_can_consume_system_keys(bool can_consume_system_keys
) {
269 can_consume_system_keys_
= can_consume_system_keys
;
272 // True if this window has requested that the top-row keys (back, forward,
273 // brightness, volume) should be treated as function keys.
274 bool top_row_keys_are_function_keys() const {
275 return top_row_keys_are_function_keys_
;
277 void set_top_row_keys_are_function_keys(bool value
) {
278 top_row_keys_are_function_keys_
= value
;
281 // True if the window is in "immersive full screen mode" which is slightly
282 // different from the normal fullscreen mode by allowing the user to reveal
283 // the top portion of the window through a touch / mouse gesture. It might
284 // also allow the shelf to be shown in some situations.
285 bool in_immersive_fullscreen() const {
286 return in_immersive_fullscreen_
;
288 void set_in_immersive_fullscreen(bool enable
) {
289 in_immersive_fullscreen_
= enable
;
292 // Creates and takes ownership of a pointer to DragDetails when resizing is
293 // active. This should be done before a resizer gets created.
294 void CreateDragDetails(aura::Window
* window
,
295 const gfx::Point
& point_in_parent
,
296 int window_component
,
297 aura::client::WindowMoveSource source
);
299 // Deletes and clears a pointer to DragDetails. This should be done when the
300 // resizer gets destroyed.
301 void DeleteDragDetails();
303 // Sets the currently stored restore bounds and clears the restore bounds.
304 void SetAndClearRestoreBounds();
306 // Returns a pointer to DragDetails during drag operations.
307 const DragDetails
* drag_details() const { return drag_details_
.get(); }
308 DragDetails
* drag_details() { return drag_details_
.get(); }
310 // aura::WindowObserver overrides:
311 void OnWindowPropertyChanged(aura::Window
* window
,
313 intptr_t old
) override
;
316 friend class DefaultState
;
317 friend class ash::LockWindowState
;
318 friend class ash::MaximizeModeWindowState
;
319 friend ASH_EXPORT WindowState
* GetWindowState(aura::Window
*);
320 FRIEND_TEST_ALL_PREFIXES(WindowAnimationsTest
, CrossFadeToBounds
);
321 FRIEND_TEST_ALL_PREFIXES(WindowAnimationsTest
,
322 CrossFadeToBoundsFromTransform
);
324 explicit WindowState(aura::Window
* window
);
326 WindowStateDelegate
* delegate() { return delegate_
.get(); }
328 // Returns the window's current always_on_top state.
329 bool GetAlwaysOnTop() const;
331 // Returns the window's current show state.
332 ui::WindowShowState
GetShowState() const;
334 // Sets the window's bounds in screen coordinates.
335 void SetBoundsInScreen(const gfx::Rect
& bounds_in_screen
);
337 // Adjusts the |bounds| so that they are flush with the edge of the
338 // workspace if the window represented by |window_state| is side snapped.
339 void AdjustSnappedBounds(gfx::Rect
* bounds
);
341 // Updates the window show state according to the current window state type.
342 // Note that this does not update the window bounds.
343 void UpdateWindowShowStateFromStateType();
345 void NotifyPreStateTypeChange(WindowStateType old_window_state_type
);
346 void NotifyPostStateTypeChange(WindowStateType old_window_state_type
);
348 // Sets |bounds| as is and ensure the layer is aligned with pixel boundary.
349 void SetBoundsDirect(const gfx::Rect
& bounds
);
351 // Sets the window's |bounds| with constraint where the size of the
352 // new bounds will not exceeds the size of the work area.
353 void SetBoundsConstrained(const gfx::Rect
& bounds
);
355 // Sets the wndow's |bounds| and transitions to the new bounds with
356 // a scale animation.
357 void SetBoundsDirectAnimated(const gfx::Rect
& bounds
);
359 // Sets the window's |bounds| and transition to the new bounds with
360 // a cross fade animation.
361 void SetBoundsDirectCrossFade(const gfx::Rect
& bounds
);
363 // The owner of this window settings.
364 aura::Window
* window_
;
365 scoped_ptr
<WindowStateDelegate
> delegate_
;
367 bool window_position_managed_
;
368 bool bounds_changed_by_user_
;
369 bool panel_attached_
;
370 bool ignored_by_shelf_
;
371 bool can_consume_system_keys_
;
372 bool top_row_keys_are_function_keys_
;
373 scoped_ptr
<DragDetails
> drag_details_
;
375 bool unminimize_to_restore_bounds_
;
376 bool in_immersive_fullscreen_
;
377 bool hide_shelf_when_fullscreen_
;
378 bool minimum_visibility_
;
379 bool can_be_dragged_
;
380 bool cached_always_on_top_
;
382 // A property to remember the window position which was set before the
383 // auto window position manager changed the window bounds, so that it can get
384 // restored when only this one window gets shown.
385 scoped_ptr
<gfx::Rect
> pre_auto_manage_window_bounds_
;
387 base::ObserverList
<WindowStateObserver
> observer_list_
;
389 // True to ignore a property change event to avoid reentrance in
390 // UpdateWindowStateType()
391 bool ignore_property_change_
;
393 scoped_ptr
<State
> current_state_
;
395 DISALLOW_COPY_AND_ASSIGN(WindowState
);
398 // Returns the WindowState for active window. Returns |NULL|
399 // if there is no active window.
400 ASH_EXPORT WindowState
* GetActiveWindowState();
402 // Returns the WindowState for |window|. Creates WindowState
403 // if it didn't exist. The settings object is owned by |window|.
404 ASH_EXPORT WindowState
* GetWindowState(aura::Window
* window
);
406 // const version of GetWindowState.
407 ASH_EXPORT
const WindowState
*
408 GetWindowState(const aura::Window
* window
);
413 #endif // ASH_WM_WINDOW_STATE_H_