Commit ce4648fe authored by Joanmarie Diggs's avatar Joanmarie Diggs Committed by Commit Bot

Emit ATK state-changed events for toggleable widgets on Aura Linux

* Emit checked state changed events for checkboxes and radio buttons.
* Emit pressed state changed events for toggle buttons.
* Emit indeterminate state changed events for tri-state widgets when
  their state becomes "mixed."
* Remove checkable state for toggle buttons.

R=dmazzoni@google.com

Bug: 866341
Change-Id: I10e08330408c6f783e202d2c81c6c70d19309d08
Reviewed-on: https://chromium-review.googlesource.com/1219726Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Joanmarie Diggs <joanmarie.diggs@gmail.com>
Cr-Commit-Position: refs/heads/master@{#590350}
parent e4b8a337
...@@ -54,10 +54,7 @@ ui::AXTreeUpdate ...@@ -54,10 +54,7 @@ ui::AXTreeUpdate
void BrowserAccessibilityManagerAuraLinux::FireFocusEvent( void BrowserAccessibilityManagerAuraLinux::FireFocusEvent(
BrowserAccessibility* node) { BrowserAccessibility* node) {
BrowserAccessibilityManager::FireFocusEvent(node); BrowserAccessibilityManager::FireFocusEvent(node);
if (node->IsNative()) { FireEvent(node, ax::mojom::Event::kFocus);
ToBrowserAccessibilityAuraLinux(node)->GetNode()->NotifyAccessibilityEvent(
ax::mojom::Event::kFocus);
}
} }
void BrowserAccessibilityManagerAuraLinux::FireSelectedEvent( void BrowserAccessibilityManagerAuraLinux::FireSelectedEvent(
...@@ -71,10 +68,16 @@ void BrowserAccessibilityManagerAuraLinux::FireSelectedEvent( ...@@ -71,10 +68,16 @@ void BrowserAccessibilityManagerAuraLinux::FireSelectedEvent(
if (!node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)) if (!node->GetBoolAttribute(ax::mojom::BoolAttribute::kSelected))
return; return;
if (node->IsNative()) { FireEvent(node, ax::mojom::Event::kSelection);
ToBrowserAccessibilityAuraLinux(node)->GetNode()->NotifyAccessibilityEvent( }
ax::mojom::Event::kSelection);
} void BrowserAccessibilityManagerAuraLinux::FireEvent(BrowserAccessibility* node,
ax::mojom::Event event) {
if (!node->IsNative())
return;
ToBrowserAccessibilityAuraLinux(node)->GetNode()->NotifyAccessibilityEvent(
event);
} }
void BrowserAccessibilityManagerAuraLinux::FireBlinkEvent( void BrowserAccessibilityManagerAuraLinux::FireBlinkEvent(
...@@ -90,6 +93,9 @@ void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent( ...@@ -90,6 +93,9 @@ void BrowserAccessibilityManagerAuraLinux::FireGeneratedEvent(
BrowserAccessibilityManager::FireGeneratedEvent(event_type, node); BrowserAccessibilityManager::FireGeneratedEvent(event_type, node);
switch (event_type) { switch (event_type) {
case Event::CHECKED_STATE_CHANGED:
FireEvent(node, ax::mojom::Event::kCheckedStateChanged);
break;
case Event::MENU_ITEM_SELECTED: case Event::MENU_ITEM_SELECTED:
case Event::SELECTED_CHANGED: case Event::SELECTED_CHANGED:
FireSelectedEvent(node); FireSelectedEvent(node);
......
...@@ -46,6 +46,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAuraLinux ...@@ -46,6 +46,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAuraLinux
const std::vector<ui::AXTreeDelegate::Change>& changes) override; const std::vector<ui::AXTreeDelegate::Change>& changes) override;
private: private:
void FireEvent(BrowserAccessibility* node, ax::mojom::Event event);
AtkObject* parent_object_; AtkObject* parent_object_;
// Give BrowserAccessibilityManager::Create access to our constructor. // Give BrowserAccessibilityManager::Create access to our constructor.
......
...@@ -423,4 +423,14 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest, ...@@ -423,4 +423,14 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("text-changed.html")); RunEventTest(FILE_PATH_LITERAL("text-changed.html"));
} }
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
AccessibilityEventsAriaCheckedChanged) {
RunEventTest(FILE_PATH_LITERAL("aria-checked-changed.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
AccessibilityEventsAriaPressedChanged) {
RunEventTest(FILE_PATH_LITERAL("aria-pressed-changed.html"));
}
} // namespace content } // namespace content
STATE-CHANGE:CHECKED:FALSE role=ROLE_RADIO_BUTTON name='radio2' ENABLED,SENSITIVE,SHOWING,VISIBLE
STATE-CHANGE:CHECKED:TRUE role=ROLE_CHECK_BOX name='checkbox1' CHECKED,ENABLED,SENSITIVE,SHOWING,VISIBLE
STATE-CHANGE:CHECKED:TRUE role=ROLE_RADIO_BUTTON name='radio1' CHECKED,ENABLED,SENSITIVE,SHOWING,VISIBLE
STATE-CHANGE:INDETERMINATE:TRUE role=ROLE_CHECK_BOX name='checkbox2' ENABLED,SENSITIVE,SHOWING,VISIBLE,INDETERMINATE
<!DOCTYPE html>
<form>
<div aria-label="checkbox1" role="checkbox" aria-checked="false"></div>
<div aria-label="checkbox2" role="checkbox" aria-checked="true"></div>
<div aria-label="radio1" role="radio" aria-checked="false"></div>
<div aria-label="radio2" role="radio" aria-checked="true"></div>
</form>
<script>
function go() {
document.querySelector('div[aria-label=checkbox1]').setAttribute('aria-checked', true);
document.querySelector('div[aria-label=checkbox2]').setAttribute('aria-checked', 'mixed');
document.querySelector('div[aria-label=radio1]').setAttribute('aria-checked', true);
document.querySelector('div[aria-label=radio2]').setAttribute('aria-checked', false);
}
</script>
STATE-CHANGE:INDETERMINATE:TRUE role=ROLE_TOGGLE_BUTTON name='button2' ENABLED,SENSITIVE,SHOWING,VISIBLE,INDETERMINATE
STATE-CHANGE:PRESSED:TRUE role=ROLE_TOGGLE_BUTTON name='button1' ENABLED,PRESSED,SENSITIVE,SHOWING,VISIBLE
<!DOCTYPE html>
<form>
<div aria-label="button1" role="button" aria-pressed="false"></div>
<div aria-label="button2" role="button" aria-pressed="true"></div>
</form>
<script>
function go() {
document.querySelector('div[aria-label=button1]').setAttribute('aria-pressed', true);
document.querySelector('div[aria-label=button2]').setAttribute('aria-pressed', 'mixed');
}
</script>
STATE-CHANGE:CHECKED:TRUE role=ROLE_CHECK_BOX name='My Checkbox' CHECKED,ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE
STATE-CHANGE:CHECKED:TRUE role=ROLE_TREE_ITEM name='Treeitem' CHECKED,ENABLED,SELECTABLE,SENSITIVE,SHOWING,VISIBLE
...@@ -1457,8 +1457,10 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) { ...@@ -1457,8 +1457,10 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
static_cast<int32_t>(ax::mojom::InvalidState::kFalse)) static_cast<int32_t>(ax::mojom::InvalidState::kFalse))
atk_state_set_add_state(atk_state_set, ATK_STATE_INVALID_ENTRY); atk_state_set_add_state(atk_state_set, ATK_STATE_INVALID_ENTRY);
#if defined(ATK_216) #if defined(ATK_216)
if (data.HasIntAttribute(ax::mojom::IntAttribute::kCheckedState)) if (data.HasIntAttribute(ax::mojom::IntAttribute::kCheckedState) &&
data.role != ax::mojom::Role::kToggleButton) {
atk_state_set_add_state(atk_state_set, ATK_STATE_CHECKABLE); atk_state_set_add_state(atk_state_set, ATK_STATE_CHECKABLE);
}
if (data.HasIntAttribute(ax::mojom::IntAttribute::kHasPopup)) if (data.HasIntAttribute(ax::mojom::IntAttribute::kHasPopup))
atk_state_set_add_state(atk_state_set, ATK_STATE_HAS_POPUP); atk_state_set_add_state(atk_state_set, ATK_STATE_HAS_POPUP);
#endif #endif
...@@ -1488,18 +1490,9 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) { ...@@ -1488,18 +1490,9 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
// Checked state // Checked state
const auto checked_state = GetData().GetCheckedState(); const auto checked_state = GetData().GetCheckedState();
switch (checked_state) { if (checked_state == ax::mojom::CheckedState::kTrue ||
case ax::mojom::CheckedState::kMixed: checked_state == ax::mojom::CheckedState::kMixed) {
atk_state_set_add_state(atk_state_set, ATK_STATE_INDETERMINATE); atk_state_set_add_state(atk_state_set, GetAtkStateTypeForCheckableNode());
break;
case ax::mojom::CheckedState::kTrue:
atk_state_set_add_state(atk_state_set,
data.role == ax::mojom::Role::kToggleButton
? ATK_STATE_PRESSED
: ATK_STATE_CHECKED);
break;
default:
break;
} }
switch (GetData().GetRestriction()) { switch (GetData().GetRestriction()) {
...@@ -1595,6 +1588,14 @@ gfx::NativeViewAccessible AXPlatformNodeAuraLinux::GetNativeViewAccessible() { ...@@ -1595,6 +1588,14 @@ gfx::NativeViewAccessible AXPlatformNodeAuraLinux::GetNativeViewAccessible() {
return atk_object_; return atk_object_;
} }
void AXPlatformNodeAuraLinux::OnCheckedStateChanged() {
DCHECK(atk_object_);
atk_object_notify_state_change(
ATK_OBJECT(atk_object_), GetAtkStateTypeForCheckableNode(),
GetData().GetCheckedState() != ax::mojom::CheckedState::kFalse);
}
AtkObject* AXPlatformNodeAuraLinux::current_focused_ = nullptr; AtkObject* AXPlatformNodeAuraLinux::current_focused_ = nullptr;
void AXPlatformNodeAuraLinux::OnFocused() { void AXPlatformNodeAuraLinux::OnFocused() {
...@@ -1664,6 +1665,9 @@ bool AXPlatformNodeAuraLinux::SelectionAndFocusAreTheSame() { ...@@ -1664,6 +1665,9 @@ bool AXPlatformNodeAuraLinux::SelectionAndFocusAreTheSame() {
void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent( void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(
ax::mojom::Event event_type) { ax::mojom::Event event_type) {
switch (event_type) { switch (event_type) {
case ax::mojom::Event::kCheckedStateChanged:
OnCheckedStateChanged();
break;
case ax::mojom::Event::kFocus: case ax::mojom::Event::kFocus:
case ax::mojom::Event::kFocusContext: case ax::mojom::Event::kFocusContext:
OnFocused(); OnFocused();
...@@ -1776,6 +1780,14 @@ AtkAttributeSet* AXPlatformNodeAuraLinux::GetAtkAttributes() { ...@@ -1776,6 +1780,14 @@ AtkAttributeSet* AXPlatformNodeAuraLinux::GetAtkAttributes() {
return attribute_list; return attribute_list;
} }
AtkStateType AXPlatformNodeAuraLinux::GetAtkStateTypeForCheckableNode() {
if (GetData().GetCheckedState() == ax::mojom::CheckedState::kMixed)
return ATK_STATE_INDETERMINATE;
if (GetData().role == ax::mojom::Role::kToggleButton)
return ATK_STATE_PRESSED;
return ATK_STATE_CHECKED;
}
// AtkDocumentHelpers // AtkDocumentHelpers
const gchar* AXPlatformNodeAuraLinux::GetDocumentAttributeValue( const gchar* AXPlatformNodeAuraLinux::GetDocumentAttributeValue(
......
...@@ -76,6 +76,7 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase { ...@@ -76,6 +76,7 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
void GetFloatAttributeInGValue(ax::mojom::FloatAttribute attr, GValue* value); void GetFloatAttributeInGValue(ax::mojom::FloatAttribute attr, GValue* value);
// Event helpers // Event helpers
void OnCheckedStateChanged();
void OnFocused(); void OnFocused();
void OnSelected(); void OnSelected();
...@@ -120,6 +121,9 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase { ...@@ -120,6 +121,9 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
AtkObject* CreateAtkObject(); AtkObject* CreateAtkObject();
void DestroyAtkObjects(); void DestroyAtkObjects();
// The AtkStateType for a checkable node can vary depending on the role.
AtkStateType GetAtkStateTypeForCheckableNode();
// Keep information of latest AtkInterfaces mask to refresh atk object // Keep information of latest AtkInterfaces mask to refresh atk object
// interfaces accordingly if needed. // interfaces accordingly if needed.
int interface_mask_; int interface_mask_;
......
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