Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
AX: [ATK] Events missing and state incorrect for aria-activedescendant
https://bugs.webkit.org/show_bug.cgi?id=178523

Reviewed by Chris Fleizach.

Source/WebCore:

When the aria-activedescendant of an element changes, emit object:state-changed:focused.
When a focused element has a valid active descendant, do not expose the focused state on
the element, but rather on the active descendant. Also expose the focusable state on the
active descendant.

Tests: accessibility/gtk/aria-activedescendant-changed-notification.html
       accessibility/gtk/aria-activedescendant.html

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::isActiveDescendantOfFocusedContainer const):
(WebCore::AccessibilityObject::ariaActiveDescendantReferencingElements const):
* accessibility/AccessibilityObject.h:
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::shouldNotifyActiveDescendant const):
* accessibility/atk/AXObjectCacheAtk.cpp:
(WebCore::AXObjectCache::postPlatformNotification):
* accessibility/atk/WebKitAccessibleWrapperAtk.cpp:
(setAtkStateSetFromCoreObject):

LayoutTests:

* accessibility/gtk/aria-activedescendant-changed-notification-expected.txt: Added.
* accessibility/gtk/aria-activedescendant-changed-notification.html: Added.
* accessibility/gtk/aria-activedescendant-expected.txt: Added.
* accessibility/gtk/aria-activedescendant.html: Added.


Canonical link: https://commits.webkit.org/194772@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@223766 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
joanmarie committed Oct 20, 2017
1 parent f427cde commit 6a57556
Show file tree
Hide file tree
Showing 11 changed files with 223 additions and 1 deletion.
12 changes: 12 additions & 0 deletions LayoutTests/ChangeLog
@@ -1,3 +1,15 @@
2017-10-20 Joanmarie Diggs <jdiggs@igalia.com>

AX: [ATK] Events missing and state incorrect for aria-activedescendant
https://bugs.webkit.org/show_bug.cgi?id=178523

Reviewed by Chris Fleizach.

* accessibility/gtk/aria-activedescendant-changed-notification-expected.txt: Added.
* accessibility/gtk/aria-activedescendant-changed-notification.html: Added.
* accessibility/gtk/aria-activedescendant-expected.txt: Added.
* accessibility/gtk/aria-activedescendant.html: Added.

2017-10-20 Per Arne Vollan <pvollan@apple.com>

[Win] Mark http/tests/navigation/keyboard-events-during-provisional-navigation.html and
Expand Down
@@ -0,0 +1,15 @@
This tests that changing the aria-activedescendant value results in a state-changed notification.

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".


AXFocusedUIElementChanged: AXRole: AXEmbedded
AXFocusedUIElementChanged: AXRole: AXTextField
AXFocusedUIElementChanged: AXRole: AXGroup
AXFocusedUIElementChanged: AXRole: AXGroup
AXFocusedUIElementChanged: AXRole: AXGroup
AXFocusedUIElementChanged: AXRole: AXCheckBox
PASS successfullyParsed is true

TEST COMPLETE

@@ -0,0 +1,46 @@
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
</head>
<body>
<div id="content">
<div id="test1" tabindex="0" role="application">
<div id="child1" role="group">test</div>
</div>
<div id="test2" tabindex="0" role="searchbox">
<div id="child2" role="group">test</div>
</div>
<div id="test3" tabindex="0" role="group">
<div id="child3" role="checkbox">test</div>
</div>
</div>
<p id="description"></p>
<div id="console"></div>
<script>
window.jsTestIsAsync = true;
description("This tests that changing the aria-activedescendant value results in a state-changed notification.");

if (window.testRunner && window.accessibilityController) {
accessibilityController.addNotificationListener(function(element, notification) {
if (notification != "AXFocusedUIElementChanged")
return;
debug(notification + ": " + element.role);
});

for (var i = 1; i <= 3; i++) {
var container = document.getElementById("test" + i);
container.focus();
container.setAttribute("aria-activedescendant", "child" + i);
}

document.getElementById("content").style.visibility = "hidden";

window.setTimeout(function() {
accessibilityController.removeNotificationListener();
finishJSTest();
}, 0);
}
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>
33 changes: 33 additions & 0 deletions LayoutTests/accessibility/gtk/aria-activedescendant-expected.txt
@@ -0,0 +1,33 @@
This tests the exposure of aria-activedescendant

