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();
|
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) {
|
void AccessibleWrap::GetNativeInterface(void** aOutAccessible) {
|
||||||
*aOutAccessible = nullptr;
|
*aOutAccessible = nullptr;
|
||||||
|
|
||||||
@@ -279,7 +329,7 @@ void AccessibleWrap::GetNativeInterface(void** aOutAccessible) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GType type = GetMaiAtkType(CreateMaiInterfaces());
|
GType type = GetMaiAtkType(CreateMaiInterfaces(this));
|
||||||
if (!type) return;
|
if (!type) return;
|
||||||
|
|
||||||
mAtkObject = reinterpret_cast<AtkObject*>(g_object_new(type, nullptr));
|
mAtkObject = reinterpret_cast<AtkObject*>(g_object_new(type, nullptr));
|
||||||
@@ -307,52 +357,6 @@ AtkObject* AccessibleWrap::GetAtkObject(LocalAccessible* acc) {
|
|||||||
return atkObjPtr ? ATK_OBJECT(atkObjPtr) : nullptr;
|
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) {
|
static GType GetMaiAtkType(uint16_t interfacesBits) {
|
||||||
GType type;
|
GType type;
|
||||||
static const GTypeInfo tinfo = {
|
static const GTypeInfo tinfo = {
|
||||||
@@ -886,56 +890,10 @@ AtkObject* GetWrapperFor(Accessible* aAcc) {
|
|||||||
return AccessibleWrap::GetAtkObject(aAcc->AsLocal());
|
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) {
|
void a11y::ProxyCreated(RemoteAccessible* aProxy) {
|
||||||
MOZ_ASSERT(aProxy->RemoteParent() || aProxy->IsDoc(),
|
MOZ_ASSERT(aProxy->RemoteParent() || aProxy->IsDoc(),
|
||||||
"Need parent to check for HyperLink interface");
|
"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!");
|
NS_ASSERTION(type, "why don't we have a type!");
|
||||||
|
|
||||||
AtkObject* obj = reinterpret_cast<AtkObject*>(g_object_new(type, nullptr));
|
AtkObject* obj = reinterpret_cast<AtkObject*>(g_object_new(type, nullptr));
|
||||||
|
|||||||
@@ -82,9 +82,6 @@ class AccessibleWrap : public LocalAccessible {
|
|||||||
nsresult FireAtkTextChangedEvent(AccEvent* aEvent, AtkObject* aObject);
|
nsresult FireAtkTextChangedEvent(AccEvent* aEvent, AtkObject* aObject);
|
||||||
|
|
||||||
AtkObject* mAtkObject;
|
AtkObject* mAtkObject;
|
||||||
|
|
||||||
private:
|
|
||||||
uint16_t CreateMaiInterfaces();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace a11y
|
} // namespace a11y
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ prefs = [
|
|||||||
"accessibility.force_disabled=-1",
|
"accessibility.force_disabled=-1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
["browser_atspi_interfaces.js"]
|
||||||
["browser_groupPosition.js"]
|
["browser_groupPosition.js"]
|
||||||
["browser_prune_children.js"]
|
["browser_prune_children.js"]
|
||||||
["browser_role.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