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