21
21
#include " ui/gfx/font_list.h"
22
22
#include " ui/gfx/geometry/insets.h"
23
23
#include " ui/native_theme/native_theme.h"
24
+ #include " ui/views/accessibility/view_accessibility.h"
24
25
#include " ui/views/border.h"
25
26
#include " ui/views/controls/label.h"
26
27
#include " ui/views/controls/tabbed_pane/tabbed_pane_listener.h"
@@ -61,24 +62,6 @@ constexpr int kLabelFontSizeDeltaHighlight = 1;
61
62
const int kHarmonyTabStripTabHeight = 32 ;
62
63
constexpr int kBorderThickness = 2 ;
63
64
64
- // The View containing the text for each tab in the tab strip.
65
- class TabLabel : public Label {
66
- public:
67
- explicit TabLabel (const base::string16& tab_title)
68
- : Label(tab_title, style::CONTEXT_LABEL, style::STYLE_TAB_ACTIVE) {}
69
-
70
- // Label:
71
- void GetAccessibleNodeData (ui::AXNodeData* data) override {
72
- // views::Tab shouldn't expose any of its children in the a11y tree.
73
- // Instead, it should provide the a11y information itself. Normally,
74
- // non-keyboard-focusable children of keyboard-focusable parents are
75
- // ignored, but Tabs only mark the currently selected tab as
76
- // keyboard-focusable. This means all unselected Tabs expose their children
77
- // to the a11y tree. To fix, manually ignore the children.
78
- data->role = ax::mojom::Role::kIgnored ;
79
- }
80
- };
81
-
82
65
} // namespace
83
66
84
67
// static
@@ -141,7 +124,7 @@ const char Tab::kViewClassName[] = "Tab";
141
124
142
125
Tab::Tab (TabbedPane* tabbed_pane, const base::string16& title, View* contents)
143
126
: tabbed_pane_(tabbed_pane),
144
- title_ (new TabLabel (title)),
127
+ title_ (new Label (title, style::CONTEXT_LABEL, style::STYLE_TAB_ACTIVE )),
145
128
tab_state_(TAB_ACTIVE),
146
129
contents_(contents) {
147
130
// Calculate the size while the font list is bold.
@@ -172,6 +155,10 @@ Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents)
172
155
// Calculate the size while the font list is normal and set the max size.
173
156
preferred_title_size_.SetToMax (title_->GetPreferredSize ());
174
157
AddChildView (title_);
158
+
159
+ // Use leaf so that name is spoken by screen reader without exposing the
160
+ // children.
161
+ GetViewAccessibility ().OverrideIsLeaf ();
175
162
}
176
163
177
164
Tab::~Tab () {}
@@ -195,6 +182,10 @@ void Tab::OnStateChanged() {
195
182
: ui::kLabelFontSizeDelta ;
196
183
switch (tab_state_) {
197
184
case TAB_INACTIVE:
185
+ // Notify assistive tools to update this tab's selected status.
186
+ // The way Chrome OS accessibility is implemented right now, firing almost
187
+ // any event will work, we just need to trigger its state to be refreshed.
188
+ NotifyAccessibilityEvent (ax::mojom::Event::kCheckedStateChanged , true );
198
189
title_->SetEnabledColor (is_highlight_mode
199
190
? kTabTitleColor_InactiveHighlight
200
191
: kTabTitleColor_InactiveBorder );
@@ -219,8 +210,7 @@ void Tab::OnStateChanged() {
219
210
}
220
211
221
212
bool Tab::OnMousePressed (const ui::MouseEvent& event) {
222
- if (event.IsOnlyLeftMouseButton () &&
223
- GetLocalBounds ().Contains (event.location ()))
213
+ if (enabled () && event.IsOnlyLeftMouseButton ())
224
214
tabbed_pane_->SelectTab (this );
225
215
return true ;
226
216
}
@@ -302,13 +292,12 @@ void Tab::GetAccessibleNodeData(ui::AXNodeData* data) {
302
292
}
303
293
304
294
bool Tab::HandleAccessibleAction (const ui::AXActionData& action_data) {
305
- if (action_data.action != ax::mojom::Action::kSetSelection || !enabled ())
306
- return false ;
307
-
308
- // It's not clear what should happen if a tab is 'deselected', so the
309
- // ax::mojom::Action::kSetSelection action will always select the tab.
310
- tabbed_pane_->SelectTab (this );
311
- return true ;
295
+ // If the assistive tool sends kSetSelection, handle it like kDoDefault.
296
+ // These generate a click event handled in Tab::OnMousePressed.
297
+ ui::AXActionData action_data_copy (action_data);
298
+ if (action_data.action == ax::mojom::Action::kSetSelection )
299
+ action_data_copy.action = ax::mojom::Action::kDoDefault ;
300
+ return View::HandleAccessibleAction (action_data_copy);
312
301
}
313
302
314
303
void Tab::OnFocus () {
@@ -329,9 +318,16 @@ void Tab::OnBlur() {
329
318
330
319
bool Tab::OnKeyPressed (const ui::KeyEvent& event) {
331
320
ui::KeyboardCode key = event.key_code ();
332
- if (key != ui::VKEY_LEFT && key != ui::VKEY_RIGHT)
333
- return false ;
334
- return tabbed_pane_->MoveSelectionBy (key == ui::VKEY_RIGHT ? 1 : -1 );
321
+ const bool is_horizontal =
322
+ tabbed_pane_->GetOrientation () == TabbedPane::Orientation::kHorizontal ;
323
+ // Use left and right arrows to navigate tabs in horizontal orientation.
324
+ if (is_horizontal) {
325
+ return (key == ui::VKEY_LEFT || key == ui::VKEY_RIGHT) &&
326
+ tabbed_pane_->MoveSelectionBy (key == ui::VKEY_RIGHT ? 1 : -1 );
327
+ }
328
+ // Use up and down arrows to navigate tabs in vertical orientation.
329
+ return (key == ui::VKEY_UP || key == ui::VKEY_DOWN) &&
330
+ tabbed_pane_->MoveSelectionBy (key == ui::VKEY_DOWN ? 1 : -1 );
335
331
}
336
332
337
333
MdTab::MdTab (TabbedPane* tabbed_pane,
0 commit comments