blob: 80abb17f73c670d35fb00588a2a31af1801d8341 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/quick_insert/views/quick_insert_pseudo_focus.h"
#include "ash/quick_insert/views/quick_insert_item_view.h"
#include "ash/quick_insert/views/quick_insert_list_item_view.h"
#include "ash/quick_insert/views/quick_insert_search_bar_textfield.h"
#include "base/functional/bind.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/events/types/event_type.h"
#include "ui/views/controls/focus_ring.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/view.h"
#include "ui/views/view_utils.h"
namespace ash {
void ApplyQuickInsertPseudoFocusToView(views::View* view) {
if (view == nullptr) {
return;
}
// QuickInsertItemView has special pseudo focus behavior, so handle it
// separately.
if (auto* item_view = views::AsViewClass<QuickInsertItemView>(view)) {
item_view->SetItemState(QuickInsertItemView::ItemState::kPseudoFocused);
if (auto* list_item_view =
views::AsViewClass<QuickInsertListItemView>(view)) {
list_item_view->SetBadgeVisible(true);
}
return;
}
// QuickInsertSearchBarTextfield has special pseudo focus appearance.
if (auto* textfield =
views::AsViewClass<QuickInsertSearchBarTextfield>(view)) {
textfield->SetShouldShowFocusIndicator(true);
return;
}
// Otherwise, default to drawing a focus ring around the view.
if (views::FocusRing* focus_ring = views::FocusRing::Get(view)) {
focus_ring->SetHasFocusPredicate(
base::BindRepeating([](const views::View* view) { return true; }));
focus_ring->SchedulePaint();
}
}
void RemoveQuickInsertPseudoFocusFromView(views::View* view) {
if (view == nullptr) {
return;
}
// QuickInsertItemView has special pseudo focus behavior, so handle it
// separately.
if (auto* item_view = views::AsViewClass<QuickInsertItemView>(view)) {
item_view->SetItemState(QuickInsertItemView::ItemState::kNormal);
if (auto* list_item_view =
views::AsViewClass<QuickInsertListItemView>(view)) {
list_item_view->SetBadgeVisible(false);
}
return;
}
// QuickInsertSearchBarTextfield has special pseudo focus appearance.
if (auto* textfield =
views::AsViewClass<QuickInsertSearchBarTextfield>(view)) {
textfield->SetShouldShowFocusIndicator(false);
return;
}
// Otherwise, default to removing the focus ring around the view.
if (views::FocusRing* focus_ring = views::FocusRing::Get(view)) {
focus_ring->SetHasFocusPredicate(
base::BindRepeating([](const views::View* view) { return false; }));
focus_ring->SchedulePaint();
}
}
bool DoQuickInsertPseudoFocusedActionOnView(views::View* view) {
if (view == nullptr) {
return false;
}
// QuickInsertSearchBarTextfield has no pseudo focus action.
if (views::IsViewClass<QuickInsertSearchBarTextfield>(view)) {
return true;
}
// QuickInsertItemView has special pseudo focus behavior, so handle it
// separately.
if (auto* item_view = views::AsViewClass<QuickInsertItemView>(view)) {
item_view->SelectItem();
return true;
}
// Otherwise, default to behaving the same way as pressing the enter key.
// Here we check that `view` does not have actual focus, to ensure we won't
// trigger an infinite recursive loop of pseudo focused actions when manually
// calling `OnKeyEvent` (since the focused view may forward key events to be
// handled by the pseudo focused view).
CHECK(!view->HasFocus());
ui::KeyEvent key_event(ui::EventType::kKeyPressed, ui::VKEY_RETURN,
ui::DomCode::ENTER, ui::EF_NONE);
view->OnKeyEvent(&key_event);
return key_event.handled();
}
views::View* GetNextQuickInsertPseudoFocusableView(
views::View* view,
QuickInsertPseudoFocusDirection direction,
bool should_loop) {
return view == nullptr || view->GetFocusManager() == nullptr
? nullptr
: view->GetFocusManager()->GetNextFocusableView(
view, view->GetWidget(),
direction == QuickInsertPseudoFocusDirection::kBackward,
!should_loop);
}
} // namespace ash