// Copyright 2016 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef ASH_SHELF_SHELF_H_ #define ASH_SHELF_SHELF_H_ #include #include "ash/ash_export.h" #include "ash/public/cpp/metrics_util.h" #include "ash/public/cpp/shelf_types.h" #include "ash/shelf/shelf_layout_manager_observer.h" #include "ash/shelf/shelf_locking_manager.h" #include "base/observer_list.h" namespace aura { class Window; } namespace gfx { class Rect; } namespace ui { class GestureEvent; class MouseWheelEvent; class MouseEvent; class ScrollEvent; } // namespace ui namespace ash { enum class AnimationChangeType; class HotseatWidget; class HotseatWidgetAnimationMetricsReporter; class NavigationWidgetAnimationMetricsReporter; class ShelfFocusCycler; class LoginShelfWidget; class ShelfLayoutManager; class ShelfLayoutManagerTest; class ShelfLockingManager; class ShelfNavigationWidget; class ShelfView; class ShelfWidget; class StatusAreaWidget; class ShelfObserver; class WorkAreaInsets; class ShelfTooltipManager; // TODO(oshima) : move to .cc // Returns a value based on shelf alignment. template T SelectValueByShelfAlignment(ShelfAlignment alignment, T bottom, T left, T right) { switch (alignment) { case ShelfAlignment::kBottom: case ShelfAlignment::kBottomLocked: return bottom; case ShelfAlignment::kLeft: return left; case ShelfAlignment::kRight: return right; } NOTREACHED(); return bottom; } bool IsHorizontalAlignment(ShelfAlignment alignment); // Returns |horizontal| if shelf is horizontal, otherwise |vertical|. template T PrimaryAxisValueByShelfAlignment(ShelfAlignment alignment, T horizontal, T vertical) { return IsHorizontalAlignment(alignment) ? horizontal : vertical; } // Controller for the shelf state. One per display, because each display might // have different shelf alignment, autohide, etc. Exists for the lifetime of the // root window controller. class ASH_EXPORT Shelf : public ShelfLayoutManagerObserver { public: // Used to maintain a lock for the auto-hide shelf. If lock, then we should // not update the state of the auto-hide shelf. class ScopedAutoHideLock { public: explicit ScopedAutoHideLock(Shelf* shelf) : shelf_(shelf) { ++shelf_->auto_hide_lock_; } ~ScopedAutoHideLock() { --shelf_->auto_hide_lock_; DCHECK_GE(shelf_->auto_hide_lock_, 0); } private: Shelf* shelf_; }; Shelf(); Shelf(const Shelf&) = delete; Shelf& operator=(const Shelf&) = delete; ~Shelf() override; // Returns the shelf for the display that |window| is on. Note that the shelf // widget may not exist, or the shelf may not be visible. static Shelf* ForWindow(aura::Window* window); // Launch a 0-indexed shelf item in the shelf. A negative index launches the // last shelf item in the shelf. static void LaunchShelfItem(int item_index); // Activates the shelf item specified by the index in the list of shelf items. static void ActivateShelfItem(int item_index); // Activates the shelf item specified by the index in the list of shelf items // on the display identified by |display_id|. static void ActivateShelfItemOnDisplay(int item_index, int64_t display_id); // Updates the shelf visibility on all displays. This method exists for // historical reasons. If a display or shelf instance is available, prefer // Shelf::UpdateVisibilityState() below. static void UpdateShelfVisibility(); void CreateNavigationWidget(aura::Window* container); void CreateHotseatWidget(aura::Window* container); void CreateStatusAreaWidget(aura::Window* status_container); void CreateShelfWidget(aura::Window* root); // Begins shutdown of the ShelfWidget and all child widgets. void ShutdownShelfWidget(); // Resets `shelf_widget_`. void DestroyShelfWidget(); // Returns true if the shelf is visible. Shelf can be visible in 1) // SHELF_VISIBLE or 2) SHELF_AUTO_HIDE but in SHELF_AUTO_HIDE_SHOWN. See // details in ShelfLayoutManager::IsVisible. bool IsVisible() const; // Returns the window showing the shelf. const aura::Window* GetWindow() const; aura::Window* GetWindow(); void SetAlignment(ShelfAlignment alignment); // Returns true if the shelf alignment is horizontal (i.e. at the bottom). bool IsHorizontalAlignment() const; // Returns a value based on shelf alignment. template T SelectValueForShelfAlignment(T bottom, T left, T right) const { return SelectValueByShelfAlignment(alignment_, bottom, left, right); } // Returns |horizontal| if shelf is horizontal, otherwise |vertical|. template T PrimaryAxisValue(T horizontal, T vertical) const { return IsHorizontalAlignment() ? horizontal : vertical; } void SetAutoHideBehavior(ShelfAutoHideBehavior behavior); ShelfAutoHideState GetAutoHideState() const; // Invoke when the auto-hide state may have changed (for example, when the // system tray bubble opens it should force the shelf to be visible). void UpdateAutoHideState(); ShelfBackgroundType GetBackgroundType() const; void UpdateVisibilityState(); void MaybeUpdateShelfBackground(); ShelfVisibilityState GetVisibilityState() const; gfx::Rect GetShelfBoundsInScreen() const; // Returns the ideal bounds of the shelf assuming it is visible. gfx::Rect GetIdealBounds() const; // Returns the ideal bounds of the shelf, but in tablet mode always returns // the bounds of the in-app shelf. gfx::Rect GetIdealBoundsForWorkAreaCalculation(); // Returns the screen bounds of the item for the specified window. If there is // no item for the specified window an empty rect is returned. gfx::Rect GetScreenBoundsOfItemIconForWindow(aura::Window* window); // Handles a gesture |event| coming from a source outside the shelf widget // (e.g. the status area widget). Allows support for behaviors like toggling // auto-hide with a swipe, even if that gesture event hits another window. // Returns true if the event was handled. bool ProcessGestureEvent(const ui::GestureEvent& event); // Handles a mouse |event| coming from the Shelf. void ProcessMouseEvent(const ui::MouseEvent& event); // Handles a scroll |event| coming from the Shelf. void ProcessScrollEvent(ui::ScrollEvent* event); // Handles a mousewheel scroll event coming from the shelf. void ProcessMouseWheelEvent(ui::MouseWheelEvent* event); void AddObserver(ShelfObserver* observer); void RemoveObserver(ShelfObserver* observer); void NotifyShelfIconPositionsChanged(); StatusAreaWidget* GetStatusAreaWidget() const; // Get the anchor rect that the system tray bubble and the notification center // bubble will be anchored. // x() and y() designates anchor point, but width() and height() are dummy. // See also: BubbleDialogDelegateView::GetBubbleBounds() gfx::Rect GetSystemTrayAnchorRect() const; // Returns whether this shelf should be hidden on secondary display in a given // |state|. bool ShouldHideOnSecondaryDisplay(session_manager::SessionState state); void SetVirtualKeyboardBoundsForTesting(const gfx::Rect& bounds); ShelfLockingManager* GetShelfLockingManagerForTesting(); ShelfView* GetShelfViewForTesting(); ShelfLayoutManager* shelf_layout_manager() const { return shelf_layout_manager_; } // Getters for the various shelf components. ShelfWidget* shelf_widget() const { return shelf_widget_.get(); } ShelfNavigationWidget* navigation_widget() const { return navigation_widget_.get(); } HotseatWidget* hotseat_widget() const { return hotseat_widget_.get(); } StatusAreaWidget* status_area_widget() const { return status_area_widget_.get(); } LoginShelfWidget* login_shelf_widget() { return login_shelf_widget_.get(); } ShelfAlignment alignment() const { return alignment_; } ShelfAutoHideBehavior auto_hide_behavior() const { return auto_hide_behavior_; } ShelfAlignment stored_alignment() const { return shelf_locking_manager_.stored_alignment(); } ShelfFocusCycler* shelf_focus_cycler() { return shelf_focus_cycler_.get(); } void set_is_tablet_mode_animation_running(bool value) { is_tablet_mode_animation_running_ = value; } bool is_tablet_mode_animation_running() const { return is_tablet_mode_animation_running_; } int auto_hide_lock() const { return auto_hide_lock_; } ShelfTooltipManager* tooltip() { return tooltip_.get(); } // |target_state| is the hotseat state after hotseat transition animation. metrics_util::ReportCallback GetHotseatTransitionReportCallback( HotseatState target_state); metrics_util::ReportCallback GetTranslucentBackgroundReportCallback( HotseatState target_state); metrics_util::ReportCallback GetNavigationWidgetAnimationReportCallback( HotseatState target_hotseat_state); protected: // ShelfLayoutManagerObserver: void WillDeleteShelfLayoutManager() override; void WillChangeVisibilityState(ShelfVisibilityState new_state) override; void OnAutoHideStateChanged(ShelfAutoHideState new_state) override; void OnBackgroundUpdated(ShelfBackgroundType background_type, AnimationChangeType change_type) override; void OnHotseatStateChanged(HotseatState old_state, HotseatState new_state) override; void OnWorkAreaInsetsChanged() override; private: class AutoDimEventHandler; class AutoHideEventHandler; friend class DimShelfLayoutManagerTestBase; friend class ShelfLayoutManagerTest; // Uses Auto Dim Event Handler to update the shelf dim state. void DimShelf(); void UndimShelf(); bool HasDimShelfTimer(); // Returns work area insets object for the window with this shelf. WorkAreaInsets* GetWorkAreaInsets() const; // Layout manager for the shelf container window. Instances are constructed by // ShelfWidget and lifetimes are managed by the container windows themselves. ShelfLayoutManager* shelf_layout_manager_ = nullptr; // Pointers to shelf components. std::unique_ptr navigation_widget_; std::unique_ptr hotseat_widget_; std::unique_ptr status_area_widget_; // Null during display teardown, see WindowTreeHostManager::DeleteHost() and // RootWindowController::CloseAllChildWindows(). std::unique_ptr shelf_widget_; std::unique_ptr login_shelf_widget_; // These initial values hide the shelf until user preferences are available. ShelfAlignment alignment_ = ShelfAlignment::kBottomLocked; ShelfAutoHideBehavior auto_hide_behavior_ = ShelfAutoHideBehavior::kAlwaysHidden; // Sets shelf alignment to bottom during login and screen lock. ShelfLockingManager shelf_locking_manager_; base::ObserverList::Unchecked observers_; // Forwards mouse and gesture events to ShelfLayoutManager for auto-hide. std::unique_ptr auto_hide_event_handler_; // Forwards mouse and gesture events to ShelfLayoutManager for auto-dim. std::unique_ptr auto_dim_event_handler_; // Hands focus off to different parts of the shelf. std::unique_ptr shelf_focus_cycler_; // Animation metrics reporter for hotseat animations. Owned by the Shelf to // ensure it outlives the Hotseat Widget. std::unique_ptr hotseat_transition_metrics_reporter_; // Metrics reporter for animations of the traslucent background in the // hotseat. Owned by the Shelf to ensure it outlives the Hotseat Widget. std::unique_ptr translucent_background_metrics_reporter_; // Animation metrics reporter for navigation widget animations. Owned by the // Shelf to ensure it outlives the Navigation Widget. std::unique_ptr navigation_widget_metrics_reporter_; // True while the animation to enter or exit tablet mode is running. Sometimes // this value is true when the shelf movements are not actually animating // (animation value = 0.0). This is because this is set to true when we // enter/exit tablet mode but the animation is not started until a shelf // OnBoundsChanged is called because of tablet mode. Use this value to sync // the animation for HomeButton. bool is_tablet_mode_animation_running_ = false; // Used by ScopedAutoHideLock to maintain the state of the lock for auto-hide // shelf. int auto_hide_lock_ = 0; std::unique_ptr tooltip_; }; } // namespace ash #endif // ASH_SHELF_SHELF_H_