Commit 40cbfe21 authored by Anastasia Helfinstein's avatar Anastasia Helfinstein Committed by Commit Bot

[Switch Access] Improve MenuBubbleController

In bringing Switch Access up to the visual specification, the menu is
being rewritten directly in views/.

This change adds the remaining buttons that may appear in the menu, as
well as adding the ability to specify which buttons are displayed and
firing an event when the button is pressed.

This code is not yet used by the feature; it will be fully incorporated
in a follow-up change.

Relnotes: N/A
Bug: 973719
Change-Id: Ibc3c820b2ad791ee8107ce86da75ba52471e71ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2151826
Commit-Queue: Anastasia Helfinstein <anastasi@google.com>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarDavid Tseng <dtseng@chromium.org>
Auto-Submit: Anastasia Helfinstein <anastasi@google.com>
Cr-Commit-Position: refs/heads/master@{#762077}
parent 0b4c5871
...@@ -679,9 +679,30 @@ This file contains the strings for ash. ...@@ -679,9 +679,30 @@ This file contains the strings for ash.
<message name="IDS_ASH_SWITCH_ACCESS_BACK_BUTTON_DESCRIPTION" desc="The tooltip text for the Switch Access back button. The back button allows users to exit the feature's current focus area."> <message name="IDS_ASH_SWITCH_ACCESS_BACK_BUTTON_DESCRIPTION" desc="The tooltip text for the Switch Access back button. The back button allows users to exit the feature's current focus area.">
Back button Back button
</message> </message>
<message name="IDS_ASH_SWITCH_ACCESS_DECREMENT" desc="The label for the Switch Access menu option to decrement the selected input.">
Decrement
</message>
<message name="IDS_ASH_SWITCH_ACCESS_DICTATION" desc="The label for the Switch Access menu option to dictate into the focused input.">
Dictation
</message>
<message name="IDS_ASH_SWITCH_ACCESS_INCREMENT" desc="The label for the Switch Access menu option to increment the selected input.">
Increment
</message>
<message name="IDS_ASH_SWITCH_ACCESS_KEYBOARD" desc="The label for the Switch Access menu option to open the onscreen keyboard.">
Keyboard
</message>
<message name="IDS_ASH_SWITCH_ACCESS_SCROLL_DOWN" desc="The label for the Switch Access menu option to scroll the selected view down."> <message name="IDS_ASH_SWITCH_ACCESS_SCROLL_DOWN" desc="The label for the Switch Access menu option to scroll the selected view down.">
Scroll Down Scroll Down
</message> </message>
<message name="IDS_ASH_SWITCH_ACCESS_SCROLL_LEFT" desc="The label for the Switch Access menu option to scroll the selected view left.">
Scroll Left
</message>
<message name="IDS_ASH_SWITCH_ACCESS_SCROLL_RIGHT" desc="The label for the Switch Access menu option to scroll the selected view right.">
Scroll Right
</message>
<message name="IDS_ASH_SWITCH_ACCESS_SCROLL_UP" desc="The label for the Switch Access menu option to scroll the selected view up.">
Scroll Up
</message>
<message name="IDS_ASH_SWITCH_ACCESS_SELECT" desc="The label for the Switch Access menu option to select the focused element."> <message name="IDS_ASH_SWITCH_ACCESS_SELECT" desc="The label for the Switch Access menu option to select the focused element.">
Select Select
</message> </message>
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD - style license that can be # Use of this source code is governed by a BSD - style license that can be
# found in the LICENSE file. # found in the LICENSE file.
import("//build/config/chrome_build.gni") import("//build/config/chrome_build.gni")
import("//components/vector_icons/vector_icons.gni") import("//components/vector_icons/vector_icons.gni")
aggregate_vector_icons("ash_vector_icons") { aggregate_vector_icons("ash_vector_icons") {
...@@ -146,7 +146,13 @@ aggregate_vector_icons("ash_vector_icons") { ...@@ -146,7 +146,13 @@ aggregate_vector_icons("ash_vector_icons") {
"shelf_unlock_button.icon", "shelf_unlock_button.icon",
"switch_access.icon", "switch_access.icon",
"switch_access_back.icon", "switch_access_back.icon",
"switch_access_decrement.icon",
"switch_access_increment.icon",
"switch_access_keyboard.icon",
"switch_access_scroll_down.icon", "switch_access_scroll_down.icon",
"switch_access_scroll_left.icon",
"switch_access_scroll_right.icon",
"switch_access_scroll_up.icon",
"switch_access_select.icon", "switch_access_select.icon",
"switch_access_settings.icon", "switch_access_settings.icon",
"system_menu_accessibility.icon", "system_menu_accessibility.icon",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
MOVE_TO, 14, 9,
R_V_LINE_TO, 2,
H_LINE_TO, 6,
V_LINE_TO, 9,
CLOSE,
R_MOVE_TO, -4, -7,
R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
CLOSE,
R_MOVE_TO, 0, 14,
R_CUBIC_TO, -3.31f, 0, -6, -2.69f, -6, -6,
R_CUBIC_TO, 0, -3.31f, 2.69f, -6, 6, -6,
R_CUBIC_TO, 3.31f, 0, 6, 2.69f, 6, 6,
R_CUBIC_TO, 0, 3.31f, -2.69f, 6, -6, 6,
CLOSE
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
MOVE_TO, 14, 9,
R_V_LINE_TO, 2,
R_H_LINE_TO, -3,
R_V_LINE_TO, 3,
H_LINE_TO, 9,
R_V_LINE_TO, -3,
H_LINE_TO, 6,
V_LINE_TO, 9,
R_H_LINE_TO, 3,
V_LINE_TO, 6,
R_H_LINE_TO, 2,
R_V_LINE_TO, 3,
CLOSE,
R_MOVE_TO, -4, -7,
R_CUBIC_TO, -4.42f, 0, -8, 3.58f, -8, 8,
R_CUBIC_TO, 0, 4.42f, 3.58f, 8, 8, 8,
R_CUBIC_TO, 4.42f, 0, 8, -3.58f, 8, -8,
R_CUBIC_TO, 0, -4.42f, -3.58f, -8, -8, -8,
CLOSE,
R_MOVE_TO, 0, 14,
R_CUBIC_TO, -3.31f, 0, -6, -2.69f, -6, -6,
R_CUBIC_TO, 0, -3.31f, 2.69f, -6, 6, -6,
R_CUBIC_TO, 3.31f, 0, 6, 2.69f, 6, 6,
R_CUBIC_TO, 0, 3.31f, -2.69f, 6, -6, 6,
CLOSE
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 24,
MOVE_TO, 20, 7,
R_V_LINE_TO, 10,
H_LINE_TO, 4,
V_LINE_TO, 7,
R_H_LINE_TO, 16,
R_MOVE_TO, 0, -2,
H_LINE_TO, 4,
R_CUBIC_TO, -1.1f, 0, -1.99f, 0.9f, -1.99f, 2,
LINE_TO, 2, 17,
R_CUBIC_TO, 0, 1.1f, 0.9f, 2, 2, 2,
R_H_LINE_TO, 16,
R_CUBIC_TO, 1.1f, 0, 2, -0.9f, 2, -2,
V_LINE_TO, 7,
R_CUBIC_TO, 0, -1.1f, -0.9f, -2, -2, -2,
CLOSE,
R_MOVE_TO, -9, 3,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
R_H_LINE_TO, -2,
CLOSE,
R_MOVE_TO, 0, 3,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
R_H_LINE_TO, -2,
CLOSE,
MOVE_TO, 8, 8,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
H_LINE_TO, 8,
CLOSE,
R_MOVE_TO, 0, 3,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
H_LINE_TO, 8,
CLOSE,
R_MOVE_TO, -3, 0,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
H_LINE_TO, 5,
CLOSE,
R_MOVE_TO, 0, -3,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
H_LINE_TO, 5,
CLOSE,
R_MOVE_TO, 3, 6,
R_H_LINE_TO, 8,
R_V_LINE_TO, 2,
H_LINE_TO, 8,
CLOSE,
R_MOVE_TO, 6, -3,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
R_H_LINE_TO, -2,
CLOSE,
R_MOVE_TO, 0, -3,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
R_H_LINE_TO, -2,
CLOSE,
R_MOVE_TO, 3, 3,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
R_H_LINE_TO, -2,
CLOSE,
R_MOVE_TO, 0, -3,
R_H_LINE_TO, 2,
R_V_LINE_TO, 2,
R_H_LINE_TO, -2,
CLOSE
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
MOVE_TO, 10.29f, 11,
R_LINE_TO, 1.96f, 1.87f,
LINE_TO, 11.09f, 14,
LINE_TO, 7, 10,
R_LINE_TO, 4.09f, -4,
R_LINE_TO, 1.16f, 1.13f,
LINE_TO, 10.37f, 9,
H_LINE_TO, 17,
R_V_LINE_TO, 2,
CLOSE,
MOVE_TO, 3, 14,
V_LINE_TO, 6,
R_H_LINE_TO, 2,
R_V_LINE_TO, 8,
CLOSE
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
MOVE_TO, 9.71f, 9,
LINE_TO, 7.76f, 7.13f,
LINE_TO, 8.91f, 6,
LINE_TO, 13, 10,
R_LINE_TO, -4.09f, 4,
R_LINE_TO, -1.15f, -1.13f,
LINE_TO, 9.63f, 11,
H_LINE_TO, 3,
V_LINE_TO, 9,
CLOSE,
MOVE_TO, 17, 6,
R_V_LINE_TO, 8,
R_H_LINE_TO, -2,
V_LINE_TO, 6,
CLOSE
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
CANVAS_DIMENSIONS, 20,
MOVE_TO, 9, 10.29f,
R_LINE_TO, -1.87f, 1.96f,
LINE_TO, 6, 11.09f,
LINE_TO, 10, 7,
R_LINE_TO, 4, 4.09f,
R_LINE_TO, -1.13f, 1.16f,
LINE_TO, 11, 10.37f,
V_LINE_TO, 17,
H_LINE_TO, 9,
CLOSE,
MOVE_TO, 6, 3,
R_H_LINE_TO, 8,
R_V_LINE_TO, 2,
H_LINE_TO, 6,
CLOSE
...@@ -10,12 +10,32 @@ ...@@ -10,12 +10,32 @@
#include "ash/system/tray/tray_background_view.h" #include "ash/system/tray/tray_background_view.h"
#include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_constants.h"
#include "ash/system/unified/unified_system_tray_view.h" #include "ash/system/unified/unified_system_tray_view.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
namespace ash { namespace ash {
namespace { namespace {
constexpr int kBackButtonRadiusDip = 18; constexpr int kBackButtonRadiusDip = 18;
constexpr int kBackButtonDiameterDip = 2 * kBackButtonRadiusDip; constexpr int kBackButtonDiameterDip = 2 * kBackButtonRadiusDip;
// The back button should display above and to the right of the anchor rect
// provided. Because the TrayBubbleView defaults to showing the right edges
// lining up (rather than appearing off to the side) we'll add the width of the
// button to the anchor rect's width.
gfx::Rect AdjustAnchorRect(const gfx::Rect& anchor) {
gfx::Rect adjusted_anchor(anchor.x(), anchor.y(),
anchor.width() + kBackButtonDiameterDip,
anchor.height());
// Don't allow our new rect to extend past the edge of the display.
display::Display display =
display::Screen::GetScreen()->GetDisplayMatching(anchor);
adjusted_anchor.Intersect(display.bounds());
return adjusted_anchor;
}
} // namespace } // namespace
SwitchAccessBackButtonBubbleController:: SwitchAccessBackButtonBubbleController::
...@@ -31,7 +51,7 @@ void SwitchAccessBackButtonBubbleController::ShowBackButton( ...@@ -31,7 +51,7 @@ void SwitchAccessBackButtonBubbleController::ShowBackButton(
const gfx::Rect& anchor) { const gfx::Rect& anchor) {
if (widget_) { if (widget_) {
DCHECK(bubble_view_); DCHECK(bubble_view_);
bubble_view_->ChangeAnchorRect(anchor); bubble_view_->ChangeAnchorRect(AdjustAnchorRect(anchor));
return; return;
} }
...@@ -42,7 +62,7 @@ void SwitchAccessBackButtonBubbleController::ShowBackButton( ...@@ -42,7 +62,7 @@ void SwitchAccessBackButtonBubbleController::ShowBackButton(
Shell::GetContainer(Shell::GetPrimaryRootWindow(), Shell::GetContainer(Shell::GetPrimaryRootWindow(),
kShellWindowId_AccessibilityPanelContainer); kShellWindowId_AccessibilityPanelContainer);
init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect; init_params.anchor_mode = TrayBubbleView::AnchorMode::kRect;
init_params.anchor_rect = anchor; init_params.anchor_rect = AdjustAnchorRect(anchor);
init_params.is_anchored_to_status_area = false; init_params.is_anchored_to_status_area = false;
init_params.has_shadow = false; init_params.has_shadow = false;
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "ash/system/accessibility/floating_menu_button.h" #include "ash/system/accessibility/floating_menu_button.h"
#include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_constants.h"
#include "cc/paint/paint_flags.h" #include "cc/paint/paint_flags.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/mojom/ax_node_data.mojom-shared.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
...@@ -18,6 +20,10 @@ ...@@ -18,6 +20,10 @@
namespace ash { namespace ash {
namespace {
constexpr char kUniqueId[] = "switch_access_back_button";
} // namespace
SwitchAccessBackButtonView::SwitchAccessBackButtonView(int diameter) SwitchAccessBackButtonView::SwitchAccessBackButtonView(int diameter)
: diameter_(diameter), : diameter_(diameter),
back_button_( back_button_(
...@@ -34,9 +40,13 @@ SwitchAccessBackButtonView::SwitchAccessBackButtonView(int diameter) ...@@ -34,9 +40,13 @@ SwitchAccessBackButtonView::SwitchAccessBackButtonView(int diameter)
void SwitchAccessBackButtonView::ButtonPressed(views::Button* sender, void SwitchAccessBackButtonView::ButtonPressed(views::Button* sender,
const ui::Event& event) { const ui::Event& event) {
// This code should not be called presently, as the button is never shown. NotifyAccessibilityEvent(ax::mojom::Event::kClicked,
// TODO(crbug/973719): Transition to using new back button and menu which /*send_native_event=*/false);
// will be implemented using views/. }
void SwitchAccessBackButtonView::GetAccessibleNodeData(
ui::AXNodeData* node_data) {
node_data->html_attributes.push_back(std::make_pair("id", kUniqueId));
} }
const char* SwitchAccessBackButtonView::GetClassName() const { const char* SwitchAccessBackButtonView::GetClassName() const {
......
...@@ -27,6 +27,7 @@ class SwitchAccessBackButtonView : public views::View, ...@@ -27,6 +27,7 @@ class SwitchAccessBackButtonView : public views::View,
void ButtonPressed(views::Button* sender, const ui::Event& event) override; void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// views::View: // views::View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
const char* GetClassName() const override; const char* GetClassName() const override;
void OnPaint(gfx::Canvas* canvas) override; void OnPaint(gfx::Canvas* canvas) override;
......
...@@ -27,10 +27,15 @@ void SwitchAccessMenuBubbleController::ShowBackButton(const gfx::Rect& anchor) { ...@@ -27,10 +27,15 @@ void SwitchAccessMenuBubbleController::ShowBackButton(const gfx::Rect& anchor) {
back_button_controller_->ShowBackButton(anchor); back_button_controller_->ShowBackButton(anchor);
} }
void SwitchAccessMenuBubbleController::ShowMenu(const gfx::Rect& anchor) { void SwitchAccessMenuBubbleController::ShowMenu(
const gfx::Rect& anchor,
const std::vector<std::string>& actions_to_show) {
if (widget_) { if (widget_) {
DCHECK(bubble_view_); DCHECK(bubble_view_);
menu_view_->SetActions(actions_to_show);
bubble_view_->SetPreferredWidth(menu_view_->GetBubbleWidthDip());
bubble_view_->ChangeAnchorRect(anchor); bubble_view_->ChangeAnchorRect(anchor);
ShowBackButtonForMenu();
return; return;
} }
...@@ -50,6 +55,7 @@ void SwitchAccessMenuBubbleController::ShowMenu(const gfx::Rect& anchor) { ...@@ -50,6 +55,7 @@ void SwitchAccessMenuBubbleController::ShowMenu(const gfx::Rect& anchor) {
bubble_view_ = new TrayBubbleView(init_params); bubble_view_ = new TrayBubbleView(init_params);
menu_view_ = new SwitchAccessMenuView(); menu_view_ = new SwitchAccessMenuView();
menu_view_->SetActions(actions_to_show);
menu_view_->SetBorder( menu_view_->SetBorder(
views::CreateEmptyBorder(kUnifiedTopShortcutSpacing, 0, 0, 0)); views::CreateEmptyBorder(kUnifiedTopShortcutSpacing, 0, 0, 0));
bubble_view_->SetPreferredWidth(menu_view_->GetBubbleWidthDip()); bubble_view_->SetPreferredWidth(menu_view_->GetBubbleWidthDip());
...@@ -61,6 +67,7 @@ void SwitchAccessMenuBubbleController::ShowMenu(const gfx::Rect& anchor) { ...@@ -61,6 +67,7 @@ void SwitchAccessMenuBubbleController::ShowMenu(const gfx::Rect& anchor) {
widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_); widget_ = views::BubbleDialogDelegateView::CreateBubble(bubble_view_);
TrayBackgroundView::InitializeBubbleAnimations(widget_); TrayBackgroundView::InitializeBubbleAnimations(widget_);
bubble_view_->InitializeAndShowBubble(); bubble_view_->InitializeAndShowBubble();
ShowBackButtonForMenu();
} }
void SwitchAccessMenuBubbleController::CloseAll() { void SwitchAccessMenuBubbleController::CloseAll() {
...@@ -75,4 +82,9 @@ void SwitchAccessMenuBubbleController::BubbleViewDestroyed() { ...@@ -75,4 +82,9 @@ void SwitchAccessMenuBubbleController::BubbleViewDestroyed() {
widget_ = nullptr; widget_ = nullptr;
} }
void SwitchAccessMenuBubbleController::ShowBackButtonForMenu() {
gfx::Rect widget_bounds = widget_->GetWindowBoundsInScreen();
ShowBackButton(widget_bounds);
}
} // namespace ash } // namespace ash
...@@ -25,7 +25,8 @@ class ASH_EXPORT SwitchAccessMenuBubbleController ...@@ -25,7 +25,8 @@ class ASH_EXPORT SwitchAccessMenuBubbleController
const SwitchAccessMenuBubbleController&) = delete; const SwitchAccessMenuBubbleController&) = delete;
void ShowBackButton(const gfx::Rect& anchor); void ShowBackButton(const gfx::Rect& anchor);
void ShowMenu(const gfx::Rect& anchor); void ShowMenu(const gfx::Rect& anchor,
const std::vector<std::string>& actions_to_show);
void CloseAll(); void CloseAll();
// TrayBubbleView::Delegate: // TrayBubbleView::Delegate:
...@@ -34,6 +35,8 @@ class ASH_EXPORT SwitchAccessMenuBubbleController ...@@ -34,6 +35,8 @@ class ASH_EXPORT SwitchAccessMenuBubbleController
private: private:
friend class SwitchAccessMenuBubbleControllerTest; friend class SwitchAccessMenuBubbleControllerTest;
void ShowBackButtonForMenu();
std::unique_ptr<SwitchAccessBackButtonBubbleController> std::unique_ptr<SwitchAccessBackButtonBubbleController>
back_button_controller_; back_button_controller_;
......
...@@ -45,9 +45,14 @@ class SwitchAccessMenuBubbleControllerTest : public AshTestBase { ...@@ -45,9 +45,14 @@ class SwitchAccessMenuBubbleControllerTest : public AshTestBase {
} }
std::vector<SwitchAccessMenuButton*> GetMenuButtons() { std::vector<SwitchAccessMenuButton*> GetMenuButtons() {
return std::vector<SwitchAccessMenuButton*>( std::vector<SwitchAccessMenuButton*> buttons;
{GetMenuView()->scroll_down_button_, GetMenuView()->select_button_, for (views::View* button : GetMenuView()->children())
GetMenuView()->settings_button_}); buttons.push_back(static_cast<SwitchAccessMenuButton*>(button));
return buttons;
}
std::string GetName(SwitchAccessMenuButton* button) {
return button->action_name_;
} }
gfx::Rect GetBackButtonBounds() { gfx::Rect GetBackButtonBounds() {
...@@ -68,7 +73,6 @@ class SwitchAccessMenuBubbleControllerTest : public AshTestBase { ...@@ -68,7 +73,6 @@ class SwitchAccessMenuBubbleControllerTest : public AshTestBase {
// TODO(anastasi): Add more tests for closing and repositioning the button. // TODO(anastasi): Add more tests for closing and repositioning the button.
TEST_F(SwitchAccessMenuBubbleControllerTest, ShowBackButton) { TEST_F(SwitchAccessMenuBubbleControllerTest, ShowBackButton) {
EXPECT_TRUE(GetBubbleController());
gfx::Rect anchor_rect(100, 100, 0, 0); gfx::Rect anchor_rect(100, 100, 0, 0);
GetBubbleController()->ShowBackButton(anchor_rect); GetBubbleController()->ShowBackButton(anchor_rect);
...@@ -78,9 +82,9 @@ TEST_F(SwitchAccessMenuBubbleControllerTest, ShowBackButton) { ...@@ -78,9 +82,9 @@ TEST_F(SwitchAccessMenuBubbleControllerTest, ShowBackButton) {
} }
TEST_F(SwitchAccessMenuBubbleControllerTest, ShowMenu) { TEST_F(SwitchAccessMenuBubbleControllerTest, ShowMenu) {
EXPECT_TRUE(GetBubbleController());
gfx::Rect anchor_rect(10, 10, 0, 0); gfx::Rect anchor_rect(10, 10, 0, 0);
GetBubbleController()->ShowMenu(anchor_rect); GetBubbleController()->ShowMenu(anchor_rect,
{"select", "scrollDown", "settings"});
EXPECT_TRUE(GetMenuView()); EXPECT_TRUE(GetMenuView());
for (SwitchAccessMenuButton* button : GetMenuButtons()) { for (SwitchAccessMenuButton* button : GetMenuButtons()) {
...@@ -91,4 +95,29 @@ TEST_F(SwitchAccessMenuBubbleControllerTest, ShowMenu) { ...@@ -91,4 +95,29 @@ TEST_F(SwitchAccessMenuBubbleControllerTest, ShowMenu) {
EXPECT_EQ(GetMenuView()->width(), GetExpectedBubbleWidth()); EXPECT_EQ(GetMenuView()->width(), GetExpectedBubbleWidth());
} }
TEST_F(SwitchAccessMenuBubbleControllerTest, SetActions) {
gfx::Rect anchor_rect(10, 10, 0, 0);
GetBubbleController()->ShowMenu(anchor_rect,
{"select", "scrollDown", "settings"});
EXPECT_TRUE(GetMenuView());
std::vector<SwitchAccessMenuButton*> buttons = GetMenuButtons();
EXPECT_EQ(3ul, buttons.size());
EXPECT_EQ("select", GetName(buttons[0]));
EXPECT_EQ("scrollDown", GetName(buttons[1]));
EXPECT_EQ("settings", GetName(buttons[2]));
GetBubbleController()->ShowMenu(
anchor_rect,
{"keyboard", "dictation", "increment", "decrement", "settings"});
buttons = GetMenuButtons();
EXPECT_EQ(5ul, buttons.size());
EXPECT_EQ("keyboard", GetName(buttons[0]));
EXPECT_EQ("dictation", GetName(buttons[1]));
EXPECT_EQ("increment", GetName(buttons[2]));
EXPECT_EQ("decrement", GetName(buttons[3]));
EXPECT_EQ("settings", GetName(buttons[4]));
}
} // namespace ash } // namespace ash
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#include "ash/system/accessibility/switch_access_menu_button.h" #include "ash/system/accessibility/switch_access_menu_button.h"
#include "ash/style/ash_color_provider.h" #include "ash/style/ash_color_provider.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/mojom/ax_node_data.mojom-shared.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/paint_vector_icon.h"
...@@ -29,10 +31,11 @@ constexpr int kLabelTopPaddingSmallDip = 8; ...@@ -29,10 +31,11 @@ constexpr int kLabelTopPaddingSmallDip = 8;
constexpr int kTextLineHeightDip = 20; constexpr int kTextLineHeightDip = 20;
} // namespace } // namespace
SwitchAccessMenuButton::SwitchAccessMenuButton(views::ButtonListener* listener, SwitchAccessMenuButton::SwitchAccessMenuButton(std::string action_name,
const gfx::VectorIcon& icon, const gfx::VectorIcon& icon,
int label_text_id) int label_text_id)
: views::Button(listener), : views::Button(this),
action_name_(action_name),
image_view_(new views::ImageView()), image_view_(new views::ImageView()),
label_(new views::Label(l10n_util::GetStringUTF16(label_text_id), label_(new views::Label(l10n_util::GetStringUTF16(label_text_id),
views::style::CONTEXT_BUTTON)) { views::style::CONTEXT_BUTTON)) {
...@@ -73,4 +76,16 @@ SwitchAccessMenuButton::SwitchAccessMenuButton(views::ButtonListener* listener, ...@@ -73,4 +76,16 @@ SwitchAccessMenuButton::SwitchAccessMenuButton(views::ButtonListener* listener,
SetLayoutManager(std::move(layout)); SetLayoutManager(std::move(layout));
} }
void SwitchAccessMenuButton::ButtonPressed(views::Button* sender,
const ui::Event& event) {
NotifyAccessibilityEvent(ax::mojom::Event::kClicked,
/*send_native_event=*/false);
}
void SwitchAccessMenuButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
views::Button::GetAccessibleNodeData(node_data);
node_data->AddStringAttribute(ax::mojom::StringAttribute::kValue,
action_name_);
}
} // namespace ash } // namespace ash
...@@ -18,9 +18,10 @@ class Label; ...@@ -18,9 +18,10 @@ class Label;
namespace ash { namespace ash {
class SwitchAccessMenuButton : public views::Button { class SwitchAccessMenuButton : public views::Button,
public views::ButtonListener {
public: public:
SwitchAccessMenuButton(views::ButtonListener* listener, SwitchAccessMenuButton(std::string action_name,
const gfx::VectorIcon& icon, const gfx::VectorIcon& icon,
int accessible_name_id); int accessible_name_id);
~SwitchAccessMenuButton() override = default; ~SwitchAccessMenuButton() override = default;
...@@ -30,7 +31,17 @@ class SwitchAccessMenuButton : public views::Button { ...@@ -30,7 +31,17 @@ class SwitchAccessMenuButton : public views::Button {
static constexpr int kWidthDip = 80; static constexpr int kWidthDip = 80;
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// views::View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
private: private:
friend class SwitchAccessMenuBubbleControllerTest;
std::string action_name_;
// Owned by the views hierarchy. // Owned by the views hierarchy.
views::ImageView* image_view_; views::ImageView* image_view_;
views::Label* label_; views::Label* label_;
......
...@@ -4,34 +4,68 @@ ...@@ -4,34 +4,68 @@
#include "ash/system/accessibility/switch_access_menu_view.h" #include "ash/system/accessibility/switch_access_menu_view.h"
#include "ash/accessibility/accessibility_controller_impl.h"
#include "ash/resources/vector_icons/vector_icons.h" #include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h" #include "ash/strings/grit/ash_strings.h"
#include "ash/system/accessibility/switch_access_menu_button.h" #include "ash/system/accessibility/switch_access_menu_button.h"
#include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_constants.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/mojom/ax_node_data.mojom-shared.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
namespace ash { namespace ash {
SwitchAccessMenuView::SwitchAccessMenuView() namespace {
: scroll_down_button_( constexpr char kUniqueId[] = "switch_access_menu_view";
new SwitchAccessMenuButton(this,
kSwitchAccessScrollDownIcon, struct ButtonInfo {
IDS_ASH_SWITCH_ACCESS_SCROLL_DOWN)), const char* name;
select_button_(new SwitchAccessMenuButton(this, const gfx::VectorIcon* icon;
kSwitchAccessSelectIcon, int label_id;
IDS_ASH_SWITCH_ACCESS_SELECT)), };
settings_button_(
new SwitchAccessMenuButton(this, // These strings must match the values of
kSwitchAccessSettingsIcon, // accessibility_private::SwitchAccessMenuAction.
IDS_ASH_SWITCH_ACCESS_SETTINGS)) { const ButtonInfo kMenuButtonDetails[] = {
{"decrement", &kSwitchAccessDecrementIcon, IDS_ASH_SWITCH_ACCESS_DECREMENT},
{"dictation", &kDictationOnNewuiIcon, IDS_ASH_SWITCH_ACCESS_DICTATION},
{"increment", &kSwitchAccessIncrementIcon, IDS_ASH_SWITCH_ACCESS_INCREMENT},
{"keyboard", &kSwitchAccessKeyboardIcon, IDS_ASH_SWITCH_ACCESS_KEYBOARD},
{"scrollDown", &kSwitchAccessScrollDownIcon,
IDS_ASH_SWITCH_ACCESS_SCROLL_DOWN},
{"scrollLeft", &kSwitchAccessScrollLeftIcon,
IDS_ASH_SWITCH_ACCESS_SCROLL_LEFT},
{"scrollRight", &kSwitchAccessScrollRightIcon,
IDS_ASH_SWITCH_ACCESS_SCROLL_RIGHT},
{"scrollUp", &kSwitchAccessScrollUpIcon, IDS_ASH_SWITCH_ACCESS_SCROLL_UP},
{"select", &kSwitchAccessSelectIcon, IDS_ASH_SWITCH_ACCESS_SELECT},
{"settings", &kSwitchAccessSettingsIcon, IDS_ASH_SWITCH_ACCESS_SETTINGS},
};
} // namespace
SwitchAccessMenuView::SwitchAccessMenuView() {
SetLayoutManager(std::make_unique<views::BoxLayout>( SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, kUnifiedMenuItemPadding, views::BoxLayout::Orientation::kHorizontal, kUnifiedMenuItemPadding,
kUnifiedMenuPadding)); kUnifiedMenuPadding));
}
SwitchAccessMenuView::~SwitchAccessMenuView() {}
void SwitchAccessMenuView::SetActions(std::vector<std::string> actions) {
RemoveAllChildViews(/*delete_children=*/true);
AddChildView(select_button_); for (std::string action : actions) {
AddChildView(scroll_down_button_); for (ButtonInfo info : kMenuButtonDetails) {
AddChildView(settings_button_); if (action == info.name) {
AddChildView(
new SwitchAccessMenuButton(info.name, *info.icon, info.label_id));
break;
}
}
}
} }
int SwitchAccessMenuView::GetBubbleWidthDip() const { int SwitchAccessMenuView::GetBubbleWidthDip() const {
...@@ -42,10 +76,9 @@ int SwitchAccessMenuView::GetBubbleWidthDip() const { ...@@ -42,10 +76,9 @@ int SwitchAccessMenuView::GetBubbleWidthDip() const {
kUnifiedMenuItemPadding.left() + kUnifiedMenuItemPadding.right(); kUnifiedMenuItemPadding.left() + kUnifiedMenuItemPadding.right();
} }
void SwitchAccessMenuView::ButtonPressed(views::Button* sender, void SwitchAccessMenuView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
const ui::Event& event) { node_data->role = ax::mojom::Role::kMenu;
// TODO(crbug/973719): Transition to using new back button and menu which node_data->html_attributes.push_back(std::make_pair("id", kUniqueId));
// will be implemented using views/.
} }
const char* SwitchAccessMenuView::GetClassName() const { const char* SwitchAccessMenuView::GetClassName() const {
......
...@@ -5,37 +5,31 @@ ...@@ -5,37 +5,31 @@
#ifndef ASH_SYSTEM_ACCESSIBILITY_SWITCH_ACCESS_MENU_VIEW_H_ #ifndef ASH_SYSTEM_ACCESSIBILITY_SWITCH_ACCESS_MENU_VIEW_H_
#define ASH_SYSTEM_ACCESSIBILITY_SWITCH_ACCESS_MENU_VIEW_H_ #define ASH_SYSTEM_ACCESSIBILITY_SWITCH_ACCESS_MENU_VIEW_H_
#include "ui/views/controls/button/button.h" #include <vector>
#include "base/containers/flat_map.h"
#include "ui/views/view.h" #include "ui/views/view.h"
namespace ash { namespace ash {
class SwitchAccessMenuButton;
// View for the Switch Access menu. // View for the Switch Access menu.
class SwitchAccessMenuView : public views::View, public views::ButtonListener { class SwitchAccessMenuView : public views::View {
public: public:
SwitchAccessMenuView(); SwitchAccessMenuView();
~SwitchAccessMenuView() override = default; ~SwitchAccessMenuView() override;
SwitchAccessMenuView(const SwitchAccessMenuView&) = delete; SwitchAccessMenuView(const SwitchAccessMenuView&) = delete;
SwitchAccessMenuView& operator=(const SwitchAccessMenuView&) = delete; SwitchAccessMenuView& operator=(const SwitchAccessMenuView&) = delete;
int GetBubbleWidthDip() const; int GetBubbleWidthDip() const;
void SetActions(std::vector<std::string> actions);
// views::ButtonListener:
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
// views::View: // views::View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
const char* GetClassName() const override; const char* GetClassName() const override;
private: private:
friend class SwitchAccessMenuBubbleControllerTest; friend class SwitchAccessMenuBubbleControllerTest;
// Owned by the views hierarchy.
SwitchAccessMenuButton* scroll_down_button_;
SwitchAccessMenuButton* select_button_;
SwitchAccessMenuButton* settings_button_;
}; };
} // namespace ash } // namespace ash
......
...@@ -70,6 +70,22 @@ chrome.accessibilityPrivate.SwitchAccessCommand = { ...@@ -70,6 +70,22 @@ chrome.accessibilityPrivate.SwitchAccessCommand = {
PREVIOUS: 'previous', PREVIOUS: 'previous',
}; };
/**
* @enum {string}
*/
chrome.accessibilityPrivate.SwitchAccessMenuAction = {
DECREMENT: 'decrement',
DICTATION: 'dictation',
INCREMENT: 'increment',
KEYBOARD: 'keyboard',
SCROLL_DOWN: 'scroll_down',
SCROLL_LEFT: 'scroll_left',
SCROLL_RIGHT: 'scroll_right',
SCROLL_UP: 'scroll_up',
SELECT: 'select',
SETTINGS: 'settings',
};
/** /**
* @enum {string} * @enum {string}
*/ */
......
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