7#include <atspi/atspi-constants.h>
8#include <private/qguiapplication_p.h>
9#include <qpa/qplatformintegration.h>
19#if QT_CONFIG(accessibility)
20#include "deviceeventcontroller_adaptor.h"
24using namespace Qt::StringLiterals;
25using namespace QtGuiPrivate;
28
29
30
32QSpiAccessibleBridge::QSpiAccessibleBridge()
33 : cache(
nullptr), dec(
nullptr), dbusAdaptor(
nullptr)
35 dbusConnection =
new QAtSpiDBusConnection();
36 connect(dbusConnection, SIGNAL(enabledChanged(
bool)),
this, SLOT(enabledChanged(
bool)));
42 if (dbusConnection->isEnabled() && dbusConnection->connection().isConnected())
47void QSpiAccessibleBridge::enabledChanged(
bool enabled)
53QSpiAccessibleBridge::~QSpiAccessibleBridge()
55 delete dbusConnection;
58QDBusConnection QSpiAccessibleBridge::dBusConnection()
const
60 return dbusConnection->connection();
63void QSpiAccessibleBridge::updateStatus()
66 if (!dbusAdaptor && isActive()) {
67 qSpiInitializeStructTypes();
68 initializeConstantMappings();
70 cache =
new QSpiDBusCache(dbusConnection->connection(),
this);
71 dec =
new DeviceEventControllerAdaptor(
this);
73 dbusConnection->connection().registerObject(ATSPI_DBUS_PATH_DEC
""_L1,
this, QDBusConnection::ExportAdaptors);
75 dbusAdaptor =
new AtSpiAdaptor(dbusConnection,
this);
76 dbusConnection->connection().registerVirtualObject(QSPI_OBJECT_PATH_ACCESSIBLE
""_L1, dbusAdaptor, QDBusConnection::SubPath);
77 dbusAdaptor->registerApplication();
81void QSpiAccessibleBridge::notifyAccessibilityUpdate(QAccessibleEvent *event)
85 if (isActive() && event->accessibleInterface())
86 dbusAdaptor->notify(event);
90 QAccessible::Role role;
95static RoleMapping map[] = {
97 { QAccessible::NoRole, ATSPI_ROLE_INVALID, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"invalid role") },
99 { QAccessible::TitleBar, ATSPI_ROLE_TEXT, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"title bar") },
101 { QAccessible::MenuBar, ATSPI_ROLE_MENU_BAR, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"menu bar") },
103 { QAccessible::ScrollBar, ATSPI_ROLE_SCROLL_BAR, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"scroll bar") },
105 { QAccessible::Grip, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"grip") },
107 { QAccessible::Sound, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"sound") },
109 { QAccessible::Cursor, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"cursor") },
111 { QAccessible::Caret, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"text caret") },
113 { QAccessible::AlertMessage, ATSPI_ROLE_ALERT, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"alert message") },
115 { QAccessible::Window, ATSPI_ROLE_FRAME, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"frame") },
117 { QAccessible::Client, ATSPI_ROLE_FILLER, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"filler") },
119 { QAccessible::PopupMenu, ATSPI_ROLE_POPUP_MENU, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"popup menu") },
121 { QAccessible::MenuItem, ATSPI_ROLE_MENU_ITEM, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"menu item") },
123 { QAccessible::ToolTip, ATSPI_ROLE_TOOL_TIP, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"tool tip") },
125 { QAccessible::Application, ATSPI_ROLE_APPLICATION, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"application") },
127 { QAccessible::Document, ATSPI_ROLE_DOCUMENT_FRAME, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"document") },
129 { QAccessible::Pane, ATSPI_ROLE_PANEL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"panel") },
131 { QAccessible::Chart, ATSPI_ROLE_CHART, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"chart") },
133 { QAccessible::Dialog, ATSPI_ROLE_DIALOG, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"dialog") },
135 { QAccessible::Border, ATSPI_ROLE_PANEL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"panel") },
137 { QAccessible::Grouping, ATSPI_ROLE_PANEL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"panel") },
139 { QAccessible::Separator, ATSPI_ROLE_SEPARATOR, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"separator") },
141 { QAccessible::ToolBar, ATSPI_ROLE_TOOL_BAR, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"tool bar") },
143 { QAccessible::StatusBar, ATSPI_ROLE_STATUS_BAR, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"status bar") },
145 { QAccessible::Table, ATSPI_ROLE_TABLE, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"table") },
147 { QAccessible::ColumnHeader, ATSPI_ROLE_TABLE_COLUMN_HEADER, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"column header") },
149 { QAccessible::RowHeader, ATSPI_ROLE_TABLE_ROW_HEADER, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"row header") },
151 { QAccessible::Column, ATSPI_ROLE_TABLE_CELL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"column") },
153 { QAccessible::Row, ATSPI_ROLE_TABLE_ROW, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"row") },
155 { QAccessible::Cell, ATSPI_ROLE_TABLE_CELL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"cell") },
157 { QAccessible::Link, ATSPI_ROLE_LINK, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"link") },
159 { QAccessible::HelpBalloon, ATSPI_ROLE_DIALOG, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"help balloon") },
161 { QAccessible::Assistant, ATSPI_ROLE_DIALOG, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"assistant") },
163 { QAccessible::List, ATSPI_ROLE_LIST, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"list") },
165 { QAccessible::ListItem, ATSPI_ROLE_LIST_ITEM, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"list item") },
167 { QAccessible::Tree, ATSPI_ROLE_TREE, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"tree") },
169 { QAccessible::TreeItem, ATSPI_ROLE_TABLE_CELL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"tree item") },
171 { QAccessible::PageTab, ATSPI_ROLE_PAGE_TAB, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"page tab") },
173 { QAccessible::PropertyPage, ATSPI_ROLE_PAGE_TAB, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"property page") },
175 { QAccessible::Indicator, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"indicator") },
177 { QAccessible::Graphic, ATSPI_ROLE_IMAGE, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"graphic") },
179 { QAccessible::StaticText, ATSPI_ROLE_LABEL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"label") },
181 { QAccessible::EditableText, ATSPI_ROLE_TEXT, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"text") },
183 { QAccessible::PushButton, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"push button") },
185 { QAccessible::CheckBox, ATSPI_ROLE_CHECK_BOX, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"check box") },
187 { QAccessible::RadioButton, ATSPI_ROLE_RADIO_BUTTON, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"radio button") },
189 { QAccessible::ComboBox, ATSPI_ROLE_COMBO_BOX, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"combo box") },
191 { QAccessible::ProgressBar, ATSPI_ROLE_PROGRESS_BAR, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"progress bar") },
193 { QAccessible::Dial, ATSPI_ROLE_DIAL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"dial") },
195 { QAccessible::HotkeyField, ATSPI_ROLE_TEXT, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"hotkey field") },
197 { QAccessible::Slider, ATSPI_ROLE_SLIDER, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"slider") },
199 { QAccessible::SpinBox, ATSPI_ROLE_SPIN_BUTTON, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"spin box") },
201 { QAccessible::Canvas, ATSPI_ROLE_CANVAS, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"canvas") },
203 { QAccessible::Animation, ATSPI_ROLE_ANIMATION, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"animation") },
205 { QAccessible::Equation, ATSPI_ROLE_TEXT, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"equation") },
207 { QAccessible::ButtonDropDown, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"button with drop down") },
209#if ATSPI_ROLE_COUNT > 130
210 { QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON_MENU, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"button menu") },
212 { QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"button menu") },
215 { QAccessible::ButtonDropGrid, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"button with drop down grid") },
217 { QAccessible::Whitespace, ATSPI_ROLE_FILLER, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"space") },
219 { QAccessible::PageTabList, ATSPI_ROLE_PAGE_TAB_LIST, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"page tab list") },
221 { QAccessible::Clock, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"clock") },
223 { QAccessible::Splitter, ATSPI_ROLE_SPLIT_PANE, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"splitter") },
225 { QAccessible::LayeredPane, ATSPI_ROLE_LAYERED_PANE, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"layered pane") },
227 { QAccessible::WebDocument, ATSPI_ROLE_DOCUMENT_WEB, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"web document") },
229 { QAccessible::Paragraph, ATSPI_ROLE_PARAGRAPH, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"paragraph") },
231 { QAccessible::Section, ATSPI_ROLE_SECTION, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"section") },
233 { QAccessible::ColorChooser, ATSPI_ROLE_COLOR_CHOOSER, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"color chooser") },
235 { QAccessible::Footer, ATSPI_ROLE_FOOTER, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"footer") },
237 { QAccessible::Form, ATSPI_ROLE_FORM, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"form") },
239 { QAccessible::Heading, ATSPI_ROLE_HEADING, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"heading") },
241 { QAccessible::Note, ATSPI_ROLE_COMMENT, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"note") },
243 { QAccessible::ComplementaryContent, ATSPI_ROLE_SECTION, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"complementary content") },
245 { QAccessible::Terminal, ATSPI_ROLE_TERMINAL, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"terminal") },
247 { QAccessible::Desktop, ATSPI_ROLE_DESKTOP_FRAME, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"desktop") },
249 { QAccessible::Notification, ATSPI_ROLE_NOTIFICATION, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"notification") },
251 { QAccessible::BlockQuote, ATSPI_ROLE_BLOCK_QUOTE, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"block quote") },
253 { QAccessible::UserRole, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP(
"QSpiAccessibleBridge",
"unknown") }
256void QSpiAccessibleBridge::initializeConstantMappings()
258 for (uint i = 0; i <
sizeof(map) /
sizeof(RoleMapping); ++i)
259 m_spiRoleMapping.insert(map[i].role, RoleNames(map[i].spiRole, QLatin1StringView(map[i].name), tr(map[i].name)));
262 Q_ASSERT_X(m_spiRoleMapping.size() ==
263 QAccessible::staticMetaObject.enumerator(
264 QAccessible::staticMetaObject.indexOfEnumerator(
"Role")).keyCount() - 1,
265 "",
"Handle all QAccessible::Role members in qSpiRoleMapping");
268QSpiAccessibleBridge *QSpiAccessibleBridge::instance()
270 if (
auto integration = QGuiApplicationPrivate::platformIntegration()) {
271 if (
auto accessibility = integration->accessibility())
272 return static_cast<QSpiAccessibleBridge *>(accessibility);
277RoleNames QSpiAccessibleBridge::namesForRole(QAccessible::Role role)
279 auto brigde = QSpiAccessibleBridge::instance();
280 return brigde ? brigde->spiRoleNames().value(role) : RoleNames();
285#include "moc_qspiaccessiblebridge_p.cpp"