On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".



test1 descendant: ''
parent AXRole: AXEmbedded, isFocusable: true, isFocused: true
child1 AXRole: AXGroup, isFocusable: false, isFocused: false

test2 descendant: 'child2'
parent AXRole: AXEmbedded, isFocusable: true, isFocused: false
child2 AXRole: AXGroup, isFocusable: true, isFocused: true

test3 descendant: ''
parent AXRole: AXTextField, isFocusable: true, isFocused: true
child3 AXRole: AXGroup, isFocusable: false, isFocused: false

test4 descendant: 'child4'
parent AXRole: AXTextField, isFocusable: true, isFocused: false
child4 AXRole: AXGroup, isFocusable: true, isFocused: true

test5 descendant: ''
parent AXRole: AXGroup, isFocusable: true, isFocused: true
child5 AXRole: AXCheckBox, isFocusable: false, isFocused: false

test6 descendant: 'child6'
parent AXRole: AXCheckBox, isFocusable: true, isFocused: true
child6 AXRole: AXCheckBox, isFocusable: true, isFocused: true
PASS successfullyParsed is true

TEST COMPLETE

54 changes: 54 additions & 0 deletions LayoutTests/accessibility/gtk/aria-activedescendant.html
@@ -0,0 +1,54 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<script src="../../resources/js-test-pre.js"></script>
</head>
<body id="body">
<div id="content">
<div id="test1" tabindex="0" aria-activedescendant="" role="application">
<div id="child1" role="group">test</div>
</div>
<div id="test2" tabindex="0" aria-activedescendant="child2" role="application">
<div id="child2" role="group">test</div>
</div>
<div id="test3" tabindex="0" aria-activedescendant="" role="searchbox">
<div id="child3" role="group">test</div>
</div>
<div id="test4" tabindex="0" aria-activedescendant="child4" role="searchbox">
<div id="child4" role="group">test</div>
</div>
<div id="test5" tabindex="0" aria-activedescendant="" role="group">
<div id="child5" role="checkbox">test</div>
</div>
<div id="test6" tabindex="0" aria-activedescendant="child6" role="group">
<div id="child6" role="checkbox">test</div>
</div>
</div>
<p id="description"></p>
<div id="console"></div>
<script>
description("This tests the exposure of aria-activedescendant");
if (window.accessibilityController) {
for (var i = 1; i <= 6; i++) {
var container = document.getElementById("test" + i);
debug("\ntest" + i + " descendant: '" + container.getAttribute("aria-activedescendant") + "'");

container.focus();
var axContainer = accessibilityController.focusedElement;
debug("parent " + axContainer.role + ", " +
"isFocusable: " + axContainer.isFocusable + ", " +
"isFocused: " + axContainer.isFocused);

var axChild = accessibilityController.accessibleElementById("child" + i);
debug("child" + i + " " + axChild.role + ", " +
"isFocusable: " + axChild.isFocusable + ", " +
"isFocused: " + axChild.isFocused);
}

document.getElementById("content").style.visibility = "hidden";
}
</script>
<script src="../../resources/js-test-post.js"></script>
</body>
</html>

26 changes: 26 additions & 0 deletions Source/WebCore/ChangeLog
@@ -1,3 +1,29 @@
2017-10-20 Joanmarie Diggs <jdiggs@igalia.com>

AX: [ATK] Events missing and state incorrect for aria-activedescendant
https://bugs.webkit.org/show_bug.cgi?id=178523

Reviewed by Chris Fleizach.

When the aria-activedescendant of an element changes, emit object:state-changed:focused.
When a focused element has a valid active descendant, do not expose the focused state on
the element, but rather on the active descendant. Also expose the focusable state on the
active descendant.

Tests: accessibility/gtk/aria-activedescendant-changed-notification.html
accessibility/gtk/aria-activedescendant.html

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::isActiveDescendantOfFocusedContainer const):
(WebCore::AccessibilityObject::ariaActiveDescendantReferencingElements const):
* accessibility/AccessibilityObject.h:
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::shouldNotifyActiveDescendant const):
* accessibility/atk/AXObjectCacheAtk.cpp:
(WebCore::AXObjectCache::postPlatformNotification):
* accessibility/atk/WebKitAccessibleWrapperAtk.cpp:
(setAtkStateSetFromCoreObject):

