OLD | NEW |
| (Empty) |
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_WM_SHELF_LAYOUT_MANAGER_H_ | |
6 #define ASH_WM_SHELF_LAYOUT_MANAGER_H_ | |
7 | |
8 #include "ash/ash_export.h" | |
9 #include "ash/launcher/launcher.h" | |
10 #include "ash/shelf_types.h" | |
11 #include "ash/shell_observer.h" | |
12 #include "base/basictypes.h" | |
13 #include "base/compiler_specific.h" | |
14 #include "base/logging.h" | |
15 #include "base/observer_list.h" | |
16 #include "base/timer.h" | |
17 #include "ui/aura/client/activation_change_observer.h" | |
18 #include "ui/aura/layout_manager.h" | |
19 #include "ui/gfx/insets.h" | |
20 #include "ui/gfx/rect.h" | |
21 | |
22 namespace aura { | |
23 class RootWindow; | |
24 } | |
25 | |
26 namespace ui { | |
27 class GestureEvent; | |
28 } | |
29 | |
30 namespace ash { | |
31 class ScreenAsh; | |
32 namespace internal { | |
33 | |
34 class ShelfLayoutManagerTest; | |
35 class StatusAreaWidget; | |
36 class WorkspaceController; | |
37 | |
38 // ShelfLayoutManager is the layout manager responsible for the launcher and | |
39 // status widgets. The launcher is given the total available width and told the | |
40 // width of the status area. This allows the launcher to draw the background and | |
41 // layout to the status area. | |
42 // To respond to bounds changes in the status area StatusAreaLayoutManager works | |
43 // closely with ShelfLayoutManager. | |
44 class ASH_EXPORT ShelfLayoutManager : | |
45 public aura::LayoutManager, | |
46 public ash::ShellObserver, | |
47 public aura::client::ActivationChangeObserver { | |
48 public: | |
49 class ASH_EXPORT Observer { | |
50 public: | |
51 // Called when the target ShelfLayoutManager will be deleted. | |
52 virtual void WillDeleteShelf() {} | |
53 | |
54 // Called when the visibility change is scheduled. | |
55 virtual void WillChangeVisibilityState(ShelfVisibilityState new_state) {} | |
56 | |
57 // Called when the auto hide state is changed. | |
58 virtual void OnAutoHideStateChanged(ShelfAutoHideState new_state) {} | |
59 }; | |
60 | |
61 // We reserve a small area at the bottom of the workspace area to ensure that | |
62 // the bottom-of-window resize handle can be hit. | |
63 static const int kWorkspaceAreaBottomInset; | |
64 | |
65 // Size of the shelf when auto-hidden. | |
66 static const int kAutoHideSize; | |
67 | |
68 explicit ShelfLayoutManager(StatusAreaWidget* status); | |
69 virtual ~ShelfLayoutManager(); | |
70 | |
71 // Sets the ShelfAutoHideBehavior. See enum description for details. | |
72 void SetAutoHideBehavior(ShelfAutoHideBehavior behavior); | |
73 ShelfAutoHideBehavior auto_hide_behavior() const { | |
74 return auto_hide_behavior_; | |
75 } | |
76 | |
77 // Sets the alignment. Returns true if the alignment is changed. Otherwise, | |
78 // returns false. | |
79 bool SetAlignment(ShelfAlignment alignment); | |
80 ShelfAlignment GetAlignment() const { return alignment_; } | |
81 | |
82 void set_workspace_controller(WorkspaceController* controller) { | |
83 workspace_controller_ = controller; | |
84 } | |
85 | |
86 views::Widget* launcher_widget() { | |
87 return launcher_ ? launcher_->widget() : NULL; | |
88 } | |
89 const views::Widget* launcher_widget() const { | |
90 return launcher_ ? launcher_->widget() : NULL; | |
91 } | |
92 StatusAreaWidget* status_area_widget() { return status_area_widget_; } | |
93 | |
94 bool in_layout() const { return in_layout_; } | |
95 | |
96 // Returns whether the shelf and its contents (launcher, status) are visible | |
97 // on the screen. | |
98 bool IsVisible() const; | |
99 | |
100 // The launcher is typically created after the layout manager. | |
101 void SetLauncher(Launcher* launcher); | |
102 Launcher* launcher() { return launcher_; } | |
103 | |
104 // Returns the ideal bounds of the shelf assuming it is visible. | |
105 gfx::Rect GetIdealBounds(); | |
106 | |
107 // Stops any animations and sets the bounds of the launcher and status | |
108 // widgets. | |
109 void LayoutShelf(); | |
110 | |
111 // Returns shelf visibility state based on current value of auto hide | |
112 // behavior setting. | |
113 ShelfVisibilityState CalculateShelfVisibility(); | |
114 | |
115 // Returns shelf visibility state based on current value of auto hide | |
116 // behavior setting. | |
117 ShelfVisibilityState CalculateShelfVisibilityWhileDragging(); | |
118 | |
119 // Updates the visibility state. | |
120 void UpdateVisibilityState(); | |
121 | |
122 // Invoked by the shelf/launcher when the auto-hide state may have changed. | |
123 void UpdateAutoHideState(); | |
124 | |
125 ShelfVisibilityState visibility_state() const { | |
126 return state_.visibility_state; | |
127 } | |
128 ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; } | |
129 | |
130 // Sets whether any windows overlap the shelf. If a window overlaps the shelf | |
131 // the shelf renders slightly differently. | |
132 void SetWindowOverlapsShelf(bool value); | |
133 bool window_overlaps_shelf() const { return window_overlaps_shelf_; } | |
134 | |
135 void AddObserver(Observer* observer); | |
136 void RemoveObserver(Observer* observer); | |
137 | |
138 // Gesture dragging related functions: | |
139 void StartGestureDrag(const ui::GestureEvent& gesture); | |
140 enum DragState { | |
141 DRAG_SHELF, | |
142 DRAG_TRAY | |
143 }; | |
144 // Returns DRAG_SHELF if the gesture should continue to drag the entire shelf. | |
145 // Returns DRAG_TRAY if the gesture can start dragging the tray-bubble from | |
146 // this point on. | |
147 DragState UpdateGestureDrag(const ui::GestureEvent& gesture); | |
148 void CompleteGestureDrag(const ui::GestureEvent& gesture); | |
149 void CancelGestureDrag(); | |
150 | |
151 // Overridden from aura::LayoutManager: | |
152 virtual void OnWindowResized() OVERRIDE; | |
153 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE; | |
154 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE; | |
155 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE; | |
156 virtual void OnChildWindowVisibilityChanged(aura::Window* child, | |
157 bool visible) OVERRIDE; | |
158 virtual void SetChildBounds(aura::Window* child, | |
159 const gfx::Rect& requested_bounds) OVERRIDE; | |
160 | |
161 // Overridden from ash::ShellObserver: | |
162 virtual void OnLockStateChanged(bool locked) OVERRIDE; | |
163 | |
164 // Overriden from aura::client::ActivationChangeObserver: | |
165 virtual void OnWindowActivated(aura::Window* gained_active, | |
166 aura::Window* lost_active) OVERRIDE; | |
167 | |
168 // TODO(harrym|oshima): These templates will be moved to | |
169 // new Shelf class. | |
170 // A helper function that provides a shortcut for choosing | |
171 // values specific to a shelf alignment. | |
172 template<typename T> | |
173 T SelectValueForShelfAlignment(T bottom, T left, T right, T top) const { | |
174 switch (alignment_) { | |
175 case SHELF_ALIGNMENT_BOTTOM: | |
176 return bottom; | |
177 case SHELF_ALIGNMENT_LEFT: | |
178 return left; | |
179 case SHELF_ALIGNMENT_RIGHT: | |
180 return right; | |
181 case SHELF_ALIGNMENT_TOP: | |
182 return top; | |
183 } | |
184 NOTREACHED(); | |
185 return right; | |
186 } | |
187 | |
188 template<typename T> | |
189 T PrimaryAxisValue(T horizontal, T vertical) const { | |
190 return IsHorizontalAlignment() ? horizontal : vertical; | |
191 } | |
192 | |
193 // Is the shelf's alignment horizontal? | |
194 bool IsHorizontalAlignment() const; | |
195 | |
196 // Returns a ShelfLayoutManager on the display which has a launcher for | |
197 // given |window|. See RootWindowController::ForLauncher for more info. | |
198 static ShelfLayoutManager* ForLauncher(aura::Window* window); | |
199 | |
200 private: | |
201 class AutoHideEventFilter; | |
202 class UpdateShelfObserver; | |
203 friend class ash::ScreenAsh; | |
204 friend class ShelfLayoutManagerTest; | |
205 | |
206 struct TargetBounds { | |
207 TargetBounds(); | |
208 | |
209 float opacity; | |
210 gfx::Rect launcher_bounds_in_root; | |
211 gfx::Rect status_bounds_in_root; | |
212 gfx::Insets work_area_insets; | |
213 }; | |
214 | |
215 struct State { | |
216 State() : visibility_state(SHELF_VISIBLE), | |
217 auto_hide_state(SHELF_AUTO_HIDE_HIDDEN), | |
218 is_screen_locked(false) {} | |
219 | |
220 // Returns true if the two states are considered equal. As | |
221 // |auto_hide_state| only matters if |visibility_state| is | |
222 // |SHELF_AUTO_HIDE|, Equals() ignores the |auto_hide_state| as | |
223 // appropriate. | |
224 bool Equals(const State& other) const { | |
225 return other.visibility_state == visibility_state && | |
226 (visibility_state != SHELF_AUTO_HIDE || | |
227 other.auto_hide_state == auto_hide_state) && | |
228 other.is_screen_locked == is_screen_locked; | |
229 } | |
230 | |
231 ShelfVisibilityState visibility_state; | |
232 ShelfAutoHideState auto_hide_state; | |
233 bool is_screen_locked; | |
234 }; | |
235 | |
236 // Sets the visibility of the shelf to |state|. | |
237 void SetState(ShelfVisibilityState visibility_state); | |
238 | |
239 // Stops any animations. | |
240 void StopAnimating(); | |
241 | |
242 // Returns the width (if aligned to the side) or height (if aligned to the | |
243 // bottom). | |
244 void GetShelfSize(int* width, int* height); | |
245 | |
246 // Insets |bounds| by |inset| on the edge the shelf is aligned to. | |
247 void AdjustBoundsBasedOnAlignment(int inset, gfx::Rect* bounds) const; | |
248 | |
249 // Calculates the target bounds assuming visibility of |visible|. | |
250 void CalculateTargetBounds(const State& state, TargetBounds* target_bounds); | |
251 | |
252 // Updates the target bounds if a gesture-drag is in progress. This is only | |
253 // used by |CalculateTargetBounds()|. | |
254 void UpdateTargetBoundsForGesture(TargetBounds* target_bounds) const; | |
255 | |
256 // Updates the background of the shelf. | |
257 void UpdateShelfBackground(BackgroundAnimator::ChangeType type); | |
258 | |
259 // Returns whether the launcher should draw a background. | |
260 bool GetLauncherPaintsBackground() const; | |
261 | |
262 // Updates the auto hide state immediately. | |
263 void UpdateAutoHideStateNow(); | |
264 | |
265 // Returns the AutoHideState. This value is determined from the launcher and | |
266 // tray. | |
267 ShelfAutoHideState CalculateAutoHideState( | |
268 ShelfVisibilityState visibility_state) const; | |
269 | |
270 // Updates the hit test bounds override for launcher and status area. | |
271 void UpdateHitTestBounds(); | |
272 | |
273 // Returns true if |window| is a descendant of the shelf. | |
274 bool IsShelfWindow(aura::Window* window); | |
275 | |
276 int GetWorkAreaSize(const State& state, int size) const; | |
277 | |
278 // The RootWindow is cached so that we don't invoke Shell::GetInstance() from | |
279 // our destructor. We avoid that as at the time we're deleted Shell is being | |
280 // deleted too. | |
281 aura::RootWindow* root_window_; | |
282 | |
283 // True when inside LayoutShelf method. Used to prevent calling LayoutShelf | |
284 // again from SetChildBounds(). | |
285 bool in_layout_; | |
286 | |
287 // See description above setter. | |
288 ShelfAutoHideBehavior auto_hide_behavior_; | |
289 | |
290 ShelfAlignment alignment_; | |
291 | |
292 // Current state. | |
293 State state_; | |
294 | |
295 Launcher* launcher_; | |
296 StatusAreaWidget* status_area_widget_; | |
297 | |
298 WorkspaceController* workspace_controller_; | |
299 | |
300 // Do any windows overlap the shelf? This is maintained by WorkspaceManager. | |
301 bool window_overlaps_shelf_; | |
302 | |
303 base::OneShotTimer<ShelfLayoutManager> auto_hide_timer_; | |
304 | |
305 // EventFilter used to detect when user moves the mouse over the launcher to | |
306 // trigger showing the launcher. | |
307 scoped_ptr<AutoHideEventFilter> event_filter_; | |
308 | |
309 ObserverList<Observer> observers_; | |
310 | |
311 // The shelf reacts to gesture-drags, and can be set to auto-hide for certain | |
312 // gestures. Some shelf behaviour (e.g. visibility state, background color | |
313 // etc.) are affected by various stages of the drag. The enum keeps track of | |
314 // the present status of the gesture drag. | |
315 enum GestureDragStatus { | |
316 GESTURE_DRAG_NONE, | |
317 GESTURE_DRAG_IN_PROGRESS, | |
318 GESTURE_DRAG_COMPLETE_IN_PROGRESS | |
319 }; | |
320 GestureDragStatus gesture_drag_status_; | |
321 | |
322 // Tracks the amount of the drag. The value is only valid when | |
323 // |gesture_drag_status_| is set to GESTURE_DRAG_IN_PROGRESS. | |
324 float gesture_drag_amount_; | |
325 | |
326 // Manage the auto-hide state during the gesture. | |
327 ShelfAutoHideState gesture_drag_auto_hide_state_; | |
328 | |
329 // Used to delay updating shelf background. | |
330 UpdateShelfObserver* update_shelf_observer_; | |
331 | |
332 DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager); | |
333 }; | |
334 | |
335 } // namespace internal | |
336 } // namespace ash | |
337 | |
338 #endif // ASH_WM_SHELF_LAYOUT_MANAGER_H_ | |
OLD | NEW |