blob: 467fe1a7424ec67d4e63a143772613940d340e51 [file] [log] [blame]
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +00001// 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
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +01008#include <vector>
9
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000010#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"
Ben Murdochca12bfa2013-07-23 11:17:05 +010016#include "ash/wm/dock/docked_window_layout_manager_observer.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010017#include "ash/wm/workspace/workspace_types.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000018#include "base/basictypes.h"
19#include "base/compiler_specific.h"
20#include "base/logging.h"
21#include "base/observer_list.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010022#include "base/timer/timer.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000023#include "ui/aura/client/activation_change_observer.h"
24#include "ui/aura/layout_manager.h"
25#include "ui/gfx/insets.h"
26#include "ui/gfx/rect.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010027#include "ui/keyboard/keyboard_controller.h"
28#include "ui/keyboard/keyboard_controller_observer.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000029
30namespace aura {
31class RootWindow;
32}
33
34namespace ui {
35class GestureEvent;
36}
37
38namespace ash {
39class ScreenAsh;
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010040class ShelfLayoutManagerObserver;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000041class ShelfWidget;
42namespace internal {
43
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010044class PanelLayoutManagerTest;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010045class ShelfBezelEventFilter;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000046class ShelfLayoutManagerTest;
47class StatusAreaWidget;
48class WorkspaceController;
49
50// ShelfLayoutManager is the layout manager responsible for the launcher and
51// status widgets. The launcher is given the total available width and told the
52// width of the status area. This allows the launcher to draw the background and
53// layout to the status area.
54// To respond to bounds changes in the status area StatusAreaLayoutManager works
55// closely with ShelfLayoutManager.
56class ASH_EXPORT ShelfLayoutManager :
57 public aura::LayoutManager,
58 public ash::ShellObserver,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010059 public aura::client::ActivationChangeObserver,
Ben Murdochca12bfa2013-07-23 11:17:05 +010060 public DockedWindowLayoutManagerObserver,
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010061 public keyboard::KeyboardControllerObserver {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000062 public:
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010063
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010064 // We reserve a small area on the edge of the workspace area to ensure that
65 // the resize handle at the edge of the window can be hit.
66 static const int kWorkspaceAreaVisibleInset;
67
68 // When autohidden we extend the touch hit target onto the screen so that the
69 // user can drag the shelf out.
70 static const int kWorkspaceAreaAutoHideInset;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000071
72 // Size of the shelf when auto-hidden.
73 static const int kAutoHideSize;
74
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010075 // The size of the shelf when shown (currently only used in alternate
76 // settings see ash::switches::UseAlternateShelfLayout).
77 static const int kShelfSize;
78
Ben Murdochca12bfa2013-07-23 11:17:05 +010079 // Returns the preferred size for the shelf (either kLauncherPreferredSize or
80 // kShelfSize).
81 static int GetPreferredShelfSize();
82
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000083 explicit ShelfLayoutManager(ShelfWidget* shelf);
84 virtual ~ShelfLayoutManager();
85
86 // Sets the ShelfAutoHideBehavior. See enum description for details.
87 void SetAutoHideBehavior(ShelfAutoHideBehavior behavior);
88 ShelfAutoHideBehavior auto_hide_behavior() const {
89 return auto_hide_behavior_;
90 }
91
92 // Sets the alignment. Returns true if the alignment is changed. Otherwise,
93 // returns false.
94 bool SetAlignment(ShelfAlignment alignment);
95 ShelfAlignment GetAlignment() const { return alignment_; }
96
97 void set_workspace_controller(WorkspaceController* controller) {
98 workspace_controller_ = controller;
99 }
100
101 bool in_layout() const { return in_layout_; }
102
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100103 // Clears internal data for shutdown process.
104 void PrepareForShutdown();
105
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000106 // Returns whether the shelf and its contents (launcher, status) are visible
107 // on the screen.
108 bool IsVisible() const;
109
110 // Returns the ideal bounds of the shelf assuming it is visible.
111 gfx::Rect GetIdealBounds();
112
113 // Stops any animations and sets the bounds of the launcher and status
114 // widgets.
115 void LayoutShelf();
116
117 // Returns shelf visibility state based on current value of auto hide
118 // behavior setting.
119 ShelfVisibilityState CalculateShelfVisibility();
120
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000121 // Updates the visibility state.
122 void UpdateVisibilityState();
123
124 // Invoked by the shelf/launcher when the auto-hide state may have changed.
125 void UpdateAutoHideState();
126
127 ShelfVisibilityState visibility_state() const {
128 return state_.visibility_state;
129 }
130 ShelfAutoHideState auto_hide_state() const { return state_.auto_hide_state; }
131
132 ShelfWidget* shelf_widget() { return shelf_; }
133
134 // Sets whether any windows overlap the shelf. If a window overlaps the shelf
135 // the shelf renders slightly differently.
136 void SetWindowOverlapsShelf(bool value);
137 bool window_overlaps_shelf() const { return window_overlaps_shelf_; }
138
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100139 void AddObserver(ShelfLayoutManagerObserver* observer);
140 void RemoveObserver(ShelfLayoutManagerObserver* observer);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000141
142 // Gesture dragging related functions:
143 void StartGestureDrag(const ui::GestureEvent& gesture);
144 enum DragState {
145 DRAG_SHELF,
146 DRAG_TRAY
147 };
148 // Returns DRAG_SHELF if the gesture should continue to drag the entire shelf.
149 // Returns DRAG_TRAY if the gesture can start dragging the tray-bubble from
150 // this point on.
151 DragState UpdateGestureDrag(const ui::GestureEvent& gesture);
152 void CompleteGestureDrag(const ui::GestureEvent& gesture);
153 void CancelGestureDrag();
154
155 // Overridden from aura::LayoutManager:
156 virtual void OnWindowResized() OVERRIDE;
157 virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
158 virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE;
159 virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE;
160 virtual void OnChildWindowVisibilityChanged(aura::Window* child,
161 bool visible) OVERRIDE;
162 virtual void SetChildBounds(aura::Window* child,
163 const gfx::Rect& requested_bounds) OVERRIDE;
164
165 // Overridden from ash::ShellObserver:
166 virtual void OnLockStateChanged(bool locked) OVERRIDE;
167
168 // Overriden from aura::client::ActivationChangeObserver:
169 virtual void OnWindowActivated(aura::Window* gained_active,
170 aura::Window* lost_active) OVERRIDE;
171
172 // TODO(harrym|oshima): These templates will be moved to
173 // new Shelf class.
174 // A helper function that provides a shortcut for choosing
175 // values specific to a shelf alignment.
176 template<typename T>
177 T SelectValueForShelfAlignment(T bottom, T left, T right, T top) const {
178 switch (alignment_) {
179 case SHELF_ALIGNMENT_BOTTOM:
180 return bottom;
181 case SHELF_ALIGNMENT_LEFT:
182 return left;
183 case SHELF_ALIGNMENT_RIGHT:
184 return right;
185 case SHELF_ALIGNMENT_TOP:
186 return top;
187 }
188 NOTREACHED();
189 return right;
190 }
191
192 template<typename T>
193 T PrimaryAxisValue(T horizontal, T vertical) const {
194 return IsHorizontalAlignment() ? horizontal : vertical;
195 }
196
197 // Is the shelf's alignment horizontal?
198 bool IsHorizontalAlignment() const;
199
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100200 // Tests if the browser is currently in fullscreen mode with minimal
201 // Chrome. When minimal Chrome is present the shelf should be displayed.
202 bool FullscreenWithMinimalChrome() const;
203
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000204 // Returns a ShelfLayoutManager on the display which has a launcher for
205 // given |window|. See RootWindowController::ForLauncher for more info.
206 static ShelfLayoutManager* ForLauncher(aura::Window* window);
207
208 private:
209 class AutoHideEventFilter;
210 class UpdateShelfObserver;
211 friend class ash::ScreenAsh;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100212 friend class PanelLayoutManagerTest;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000213 friend class ShelfLayoutManagerTest;
214
215 struct TargetBounds {
216 TargetBounds();
217 ~TargetBounds();
218
219 float opacity;
Ben Murdocheb525c52013-07-10 11:40:50 +0100220 float status_opacity;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000221 gfx::Rect shelf_bounds_in_root;
222 gfx::Rect launcher_bounds_in_shelf;
223 gfx::Rect status_bounds_in_shelf;
224 gfx::Insets work_area_insets;
225 };
226
227 struct State {
228 State() : visibility_state(SHELF_VISIBLE),
229 auto_hide_state(SHELF_AUTO_HIDE_HIDDEN),
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100230 window_state(WORKSPACE_WINDOW_STATE_DEFAULT),
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000231 is_screen_locked(false) {}
232
233 // Returns true if the two states are considered equal. As
234 // |auto_hide_state| only matters if |visibility_state| is
235 // |SHELF_AUTO_HIDE|, Equals() ignores the |auto_hide_state| as
236 // appropriate.
237 bool Equals(const State& other) const {
238 return other.visibility_state == visibility_state &&
239 (visibility_state != SHELF_AUTO_HIDE ||
240 other.auto_hide_state == auto_hide_state) &&
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100241 other.window_state == window_state &&
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000242 other.is_screen_locked == is_screen_locked;
243 }
244
245 ShelfVisibilityState visibility_state;
246 ShelfAutoHideState auto_hide_state;
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100247 WorkspaceWindowState window_state;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000248 bool is_screen_locked;
249 };
250
251 // Sets the visibility of the shelf to |state|.
252 void SetState(ShelfVisibilityState visibility_state);
253
Ben Murdocheb525c52013-07-10 11:40:50 +0100254 // Stops any animations and progresses them to the end.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000255 void StopAnimating();
256
257 // Returns the width (if aligned to the side) or height (if aligned to the
258 // bottom).
259 void GetShelfSize(int* width, int* height);
260
261 // Insets |bounds| by |inset| on the edge the shelf is aligned to.
262 void AdjustBoundsBasedOnAlignment(int inset, gfx::Rect* bounds) const;
263
264 // Calculates the target bounds assuming visibility of |visible|.
265 void CalculateTargetBounds(const State& state, TargetBounds* target_bounds);
266
267 // Updates the target bounds if a gesture-drag is in progress. This is only
268 // used by |CalculateTargetBounds()|.
269 void UpdateTargetBoundsForGesture(TargetBounds* target_bounds) const;
270
271 // Updates the background of the shelf.
272 void UpdateShelfBackground(BackgroundAnimator::ChangeType type);
273
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100274 // Returns how the shelf background is painted.
275 ShelfBackgroundType GetShelfBackgroundType() const;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000276
277 // Updates the auto hide state immediately.
278 void UpdateAutoHideStateNow();
279
Ben Murdochbb1529c2013-08-08 10:24:53 +0100280 // Stops the auto hide timer and clears
281 // |mouse_over_shelf_when_auto_hide_timer_started_|.
282 void StopAutoHideTimer();
283
284 // Returns the bounds of an additional region which can trigger showing the
285 // shelf. This region exists to make it easier to trigger showing the shelf
286 // when the shelf is auto hidden and the shelf is on the boundary between
287 // two displays.
288 gfx::Rect GetAutoHideShowShelfRegionInScreen() const;
289
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000290 // Returns the AutoHideState. This value is determined from the launcher and
291 // tray.
292 ShelfAutoHideState CalculateAutoHideState(
293 ShelfVisibilityState visibility_state) const;
294
295 // Updates the hit test bounds override for launcher and status area.
296 void UpdateHitTestBounds();
297
298 // Returns true if |window| is a descendant of the shelf.
299 bool IsShelfWindow(aura::Window* window);
300
301 int GetWorkAreaSize(const State& state, int size) const;
302
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100303 // Return the bounds available in the parent, taking into account the bounds
304 // of the keyboard if necessary.
305 gfx::Rect GetAvailableBounds() const;
306
307 // Overridden from keyboard::KeyboardControllerObserver:
308 virtual void OnKeyboardBoundsChanging(
309 const gfx::Rect& keyboard_bounds) OVERRIDE;
310
Ben Murdochca12bfa2013-07-23 11:17:05 +0100311 // Overridden from dock::DockObserver:
312 virtual void OnDockBoundsChanging(const gfx::Rect& dock_bounds) OVERRIDE;
313
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100314 // Generates insets for inward edge based on the current shelf alignment.
315 gfx::Insets GetInsetsForAlignment(int distance) const;
316
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000317 // The RootWindow is cached so that we don't invoke Shell::GetInstance() from
318 // our destructor. We avoid that as at the time we're deleted Shell is being
319 // deleted too.
320 aura::RootWindow* root_window_;
321
322 // True when inside LayoutShelf method. Used to prevent calling LayoutShelf
323 // again from SetChildBounds().
324 bool in_layout_;
325
326 // See description above setter.
327 ShelfAutoHideBehavior auto_hide_behavior_;
328
329 ShelfAlignment alignment_;
330
331 // Current state.
332 State state_;
333
334 ShelfWidget* shelf_;
335
336 WorkspaceController* workspace_controller_;
337
338 // Do any windows overlap the shelf? This is maintained by WorkspaceManager.
339 bool window_overlaps_shelf_;
340
341 base::OneShotTimer<ShelfLayoutManager> auto_hide_timer_;
342
Ben Murdochbb1529c2013-08-08 10:24:53 +0100343 // Whether the mouse was over the shelf when the auto hide timer started.
344 // False when neither the auto hide timer nor the timer task are running.
345 bool mouse_over_shelf_when_auto_hide_timer_started_;
346
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000347 // EventFilter used to detect when user moves the mouse over the launcher to
348 // trigger showing the launcher.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100349 scoped_ptr<AutoHideEventFilter> auto_hide_event_filter_;
350
351 // EventFilter used to detect when user issues a gesture on a bezel sensor.
352 scoped_ptr<ShelfBezelEventFilter> bezel_event_filter_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000353
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +0100354 ObserverList<ShelfLayoutManagerObserver> observers_;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000355
356 // The shelf reacts to gesture-drags, and can be set to auto-hide for certain
357 // gestures. Some shelf behaviour (e.g. visibility state, background color
358 // etc.) are affected by various stages of the drag. The enum keeps track of
359 // the present status of the gesture drag.
360 enum GestureDragStatus {
361 GESTURE_DRAG_NONE,
362 GESTURE_DRAG_IN_PROGRESS,
363 GESTURE_DRAG_COMPLETE_IN_PROGRESS
364 };
365 GestureDragStatus gesture_drag_status_;
366
367 // Tracks the amount of the drag. The value is only valid when
368 // |gesture_drag_status_| is set to GESTURE_DRAG_IN_PROGRESS.
369 float gesture_drag_amount_;
370
371 // Manage the auto-hide state during the gesture.
372 ShelfAutoHideState gesture_drag_auto_hide_state_;
373
374 // Used to delay updating shelf background.
375 UpdateShelfObserver* update_shelf_observer_;
376
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100377 // The bounds of the keyboard.
378 gfx::Rect keyboard_bounds_;
379
Ben Murdochca12bfa2013-07-23 11:17:05 +0100380 // The bounds of the dock.
381 gfx::Rect dock_bounds_;
382
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000383 DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManager);
384};
385
386} // namespace internal
387} // namespace ash
388
389#endif // ASH_SHELF_SHELF_LAYOUT_MANAGER_H_