File indexing completed on 2024-11-10 04:17:46
0001 /* 0002 SPDX-FileCopyrightText: 2012 Frederik Gladhorn <gladhorn@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "registry_p.h" 0008 #include "registry.h" 0009 #include "qaccessibilityclient_debug.h" 0010 0011 #include <QDBusMessage> 0012 #include <QDBusArgument> 0013 #include <QDBusReply> 0014 #include <QDBusPendingCall> 0015 #include <QDBusArgument> 0016 #include <QDBusMetaType> 0017 0018 #include <QDBusMessage> 0019 #include <QStringList> 0020 #include <qurl.h> 0021 0022 #include "atspi/atspi-constants.h" 0023 0024 #include <QString> 0025 0026 // interface names from at-spi2-core/atspi/atspi-misc-private.h 0027 #define ATSPI_DBUS_NAME_REGISTRY "org.a11y.atspi.Registry" 0028 #define ATSPI_DBUS_PATH_REGISTRY "/org/a11y/atspi/registry" 0029 #define ATSPI_DBUS_INTERFACE_REGISTRY "org.a11y.atspi.Registry" 0030 0031 #define ATSPI_DBUS_PATH_NULL "/org/a11y/atspi/null" 0032 #define ATSPI_DBUS_PATH_ROOT "/org/a11y/atspi/accessible/root" 0033 0034 #define ATSPI_DBUS_PATH_DEC "/org/a11y/atspi/registry/deviceeventcontroller" 0035 #define ATSPI_DBUS_INTERFACE_DEC "org.a11y.atspi.DeviceEventController" 0036 #define ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER "org.a11y.atspi.DeviceEventListener" 0037 0038 #define ATSPI_DBUS_INTERFACE_CACHE "org.a11y.atspi.Cache" 0039 #define ATSPI_DBUS_INTERFACE_ACCESSIBLE "org.a11y.atspi.Accessible" 0040 #define ATSPI_DBUS_INTERFACE_ACTION "org.a11y.atspi.Action" 0041 #define ATSPI_DBUS_INTERFACE_APPLICATION "org.a11y.atspi.Application" 0042 #define ATSPI_DBUS_INTERFACE_COLLECTION "org.a11y.atspi.Collection" 0043 #define ATSPI_DBUS_INTERFACE_COMPONENT "org.a11y.atspi.Component" 0044 #define ATSPI_DBUS_INTERFACE_DOCUMENT "org.a11y.atspi.Document" 0045 #define ATSPI_DBUS_INTERFACE_EDITABLE_TEXT "org.a11y.atspi.EditableText" 0046 #define ATSPI_DBUS_INTERFACE_EVENT_KEYBOARD "org.a11y.atspi.Event.Keyboard" 0047 #define ATSPI_DBUS_INTERFACE_EVENT_MOUSE "org.a11y.atspi.Event.Mouse" 0048 #define ATSPI_DBUS_INTERFACE_EVENT_OBJECT "org.a11y.atspi.Event.Object" 0049 #define ATSPI_DBUS_INTERFACE_HYPERLINK "org.a11y.atspi.Hyperlink" 0050 #define ATSPI_DBUS_INTERFACE_HYPERTEXT "org.a11y.atspi.Hypertext" 0051 #define ATSPI_DBUS_INTERFACE_IMAGE "org.a11y.atspi.Image" 0052 #define ATSPI_DBUS_INTERFACE_SELECTION "org.a11y.atspi.Selection" 0053 #define ATSPI_DBUS_INTERFACE_TABLE "org.a11y.atspi.Table" 0054 #define ATSPI_DBUS_INTERFACE_TEXT "org.a11y.atspi.Text" 0055 #define ATSPI_DBUS_INTERFACE_VALUE "org.a11y.atspi.Value" 0056 #define ATSPI_DBUS_INTERFACE_SOCKET "org.a11y.atspi.Socket" 0057 0058 // missing from at-spi2-core: 0059 #define ATSPI_DBUS_INTERFACE_EVENT_WINDOW "org.a11y.atspi.Event.Window" 0060 #define ATSPI_DBUS_INTERFACE_EVENT_FOCUS "org.a11y.atspi.Event.Focus" 0061 0062 #define QSPI_OBJECT_PATH_ACCESSIBLE "/org/a11y/atspi/accessible" 0063 #define QSPI_OBJECT_PATH_PREFIX "/org/a11y/atspi/accessible/" 0064 #define QSPI_OBJECT_PATH_ROOT QSPI_OBJECT_PATH_PREFIX "root" 0065 0066 #define QSPI_REGISTRY_NAME "org.a11y.atspi.Registry" 0067 0068 //#define ATSPI_DEBUG 0069 0070 using namespace QAccessibleClient; 0071 0072 QString RegistryPrivate::ACCESSIBLE_OBJECT_SCHEME_STRING = QLatin1String("accessibleobject"); 0073 0074 RegistryPrivate::RegistryPrivate(Registry *qq) 0075 :q(qq) 0076 , m_subscriptions(Registry::NoEventListeners) 0077 { 0078 qDBusRegisterMetaType<QVector<quint32> >(); 0079 0080 connect(&conn, SIGNAL(connectionFetched()), this, SLOT(connectionFetched())); 0081 connect(&m_actionMapper, SIGNAL(mappedString(QString)), this, SLOT(actionTriggered(QString))); 0082 init(); 0083 } 0084 0085 RegistryPrivate::~RegistryPrivate() 0086 { 0087 delete m_cache; 0088 } 0089 0090 void RegistryPrivate::init() 0091 { 0092 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_CACHE)] = AccessibleObject::CacheInterface; 0093 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_ACCESSIBLE)] = AccessibleObject::AccessibleInterface; 0094 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_ACTION)] = AccessibleObject::ActionInterface; 0095 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_APPLICATION)] = AccessibleObject::ApplicationInterface; 0096 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_COLLECTION)] = AccessibleObject::CollectionInterface; 0097 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_COMPONENT)] = AccessibleObject::ComponentInterface; 0098 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_DOCUMENT)] = AccessibleObject::DocumentInterface; 0099 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_EDITABLE_TEXT)] = AccessibleObject::EditableTextInterface; 0100 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_KEYBOARD)] = AccessibleObject::EventKeyboardInterface; 0101 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_MOUSE)] = AccessibleObject::EventMouseInterface; 0102 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT)] = AccessibleObject::EventObjectInterface; 0103 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_HYPERLINK)] = AccessibleObject::HyperlinkInterface; 0104 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_HYPERTEXT)] = AccessibleObject::HypertextInterface; 0105 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_IMAGE)] = AccessibleObject::ImageInterface; 0106 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_SELECTION)] = AccessibleObject::SelectionInterface; 0107 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_TABLE)] = AccessibleObject::TableInterface; 0108 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_TEXT)] = AccessibleObject::TextInterface; 0109 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_VALUE)] = AccessibleObject::ValueInterface; 0110 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_SOCKET)] = AccessibleObject::SocketInterface; 0111 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_WINDOW)] = AccessibleObject::EventWindowInterface; 0112 interfaceHash[QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_FOCUS)] = AccessibleObject::EventFocusInterface; 0113 } 0114 0115 bool RegistryPrivate::isEnabled() const 0116 { 0117 if (conn.status() != DBusConnection::Connected) 0118 return false; 0119 QDBusMessage message = QDBusMessage::createMethodCall( 0120 QLatin1String("org.a11y.Bus"), QLatin1String("/org/a11y/bus"), QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Get")); 0121 message.setArguments(QVariantList() << QLatin1String("org.a11y.Status") << QLatin1String("IsEnabled")); 0122 QDBusReply<QVariant> reply = QDBusConnection::sessionBus().call(message); 0123 if (!reply.isValid()) 0124 return false; 0125 return reply.value().toBool(); 0126 } 0127 0128 void RegistryPrivate::setEnabled(bool enable) 0129 { 0130 QDBusMessage message = QDBusMessage::createMethodCall( 0131 QLatin1String("org.a11y.Bus"), QLatin1String("/org/a11y/bus"), QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Set")); 0132 message.setArguments(QVariantList() << QLatin1String("org.a11y.Status") << QLatin1String("IsEnabled") << QVariant::fromValue(QDBusVariant(enable))); 0133 QDBusMessage reply = QDBusConnection::sessionBus().call(message); 0134 if (reply.type() == QDBusMessage::ErrorMessage) { 0135 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not set org.a11y.Status.isEnabled." << reply.errorName() << reply.errorMessage(); 0136 } 0137 } 0138 0139 bool RegistryPrivate::isScreenReaderEnabled() const 0140 { 0141 if (conn.status() != DBusConnection::Connected) 0142 return false; 0143 QDBusMessage message = QDBusMessage::createMethodCall( 0144 QLatin1String("org.a11y.Bus"), QLatin1String("/org/a11y/bus"), QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Get")); 0145 message.setArguments(QVariantList() << QLatin1String("org.a11y.Status") << QLatin1String("ScreenReaderEnabled")); 0146 QDBusReply<QVariant> reply = QDBusConnection::sessionBus().call(message); 0147 if (!reply.isValid()) 0148 return false; 0149 return reply.value().toBool(); 0150 } 0151 0152 void RegistryPrivate::setScreenReaderEnabled(bool enable) 0153 { 0154 QDBusMessage message = QDBusMessage::createMethodCall( 0155 QLatin1String("org.a11y.Bus"), QLatin1String("/org/a11y/bus"), QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Set")); 0156 message.setArguments(QVariantList() << QLatin1String("org.a11y.Status") << QLatin1String("ScreenReaderEnabled") << QVariant::fromValue(QDBusVariant(enable))); 0157 QDBusMessage reply = QDBusConnection::sessionBus().call(message); 0158 if (reply.type() == QDBusMessage::ErrorMessage) { 0159 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not set org.a11y.Status.ScreenReaderEnabled." << reply.errorName() << reply.errorMessage(); 0160 } 0161 } 0162 0163 AccessibleObject RegistryPrivate::fromUrl(const QUrl &url) const 0164 { 0165 Q_ASSERT(url.scheme() == ACCESSIBLE_OBJECT_SCHEME_STRING); 0166 if (url.scheme() != ACCESSIBLE_OBJECT_SCHEME_STRING) 0167 return AccessibleObject(); 0168 QString path = url.path(); 0169 QString service = url.fragment(); 0170 return accessibleFromPath(service, path); 0171 } 0172 0173 void RegistryPrivate::connectionFetched() 0174 { 0175 Q_ASSERT(conn.status() == DBusConnection::Connected); 0176 0177 QDBusConnection session = QDBusConnection::sessionBus(); 0178 if (session.isConnected()) { 0179 bool connected = session.connect(QLatin1String("org.a11y.Bus"), QLatin1String("/org/a11y/bus"), QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("PropertiesChanged"), this, SLOT(a11yConnectionChanged(QString,QVariantMap,QStringList))); 0180 if (!connected) 0181 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << Q_FUNC_INFO << "Failed to connect with signal org.a11y.Status.PropertiesChanged on org.a11y.Bus"; 0182 } 0183 0184 if (m_pendingSubscriptions > 0) { 0185 subscribeEventListeners(m_pendingSubscriptions); 0186 m_pendingSubscriptions = {}; 0187 } 0188 } 0189 0190 void RegistryPrivate::subscribeEventListeners(const Registry::EventListeners &listeners) 0191 { 0192 if (conn.isFetchingConnection()) { 0193 m_pendingSubscriptions = listeners; 0194 return; 0195 } 0196 0197 Registry::EventListeners addedListeners = listeners & ~m_subscriptions; 0198 Registry::EventListeners removedListeners = m_subscriptions & ~listeners; 0199 0200 QStringList newSubscriptions; 0201 QStringList removedSubscriptions; 0202 0203 if (removedListeners.testFlag(Registry::Window)) { 0204 removedSubscriptions << QLatin1String("window:"); 0205 } else if (addedListeners.testFlag(Registry::Window)) { 0206 // subscribe all window events 0207 newSubscriptions << QLatin1String("window:"); 0208 0209 bool created = conn.connection().connect( 0210 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Create"), 0211 this, SLOT(slotWindowCreate(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0212 bool destroyed = conn.connection().connect( 0213 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Destroy"), 0214 this, SLOT(slotWindowDestroy(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0215 0216 bool closed = conn.connection().connect( 0217 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Close"), 0218 this, SLOT(slotWindowClose(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0219 bool reparented = conn.connection().connect( 0220 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Reparent"), 0221 this, SLOT(slotWindowReparent(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0222 0223 bool minimized = conn.connection().connect( 0224 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Minimize"), 0225 this, SLOT(slotWindowMinimize(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0226 bool maximized = conn.connection().connect( 0227 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Maximize"), 0228 this, SLOT(slotWindowMaximize(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0229 bool restored = conn.connection().connect( 0230 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Restore"), 0231 this, SLOT(slotWindowRestore(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0232 0233 bool activated = conn.connection().connect( 0234 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Activate"), 0235 this, SLOT(slotWindowActivate(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0236 bool deactivated = conn.connection().connect( 0237 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Deactivate"), 0238 this, SLOT(slotWindowDeactivate(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0239 0240 bool desktopCreated = conn.connection().connect( 0241 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("DesktopCreate"), 0242 this, SLOT(slotWindowDesktopCreate(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0243 bool desktopDestroyed = conn.connection().connect( 0244 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("DesktopDestroy"), 0245 this, SLOT(slotWindowDesktopDestroy(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0246 bool raised = conn.connection().connect( 0247 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Raise"), 0248 this, SLOT(slotWindowRaise(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0249 bool lowered = conn.connection().connect( 0250 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Lower"), 0251 this, SLOT(slotWindowLower(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0252 bool moved = conn.connection().connect( 0253 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Move"), 0254 this, SLOT(slotWindowMove(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0255 bool resized = conn.connection().connect( 0256 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Resize"), 0257 this, SLOT(slotWindowResize(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0258 bool shaded = conn.connection().connect( 0259 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Shade"), 0260 this, SLOT(slotWindowShade(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0261 bool unshaded = conn.connection().connect( 0262 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Window"), QLatin1String("Unshade"), 0263 this, SLOT(slotWindowUnshade(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0264 0265 if (!created || !destroyed || !closed || !reparented || !minimized || !maximized || !restored || 0266 !activated || !deactivated || !desktopCreated || !desktopDestroyed || 0267 !raised || !lowered || !moved || !resized || !shaded || !unshaded 0268 ) { 0269 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to Window event(s)." 0270 << "created:" << created << "destroyed:" << destroyed 0271 << "closed:" << closed << "reparented:" << reparented 0272 << "minimized:" << minimized << "maximized:" << maximized << "restored:" << restored 0273 << "activated:" << activated << "deactivated:" << deactivated 0274 << "desktopCreated:" << desktopCreated << "desktopDestroyed:" << desktopDestroyed 0275 << "raised:" << raised << "lowered:" << lowered 0276 << "moved:" << moved << "resized:" << resized 0277 << "shaded:" << shaded << "unshaded:" << unshaded 0278 ; 0279 } 0280 } 0281 0282 if (removedListeners.testFlag(Registry::ChildrenChanged)) { 0283 removedSubscriptions << QLatin1String("object:children-changed"); 0284 } else if (addedListeners.testFlag(Registry::ChildrenChanged)) { 0285 newSubscriptions << QLatin1String("object:children-changed"); 0286 bool success = conn.connection().connect( 0287 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("ChildrenChanged"), 0288 this, SLOT(slotChildrenChanged(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0289 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility ChildrenChanged events."; 0290 } 0291 0292 if (removedListeners.testFlag(Registry::VisibleDataChanged)) { 0293 removedSubscriptions << QLatin1String("object:visibledata-changed"); 0294 } else if (addedListeners.testFlag(Registry::VisibleDataChanged)) { 0295 newSubscriptions << QLatin1String("object:visibledata-changed"); 0296 bool success = conn.connection().connect( 0297 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("VisibleDataChanged"), 0298 this, SLOT(slotVisibleDataChanged(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0299 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility VisibleDataChanged events."; 0300 } 0301 0302 if (removedListeners.testFlag(Registry::SelectionChanged)) { 0303 removedSubscriptions << QLatin1String("object:selection-changed"); 0304 } else if (addedListeners.testFlag(Registry::SelectionChanged)) { 0305 newSubscriptions << QLatin1String("object:selection-changed"); 0306 bool success = conn.connection().connect( 0307 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("SelectionChanged"), 0308 this, SLOT(slotSelectionChanged(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0309 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility SelectionChanged events."; 0310 } 0311 0312 0313 if (removedListeners.testFlag(Registry::ModelChanged)) { 0314 removedSubscriptions << QLatin1String("object:model-changed"); 0315 } else if (addedListeners.testFlag(Registry::ModelChanged)) { 0316 newSubscriptions << QLatin1String("object:model-changed"); 0317 bool success = conn.connection().connect( 0318 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("ModelChanged"), 0319 this, SLOT(slotModelChanged(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0320 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility ModelChanged events."; 0321 } 0322 0323 // we need state-changed-focus for focus events 0324 if ((removedListeners.testFlag(Registry::StateChanged) || removedListeners.testFlag(Registry::Focus)) 0325 && (!(addedListeners.testFlag(Registry::StateChanged) || addedListeners.testFlag(Registry::Focus)))) { 0326 removedSubscriptions << QLatin1String("object:state-changed"); 0327 } else if (addedListeners.testFlag(Registry::StateChanged) || addedListeners.testFlag(Registry::Focus)) { 0328 if (listeners.testFlag(Registry::Focus)) newSubscriptions << QLatin1String("focus:"); 0329 newSubscriptions << QLatin1String("object:state-changed"); 0330 bool success = conn.connection().connect( 0331 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("StateChanged"), 0332 this, SLOT(slotStateChanged(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0333 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility Focus events."; 0334 } 0335 0336 if (removedListeners.testFlag(Registry::TextChanged)) { 0337 removedSubscriptions << QLatin1String("object:text-changed"); 0338 } else if (addedListeners.testFlag(Registry::TextChanged)) { 0339 newSubscriptions << QLatin1String("object:text-changed"); 0340 bool success = conn.connection().connect( 0341 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("TextChanged"), 0342 this, SLOT(slotTextChanged(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0343 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility TextChanged events."; 0344 } 0345 0346 if (removedListeners.testFlag(Registry::TextCaretMoved)) { 0347 removedSubscriptions << QLatin1String("object:text-caret-moved"); 0348 } else if (addedListeners.testFlag(Registry::TextCaretMoved)) { 0349 newSubscriptions << QLatin1String("object:text-caret-moved"); 0350 bool success = conn.connection().connect( 0351 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("TextCaretMoved"), 0352 this, SLOT(slotTextCaretMoved(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0353 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility TextCaretMoved events."; 0354 } 0355 0356 if (removedListeners.testFlag(Registry::TextSelectionChanged)) { 0357 removedSubscriptions << QLatin1String("object:text-selection-changed"); 0358 } else if (addedListeners.testFlag(Registry::TextSelectionChanged)) { 0359 newSubscriptions << QLatin1String("object:text-selection-changed"); 0360 bool success = conn.connection().connect( 0361 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("TextSelectionChanged"), 0362 this, SLOT(slotTextSelectionChanged(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0363 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility TextSelectionChanged events."; 0364 } 0365 0366 if (removedListeners.testFlag(Registry::PropertyChanged)) { 0367 removedSubscriptions << QLatin1String("object:property-change"); 0368 } else if (addedListeners.testFlag(Registry::PropertyChanged )) { 0369 newSubscriptions << QLatin1String("object:property-change"); 0370 bool success = conn.connection().connect( 0371 QString(), QLatin1String(""), QLatin1String("org.a11y.atspi.Event.Object"), QLatin1String("PropertyChange"), 0372 this, SLOT(slotPropertyChange(QString,int,int,QDBusVariant,QAccessibleClient::QSpiObjectReference))); 0373 if (!success) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility PropertyChange events."; 0374 } 0375 0376 for (const QString &subscription : std::as_const(newSubscriptions)) { 0377 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String("org.a11y.atspi.Registry"), 0378 QLatin1String("/org/a11y/atspi/registry"), 0379 QLatin1String("org.a11y.atspi.Registry"), QLatin1String("RegisterEvent")); 0380 m.setArguments(QVariantList() << subscription); 0381 0382 QDBusPendingCall async = conn.connection().asyncCall(m); 0383 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(async, this); 0384 QObject::connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), this, SLOT(slotSubscribeEventListenerFinished(QDBusPendingCallWatcher*))); 0385 } 0386 0387 for (const QString &subscription : std::as_const(removedSubscriptions)) { 0388 QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String("org.a11y.atspi.Registry"), 0389 QLatin1String("/org/a11y/atspi/registry"), 0390 QLatin1String("org.a11y.atspi.Registry"), QLatin1String("DeregisterEvent")); 0391 m.setArguments(QVariantList() << subscription); 0392 conn.connection().asyncCall(m); 0393 } 0394 0395 m_subscriptions = listeners; 0396 0397 // accerciser 0398 // (u':1.7', u'Object:StateChanged:'), 0399 // (u':1.7', u'Object:BoundsChanged:'), 0400 // (u':1.7', u'Object:VisibleDataChanged:'), 0401 // (u':1.7', u'Object:StateChanged:'), 0402 // orca 0403 // [(u':1.8', u'Object:ChildrenChanged:'), 0404 // (u':1.8', u'Mouse:Button:'), 0405 // (u':1.8', u'Mouse:Abs:'), 0406 // (u':1.8', u'Object:StateChanged:Selected'), 0407 // (u':1.8', u'Object:StateChanged:Expanded'), 0408 // (u':1.8', u'Object:ValueChanged:'), 0409 // (u':1.8', u'Object:StateChanged:Focused'), 0410 // (u':1.8', u'Object:StateChanged:Active'), 0411 // (u':1.8', u'Window:Create:'), 0412 // (u':1.8', u'Object:TextAttributesChanged:'), 0413 // (u':1.8', u'Object:TextCaretMoved:'), 0414 // (u':1.8', u'Object:SelectionChanged:'), 0415 // (u':1.8', u'Focus::'), 0416 // (u':1.8', u'Object:ActiveDescendantChanged:'), 0417 // (u':1.8', u'Object:PropertyChange:AccessibleName'), 0418 // (u':1.8', u'Window:Activate:'), 0419 // (u':1.8', u'Window:Deactivate:'), 0420 // (u':1.8', u'Mouse:Button:'), 0421 // (u':1.8', u'Object:StateChanged:Indeterminate'), 0422 // (u':1.8', u'Object:LinkSelected:'), 0423 // (u':1.8', u'Object:TextChanged:Insert'), 0424 // (u':1.8', u'Object:PropertyChange:AccessibleValue'), 0425 // (u':1.8', u'Object:TextSelectionChanged:'), 0426 // // (u':1.8', u'Object:StateChanged:Showing'), 0427 // (u':1.8', u'Object:TextChanged:Delete'), 0428 // (u':1.8', u'Object:StateChanged:Pressed'), 0429 // (u':1.8', u'Object:StateChanged:Checked'), 0430 // (u':1.8', u'Object:ChildrenChanged:Remove')] 0431 0432 } 0433 0434 Registry::EventListeners RegistryPrivate::eventListeners() const 0435 { 0436 return m_subscriptions | m_pendingSubscriptions; 0437 } 0438 0439 void RegistryPrivate::slotSubscribeEventListenerFinished(QDBusPendingCallWatcher *call) 0440 { 0441 if (call->isError()) { 0442 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not subscribe to accessibility event: " << call->error().type() << call->error().message(); 0443 } 0444 call->deleteLater(); 0445 } 0446 0447 void RegistryPrivate::a11yConnectionChanged(const QString &interface,const QVariantMap &changedProperties, const QStringList &invalidatedProperties) 0448 { 0449 //qDebug() << Q_FUNC_INFO << "interface=" << interface << "changedProperties=" << changedProperties << "invalidatedProperties=" << invalidatedProperties; 0450 if (conn.status() != DBusConnection::Connected) 0451 return; 0452 if (interface == QLatin1String("org.a11y.Status")) { 0453 QVariantMap::ConstIterator IsEnabledIt = changedProperties.constFind(QLatin1String("IsEnabled")); 0454 if (IsEnabledIt != changedProperties.constEnd()) 0455 Q_EMIT q->enabledChanged(IsEnabledIt.value().toBool()); 0456 else if (invalidatedProperties.contains(QLatin1String("IsEnabled"))) 0457 Q_EMIT q->enabledChanged(isEnabled()); 0458 0459 QVariantMap::ConstIterator ScreenReaderEnabledIt = changedProperties.constFind(QLatin1String("ScreenReaderEnabled")); 0460 if (ScreenReaderEnabledIt != changedProperties.constEnd()) 0461 Q_EMIT q->screenReaderEnabledChanged(ScreenReaderEnabledIt.value().toBool()); 0462 else if (invalidatedProperties.contains(QLatin1String("ScreenReaderEnabled"))) 0463 Q_EMIT q->screenReaderEnabledChanged(isScreenReaderEnabled()); 0464 } 0465 } 0466 0467 AccessibleObject RegistryPrivate::parentAccessible(const AccessibleObject &object) const 0468 { 0469 QVariant parent = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("Parent")); 0470 if (!parent.isValid()) 0471 return AccessibleObject(); 0472 const QDBusArgument arg = parent.value<QDBusArgument>(); 0473 QSpiObjectReference ref; 0474 arg >> ref; 0475 0476 if (ref.path.path() == object.d->path) { 0477 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "WARNING: Accessible claims to be its own parent: " << object; 0478 return AccessibleObject(); 0479 } 0480 0481 if (ref.service.isEmpty() || ref.path.path().isEmpty()) 0482 return AccessibleObject(); 0483 0484 return AccessibleObject(const_cast<RegistryPrivate*>(this), ref.service, ref.path.path()); 0485 } 0486 0487 int RegistryPrivate::childCount(const AccessibleObject &object) const 0488 { 0489 QVariant childCount = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("ChildCount")); 0490 return childCount.toInt(); 0491 } 0492 0493 int RegistryPrivate::indexInParent(const AccessibleObject &object) const 0494 { 0495 QDBusMessage message = QDBusMessage::createMethodCall ( 0496 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("GetIndexInParent")); 0497 0498 QDBusReply<int> reply = conn.connection().call(message); 0499 if (!reply.isValid()) { 0500 QDBusReply<uint> reply2 = conn.connection().call(message); 0501 if (reply2.isValid()) { 0502 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Found old api returning uint in GetIndexInParent." << reply.error().message(); 0503 return static_cast<int>(reply.value()); 0504 } 0505 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access index in parent." << reply.error().message(); 0506 return -1; 0507 } 0508 return reply.value(); 0509 } 0510 0511 AccessibleObject RegistryPrivate::child(const AccessibleObject &object, int index) const 0512 { 0513 QDBusMessage message = QDBusMessage::createMethodCall ( 0514 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("GetChildAtIndex")); 0515 QVariantList args; 0516 args << index; 0517 message.setArguments(args); 0518 0519 QDBusReply<QSpiObjectReference> reply = conn.connection().call(message); 0520 if (!reply.isValid()) { 0521 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access child." << reply.error().message(); 0522 return AccessibleObject(); 0523 } 0524 const QSpiObjectReference child = reply.value(); 0525 return AccessibleObject(const_cast<RegistryPrivate*>(this), child.service, child.path.path()); 0526 } 0527 0528 QList<AccessibleObject> RegistryPrivate::children(const AccessibleObject &object) const 0529 { 0530 QList<AccessibleObject> accs; 0531 0532 QDBusMessage message = QDBusMessage::createMethodCall ( 0533 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("GetChildren")); 0534 0535 QDBusReply<QSpiObjectReferenceList> reply = conn.connection().call(message, QDBus::Block, 500); 0536 if (!reply.isValid()) { 0537 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access children." << reply.error().message(); 0538 return accs; 0539 } 0540 0541 const QSpiObjectReferenceList children = reply.value(); 0542 for (const QSpiObjectReference &child : children) { 0543 accs.append(AccessibleObject(const_cast<RegistryPrivate*>(this), child.service, child.path.path())); 0544 } 0545 0546 return accs; 0547 } 0548 0549 QList<AccessibleObject> RegistryPrivate::topLevelAccessibles() const 0550 { 0551 QString service = QLatin1String("org.a11y.atspi.Registry"); 0552 QString path = QLatin1String("/org/a11y/atspi/accessible/root"); 0553 return children(AccessibleObject(const_cast<RegistryPrivate*>(this), service, path)); 0554 } 0555 0556 QString RegistryPrivate::accessibleId(const AccessibleObject &object) const 0557 { 0558 if (!object.isValid()) 0559 return QString(); 0560 return getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("AccessibleId")).toString(); 0561 } 0562 0563 QString RegistryPrivate::name(const AccessibleObject &object) const 0564 { 0565 if (!object.isValid()) 0566 return QString(); 0567 return getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("Name")).toString(); 0568 } 0569 0570 QString RegistryPrivate::description(const AccessibleObject &object) const 0571 { 0572 if (!object.isValid()) 0573 return QString(); 0574 return getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("Description")).toString(); 0575 } 0576 0577 AccessibleObject::Role RegistryPrivate::role(const AccessibleObject &object) const 0578 { 0579 if (!object.isValid()) 0580 return AccessibleObject::NoRole; 0581 0582 QDBusMessage message = QDBusMessage::createMethodCall ( 0583 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("GetRole")); 0584 0585 QDBusReply<uint> reply = conn.connection().call(message); 0586 if (!reply.isValid()) { 0587 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access role." << reply.error().message(); 0588 return AccessibleObject::NoRole; 0589 } 0590 return atspiRoleToRole(static_cast<AtspiRole>(reply.value())); 0591 } 0592 0593 AccessibleObject::Role RegistryPrivate::atspiRoleToRole(AtspiRole role) 0594 { 0595 switch (role) { 0596 case ATSPI_ROLE_INVALID: return AccessibleObject::NoRole; 0597 // case ATSPI_ROLE_ACCELERATOR_LABEL: return AccessibleObject::; 0598 // case ATSPI_ROLE_ALERT: return AccessibleObject::; 0599 // case ATSPI_ROLE_ANIMATION: return AccessibleObject::; 0600 // case ATSPI_ROLE_ARROW: return AccessibleObject::; 0601 // case ATSPI_ROLE_CALENDAR: return AccessibleObject::; 0602 // case ATSPI_ROLE_CANVAS: return AccessibleObject::; 0603 case ATSPI_ROLE_CHECK_BOX: return AccessibleObject::CheckBox; 0604 case ATSPI_ROLE_CHECK_MENU_ITEM: return AccessibleObject::CheckableMenuItem; 0605 // case ATSPI_ROLE_COLOR_CHOOSER: return AccessibleObject::; 0606 case ATSPI_ROLE_COLUMN_HEADER: return AccessibleObject::ColumnHeader; 0607 case ATSPI_ROLE_COMBO_BOX: return AccessibleObject::ComboBox; 0608 // case ATSPI_ROLE_DATE_EDITOR: return AccessibleObject::; 0609 // case ATSPI_ROLE_DESKTOP_ICON: return AccessibleObject::; 0610 case ATSPI_ROLE_DESKTOP_FRAME: return AccessibleObject::DesktopFrame; 0611 // case ATSPI_ROLE_DIAL: return AccessibleObject::; 0612 case ATSPI_ROLE_DIALOG: return AccessibleObject::Dialog; 0613 // case ATSPI_ROLE_DIRECTORY_PANE: return AccessibleObject::; 0614 // case ATSPI_ROLE_DRAWING_AREA: return AccessibleObject::; 0615 // case ATSPI_ROLE_FILE_CHOOSER: return AccessibleObject::; 0616 case ATSPI_ROLE_FILLER: return AccessibleObject::Filler; 0617 // case ATSPI_ROLE_FOCUS_TRAVERSABLE: return AccessibleObject::; 0618 // case ATSPI_ROLE_FONT_CHOOSER: return AccessibleObject::; 0619 case ATSPI_ROLE_FRAME: return AccessibleObject::Frame; 0620 // case ATSPI_ROLE_GLASS_PANE: return AccessibleObject::; 0621 // case ATSPI_ROLE_HTML_CONTAINER: return AccessibleObject::; 0622 case ATSPI_ROLE_ICON: return AccessibleObject::Icon; 0623 // case ATSPI_ROLE_IMAGE: return AccessibleObject::; 0624 // case ATSPI_ROLE_INTERNAL_FRAME: return AccessibleObject::; 0625 case ATSPI_ROLE_LABEL: return AccessibleObject::Label; 0626 // case ATSPI_ROLE_LAYERED_PANE: return AccessibleObject::; 0627 case ATSPI_ROLE_LIST: return AccessibleObject::ListView; 0628 case ATSPI_ROLE_LIST_ITEM: return AccessibleObject::ListItem; 0629 case ATSPI_ROLE_MENU: return AccessibleObject::Menu; 0630 case ATSPI_ROLE_MENU_BAR: return AccessibleObject::MenuBar; 0631 case ATSPI_ROLE_MENU_ITEM: return AccessibleObject::MenuItem; 0632 // case ATSPI_ROLE_OPTION_PANE: return AccessibleObject::; 0633 case ATSPI_ROLE_PAGE_TAB: return AccessibleObject::Tab; 0634 case ATSPI_ROLE_PAGE_TAB_LIST: return AccessibleObject::TabContainer; 0635 // case ATSPI_ROLE_PANEL: return AccessibleObject::; 0636 case ATSPI_ROLE_PASSWORD_TEXT: return AccessibleObject::PasswordText; 0637 case ATSPI_ROLE_POPUP_MENU: return AccessibleObject::PopupMenu; 0638 case ATSPI_ROLE_PROGRESS_BAR: return AccessibleObject::ProgressBar; 0639 case ATSPI_ROLE_PUSH_BUTTON: return AccessibleObject::Button; 0640 case ATSPI_ROLE_RADIO_BUTTON: return AccessibleObject::RadioButton; 0641 case ATSPI_ROLE_RADIO_MENU_ITEM: return AccessibleObject::RadioMenuItem; 0642 // case ATSPI_ROLE_ROOT_PANE: return AccessibleObject::; 0643 case ATSPI_ROLE_ROW_HEADER: return AccessibleObject::RowHeader; 0644 case ATSPI_ROLE_SCROLL_BAR: return AccessibleObject::ScrollBar; 0645 case ATSPI_ROLE_SCROLL_PANE: return AccessibleObject::ScrollArea; 0646 case ATSPI_ROLE_SEPARATOR: return AccessibleObject::Separator; 0647 case ATSPI_ROLE_SLIDER: return AccessibleObject::Slider; 0648 case ATSPI_ROLE_SPIN_BUTTON: return AccessibleObject::SpinButton; 0649 // case ATSPI_ROLE_SPLIT_PANE: return AccessibleObject::; 0650 case ATSPI_ROLE_STATUS_BAR: return AccessibleObject::StatusBar; 0651 case ATSPI_ROLE_TABLE: return AccessibleObject::TableView; 0652 case ATSPI_ROLE_TABLE_CELL: return AccessibleObject::TableCell; 0653 case ATSPI_ROLE_TABLE_COLUMN_HEADER: return AccessibleObject::TableColumnHeader; 0654 case ATSPI_ROLE_TABLE_ROW_HEADER: return AccessibleObject::TableRowHeader; 0655 // case ATSPI_ROLE_TEAROFF_MENU_ITEM: return AccessibleObject::; 0656 case ATSPI_ROLE_TERMINAL: return AccessibleObject::Terminal; 0657 case ATSPI_ROLE_TEXT: return AccessibleObject::Text; 0658 case ATSPI_ROLE_TOGGLE_BUTTON: return AccessibleObject::ToggleButton; 0659 case ATSPI_ROLE_TOOL_BAR: return AccessibleObject::ToolBar; 0660 case ATSPI_ROLE_TOOL_TIP: return AccessibleObject::ToolTip; 0661 case ATSPI_ROLE_TREE: return AccessibleObject::TreeView; 0662 case ATSPI_ROLE_TREE_TABLE: return AccessibleObject::TreeView; 0663 case ATSPI_ROLE_UNKNOWN: return AccessibleObject::NoRole; 0664 // case ATSPI_ROLE_VIEWPORT: return AccessibleObject::; 0665 case ATSPI_ROLE_WINDOW: return AccessibleObject::Window; 0666 // case ATSPI_ROLE_EXTENDED: return AccessibleObject::; 0667 // case ATSPI_ROLE_HEADER: return AccessibleObject::; 0668 // case ATSPI_ROLE_FOOTER: return AccessibleObject::; 0669 // case ATSPI_ROLE_PARAGRAPH: return AccessibleObject::; 0670 // case ATSPI_ROLE_RULER: return AccessibleObject::; 0671 // case ATSPI_ROLE_APPLICATION: return AccessibleObject::; 0672 // case ATSPI_ROLE_AUTOCOMPLETE: return AccessibleObject::; 0673 // case ATSPI_ROLE_EDITBAR: return AccessibleObject::; 0674 // case ATSPI_ROLE_EMBEDDED: return AccessibleObject::; 0675 // case ATSPI_ROLE_ENTRY: return AccessibleObject::; 0676 // case ATSPI_ROLE_CHART: return AccessibleObject::; 0677 // case ATSPI_ROLE_CAPTION: return AccessibleObject::; 0678 // case ATSPI_ROLE_DOCUMENT_FRAME: return AccessibleObject::; 0679 // case ATSPI_ROLE_HEADING: return AccessibleObject::; 0680 // case ATSPI_ROLE_PAGE: return AccessibleObject::; 0681 // case ATSPI_ROLE_SECTION: return AccessibleObject::; 0682 // case ATSPI_ROLE_REDUNDANT_OBJECT: return AccessibleObject::; 0683 // case ATSPI_ROLE_FORM: return AccessibleObject::; 0684 // case ATSPI_ROLE_LINK: return AccessibleObject::; 0685 // case ATSPI_ROLE_INPUT_METHOD_WINDOW: return AccessibleObject::; 0686 case ATSPI_ROLE_TABLE_ROW: return AccessibleObject::TableRow; 0687 case ATSPI_ROLE_TREE_ITEM: return AccessibleObject::TreeItem; 0688 // case ATSPI_ROLE_DOCUMENT_SPREADSHEET: return AccessibleObject::; 0689 // case ATSPI_ROLE_DOCUMENT_PRESENTATION: return AccessibleObject::; 0690 // case ATSPI_ROLE_DOCUMENT_TEXT: return AccessibleObject::; 0691 // case ATSPI_ROLE_DOCUMENT_WEB: return AccessibleObject::; 0692 // case ATSPI_ROLE_DOCUMENT_EMAIL: return AccessibleObject::; 0693 // case ATSPI_ROLE_COMMENT: return AccessibleObject::; 0694 // case ATSPI_ROLE_LIST_BOX: return AccessibleObject::; 0695 // case ATSPI_ROLE_GROUPING: return AccessibleObject::; 0696 // case ATSPI_ROLE_IMAGE_MAP: return AccessibleObject::; 0697 // case ATSPI_ROLE_NOTIFICATION: return AccessibleObject::; 0698 // case ATSPI_ROLE_INFO_BAR: return AccessibleObject::; 0699 // case ATSPI_ROLE_LAST_DEFINED: return AccessibleObject::; 0700 } 0701 return AccessibleObject::NoRole; 0702 } 0703 0704 QString RegistryPrivate::roleName(const AccessibleObject &object) const 0705 { 0706 QDBusMessage message = QDBusMessage::createMethodCall ( 0707 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("GetRoleName")); 0708 0709 QDBusReply<QString> reply = conn.connection().call(message); 0710 if (!reply.isValid()) { 0711 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access roleName." << reply.error().message(); 0712 return QString(); 0713 } 0714 return reply.value(); 0715 } 0716 0717 QString RegistryPrivate::localizedRoleName(const AccessibleObject &object) const 0718 { 0719 QDBusMessage message = QDBusMessage::createMethodCall ( 0720 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("GetLocalizedRoleName")); 0721 0722 QDBusReply<QString> reply = conn.connection().call(message); 0723 if (!reply.isValid()) { 0724 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access localizedRoleName." << reply.error().message();\ 0725 return QString(); 0726 } 0727 return reply.value(); 0728 } 0729 0730 quint64 RegistryPrivate::state(const AccessibleObject &object) const 0731 { 0732 if (m_cache) { 0733 quint64 cachedValue = m_cache->state(object); 0734 if (cachedValue != QAccessibleClient::ObjectCache::StateNotFound) 0735 return cachedValue; 0736 } 0737 0738 QDBusMessage message = QDBusMessage::createMethodCall ( 0739 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("GetState")); 0740 0741 QDBusReply<QVector<quint32> > reply = conn.connection().call(message); 0742 if (!reply.isValid()) { 0743 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access state." << reply.error().message(); 0744 return 0; 0745 } 0746 if (reply.value().size() < 2) { 0747 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Did not receive expected reply."; 0748 return 0; 0749 } 0750 const quint32 low = reply.value().at(0); 0751 const quint32 high = reply.value().at(1); 0752 const quint64 state = low + (static_cast<quint64>(high) << 32); 0753 0754 if (m_cache) { 0755 m_cache->setState(object, state); 0756 } 0757 0758 return state; 0759 } 0760 0761 int RegistryPrivate::layer(const AccessibleObject &object) const 0762 { 0763 QDBusMessage message = QDBusMessage::createMethodCall ( 0764 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Component"), QLatin1String("GetLayer")); 0765 QDBusReply<uint> reply = conn.connection().call(message); 0766 if (!reply.isValid()) { 0767 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access layer." << reply.error().message(); 0768 return 1; 0769 } 0770 return reply.value(); 0771 } 0772 0773 int RegistryPrivate::mdiZOrder(const AccessibleObject &object) const 0774 { 0775 QDBusMessage message = QDBusMessage::createMethodCall ( 0776 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Component"), QLatin1String("GetMDIZOrder")); 0777 QDBusReply<short> reply = conn.connection().call(message); 0778 if (!reply.isValid()) { 0779 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access mdiZOrder." << reply.error().message(); 0780 return 0; 0781 } 0782 return reply.value(); 0783 } 0784 0785 double RegistryPrivate::alpha(const AccessibleObject &object) const 0786 { 0787 QDBusMessage message = QDBusMessage::createMethodCall ( 0788 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Component"), QLatin1String("GetAlpha")); 0789 QDBusReply<double> reply = conn.connection().call(message); 0790 if (!reply.isValid()) { 0791 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access alpha." << reply.error().message(); 0792 return 1.0; 0793 } 0794 return reply.value(); 0795 } 0796 0797 QRect RegistryPrivate::boundingRect(const AccessibleObject &object) const 0798 { 0799 QDBusMessage message = QDBusMessage::createMethodCall( 0800 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Component"), QLatin1String("GetExtents") ); 0801 QVariantList args; 0802 quint32 coords = ATSPI_COORD_TYPE_SCREEN; 0803 args << coords; 0804 message.setArguments(args); 0805 0806 QDBusReply< QRect > reply = conn.connection().call(message); 0807 if(!reply.isValid()){ 0808 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not get extents." << reply.error().message(); 0809 return QRect(); 0810 } 0811 0812 return QRect( reply.value() ); 0813 } 0814 0815 QRect RegistryPrivate::characterRect(const AccessibleObject &object, int offset) const 0816 { 0817 QDBusMessage message = QDBusMessage::createMethodCall( 0818 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), 0819 QLatin1String("GetCharacterExtents")); 0820 0821 QVariantList args; 0822 quint32 coords = ATSPI_COORD_TYPE_SCREEN; 0823 args << offset; 0824 args << coords; 0825 message.setArguments(args); 0826 0827 0828 QDBusReply< QRect > reply = conn.connection().call(message); 0829 if(!reply.isValid()){ 0830 if (reply.error().type() == QDBusError::InvalidSignature) { 0831 QDBusMessage reply2 = conn.connection().call(message); 0832 if (reply2.signature() != QLatin1String("iiii")) { 0833 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not get Character Extents. " << reply.error().message(); 0834 return QRect(); 0835 } 0836 QList<QVariant> args = reply2.arguments(); 0837 QRect rect(args.at(0).toInt(), args.at(1).toInt(), args.at(2).toInt(), args.at(3).toInt()); 0838 return rect; 0839 } 0840 } 0841 0842 return reply.value(); 0843 } 0844 0845 AccessibleObject::Interfaces RegistryPrivate::supportedInterfaces(const AccessibleObject &object) const 0846 { 0847 if (m_cache) { 0848 AccessibleObject::Interfaces interfaces = m_cache->interfaces(object); 0849 if (!(interfaces & AccessibleObject::InvalidInterface)) 0850 return interfaces; 0851 } 0852 0853 QDBusMessage message = QDBusMessage::createMethodCall( 0854 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), 0855 QLatin1String("GetInterfaces")); 0856 0857 QDBusReply<QStringList > reply = conn.connection().call(message); 0858 if(!reply.isValid()){ 0859 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not get Interfaces. " << reply.error().message(); 0860 return AccessibleObject::NoInterface; 0861 } 0862 0863 AccessibleObject::Interfaces interfaces = AccessibleObject::NoInterface; 0864 const auto values{reply.value()}; 0865 for (const QString &interface : values){ 0866 interfaces |= interfaceHash[interface]; 0867 } 0868 0869 if (m_cache) { 0870 m_cache->setInterfaces(object, interfaces); 0871 } 0872 0873 return interfaces; 0874 } 0875 0876 int RegistryPrivate::caretOffset(const AccessibleObject &object) const 0877 { 0878 QVariant offset= getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("CaretOffset")); 0879 if (offset.isNull()) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not get caret offset"; 0880 return offset.toInt(); 0881 } 0882 0883 int RegistryPrivate::characterCount(const AccessibleObject &object) const 0884 { 0885 QVariant count = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("CharacterCount")); 0886 if (count.isNull()) qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not get character count"; 0887 return count.toInt(); 0888 } 0889 0890 QList< QPair<int,int> > RegistryPrivate::textSelections(const AccessibleObject &object) const 0891 { 0892 QList< QPair<int,int> > result; 0893 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("GetNSelections")); 0894 QDBusReply<int> reply = conn.connection().call(message); 0895 if (!reply.isValid()) { 0896 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access GetNSelections." << reply.error().message(); 0897 return result; 0898 } 0899 int count = reply.value(); 0900 for(int i = 0; i < count; ++i) { 0901 QDBusMessage m = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("GetSelection")); 0902 m.setArguments(QVariantList() << i); 0903 m = conn.connection().call(m); 0904 QList<QVariant> args = m.arguments(); 0905 if (args.count() < 2) { 0906 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Invalid number of arguments. Expected=2 Actual=" << args.count(); 0907 continue; 0908 } 0909 int startOffset = args[0].toInt(); 0910 int endOffset = args[1].toInt(); 0911 if (startOffset > endOffset) 0912 qSwap(startOffset, endOffset); 0913 result.append(qMakePair(startOffset, endOffset)); 0914 } 0915 return result; 0916 } 0917 0918 void RegistryPrivate::setTextSelections(const AccessibleObject &object, const QList< QPair<int,int> > &selections) 0919 { 0920 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("GetNSelections")); 0921 QDBusReply<int> reply = conn.connection().call(message); 0922 if (!reply.isValid()) { 0923 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access GetNSelections." << reply.error().message(); 0924 return; 0925 } 0926 int count = reply.value(); 0927 int setSel = qMin(selections.count(), count); 0928 for(int i = 0; i < setSel; ++i) { 0929 Q_ASSERT(i < selections.count()); 0930 QPair<int,int> p = selections[i]; 0931 QDBusMessage m = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("SetSelection")); 0932 m.setArguments(QVariantList() << i << p.first << p.second); 0933 QDBusReply<bool> r = conn.connection().call(m); 0934 if (!r.isValid()) { 0935 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Failed call text.SetSelection." << r.error().message(); 0936 continue; 0937 } 0938 } 0939 int removeSel = qMax(0, count - selections.count()); 0940 for(int i = 0, k = selections.count(); i < removeSel; ++i, ++k) { 0941 QDBusMessage m = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("RemoveSelection")); 0942 m.setArguments(QVariantList() << k); 0943 QDBusReply<bool> r = conn.connection().call(m); 0944 if (!r.isValid()) { 0945 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Failed call text.RemoveSelection." << r.error().message(); 0946 continue; 0947 } 0948 } 0949 int addSel = qMax(0, selections.count() - count); 0950 for(int i = 0, k = count; i < addSel; ++i, ++k) { 0951 Q_ASSERT(k < selections.count()); 0952 QPair<int,int> p = selections[k]; 0953 QDBusMessage m = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("AddSelection")); 0954 m.setArguments(QVariantList() << p.first << p.second); 0955 QDBusReply<bool> r = conn.connection().call(m); 0956 if (!r.isValid()) { 0957 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Failed call text.AddSelection." << r.error().message(); 0958 continue; 0959 } 0960 } 0961 } 0962 0963 QString RegistryPrivate::text(const AccessibleObject &object, int startOffset, int endOffset) const 0964 { 0965 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("GetText")); 0966 message.setArguments(QVariantList() << startOffset << endOffset); 0967 QDBusReply<QString> reply = conn.connection().call(message); 0968 if (!reply.isValid()) { 0969 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access text." << reply.error().message(); 0970 return QString(); 0971 } 0972 return reply.value(); 0973 } 0974 0975 QString RegistryPrivate::textWithBoundary(const AccessibleObject &object, int offset, AccessibleObject::TextBoundary boundary, int *startOffset, int *endOffset) const 0976 { 0977 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Text"), QLatin1String("GetTextAtOffset")); 0978 message.setArguments(QVariantList() << offset << static_cast<AtspiTextBoundaryType>(boundary)); 0979 QDBusMessage reply = conn.connection().call(message); 0980 if (reply.type() != QDBusMessage::ReplyMessage || reply.signature() != QLatin1String("sii")) { 0981 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access text." << reply.errorMessage(); 0982 if (startOffset) 0983 *startOffset = 0; 0984 if (endOffset) 0985 *endOffset = 0; 0986 return QString(); 0987 } 0988 if (startOffset) 0989 *startOffset = reply.arguments().at(1).toInt(); 0990 if (endOffset) 0991 *endOffset = reply.arguments().at(2).toInt(); 0992 return reply.arguments().first().toString();; 0993 } 0994 0995 bool RegistryPrivate::setText(const AccessibleObject &object, const QString &text) 0996 { 0997 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.EditableText"), QLatin1String("SetTextContents")); 0998 message.setArguments(QVariantList() << text); 0999 QDBusReply<bool> reply = conn.connection().call(message); 1000 if (!reply.isValid()) { 1001 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not set text." << reply.error().message(); 1002 return false; 1003 } 1004 return reply.value(); 1005 } 1006 1007 bool RegistryPrivate::insertText(const AccessibleObject &object, const QString &text, int position, int length) 1008 { 1009 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.EditableText"), QLatin1String("InsertText")); 1010 message.setArguments(QVariantList() << position << text << length); 1011 QDBusReply<bool> reply = conn.connection().call(message); 1012 if (!reply.isValid()) { 1013 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not insert text." << reply.error().message(); 1014 return false; 1015 } 1016 return reply.value(); 1017 } 1018 1019 bool RegistryPrivate::copyText(const AccessibleObject &object, int startPos, int endPos) 1020 { 1021 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.EditableText"), QLatin1String("CopyText")); 1022 message.setArguments(QVariantList() << startPos << endPos); 1023 conn.connection().call(message); 1024 return true; 1025 } 1026 1027 bool RegistryPrivate::cutText(const AccessibleObject &object, int startPos, int endPos) 1028 { 1029 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.EditableText"), QLatin1String("CutText")); 1030 message.setArguments(QVariantList() << startPos << endPos); 1031 QDBusReply<bool> reply = conn.connection().call(message); 1032 if (!reply.isValid()) { 1033 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not cut text." << reply.error().message(); 1034 return false; 1035 } 1036 return reply.value(); 1037 } 1038 1039 bool RegistryPrivate::deleteText(const AccessibleObject &object, int startPos, int endPos) 1040 { 1041 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.EditableText"), QLatin1String("DeleteText")); 1042 message.setArguments(QVariantList() << startPos << endPos); 1043 QDBusReply<bool> reply = conn.connection().call(message); 1044 if (!reply.isValid()) { 1045 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not delete text." << reply.error().message(); 1046 return false; 1047 } 1048 return reply.value(); 1049 } 1050 1051 bool RegistryPrivate::pasteText(const AccessibleObject &object, int position) 1052 { 1053 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.EditableText"), QLatin1String("PasteText")); 1054 message.setArguments(QVariantList() << position); 1055 QDBusReply<bool> reply = conn.connection().call(message); 1056 if (!reply.isValid()) { 1057 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not paste text." << reply.error().message(); 1058 return false; 1059 } 1060 return reply.value(); 1061 } 1062 1063 AccessibleObject RegistryPrivate::application(const AccessibleObject &object) const 1064 { 1065 QDBusMessage message = QDBusMessage::createMethodCall( 1066 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Accessible"), QLatin1String("GetApplication")); 1067 QDBusReply<QSpiObjectReference> reply = conn.connection().call(message); 1068 if (!reply.isValid()) { 1069 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access application." << reply.error().message(); 1070 return AccessibleObject(); 1071 } 1072 const QSpiObjectReference child = reply.value(); 1073 return AccessibleObject(const_cast<RegistryPrivate*>(this), child.service, child.path.path()); 1074 } 1075 1076 QString RegistryPrivate::appToolkitName(const AccessibleObject &object) const 1077 { 1078 const QVariant v = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Application"), QLatin1String("ToolkitName")); 1079 return v.toString(); 1080 } 1081 1082 QString RegistryPrivate::appVersion(const AccessibleObject &object) const 1083 { 1084 const QVariant v = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Application"), QLatin1String("Version")); 1085 return v.toString(); 1086 } 1087 1088 int RegistryPrivate::appId(const AccessibleObject &object) const 1089 { 1090 const QVariant v = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Application"), QLatin1String("Id")); 1091 return v.toInt(); 1092 } 1093 1094 QString RegistryPrivate::appLocale(const AccessibleObject &object, uint lctype) const 1095 { 1096 // some apps misbehave and claim to be the service, but on :1.0 we have the atspi service which doesn't reply anything sensible here 1097 if (object.d->service == QLatin1String(":1.0")) 1098 return QString(); 1099 1100 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Application"), QLatin1String("GetLocale")); 1101 1102 QVariantList args; 1103 args.append(lctype); 1104 message.setArguments(args); 1105 1106 QDBusReply<QString> reply = conn.connection().call(message, QDBus::Block, 500); 1107 if (!reply.isValid()) { 1108 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access appLocale." << reply.error().message(); 1109 return QString(); 1110 } 1111 return reply.value(); 1112 } 1113 1114 QString RegistryPrivate::appBusAddress(const AccessibleObject &object) const 1115 { 1116 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Application"), QLatin1String("GetApplicationBusAddress")); 1117 QDBusReply<QString> reply = conn.connection().call(message); 1118 if (!reply.isValid()) { 1119 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << Q_FUNC_INFO << "Could not access application bus address. Error: " << reply.error().message() << " in response to: " << message; 1120 return QString(); 1121 } 1122 return reply.value(); 1123 } 1124 1125 double RegistryPrivate::minimumValue(const AccessibleObject &object) const 1126 { 1127 const QVariant v = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Value"), QLatin1String("MinimumValue")); 1128 return v.toDouble(); 1129 } 1130 1131 double RegistryPrivate::maximumValue(const AccessibleObject &object) const 1132 { 1133 const QVariant v = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Value"), QLatin1String("MaximumValue")); 1134 return v.toDouble(); 1135 } 1136 1137 double RegistryPrivate::minimumValueIncrement(const AccessibleObject &object) const 1138 { 1139 const QVariant v = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Value"), QLatin1String("MinimumIncrement")); 1140 return v.toDouble(); 1141 } 1142 1143 double RegistryPrivate::currentValue(const AccessibleObject &object) const 1144 { 1145 const QVariant v = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Value"), QLatin1String("CurrentValue")); 1146 return v.toDouble(); 1147 } 1148 1149 bool RegistryPrivate::setCurrentValue(const AccessibleObject &object, double value) 1150 { 1151 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Value"), QLatin1String("SetCurrentValue")); 1152 1153 QVariantList arguments; 1154 arguments << QLatin1String("org.a11y.atspi.Value") << QLatin1String("CurrentValue"); 1155 arguments << QVariant::fromValue(QDBusVariant(value)); 1156 message.setArguments(arguments); 1157 1158 QDBusReply<bool> reply = conn.connection().call(message); 1159 if (!reply.isValid()) { 1160 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not set text." << reply.error().message(); 1161 return false; 1162 } 1163 return reply.value(); 1164 } 1165 1166 QList<AccessibleObject> RegistryPrivate::selection(const AccessibleObject &object) const 1167 { 1168 QList<AccessibleObject> result; 1169 int count = getProperty(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Selection"), QLatin1String("CurrentValue")).toInt(); 1170 for(int i = 0; i < count; ++i) { 1171 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Selection"), QLatin1String("GetSelectedChild")); 1172 QDBusReply<QSpiObjectReference> reply = conn.connection().call(message); 1173 if (!reply.isValid()) { 1174 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access selection." << reply.error().message(); 1175 return QList<AccessibleObject>(); 1176 } 1177 const QSpiObjectReference ref = reply.value(); 1178 result.append(AccessibleObject(const_cast<RegistryPrivate*>(this), ref.service, ref.path.path())); 1179 } 1180 return result; 1181 } 1182 1183 QString RegistryPrivate::imageDescription(const AccessibleObject &object) const 1184 { 1185 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Image"), QLatin1String("ImageDescription")); 1186 QDBusReply<QString> reply = conn.connection().call(message); 1187 if (!reply.isValid()) { 1188 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access imageDescription." << reply.error().message(); 1189 return QString(); 1190 } 1191 return reply.value(); 1192 } 1193 1194 QString RegistryPrivate::imageLocale(const AccessibleObject &object) const 1195 { 1196 const QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Image"), QLatin1String("ImageLocale")); 1197 const QDBusReply<QString> reply = conn.connection().call(message, QDBus::Block, 500); 1198 if (!reply.isValid()) { 1199 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access imageLocale." << reply.error().message(); 1200 return QString(); 1201 } 1202 return reply.value(); 1203 } 1204 1205 QRect RegistryPrivate::imageRect(const AccessibleObject &object) const 1206 { 1207 QDBusMessage message = QDBusMessage::createMethodCall(object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Image"), QLatin1String("GetImageExtents")); 1208 QVariantList args; 1209 quint32 coords = ATSPI_COORD_TYPE_SCREEN; 1210 args << coords; 1211 message.setArguments(args); 1212 QDBusReply<QRect> reply = conn.connection().call(message); 1213 if (!reply.isValid()) { 1214 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access imageRect." << reply.error().message(); 1215 return QRect(); 1216 } 1217 return QRect( reply.value() ); 1218 } 1219 1220 QVector< QSharedPointer<QAction> > RegistryPrivate::actions(const AccessibleObject &object) 1221 { 1222 const QDBusMessage message = QDBusMessage::createMethodCall ( 1223 object.d->service, object.d->path, QLatin1String("org.a11y.atspi.Action"), QLatin1String("GetActions")); 1224 1225 const QDBusReply<QSpiActionArray> reply = conn.connection().call(message, QDBus::Block, 500); 1226 if (!reply.isValid()) { 1227 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not access actions." << reply.error().message(); 1228 return QVector< QSharedPointer<QAction> >(); 1229 } 1230 1231 const QSpiActionArray actionArray = reply.value(); 1232 QVector< QSharedPointer<QAction> > list; 1233 for(int i = 0, total = actionArray.count(); i < total; ++i) { 1234 const QSpiAction &a = actionArray[i]; 1235 QAction *action = new QAction(); 1236 const QString id = QStringLiteral("%1;%2;%3").arg(object.d->service).arg(object.d->path).arg(i); 1237 action->setObjectName(id); 1238 action->setText(a.name); 1239 action->setWhatsThis(a.description); 1240 if (!a.keyBinding.isEmpty()) { 1241 const QKeySequence shortcut(a.keyBinding); 1242 action->setShortcut(std::move(shortcut)); 1243 } 1244 m_actionMapper.setMapping(action, id); 1245 connect(action, SIGNAL(triggered()), &m_actionMapper, SLOT(map())); 1246 list.append(QSharedPointer<QAction>(action)); 1247 } 1248 return list; 1249 } 1250 1251 void RegistryPrivate::actionTriggered(const QString &action) 1252 { 1253 const QStringList actionParts = action.split(QLatin1Char(';')); 1254 Q_ASSERT(actionParts.count() == 3); 1255 const QString service = actionParts.at(0); 1256 const QString path = actionParts.at(1); 1257 const int index = actionParts.at(2).toInt(); 1258 1259 QDBusMessage message = QDBusMessage::createMethodCall ( 1260 service, path, QLatin1String("org.a11y.atspi.Action"), QLatin1String("DoAction")); 1261 1262 QVariantList args; 1263 args << index; 1264 message.setArguments(args); 1265 1266 QDBusReply<bool> reply = conn.connection().call(message, QDBus::Block, 500); 1267 if (!reply.isValid()) { 1268 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Could not execute action=" << action << reply.error().message(); 1269 return; 1270 } 1271 1272 if (reply.value()) { 1273 qDebug() << "Successful executed action=" << action; 1274 } else { 1275 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Failed to execute action=" << action; 1276 } 1277 } 1278 1279 QVariant RegistryPrivate::getProperty(const QString &service, const QString &path, const QString &interface, const QString &name) const 1280 { 1281 QVariantList args; 1282 args.append(interface); 1283 args.append(name); 1284 1285 QDBusMessage message = QDBusMessage::createMethodCall ( 1286 service, path, QLatin1String("org.freedesktop.DBus.Properties"), QLatin1String("Get")); 1287 1288 message.setArguments(args); 1289 const QDBusMessage reply = conn.connection().call(message, QDBus::Block, 500); 1290 if (reply.arguments().isEmpty()) 1291 return QVariant(); 1292 1293 const QDBusVariant v = reply.arguments().at(0).value<QDBusVariant>(); 1294 return v.variant(); 1295 } 1296 1297 AccessibleObject RegistryPrivate::accessibleFromPath(const QString &service, const QString &path) const 1298 { 1299 return AccessibleObject(const_cast<RegistryPrivate*>(this), service, path); 1300 } 1301 1302 AccessibleObject RegistryPrivate::accessibleFromReference(const QSpiObjectReference &reference) const 1303 { 1304 return accessibleFromPath(reference.service, reference.path.path()); 1305 } 1306 1307 AccessibleObject RegistryPrivate::accessibleFromContext() const 1308 { 1309 return accessibleFromPath(QDBusContext::message().service(), QDBusContext::message().path()); 1310 } 1311 1312 void RegistryPrivate::slotWindowCreate(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &) 1313 { 1314 Q_EMIT q->windowCreated(accessibleFromContext()); 1315 } 1316 1317 void RegistryPrivate::slotWindowDestroy(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1318 { 1319 Q_EMIT q->windowDestroyed(accessibleFromContext()); 1320 } 1321 1322 void RegistryPrivate::slotWindowClose(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1323 { 1324 Q_EMIT q->windowClosed(accessibleFromContext()); 1325 } 1326 1327 void RegistryPrivate::slotWindowReparent(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1328 { 1329 Q_EMIT q->windowReparented(accessibleFromContext()); 1330 } 1331 1332 void RegistryPrivate::slotWindowMinimize(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1333 { 1334 Q_EMIT q->windowMinimized(accessibleFromContext()); 1335 } 1336 1337 void RegistryPrivate::slotWindowMaximize(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1338 { 1339 Q_EMIT q->windowMaximized(accessibleFromContext()); 1340 } 1341 1342 void RegistryPrivate::slotWindowRestore(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1343 { 1344 Q_EMIT q->windowRestored(accessibleFromContext()); 1345 } 1346 1347 void RegistryPrivate::slotWindowActivate(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1348 { 1349 Q_EMIT q->windowActivated(accessibleFromContext()); 1350 } 1351 1352 void RegistryPrivate::slotWindowDeactivate(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1353 { 1354 Q_EMIT q->windowDeactivated(accessibleFromContext()); 1355 } 1356 1357 void RegistryPrivate::slotWindowDesktopCreate(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1358 { 1359 Q_EMIT q->windowDesktopCreated(accessibleFromContext()); 1360 } 1361 1362 void RegistryPrivate::slotWindowDesktopDestroy(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1363 { 1364 Q_EMIT q->windowDesktopDestroyed(accessibleFromContext()); 1365 } 1366 1367 void RegistryPrivate::slotWindowRaise(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1368 { 1369 Q_EMIT q->windowRaised(accessibleFromContext()); 1370 } 1371 1372 void RegistryPrivate::slotWindowLower(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1373 { 1374 Q_EMIT q->windowLowered(accessibleFromContext()); 1375 } 1376 1377 void RegistryPrivate::slotWindowMove(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1378 { 1379 Q_EMIT q->windowMoved(accessibleFromContext()); 1380 } 1381 1382 void RegistryPrivate::slotWindowResize(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1383 { 1384 Q_EMIT q->windowResized(accessibleFromContext()); 1385 } 1386 1387 void RegistryPrivate::slotWindowShade(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1388 { 1389 Q_EMIT q->windowShaded(accessibleFromContext()); 1390 } 1391 1392 void RegistryPrivate::slotWindowUnshade(const QString &state, int detail1, int detail2, const QDBusVariant &/*args*/, const QAccessibleClient::QSpiObjectReference &reference) 1393 { 1394 Q_EMIT q->windowUnshaded(accessibleFromContext()); 1395 } 1396 1397 void RegistryPrivate::slotPropertyChange(const QString &property, int detail1, int detail2, const QDBusVariant &args, const QSpiObjectReference &reference) 1398 { 1399 #ifdef ATSPI_DEBUG 1400 qDebug() << Q_FUNC_INFO << property << detail1 << detail2 << args.variant() << reference.path.path(); 1401 #endif 1402 if (property == QLatin1String("accessible-name")) { 1403 Q_EMIT q->accessibleNameChanged(accessibleFromContext()); 1404 } else if (property == QLatin1String("accessible-description")) { 1405 Q_EMIT q->accessibleDescriptionChanged(accessibleFromContext()); 1406 } 1407 } 1408 1409 void RegistryPrivate::slotStateChanged(const QString &state, int detail1, int detail2, const QDBusVariant &object, const QSpiObjectReference &reference) 1410 { 1411 //qDebug() << Q_FUNC_INFO << state << detail1 << detail2 << reference.service << reference.path.path() << QDBusContext::message(); 1412 1413 if (state == QLatin1String("defunct") && (detail1 == 1)) { 1414 QSpiObjectReference removed; 1415 removed.service = QDBusContext::message().service(); 1416 removed.path = QDBusObjectPath(QDBusContext::message().path()); 1417 removeAccessibleObject(removed); 1418 return; 1419 } 1420 1421 AccessibleObject accessible = accessibleFromContext(); 1422 if (m_cache) { 1423 m_cache->cleanState(accessible); 1424 } 1425 1426 if (state == QLatin1String("focused") && (detail1 == 1) && 1427 (q->subscribedEventListeners().testFlag(Registry::Focus))) { 1428 Q_EMIT q->focusChanged(accessible); 1429 } 1430 1431 if (q->subscribedEventListeners().testFlag(Registry::StateChanged)) { 1432 Q_EMIT q->stateChanged(accessible, state, detail1 == 1); 1433 } 1434 } 1435 1436 // void RegistryPrivate::slotLinkSelected(const QString &/*state*/, int /*detail1*/, int /*detail2*/, const QDBusVariant &args, const QAccessibleClient::QSpiObjectReference &reference) 1437 // { 1438 // Q_EMIT q->linkSelected(accessibleFromContext()); 1439 // } 1440 1441 bool RegistryPrivate::removeAccessibleObject(const QAccessibleClient::AccessibleObject &accessible) 1442 { 1443 Q_ASSERT(accessible.isValid()); 1444 if (m_cache) { 1445 const QString id = accessible.id(); 1446 if (m_cache->remove(id)) { 1447 Q_EMIT q->removed(accessible); 1448 } 1449 } else { 1450 Q_EMIT q->removed(accessible); 1451 } 1452 if (accessible.d) 1453 accessible.d->setDefunct(); 1454 return true; 1455 } 1456 1457 bool RegistryPrivate::removeAccessibleObject(const QAccessibleClient::QSpiObjectReference &reference) 1458 { 1459 QAccessibleClient::AccessibleObject acc = accessibleFromReference(reference); 1460 if (acc.isValid()) { 1461 if (removeAccessibleObject(acc)) 1462 return true; 1463 } 1464 return false; 1465 } 1466 1467 void RegistryPrivate::slotChildrenChanged(const QString &state, int detail1, int detail2, const QDBusVariant &args, const QAccessibleClient::QSpiObjectReference &reference) 1468 { 1469 // qDebug() << Q_FUNC_INFO << state << detail1 << detail2 << args.variant() << reference.path.path(); 1470 QAccessibleClient::AccessibleObject parentAccessible = accessibleFromContext(); 1471 if (!parentAccessible.isValid()) { 1472 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << Q_FUNC_INFO << "Children change with invalid parent." << reference.path.path(); 1473 return; 1474 } 1475 1476 const int index = detail1; 1477 if (state == QLatin1String("add")) { 1478 Q_EMIT q->childAdded(parentAccessible, index); 1479 } else if (state == QLatin1String("remove")) { 1480 Q_EMIT q->childRemoved(parentAccessible, index); 1481 } else { 1482 qCWarning(LIBQACCESSIBILITYCLIENT_LOG) << "Invalid state in ChildrenChanged." << state; 1483 } 1484 } 1485 1486 void RegistryPrivate::slotVisibleDataChanged(const QString &/*state*/, int /*detail1*/, int /*detail2*/, const QDBusVariant &args, const QAccessibleClient::QSpiObjectReference &reference) 1487 { 1488 Q_EMIT q->visibleDataChanged(accessibleFromContext()); 1489 } 1490 1491 void RegistryPrivate::slotSelectionChanged(const QString &/*state*/, int /*detail1*/, int /*detail2*/, const QDBusVariant &args, const QAccessibleClient::QSpiObjectReference &reference) 1492 { 1493 Q_EMIT q->selectionChanged(accessibleFromContext()); 1494 } 1495 1496 void RegistryPrivate::slotModelChanged(const QString &/*state*/, int /*detail1*/, int /*detail2*/, const QDBusVariant &args, const QAccessibleClient::QSpiObjectReference &reference) 1497 { 1498 Q_EMIT q->modelChanged(accessibleFromContext()); 1499 } 1500 1501 void RegistryPrivate::slotTextCaretMoved(const QString &/*state*/, int detail1, int /*detail2*/, const QDBusVariant &/*args*/, const QSpiObjectReference &reference) 1502 { 1503 Q_EMIT q->textCaretMoved(accessibleFromContext(), detail1); 1504 } 1505 1506 void RegistryPrivate::slotTextSelectionChanged(const QString &/*state*/, int /*detail1*/, int /*detail2*/, const QDBusVariant &/*args*/, const QSpiObjectReference &reference) 1507 { 1508 Q_EMIT q->textSelectionChanged(accessibleFromContext()); 1509 } 1510 1511 void RegistryPrivate::slotTextChanged(const QString &change, int start, int end, const QDBusVariant &textVariant, const QSpiObjectReference &reference) 1512 { 1513 const AccessibleObject object(accessibleFromContext()); 1514 const QString text = textVariant.variant().toString(); 1515 1516 if (change == QLatin1String("insert")) { 1517 Q_EMIT q->textInserted(object, text, start, end); 1518 } else if (change == QLatin1String("remove")) { 1519 Q_EMIT q->textRemoved(object, text, start, end); 1520 } else { 1521 Q_EMIT q->textChanged(object, text, start, end); 1522 } 1523 } 1524 1525 #include "moc_registry_p.cpp"