Bug 1954205 - Unify AT-SPI interface generation for local and remote. r=Jamie
Had to get rid of dependency on MustPrune because this happens at instantiaton. If an accessible loses or gains a child in its lifetime the interfaces it supports cannot change. Differential Revision: https://phabricator.services.mozilla.com/D241690
This commit is contained in:
@@ -269,6 +269,56 @@ void AccessibleWrap::Shutdown() {
|
||||
LocalAccessible::Shutdown();
|
||||
}
|
||||
|
||||
static uint16_t CreateMaiInterfaces(Accessible* aAccessible) {
|
||||
uint16_t interfaces = 1 << MAI_INTERFACE_COMPONENT;
|
||||
|
||||
if (aAccessible->IsHyperText() && aAccessible->IsTextRole()) {
|
||||
interfaces |= (1 << MAI_INTERFACE_HYPERTEXT) | (1 << MAI_INTERFACE_TEXT) |
|
||||
(1 << MAI_INTERFACE_EDITABLE_TEXT);
|
||||
}
|
||||
|
||||
if (aAccessible->IsLink()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
|
||||
}
|
||||
|
||||
if (aAccessible->HasNumericValue()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_VALUE;
|
||||
}
|
||||
|
||||
if (aAccessible->IsTable()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_TABLE;
|
||||
}
|
||||
|
||||
if (aAccessible->IsTableCell()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_TABLE_CELL;
|
||||
}
|
||||
|
||||
if (aAccessible->IsImage()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_IMAGE;
|
||||
}
|
||||
|
||||
if (aAccessible->IsDoc()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_DOCUMENT;
|
||||
}
|
||||
|
||||
if (aAccessible->IsSelect()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_SELECTION;
|
||||
}
|
||||
|
||||
if (aAccessible->IsRemote()) {
|
||||
if (aAccessible->IsActionable()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_ACTION;
|
||||
}
|
||||
} else {
|
||||
// XXX: Harmonize this with remote accessibles
|
||||
if (aAccessible->ActionCount()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_ACTION;
|
||||
}
|
||||
}
|
||||
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
void AccessibleWrap::GetNativeInterface(void** aOutAccessible) {
|
||||
*aOutAccessible = nullptr;
|
||||
|
||||
@@ -279,7 +329,7 @@ void AccessibleWrap::GetNativeInterface(void** aOutAccessible) {
|
||||
return;
|
||||
}
|
||||
|
||||
GType type = GetMaiAtkType(CreateMaiInterfaces());
|
||||
GType type = GetMaiAtkType(CreateMaiInterfaces(this));
|
||||
if (!type) return;
|
||||
|
||||
mAtkObject = reinterpret_cast<AtkObject*>(g_object_new(type, nullptr));
|
||||
@@ -307,52 +357,6 @@ AtkObject* AccessibleWrap::GetAtkObject(LocalAccessible* acc) {
|
||||
return atkObjPtr ? ATK_OBJECT(atkObjPtr) : nullptr;
|
||||
}
|
||||
|
||||
/* private */
|
||||
uint16_t AccessibleWrap::CreateMaiInterfaces(void) {
|
||||
uint16_t interfacesBits = 0;
|
||||
|
||||
// The Component interface is supported by all accessibles.
|
||||
interfacesBits |= 1 << MAI_INTERFACE_COMPONENT;
|
||||
|
||||
// Add Action interface if the action count is more than zero.
|
||||
if (ActionCount() > 0) interfacesBits |= 1 << MAI_INTERFACE_ACTION;
|
||||
|
||||
// Text, Editabletext, and Hypertext interface.
|
||||
HyperTextAccessible* hyperText = AsHyperText();
|
||||
if (hyperText && hyperText->IsTextRole()) {
|
||||
interfacesBits |= 1 << MAI_INTERFACE_TEXT;
|
||||
interfacesBits |= 1 << MAI_INTERFACE_EDITABLE_TEXT;
|
||||
if (!nsAccUtils::MustPrune(this)) {
|
||||
interfacesBits |= 1 << MAI_INTERFACE_HYPERTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
// Value interface.
|
||||
if (HasNumericValue()) interfacesBits |= 1 << MAI_INTERFACE_VALUE;
|
||||
|
||||
// Document interface.
|
||||
if (IsDoc()) interfacesBits |= 1 << MAI_INTERFACE_DOCUMENT;
|
||||
|
||||
if (IsImage()) interfacesBits |= 1 << MAI_INTERFACE_IMAGE;
|
||||
|
||||
// HyperLink interface.
|
||||
if (IsLink()) interfacesBits |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
|
||||
|
||||
if (!nsAccUtils::MustPrune(this)) { // These interfaces require children
|
||||
// Table interface.
|
||||
if (AsTable()) interfacesBits |= 1 << MAI_INTERFACE_TABLE;
|
||||
|
||||
if (AsTableCell()) interfacesBits |= 1 << MAI_INTERFACE_TABLE_CELL;
|
||||
|
||||
// Selection interface.
|
||||
if (IsSelect()) {
|
||||
interfacesBits |= 1 << MAI_INTERFACE_SELECTION;
|
||||
}
|
||||
}
|
||||
|
||||
return interfacesBits;
|
||||
}
|
||||
|
||||
static GType GetMaiAtkType(uint16_t interfacesBits) {
|
||||
GType type;
|
||||
static const GTypeInfo tinfo = {
|
||||
@@ -886,56 +890,10 @@ AtkObject* GetWrapperFor(Accessible* aAcc) {
|
||||
return AccessibleWrap::GetAtkObject(aAcc->AsLocal());
|
||||
}
|
||||
|
||||
static uint16_t GetInterfacesForProxy(RemoteAccessible* aProxy) {
|
||||
uint16_t interfaces = 1 << MAI_INTERFACE_COMPONENT;
|
||||
|
||||
if (aProxy->IsHyperText() && aProxy->IsTextRole()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_TEXT;
|
||||
interfaces |= 1 << MAI_INTERFACE_EDITABLE_TEXT;
|
||||
if (!nsAccUtils::MustPrune(aProxy)) {
|
||||
interfaces |= 1 << MAI_INTERFACE_HYPERTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
if (aProxy->IsLink()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
|
||||
}
|
||||
|
||||
if (aProxy->HasNumericValue()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_VALUE;
|
||||
}
|
||||
|
||||
if (aProxy->IsTable()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_TABLE;
|
||||
}
|
||||
|
||||
if (aProxy->IsTableCell()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_TABLE_CELL;
|
||||
}
|
||||
|
||||
if (aProxy->IsImage()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_IMAGE;
|
||||
}
|
||||
|
||||
if (aProxy->IsDoc()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_DOCUMENT;
|
||||
}
|
||||
|
||||
if (aProxy->IsSelect()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_SELECTION;
|
||||
}
|
||||
|
||||
if (aProxy->IsActionable()) {
|
||||
interfaces |= 1 << MAI_INTERFACE_ACTION;
|
||||
}
|
||||
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
void a11y::ProxyCreated(RemoteAccessible* aProxy) {
|
||||
MOZ_ASSERT(aProxy->RemoteParent() || aProxy->IsDoc(),
|
||||
"Need parent to check for HyperLink interface");
|
||||
GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy));
|
||||
GType type = GetMaiAtkType(CreateMaiInterfaces(aProxy));
|
||||
NS_ASSERTION(type, "why don't we have a type!");
|
||||
|
||||
AtkObject* obj = reinterpret_cast<AtkObject*>(g_object_new(type, nullptr));
|
||||
|
||||
@@ -82,9 +82,6 @@ class AccessibleWrap : public LocalAccessible {
|
||||
nsresult FireAtkTextChangedEvent(AccEvent* aEvent, AtkObject* aObject);
|
||||
|
||||
AtkObject* mAtkObject;
|
||||
|
||||
private:
|
||||
uint16_t CreateMaiInterfaces();
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
|
||||
@@ -11,6 +11,7 @@ prefs = [
|
||||
"accessibility.force_disabled=-1",
|
||||
]
|
||||
|
||||
["browser_atspi_interfaces.js"]
|
||||
["browser_groupPosition.js"]
|
||||
["browser_prune_children.js"]
|
||||
["browser_role.js"]
|
||||
|
||||
80
accessible/tests/browser/atk/browser_atspi_interfaces.js
Normal file
80
accessible/tests/browser/atk/browser_atspi_interfaces.js
Normal file
@@ -0,0 +1,80 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
addAccessibleTask(
|
||||
`
|
||||
<p id="p">p</p>
|
||||
<a href="https://example.com" id="link">a</a>
|
||||
<input id="range_input" type="range" min="0" max="10" value="8">
|
||||
<input id="text_input" type="text" value="hello">
|
||||
<button id="button">hello</button>`,
|
||||
async function testInterfaces() {
|
||||
await runPython(`
|
||||
global doc
|
||||
doc = getDoc()
|
||||
`);
|
||||
|
||||
async function checkInterfaces(id, expectedInterfaces) {
|
||||
let interfaces = await runPython(`
|
||||
return findByDomId(doc, "${id}").get_interfaces()
|
||||
`);
|
||||
|
||||
Assert.deepEqual(
|
||||
expectedInterfaces.slice().sort(),
|
||||
interfaces.sort(),
|
||||
`Correct interfaces for "${id}"`
|
||||
);
|
||||
}
|
||||
|
||||
await checkInterfaces("p", [
|
||||
"Accessible",
|
||||
"Collection",
|
||||
"Component",
|
||||
"EditableText",
|
||||
"Hyperlink",
|
||||
"Hypertext",
|
||||
"Text",
|
||||
]);
|
||||
await checkInterfaces("link", [
|
||||
"Accessible",
|
||||
"Action",
|
||||
"Collection",
|
||||
"Component",
|
||||
"EditableText",
|
||||
"Hyperlink",
|
||||
"Hypertext",
|
||||
"Text",
|
||||
]);
|
||||
await checkInterfaces("range_input", [
|
||||
"Accessible",
|
||||
"Collection",
|
||||
"Component",
|
||||
"Hyperlink",
|
||||
"Value",
|
||||
]);
|
||||
await checkInterfaces("text_input", [
|
||||
"Accessible",
|
||||
"Action",
|
||||
"Collection",
|
||||
"Component",
|
||||
"EditableText",
|
||||
"Hyperlink",
|
||||
"Hypertext",
|
||||
"Text",
|
||||
]);
|
||||
await checkInterfaces("button", [
|
||||
"Accessible",
|
||||
"Action",
|
||||
"Collection",
|
||||
"Component",
|
||||
"EditableText",
|
||||
"Hyperlink",
|
||||
"Hypertext",
|
||||
"Text",
|
||||
]);
|
||||
},
|
||||
{ chrome: true, topLevel: true }
|
||||
);
|
||||
Reference in New Issue
Block a user