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
|
// 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 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.
std::u16string_view GetPlaceholderText() const;
void SetPlaceholderText(std::u16string_view 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_
|