Commit 331ae768 authored by Olesia Marukhno's avatar Olesia Marukhno Committed by Commit Bot

[omnibox] Fix accessibility bugs for dedicated row and pedals

Fixed a11y for remove suggestion button and buttons in dedicated row
(set role to be list box option and set correct accessible name).
Fixed selection event not being triggered for dedicated row buttons
(GetSecondaryButton wasn't returning buttons from dedicated row).
Fixed value changed event triggering extra time when switching selection
from button to button.

Bug: 1104264
Change-Id: If5fc4692ac4e86f50e1a1d1b754feec795b76c10
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2366758
Commit-Queue: Olesia Marukhno <olesiamarukhno@google.com>
Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800300}
parent 1f99b42c
...@@ -45,6 +45,26 @@ ...@@ -45,6 +45,26 @@
#include "base/win/atl.h" #include "base/win/atl.h"
#endif #endif
namespace {
class OmniboxRemoveSuggestionButton : public views::ImageButton {
public:
explicit OmniboxRemoveSuggestionButton(views::ButtonListener* listener)
: ImageButton(listener) {
views::ConfigureVectorImageButton(this);
}
void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
node_data->SetName(
l10n_util::GetStringUTF16(IDS_ACC_REMOVE_SUGGESTION_BUTTON));
// Although this appears visually as a button, expose as a list box option
// so that it matches the other options within its list box container.
node_data->role = ax::mojom::Role::kListBoxOption;
}
};
} // namespace
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// OmniboxResultView, public: // OmniboxResultView, public:
...@@ -72,7 +92,7 @@ OmniboxResultView::OmniboxResultView( ...@@ -72,7 +92,7 @@ OmniboxResultView::OmniboxResultView(
// TODO(tommycli): Make sure we announce the Shift+Delete capability in the // TODO(tommycli): Make sure we announce the Shift+Delete capability in the
// accessibility node data for removable suggestions. // accessibility node data for removable suggestions.
remove_suggestion_button_ = remove_suggestion_button_ =
AddChildView(views::CreateVectorImageButton(this)); AddChildView(std::make_unique<OmniboxRemoveSuggestionButton>(this));
// The remove suggestion button may receive mouse enter/exit events with very // The remove suggestion button may receive mouse enter/exit events with very
// quick mouse movements. Monitor the button to update our state. // quick mouse movements. Monitor the button to update our state.
update_on_mouse_enter_exit_.emplace(this, remove_suggestion_button_); update_on_mouse_enter_exit_.emplace(this, remove_suggestion_button_);
...@@ -276,6 +296,10 @@ views::Button* OmniboxResultView::GetSecondaryButton() { ...@@ -276,6 +296,10 @@ views::Button* OmniboxResultView::GetSecondaryButton() {
if (remove_suggestion_button_->GetVisible()) if (remove_suggestion_button_->GetVisible())
return remove_suggestion_button_; return remove_suggestion_button_;
if (OmniboxFieldTrial::IsSuggestionButtonRowEnabled()) {
return button_row_->GetActiveButton();
}
return nullptr; return nullptr;
} }
......
...@@ -17,9 +17,11 @@ ...@@ -17,9 +17,11 @@
#include "components/strings/grit/components_strings.h" #include "components/strings/grit/components_strings.h"
#include "components/vector_icons/vector_icons.h" #include "components/vector_icons/vector_icons.h"
#include "third_party/metrics_proto/omnibox_event.pb.h" #include "third_party/metrics_proto/omnibox_event.pb.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_utils.h" #include "ui/gfx/color_utils.h"
#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/paint_vector_icon.h"
#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/animation/ink_drop_highlight.h" #include "ui/views/animation/ink_drop_highlight.h"
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/controls/button/label_button_border.h" #include "ui/views/controls/button/label_button_border.h"
...@@ -33,8 +35,12 @@ class OmniboxSuggestionRowButton : public views::MdTextButton { ...@@ -33,8 +35,12 @@ class OmniboxSuggestionRowButton : public views::MdTextButton {
OmniboxSuggestionRowButton(views::ButtonListener* listener, OmniboxSuggestionRowButton(views::ButtonListener* listener,
const base::string16& text, const base::string16& text,
const gfx::VectorIcon& icon, const gfx::VectorIcon& icon,
const views::FocusRing::ViewPredicate& predicate) OmniboxPopupContentsView* popup_contents_view,
: MdTextButton(listener, text, CONTEXT_OMNIBOX_PRIMARY), icon_(icon) { OmniboxPopupModel::Selection selection)
: MdTextButton(listener, text, CONTEXT_OMNIBOX_PRIMARY),
icon_(icon),
popup_contents_view_(popup_contents_view),
selection_(selection) {
views::InstallPillHighlightPathGenerator(this); views::InstallPillHighlightPathGenerator(this);
SetImageLabelSpacing(ChromeLayoutProvider::Get()->GetDistanceMetric( SetImageLabelSpacing(ChromeLayoutProvider::Get()->GetDistanceMetric(
DISTANCE_RELATED_LABEL_HORIZONTAL_LIST)); DISTANCE_RELATED_LABEL_HORIZONTAL_LIST));
...@@ -44,7 +50,10 @@ class OmniboxSuggestionRowButton : public views::MdTextButton { ...@@ -44,7 +50,10 @@ class OmniboxSuggestionRowButton : public views::MdTextButton {
GetLayoutConstant(LOCATION_BAR_ICON_SIZE)); GetLayoutConstant(LOCATION_BAR_ICON_SIZE));
set_ink_drop_highlight_opacity(CalculateInkDropHighlightOpacity()); set_ink_drop_highlight_opacity(CalculateInkDropHighlightOpacity());
focus_ring()->SetHasFocusPredicate(predicate); focus_ring()->SetHasFocusPredicate([=](View* view) {
return view->GetVisible() &&
popup_contents_view_->model()->selection() == selection_;
});
} }
OmniboxSuggestionRowButton(const OmniboxSuggestionRowButton&) = delete; OmniboxSuggestionRowButton(const OmniboxSuggestionRowButton&) = delete;
...@@ -59,6 +68,8 @@ class OmniboxSuggestionRowButton : public views::MdTextButton { ...@@ -59,6 +68,8 @@ class OmniboxSuggestionRowButton : public views::MdTextButton {
void OnStyleRefresh() { focus_ring()->SchedulePaint(); } void OnStyleRefresh() { focus_ring()->SchedulePaint(); }
OmniboxPopupModel::Selection selection() { return selection_; }
std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
const override { const override {
// MdTextButton uses custom colors when creating ink drop highlight. // MdTextButton uses custom colors when creating ink drop highlight.
...@@ -77,8 +88,17 @@ class OmniboxSuggestionRowButton : public views::MdTextButton { ...@@ -77,8 +88,17 @@ class OmniboxSuggestionRowButton : public views::MdTextButton {
icon_, GetLayoutConstant(LOCATION_BAR_ICON_SIZE), color)); icon_, GetLayoutConstant(LOCATION_BAR_ICON_SIZE), color));
} }
void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
node_data->SetName(GetAccessibleName());
// Although this appears visually as a button, expose as a list box option
// so that it matches the other options within its list box container.
node_data->role = ax::mojom::Role::kListBoxOption;
}
private: private:
const gfx::VectorIcon& icon_; const gfx::VectorIcon& icon_;
OmniboxPopupContentsView* popup_contents_view_;
OmniboxPopupModel::Selection selection_;
float CalculateInkDropHighlightOpacity() { float CalculateInkDropHighlightOpacity() {
// Ink drop highlight opacity is result of mixing a layer with hovered // Ink drop highlight opacity is result of mixing a layer with hovered
...@@ -109,30 +129,27 @@ OmniboxSuggestionButtonRowView::OmniboxSuggestionButtonRowView( ...@@ -109,30 +129,27 @@ OmniboxSuggestionButtonRowView::OmniboxSuggestionButtonRowView(
gfx::Insets(0, ChromeLayoutProvider::Get()->GetDistanceMetric( gfx::Insets(0, ChromeLayoutProvider::Get()->GetDistanceMetric(
views::DISTANCE_RELATED_BUTTON_HORIZONTAL))); views::DISTANCE_RELATED_BUTTON_HORIZONTAL)));
const auto make_predicate = [=](auto state) {
return [=](View* view) {
return view->GetVisible() &&
model()->selection() ==
OmniboxPopupModel::Selection(model_index_, state);
};
};
// For all of these buttons, the visibility set from UpdateFromModel(). // For all of these buttons, the visibility set from UpdateFromModel().
// The Keyword and Pedal buttons also get their text from there, since the // The Keyword and Pedal buttons also get their text from there, since the
// text depends on the actual match. That shouldn't produce a flicker, because // text depends on the actual match. That shouldn't produce a flicker, because
// it's called directly from OmniboxResultView::SetMatch(). If this flickers, // it's called directly from OmniboxResultView::SetMatch(). If this flickers,
// then so does everything else in the result view. // then so does everything else in the result view.
keyword_button_ = AddChildView(std::make_unique<OmniboxSuggestionRowButton>( keyword_button_ = AddChildView(std::make_unique<OmniboxSuggestionRowButton>(
this, base::string16(), vector_icons::kSearchIcon, this, base::string16(), vector_icons::kSearchIcon, popup_contents_view_,
make_predicate(OmniboxPopupModel::FOCUSED_BUTTON_KEYWORD))); OmniboxPopupModel::Selection(model_index_,
OmniboxPopupModel::FOCUSED_BUTTON_KEYWORD)));
tab_switch_button_ = tab_switch_button_ =
AddChildView(std::make_unique<OmniboxSuggestionRowButton>( AddChildView(std::make_unique<OmniboxSuggestionRowButton>(
this, l10n_util::GetStringUTF16(IDS_OMNIBOX_TAB_SUGGEST_HINT), this, l10n_util::GetStringUTF16(IDS_OMNIBOX_TAB_SUGGEST_HINT),
omnibox::kSwitchIcon, omnibox::kSwitchIcon, popup_contents_view_,
make_predicate(OmniboxPopupModel::FOCUSED_BUTTON_TAB_SWITCH))); OmniboxPopupModel::Selection(
model_index_, OmniboxPopupModel::FOCUSED_BUTTON_TAB_SWITCH)));
tab_switch_button_->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_ACC_TAB_SWITCH_BUTTON));
pedal_button_ = AddChildView(std::make_unique<OmniboxSuggestionRowButton>( pedal_button_ = AddChildView(std::make_unique<OmniboxSuggestionRowButton>(
this, base::string16(), omnibox::kProductIcon, this, base::string16(), omnibox::kProductIcon, popup_contents_view_,
make_predicate(OmniboxPopupModel::FOCUSED_BUTTON_PEDAL))); OmniboxPopupModel::Selection(model_index_,
OmniboxPopupModel::FOCUSED_BUTTON_PEDAL)));
} }
OmniboxSuggestionButtonRowView::~OmniboxSuggestionButtonRowView() = default; OmniboxSuggestionButtonRowView::~OmniboxSuggestionButtonRowView() = default;
...@@ -150,14 +167,17 @@ void OmniboxSuggestionButtonRowView::UpdateFromModel() { ...@@ -150,14 +167,17 @@ void OmniboxSuggestionButtonRowView::UpdateFromModel() {
const auto names = SelectedKeywordView::GetKeywordLabelNames( const auto names = SelectedKeywordView::GetKeywordLabelNames(
keyword, edit_model->client()->GetTemplateURLService()); keyword, edit_model->client()->GetTemplateURLService());
keyword_button_->SetText(names.full_name); keyword_button_->SetText(names.full_name);
keyword_button_->SetAccessibleName(
l10n_util::GetStringFUTF16(IDS_ACC_KEYWORD_BUTTON, names.short_name));
} }
SetPillButtonVisibility(pedal_button_, SetPillButtonVisibility(pedal_button_,
OmniboxPopupModel::FOCUSED_BUTTON_PEDAL); OmniboxPopupModel::FOCUSED_BUTTON_PEDAL);
if (pedal_button_->GetVisible()) { if (pedal_button_->GetVisible()) {
pedal_button_->SetText(match().pedal->GetLabelStrings().hint); const auto pedal_strings = match().pedal->GetLabelStrings();
pedal_button_->SetTooltipText( pedal_button_->SetText(pedal_strings.hint);
match().pedal->GetLabelStrings().suggestion_contents); pedal_button_->SetTooltipText(pedal_strings.suggestion_contents);
pedal_button_->SetAccessibleName(pedal_strings.accessibility_hint);
} }
SetPillButtonVisibility(tab_switch_button_, SetPillButtonVisibility(tab_switch_button_,
...@@ -210,6 +230,28 @@ void OmniboxSuggestionButtonRowView::ButtonPressed(views::Button* button, ...@@ -210,6 +230,28 @@ void OmniboxSuggestionButtonRowView::ButtonPressed(views::Button* button,
} }
} }
views::Button* OmniboxSuggestionButtonRowView::GetActiveButton() const {
std::vector<OmniboxSuggestionRowButton*> visible_buttons;
if (keyword_button_->GetVisible())
visible_buttons.push_back(keyword_button_);
if (tab_switch_button_->GetVisible())
visible_buttons.push_back(tab_switch_button_);
if (pedal_button_->GetVisible())
visible_buttons.push_back(pedal_button_);
if (visible_buttons.empty())
return nullptr;
// Find first visible button that matches model selection.
auto selected_button =
std::find_if(visible_buttons.begin(), visible_buttons.end(),
[=](OmniboxSuggestionRowButton* button) {
return model()->selection() == button->selection();
});
return selected_button == visible_buttons.end() ? visible_buttons.front()
: *selected_button;
}
const OmniboxPopupModel* OmniboxSuggestionButtonRowView::model() const { const OmniboxPopupModel* OmniboxSuggestionButtonRowView::model() const {
return popup_contents_view_->model(); return popup_contents_view_->model();
} }
......
...@@ -32,6 +32,8 @@ class OmniboxSuggestionButtonRowView : public views::View, ...@@ -32,6 +32,8 @@ class OmniboxSuggestionButtonRowView : public views::View,
// views::ButtonListener: // views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
views::Button* GetActiveButton() const;
private: private:
// Get the popup model from the view. // Get the popup model from the view.
const OmniboxPopupModel* model() const; const OmniboxPopupModel* model() const;
......
...@@ -181,6 +181,7 @@ void OmniboxPopupModel::SetSelection(Selection new_selection, ...@@ -181,6 +181,7 @@ void OmniboxPopupModel::SetSelection(Selection new_selection,
base::string16()); base::string16());
} else if (old_selection.line != selection_.line || } else if (old_selection.line != selection_.line ||
(old_selection.IsButtonFocused() && (old_selection.IsButtonFocused() &&
!new_selection.IsButtonFocused() &&
new_selection.state != KEYWORD_MODE)) { new_selection.state != KEYWORD_MODE)) {
// Otherwise, only update the edit model for line number changes, or // Otherwise, only update the edit model for line number changes, or
// when the old selection was a button and we're not entering keyword mode. // when the old selection was a button and we're not entering keyword mode.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment