Avi Drissman | 3a215d1e | 2022-09-07 19:43:09 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 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" |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 11 | #include "ash/app_list/app_list_model_provider.h" |
| 12 | #include "ash/app_list/quick_app_access_model.h" |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 13 | #include "ash/ash_export.h" |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 14 | #include "ash/public/cpp/app_list/app_list_controller_observer.h" |
Toni Barzic | 705b8aa | 2023-05-24 01:50:10 | [diff] [blame] | 15 | #include "ash/public/cpp/shelf_config.h" |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 16 | #include "ash/shelf/home_button_controller.h" |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 17 | #include "ash/shelf/shelf_button_delegate.h" |
Manu Cornet | 40f90812 | 2018-11-08 23:15:25 | [diff] [blame] | 18 | #include "ash/shelf/shelf_control_button.h" |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 19 | #include "ash/shell_observer.h" |
Arthur Sonzogni | 834e018f | 2023-04-22 10:20:02 | [diff] [blame] | 20 | #include "base/memory/raw_ptr.h" |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 21 | #include "base/scoped_observation.h" |
David Yeung | 1f2e3e2 | 2023-11-15 17:29:47 | [diff] [blame] | 22 | #include "ui/base/metadata/metadata_header_macros.h" |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 23 | #include "ui/gfx/geometry/rect.h" |
Matthew Mourgos | 1f28632 | 2023-04-20 18:16:50 | [diff] [blame] | 24 | #include "ui/gfx/geometry/transform.h" |
Ahmed Mehfooz | 6509620f | 2019-05-21 20:35:12 | [diff] [blame] | 25 | #include "ui/views/view_targeter_delegate.h" |
xiaohuic | fb5c54fc | 2017-06-28 17:32:02 | [diff] [blame] | 26 | |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 27 | namespace views { |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 28 | class AnimationBuilder; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 29 | class CircleLayerDelegate; |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 30 | class ImageButton; |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 31 | class Label; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 32 | } // namespace views |
| 33 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 34 | namespace ui { |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 35 | class LayerOwner; |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 36 | } |
| 37 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 38 | namespace ash { |
Sammie Quon | 9b911f2f | 2017-12-15 02:53:15 | [diff] [blame] | 39 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 40 | class Shelf; |
Alex Newcomer | 030e706 | 2019-07-02 00:03:57 | [diff] [blame] | 41 | class ShelfButtonDelegate; |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 42 | class ShelfNavigationWidget; |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 43 | class Shell; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 44 | |
Michael Giuffrida | 01adeb07 | 2019-03-21 22:05:30 | [diff] [blame] | 45 | // Button used for the AppList icon on the shelf. It opens the app list (in |
| 46 | // clamshell mode) or home screen (in tablet mode). Because the clamshell-mode |
| 47 | // app list appears like a dismissable overlay, the button is highlighted while |
| 48 | // the app list is open in clamshell mode. |
| 49 | // |
| 50 | // If Assistant is enabled, the button is filled in; long-pressing it will |
| 51 | // launch Assistant. |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 52 | class ASH_EXPORT HomeButton : public ShelfControlButton, |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 53 | public ShelfButtonDelegate, |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 54 | public views::ViewTargeterDelegate, |
| 55 | public ShellObserver, |
Toni Barzic | 705b8aa | 2023-05-24 01:50:10 | [diff] [blame] | 56 | public ShelfConfig::Observer, |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 57 | public AppListModelProvider::Observer, |
| 58 | public QuickAppAccessModel::Observer { |
David Yeung | 1f2e3e2 | 2023-11-15 17:29:47 | [diff] [blame] | 59 | METADATA_HEADER(HomeButton, ShelfControlButton) |
| 60 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 61 | public: |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 62 | class ScopedNoClipRect { |
| 63 | public: |
| 64 | explicit ScopedNoClipRect(ShelfNavigationWidget* shelf_navigation_widget); |
| 65 | ScopedNoClipRect(const ScopedNoClipRect&) = delete; |
| 66 | ScopedNoClipRect& operator=(const ScopedNoClipRect&) = delete; |
| 67 | ~ScopedNoClipRect(); |
| 68 | |
| 69 | private: |
Bartek Nowierski | deb7584 | 2023-12-27 02:32:42 | [diff] [blame] | 70 | const raw_ptr<ShelfNavigationWidget> shelf_navigation_widget_; |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 71 | const gfx::Rect clip_rect_; |
| 72 | }; |
| 73 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 74 | // An observer that can be used to track the nudge animation state. Currently |
| 75 | // used in testing. |
| 76 | class NudgeAnimationObserver : public base::CheckedObserver { |
| 77 | public: |
| 78 | NudgeAnimationObserver() = default; |
| 79 | NudgeAnimationObserver(const NudgeAnimationObserver&) = delete; |
| 80 | NudgeAnimationObserver& operator=(const NudgeAnimationObserver&) = delete; |
| 81 | ~NudgeAnimationObserver() override = default; |
| 82 | |
| 83 | // Called when the nudge animation is started/ended. |
| 84 | virtual void NudgeAnimationStarted(HomeButton* home_button) = 0; |
| 85 | virtual void NudgeAnimationEnded(HomeButton* home_button) = 0; |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 86 | |
| 87 | // Called when the nudge label is animated to fully shown. |
| 88 | virtual void NudgeLabelShown(HomeButton* home_button) = 0; |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 89 | }; |
| 90 | |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 91 | explicit HomeButton(Shelf* shelf); |
Peter Boström | 5fc1d31 | 2021-09-24 02:32:15 | [diff] [blame] | 92 | |
| 93 | HomeButton(const HomeButton&) = delete; |
| 94 | HomeButton& operator=(const HomeButton&) = delete; |
| 95 | |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 96 | ~HomeButton() override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 97 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 98 | // views::View: |
| 99 | gfx::Size CalculatePreferredSize() const override; |
Peter Kasting | 1e3a1e99 | 2024-02-01 18:10:41 | [diff] [blame] | 100 | void Layout(PassKey) override; |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 101 | |
Manu Cornet | e363aec | 2019-01-13 13:07:07 | [diff] [blame] | 102 | // views::Button: |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 103 | void OnGestureEvent(ui::GestureEvent* event) override; |
Jan Wilken Dörrie | 85285b0 | 2021-03-11 23:38:47 | [diff] [blame] | 104 | std::u16string GetTooltipText(const gfx::Point& p) const override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 105 | |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 106 | // ShelfButtonDelegate: |
| 107 | void OnShelfButtonAboutToRequestFocusFromTabTraversal(ShelfButton* button, |
| 108 | bool reverse) override; |
| 109 | void ButtonPressed(views::Button* sender, |
| 110 | const ui::Event& event, |
| 111 | views::InkDrop* ink_drop) override; |
Manu Cornet | 86aef98 | 2019-07-18 21:31:10 | [diff] [blame] | 112 | |
Toni Barzic | 705b8aa | 2023-05-24 01:50:10 | [diff] [blame] | 113 | // ShelfConfig::Observer: |
| 114 | void OnShelfConfigUpdated() override; |
| 115 | |
Michael Giuffrida | 01adeb07 | 2019-03-21 22:05:30 | [diff] [blame] | 116 | // Called when the availability of a long-press gesture may have changed, e.g. |
| 117 | // when Assistant becomes enabled. |
Yue Li | bcdb6aa | 2019-10-02 17:50:57 | [diff] [blame] | 118 | void OnAssistantAvailabilityChanged(); |
Michael Giuffrida | 01adeb07 | 2019-03-21 22:05:30 | [diff] [blame] | 119 | |
| 120 | // True if the app list is shown for the display containing this button. |
| 121 | bool IsShowingAppList() const; |
| 122 | |
Toni Barzic | 71ebb6fd | 2020-05-29 17:16:53 | [diff] [blame] | 123 | // Called when a locale change is detected. Updates the button tooltip and |
| 124 | // accessible name. |
| 125 | void HandleLocaleChange(); |
Manu Cornet | 1ed1f6b | 2019-06-14 17:25:53 | [diff] [blame] | 126 | |
Alex Newcomer | 030e706 | 2019-07-02 00:03:57 | [diff] [blame] | 127 | // Returns the display which contains this view. |
| 128 | int64_t GetDisplayId() const; |
| 129 | |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 130 | // Clip rect of this view's widget will be removed during the life time of the |
| 131 | // returned ScopedNoClipRect. |
Daniel Cheng | b28e2af6 | 2022-01-13 23:56:21 | [diff] [blame] | 132 | [[nodiscard]] std::unique_ptr<ScopedNoClipRect> CreateScopedNoClipRect(); |
Yuki Awano | 2090b46 | 2021-06-08 01:33:07 | [diff] [blame] | 133 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 134 | // Checks if the `nudge_label_` can be shown for the launcher nudge. |
| 135 | // NOTE: This must be called after `CreateNudgeLabel()`, where the |
| 136 | // `nudge_label_` is created. This is because whether the nudge can be shown |
| 137 | // depends on nudge_label_'s preferred size. |
| 138 | bool CanShowNudgeLabel() const; |
| 139 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 140 | // Starts the launcher nudge animation. |
| 141 | void StartNudgeAnimation(); |
| 142 | |
Toni Barzic | 2e554738 | 2023-05-26 21:53:24 | [diff] [blame] | 143 | // Sets the button's "toggled" state - the button is toggled when the bubble |
| 144 | // launcher is shown. |
| 145 | void SetToggled(bool toggled); |
| 146 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 147 | void AddNudgeAnimationObserverForTest(NudgeAnimationObserver* observer); |
| 148 | void RemoveNudgeAnimationObserverForTest(NudgeAnimationObserver* observer); |
| 149 | |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 150 | views::View* expandable_container_for_test() const { |
| 151 | return expandable_container_; |
| 152 | } |
| 153 | |
| 154 | views::Label* nudge_label_for_test() const { return nudge_label_; } |
| 155 | |
| 156 | views::ImageButton* quick_app_button_for_test() const { |
| 157 | return quick_app_button_; |
| 158 | } |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 159 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 160 | protected: |
Manu Cornet | e363aec | 2019-01-13 13:07:07 | [diff] [blame] | 161 | // views::Button: |
Yulun Wu | 8924cebb | 2021-01-12 20:23:28 | [diff] [blame] | 162 | void OnThemeChanged() override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 163 | |
| 164 | private: |
Toni Barzic | 705b8aa | 2023-05-24 01:50:10 | [diff] [blame] | 165 | class ButtonImageView; |
| 166 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 167 | // Creates `nudge_label_` for launcher nudge. |
| 168 | void CreateNudgeLabel(); |
| 169 | |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 170 | // Creates the `expandable_container_` which holds either the `nudge_label_` |
| 171 | // or the `quick_app_button_`. |
| 172 | void CreateExpandableContainer(); |
| 173 | |
| 174 | // Creates the `quick_app_button_` to be shown next to the home button. |
| 175 | void CreateQuickAppButton(); |
| 176 | |
| 177 | // Called when the quick app button is pressed. |
| 178 | void QuickAppButtonPressed(); |
| 179 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 180 | // Animation functions for launcher nudge. |
| 181 | void AnimateNudgeRipple(views::AnimationBuilder& builder); |
| 182 | void AnimateNudgeBounce(views::AnimationBuilder& builder); |
| 183 | void AnimateNudgeLabelSlideIn(views::AnimationBuilder& builder); |
| 184 | void AnimateNudgeLabelSlideOut(); |
| 185 | void AnimateNudgeLabelFadeOut(); |
| 186 | |
| 187 | // Callbacks for the nudge animation. |
| 188 | void OnNudgeAnimationStarted(); |
| 189 | void OnNudgeAnimationEnded(); |
| 190 | void OnLabelSlideInAnimationEnded(); |
| 191 | void OnLabelFadeOutAnimationEnded(); |
| 192 | |
| 193 | // Removes the nudge label from the view hierarchy. |
| 194 | void RemoveNudgeLabel(); |
| 195 | |
Matthew Mourgos | be9f2827 | 2023-04-13 17:45:45 | [diff] [blame] | 196 | // Removes the quick app button from the view hierarchy. |
| 197 | void RemoveQuickAppButton(); |
| 198 | |
Ahmed Mehfooz | 6509620f | 2019-05-21 20:35:12 | [diff] [blame] | 199 | // views::ViewTargeterDelegate: |
| 200 | bool DoesIntersectRect(const views::View* target, |
| 201 | const gfx::Rect& rect) const override; |
| 202 | |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 203 | // ShellObserver: |
| 204 | void OnShellDestroying() override; |
| 205 | |
| 206 | // AppListModelProvider::Observer: |
| 207 | void OnActiveAppListModelsChanged(AppListModel* model, |
| 208 | SearchModel* search_model) override; |
| 209 | |
| 210 | // QuickAppAccessModel::Observer: |
Matthew Mourgos | be9f2827 | 2023-04-13 17:45:45 | [diff] [blame] | 211 | void OnQuickAppShouldShowChanged(bool quick_app_shown) override; |
| 212 | void OnQuickAppIconChanged() override; |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 213 | |
Matthew Mourgos | 1f28632 | 2023-04-20 18:16:50 | [diff] [blame] | 214 | // Create and animate in the quick app button from behind the home button. |
| 215 | void AnimateQuickAppButtonIn(); |
| 216 | |
| 217 | // Animate out the quick app button, deleting the quick app button when |
| 218 | // completed. |
| 219 | void AnimateQuickAppButtonOut(); |
| 220 | |
| 221 | // Callback for the quick app button slide out animation. |
| 222 | void OnQuickAppButtonSlideOutDone(); |
| 223 | |
| 224 | // Returns a transform which will translate the child of the |
| 225 | // `expandable_container` to be placed behind the home button. |
| 226 | gfx::Transform GetTransformForContainerChildBehindHomeButton(); |
| 227 | |
| 228 | // Returns a clip rect which will clip the `expandable_container` to the |
| 229 | // bounds of the home button. |
| 230 | gfx::Rect GetExpandableContainerClipRectToHomeButton(); |
| 231 | |
Toni Barzic | 2e554738 | 2023-05-26 21:53:24 | [diff] [blame] | 232 | const bool jelly_enabled_; |
| 233 | |
Matthew Mourgos | d477282 | 2023-04-05 18:35:03 | [diff] [blame] | 234 | base::ScopedObservation<QuickAppAccessModel, QuickAppAccessModel::Observer> |
| 235 | quick_app_model_observation_{this}; |
| 236 | |
| 237 | base::ScopedObservation<Shell, ShellObserver> shell_observation_{this}; |
| 238 | |
| 239 | base::ScopedObservation<AppListModelProvider, AppListModelProvider::Observer> |
| 240 | app_list_model_observation_{this}; |
| 241 | |
Bartek Nowierski | deb7584 | 2023-12-27 02:32:42 | [diff] [blame] | 242 | const raw_ptr<Shelf> shelf_; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 243 | |
Toni Barzic | 705b8aa | 2023-05-24 01:50:10 | [diff] [blame] | 244 | // The view that paints the home button content. In its own view to ensure |
| 245 | // the background is stacked above `expandable_container_`. |
Bartek Nowierski | deb7584 | 2023-12-27 02:32:42 | [diff] [blame] | 246 | raw_ptr<ButtonImageView> button_image_view_ = nullptr; |
Toni Barzic | 705b8aa | 2023-05-24 01:50:10 | [diff] [blame] | 247 | |
| 248 | // The container of `nudge_label_` or `quick_app_button_`. This is also |
| 249 | // responsible for painting the background of the contents. This container can |
| 250 | // expand visually by animation. |
Jan Keitel | ae0e7e0 | 2024-02-07 22:09:06 | [diff] [blame] | 251 | raw_ptr<views::View> expandable_container_ = nullptr; |
Toni Barzic | 705b8aa | 2023-05-24 01:50:10 | [diff] [blame] | 252 | |
| 253 | // The app button which is shown next to the home button. Only shown when |
| 254 | // set by SetQuickApp(). |
Jan Keitel | ae0e7e0 | 2024-02-07 22:09:06 | [diff] [blame] | 255 | raw_ptr<views::ImageButton> quick_app_button_ = nullptr; |
Toni Barzic | 705b8aa | 2023-05-24 01:50:10 | [diff] [blame] | 256 | |
Michael Giuffrida | 01adeb07 | 2019-03-21 22:05:30 | [diff] [blame] | 257 | // The controller used to determine the button's behavior. |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 258 | HomeButtonController controller_; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 259 | |
Jan Keitel | ae0e7e0 | 2024-02-07 22:09:06 | [diff] [blame] | 260 | // The delegate used by |nudge_ripple_layer_|. Only exists during the |
| 261 | // nudge animation. |
| 262 | std::unique_ptr<views::CircleLayerDelegate> ripple_layer_delegate_; |
| 263 | |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 264 | // The ripple layer in the launcher nudge animation. Only exists during the |
| 265 | // nudge animation. |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 266 | ui::LayerOwner nudge_ripple_layer_; |
| 267 | |
| 268 | // The label view and for launcher nudge animation. |
Jan Keitel | ae0e7e0 | 2024-02-07 22:09:06 | [diff] [blame] | 269 | raw_ptr<views::Label> nudge_label_ = nullptr; |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 270 | |
Wen-Chien Wang | 51a5d604d | 2022-05-10 18:18:01 | [diff] [blame] | 271 | // The timer that counts down to hide the nudge_label_ from showing state. |
| 272 | base::OneShotTimer label_nudge_timer_; |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 273 | |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 274 | std::unique_ptr<ScopedNoClipRect> scoped_no_clip_rect_; |
| 275 | |
Wen-Chien Wang | 617c38a | 2021-10-07 10:23:50 | [diff] [blame] | 276 | base::ObserverList<NudgeAnimationObserver> observers_; |
| 277 | |
Wen-Chien Wang | 3667df20 | 2021-09-30 20:08:23 | [diff] [blame] | 278 | base::WeakPtrFactory<HomeButton> weak_ptr_factory_{this}; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 279 | }; |
| 280 | |
| 281 | } // namespace ash |
| 282 | |
Manu Cornet | f953d49 | 2019-06-27 05:56:51 | [diff] [blame] | 283 | #endif // ASH_SHELF_HOME_BUTTON_H_ |