Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / ash / shelf / shelf_layout_manager.h
1 // Copyright (c) 2012 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_SHELF_SHELF_LAYOUT_MANAGER_H_
6 #define ASH_SHELF_SHELF_LAYOUT_MANAGER_H_
7
8 #include <vector>
9
10 #include "ash/ash_export.h"
11 #include "ash/shelf/background_animator.h"
12 #include "ash/shelf/shelf.h"
13 #include "ash/shelf/shelf_types.h"
14 #include "ash/shell_observer.h"
15 #include "ash/system/status_area_widget.h"
16 #include "ash/wm/dock/docked_window_layout_manager_observer.h"
17 #include "ash/wm/lock_state_observer.h"
18 #include "ash/wm/workspace/workspace_types.h"
19 #include "base/basictypes.h"
20 #include "base/compiler_specific.h"
21 #include "base/logging.h"
22 #include "base/observer_list.h"
23 #include "base/timer/timer.h"
24 #include "ui/aura/client/activation_change_observer.h"
25 #include "ui/aura/layout_manager.h"
26 #include "ui/gfx/insets.h"
27 #include "ui/gfx/rect.h"
28 #include "ui/keyboard/keyboard_controller.h"
29 #include "ui/keyboard/keyboard_controller_observer.h"
30
31 namespace aura {
32 class RootWindow;
33 }
34
35 namespace ui {
36 class GestureEvent;
37 class ImplicitAnimationObserver;
38 }
39
40 namespace ash {
41 class ScreenAsh;
42 class ShelfLayoutManagerObserver;
43 class ShelfWidget;
44 FORWARD_DECLARE_TEST(WebNotificationTrayTest, PopupAndFullscreen);
45
46 namespace internal {
47
48 class PanelLayoutManagerTest;
49 class ShelfBezelEventFilter;
50 class ShelfLayoutManagerTest;
51 class StatusAreaWidget;
52 class WorkspaceController;
53
54 // ShelfLayoutManager is the layout manager responsible for the shelf and
55 // status widgets. The shelf is given the total available width and told the
56 // width of the status area. This allows the shelf to draw the background and
57 // layout to the status area.
58 // To respond to bounds changes in the status area StatusAreaLayoutManager works
59 // closely with ShelfLayoutManager.
60 class ASH_EXPORT ShelfLayoutManager :
61     public aura::LayoutManager,
62     public ash::ShellObserver,
63     public aura::client::ActivationChangeObserver,
64     public DockedWindowLayoutManagerObserver,
65     public keyboard::KeyboardControllerObserver,
66     public LockStateObserver {
67  public:
68
69   // We reserve a small area on the edge of the workspace area to ensure that
70   // the resize handle at the edge of the window can be hit.
71   static const int kWorkspaceAreaVisibleInset;
72
73   // When autohidden we extend the touch hit target onto the screen so that the
74   // user can drag the shelf out.
75   static const int kWorkspaceAreaAutoHideInset;
76
77   // Size of the shelf when auto-hidden.
78   static const int kAutoHideSize;
79
80   // The size of the shelf when shown (currently only used in alternate
81   // settings see ash::switches::UseAlternateShelfLayout).
82   static const int kShelfSize;
83
84   // Inset between the inner edge of the shelf (towards centre of screen), and
85   // the shelf items, notifications, status area etc.
86   static const int kShelfItemInset;
87
88   // Returns the preferred size for the shelf (either kShelfPreferredSize or
89   // kShelfSize).
90   static int GetPreferredShelfSize();
91
92   explicit ShelfLayoutManager(ShelfWidget* shelf);
93   virtual ~ShelfLayoutManager();
94
95   // Sets the ShelfAutoHideBehavior. See enum description for details.
96   void SetAutoHideBehavior(ShelfAutoHideBehavior behavior);
97   ShelfAutoHideBehavior auto_hide_behavior() const {
98     return auto_hide_behavior_;
99   }
100
101   // Sets the alignment. Returns true if the alignment is changed. Otherwise,
102   // returns false.
103   bool SetAlignment(ShelfAlignment alignment);
104   // Returns the desired alignment for the current state, either the user's
105   // set alignment (alignment_) or SHELF_ALIGNMENT_BOTTOM when the screen
106   // is locked.
107   ShelfAlignment GetAlignment() const;
108
109   void set_workspace_controller(WorkspaceController* controller) {
110     workspace_controller_ = controller;
111   }
112
113   bool updating_bounds() const { return updating_bounds_; }
114
115   // Clears internal data for shutdown process.
116   void PrepareForShutdown();
117
118   // Returns whether the shelf and its contents (shelf, status) are visible
119   // on the screen.
120   bool IsVisible() const;
121
122   // Returns the ideal bounds of the shelf assuming it is visible.
123   gfx::Rect GetIdealBounds();
124
125   // Returns the docked area bounds.
126   const gfx::Rect& dock_bounds() const { return dock_bounds_; }
127
128   // Stops any animations and sets the bounds of the shelf and status
129   // widgets.
130   void LayoutShelf();
131
132   // Returns shelf visibility state based on current value of auto hide
133   // behavior setting.
134   ShelfVisibilityState CalculateShelfVisibility();
135
136   // Updates the visibility state.
137   void UpdateVisibilityState();
138
139   // Invoked by the shelf when the auto-hide state may have changed.
140   void UpdateAutoHideState();
141
142   ShelfVisibilityState visibility_state() const {
143     return state_.visibility_state;
144   }
145   ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; }
146
147   ShelfWidget* shelf_widget() { return shelf_; }
148
149   // Sets whether any windows overlap the shelf. If a window overlaps the shelf
150   // the shelf renders slightly differently.
151   void SetWindowOverlapsShelf(bool value);
152   bool window_overlaps_shelf() const { return window_overlaps_shelf_; }
153
154   void AddObserver(ShelfLayoutManagerObserver* observer);
155   void RemoveObserver(ShelfLayoutManagerObserver* observer);
156
157   // Gesture dragging related functions:
158   void StartGestureDrag(const ui::GestureEvent& gesture);
159   enum DragState {
160     DRAG_SHELF,
161     DRAG_TRAY
162   };
163   // Returns DRAG_SHELF if the gesture should continue to drag the entire shelf.
164   // Returns DRAG_TRAY if the gesture can start dragging the tray-bubble from
165   // this point on.
166   DragState UpdateGestureDrag(const ui::GestureEvent& gesture);
167   void CompleteGestureDrag(const ui::GestureEvent& gesture);
168   void CancelGestureDrag();
169
170   // Overridden from aura::LayoutManager:
171   virtual void OnWindowResized() OVERRIDE;
172   virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
173   virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE;
174   virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE;
175   virtual void OnChildWindowVisibilityChanged(aura::Window* child,
176                                               bool visible) OVERRIDE;
177   virtual void SetChildBounds(aura::Window* child,
178                               const gfx::Rect& requested_bounds) OVERRIDE;
179
180   // Overridden from ash::ShellObserver:
181   virtual void OnLockStateChanged(bool locked) OVERRIDE;
182
183   // Overriden from aura::client::ActivationChangeObserver:
184   virtual void OnWindowActivated(aura::Window* gained_active,
185                                  aura::Window* lost_active) OVERRIDE;
186
187   // Overridden from ash::LockStateObserver:
188   virtual void OnLockStateEvent(LockStateObserver::EventType event) OVERRIDE;
189
190   // TODO(harrym|oshima): These templates will be moved to
191   // new Shelf class.
192   // A helper function that provides a shortcut for choosing
193   // values specific to a shelf alignment.
194   template<typename T>
195   T SelectValueForShelfAlignment(T bottom, T left, T right, T top) const {
196     switch (GetAlignment()) {
197       case SHELF_ALIGNMENT_BOTTOM:
198         return bottom;
199       case SHELF_ALIGNMENT_LEFT:
200         return left;
201       case SHELF_ALIGNMENT_RIGHT:
202         return right;
203       case SHELF_ALIGNMENT_TOP:
204         return top;
205     }
206     NOTREACHED();
207     return right;
208   }
209
210   template<typename T>
211   T PrimaryAxisValue(T horizontal, T vertical) const {
212     return IsHorizontalAlignment() ? horizontal : vertical;
213   }
214
215   // Is the shelf's alignment horizontal?
216   bool IsHorizontalAlignment() const;
217
218   // Returns a ShelfLayoutManager on the display which has a shelf for
219   // given |window|. See RootWindowController::ForShelf for more info.
220   static ShelfLayoutManager* ForShelf(aura::Window* window);
221
222  private:
223   class AutoHideEventFilter;
224   class UpdateShelfObserver;
225   friend class ash::ScreenAsh;
226   friend class PanelLayoutManagerTest;
227   friend class ShelfLayoutManagerTest;
228   FRIEND_TEST_ALL_PREFIXES(ash::WebNotificationTrayTest, PopupAndFullscreen);
229
230   struct TargetBounds {
231     TargetBounds();
232     ~TargetBounds();
233
234     float opacity;
235     float status_opacity;
236     gfx::Rect shelf_bounds_in_root;
237     gfx::Rect shelf_bounds_in_shelf;
238     gfx::Rect status_bounds_in_shelf;
239     gfx::Insets work_area_insets;
240   };
241
242   struct State {
243     State() : visibility_state(SHELF_VISIBLE),
244               auto_hide_state(SHELF_AUTO_HIDE_HIDDEN),
245               window_state(WORKSPACE_WINDOW_STATE_DEFAULT),
246               is_screen_locked(false) {}
247
248     // Returns true if the two states are considered equal. As
249     // |auto_hide_state| only matters if |visibility_state| is
250     // |SHELF_AUTO_HIDE|, Equals() ignores the |auto_hide_state| as
251     // appropriate.
252     bool Equals(const State& other) const {
253       return other.visibility_state == visibility_state &&
254           (visibility_state != SHELF_AUTO_HIDE ||
255            other.auto_hide_state == auto_hide_state) &&
256           other.window_state == window_state &&
257           other.is_screen_locked == is_screen_locked;
258     }
259
260     ShelfVisibilityState visibility_state;
261     ShelfAutoHideState auto_hide_state;
262     WorkspaceWindowState window_state;
263     bool is_screen_locked;
264   };
265
266   // Sets the visibility of the shelf to |state|.
267   void SetState(ShelfVisibilityState visibility_state);
268
269   // Updates the bounds and opacity of the shelf and status widgets.
270   // If |observer| is specified, it will be called back when the animations, if
271   // any, are complete.
272   void UpdateBoundsAndOpacity(const TargetBounds& target_bounds,
273                               bool animate,
274                               ui::ImplicitAnimationObserver* observer);
275
276   // Stops any animations and progresses them to the end.
277   void StopAnimating();
278
279   // Returns the width (if aligned to the side) or height (if aligned to the
280   // bottom).
281   void GetShelfSize(int* width, int* height);
282
283   // Insets |bounds| by |inset| on the edge the shelf is aligned to.
284   void AdjustBoundsBasedOnAlignment(int inset, gfx::Rect* bounds) const;
285
286   // Calculates the target bounds assuming visibility of |visible|.
287   void CalculateTargetBounds(const State& state, TargetBounds* target_bounds);
288
289   // Updates the target bounds if a gesture-drag is in progress. This is only
290   // used by |CalculateTargetBounds()|.
291   void UpdateTargetBoundsForGesture(TargetBounds* target_bounds) const;
292
293   // Updates the background of the shelf.
294   void UpdateShelfBackground(BackgroundAnimatorChangeType type);
295
296   // Returns how the shelf background is painted.
297   ShelfBackgroundType GetShelfBackgroundType() const;
298
299   // Updates the auto hide state immediately.
300   void UpdateAutoHideStateNow();
301
302   // Stops the auto hide timer and clears
303   // |mouse_over_shelf_when_auto_hide_timer_started_|.
304   void StopAutoHideTimer();
305
306   // Returns the bounds of an additional region which can trigger showing the
307   // shelf. This region exists to make it easier to trigger showing the shelf
308   // when the shelf is auto hidden and the shelf is on the boundary between
309   // two displays.
310   gfx::Rect GetAutoHideShowShelfRegionInScreen() const;
311
312   // Returns the AutoHideState. This value is determined from the shelf and
313   // tray.
314   ShelfAutoHideState CalculateAutoHideState(
315       ShelfVisibilityState visibility_state) const;
316
317   // Updates the hit test bounds override for shelf and status area.
318   // TODO(sad): Remove this (crbug.com/318879)
319   void UpdateHitTestBounds();
320
321   // Returns true if |window| is a descendant of the shelf.
322   bool IsShelfWindow(aura::Window* window);
323
324   int GetWorkAreaSize(const State& state, int size) const;
325
326   // Return the bounds available in the parent, taking into account the bounds
327   // of the keyboard if necessary.
328   gfx::Rect GetAvailableBounds() const;
329
330   // Overridden from keyboard::KeyboardControllerObserver:
331   virtual void OnKeyboardBoundsChanging(
332       const gfx::Rect& keyboard_bounds) OVERRIDE;
333
334   // Overridden from DockedWindowLayoutManagerObserver:
335   virtual void OnDockBoundsChanging(
336       const gfx::Rect& dock_bounds,
337       DockedWindowLayoutManagerObserver::Reason reason) OVERRIDE;
338
339   // Generates insets for inward edge based on the current shelf alignment.
340   // TODO(sad): Remove this (crbug.com/318879)
341   gfx::Insets GetInsetsForAlignment(int distance) const;
342
343   // The RootWindow is cached so that we don't invoke Shell::GetInstance() from
344   // our destructor. We avoid that as at the time we're deleted Shell is being
345   // deleted too.
346   aura::Window* root_window_;
347
348   // True when inside UpdateBoundsAndOpacity() method. Used to prevent calling
349   // UpdateBoundsAndOpacity() again from SetChildBounds().
350   bool updating_bounds_;
351
352   // See description above setter.
353   ShelfAutoHideBehavior auto_hide_behavior_;
354
355   // See description above getter.
356   ShelfAlignment alignment_;
357
358   // Current state.
359   State state_;
360
361   ShelfWidget* shelf_;
362
363   WorkspaceController* workspace_controller_;
364
365   // Do any windows overlap the shelf? This is maintained by WorkspaceManager.
366   bool window_overlaps_shelf_;
367
368   base::OneShotTimer<ShelfLayoutManager> auto_hide_timer_;
369
370   // Whether the mouse was over the shelf when the auto hide timer started.
371   // False when neither the auto hide timer nor the timer task are running.
372   bool mouse_over_shelf_when_auto_hide_timer_started_;
373
374   // EventFilter used to detect when user moves the mouse over the shelf to
375   // trigger showing the shelf.
376   scoped_ptr<AutoHideEventFilter> auto_hide_event_filter_;
377
378   // EventFilter used to detect when user issues a gesture on a bezel sensor.
379   scoped_ptr<ShelfBezelEventFilter> bezel_event_filter_;
380
381   ObserverList<ShelfLayoutManagerObserver> observers_;
382
383   // The shelf reacts to gesture-drags, and can be set to auto-hide for certain
384   // gestures. Some shelf behaviour (e.g. visibility state, background color
385   // etc.) are affected by various stages of the drag. The enum keeps track of
386   // the present status of the gesture drag.
387   enum GestureDragStatus {
388     GESTURE_DRAG_NONE,
389     GESTURE_DRAG_IN_PROGRESS,
390     GESTURE_DRAG_CANCEL_IN_PROGRESS,
391     GESTURE_DRAG_COMPLETE_IN_PROGRESS
392   };
393   GestureDragStatus gesture_drag_status_;
394
395   // Tracks the amount of the drag. The value is only valid when
396   // |gesture_drag_status_| is set to GESTURE_DRAG_IN_PROGRESS.
397   float gesture_drag_amount_;
398
399   // Manage the auto-hide state during the gesture.
400   ShelfAutoHideState gesture_drag_auto_hide_state_;
401
402   // Used to delay updating shelf background.
403   UpdateShelfObserver* update_shelf_observer_;
404
405   // The bounds of the keyboard.
406   gfx::Rect keyboard_bounds_;
407
408   // The bounds of the dock.
409   gfx::Rect dock_bounds_;
410
411   DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager);
412 };
413
414 }  // namespace internal
415 }  // namespace ash
416
417 #endif  // ASH_SHELF_SHELF_LAYOUT_MANAGER_H_