Skip to content

Commit

Permalink
AX: aria-grabbed and aria-dropeffects don't work for display:contents…
Browse files Browse the repository at this point in the history
… elements

https://bugs.webkit.org/show_bug.cgi?id=255757
rdar://problem/108349820

Reviewed by Chris Fleizach.

Fix this by moving the necessary implementations from
AccessibilityRenderObject to AccessibilityNodeObject.

* LayoutTests/accessibility/mac/aria-drag-drop-expected.txt:
* LayoutTests/accessibility/mac/aria-drag-drop.html:
* Source/WebCore/accessibility/AccessibilityNodeObject.cpp:
(WebCore::AccessibilityNodeObject::supportsDropping const):
(WebCore::AccessibilityNodeObject::supportsDragging const):
(WebCore::AccessibilityNodeObject::isGrabbed):
(WebCore::AccessibilityNodeObject::determineDropEffects const):
* Source/WebCore/accessibility/AccessibilityNodeObject.h:
* Source/WebCore/accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::supportsDropping const): Deleted.
(WebCore::AccessibilityRenderObject::supportsDragging const): Deleted.
(WebCore::AccessibilityRenderObject::isGrabbed): Deleted.
(WebCore::AccessibilityRenderObject::determineDropEffects const): Deleted.
* Source/WebCore/accessibility/AccessibilityRenderObject.h:

Canonical link: https://commits.webkit.org/263249@main
  • Loading branch information
twilco committed Apr 21, 2023
1 parent 2148feb commit 3f549df
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 75 deletions.
5 changes: 5 additions & 0 deletions LayoutTests/accessibility/mac/aria-drag-drop-expected.txt
Expand Up @@ -5,6 +5,9 @@ PASS: initiallyGrabbedDiv.ariaIsGrabbed === true
PASS: initiallyUngrabbedDiv.ariaIsGrabbed === false
PASS: initiallyGrabbedDiv.isAttributeSettable('AXGrabbed') === true
PASS: initiallyUngrabbedDiv.isAttributeSettable('AXGrabbed') === true
PASS: displayContentsDiv.ariaIsGrabbed === true
PASS: displayContentsDiv.isAttributeSettable('AXGrabbed') === true
PASS: displayContentsDiv.ariaDropEffects === 'copy,move'

Setting aria-grabbed false for element #initially-grabbed-div.
PASS: initiallyGrabbedDiv.ariaIsGrabbed === false
Expand All @@ -18,3 +21,5 @@ TEST COMPLETE
drop
grab
grab
display:contents grab

66 changes: 36 additions & 30 deletions LayoutTests/accessibility/mac/aria-drag-drop.html
Expand Up @@ -9,38 +9,44 @@
<div id="dropeffect-div" tabindex=0 aria-dropeffect="copy move" role="button" aria-label="drop">drop</div>
<div id="initially-grabbed-div" tabindex=0 aria-grabbed=true role="button" aria-label="grab1">grab</div>
<div id="initially-ungrabbed-div" tabindex=0 aria-grabbed=false role="button" aria-label="grab2">grab</div>
<div id="display-contents-div" tabindex="0" aria-dropeffect="copy move" aria-grabbed="true" role="button" aria-label="grab3" style="display:contents">display:contents grab</div>

<script>
var testOutput = "This tests that the ARIA drag and drop attributes work as intended.\n\n";

