James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 1 | // Copyright 2014 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 | |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 5 | #ifndef ASH_SHELF_HOME_BUTTON_H_ |
| 6 | #define ASH_SHELF_HOME_BUTTON_H_ |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 7 | |
| 8 | #include <memory> |
| 9 | |
Manu Cornet | 1ed1f6b | 2019-06-14 17:25:53 | [diff] [blame] | 10 | #include "ash/app_list/app_list_metrics.h" |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 11 | #include "ash/ash_export.h" |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 12 | #include "ash/shelf/home_button_controller.h" |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 13 | #include "ash/shelf/shelf_button_delegate.h" |
Manu Cornet | 40f90812 | 2018-11-08 23:15:25 | [diff] [blame] | 14 | #include "ash/shelf/shelf_control_button.h" |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 15 | #include "ui/gfx/geometry/rect.h" |
Ahmed Mehfooz | 6509620f | 2019-05-21 20:35:12 | [diff] [blame] | 16 | #include "ui/views/view_targeter_delegate.h" |
xiaohuic | fb5c54fc | 2017-06-28 17:32:02 | [diff] [blame] | 17 | |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 18 | namespace views { |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 19 | class AnimationBuilder; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 20 | class CircleLayerDelegate; |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 21 | class Label; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 22 | } // namespace views |
| 23 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 24 | namespace ui { |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 25 | class LayerOwner; |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 26 | } |
| 27 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 28 | namespace ash { |
Sammie Quon | 9b911f2f | 2017-12-15 02:53:15 | [diff] [blame] | 29 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 30 | class Shelf; |
Alex Newcomer | 030e706 | 2019-07-02 00:03:57 | [diff] [blame] | 31 | class ShelfButtonDelegate; |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 32 | class ShelfNavigationWidget; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 33 | |
Michael Giuffrida | 01adeb07 | 2019-03-21 22:05:30 | [diff] [blame] | 34 | // Button used for the AppList icon on the shelf. It opens the app list (in |
| 35 | // clamshell mode) or home screen (in tablet mode). Because the clamshell-mode |
| 36 | // app list appears like a dismissable overlay, the button is highlighted while |
| 37 | // the app list is open in clamshell mode. |
| 38 | // |
| 39 | // If Assistant is enabled, the button is filled in; long-pressing it will |
| 40 | // launch Assistant. |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 41 | class ASH_EXPORT HomeButton : public ShelfControlButton, |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 42 | public ShelfButtonDelegate, |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 43 | public views::ViewTargeterDelegate { |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 44 | public: |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 45 | class ScopedNoClipRect { |
| 46 | public: |
| 47 | explicit ScopedNoClipRect(ShelfNavigationWidget* shelf_navigation_widget); |
| 48 | ScopedNoClipRect(const ScopedNoClipRect&) = delete; |
| 49 | ScopedNoClipRect& operator=(const ScopedNoClipRect&) = delete; |
| 50 | ~ScopedNoClipRect(); |
| 51 | |
| 52 | private: |
| 53 | ShelfNavigationWidget* const shelf_navigation_widget_; |
| 54 | const gfx::Rect clip_rect_; |
| 55 | }; |
| 56 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 57 | // An observer that can be used to track the nudge animation state. Currently |
| 58 | // used in testing. |
| 59 | class NudgeAnimationObserver : public base::CheckedObserver { |
| 60 | public: |
| 61 | NudgeAnimationObserver() = default; |
| 62 | NudgeAnimationObserver(const NudgeAnimationObserver&) = delete; |
| 63 | NudgeAnimationObserver& operator=(const NudgeAnimationObserver&) = delete; |
| 64 | ~NudgeAnimationObserver() override = default; |
| 65 | |
| 66 | // Called when the nudge animation is started/ended. |
| 67 | virtual void NudgeAnimationStarted(HomeButton* home_button) = 0; |
| 68 | virtual void NudgeAnimationEnded(HomeButton* home_button) = 0; |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 69 | |
| 70 | // Called when the nudge label is animated to fully shown. |
| 71 | virtual void NudgeLabelShown(HomeButton* home_button) = 0; |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 72 | }; |
| 73 | |
Manu Cornet | c006633 | 2019-02-20 19:26:03 | [diff] [blame] | 74 | static const char kViewClassName[]; |
| 75 | |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 76 | explicit HomeButton(Shelf* shelf); |
Peter Boström | 5fc1d31 | 2021-09-24 02:32:15 | [diff] [blame] | 77 | |
| 78 | HomeButton(const HomeButton&) = delete; |
| 79 | HomeButton& operator=(const HomeButton&) = delete; |
| 80 | |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 81 | ~HomeButton() override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 82 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 83 | // views::View: |
| 84 | gfx::Size CalculatePreferredSize() const override; |
| 85 | void Layout() override; |
| 86 | |
Manu Cornet | e363aec | 2019-01-13 13:07:07 | [diff] [blame] | 87 | // views::Button: |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 88 | void OnGestureEvent(ui::GestureEvent* event) override; |
Manu Cornet | c006633 | 2019-02-20 19:26:03 | [diff] [blame] | 89 | const char* GetClassName() const override; |
Jan Wilken Dörrie | 85285b0 | 2021-03-11 23:38:47 | [diff] [blame] | 90 | std::u16string GetTooltipText(const gfx::Point& p) const override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 91 | |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 92 | // ShelfButtonDelegate: |
| 93 | void OnShelfButtonAboutToRequestFocusFromTabTraversal(ShelfButton* button, |
| 94 | bool reverse) override; |
| 95 | void ButtonPressed(views::Button* sender, |
| 96 | const ui::Event& event, |
| 97 | views::InkDrop* ink_drop) override; |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 98 | |
Michael Giuffrida | 01adeb07 | 2019-03-21 22:05:30 | [diff] [blame] | 99 | // Called when the availability of a long-press gesture may have changed, e.g. |
| 100 | // when Assistant becomes enabled. |
Yue Li | bcdb6aa | 2019-10-02 17:50:57 | [diff] [blame] | 101 | void OnAssistantAvailabilityChanged(); |
Michael Giuffrida | 01adeb07 | 2019-03-21 22:05:30 | [diff] [blame] | 102 | |
| 103 | // True if the app list is shown for the display containing this button. |
| 104 | bool IsShowingAppList() const; |
| 105 | |
Toni Barzic | 71ebb6fd | 2020-05-29 17:16:53 | [diff] [blame] | 106 | // Called when a locale change is detected. Updates the button tooltip and |
| 107 | // accessible name. |
| 108 | void HandleLocaleChange(); |
Manu Cornet | 1ed1f6b | 2019-06-14 17:25:53 | [diff] [blame] | 109 | |
Alex Newcomer | 030e706 | 2019-07-02 00:03:57 | [diff] [blame] | 110 | // Returns the display which contains this view. |
| 111 | int64_t GetDisplayId() const; |
| 112 | |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 113 | // Clip rect of this view's widget will be removed during the life time of the |
| 114 | // returned ScopedNoClipRect. |
Daniel Cheng | b28e2af6 | 2022-01-13 23:56:21 | [diff] [blame] | 115 | [[nodiscard]] std::unique_ptr<ScopedNoClipRect> CreateScopedNoClipRect(); |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 116 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 117 | // Checks if the `nudge_label_` can be shown for the launcher nudge. |
| 118 | // NOTE: This must be called after `CreateNudgeLabel()`, where the |
| 119 | // `nudge_label_` is created. This is because whether the nudge can be shown |
| 120 | // depends on nudge_label_'s preferred size. |
| 121 | bool CanShowNudgeLabel() const; |
| 122 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 123 | // Starts the launcher nudge animation. |
| 124 | void StartNudgeAnimation(); |
| 125 | |
| 126 | void AddNudgeAnimationObserverForTest(NudgeAnimationObserver* observer); |
| 127 | void RemoveNudgeAnimationObserverForTest(NudgeAnimationObserver* observer); |
| 128 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 129 | views::View* label_container_for_test() const { return label_container_; } |
| 130 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 131 | protected: |
Manu Cornet | e363aec | 2019-01-13 13:07:07 | [diff] [blame] | 132 | // views::Button: |
Evan Stade | bad2bc6 | 2017-05-30 21:53:24 | [diff] [blame] | 133 | void PaintButtonContents(gfx::Canvas* canvas) override; |
Yulun Wu | 8924cebb | 2021-01-12 20:23:28 | [diff] [blame] | 134 | void OnThemeChanged() override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 135 | |
| 136 | private: |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 137 | // Creates `nudge_label_` for launcher nudge. |
| 138 | void CreateNudgeLabel(); |
| 139 | |
| 140 | // Animation functions for launcher nudge. |
| 141 | void AnimateNudgeRipple(views::AnimationBuilder& builder); |
| 142 | void AnimateNudgeBounce(views::AnimationBuilder& builder); |
| 143 | void AnimateNudgeLabelSlideIn(views::AnimationBuilder& builder); |
| 144 | void AnimateNudgeLabelSlideOut(); |
| 145 | void AnimateNudgeLabelFadeOut(); |
| 146 | |
| 147 | // Callbacks for the nudge animation. |
| 148 | void OnNudgeAnimationStarted(); |
| 149 | void OnNudgeAnimationEnded(); |
| 150 | void OnLabelSlideInAnimationEnded(); |
| 151 | void OnLabelFadeOutAnimationEnded(); |
| 152 | |
| 153 | // Removes the nudge label from the view hierarchy. |
| 154 | void RemoveNudgeLabel(); |
| 155 | |
Ahmed Mehfooz | 6509620f | 2019-05-21 20:35:12 | [diff] [blame] | 156 | // views::ViewTargeterDelegate: |
| 157 | bool DoesIntersectRect(const views::View* target, |
| 158 | const gfx::Rect& rect) const override; |
| 159 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 160 | Shelf* const shelf_; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 161 | |
Michael Giuffrida | 01adeb07 | 2019-03-21 22:05:30 | [diff] [blame] | 162 | // The controller used to determine the button's behavior. |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 163 | HomeButtonController controller_; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 164 | |
| 165 | // The ripple layer in the launcher nudge animation. Only exists during the |
| 166 | // nudge animation. |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame^] | 167 | ui::LayerOwner nudge_ripple_layer_; |
| 168 | |
| 169 | // The label view and for launcher nudge animation. |
| 170 | views::Label* nudge_label_ = nullptr; |
| 171 | |
| 172 | // The container of `nudge_label_`. This is also responsible for painting the |
| 173 | // background of the label. |
| 174 | views::View* label_container_ = nullptr; |
| 175 | |
| 176 | // The timer that counts down to hide the nudge_label_ from showing state. |
| 177 | base::OneShotTimer label_nudge_timer_; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 178 | |
| 179 | // The delegate used by |nudge_ripple_layer_|. Only exists during the |
| 180 | // nudge animation. |
| 181 | std::unique_ptr<views::CircleLayerDelegate> ripple_layer_delegate_; |
| 182 | |
| 183 | std::unique_ptr<ScopedNoClipRect> scoped_no_clip_rect_; |
| 184 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 185 | base::ObserverList<NudgeAnimationObserver> observers_; |
| 186 | |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 187 | base::WeakPtrFactory<HomeButton> weak_ptr_factory_{this}; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 188 | }; |
| 189 | |
| 190 | } // namespace ash |
| 191 | |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 192 | #endif // ASH_SHELF_HOME_BUTTON_H_ |