[A11y] Expose presence of potential interest target
An interesttarget is an experimental HTML attribute that, along with an interestaction, allows for the target's visibility to be toggled on mouse hover. However, an AT user must be informed that there is potentially an object there. - Expose a new object attribute for "rich" interest targets that are not just plain text (plain text targets are exposed as descriptions) - Unlike the details relation, the state is exposed even if if the target is currently hidden This will allow ATs to inform users that there is an interest target present, so that they can use the command to bring it up (e.g. ctrl+insert+enter should work on JAWS, which routes the mouse cursor to the object to trigger any mouseover effects). Fixed: 377923492 Change-Id: I6103ce77154e94b14d67f6195888efc616e220f6 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6012299 Commit-Queue: Aaron Leventhal <aleventhal@chromium.org> Reviewed-by: David Tseng <dtseng@chromium.org> Reviewed-by: Mark Schillaci <mschillaci@google.com> Reviewed-by: Dominic Farolino <dom@chromium.org> Auto-Submit: Aaron Leventhal <aleventhal@chromium.org> Cr-Commit-Position: refs/heads/main@{#1383299}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
d535bdcfe9
commit
d62ef43218
chrome/browser/resources/chromeos/accessibility/definitions
content/test/data/accessibility/html
interest-target-expected-auralinux.txtinterest-target-expected-blink.txtinterest-target-expected-win.txtinterest-target.html
extensions/common/api
third_party/blink/renderer/modules/accessibility
ui/accessibility
@ -358,6 +358,7 @@ declare namespace chrome {
|
||||
FOCUSABLE = 'focusable',
|
||||
FOCUSED = 'focused',
|
||||
HAS_ACTIONS = 'hasActions',
|
||||
HAS_INTEREST_TARGET = 'hasInterestTarget',
|
||||
HORIZONTAL = 'horizontal',
|
||||
HOVERED = 'hovered',
|
||||
IGNORED = 'ignored',
|
||||
|
@ -1,7 +1,7 @@
|
||||
[document web]
|
||||
++[section] details-for=[push button]
|
||||
++++[entry] selectable-text
|
||||
++[push button] name='Button' details=[section] details-from:interest-target details-roles:*
|
||||
++[push button] name='Button' details=[section] details-from:interest-target details-roles:* has-interest-target:true
|
||||
++[push button] name='Button'
|
||||
++[section]
|
||||
++++[entry] selectable-text
|
||||
|
@ -4,7 +4,7 @@ rootWebArea
|
||||
++++++genericContainer
|
||||
++++++++textField
|
||||
++++++++++genericContainer
|
||||
++++++button name='Button' detailsFrom=interestTarget detailsIds=genericContainer
|
||||
++++++button hasInterestTarget name='Button' detailsFrom=interestTarget detailsIds=genericContainer
|
||||
++++++++staticText name='Button'
|
||||
++++++++++inlineTextBox name='Button'
|
||||
++++++button name='Button'
|
||||
|
@ -1,7 +1,7 @@
|
||||
ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
|
||||
++IA2_ROLE_SECTION
|
||||
++++ROLE_SYSTEM_TEXT FOCUSABLE
|
||||
++ROLE_SYSTEM_PUSHBUTTON name='Button' FOCUSABLE details-from:interest-target details-roles:*
|
||||
++ROLE_SYSTEM_PUSHBUTTON name='Button' FOCUSABLE has-interest-target:true details-from:interest-target details-roles:*
|
||||
++ROLE_SYSTEM_PUSHBUTTON name='Button' FOCUSABLE
|
||||
++IA2_ROLE_SECTION
|
||||
++++ROLE_SYSTEM_TEXT FOCUSABLE
|
||||
|
@ -5,14 +5,17 @@
|
||||
@WIN-ALLOW:EXPANDED*
|
||||
@WIN-ALLOW:HASPOPUP*
|
||||
@WIN-ALLOW:haspopup*
|
||||
@WIN-ALLOW:has-interest-target*
|
||||
@BLINK-ALLOW:details*
|
||||
@BLINK-ALLOW:desc*
|
||||
@BLINK-ALLOW:haspopup*
|
||||
@BLINK-ALLOW:hasInterestTarget*
|
||||
@BLINK-ALLOW:expanded*
|
||||
@AURALINUX-ALLOW:details-from*
|
||||
@AURALINUX-ALLOW:details-roles*
|
||||
@AURALINUX-ALLOW:expanded*
|
||||
@AURALINUX-ALLOW:haspopup:*
|
||||
@AURALINUX-ALLOW:has-interest-target*
|
||||
-->
|
||||
<!-- Rich interest target -->
|
||||
|
||||
|
@ -383,7 +383,8 @@
|
||||
richlyEditable,
|
||||
vertical,
|
||||
visited,
|
||||
hasActions
|
||||
hasActions,
|
||||
hasInterestTarget
|
||||
};
|
||||
|
||||
// All possible actions that can be performed on automation nodes.
|
||||
|
@ -2564,7 +2564,7 @@ void AXObject::SerializeUnignoredAttributes(ui::AXNodeData* node_data,
|
||||
}
|
||||
}
|
||||
|
||||
// Check for presence of aria-actions. Even if the value is empty because the
|
||||
// Check for presence of aria-actions. Even if the value is empty or the
|
||||
// targets are hidden, we still want to expose that there could be actions.
|
||||
if (RuntimeEnabledFeatures::AriaActionsEnabled() &&
|
||||
HasAriaAttribute(html_names::kAriaActionsAttr)) {
|
||||
@ -2611,6 +2611,19 @@ void AXObject::SerializeComputedDetailsRelation(
|
||||
return;
|
||||
}
|
||||
|
||||
// Add aria-details for a interest target.
|
||||
if (AXObject* interest_popover = GetInterestTargetForInvoker()) {
|
||||
// Add state even if the target is hidden.
|
||||
node_data->AddState(ax::mojom::blink::State::kHasInterestTarget);
|
||||
if (interest_popover->IsVisible()) {
|
||||
node_data->AddIntListAttribute(
|
||||
ax::mojom::blink::IntListAttribute::kDetailsIds,
|
||||
{static_cast<int32_t>(interest_popover->AXObjectID())});
|
||||
node_data->SetDetailsFrom(ax::mojom::blink::DetailsFrom::kInterestTarget);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add aria-details for a popover invoker.
|
||||
if (AXObject* popover = GetPopoverTargetForInvoker()) {
|
||||
node_data->AddIntListAttribute(
|
||||
@ -2620,15 +2633,6 @@ void AXObject::SerializeComputedDetailsRelation(
|
||||
return;
|
||||
}
|
||||
|
||||
// Add aria-details for a popover invoker.
|
||||
if (AXObject* interest_popover = GetInterestTargetForInvoker()) {
|
||||
node_data->AddIntListAttribute(
|
||||
ax::mojom::blink::IntListAttribute::kDetailsIds,
|
||||
{static_cast<int32_t>(interest_popover->AXObjectID())});
|
||||
node_data->SetDetailsFrom(ax::mojom::blink::DetailsFrom::kInterestTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add aria-details for the element anchored to this object.
|
||||
if (AXObject* positioned_obj = GetPositionedObjectForAnchor(node_data)) {
|
||||
node_data->AddIntListAttribute(
|
||||
@ -2719,7 +2723,7 @@ AXObject* AXObject::GetInterestTargetForInvoker() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ax_popover->IsVisible() ? ax_popover : nullptr;
|
||||
return ax_popover;
|
||||
}
|
||||
|
||||
AXObject* AXObject::GetPositionedObjectForAnchor(ui::AXNodeData* data) const {
|
||||
|
@ -905,6 +905,8 @@ class MODULES_EXPORT AXObject : public GarbageCollected<AXObject> {
|
||||
AXObject* GetPopoverTargetForInvoker() const;
|
||||
|
||||
// Heuristic to get the interest target for an invoking element.
|
||||
// Returns null if the interest target points to plain content and can be
|
||||
// expose as a description instead.
|
||||
AXObject* GetInterestTargetForInvoker() const;
|
||||
|
||||
// Elements can be positioned relative to other elements with CSS anchor
|
||||
|
@ -1018,6 +1018,8 @@ const char* ToString(ax::mojom::State state) {
|
||||
return "focusable";
|
||||
case ax::mojom::State::kHasActions:
|
||||
return "hasActions";
|
||||
case ax::mojom::State::kHasInterestTarget:
|
||||
return "hasInterestTarget";
|
||||
case ax::mojom::State::kHorizontal:
|
||||
return "horizontal";
|
||||
case ax::mojom::State::kHovered:
|
||||
|
@ -359,8 +359,8 @@ enum Role {
|
||||
|
||||
// Bitfield value. Each state can either be true or false.
|
||||
//
|
||||
// Next version: 2
|
||||
// Next value: 20
|
||||
// Next version: 3
|
||||
// Next value: 21
|
||||
[Extensible, Stable, Uuid="35e7123a-f31f-4de7-94a4-3412dcb6bd5a"]
|
||||
enum State {
|
||||
[Default]kNone = 0,
|
||||
@ -386,6 +386,7 @@ enum State {
|
||||
kVertical = 17,
|
||||
kVisited = 18,
|
||||
[MinVersion=1] kHasActions = 19,
|
||||
[MinVersion=2] kHasInterestTarget = 20,
|
||||
};
|
||||
|
||||
// An action to be taken on an accessibility node.
|
||||
|
@ -1373,6 +1373,10 @@ void AXPlatformNodeBase::ComputeAttributes(PlatformAttributeList* attributes) {
|
||||
AddAttributeToList("haspopup", "menu", attributes);
|
||||
}
|
||||
|
||||
if (HasState(ax::mojom::State::kHasInterestTarget)) {
|
||||
AddAttributeToList("has-interest-target", "true", attributes);
|
||||
}
|
||||
|
||||
// Expose the aria-ispopup attribute.
|
||||
int32_t is_popup;
|
||||
if (GetIntAttribute(ax::mojom::IntAttribute::kIsPopup, &is_popup)) {
|
||||
|
@ -628,6 +628,7 @@ const char* const ATK_OBJECT_ATTRIBUTES[] = {
|
||||
"explicit-name",
|
||||
"grabbed",
|
||||
"haspopup",
|
||||
"has-interest-target",
|
||||
"hidden",
|
||||
"id",
|
||||
"keyshortcuts",
|
||||
|
Reference in New Issue
Block a user