1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
ash / shelf / home_button.h [blame]
// 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/events/devices/input_device_event_observer.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,
public ui::InputDeviceEventObserver {
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 views::SizeBounds& available_size) const override;
void Layout(PassKey) override;
void AddedToWidget() 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;
// ui::InputDeviceEventObserver:
void OnInputDeviceConfigurationChanged(uint8_t input_device_types) override;
void OnDeviceListsComplete() 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_;
}
void UpdateTooltipText();
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();
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_