| 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 |