| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ASH_SHELF_HOME_BUTTON_H_ |
| #define ASH_SHELF_HOME_BUTTON_H_ |
| |
| #include <memory> |
| |
| #include "ash/app_list/app_list_metrics.h" |
| #include "ash/app_list/app_list_model_provider.h" |
| #include "ash/app_list/quick_app_access_model.h" |
| #include "ash/ash_export.h" |
| #include "ash/public/cpp/app_list/app_list_controller_observer.h" |
| #include "ash/public/cpp/shelf_config.h" |
| #include "ash/shelf/home_button_controller.h" |
| #include "ash/shelf/shelf_button_delegate.h" |
| #include "ash/shelf/shelf_control_button.h" |
| #include "ash/shell_observer.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/scoped_observation.h" |
| #include "ui/base/metadata/metadata_header_macros.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/transform.h" |
| #include "ui/views/view_targeter_delegate.h" |
| |
| namespace views { |
| class AnimationBuilder; |
| class CircleLayerDelegate; |
| class ImageButton; |
| class Label; |
| } // namespace views |
| |
| namespace ui { |
| class LayerOwner; |
| } |
| |
| namespace ash { |
| |
| class Shelf; |
| class ShelfButtonDelegate; |
| class ShelfNavigationWidget; |
| class Shell; |
| |
| // Button used for the AppList icon on the shelf. It opens the app list (in |
| // clamshell mode) or home screen (in tablet mode). Because the clamshell-mode |
| // app list appears like a dismissable overlay, the button is highlighted while |
| // the app list is open in clamshell mode. |
| // |
| // If Assistant is enabled, the button is filled in; long-pressing it will |
| // launch Assistant. |
| class ASH_EXPORT HomeButton : public ShelfControlButton, |
| public ShelfButtonDelegate, |
| public views::ViewTargeterDelegate, |
| public ShellObserver, |
| public ShelfConfig::Observer, |
| public AppListModelProvider::Observer, |
| public QuickAppAccessModel::Observer { |
| METADATA_HEADER(HomeButton, ShelfControlButton) |
| |
| public: |
| class ScopedNoClipRect { |
| public: |
| explicit ScopedNoClipRect(ShelfNavigationWidget* shelf_navigation_widget); |
| ScopedNoClipRect(const ScopedNoClipRect&) = delete; |
| ScopedNoClipRect& operator=(const ScopedNoClipRect&) = delete; |
| ~ScopedNoClipRect(); |
| |
| private: |
| const raw_ptr<ShelfNavigationWidget> shelf_navigation_widget_; |
| const gfx::Rect clip_rect_; |
| }; |
| |
| // An observer that can be used to track the nudge animation state. Currently |
| // used in testing. |
| class NudgeAnimationObserver : public base::CheckedObserver { |
| public: |
| NudgeAnimationObserver() = default; |
| NudgeAnimationObserver(const NudgeAnimationObserver&) = delete; |
| NudgeAnimationObserver& operator=(const NudgeAnimationObserver&) = delete; |
| ~NudgeAnimationObserver() override = default; |
| |
| // Called when the nudge animation is started/ended. |
| virtual void NudgeAnimationStarted(HomeButton* home_button) = 0; |
| virtual void NudgeAnimationEnded(HomeButton* home_button) = 0; |
| |
| // Called when the nudge label is animated to fully shown. |
| virtual void NudgeLabelShown(HomeButton* home_button) = 0; |
| }; |
| |
| explicit HomeButton(Shelf* shelf); |
| |
| HomeButton(const HomeButton&) = delete; |
| HomeButton& operator=(const HomeButton&) = delete; |
| |
| ~HomeButton() override; |
| |
| // views::View: |
| gfx::Size CalculatePreferredSize() const override; |
| void Layout(PassKey) override; |
| |
| // views::Button: |
| void OnGestureEvent(ui::GestureEvent* event) override; |
| std::u16string GetTooltipText(const gfx::Point& p) const override; |
| |
| // ShelfButtonDelegate: |
| void OnShelfButtonAboutToRequestFocusFromTabTraversal(ShelfButton* button, |
| bool reverse) override; |
| void ButtonPressed(views::Button* sender, |
| const ui::Event& event, |
| views::InkDrop* ink_drop) override; |
| |
| // ShelfConfig::Observer: |
| void OnShelfConfigUpdated() override; |
| |
| // Called when the availability of a long-press gesture may have changed, e.g. |
| // when Assistant becomes enabled. |
| void OnAssistantAvailabilityChanged(); |
| |
| // True if the app list is shown for the display containing this button. |
| bool IsShowingAppList() const; |
| |
| // Called when a locale change is detected. Updates the button tooltip and |
| // accessible name. |
| void HandleLocaleChange(); |
| |
| // Returns the display which contains this view. |
| int64_t GetDisplayId() const; |
| |
| // Clip rect of this view's widget will be removed during the life time of the |
| // returned ScopedNoClipRect. |
| [[nodiscard]] std::unique_ptr<ScopedNoClipRect> CreateScopedNoClipRect(); |
| |
| // Checks if the `nudge_label_` can be shown for the launcher nudge. |
| // NOTE: This must be called after `CreateNudgeLabel()`, where the |
| // `nudge_label_` is created. This is because whether the nudge can be shown |
| // depends on nudge_label_'s preferred size. |
| bool CanShowNudgeLabel() const; |
| |
| // Starts the launcher nudge animation. |
| void StartNudgeAnimation(); |
| |
| // Sets the button's "toggled" state - the button is toggled when the bubble |
| // launcher is shown. |
| void SetToggled(bool toggled); |
| |
| void AddNudgeAnimationObserverForTest(NudgeAnimationObserver* observer); |
| void RemoveNudgeAnimationObserverForTest(NudgeAnimationObserver* observer); |
| |
| views::View* expandable_container_for_test() const { |
| return expandable_container_; |
| } |
| |
| views::Label* nudge_label_for_test() const { return nudge_label_; } |
| |
| views::ImageButton* quick_app_button_for_test() const { |
| return quick_app_button_; |
| } |
| |
| protected: |
| // views::Button: |
| void OnThemeChanged() override; |
| |
| private: |
| class ButtonImageView; |
| |
| // Creates `nudge_label_` for launcher nudge. |
| void CreateNudgeLabel(); |
| |
| // Creates the `expandable_container_` which holds either the `nudge_label_` |
| // or the `quick_app_button_`. |
| void CreateExpandableContainer(); |
| |
| // Creates the `quick_app_button_` to be shown next to the home button. |
| void CreateQuickAppButton(); |
| |
| // Called when the quick app button is pressed. |
| void QuickAppButtonPressed(); |
| |
| // Animation functions for launcher nudge. |
| void AnimateNudgeRipple(views::AnimationBuilder& builder); |
| void AnimateNudgeBounce(views::AnimationBuilder& builder); |
| void AnimateNudgeLabelSlideIn(views::AnimationBuilder& builder); |
| void AnimateNudgeLabelSlideOut(); |
| void AnimateNudgeLabelFadeOut(); |
| |
| // Callbacks for the nudge animation. |
| void OnNudgeAnimationStarted(); |
| void OnNudgeAnimationEnded(); |
| void OnLabelSlideInAnimationEnded(); |
| void OnLabelFadeOutAnimationEnded(); |
| |
| // Removes the nudge label from the view hierarchy. |
| void RemoveNudgeLabel(); |
| |
| // Removes the quick app button from the view hierarchy. |
| void RemoveQuickAppButton(); |
| |
| // views::ViewTargeterDelegate: |
| bool DoesIntersectRect(const views::View* target, |
| const gfx::Rect& rect) const override; |
| |
| // ShellObserver: |
| void OnShellDestroying() override; |
| |
| // AppListModelProvider::Observer: |
| void OnActiveAppListModelsChanged(AppListModel* model, |
| SearchModel* search_model) override; |
| |
| // QuickAppAccessModel::Observer: |
| void OnQuickAppShouldShowChanged(bool quick_app_shown) override; |
| void OnQuickAppIconChanged() override; |
| |
| // Create and animate in the quick app button from behind the home button. |
| void AnimateQuickAppButtonIn(); |
| |
| // Animate out the quick app button, deleting the quick app button when |
| // completed. |
| void AnimateQuickAppButtonOut(); |
| |
| // Callback for the quick app button slide out animation. |
| void OnQuickAppButtonSlideOutDone(); |
| |
| // Returns a transform which will translate the child of the |
| // `expandable_container` to be placed behind the home button. |
| gfx::Transform GetTransformForContainerChildBehindHomeButton(); |
| |
| // Returns a clip rect which will clip the `expandable_container` to the |
| // bounds of the home button. |
| gfx::Rect GetExpandableContainerClipRectToHomeButton(); |
| |
| const bool jelly_enabled_; |
| |
| base::ScopedObservation<QuickAppAccessModel, QuickAppAccessModel::Observer> |
| quick_app_model_observation_{this}; |
| |
| base::ScopedObservation<Shell, ShellObserver> shell_observation_{this}; |
| |
| base::ScopedObservation<AppListModelProvider, AppListModelProvider::Observer> |
| app_list_model_observation_{this}; |
| |
| const raw_ptr<Shelf> shelf_; |
| |
| // The view that paints the home button content. In its own view to ensure |
| // the background is stacked above `expandable_container_`. |
| raw_ptr<ButtonImageView> button_image_view_ = nullptr; |
| |
| // The container of `nudge_label_` or `quick_app_button_`. This is also |
| // responsible for painting the background of the contents. This container can |
| // expand visually by animation. |
| raw_ptr<views::View> expandable_container_ = nullptr; |
| |
| // The app button which is shown next to the home button. Only shown when |
| // set by SetQuickApp(). |
| raw_ptr<views::ImageButton> quick_app_button_ = nullptr; |
| |
| // The controller used to determine the button's behavior. |
| HomeButtonController controller_; |
| |
| // The delegate used by |nudge_ripple_layer_|. Only exists during the |
| // nudge animation. |
| std::unique_ptr<views::CircleLayerDelegate> ripple_layer_delegate_; |
| |
| // The ripple layer in the launcher nudge animation. Only exists during the |
| // nudge animation. |
| ui::LayerOwner nudge_ripple_layer_; |
| |
| // The label view and for launcher nudge animation. |
| raw_ptr<views::Label> nudge_label_ = nullptr; |
| |
| // The timer that counts down to hide the nudge_label_ from showing state. |
| base::OneShotTimer label_nudge_timer_; |
| |
| std::unique_ptr<ScopedNoClipRect> scoped_no_clip_rect_; |
| |
| base::ObserverList<NudgeAnimationObserver> observers_; |
| |
| base::WeakPtrFactory<HomeButton> weak_ptr_factory_{this}; |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_SHELF_HOME_BUTTON_H_ |