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
ash / quick_insert / views / quick_insert_search_field_view.h [blame]
// Copyright 2023 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_QUICK_INSERT_VIEWS_QUICK_INSERT_SEARCH_FIELD_VIEW_H_
#define ASH_QUICK_INSERT_VIEWS_QUICK_INSERT_SEARCH_FIELD_VIEW_H_
#include <string_view>
#include "ash/ash_export.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/layout/box_layout_view.h"
#include "ui/views/metadata/view_factory.h"
#include "ui/views/view.h"
#include "ui/views/view_tracker.h"
namespace views {
class Textfield;
class ImageButton;
} // namespace views
namespace ash {
class QuickInsertKeyEventHandler;
class QuickInsertPerformanceMetrics;
class QuickInsertSearchBarTextfield;
// View for the Quick Insert search field.
class ASH_EXPORT QuickInsertSearchFieldView
: public views::BoxLayoutView,
public views::TextfieldController,
public views::FocusChangeListener {
METADATA_HEADER(QuickInsertSearchFieldView, views::BoxLayoutView)
public:
using SearchCallback =
base::RepeatingCallback<void(const std::u16string& query)>;
using BackCallback = base::RepeatingClosure;
// The delay before notifying the initial active descendant when the textfield
// is focused. Same value as Launcher.
static constexpr base::TimeDelta kNotifyInitialActiveDescendantA11yDelay =
base::Milliseconds(1500);
// `search_callback` is called asynchronously whenever the contents of the
// search field changes (with debouncing logic to avoid unnecessary calls).
// `key_event_handler` and `performance_metrics` must live as long as this
// class. `delay` is the time to wait before calling `search_callback` for
// debouncing.
//
// `back_callback` is called when clicking on the back button.
explicit QuickInsertSearchFieldView(
SearchCallback search_callback,
BackCallback back_callback,
QuickInsertKeyEventHandler* key_event_handler,
QuickInsertPerformanceMetrics* performance_metrics);
QuickInsertSearchFieldView(const QuickInsertSearchFieldView&) = delete;
QuickInsertSearchFieldView& operator=(const QuickInsertSearchFieldView&) =
delete;
~QuickInsertSearchFieldView() override;
// views::View:
void RequestFocus() override;
void AddedToWidget() override;
void RemovedFromWidget() override;
void OnPaint(gfx::Canvas* canvas) override;
// views::TextfieldController:
void ContentsChanged(views::Textfield* sender,
const std::u16string& new_contents) override;
bool HandleKeyEvent(views::Textfield* sender,
const ui::KeyEvent& key_event) override;
// views::FocusChangeListener:
void OnWillChangeFocus(View* focused_before, View* focused_now) override;
void OnDidChangeFocus(View* focused_before, View* focused_now) override;
// Should be called every time the contents of the text field changes, even
// if the search callback should not be called.
void ContentsChangedInternal(std::u16string_view new_contents);
// Gets or sets the placeholder text to show when the textfield is empty.
const std::u16string& GetPlaceholderText() const;
void SetPlaceholderText(const std::u16string& new_placeholder_text);
// Sets the active descendant of the underlying textfield to `view` for screen
// readers. `view` may be null, in which case the active descendant is
// cleared.
void SetTextfieldActiveDescendant(views::View* view);
// Gets the current search query text.
std::u16string_view GetQueryText() const;
// Sets the current search query text. Does not call the search callback.
void SetQueryText(std::u16string text);
// Sets whether the back button is visible.
void SetBackButtonVisible(bool visible);
void SetShouldShowFocusIndicator(bool should_show_focus_indicator);
// Returns the view directly to the left / right of `view`, or nullptr if
// there is no such view in the QuickInsertSearchFieldView.
views::View* GetViewLeftOf(views::View* view);
views::View* GetViewRightOf(views::View* view);
// Returns true if a left / right key event should move the cursor rather than
// moving the currently pseudo focused view.
bool LeftEventShouldMoveCursor(views::View* pseudo_focused_view);
bool RightEventShouldMoveCursor(views::View* pseudo_focused_view);
// Should be called when the search field or one of its child views gains
// pseudo focus after a left / right key event.
void OnGainedPseudoFocusFromLeftEvent(views::View* pseudo_focused_view);
void OnGainedPseudoFocusFromRightEvent(views::View* pseudo_focused_view);
QuickInsertSearchBarTextfield* textfield() { return textfield_; }
QuickInsertSearchBarTextfield& textfield_for_testing() { return *textfield_; }
views::ImageButton& back_button_for_testing() { return *back_button_; }
views::ImageButton& clear_button_for_testing() { return *clear_button_; }
private:
void ClearButtonPressed();
// Updates the textfield border when the clear button visibility changes.
void UpdateTextfieldBorder();
// Schedules a delayed announcement of the initial active descendant.
void ScheduleNotifyInitialActiveDescendantForA11y();
// Notifies the initial active descendant for the screen reader.
void NotifyInitialActiveDescendantForA11y();
// Gets the start and end indices of the current search query text, to use
// when moving pseudo focus to and from the textfield. Note that the start and
// end are swapped in RTL locales since we swapped left and right key events
// when traversing the Quick Insert UI in RTL.
size_t GetQueryStartIndexForTraversal();
size_t GetQueryEndIndexForTraversal();
bool should_show_focus_indicator_ = false;
SearchCallback search_callback_;
raw_ptr<QuickInsertKeyEventHandler> key_event_handler_ = nullptr;
raw_ptr<QuickInsertPerformanceMetrics> performance_metrics_ = nullptr;
raw_ptr<QuickInsertSearchBarTextfield> textfield_ = nullptr;
raw_ptr<views::ImageButton> back_button_ = nullptr;
raw_ptr<views::ImageButton> clear_button_ = nullptr;
// Tracks pending active descendant change when the textfield is not focused.
views::ViewTracker active_descendant_tracker_;
// Delay the initial active descendant change notification for a query.
base::OneShotTimer notify_initial_active_descendant_timer_;
};
BEGIN_VIEW_BUILDER(ASH_EXPORT, QuickInsertSearchFieldView, views::BoxLayoutView)
VIEW_BUILDER_PROPERTY(std::u16string, PlaceholderText)
END_VIEW_BUILDER
} // namespace ash
DEFINE_VIEW_BUILDER(ASH_EXPORT, ash::QuickInsertSearchFieldView)
#endif // ASH_QUICK_INSERT_VIEWS_QUICK_INSERT_SEARCH_FIELD_VIEW_H_