if (window.accessibilityController) {
window.jsTestIsAsync = true;

var dropeffectDiv = accessibilityController.accessibleElementById("dropeffect-div");
testOutput += expect("dropeffectDiv.ariaDropEffects", "'copy,move'");

var initiallyGrabbedDiv = accessibilityController.accessibleElementById("initially-grabbed-div");
var initiallyUngrabbedDiv = accessibilityController.accessibleElementById("initially-ungrabbed-div");
testOutput += expect("initiallyGrabbedDiv.ariaIsGrabbed", "true");
testOutput += expect("initiallyUngrabbedDiv.ariaIsGrabbed", "false");
testOutput += expect("initiallyGrabbedDiv.isAttributeSettable('AXGrabbed')", "true");
testOutput += expect("initiallyUngrabbedDiv.isAttributeSettable('AXGrabbed')", "true");

testOutput += "\nSetting aria-grabbed false for element #initially-grabbed-div.\n";
document.getElementById("initially-grabbed-div").setAttribute("aria-grabbed", "false");
setTimeout(async function() {
await waitFor(() => !initiallyGrabbedDiv.ariaIsGrabbed);
testOutput += expect("initiallyGrabbedDiv.ariaIsGrabbed", "false");

testOutput += "\nSetting aria-dropeffect of #dropeffect-div to 'move'.\n";
document.getElementById("dropeffect-div").setAttribute("aria-dropeffect", "move");
await waitFor(() => dropeffectDiv.ariaDropEffects === "move");
testOutput += expect("dropeffectDiv.ariaDropEffects", "'move'");

debug(testOutput);
finishJSTest();
}, 0);
}
var testOutput = "This tests that the ARIA drag and drop attributes work as intended.\n\n";

if (window.accessibilityController) {
window.jsTestIsAsync = true;

var dropeffectDiv = accessibilityController.accessibleElementById("dropeffect-div");
testOutput += expect("dropeffectDiv.ariaDropEffects", "'copy,move'");

var initiallyGrabbedDiv = accessibilityController.accessibleElementById("initially-grabbed-div");
var initiallyUngrabbedDiv = accessibilityController.accessibleElementById("initially-ungrabbed-div");
var displayContentsDiv = accessibilityController.accessibleElementById("display-contents-div");
testOutput += expect("initiallyGrabbedDiv.ariaIsGrabbed", "true");
testOutput += expect("initiallyUngrabbedDiv.ariaIsGrabbed", "false");
testOutput += expect("initiallyGrabbedDiv.isAttributeSettable('AXGrabbed')", "true");
testOutput += expect("initiallyUngrabbedDiv.isAttributeSettable('AXGrabbed')", "true");

testOutput += expect("displayContentsDiv.ariaIsGrabbed", "true");
testOutput += expect("displayContentsDiv.isAttributeSettable('AXGrabbed')", "true");
testOutput += expect("displayContentsDiv.ariaDropEffects", "'copy,move'");

testOutput += "\nSetting aria-grabbed false for element #initially-grabbed-div.\n";
document.getElementById("initially-grabbed-div").setAttribute("aria-grabbed", "false");
setTimeout(async function() {
await waitFor(() => !initiallyGrabbedDiv.ariaIsGrabbed);
testOutput += expect("initiallyGrabbedDiv.ariaIsGrabbed", "false");

testOutput += "\nSetting aria-dropeffect of #dropeffect-div to 'move'.\n";
document.getElementById("dropeffect-div").setAttribute("aria-dropeffect", "move");
await waitFor(() => dropeffectDiv.ariaDropEffects === "move");
testOutput += expect("dropeffectDiv.ariaDropEffects", "'move'");

debug(testOutput);
finishJSTest();
}, 0);
}
</script>
</body>
</html>
Expand Down
40 changes: 40 additions & 0 deletions Source/WebCore/accessibility/AccessibilityNodeObject.cpp
Expand Up @@ -41,6 +41,7 @@
#include "ElementAncestorIteratorInlines.h"
#include "ElementChildIteratorInlines.h"
#include "Event.h"
#include "EventHandler.h"
#include "EventNames.h"
#include "FloatRect.h"
#include "FrameLoader.h"
Expand Down Expand Up @@ -817,6 +818,45 @@ String AccessibilityNodeObject::accessKey() const
return element ? element->attributeWithoutSynchronization(accesskeyAttr) : String();
}

bool AccessibilityNodeObject::supportsDropping() const
{
return determineDropEffects().size();
}

bool AccessibilityNodeObject::supportsDragging() const
{
const AtomString& grabbed = getAttribute(aria_grabbedAttr);
return equalLettersIgnoringASCIICase(grabbed, "true"_s) || equalLettersIgnoringASCIICase(grabbed, "false"_s) || hasAttribute(draggableAttr);
}

bool AccessibilityNodeObject::isGrabbed()
{
#if ENABLE(DRAG_SUPPORT)
if (mainFrame() && mainFrame()->eventHandler().draggingElement() == element())
return true;
#endif

return elementAttributeValue(aria_grabbedAttr);
}

