1 // Copyright 2016 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_H_ 6 #define ASH_SHELF_SHELF_H_ 7 8 #include <memory> 9 10 #include "ash/ash_export.h" 11 #include "ash/public/cpp/metrics_util.h" 12 #include "ash/public/cpp/shelf_types.h" 13 #include "ash/shelf/shelf_layout_manager_observer.h" 14 #include "ash/shelf/shelf_locking_manager.h" 15 #include "base/observer_list.h" 16 17 namespace aura { 18 class Window; 19 } 20 21 namespace gfx { 22 class Rect; 23 } 24 25 namespace ui { 26 class GestureEvent; 27 class MouseWheelEvent; 28 class MouseEvent; 29 class ScrollEvent; 30 } // namespace ui 31 32 namespace ash { 33 34 enum class AnimationChangeType; 35 class HotseatWidget; 36 class HotseatWidgetAnimationMetricsReporter; 37 class NavigationWidgetAnimationMetricsReporter; 38 class ShelfFocusCycler; 39 class ShelfLayoutManager; 40 class ShelfLayoutManagerTest; 41 class ShelfLockingManager; 42 class ShelfNavigationWidget; 43 class ShelfView; 44 class ShelfWidget; 45 class StatusAreaWidget; 46 class ShelfObserver; 47 class TrayBackgroundView; 48 class WorkAreaInsets; 49 class ShelfTooltipManager; 50 51 // Controller for the shelf state. One per display, because each display might 52 // have different shelf alignment, autohide, etc. Exists for the lifetime of the 53 // root window controller. 54 class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver { 55 public: 56 // Used to maintain a lock for the auto-hide shelf. If lock, then we should 57 // not update the state of the auto-hide shelf. 58 class ScopedAutoHideLock { 59 public: ScopedAutoHideLock(Shelf * shelf)60 explicit ScopedAutoHideLock(Shelf* shelf) : shelf_(shelf) { 61 ++shelf_->auto_hide_lock_; 62 } ~ScopedAutoHideLock()63 ~ScopedAutoHideLock() { 64 --shelf_->auto_hide_lock_; 65 DCHECK_GE(shelf_->auto_hide_lock_, 0); 66 } 67 68 private: 69 Shelf* shelf_; 70 }; 71 72 Shelf(); 73 ~Shelf() override; 74 75 // Returns the shelf for the display that |window| is on. Note that the shelf 76 // widget may not exist, or the shelf may not be visible. 77 static Shelf* ForWindow(aura::Window* window); 78 79 // Launch a 0-indexed shelf item in the shelf. A negative index launches the 80 // last shelf item in the shelf. 81 static void LaunchShelfItem(int item_index); 82 83 // Activates the shelf item specified by the index in the list of shelf items. 84 static void ActivateShelfItem(int item_index); 85 86 // Activates the shelf item specified by the index in the list of shelf items 87 // on the display identified by |display_id|. 88 static void ActivateShelfItemOnDisplay(int item_index, int64_t display_id); 89 90 void CreateNavigationWidget(aura::Window* container); 91 void CreateHotseatWidget(aura::Window* container); 92 void CreateStatusAreaWidget(aura::Window* status_container); 93 void CreateShelfWidget(aura::Window* root); 94 void ShutdownShelfWidget(); 95 void DestroyShelfWidget(); 96 97 // Returns true if the shelf is visible. Shelf can be visible in 1) 98 // SHELF_VISIBLE or 2) SHELF_AUTO_HIDE but in SHELF_AUTO_HIDE_SHOWN. See 99 // details in ShelfLayoutManager::IsVisible. 100 bool IsVisible() const; 101 102 // Returns the window showing the shelf. 103 const aura::Window* GetWindow() const; 104 aura::Window* GetWindow(); 105 106 void SetAlignment(ShelfAlignment alignment); 107 108 // Returns true if the shelf alignment is horizontal (i.e. at the bottom). 109 bool IsHorizontalAlignment() const; 110 111 // Returns a value based on shelf alignment. 112 template <typename T> SelectValueForShelfAlignment(T bottom,T left,T right)113 T SelectValueForShelfAlignment(T bottom, T left, T right) const { 114 switch (alignment_) { 115 case ShelfAlignment::kBottom: 116 case ShelfAlignment::kBottomLocked: 117 return bottom; 118 case ShelfAlignment::kLeft: 119 return left; 120 case ShelfAlignment::kRight: 121 return right; 122 } 123 NOTREACHED(); 124 return bottom; 125 } 126 127 // Returns |horizontal| if shelf is horizontal, otherwise |vertical|. 128 template <typename T> PrimaryAxisValue(T horizontal,T vertical)129 T PrimaryAxisValue(T horizontal, T vertical) const { 130 return IsHorizontalAlignment() ? horizontal : vertical; 131 } 132 133 void SetAutoHideBehavior(ShelfAutoHideBehavior behavior); 134 135 ShelfAutoHideState GetAutoHideState() const; 136 137 // Invoke when the auto-hide state may have changed (for example, when the 138 // system tray bubble opens it should force the shelf to be visible). 139 void UpdateAutoHideState(); 140 141 ShelfBackgroundType GetBackgroundType() const; 142 143 void UpdateVisibilityState(); 144 145 void MaybeUpdateShelfBackground(); 146 147 ShelfVisibilityState GetVisibilityState() const; 148 149 gfx::Rect GetShelfBoundsInScreen() const; 150 151 // Returns the ideal bounds of the shelf assuming it is visible. 152 gfx::Rect GetIdealBounds() const; 153 154 // Returns the ideal bounds of the shelf, but in tablet mode always returns 155 // the bounds of the in-app shelf. 156 gfx::Rect GetIdealBoundsForWorkAreaCalculation(); 157 158 // Returns the screen bounds of the item for the specified window. If there is 159 // no item for the specified window an empty rect is returned. 160 gfx::Rect GetScreenBoundsOfItemIconForWindow(aura::Window* window); 161 162 // Handles a gesture |event| coming from a source outside the shelf widget 163 // (e.g. the status area widget). Allows support for behaviors like toggling 164 // auto-hide with a swipe, even if that gesture event hits another window. 165 // Returns true if the event was handled. 166 bool ProcessGestureEvent(const ui::GestureEvent& event); 167 168 // Handles a mouse |event| coming from the Shelf. 169 void ProcessMouseEvent(const ui::MouseEvent& event); 170 171 // Handles a scroll |event| coming from the Shelf. 172 void ProcessScrollEvent(ui::ScrollEvent* event); 173 174 // Handles a mousewheel scroll event coming from the shelf. We use 175 // |from_touchpad| to distinguish if an event originated from a touchpad 176 // scroll or a mousewheel scroll. 177 void ProcessMouseWheelEvent(ui::MouseWheelEvent* event, bool from_touchpad); 178 179 void AddObserver(ShelfObserver* observer); 180 void RemoveObserver(ShelfObserver* observer); 181 182 void NotifyShelfIconPositionsChanged(); 183 StatusAreaWidget* GetStatusAreaWidget() const; 184 185 // Get the tray button that the system tray bubble and the notification center 186 // bubble will be anchored. See also: StatusAreaWidget::GetSystemTrayAnchor() 187 TrayBackgroundView* GetSystemTrayAnchorView() const; 188 189 // Get the anchor rect that the system tray bubble and the notification center 190 // bubble will be anchored. 191 // x() and y() designates anchor point, but width() and height() are dummy. 192 // See also: BubbleDialogDelegateView::GetBubbleBounds() 193 gfx::Rect GetSystemTrayAnchorRect() const; 194 195 // Returns whether this shelf should be hidden on secondary display in a given 196 // |state|. 197 bool ShouldHideOnSecondaryDisplay(session_manager::SessionState state); 198 199 void SetVirtualKeyboardBoundsForTesting(const gfx::Rect& bounds); 200 ShelfLockingManager* GetShelfLockingManagerForTesting(); 201 ShelfView* GetShelfViewForTesting(); 202 shelf_layout_manager()203 ShelfLayoutManager* shelf_layout_manager() const { 204 return shelf_layout_manager_; 205 } 206 207 // Getters for the various shelf components. shelf_widget()208 ShelfWidget* shelf_widget() const { return shelf_widget_.get(); } navigation_widget()209 ShelfNavigationWidget* navigation_widget() const { 210 return navigation_widget_.get(); 211 } hotseat_widget()212 HotseatWidget* hotseat_widget() const { return hotseat_widget_.get(); } status_area_widget()213 StatusAreaWidget* status_area_widget() const { 214 return status_area_widget_.get(); 215 } 216 alignment()217 ShelfAlignment alignment() const { return alignment_; } auto_hide_behavior()218 ShelfAutoHideBehavior auto_hide_behavior() const { 219 return auto_hide_behavior_; 220 } 221 shelf_focus_cycler()222 ShelfFocusCycler* shelf_focus_cycler() { return shelf_focus_cycler_.get(); } 223 set_is_tablet_mode_animation_running(bool value)224 void set_is_tablet_mode_animation_running(bool value) { 225 is_tablet_mode_animation_running_ = value; 226 } is_tablet_mode_animation_running()227 bool is_tablet_mode_animation_running() const { 228 return is_tablet_mode_animation_running_; 229 } auto_hide_lock()230 int auto_hide_lock() const { return auto_hide_lock_; } 231 tooltip()232 ShelfTooltipManager* tooltip() { return tooltip_.get(); } 233 234 // |target_state| is the hotseat state after hotseat transition animation. 235 metrics_util::ReportCallback GetHotseatTransitionReportCallback( 236 HotseatState target_state); 237 metrics_util::ReportCallback GetTranslucentBackgroundReportCallback( 238 HotseatState target_state); 239 240 metrics_util::ReportCallback GetNavigationWidgetAnimationReportCallback( 241 HotseatState target_hotseat_state); 242 243 protected: 244 // ShelfLayoutManagerObserver: 245 void WillDeleteShelfLayoutManager() override; 246 void WillChangeVisibilityState(ShelfVisibilityState new_state) override; 247 void OnAutoHideStateChanged(ShelfAutoHideState new_state) override; 248 void OnBackgroundUpdated(ShelfBackgroundType background_type, 249 AnimationChangeType change_type) override; 250 void OnHotseatStateChanged(HotseatState old_state, 251 HotseatState new_state) override; 252 void OnWorkAreaInsetsChanged() override; 253 254 private: 255 class AutoDimEventHandler; 256 class AutoHideEventHandler; 257 friend class DimShelfLayoutManagerTestBase; 258 friend class ShelfLayoutManagerTest; 259 260 // Uses Auto Dim Event Handler to update the shelf dim state. 261 void DimShelf(); 262 void UndimShelf(); 263 bool HasDimShelfTimer(); 264 265 // Returns work area insets object for the window with this shelf. 266 WorkAreaInsets* GetWorkAreaInsets() const; 267 268 // Layout manager for the shelf container window. Instances are constructed by 269 // ShelfWidget and lifetimes are managed by the container windows themselves. 270 ShelfLayoutManager* shelf_layout_manager_ = nullptr; 271 272 // Pointers to shelf components. 273 std::unique_ptr<ShelfNavigationWidget> navigation_widget_; 274 std::unique_ptr<HotseatWidget> hotseat_widget_; 275 std::unique_ptr<StatusAreaWidget> status_area_widget_; 276 // Null during display teardown, see WindowTreeHostManager::DeleteHost() and 277 // RootWindowController::CloseAllChildWindows(). 278 std::unique_ptr<ShelfWidget> shelf_widget_; 279 280 // These initial values hide the shelf until user preferences are available. 281 ShelfAlignment alignment_ = ShelfAlignment::kBottomLocked; 282 ShelfAutoHideBehavior auto_hide_behavior_ = 283 ShelfAutoHideBehavior::kAlwaysHidden; 284 285 // Sets shelf alignment to bottom during login and screen lock. 286 ShelfLockingManager shelf_locking_manager_; 287 288 base::ObserverList<ShelfObserver>::Unchecked observers_; 289 290 // Forwards mouse and gesture events to ShelfLayoutManager for auto-hide. 291 std::unique_ptr<AutoHideEventHandler> auto_hide_event_handler_; 292 293 // Forwards mouse and gesture events to ShelfLayoutManager for auto-dim. 294 std::unique_ptr<AutoDimEventHandler> auto_dim_event_handler_; 295 296 // Hands focus off to different parts of the shelf. 297 std::unique_ptr<ShelfFocusCycler> shelf_focus_cycler_; 298 299 // Animation metrics reporter for hotseat animations. Owned by the Shelf to 300 // ensure it outlives the Hotseat Widget. 301 std::unique_ptr<HotseatWidgetAnimationMetricsReporter> 302 hotseat_transition_metrics_reporter_; 303 304 // Metrics reporter for animations of the traslucent background in the 305 // hotseat. Owned by the Shelf to ensure it outlives the Hotseat Widget. 306 std::unique_ptr<HotseatWidgetAnimationMetricsReporter> 307 translucent_background_metrics_reporter_; 308 309 // Animation metrics reporter for navigation widget animations. Owned by the 310 // Shelf to ensure it outlives the Navigation Widget. 311 std::unique_ptr<NavigationWidgetAnimationMetricsReporter> 312 navigation_widget_metrics_reporter_; 313 314 // True while the animation to enter or exit tablet mode is running. Sometimes 315 // this value is true when the shelf movements are not actually animating 316 // (animation value = 0.0). This is because this is set to true when we 317 // enter/exit tablet mode but the animation is not started until a shelf 318 // OnBoundsChanged is called because of tablet mode. Use this value to sync 319 // the animation for HomeButton. 320 bool is_tablet_mode_animation_running_ = false; 321 322 // Used by ScopedAutoHideLock to maintain the state of the lock for auto-hide 323 // shelf. 324 int auto_hide_lock_ = 0; 325 326 std::unique_ptr<ShelfTooltipManager> tooltip_; 327 328 DISALLOW_COPY_AND_ASSIGN(Shelf); 329 }; 330 331 } // namespace ash 332 333 #endif // ASH_SHELF_SHELF_H_ 334