- add sources.
[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/launcher/launcher.h"
12 #include "ash/shelf/background_animator.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 launcher and
55 // status widgets. The launcher is given the total available width and told the
56 // width of the status area. This allows the launcher 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 launcher items, notifications, status area etc.
86   static const int kShelfItemInset;
87
88   // Returns the preferred size for the shelf (either kLauncherPreferredSize 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 (launcher, 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   // Stops any animations and sets the bounds of the launcher and status
126   // widgets.
127   void LayoutShelf();
128
129   // Returns shelf visibility state based on current value of auto hide
130   // behavior setting.
131   ShelfVisibilityState CalculateShelfVisibility();
132
133   // Updates the visibility state.
134   void UpdateVisibilityState();
135
136   // Invoked by the shelf/launcher when the auto-hide state may have changed.
137   void UpdateAutoHideState();
138
139   ShelfVisibilityState visibility_state() const {
140     return state_.visibility_state;
141   }
142   ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; }
143
144   ShelfWidget* shelf_widget() { return shelf_; }
145
146   // Sets whether any windows overlap the shelf. If a window overlaps the shelf
147   // the shelf renders slightly differently.
148   void SetWindowOverlapsShelf(bool value);
149   bool window_overlaps_shelf() const { return window_overlaps_shelf_; }
150
151   void AddObserver(ShelfLayoutManagerObserver* observer);
152   void RemoveObserver(ShelfLayoutManagerObserver* observer);
153
154   // Gesture dragging related functions:
155   void StartGestureDrag(const ui::GestureEvent& gesture);
156   enum DragState {
157     DRAG_SHELF,
158     DRAG_TRAY
159   };
160   // Returns DRAG_SHELF if the gesture should continue to drag the entire shelf.
161   // Returns DRAG_TRAY if the gesture can start dragging the tray-bubble from
162   // this point on.
163   DragState UpdateGestureDrag(const ui::GestureEvent& gesture);
164   void CompleteGestureDrag(const ui::GestureEvent& gesture);
165   void CancelGestureDrag();
166
167   // Overridden from aura::LayoutManager:
168   virtual void OnWindowResized() OVERRIDE;
169   virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
170   virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE;
171   virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE;
172   virtual void OnChildWindowVisibilityChanged(aura::Window* child,
173                                               bool visible) OVERRIDE;
174   virtual void SetChildBounds(aura::Window* child,
175                               const gfx::Rect& requested_bounds) OVERRIDE;
176
177   // Overridden from ash::ShellObserver:
178   virtual void OnLockStateChanged(bool locked) OVERRIDE;
179
180   // Overriden from aura::client::ActivationChangeObserver:
181   virtual void OnWindowActivated(aura::Window* gained_active,
182                                  aura::Window* lost_active) OVERRIDE;
183
184   // Overridden from ash::LockStateObserver:
185   virtual void OnLockStateEvent(LockStateObserver::EventType event) OVERRIDE;
186
187   // TODO(harrym|oshima): These templates will be moved to
188   // new Shelf class.
189   // A helper function that provides a shortcut for choosing
190   // values specific to a shelf alignment.
191   template<typename T>
192   T SelectValueForShelfAlignment(T bottom, T left, T right, T top) const {
193     switch (GetAlignment()) {
194       case SHELF_ALIGNMENT_BOTTOM:
195         return bottom;
196       case SHELF_ALIGNMENT_LEFT:
197         return left;
198       case SHELF_ALIGNMENT_RIGHT:
199         return right;
200       case SHELF_ALIGNMENT_TOP:
201         return top;
202     }
203     NOTREACHED();
204     return right;
205   }
206
207   template<typename T>
208   T PrimaryAxisValue(T horizontal, T vertical) const {
209     return IsHorizontalAlignment() ? horizontal : vertical;
210   }
211
212   // Is the shelf's alignment horizontal?
213   bool IsHorizontalAlignment() const;
214
215   // Returns true if there is a fullscreen window and the shelf needs to be
216   // hidden for the topmost fullscreen window.
217   bool FullscreenWithHiddenShelf() const;
218
219   // Returns a ShelfLayoutManager on the display which has a launcher for
220   // given |window|. See RootWindowController::ForLauncher for more info.
221   static ShelfLayoutManager* ForLauncher(aura::Window* window);
222
223  private:
224   class AutoHideEventFilter;
225   class UpdateShelfObserver;
226   friend class ash::ScreenAsh;
227   friend class PanelLayoutManagerTest;
228   friend class ShelfLayoutManagerTest;
229   FRIEND_TEST_ALL_PREFIXES(ash::WebNotificationTrayTest, PopupAndFullscreen);
230
231   struct TargetBounds {
232     TargetBounds();
233     ~TargetBounds();
234
235     float opacity;
236     float status_opacity;
237     gfx::Rect shelf_bounds_in_root;
238     gfx::Rect launcher_bounds_in_shelf;
239     gfx::Rect status_bounds_in_shelf;
240     gfx::Insets work_area_insets;
241   };
242
243   struct State {
244     State() : visibility_state(SHELF_VISIBLE),
245               auto_hide_state(SHELF_AUTO_HIDE_HIDDEN),
246               window_state(WORKSPACE_WINDOW_STATE_DEFAULT),
247               is_screen_locked(false) {}
248
249     // Returns true if the two states are considered equal. As
250     // |auto_hide_state| only matters if |visibility_state| is
251     // |SHELF_AUTO_HIDE|, Equals() ignores the |auto_hide_state| as
252     // appropriate.
253     bool Equals(const State& other) const {
254       return other.visibility_state == visibility_state &&
255           (visibility_state != SHELF_AUTO_HIDE ||
256            other.auto_hide_state == auto_hide_state) &&
257           other.window_state == window_state &&
258           other.is_screen_locked == is_screen_locked;
259     }
260
261     ShelfVisibilityState visibility_state;
262     ShelfAutoHideState auto_hide_state;
263     WorkspaceWindowState window_state;
264     bool is_screen_locked;
265   };
266
267   // Sets the visibility of the shelf to |state|.
268   void SetState(ShelfVisibilityState visibility_state);
269
270   // Updates the bounds and opacity of the launcher and status widgets.
271   // If |observer| is specified, it will be called back when the animations, if
272   // any, are complete.
273   void UpdateBoundsAndOpacity(const TargetBounds& target_bounds,
274                               bool animate,
275                               ui::ImplicitAnimationObserver* observer);
276
277   // Stops any animations and progresses them to the end.
278   void StopAnimating();
279
280   // Returns the width (if aligned to the side) or height (if aligned to the
281   // bottom).
282   void GetShelfSize(int* width, int* height);
283
284   // Insets |bounds| by |inset| on the edge the shelf is aligned to.
285   void AdjustBoundsBasedOnAlignment(int inset, gfx::Rect* bounds) const;
286
287   // Calculates the target bounds assuming visibility of |visible|.
288   void CalculateTargetBounds(const State& state, TargetBounds* target_bounds);
289
290   // Updates the target bounds if a gesture-drag is in progress. This is only
291   // used by |CalculateTargetBounds()|.
292   void UpdateTargetBoundsForGesture(TargetBounds* target_bounds) const;
293
294   // Updates the background of the shelf.
295   void UpdateShelfBackground(BackgroundAnimator::ChangeType type);
296
297   // Returns how the shelf background is painted.
298   ShelfBackgroundType GetShelfBackgroundType() const;
299
300   // Updates the auto hide state immediately.
301   void UpdateAutoHideStateNow();
302
303   // Stops the auto hide timer and clears
304   // |mouse_over_shelf_when_auto_hide_timer_started_|.
305   void StopAutoHideTimer();
306
307   // Returns the bounds of an additional region which can trigger showing the
308   // shelf. This region exists to make it easier to trigger showing the shelf
309   // when the shelf is auto hidden and the shelf is on the boundary between
310   // two displays.
311   gfx::Rect GetAutoHideShowShelfRegionInScreen() const;
312
313   // Returns the AutoHideState. This value is determined from the launcher and
314   // tray.
315   ShelfAutoHideState CalculateAutoHideState(
316       ShelfVisibilityState visibility_state) const;
317
318   // Updates the hit test bounds override for launcher and status area.
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 dock::DockObserver:
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   gfx::Insets GetInsetsForAlignment(int distance) const;
341
342   // The RootWindow is cached so that we don't invoke Shell::GetInstance() from
343   // our destructor. We avoid that as at the time we're deleted Shell is being
344   // deleted too.
345   aura::Window* root_window_;
346
347   // True when inside UpdateBoundsAndOpacity() method. Used to prevent calling
348   // UpdateBoundsAndOpacity() again from SetChildBounds().
349   bool updating_bounds_;
350
351   // See description above setter.
352   ShelfAutoHideBehavior auto_hide_behavior_;
353
354   // See description above getter.
355   ShelfAlignment alignment_;
356
357   // Current state.
358   State state_;
359
360   ShelfWidget* shelf_;
361
362   WorkspaceController* workspace_controller_;
363
364   // Do any windows overlap the shelf? This is maintained by WorkspaceManager.
365   bool window_overlaps_shelf_;
366
367   base::OneShotTimer<ShelfLayoutManager> auto_hide_timer_;
368
369   // Whether the mouse was over the shelf when the auto hide timer started.
370   // False when neither the auto hide timer nor the timer task are running.
371   bool mouse_over_shelf_when_auto_hide_timer_started_;
372
373   // EventFilter used to detect when user moves the mouse over the launcher to
374   // trigger showing the launcher.
375   scoped_ptr<AutoHideEventFilter> auto_hide_event_filter_;
376
377   // EventFilter used to detect when user issues a gesture on a bezel sensor.
378   scoped_ptr<ShelfBezelEventFilter> bezel_event_filter_;
379
380   ObserverList<ShelfLayoutManagerObserver> observers_;
381
382   // The shelf reacts to gesture-drags, and can be set to auto-hide for certain
383   // gestures. Some shelf behaviour (e.g. visibility state, background color
384   // etc.) are affected by various stages of the drag. The enum keeps track of
385   // the present status of the gesture drag.
386   enum GestureDragStatus {
387     GESTURE_DRAG_NONE,
388     GESTURE_DRAG_IN_PROGRESS,
389     GESTURE_DRAG_CANCEL_IN_PROGRESS,
390     GESTURE_DRAG_COMPLETE_IN_PROGRESS
391   };
392   GestureDragStatus gesture_drag_status_;
393
394   // Tracks the amount of the drag. The value is only valid when
395   // |gesture_drag_status_| is set to GESTURE_DRAG_IN_PROGRESS.
396   float gesture_drag_amount_;
397
398   // Manage the auto-hide state during the gesture.
399   ShelfAutoHideState gesture_drag_auto_hide_state_;
400
401   // Used to delay updating shelf background.
402   UpdateShelfObserver* update_shelf_observer_;
403
404   // The bounds of the keyboard.
405   gfx::Rect keyboard_bounds_;
406
407   // The bounds of the dock.
408   gfx::Rect dock_bounds_;
409
410   DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager);
411 };
412
413 }  // namespace internal
414 }  // namespace ash
415
416 #endif  // ASH_SHELF_SHELF_LAYOUT_MANAGER_H_