2017-10-20 Ms2ger <Ms2ger@igalia.com>

Add the MAX_CLIENT_WAIT_TIMEOUT_WEBGL constant to WebGL2RenderingContext.
Expand Down
17 changes: 17 additions & 0 deletions Source/WebCore/accessibility/AccessibilityObject.cpp
Expand Up @@ -3407,6 +3407,23 @@ void AccessibilityObject::ariaElementsReferencedByAttribute(AccessibilityChildre
}
}

bool AccessibilityObject::isActiveDescendantOfFocusedContainer() const
{
AccessibilityChildrenVector containers;
ariaActiveDescendantReferencingElements(containers);
for (auto& container : containers) {
if (container->isFocused())
return true;
}

return false;
}

void AccessibilityObject::ariaActiveDescendantReferencingElements(AccessibilityChildrenVector& containers) const
{
ariaElementsReferencedByAttribute(containers, aria_activedescendantAttr);
}

void AccessibilityObject::ariaControlsElements(AccessibilityChildrenVector& ariaControls) const
{
ariaElementsFromAttribute(ariaControls, aria_controlsAttr);
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/accessibility/AccessibilityObject.h
Expand Up @@ -670,6 +670,8 @@ class AccessibilityObject : public RefCounted<AccessibilityObject> {
static bool isARIAInput(AccessibilityRole);

virtual bool supportsARIAOwns() const { return false; }
bool isActiveDescendantOfFocusedContainer() const;
void ariaActiveDescendantReferencingElements(AccessibilityChildrenVector&) const;
void ariaControlsElements(AccessibilityChildrenVector&) const;
void ariaControlsReferencingElements(AccessibilityChildrenVector&) const;
void ariaDescribedByElements(AccessibilityChildrenVector&) const;
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Expand Up @@ -2395,6 +2395,11 @@ AccessibilityObject* AccessibilityRenderObject::accessibilityHitTest(const IntPo

bool AccessibilityRenderObject::shouldNotifyActiveDescendant() const
{
#if PLATFORM(GTK)
// According to the Core AAM spec, ATK expects object:state-changed:focused notifications
// whenever the active descendant changes.
return true;
#endif
// We want to notify that the combo box has changed its active descendant,
// but we do not want to change the focus, because focus should remain with the combo box.
if (isComboBox())
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/accessibility/atk/AXObjectCacheAtk.cpp
Expand Up @@ -280,6 +280,11 @@ void AXObjectCache::postPlatformNotification(AccessibilityObject* coreObject, AX
atk_object_notify_state_change(axObject, ATK_STATE_REQUIRED, coreObject->isRequired());
break;

case AXActiveDescendantChanged:
if (AccessibilityObject* descendant = coreObject->activeDescendant())
platformHandleFocusedUIElementChanged(nullptr, descendant->node());
break;

default:
break;
}
Expand Down
Expand Up @@ -962,8 +962,15 @@ static void setAtkStateSetFromCoreObject(AccessibilityObject* coreObject, AtkSta
if (coreObject->canSetFocusAttribute())
atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE);

if (coreObject->isFocused() || isTextWithCaret(coreObject))
// According to the Core AAM, if the element which is focused has a valid aria-activedescendant,
// we should not expose the focused state on the element which is actually focused, but instead
// on its active descendant.
if ((coreObject->isFocused() && !coreObject->activeDescendant()) || isTextWithCaret(coreObject))
atk_state_set_add_state(stateSet, ATK_STATE_FOCUSED);
else if (coreObject->isActiveDescendantOfFocusedContainer()) {
atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE);
atk_state_set_add_state(stateSet, ATK_STATE_FOCUSED);
}

if (coreObject->orientation() == AccessibilityOrientationHorizontal)
atk_state_set_add_state(stateSet, ATK_STATE_HORIZONTAL);
Expand Down

0 comments on commit 6a57556

Please sign in to comment.