blob: 8732d281b788d2adf1e121d97f499410f3fd6ba4 [file] [log] [blame]
Torne (Richard Coles)68043e12013-09-26 13:24:57 +01001// 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"
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +00009#include "ash/wm/drag_details.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010010#include "ash/wm/wm_types.h"
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010011#include "base/basictypes.h"
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000012#include "base/gtest_prod_util.h"
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010013#include "base/memory/scoped_ptr.h"
14#include "base/observer_list.h"
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010015#include "ui/aura/window_observer.h"
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010016#include "ui/base/ui_base_types.h"
17
18namespace aura {
19class Window;
20}
21
22namespace gfx {
23class Rect;
24}
25
26namespace ash {
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000027class WorkspaceLayoutManager;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +010028class LockWindowState;
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000029class MaximizeModeWindowState;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000030
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010031namespace wm {
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000032class WindowStateDelegate;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010033class WindowStateObserver;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000034class WMEvent;
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010035
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.
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010047class ASH_EXPORT WindowState : public aura::WindowObserver {
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010048 public:
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000049
50 // A subclass of State class represents one of the window's states
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000051 // that corresponds to WindowStateType in Ash environment, e.g.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000052 // maximized, minimized or side snapped, as subclass.
53 // Each subclass defines its own behavior and transition for each WMEvent.
54 class State {
55 public:
56 State() {}
57 virtual ~State() {}
58
59 // Update WindowState based on |event|.
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000060 virtual void OnWMEvent(WindowState* window_state, const WMEvent* event) = 0;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000061
62 virtual WindowStateType GetType() const = 0;
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000063
Torne (Richard Coles)23730a62014-03-21 14:25:57 +000064 // 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
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +000077 private:
78 DISALLOW_COPY_AND_ASSIGN(State);
79 };
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010080
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +010081 // Call GetWindowState() to instantiate this class.
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010082 virtual ~WindowState();
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010083
84 aura::Window* window() { return window_; }
85 const aura::Window* window() const { return window_; }
86
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +000087 bool HasDelegate() const;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +000088 void SetDelegate(scoped_ptr<WindowStateDelegate> delegate);
89
Torne (Richard Coles)a1401312014-03-18 10:20:56 +000090 // 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;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +010094
Torne (Richard Coles)68043e12013-09-26 13:24:57 +010095 // Predicates to check window state.
96 bool IsMinimized() const;
97 bool IsMaximized() const;
98 bool IsFullscreen() const;
99 bool IsMaximizedOrFullscreen() const;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000100 bool IsSnapped() const;
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000101
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000102 // True if the window's state type is WINDOW_STATE_TYPE_NORMAL or
103 // WINDOW_STATE_TYPE_DEFAULT.
104 bool IsNormalStateType() const;
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000105
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000106 bool IsNormalOrSnapped() const;
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000107
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100108 bool IsActive() const;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000109 bool IsDocked() const;
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100110
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
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000121 // 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.
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100124 void Maximize();
125 void Minimize();
126 void Unminimize();
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000127
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100128 void Activate();
129 void Deactivate();
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000130
131 // Set the window state to normal.
132 // TODO(oshima): Change to use RESTORE event.
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100133 void Restore();
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100134
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000135 // Invoked when a WMevent occurs, which drives the internal
136 // state machine.
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000137 void OnWMEvent(const WMEvent* event);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000138
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000139 // 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).
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100142
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
Torne (Richard Coles)23730a62014-03-21 14:25:57 +0000166 // 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
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000171 // 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.
174 bool unminimize_to_restore_bounds() const {
175 return unminimize_to_restore_bounds_;
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100176 }
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000177 void set_unminimize_to_restore_bounds(bool value) {
178 unminimize_to_restore_bounds_ = value;
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100179 }
180
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000181 // Gets/sets whether the shelf should be hidden when this window is
182 // fullscreen.
183 bool hide_shelf_when_fullscreen() const {
184 return hide_shelf_when_fullscreen_;
185 }
186
187 void set_hide_shelf_when_fullscreen(bool value) {
188 hide_shelf_when_fullscreen_ = value;
189 }
190
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000191 // 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.
196 bool minimum_visibility() const {
197 return minimum_visibility_;
198 }
199 void set_minimum_visibility(bool minimum_visibility) {
200 minimum_visibility_ = minimum_visibility;
201 }
202
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000203 // Specifies if the window can be dragged by the user via the caption or not.
204 bool can_be_dragged() const {
205 return can_be_dragged_;
206 }
207 void set_can_be_dragged(bool can_be_dragged) {
208 can_be_dragged_ = can_be_dragged;
209 }
210
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100211 // 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.
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
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100220 void AddObserver(WindowStateObserver* observer);
221 void RemoveObserver(WindowStateObserver* observer);
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100222
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000223 // Whether the window is being dragged.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000224 bool is_dragged() const {
225 return drag_details_;
226 }
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100227
228 // Whether or not the window's position can be managed by the
229 // auto management logic.
230 bool window_position_managed() const { return 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.
236 bool bounds_changed_by_user() const { return bounds_changed_by_user_; }
Bo Liu5c02ac12014-05-01 10:37:37 -0700237 void set_bounds_changed_by_user(bool bounds_changed_by_user);
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100238
239 // True if this window is an attached panel.
240 bool panel_attached() const {
241 return panel_attached_;
242 }
243 void set_panel_attached(bool panel_attached) {
244 panel_attached_ = panel_attached;
245 }
246
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100247 // True if the window is ignored by the shelf layout manager for
248 // purposes of darkening the shelf.
249 bool ignored_by_shelf() const { return ignored_by_shelf_; }
250 void set_ignored_by_shelf(bool ignored_by_shelf) {
251 ignored_by_shelf_ = ignored_by_shelf;
252 }
253
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100254 // 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.
257 bool can_consume_system_keys() const { return 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.
264 bool top_row_keys_are_function_keys() const {
265 return top_row_keys_are_function_keys_;
266 }
267 void set_top_row_keys_are_function_keys(bool value) {
268 top_row_keys_are_function_keys_ = value;
269 }
270
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100271 // 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.
275 bool in_immersive_fullscreen() const {
276 return in_immersive_fullscreen_;
277 }
278 void set_in_immersive_fullscreen(bool enable) {
279 in_immersive_fullscreen_ = enable;
280 }
281
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000282 // 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
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000296 // Returns a pointer to DragDetails during drag operations.
297 const DragDetails* drag_details() const { return drag_details_.get(); }
298 DragDetails* drag_details() { return drag_details_.get(); }
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000299
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100300 // aura::WindowObserver overrides:
301 virtual void OnWindowPropertyChanged(aura::Window* window,
302 const void* key,
303 intptr_t old) OVERRIDE;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100304
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100305 private:
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000306 friend class DefaultState;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100307 friend class ash::LockWindowState;
Ben Murdochc5cede92014-04-10 11:22:14 +0100308 friend class ash::MaximizeModeWindowState;
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100309 friend ASH_EXPORT WindowState* GetWindowState(aura::Window*);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000310 FRIEND_TEST_ALL_PREFIXES(WindowAnimationsTest, CrossFadeToBounds);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000311
Torne (Richard Coles)f8ee7882014-06-20 14:52:04 +0100312 explicit WindowState(aura::Window* window);
313
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000314 WindowStateDelegate* delegate() { return delegate_.get(); }
315
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000316 // Returns the window's current show state.
317 ui::WindowShowState GetShowState() const;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100318
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000319 // 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.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000327 // Note that this does not update the window bounds.
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000328 void UpdateWindowShowStateFromStateType();
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000329
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000330 void NotifyPreStateTypeChange(WindowStateType old_window_state_type);
331 void NotifyPostStateTypeChange(WindowStateType old_window_state_type);
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000332
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000333 // Sets |bounds| as is.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000334 void SetBoundsDirect(const gfx::Rect& bounds);
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000335
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.
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000342 void SetBoundsDirectAnimated(const gfx::Rect& bounds);
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000343
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000344 // 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
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100348 // The owner of this window settings.
349 aura::Window* window_;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000350 scoped_ptr<WindowStateDelegate> delegate_;
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100351
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100352 bool window_position_managed_;
353 bool bounds_changed_by_user_;
354 bool panel_attached_;
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100355 bool ignored_by_shelf_;
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100356 bool can_consume_system_keys_;
357 bool top_row_keys_are_function_keys_;
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000358 scoped_ptr<DragDetails> drag_details_;
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100359
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000360 bool unminimize_to_restore_bounds_;
Torne (Richard Coles)46d4c2b2014-06-09 12:00:27 +0100361 bool in_immersive_fullscreen_;
Torne (Richard Coles)1e9bf3e2013-10-31 11:16:26 +0000362 bool hide_shelf_when_fullscreen_;
Torne (Richard Coles)0f1bc082013-11-06 12:27:47 +0000363 bool minimum_visibility_;
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000364 bool can_be_dragged_;
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100365
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
Torne (Richard Coles)4e180b62013-10-18 15:46:22 +0100371 ObserverList<WindowStateObserver> observer_list_;
372
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000373 // True to ignore a property change event to avoid reentrance in
Torne (Richard Coles)a1401312014-03-18 10:20:56 +0000374 // UpdateWindowStateType()
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000375 bool ignore_property_change_;
Torne (Richard Coles)a3f6a492013-12-18 16:25:09 +0000376
Torne (Richard Coles)5d1f7b12014-02-21 12:16:55 +0000377 scoped_ptr<State> current_state_;
378
Torne (Richard Coles)68043e12013-09-26 13:24:57 +0100379 DISALLOW_COPY_AND_ASSIGN(WindowState);
380};
381
382// Returns the WindowState for active window. Returns |NULL|
383// if there is no active window.
384ASH_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|.
388ASH_EXPORT WindowState* GetWindowState(aura::Window* window);
389
390// const version of GetWindowState.
391ASH_EXPORT const WindowState*
392GetWindowState(const aura::Window* window);
393
394} // namespace wm
395} // namespace ash
396
397#endif // ASH_WM_WINDOW_STATE_H_