Vector<String> AccessibilityNodeObject::determineDropEffects() const
{
// Order is aria-dropeffect, dropzone, webkitdropzone
const AtomString& dropEffects = getAttribute(aria_dropeffectAttr);
if (!dropEffects.isEmpty())
return makeStringByReplacingAll(dropEffects.string(), '\n', ' ').split(' ');

auto dropzone = getAttribute(dropzoneAttr);
if (!dropzone.isEmpty())
return Vector<String> { dropzone };

auto webkitdropzone = getAttribute(webkitdropzoneAttr);
if (!webkitdropzone.isEmpty())
return Vector<String> { webkitdropzone };

return { };
}

bool AccessibilityNodeObject::supportsARIAOwns() const
{
return !getAttribute(aria_ownsAttr).isEmpty();
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/accessibility/AccessibilityNodeObject.h
Expand Up @@ -73,6 +73,11 @@ class AccessibilityNodeObject : public AccessibilityObject {
bool supportsARIAOwns() const final;
bool supportsRequiredAttribute() const override;

bool supportsDropping() const override;
bool supportsDragging() const override;
bool isGrabbed() override;
Vector<String> determineDropEffects() const override;

bool canSetSelectedAttribute() const override;

void setNode(Node*);
Expand Down
40 changes: 0 additions & 40 deletions Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Expand Up @@ -42,7 +42,6 @@
#include "Editor.h"
#include "EditorClient.h"
#include "ElementAncestorIteratorInlines.h"
#include "EventHandler.h"
#include "FloatRect.h"
#include "FrameLoader.h"
#include "FrameSelection.h"
Expand Down Expand Up @@ -1073,45 +1072,6 @@ AXCoreObject::AccessibilityChildrenVector AccessibilityRenderObject::linkedObjec
return linkedObjects;
}

bool AccessibilityRenderObject::supportsDropping() const
{
return determineDropEffects().size();
}

bool AccessibilityRenderObject::supportsDragging() const
{
const AtomString& grabbed = getAttribute(aria_grabbedAttr);
return equalLettersIgnoringASCIICase(grabbed, "true"_s) || equalLettersIgnoringASCIICase(grabbed, "false"_s) || hasAttribute(draggableAttr);
}

bool AccessibilityRenderObject::isGrabbed()
{
#if ENABLE(DRAG_SUPPORT)
if (mainFrame() && mainFrame()->eventHandler().draggingElement() == element())
return true;
#endif

return elementAttributeValue(aria_grabbedAttr);
}

Vector<String> AccessibilityRenderObject::determineDropEffects() const
{
// Order is aria-dropeffect, dropzone, webkitdropzone
const AtomString& dropEffects = getAttribute(aria_dropeffectAttr);
if (!dropEffects.isEmpty())
return makeStringByReplacingAll(dropEffects.string(), '\n', ' ').split(' ');

auto dropzone = getAttribute(dropzoneAttr);
if (!dropzone.isEmpty())
return Vector<String> { dropzone };

auto webkitdropzone = getAttribute(webkitdropzoneAttr);
if (!webkitdropzone.isEmpty())
return Vector<String> { webkitdropzone };

return { };
}

#if ENABLE(APPLE_PAY)
String AccessibilityRenderObject::applePayButtonDescription() const
{
Expand Down
5 changes: 0 additions & 5 deletions Source/WebCore/accessibility/AccessibilityRenderObject.h
Expand Up @@ -132,11 +132,6 @@ class AccessibilityRenderObject : public AccessibilityNodeObject {
void setSelectedVisiblePositionRange(const VisiblePositionRange&) const override;
bool isVisiblePositionRangeInDifferentDocument(const VisiblePositionRange&) const;

bool supportsDropping() const override;
bool supportsDragging() const override;
bool isGrabbed() override;
Vector<String> determineDropEffects() const override;

VisiblePosition visiblePositionForPoint(const IntPoint&) const override;
VisiblePosition visiblePositionForIndex(unsigned indexValue, bool lastIndexOK) const override;
int index(const VisiblePosition&) const override;
Expand Down

0 comments on commit 3f549df

Please sign in to comment.