Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qspiaccessiblebridge.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
6
7#include <atspi/atspi-constants.h>
8#include <private/qguiapplication_p.h>
9#include <qpa/qplatformintegration.h>
10#include <qstring.h>
11
12#include "atspiadaptor_p.h"
13
14#include "qspidbuscache_p.h"
16#include "dbusconnection_p.h"
18
19#if QT_CONFIG(accessibility)
20#include "deviceeventcontroller_adaptor.h"
21
23
24using namespace Qt::StringLiterals;
25
32 : cache(nullptr), dec(nullptr), dbusAdaptor(nullptr)
33{
34 dbusConnection = new DBusConnection();
35 connect(dbusConnection, SIGNAL(enabledChanged(bool)), this, SLOT(enabledChanged(bool)));
36 // Now that we have connected the signal, make sure we didn't miss a change,
37 // e.g. when running as root or when AT_SPI_BUS_ADDRESS is set by hand.
38 // But do that only on next loop, once dbus is really settled.
40 0, this, [this]{
41 if (dbusConnection->isEnabled() && dbusConnection->connection().isConnected())
42 enabledChanged(true);
43 });
44}
45
47{
48 setActive(enabled);
49 updateStatus();
50}
51
53{
54 delete dbusConnection;
55} // Qt currently doesn't delete plugins.
56
58{
59 return dbusConnection->connection();
60}
61
62void QSpiAccessibleBridge::updateStatus()
63{
64 // create the adaptor to handle everything if we are in enabled state
65 if (!dbusAdaptor && isActive()) {
67 initializeConstantMappings();
68
69 cache = new QSpiDBusCache(dbusConnection->connection(), this);
70 dec = new DeviceEventControllerAdaptor(this);
71
73
74 dbusAdaptor = new AtSpiAdaptor(dbusConnection, this);
76 dbusAdaptor->registerApplication();
77 }
78}
79
81{
82 if (!dbusAdaptor)
83 return;
84 if (isActive() && event->accessibleInterface())
85 dbusAdaptor->notify(event);
86}
87
88struct RoleMapping {
89 QAccessible::Role role;
90 AtspiRole spiRole;
91 const char *name;
92};
93
94static RoleMapping map[] = {
95 //: Role of an accessible object - the object is in an invalid state or could not be constructed
96 { QAccessible::NoRole, ATSPI_ROLE_INVALID, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "invalid role") },
97 //: Role of an accessible object
98 { QAccessible::TitleBar, ATSPI_ROLE_TEXT, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "title bar") },
99 //: Role of an accessible object
100 { QAccessible::MenuBar, ATSPI_ROLE_MENU_BAR, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "menu bar") },
101 //: Role of an accessible object
102 { QAccessible::ScrollBar, ATSPI_ROLE_SCROLL_BAR, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "scroll bar") },
103 //: Role of an accessible object - the grip is usually used for resizing another object
104 { QAccessible::Grip, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "grip") },
105 //: Role of an accessible object
106 { QAccessible::Sound, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "sound") },
107 //: Role of an accessible object
108 { QAccessible::Cursor, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "cursor") },
109 //: Role of an accessible object
110 { QAccessible::Caret, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "text caret") },
111 //: Role of an accessible object
112 { QAccessible::AlertMessage, ATSPI_ROLE_ALERT, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "alert message") },
113 //: Role of an accessible object: a window with frame and title
114 { QAccessible::Window, ATSPI_ROLE_FRAME, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "frame") },
115 //: Role of an accessible object
116 { QAccessible::Client, ATSPI_ROLE_FILLER, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "filler") },
117 //: Role of an accessible object
118 { QAccessible::PopupMenu, ATSPI_ROLE_POPUP_MENU, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "popup menu") },
119 //: Role of an accessible object
120 { QAccessible::MenuItem, ATSPI_ROLE_MENU_ITEM, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "menu item") },
121 //: Role of an accessible object
122 { QAccessible::ToolTip, ATSPI_ROLE_TOOL_TIP, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "tool tip") },
123 //: Role of an accessible object
124 { QAccessible::Application, ATSPI_ROLE_APPLICATION, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "application") },
125 //: Role of an accessible object
126 { QAccessible::Document, ATSPI_ROLE_DOCUMENT_FRAME, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "document") },
127 //: Role of an accessible object
128 { QAccessible::Pane, ATSPI_ROLE_PANEL, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "panel") },
129 //: Role of an accessible object
130 { QAccessible::Chart, ATSPI_ROLE_CHART, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "chart") },
131 //: Role of an accessible object
132 { QAccessible::Dialog, ATSPI_ROLE_DIALOG, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "dialog") },
133 //: Role of an accessible object
134 { QAccessible::Border, ATSPI_ROLE_FRAME, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "frame") },
135 //: Role of an accessible object
136 { QAccessible::Grouping, ATSPI_ROLE_PANEL, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "panel") },
137 //: Role of an accessible object
138 { QAccessible::Separator, ATSPI_ROLE_SEPARATOR, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "separator") },
139 //: Role of an accessible object
140 { QAccessible::ToolBar, ATSPI_ROLE_TOOL_BAR, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "tool bar") },
141 //: Role of an accessible object
142 { QAccessible::StatusBar, ATSPI_ROLE_STATUS_BAR, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "status bar") },
143 //: Role of an accessible object
144 { QAccessible::Table, ATSPI_ROLE_TABLE, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "table") },
145 //: Role of an accessible object - part of a table
146 { QAccessible::ColumnHeader, ATSPI_ROLE_TABLE_COLUMN_HEADER, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "column header") },
147 //: Role of an accessible object - part of a table
148 { QAccessible::RowHeader, ATSPI_ROLE_TABLE_ROW_HEADER, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "row header") },
149 //: Role of an accessible object - part of a table
150 { QAccessible::Column, ATSPI_ROLE_TABLE_CELL, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "column") },
151 //: Role of an accessible object - part of a table
152 { QAccessible::Row, ATSPI_ROLE_TABLE_ROW, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "row") },
153 //: Role of an accessible object - part of a table
154 { QAccessible::Cell, ATSPI_ROLE_TABLE_CELL, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "cell") },
155 //: Role of an accessible object
156 { QAccessible::Link, ATSPI_ROLE_LINK, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "link") },
157 //: Role of an accessible object
158 { QAccessible::HelpBalloon, ATSPI_ROLE_DIALOG, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "help balloon") },
159 //: Role of an accessible object - a helper dialog
160 { QAccessible::Assistant, ATSPI_ROLE_DIALOG, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "assistant") },
161 //: Role of an accessible object
162 { QAccessible::List, ATSPI_ROLE_LIST, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "list") },
163 //: Role of an accessible object
164 { QAccessible::ListItem, ATSPI_ROLE_LIST_ITEM, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "list item") },
165 //: Role of an accessible object
166 { QAccessible::Tree, ATSPI_ROLE_TREE, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "tree") },
167 //: Role of an accessible object
168 { QAccessible::TreeItem, ATSPI_ROLE_TABLE_CELL, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "tree item") },
169 //: Role of an accessible object
170 { QAccessible::PageTab, ATSPI_ROLE_PAGE_TAB, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "page tab") },
171 //: Role of an accessible object
172 { QAccessible::PropertyPage, ATSPI_ROLE_PAGE_TAB, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "property page") },
173 //: Role of an accessible object
174 { QAccessible::Indicator, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "indicator") },
175 //: Role of an accessible object
176 { QAccessible::Graphic, ATSPI_ROLE_IMAGE, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "graphic") },
177 //: Role of an accessible object
178 { QAccessible::StaticText, ATSPI_ROLE_LABEL, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "label") },
179 //: Role of an accessible object
180 { QAccessible::EditableText, ATSPI_ROLE_TEXT, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "text") },
181 //: Role of an accessible object
182 { QAccessible::PushButton, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "push button") },
183 //: Role of an accessible object
184 { QAccessible::CheckBox, ATSPI_ROLE_CHECK_BOX, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "check box") },
185 //: Role of an accessible object
186 { QAccessible::RadioButton, ATSPI_ROLE_RADIO_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "radio button") },
187 //: Role of an accessible object
188 { QAccessible::ComboBox, ATSPI_ROLE_COMBO_BOX, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "combo box") },
189 //: Role of an accessible object
190 { QAccessible::ProgressBar, ATSPI_ROLE_PROGRESS_BAR, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "progress bar") },
191 //: Role of an accessible object
192 { QAccessible::Dial, ATSPI_ROLE_DIAL, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "dial") },
193 //: Role of an accessible object
194 { QAccessible::HotkeyField, ATSPI_ROLE_TEXT, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "hotkey field") },
195 //: Role of an accessible object
196 { QAccessible::Slider, ATSPI_ROLE_SLIDER, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "slider") },
197 //: Role of an accessible object
198 { QAccessible::SpinBox, ATSPI_ROLE_SPIN_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "spin box") },
199 //: Role of an accessible object
200 { QAccessible::Canvas, ATSPI_ROLE_CANVAS, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "canvas") },
201 //: Role of an accessible object
202 { QAccessible::Animation, ATSPI_ROLE_ANIMATION, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "animation") },
203 //: Role of an accessible object
204 { QAccessible::Equation, ATSPI_ROLE_TEXT, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "equation") },
205 //: Role of an accessible object
206 { QAccessible::ButtonDropDown, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button with drop down") },
207 //: Role of an accessible object
208#if ATSPI_ROLE_COUNT > 130
209 { QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON_MENU, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button menu") },
210#else
211 { QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button menu") },
212#endif
213 //: Role of an accessible object - a button that expands a grid.
214 { QAccessible::ButtonDropGrid, ATSPI_ROLE_PUSH_BUTTON, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "button with drop down grid") },
215 //: Role of an accessible object - blank space between other objects.
216 { QAccessible::Whitespace, ATSPI_ROLE_FILLER, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "space") },
217 //: Role of an accessible object
218 { QAccessible::PageTabList, ATSPI_ROLE_PAGE_TAB_LIST, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "page tab list") },
219 //: Role of an accessible object
220 { QAccessible::Clock, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "clock") },
221 //: Role of an accessible object
222 { QAccessible::Splitter, ATSPI_ROLE_SPLIT_PANE, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "splitter") },
223 //: Role of an accessible object
224 { QAccessible::LayeredPane, ATSPI_ROLE_LAYERED_PANE, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "layered pane") },
225 //: Role of an accessible object
226 { QAccessible::WebDocument, ATSPI_ROLE_DOCUMENT_WEB, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "web document") },
227 //: Role of an accessible object
228 { QAccessible::Paragraph, ATSPI_ROLE_PARAGRAPH, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "paragraph") },
229 //: Role of an accessible object
230 { QAccessible::Section, ATSPI_ROLE_SECTION, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "section") },
231 //: Role of an accessible object
232 { QAccessible::ColorChooser, ATSPI_ROLE_COLOR_CHOOSER, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "color chooser") },
233 //: Role of an accessible object
234 { QAccessible::Footer, ATSPI_ROLE_FOOTER, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "footer") },
235 //: Role of an accessible object
236 { QAccessible::Form, ATSPI_ROLE_FORM, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "form") },
237 //: Role of an accessible object
238 { QAccessible::Heading, ATSPI_ROLE_HEADING, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "heading") },
239 //: Role of an accessible object
240 { QAccessible::Note, ATSPI_ROLE_COMMENT, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "note") },
241 //: Role of an accessible object
242 { QAccessible::ComplementaryContent, ATSPI_ROLE_SECTION, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "complementary content") },
243 //: Role of an accessible object
244 { QAccessible::Terminal, ATSPI_ROLE_TERMINAL, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "terminal") },
245 //: Role of an accessible object
246 { QAccessible::Desktop, ATSPI_ROLE_DESKTOP_FRAME, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "desktop") },
247 //: Role of an accessible object
248 { QAccessible::Notification, ATSPI_ROLE_NOTIFICATION, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "notification") },
249 //: Role of an accessible object
250 { QAccessible::UserRole, ATSPI_ROLE_UNKNOWN, QT_TRANSLATE_NOOP("QSpiAccessibleBridge", "unknown") }
251};
252
253void QSpiAccessibleBridge::initializeConstantMappings()
254{
255 for (uint i = 0; i < sizeof(map) / sizeof(RoleMapping); ++i)
256 m_spiRoleMapping.insert(map[i].role, RoleNames(map[i].spiRole, QLatin1StringView(map[i].name), tr(map[i].name)));
257
258 // -1 because we have button duplicated, as PushButton and Button.
259 Q_ASSERT_X(m_spiRoleMapping.size() ==
260 QAccessible::staticMetaObject.enumerator(
261 QAccessible::staticMetaObject.indexOfEnumerator("Role")).keyCount() - 1,
262 "", "Handle all QAccessible::Role members in qSpiRoleMapping");
263}
264
266{
267 if (auto integration = QGuiApplicationPrivate::platformIntegration()) {
268 if (auto accessibility = integration->accessibility())
269 return static_cast<QSpiAccessibleBridge *>(accessibility);
270 }
271 return nullptr;
272}
273
274RoleNames QSpiAccessibleBridge::namesForRole(QAccessible::Role role)
275{
276 auto brigde = QSpiAccessibleBridge::instance();
277 return brigde ? brigde->spiRoleNames().value(role) : RoleNames();
278}
279
281
282#include "moc_qspiaccessiblebridge_p.cpp"
283#endif // QT_CONFIG(accessibility)
bool isActive
void notify(QAccessibleEvent *event)
void registerApplication()
Connects to the accessibility dbus.
QDBusConnection connection() const
Returns the DBus connection that got established.
\inmodule QtDBus
bool registerVirtualObject(const QString &path, QDBusVirtualObject *object, VirtualObjectRegisterOption options=SingleNode)
bool registerObject(const QString &path, QObject *object, RegisterOptions options=ExportAdaptors)
Registers the object object at path path and returns true if the registration was successful.
static QPlatformIntegration * platformIntegration()
qsizetype size() const noexcept
Returns the number of items in the hash.
Definition qhash.h:927
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1303
QDBusConnection dBusConnection() const
virtual ~QSpiAccessibleBridge()
static QSpiAccessibleBridge * instance()
void notifyAccessibilityUpdate(QAccessibleEvent *event) override
static RoleNames namesForRole(QAccessible::Role role)
void enabledChanged(bool enabled)
bool singleShot
whether the timer is a single-shot timer
Definition qtimer.h:22
QMap< QString, QString > map
[6]
QCache< int, Employee > cache
[0]
Combined button and popup list for selecting options.
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLuint name
struct _cl_event * event
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
#define ATSPI_DBUS_PATH_DEC
#define QSPI_OBJECT_PATH_ACCESSIBLE
void qSpiInitializeStructTypes()
#define tr(X)
#define QT_TRANSLATE_NOOP(scope, x)
unsigned int uint
Definition qtypes.h:34
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
QObject::connect nullptr