• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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