Add Linux Accessibility Bridge
This is a plugin that bridges the QAccessible world to AT-SPI 2 on Linux. Change-Id: I7af22621ee6a3cefc723b137b7f227a611cf6641 Reviewed-by: Jan-Arve Sæther <jan-arve.saether@nokia.com>bb10
parent
85b624a969
commit
8e1ff45e74
|
|
@ -3012,7 +3012,7 @@ Configure options:
|
|||
+ -largefile ......... Enables Qt to access files larger than 4 GB.
|
||||
|
||||
-no-accessibility .. Do not compile Accessibility support.
|
||||
* -accessibility ..... Compile Accessibility support.
|
||||
+ -accessibility ..... Compile Accessibility support.
|
||||
|
||||
-no-sql-<driver> ... Disable SQL <driver> entirely.
|
||||
-qt-sql-<driver> ... Enable a SQL <driver> in the QtSql library, by default
|
||||
|
|
@ -3989,11 +3989,6 @@ if [ "$CFG_LIBPNG" = "auto" ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# detect accessibility
|
||||
if [ "$CFG_ACCESSIBILITY" = "auto" ]; then
|
||||
CFG_ACCESSIBILITY=yes
|
||||
fi
|
||||
|
||||
if [ "$CFG_EGLFS" = "yes" ]; then
|
||||
if [ "$CFG_EGL" = "no" ]; then
|
||||
echo "The EGLFS plugin requires EGL support and cannot be built"
|
||||
|
|
@ -4842,6 +4837,25 @@ if [ "$CFG_KMS" = "yes" ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Detect accessibility support
|
||||
if [ "$CFG_ACCESSIBILITY" != "no" ]; then
|
||||
if [ "$CFG_XCB" = "no" ]; then
|
||||
CFG_ACCESSIBILITY=yes
|
||||
else
|
||||
# linux/xcb accessibility needs dbus and atspi-2
|
||||
if [ "$CFG_DBUS" != "no" ] && [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists "atspi-2" 2>/dev/null; then
|
||||
CFG_ACCESSIBILITY=yes
|
||||
else
|
||||
if [ "$CFG_ACCESSIBILITY" = "auto" ]; then
|
||||
CFG_ACCESSIBILITY=no
|
||||
else
|
||||
echo "Accessibility support needs pkg-config and libatspi2."
|
||||
exit 101
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Determine the default QPA platform
|
||||
if [ -z "$QT_QPA_DEFAULT_PLATFORM" ]; then
|
||||
# check the mkspec
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
DBUS_ADAPTORS = $$PWD/xml/Cache.xml $$PWD/xml/DeviceEventController.xml
|
||||
QDBUSXML2CPP_ADAPTOR_HEADER_FLAGS = -i struct_marshallers_p.h
|
||||
|
||||
DBUS_INTERFACES = $$PWD/xml/Socket.xml
|
||||
QDBUSXML2CPP_INTERFACE_HEADER_FLAGS = -i struct_marshallers_p.h
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<node name="/node">
|
||||
<interface name="org.a11y.atspi.Cache">
|
||||
|
||||
<method name="GetItems">
|
||||
<arg name="nodes" type="a((so)(so)a(so)assusau)" direction="out"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QSpiAccessibleCacheArray"/>
|
||||
</method>
|
||||
|
||||
<signal name="AddAccessible">
|
||||
<arg name="nodeAdded" type="((so)(so)a(so)assusau)"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QSpiAccessibleCacheItem"/>
|
||||
</signal>
|
||||
|
||||
<signal name="RemoveAccessible">
|
||||
<arg name="nodeRemoved" type="(so)"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
|
||||
</signal>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<node name="/node">
|
||||
<interface name="org.a11y.atspi.DeviceEventController">
|
||||
|
||||
<!--
|
||||
<method name="RegisterKeystrokeListener">
|
||||
<arg direction="in" name="listener" type="o"/>
|
||||
<arg direction="in" name="keys" type="a(iisi)">
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QSpiKeyTypeArray"/>
|
||||
</arg>
|
||||
<arg direction="in" name="mask" type="u"/>
|
||||
<arg direction="in" name="type" type="au">
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.In3" value="QSpiEventTypeArray"/>
|
||||
</arg>
|
||||
<arg direction="in" name="mode" type="(bbb)">
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.In4" value="QSpiEventMode"/>
|
||||
</arg>
|
||||
<arg direction="out" type="b"/>
|
||||
</method>
|
||||
|
||||
<method name="DeregisterKeystrokeListener">
|
||||
<arg direction="in" name="listener" type="o"/>
|
||||
<arg direction="in" name="keys" type="a(iisi)">
|
||||
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QSpiKeyTypeArray"/>
|
||||
</arg>
|
||||
<arg direction="in" name="mask" type="u"/>
|
||||
<arg direction="in" name="type" type="u"/>
|
||||
</method>
|
||||
|
||||
<method name="RegisterDeviceEventListener">
|
||||
<arg direction="in" name="listener" type="o"/>
|
||||
<arg direction="in" name="types" type="u"/>
|
||||
<arg direction="out" type="b"/>
|
||||
</method>
|
||||
|
||||
<method name="DeregisterDeviceEventListener">
|
||||
<arg direction="in" name="listener" type="o"/>
|
||||
<arg direction="in" name="types" type="u"/>
|
||||
</method>
|
||||
|
||||
<method name="GenerateKeyboardEvent">
|
||||
<arg direction="in" name="keycode" type="i"/>
|
||||
<arg direction="in" name="keystring" type="s"/>
|
||||
<arg direction="in" name="type" type="u"/>
|
||||
</method>
|
||||
|
||||
<method name="GenerateMouseEvent">
|
||||
<arg direction="in" name="x" type="i"/>
|
||||
<arg direction="in" name="y" type="i"/>
|
||||
<arg direction="in" name="eventName" type="s"/>
|
||||
</method>
|
||||
-->
|
||||
|
||||
<method name="NotifyListenersSync">
|
||||
<arg direction="in" name="event" type="(uinnisb)"/>
|
||||
<arg direction="out" type="b"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QSpiDeviceEvent"/>
|
||||
</method>
|
||||
|
||||
<method name="NotifyListenersAsync">
|
||||
<arg direction="in" name="event" type="(uinnisb)"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QSpiDeviceEvent"/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<node name="/node">
|
||||
<interface name="org.a11y.atspi.Socket">
|
||||
|
||||
<method name="Embed">
|
||||
<arg direction="in" name="plug" type="(so)"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
|
||||
<arg direction="out" name="socket" type="(so)"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QSpiObjectReference"/>
|
||||
</method>
|
||||
|
||||
<method name="Unembed">
|
||||
<arg direction="in" name="plug" type="(so)"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
|
||||
</method>
|
||||
|
||||
<signal name="Available">
|
||||
<arg direction="in" name="socket" type="(so)"/>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QSpiObjectReference"/>
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
</node>
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "application_p.h"
|
||||
|
||||
#include <QtWidgets/qapplication.h>
|
||||
#include <QtDBus/qdbuspendingreply.h>
|
||||
#include <qdebug.h>
|
||||
|
||||
#include "deviceeventcontroller_adaptor.h"
|
||||
|
||||
//#define KEYBOARD_DEBUG
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QSpiApplicationAdaptor
|
||||
|
||||
\brief QSpiApplicationAdaptor
|
||||
|
||||
QSpiApplicationAdaptor
|
||||
*/
|
||||
|
||||
QSpiApplicationAdaptor::QSpiApplicationAdaptor(const QDBusConnection &connection, QObject *parent)
|
||||
: QObject(parent), dbusConnection(connection)
|
||||
{
|
||||
}
|
||||
|
||||
enum QSpiKeyEventType {
|
||||
QSPI_KEY_EVENT_PRESS,
|
||||
QSPI_KEY_EVENT_RELEASE,
|
||||
QSPI_KEY_EVENT_LAST_DEFINED
|
||||
};
|
||||
|
||||
void QSpiApplicationAdaptor::sendEvents(bool active)
|
||||
{
|
||||
if (active) {
|
||||
qApp->installEventFilter(this);
|
||||
} else {
|
||||
qApp->removeEventFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event)
|
||||
{
|
||||
if (!event->spontaneous())
|
||||
return false;
|
||||
|
||||
switch (event->type()) {
|
||||
case QEvent::WindowActivate:
|
||||
emit windowActivated(target, true);
|
||||
break;
|
||||
case QEvent::WindowDeactivate:
|
||||
emit windowActivated(target, false);
|
||||
break;
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease: {
|
||||
QKeyEvent *keyEvent = static_cast <QKeyEvent *>(event);
|
||||
QSpiDeviceEvent de;
|
||||
|
||||
if (event->type() == QEvent::KeyPress)
|
||||
de.type = QSPI_KEY_EVENT_PRESS;
|
||||
else
|
||||
de.type = QSPI_KEY_EVENT_RELEASE;
|
||||
|
||||
de.id = keyEvent->nativeVirtualKey();
|
||||
de.hardwareCode = keyEvent->nativeScanCode();
|
||||
|
||||
de.modifiers = keyEvent->nativeModifiers();
|
||||
de.timestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
if (keyEvent->key() == Qt::Key_Tab)
|
||||
de.text = QStringLiteral("Tab");
|
||||
else if (keyEvent->key() == Qt::Key_Backtab)
|
||||
de.text = QStringLiteral("Backtab");
|
||||
else if (keyEvent->key() == Qt::Key_Left)
|
||||
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_Left") : QStringLiteral("Left");
|
||||
else if (keyEvent->key() == Qt::Key_Right)
|
||||
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_Right") : QStringLiteral("Right");
|
||||
else if (keyEvent->key() == Qt::Key_Up)
|
||||
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_Up") : QStringLiteral("Up");
|
||||
else if (keyEvent->key() == Qt::Key_Down)
|
||||
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_Down") : QStringLiteral("Down");
|
||||
else if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)
|
||||
de.text = QStringLiteral("Return");
|
||||
else if (keyEvent->key() == Qt::Key_Backspace)
|
||||
de.text = QStringLiteral("BackSpace");
|
||||
else if (keyEvent->key() == Qt::Key_Delete)
|
||||
de.text = QStringLiteral("Delete");
|
||||
else if (keyEvent->key() == Qt::Key_PageUp)
|
||||
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_Page_Up") : QStringLiteral("Page_Up");
|
||||
else if (keyEvent->key() == Qt::Key_PageDown)
|
||||
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_Page_Up") : QStringLiteral("Page_Down");
|
||||
else if (keyEvent->key() == Qt::Key_Home)
|
||||
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_Home") : QStringLiteral("Home");
|
||||
else if (keyEvent->key() == Qt::Key_End)
|
||||
de.text = (keyEvent->modifiers() & Qt::KeypadModifier) ? QStringLiteral("KP_End") : QStringLiteral("End");
|
||||
else if (keyEvent->key() == Qt::Key_Clear && (keyEvent->modifiers() & Qt::KeypadModifier))
|
||||
de.text = QStringLiteral("KP_Begin"); // Key pad 5
|
||||
else if (keyEvent->key() == Qt::Key_Escape)
|
||||
de.text = QStringLiteral("Escape");
|
||||
else if (keyEvent->key() == Qt::Key_Space)
|
||||
de.text = QStringLiteral("space");
|
||||
else if (keyEvent->key() == Qt::Key_CapsLock)
|
||||
de.text = QStringLiteral("Caps_Lock");
|
||||
else if (keyEvent->key() == Qt::Key_NumLock)
|
||||
de.text = QStringLiteral("Num_Lock");
|
||||
else if (keyEvent->key() == Qt::Key_Insert)
|
||||
de.text = QStringLiteral("Insert");
|
||||
else
|
||||
de.text = keyEvent->text();
|
||||
|
||||
// This is a bit dubious, Gnome uses some gtk function here.
|
||||
// Long term the spec will hopefully change to just use keycodes.
|
||||
de.isText = !de.text.isEmpty();
|
||||
|
||||
#ifdef KEYBOARD_DEBUG
|
||||
qDebug() << QStringLiteral("Key event text: ") << event->type() << de.isText << QStringLiteral(" ") << de.text
|
||||
<< QStringLiteral(" hardware code: ") << de.hardwareCode
|
||||
<< QStringLiteral(" native sc: ") << keyEvent->nativeScanCode()
|
||||
<< QStringLiteral(" native mod: ") << keyEvent->nativeModifiers()
|
||||
<< QStringLiteral("native virt: ") << keyEvent->nativeVirtualKey();
|
||||
#endif
|
||||
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(QStringLiteral("org.a11y.atspi.Registry"),
|
||||
QStringLiteral("/org/a11y/atspi/registry/deviceeventcontroller"),
|
||||
QStringLiteral("org.a11y.atspi.DeviceEventController"), QStringLiteral("NotifyListenersSync"));
|
||||
m.setArguments(QVariantList() <<QVariant::fromValue(de));
|
||||
|
||||
// FIXME: this is critical, the timeout should probably be pretty low to allow normal processing
|
||||
int timeout = 100;
|
||||
bool sent = dbusConnection.callWithCallback(m, this, SLOT(notifyKeyboardListenerCallback(QDBusMessage)),
|
||||
SLOT(notifyKeyboardListenerError(QDBusError, QDBusMessage)), timeout);
|
||||
if (sent) {
|
||||
//queue the event and send it after callback
|
||||
keyEvents.enqueue(QPair<QObject*, QKeyEvent*> (target, copyKeyEvent(keyEvent)));
|
||||
#ifdef KEYBOARD_DEBUG
|
||||
qDebug() << QStringLiteral("Sent key: ") << de.text;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QKeyEvent* QSpiApplicationAdaptor::copyKeyEvent(QKeyEvent* old)
|
||||
{
|
||||
return new QKeyEvent(old->type(), old->key(), old->modifiers(), old->text(), old->isAutoRepeat(), old->count());
|
||||
}
|
||||
|
||||
void QSpiApplicationAdaptor::notifyKeyboardListenerCallback(const QDBusMessage& message)
|
||||
{
|
||||
if (!keyEvents.length()) {
|
||||
qWarning() << QStringLiteral("QSpiApplication::notifyKeyboardListenerCallback with no queued key called");
|
||||
return;
|
||||
}
|
||||
Q_ASSERT(message.arguments().length() == 1);
|
||||
if (message.arguments().at(0).toBool() == true) {
|
||||
QPair<QObject*, QKeyEvent*> event = keyEvents.dequeue();
|
||||
delete event.second;
|
||||
} else {
|
||||
QPair<QObject*, QKeyEvent*> event = keyEvents.dequeue();
|
||||
QApplication::postEvent(event.first, event.second);
|
||||
}
|
||||
}
|
||||
|
||||
void QSpiApplicationAdaptor::notifyKeyboardListenerError(const QDBusError& error, const QDBusMessage& /*message*/)
|
||||
{
|
||||
qWarning() << QStringLiteral("QSpiApplication::keyEventError ") << error.name() << error.message();
|
||||
while (!keyEvents.isEmpty()) {
|
||||
QPair<QObject*, QKeyEvent*> event = keyEvents.dequeue();
|
||||
QApplication::postEvent(event.first, event.second);
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef Q_SPI_APPLICATION_H
|
||||
#define Q_SPI_APPLICATION_H
|
||||
|
||||
#include <QtCore/QQueue>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtGui/QAccessibleInterface>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*
|
||||
* Used for the root object.
|
||||
*
|
||||
* Uses the root object reference and reports its parent as the desktop object.
|
||||
*/
|
||||
class QSpiApplicationAdaptor :public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QSpiApplicationAdaptor(const QDBusConnection &connection, QObject *parent);
|
||||
virtual ~QSpiApplicationAdaptor() {}
|
||||
void sendEvents(bool active);
|
||||
|
||||
Q_SIGNALS:
|
||||
void windowActivated(QObject* window, bool active);
|
||||
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event);
|
||||
|
||||
private Q_SLOTS:
|
||||
void notifyKeyboardListenerCallback(const QDBusMessage& message);
|
||||
void notifyKeyboardListenerError(const QDBusError& error, const QDBusMessage& message);
|
||||
|
||||
private:
|
||||
static QKeyEvent* copyKeyEvent(QKeyEvent*);
|
||||
|
||||
QQueue<QPair<QObject*, QKeyEvent*> > keyEvents;
|
||||
QDBusConnection dbusConnection;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
QT_END_HEADER
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,220 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef ATSPIADAPTOR_H
|
||||
#define ATSPIADAPTOR_H
|
||||
|
||||
#include <atspi/atspi-constants.h>
|
||||
|
||||
#include <QtCore/qsharedpointer.h>
|
||||
#include <QtDBus/qdbusvirtualobject.h>
|
||||
#include <QtGui/qaccessible.h>
|
||||
#include <QtGui/qaccessible2.h>
|
||||
|
||||
#include "dbusconnection_p.h"
|
||||
#include "struct_marshallers_p.h"
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QAccessibleInterface;
|
||||
class QSpiAccessibleInterface;
|
||||
class QSpiApplicationAdaptor;
|
||||
|
||||
typedef QSharedPointer<QAccessibleInterface> QAIPointer;
|
||||
|
||||
class AtSpiAdaptor :public QDBusVirtualObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AtSpiAdaptor(DBusConnection *connection, QObject *parent = 0);
|
||||
~AtSpiAdaptor();
|
||||
|
||||
void registerApplication();
|
||||
QString introspect(const QString &path) const;
|
||||
bool handleMessage(const QDBusMessage &message, const QDBusConnection &connection);
|
||||
void notify(QAccessibleEvent *event);
|
||||
|
||||
void setInitialized(bool init);
|
||||
|
||||
public Q_SLOTS:
|
||||
void eventListenerRegistered(const QString &bus, const QString &path);
|
||||
void eventListenerDeregistered(const QString &bus, const QString &path);
|
||||
void windowActivated(QObject* window, bool active);
|
||||
|
||||
private:
|
||||
void updateEventListeners();
|
||||
void setBitFlag(const QString &flag);
|
||||
|
||||
// sending messages
|
||||
QVariantList packDBusSignalArguments(const QString &type, int data1, int data2, const QVariant &variantData) const;
|
||||
bool sendDBusSignal(const QString &path, const QString &interface, const QString &name, const QVariantList &arguments) const;
|
||||
QVariant variantForPath(const QString &path) const;
|
||||
|
||||
void sendFocusChanged(const QAIPointer &interface) const;
|
||||
void notifyAboutCreation(const QAIPointer &interface) const;
|
||||
void notifyAboutDestruction(const QAIPointer &interface) const;
|
||||
|
||||
// handlers for the different accessible interfaces
|
||||
bool applicationInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
|
||||
bool accessibleInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
|
||||
bool componentInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
|
||||
bool actionInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
|
||||
bool textInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
|
||||
bool editableTextInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
|
||||
bool valueInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
|
||||
bool tableInterface(const QAIPointer &interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection);
|
||||
|
||||
void sendReply(const QDBusConnection &connection, const QDBusMessage &message, const QVariant &argument) const;
|
||||
|
||||
QAIPointer interfaceFromPath(const QString& dbusPath) const;
|
||||
QString pathForInterface(const QAIPointer &interface, bool inDestructor = false) const;
|
||||
QString pathForObject(QObject *object) const;
|
||||
|
||||
// accessible helper functions
|
||||
AtspiRole getRole(const QAIPointer &interface) const;
|
||||
QSpiRelationArray relationSet(const QAIPointer &interface, const QDBusConnection &connection) const;
|
||||
QStringList accessibleInterfaces(const QAIPointer &interface) const;
|
||||
|
||||
// component helper functions
|
||||
static QRect getExtents(const QAIPointer &interface, uint coordType);
|
||||
static QRect translateRectToWindowCoordinates(const QAIPointer &interface, const QRect &rect);
|
||||
|
||||
// action helper functions
|
||||
QSpiActionArray getActions(QAccessibleActionInterface* interface) const;
|
||||
|
||||
// text helper functions
|
||||
QVariantList getAttributes(const QAIPointer &, int offset, bool includeDefaults) const;
|
||||
QVariantList getAttributeValue(const QAIPointer &, int offset, const QString &attributeName) const;
|
||||
QRect getCharacterExtents(const QAIPointer &, int offset, uint coordType) const;
|
||||
QRect getRangeExtents(const QAIPointer &, int startOffset, int endOffset, uint coordType) const;
|
||||
QAccessible2::BoundaryType qAccessibleBoundaryType(int atspiTextBoundaryType) const;
|
||||
static bool inheritsQAction(QObject *object);
|
||||
|
||||
// private vars
|
||||
QSpiObjectReference accessibilityRegistry;
|
||||
DBusConnection *m_dbus;
|
||||
QSpiApplicationAdaptor *m_applicationAdaptor;
|
||||
|
||||
/// Assigned from the accessibility registry.
|
||||
int m_applicationId;
|
||||
bool initialized;
|
||||
|
||||
mutable QHash<quintptr, QPointer<QObject> > m_handledObjects;
|
||||
|
||||
// Bit fields - which updates to send
|
||||
|
||||
// AT-SPI has some events that we do not care about:
|
||||
// document
|
||||
// document-load-complete
|
||||
// document-load-stopped
|
||||
// document-reload
|
||||
uint sendFocus : 1;
|
||||
// mouse abs/rel/button
|
||||
|
||||
// all of object
|
||||
uint sendObject : 1;
|
||||
uint sendObject_active_descendant_changed : 1;
|
||||
uint sendObject_attributes_changed : 1;
|
||||
uint sendObject_bounds_changed : 1;
|
||||
uint sendObject_children_changed : 1;
|
||||
// uint sendObject_children_changed_add : 1;
|
||||
// uint sendObject_children_changed_remove : 1;
|
||||
uint sendObject_column_deleted : 1;
|
||||
uint sendObject_column_inserted : 1;
|
||||
uint sendObject_column_reordered : 1;
|
||||
uint sendObject_link_selected : 1;
|
||||
uint sendObject_model_changed : 1;
|
||||
uint sendObject_property_change : 1;
|
||||
uint sendObject_property_change_accessible_description : 1;
|
||||
uint sendObject_property_change_accessible_name : 1;
|
||||
uint sendObject_property_change_accessible_parent : 1;
|
||||
uint sendObject_property_change_accessible_role : 1;
|
||||
uint sendObject_property_change_accessible_table_caption : 1;
|
||||
uint sendObject_property_change_accessible_table_column_description : 1;
|
||||
uint sendObject_property_change_accessible_table_column_header : 1;
|
||||
uint sendObject_property_change_accessible_table_row_description : 1;
|
||||
uint sendObject_property_change_accessible_table_row_header : 1;
|
||||
uint sendObject_property_change_accessible_table_summary : 1;
|
||||
uint sendObject_property_change_accessible_value : 1;
|
||||
uint sendObject_row_deleted : 1;
|
||||
uint sendObject_row_inserted : 1;
|
||||
uint sendObject_row_reordered : 1;
|
||||
uint sendObject_selection_changed : 1;
|
||||
uint sendObject_state_changed : 1;
|
||||
uint sendObject_text_attributes_changed : 1;
|
||||
uint sendObject_text_bounds_changed : 1;
|
||||
uint sendObject_text_caret_moved : 1;
|
||||
uint sendObject_text_changed : 1;
|
||||
// uint sendObject_text_changed_delete : 1;
|
||||
// uint sendObject_text_changed_insert : 1;
|
||||
uint sendObject_text_selection_changed : 1;
|
||||
uint sendObject_value_changed : 1;
|
||||
uint sendObject_visible_data_changed : 1;
|
||||
|
||||
// we don't implement terminal
|
||||
// terminal-application_changed/charwidth_changed/columncount_changed/line_changed/linecount_changed
|
||||
uint sendWindow : 1;
|
||||
uint sendWindow_activate : 1;
|
||||
uint sendWindow_close: 1;
|
||||
uint sendWindow_create : 1;
|
||||
uint sendWindow_deactivate : 1;
|
||||
// uint sendWindow_desktop_create : 1;
|
||||
// uint sendWindow_desktop_destroy : 1;
|
||||
uint sendWindow_lower : 1;
|
||||
uint sendWindow_maximize : 1;
|
||||
uint sendWindow_minimize : 1;
|
||||
uint sendWindow_move : 1;
|
||||
uint sendWindow_raise : 1;
|
||||
uint sendWindow_reparent : 1;
|
||||
uint sendWindow_resize : 1;
|
||||
uint sendWindow_restore : 1;
|
||||
uint sendWindow_restyle : 1;
|
||||
uint sendWindow_shade : 1;
|
||||
uint sendWindow_unshade : 1;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
QT_END_HEADER
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "bridge_p.h"
|
||||
|
||||
#include <atspi/atspi-constants.h>
|
||||
#include <qstring.h>
|
||||
|
||||
#include "atspiadaptor_p.h"
|
||||
|
||||
#include "cache_p.h"
|
||||
#include "constant_mappings_p.h"
|
||||
#include "dbusconnection_p.h"
|
||||
#include "struct_marshallers_p.h"
|
||||
|
||||
#include "deviceeventcontroller_adaptor.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QSpiAccessibleBridge
|
||||
|
||||
\brief QSpiAccessibleBridge
|
||||
|
||||
QSpiAccessibleBridge
|
||||
*/
|
||||
|
||||
QSpiAccessibleBridge::QSpiAccessibleBridge()
|
||||
: cache(0)
|
||||
{
|
||||
dbusConnection = new DBusConnection();
|
||||
if (!dBusConnection().isConnected())
|
||||
qWarning() << "Could not connect to dbus.";
|
||||
|
||||
qSpiInitializeStructTypes();
|
||||
initializeConstantMappings();
|
||||
|
||||
/* Create the cache of accessible objects */
|
||||
cache = new QSpiDBusCache(dBusConnection(), this);
|
||||
dec = new DeviceEventControllerAdaptor(this);
|
||||
|
||||
bool reg = dBusConnection().registerObject(QLatin1String(ATSPI_DBUS_PATH_DEC), this, QDBusConnection::ExportAdaptors);
|
||||
qDebug() << "Registered DEC: " << reg;
|
||||
|
||||
dbusAdaptor = new AtSpiAdaptor(dbusConnection, this);
|
||||
dBusConnection().registerVirtualObject(QLatin1String(QSPI_OBJECT_PATH_ACCESSIBLE), dbusAdaptor, QDBusConnection::SubPath);
|
||||
dbusAdaptor->registerApplication();
|
||||
}
|
||||
|
||||
QSpiAccessibleBridge::~QSpiAccessibleBridge()
|
||||
{
|
||||
delete dbusConnection;
|
||||
} // Qt currently doesn't delete plugins.
|
||||
|
||||
QDBusConnection QSpiAccessibleBridge::dBusConnection() const
|
||||
{
|
||||
return dbusConnection->connection();
|
||||
}
|
||||
|
||||
void QSpiAccessibleBridge::setRootObject(QAccessibleInterface *interface)
|
||||
{
|
||||
// the interface we get will be for the QApplication object.
|
||||
// we already cache it in the constructor.
|
||||
Q_ASSERT(interface->object() == qApp);
|
||||
dbusAdaptor->setInitialized(true);
|
||||
}
|
||||
|
||||
void QSpiAccessibleBridge::notifyAccessibilityUpdate(QAccessibleEvent *event)
|
||||
{
|
||||
dbusAdaptor->notify(event);
|
||||
}
|
||||
|
||||
struct RoleMapping {
|
||||
QAccessible::Role role;
|
||||
AtspiRole spiRole;
|
||||
const char *name;
|
||||
const char *localizedName;
|
||||
};
|
||||
|
||||
static RoleMapping map[] = {
|
||||
{ QAccessible::NoRole, ATSPI_ROLE_INVALID, "invalid", QT_TR_NOOP("invalid role") },
|
||||
{ QAccessible::TitleBar, ATSPI_ROLE_TEXT, "text", QT_TR_NOOP("title bar") },
|
||||
{ QAccessible::MenuBar, ATSPI_ROLE_MENU_BAR, "menu bar", QT_TR_NOOP("menu bar") },
|
||||
{ QAccessible::ScrollBar, ATSPI_ROLE_SCROLL_BAR, "scroll bar", QT_TR_NOOP("scroll bar") },
|
||||
{ QAccessible::Grip, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("grip") },
|
||||
{ QAccessible::Sound, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("sound") },
|
||||
{ QAccessible::Cursor, ATSPI_ROLE_ARROW, "arrow", QT_TR_NOOP("cursor") },
|
||||
{ QAccessible::Caret, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("caret") },
|
||||
{ QAccessible::AlertMessage, ATSPI_ROLE_ALERT, "alert", QT_TR_NOOP("alert message") },
|
||||
{ QAccessible::Window, ATSPI_ROLE_WINDOW, "window", QT_TR_NOOP("window") },
|
||||
{ QAccessible::Client, ATSPI_ROLE_FILLER, "filler", QT_TR_NOOP("filler") },
|
||||
{ QAccessible::PopupMenu, ATSPI_ROLE_POPUP_MENU, "popup menu", QT_TR_NOOP("popup menu") },
|
||||
{ QAccessible::MenuItem, ATSPI_ROLE_MENU_ITEM, "menu item", QT_TR_NOOP("menu item") },
|
||||
{ QAccessible::ToolTip, ATSPI_ROLE_TOOL_TIP, "tool tip", QT_TR_NOOP("tool tip") },
|
||||
{ QAccessible::Application, ATSPI_ROLE_APPLICATION, "application", QT_TR_NOOP("application") },
|
||||
{ QAccessible::Document, ATSPI_ROLE_DOCUMENT_FRAME, "document frame", QT_TR_NOOP("document") },
|
||||
{ QAccessible::Pane, ATSPI_ROLE_PANEL, "panel", QT_TR_NOOP("pane") },
|
||||
{ QAccessible::Chart, ATSPI_ROLE_CHART, "chart", QT_TR_NOOP("chart") },
|
||||
{ QAccessible::Dialog, ATSPI_ROLE_DIALOG, "dialog", QT_TR_NOOP("dialog") },
|
||||
{ QAccessible::Border, ATSPI_ROLE_FRAME, "frame", QT_TR_NOOP("border") },
|
||||
{ QAccessible::Grouping, ATSPI_ROLE_PANEL, "panel", QT_TR_NOOP("grouping") },
|
||||
{ QAccessible::Separator, ATSPI_ROLE_SEPARATOR, "separator", QT_TR_NOOP("separator") },
|
||||
{ QAccessible::ToolBar, ATSPI_ROLE_TOOL_BAR, "tool bar", QT_TR_NOOP("tool bar") },
|
||||
{ QAccessible::StatusBar, ATSPI_ROLE_STATUS_BAR, "statusbar", QT_TR_NOOP("status bar") },
|
||||
{ QAccessible::Table, ATSPI_ROLE_TABLE, "table", QT_TR_NOOP("table") },
|
||||
{ QAccessible::ColumnHeader, ATSPI_ROLE_TABLE_COLUMN_HEADER, "column header", QT_TR_NOOP("column header") },
|
||||
{ QAccessible::RowHeader, ATSPI_ROLE_TABLE_ROW_HEADER, "row header", QT_TR_NOOP("row header") },
|
||||
{ QAccessible::Column, ATSPI_ROLE_TABLE_CELL, "table cell", QT_TR_NOOP("column") },
|
||||
{ QAccessible::Row, ATSPI_ROLE_TABLE_CELL, "table cell", QT_TR_NOOP("row") },
|
||||
{ QAccessible::Cell, ATSPI_ROLE_TABLE_CELL, "table cell", QT_TR_NOOP("cell") },
|
||||
{ QAccessible::Link, ATSPI_ROLE_LINK, "link", QT_TR_NOOP("link") },
|
||||
{ QAccessible::HelpBalloon, ATSPI_ROLE_DIALOG, "dialog", QT_TR_NOOP("help balloon") },
|
||||
{ QAccessible::Assistant, ATSPI_ROLE_DIALOG, "dialog", QT_TR_NOOP("assistant") },
|
||||
{ QAccessible::List, ATSPI_ROLE_LIST, "list", QT_TR_NOOP("list") },
|
||||
{ QAccessible::ListItem, ATSPI_ROLE_LIST_ITEM, "list item", QT_TR_NOOP("list item") },
|
||||
{ QAccessible::Tree, ATSPI_ROLE_TREE, "tree", QT_TR_NOOP("tree") },
|
||||
{ QAccessible::TreeItem, ATSPI_ROLE_TABLE_CELL, "tree item", QT_TR_NOOP("tree item") },
|
||||
{ QAccessible::PageTab, ATSPI_ROLE_PAGE_TAB, "page tab", QT_TR_NOOP("page tab") },
|
||||
{ QAccessible::PropertyPage, ATSPI_ROLE_PAGE_TAB, "page tab", QT_TR_NOOP("property page") },
|
||||
{ QAccessible::Indicator, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("indicator") },
|
||||
{ QAccessible::Graphic, ATSPI_ROLE_IMAGE, "image", QT_TR_NOOP("graphic") },
|
||||
{ QAccessible::StaticText, ATSPI_ROLE_LABEL, "label", QT_TR_NOOP("label") },
|
||||
{ QAccessible::EditableText, ATSPI_ROLE_TEXT, "text", QT_TR_NOOP("text") },
|
||||
{ QAccessible::PushButton, ATSPI_ROLE_PUSH_BUTTON, "push button", QT_TR_NOOP("push button") },
|
||||
{ QAccessible::CheckBox, ATSPI_ROLE_CHECK_BOX, "check box", QT_TR_NOOP("check box") },
|
||||
{ QAccessible::RadioButton, ATSPI_ROLE_RADIO_BUTTON, "radio button", QT_TR_NOOP("radio box") },
|
||||
{ QAccessible::ComboBox, ATSPI_ROLE_COMBO_BOX, "combo box", QT_TR_NOOP("combo box") },
|
||||
{ QAccessible::ProgressBar, ATSPI_ROLE_PROGRESS_BAR, "progress bar", QT_TR_NOOP("progress bar") },
|
||||
{ QAccessible::Dial, ATSPI_ROLE_DIAL, "accelerator label", QT_TR_NOOP("dial") },
|
||||
{ QAccessible::HotkeyField, ATSPI_ROLE_TEXT, "text", QT_TR_NOOP("hotkey field") }, //FIXME text?
|
||||
{ QAccessible::Slider, ATSPI_ROLE_SLIDER, "slider", QT_TR_NOOP("slider") },
|
||||
{ QAccessible::SpinBox, ATSPI_ROLE_SPIN_BUTTON, "spin button", QT_TR_NOOP("spin box") },
|
||||
{ QAccessible::Canvas, ATSPI_ROLE_CANVAS, "canvas", QT_TR_NOOP("canvas") },
|
||||
{ QAccessible::Animation, ATSPI_ROLE_ANIMATION, "animation", QT_TR_NOOP("animation") },
|
||||
{ QAccessible::Equation, ATSPI_ROLE_TEXT, "text", QT_TR_NOOP("equation") },
|
||||
{ QAccessible::ButtonDropDown, ATSPI_ROLE_PUSH_BUTTON, "push button", QT_TR_NOOP("button drop down") },
|
||||
{ QAccessible::ButtonMenu, ATSPI_ROLE_PUSH_BUTTON, "push button", QT_TR_NOOP("button menu") },
|
||||
{ QAccessible::ButtonDropGrid, ATSPI_ROLE_PUSH_BUTTON, "push button", QT_TR_NOOP("button drop grid") },
|
||||
{ QAccessible::Whitespace, ATSPI_ROLE_FILLER, "filler", QT_TR_NOOP("whitespace") },
|
||||
{ QAccessible::PageTabList, ATSPI_ROLE_PAGE_TAB_LIST, "page tab list", QT_TR_NOOP("page tab list") },
|
||||
{ QAccessible::Clock, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("clock") },
|
||||
{ QAccessible::Splitter, ATSPI_ROLE_SPLIT_PANE, "split pane", QT_TR_NOOP("splitter") },
|
||||
{ QAccessible::LayeredPane, ATSPI_ROLE_LAYERED_PANE, "layered pane", QT_TR_NOOP("layered pane") },
|
||||
{ QAccessible::UserRole, ATSPI_ROLE_UNKNOWN, "unknown", QT_TR_NOOP("user role") }
|
||||
};
|
||||
|
||||
void QSpiAccessibleBridge::initializeConstantMappings()
|
||||
{
|
||||
for (uint i = 0; i < sizeof(map) / sizeof(RoleMapping); ++i)
|
||||
qSpiRoleMapping.insert(map[i].role, RoleNames(map[i].spiRole, QLatin1String(map[i].name), tr(map[i].localizedName)));
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef QSPIACCESSIBLEBRIDGE_H
|
||||
#define QSPIACCESSIBLEBRIDGE_H
|
||||
|
||||
#include <QtDBus/qdbusconnection.h>
|
||||
#include <qpa/qplatformaccessibility.h>
|
||||
|
||||
class DeviceEventControllerAdaptor;
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class DBusConnection;
|
||||
class QSpiDBusCache;
|
||||
class AtSpiAdaptor;
|
||||
|
||||
class QSpiAccessibleBridge: public QObject, public QPlatformAccessibility
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QSpiAccessibleBridge();
|
||||
|
||||
virtual ~QSpiAccessibleBridge();
|
||||
virtual void setRootObject(QAccessibleInterface *obj);
|
||||
|
||||
virtual void notifyAccessibilityUpdate(QAccessibleEvent *event);
|
||||
QDBusConnection dBusConnection() const;
|
||||
|
||||
private:
|
||||
void initializeConstantMappings();
|
||||
|
||||
QSpiDBusCache *cache;
|
||||
DeviceEventControllerAdaptor *dec;
|
||||
|
||||
AtSpiAdaptor *dbusAdaptor;
|
||||
|
||||
DBusConnection* dbusConnection;
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
QT_END_HEADER
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "cache_p.h"
|
||||
#include "cache_adaptor.h"
|
||||
|
||||
#include "bridge_p.h"
|
||||
|
||||
#define QSPI_OBJECT_PATH_CACHE "/org/a11y/atspi/cache"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QSpiDBusCache
|
||||
|
||||
\brief This class is responsible for the AT-SPI cache interface.
|
||||
|
||||
The idea behind the cache is that starting an application would
|
||||
result in many dbus calls. The way GTK/Gail/ATK work is that
|
||||
they create accessibles for all objects on startup.
|
||||
In order to avoid querying all the objects individually via DBus
|
||||
they get sent by using the GetItems call of the cache.
|
||||
|
||||
Additionally the AddAccessible and RemoveAccessible signals
|
||||
are responsible for adding/removing objects from the cache.
|
||||
|
||||
Currently the Qt bridge chooses to ignore these.
|
||||
*/
|
||||
|
||||
QSpiDBusCache::QSpiDBusCache(QDBusConnection c, QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
new CacheAdaptor(this);
|
||||
c.registerObject(QLatin1String(QSPI_OBJECT_PATH_CACHE), this, QDBusConnection::ExportAdaptors);
|
||||
}
|
||||
|
||||
void QSpiDBusCache::emitAddAccessible(const QSpiAccessibleCacheItem& item)
|
||||
{
|
||||
emit AddAccessible(item);
|
||||
}
|
||||
|
||||
void QSpiDBusCache::emitRemoveAccessible(const QSpiObjectReference& item)
|
||||
{
|
||||
emit RemoveAccessible(item);
|
||||
}
|
||||
|
||||
QSpiAccessibleCacheArray QSpiDBusCache::GetItems()
|
||||
{
|
||||
QList <QSpiAccessibleCacheItem> cacheArray;
|
||||
return cacheArray;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef Q_SPI_CACHE_H
|
||||
#define Q_SPI_CACHE_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include "struct_marshallers_p.h"
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QSpiDBusCache : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QSpiDBusCache(QDBusConnection c, QObject* parent = 0);
|
||||
void emitAddAccessible(const QSpiAccessibleCacheItem& item);
|
||||
void emitRemoveAccessible(const QSpiObjectReference& item);
|
||||
|
||||
Q_SIGNALS:
|
||||
void AddAccessible(const QSpiAccessibleCacheItem &nodeAdded);
|
||||
void RemoveAccessible(const QSpiObjectReference &nodeRemoved);
|
||||
|
||||
public Q_SLOTS:
|
||||
QSpiAccessibleCacheArray GetItems();
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
QT_END_HEADER
|
||||
|
||||
#endif /* Q_SPI_CACHE_H */
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "constant_mappings_p.h"
|
||||
|
||||
#include <qobject.h>
|
||||
#include <qdebug.h>
|
||||
|
||||
// FIXME the assignment of roles is quite arbitrary, at some point go through this list and sort and check that it makes sense
|
||||
// "calendar" "check menu item" "color chooser" "column header" "dateeditor" "desktop icon" "desktop frame"
|
||||
// "directory pane" "drawing area" "file chooser" "fontchooser" "frame" "glass pane" "html container" "icon"
|
||||
// "internal frame" "option pane" "password text" "radio menu item" "root pane" "row header" "scroll pane"
|
||||
// "tear off menu item" "terminal" "toggle button" "tree table" "unknown" "viewport" "header" "footer" "paragraph"
|
||||
// "ruler" "autocomplete" "edit bar" "embedded component" "entry" "caption"
|
||||
// "heading" "page" "section" "redundant object" "form" "input method window" "menu"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QHash <QAccessible::Role, RoleNames> qSpiRoleMapping;
|
||||
|
||||
quint64 spiStatesFromQState(QAccessible::State state)
|
||||
{
|
||||
quint64 spiState = 0;
|
||||
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_EDITABLE);
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_ENABLED);
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_SHOWING);
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_VISIBLE);
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_SENSITIVE);
|
||||
|
||||
if (state.disabled) {
|
||||
unsetSpiStateBit(&spiState, ATSPI_STATE_ENABLED);
|
||||
unsetSpiStateBit(&spiState, ATSPI_STATE_SHOWING);
|
||||
unsetSpiStateBit(&spiState, ATSPI_STATE_VISIBLE);
|
||||
unsetSpiStateBit(&spiState, ATSPI_STATE_SENSITIVE);
|
||||
}
|
||||
|
||||
if (state.selected)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_SELECTED);
|
||||
if (state.focused)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_FOCUSED);
|
||||
if (state.pressed)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_PRESSED);
|
||||
if (state.checked)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_CHECKED);
|
||||
if (state.checkStateMixed)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_INDETERMINATE);
|
||||
if (state.readOnly)
|
||||
unsetSpiStateBit(&spiState, ATSPI_STATE_EDITABLE);
|
||||
// if (state.HotTracked)
|
||||
if (state.defaultButton)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_IS_DEFAULT);
|
||||
if (state.expanded)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_EXPANDED);
|
||||
if (state.collapsed)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_COLLAPSED);
|
||||
if (state.busy)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_BUSY);
|
||||
if (state.marqueed || state.animated)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_ANIMATED);
|
||||
if (state.invisible || state.offscreen) {
|
||||
unsetSpiStateBit(&spiState, ATSPI_STATE_SHOWING);
|
||||
unsetSpiStateBit(&spiState, ATSPI_STATE_VISIBLE);
|
||||
}
|
||||
if (state.sizeable)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_RESIZABLE);
|
||||
// if (state.Movable)
|
||||
// if (state.SelfVoicing)
|
||||
if (state.focusable)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_FOCUSABLE);
|
||||
if (state.selectable)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_SELECTABLE);
|
||||
// if (state.Linked)
|
||||
if (state.traversed)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_VISITED);
|
||||
if (state.multiSelectable)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_MULTISELECTABLE);
|
||||
if (state.extSelectable)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_SELECTABLE);
|
||||
// if (state.Protected)
|
||||
// if (state.HasPopup)
|
||||
if (state.modal)
|
||||
setSpiStateBit(&spiState, ATSPI_STATE_MODAL);
|
||||
|
||||
// Not implemented in Qt
|
||||
// if (state.singleLine)
|
||||
// setSpiStateBit(&spiState, ATSPI_STATE_SINGLE_LINE);
|
||||
|
||||
return spiState;
|
||||
}
|
||||
|
||||
QSpiUIntList spiStateSetFromSpiStates(quint64 states)
|
||||
{
|
||||
uint low = states & 0xFFFFFFFF;
|
||||
uint high = (states >> 32) & 0xFFFFFFFF;
|
||||
|
||||
QSpiUIntList stateList;
|
||||
stateList.append(low);
|
||||
stateList.append(high);
|
||||
return stateList;
|
||||
}
|
||||
|
||||
AtspiRelationType qAccessibleRelationToAtSpiRelation(QAccessible::Relation relation)
|
||||
{
|
||||
switch (relation) {
|
||||
case QAccessible::Label:
|
||||
return ATSPI_RELATION_LABELLED_BY;
|
||||
case QAccessible::Labelled:
|
||||
return ATSPI_RELATION_LABEL_FOR;
|
||||
case QAccessible::Controller:
|
||||
return ATSPI_RELATION_CONTROLLED_BY;
|
||||
case QAccessible::Controlled:
|
||||
return ATSPI_RELATION_CONTROLLER_FOR;
|
||||
default:
|
||||
qWarning() << "Cannot return AT-SPI relation for:" << relation;
|
||||
}
|
||||
return ATSPI_RELATION_NULL;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
* This file contains AT-SPI constants and mappings between QAccessible
|
||||
* and AT-SPI constants such as 'role' and 'state' enumerations.
|
||||
*/
|
||||
|
||||
#ifndef Q_SPI_CONSTANT_MAPPINGS_H
|
||||
#define Q_SPI_CONSTANT_MAPPINGS_H
|
||||
|
||||
#include "struct_marshallers_p.h"
|
||||
|
||||
#include <QtGui/QAccessible>
|
||||
#include <atspi/atspi-constants.h>
|
||||
|
||||
|
||||
// interface names from at-spi2-core/atspi/atspi-misc-private.h
|
||||
#define ATSPI_DBUS_NAME_REGISTRY "org.a11y.atspi.Registry"
|
||||
#define ATSPI_DBUS_PATH_REGISTRY "/org/a11y/atspi/registry"
|
||||
#define ATSPI_DBUS_INTERFACE_REGISTRY "org.a11y.atspi.Registry"
|
||||
|
||||
#define ATSPI_DBUS_PATH_ROOT "/org/a11y/atspi/accessible/root"
|
||||
|
||||
#define ATSPI_DBUS_PATH_DEC "/org/a11y/atspi/registry/deviceeventcontroller"
|
||||
#define ATSPI_DBUS_INTERFACE_DEC "org.a11y.atspi.DeviceEventController"
|
||||
#define ATSPI_DBUS_INTERFACE_DEVICE_EVENT_LISTENER "org.a11y.atspi.DeviceEventListener"
|
||||
|
||||
#define ATSPI_DBUS_INTERFACE_CACHE "org.a11y.atspi.Cache"
|
||||
#define ATSPI_DBUS_INTERFACE_ACCESSIBLE "org.a11y.atspi.Accessible"
|
||||
#define ATSPI_DBUS_INTERFACE_ACTION "org.a11y.atspi.Action"
|
||||
#define ATSPI_DBUS_INTERFACE_APPLICATION "org.a11y.atspi.Application"
|
||||
#define ATSPI_DBUS_INTERFACE_COLLECTION "org.a11y.atspi.Collection"
|
||||
#define ATSPI_DBUS_INTERFACE_COMPONENT "org.a11y.atspi.Component"
|
||||
#define ATSPI_DBUS_INTERFACE_DOCUMENT "org.a11y.atspi.Document"
|
||||
#define ATSPI_DBUS_INTERFACE_EDITABLE_TEXT "org.a11y.atspi.EditableText"
|
||||
#define ATSPI_DBUS_INTERFACE_EVENT_KEYBOARD "org.a11y.atspi.Event.Keyboard"
|
||||
#define ATSPI_DBUS_INTERFACE_EVENT_MOUSE "org.a11y.atspi.Event.Mouse"
|
||||
#define ATSPI_DBUS_INTERFACE_EVENT_OBJECT "org.a11y.atspi.Event.Object"
|
||||
#define ATSPI_DBUS_INTERFACE_HYPERLINK "org.a11y.atspi.Hyperlink"
|
||||
#define ATSPI_DBUS_INTERFACE_HYPERTEXT "org.a11y.atspi.Hypertext"
|
||||
#define ATSPI_DBUS_INTERFACE_IMAGE "org.a11y.atspi.Image"
|
||||
#define ATSPI_DBUS_INTERFACE_SELECTION "org.a11y.atspi.Selection"
|
||||
#define ATSPI_DBUS_INTERFACE_TABLE "org.a11y.atspi.Table"
|
||||
#define ATSPI_DBUS_INTERFACE_TEXT "org.a11y.atspi.Text"
|
||||
#define ATSPI_DBUS_INTERFACE_VALUE "org.a11y.atspi.Value"
|
||||
#define ATSPI_DBUS_INTERFACE_SOCKET "org.a11y.atspi.Socket"
|
||||
|
||||
// missing from at-spi2-core:
|
||||
#define ATSPI_DBUS_INTERFACE_EVENT_WINDOW "org.a11y.atspi.Event.Window"
|
||||
#define ATSPI_DBUS_INTERFACE_EVENT_FOCUS "org.a11y.atspi.Event.Focus"
|
||||
|
||||
#define QSPI_OBJECT_PATH_ACCESSIBLE "/org/a11y/atspi/accessible"
|
||||
#define QSPI_OBJECT_PATH_PREFIX "/org/a11y/atspi/accessible/"
|
||||
#define QSPI_OBJECT_PATH_ROOT QSPI_OBJECT_PATH_PREFIX "root"
|
||||
|
||||
#define QSPI_REGISTRY_NAME "org.a11y.atspi.Registry"
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
struct RoleNames {
|
||||
RoleNames() {}
|
||||
RoleNames(AtspiRole r, const QString& n, const QString& ln)
|
||||
:m_spiRole(r), m_name(n), m_localizedName(ln)
|
||||
{}
|
||||
|
||||
AtspiRole spiRole() const {return m_spiRole;}
|
||||
QString name() const {return m_name;}
|
||||
QString localizedName() const {return m_localizedName;}
|
||||
|
||||
private:
|
||||
AtspiRole m_spiRole;
|
||||
QString m_name;
|
||||
QString m_localizedName;
|
||||
};
|
||||
|
||||
extern QHash <QAccessible::Role, RoleNames> qSpiRoleMapping;
|
||||
extern QHash <int, AtspiStateType> qSpiStateMapping;
|
||||
|
||||
inline void setSpiStateBit(quint64* state, AtspiStateType spiState)
|
||||
{
|
||||
*state |= quint64(1) << spiState;
|
||||
}
|
||||
|
||||
inline void unsetSpiStateBit(quint64* state, AtspiStateType spiState)
|
||||
{
|
||||
*state &= ~(quint64(1) << spiState);
|
||||
}
|
||||
|
||||
quint64 spiStatesFromQState(QAccessible::State state);
|
||||
QSpiUIntList spiStateSetFromSpiStates(quint64 states);
|
||||
|
||||
AtspiRelationType qAccessibleRelationToAtSpiRelation(QAccessible::Relation relation);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
QT_END_HEADER
|
||||
|
||||
#endif /* Q_SPI_CONSTANT_MAPPINGS_H */
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "dbusconnection_p.h"
|
||||
|
||||
#include <QtDBus/QDBusMessage>
|
||||
#include <qdebug.h>
|
||||
|
||||
/*!
|
||||
\class DBusConnection
|
||||
|
||||
\brief DBusConnection
|
||||
|
||||
DBusConnection
|
||||
*/
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
Connects to the accessibility dbus.
|
||||
|
||||
This is usually a different bus from the session bus.
|
||||
*/
|
||||
DBusConnection::DBusConnection()
|
||||
: dbusConnection(connectDBus())
|
||||
{}
|
||||
|
||||
QDBusConnection DBusConnection::connectDBus()
|
||||
{
|
||||
QString address = getAccessibilityBusAddress();
|
||||
|
||||
if (!address.isEmpty()) {
|
||||
QDBusConnection c = QDBusConnection::connectToBus(address, QStringLiteral("a11y"));
|
||||
if (c.isConnected()) {
|
||||
qDebug() << "Connected to accessibility bus at: " << address;
|
||||
return c;
|
||||
}
|
||||
qWarning("Found Accessibility DBus address but cannot connect. Falling back to session bus.");
|
||||
} else {
|
||||
qWarning("Accessibility DBus not found. Falling back to session bus.");
|
||||
}
|
||||
|
||||
QDBusConnection c = QDBusConnection::sessionBus();
|
||||
if (!c.isConnected()) {
|
||||
qWarning("Could not connect to DBus.");
|
||||
}
|
||||
return QDBusConnection::sessionBus();
|
||||
}
|
||||
|
||||
QString DBusConnection::getAccessibilityBusAddress() const
|
||||
{
|
||||
QDBusConnection c = QDBusConnection::sessionBus();
|
||||
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String("org.a11y.Bus"),
|
||||
QLatin1String("/org/a11y/bus"),
|
||||
QLatin1String("org.a11y.Bus"), QLatin1String("GetAddress"));
|
||||
QDBusMessage reply = c.call(m);
|
||||
if (reply.type() == QDBusMessage::ErrorMessage) {
|
||||
qWarning() << "Qt at-spi: error getting the accessibility dbus address: " << reply.errorMessage();
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString busAddress = reply.arguments().at(0).toString();
|
||||
qDebug() << "Got bus address: " << busAddress;
|
||||
return busAddress;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the DBus connection that got established.
|
||||
*/
|
||||
QDBusConnection DBusConnection::connection() const
|
||||
{
|
||||
return dbusConnection;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef DBUSCONNECTION_H
|
||||
#define DBUSCONNECTION_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class DBusConnection
|
||||
{
|
||||
public:
|
||||
DBusConnection();
|
||||
QDBusConnection connection() const;
|
||||
|
||||
private:
|
||||
QString getAccessibilityBusAddress() const;
|
||||
QDBusConnection connectDBus();
|
||||
|
||||
QDBusConnection dbusConnection;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
QT_END_HEADER
|
||||
|
||||
#endif // DBUSCONNECTION_H
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
contains(QT_CONFIG, dbus):contains(QT_CONFIG, xcb):contains(QT_CONFIG, accessibility) {
|
||||
|
||||
PKGCONFIG += atspi-2
|
||||
CONFIG += link_pkgconfig
|
||||
QT += dbus
|
||||
include(../../3rdparty/atspi2/atspi2.pri)
|
||||
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/application_p.h \
|
||||
$$PWD/bridge_p.h \
|
||||
$$PWD/cache_p.h \
|
||||
$$PWD/struct_marshallers_p.h \
|
||||
$$PWD/constant_mappings_p.h \
|
||||
$$PWD/dbusconnection_p.h \
|
||||
$$PWD/atspiadaptor_p.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/application.cpp \
|
||||
$$PWD/bridge.cpp \
|
||||
$$PWD/cache.cpp \
|
||||
$$PWD/struct_marshallers.cpp \
|
||||
$$PWD/constant_mappings.cpp \
|
||||
$$PWD/dbusconnection.cpp \
|
||||
$$PWD/atspiadaptor.cpp
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#include "bridge.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QSpiAccessibleBridgePlugin
|
||||
|
||||
\brief QSpiAccessibleBridgePlugin
|
||||
|
||||
QSpiAccessibleBridgePlugin
|
||||
*/
|
||||
|
||||
class QSpiAccessibleBridgePlugin: public QAccessibleBridgePlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QAccessibleBridgeFactoryInterface" FILE "linuxaccessibility.json");
|
||||
public:
|
||||
QSpiAccessibleBridgePlugin(QObject *parent = 0);
|
||||
virtual ~QSpiAccessibleBridgePlugin() {}
|
||||
|
||||
virtual QAccessibleBridge* create(const QString &key);
|
||||
virtual QStringList keys() const;
|
||||
};
|
||||
|
||||
/*!
|
||||
The contructor of the plugin.
|
||||
*/
|
||||
QSpiAccessibleBridgePlugin::QSpiAccessibleBridgePlugin(QObject *parent)
|
||||
: QAccessibleBridgePlugin(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a new instance of the QAccessibleBridge plugin.
|
||||
*/
|
||||
QAccessibleBridge* QSpiAccessibleBridgePlugin::create(const QString &key)
|
||||
{
|
||||
if (key == "QSPIACCESSIBLEBRIDGE")
|
||||
return new QSpiAccessibleBridge();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
*/
|
||||
QStringList QSpiAccessibleBridgePlugin::keys() const
|
||||
{
|
||||
return QStringList() << "QSPIACCESSIBLEBRIDGE";
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "struct_marshallers_p.h"
|
||||
|
||||
#include <atspi/atspi-constants.h>
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtDBus/qdbusmetatype.h>
|
||||
|
||||
#include "bridge_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QSpiObjectReference::QSpiObjectReference()
|
||||
: path(QDBusObjectPath(ATSPI_DBUS_PATH_NULL))
|
||||
{}
|
||||
|
||||
/* QSpiAccessibleCacheArray */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiAccessibleCacheItem &item)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << item.path;
|
||||
argument << item.application;
|
||||
argument << item.parent;
|
||||
argument << item.children;
|
||||
argument << item.supportedInterfaces;
|
||||
argument << item.name;
|
||||
argument << item.role;
|
||||
argument << item.description;
|
||||
argument << item.state;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiAccessibleCacheItem &item)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument >> item.path;
|
||||
argument >> item.application;
|
||||
argument >> item.parent;
|
||||
argument >> item.children;
|
||||
argument >> item.supportedInterfaces;
|
||||
argument >> item.name;
|
||||
argument >> item.role;
|
||||
argument >> item.description;
|
||||
argument >> item.state;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
/* QSpiObjectReference */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiObjectReference &address)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << address.service;
|
||||
argument << address.path;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiObjectReference &address)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument >> address.service;
|
||||
argument >> address.path;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
/* QSpiAction */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiAction &action)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << action.name;
|
||||
argument << action.description;
|
||||
argument << action.keyBinding;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiAction &action)
|
||||
{
|
||||
Q_UNUSED(action)
|
||||
qWarning() << "QDBusArgument &operator>>(const QDBusArgument &argument, QSpiAction &action): implement me!";
|
||||
return argument;
|
||||
}
|
||||
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiEventListener &ev)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument << ev.listenerAddress;
|
||||
argument << ev.eventName;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiEventListener &ev)
|
||||
{
|
||||
argument.beginStructure();
|
||||
argument >> ev.listenerAddress;
|
||||
argument >> ev.eventName;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
/* QSpiAppUpdate */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiAppUpdate &update) {
|
||||
argument.beginStructure();
|
||||
argument << update.type << update.address;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiAppUpdate &update) {
|
||||
argument.beginStructure();
|
||||
argument >> update.type >> update.address;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
/* QSpiRelationArrayEntry */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiRelationArrayEntry &entry) {
|
||||
argument.beginStructure();
|
||||
argument << entry.first << entry.second;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiRelationArrayEntry &entry) {
|
||||
argument.beginStructure();
|
||||
argument >> entry.first >> entry.second;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
/* QSpiDeviceEvent */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiDeviceEvent &event) {
|
||||
argument.beginStructure();
|
||||
argument << event.type
|
||||
<< event.id
|
||||
<< event.hardwareCode
|
||||
<< event.modifiers
|
||||
<< event.timestamp
|
||||
<< event.text
|
||||
<< event.isText;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiDeviceEvent &event) {
|
||||
argument.beginStructure();
|
||||
argument >> event.type
|
||||
>> event.id
|
||||
>> event.hardwareCode
|
||||
>> event.modifiers
|
||||
>> event.timestamp
|
||||
>> event.text
|
||||
>> event.isText;
|
||||
argument.endStructure();
|
||||
return argument;
|
||||
}
|
||||
|
||||
void qSpiInitializeStructTypes()
|
||||
{
|
||||
qDBusRegisterMetaType<QSpiIntList>();
|
||||
qDBusRegisterMetaType<QSpiUIntList>();
|
||||
qDBusRegisterMetaType<QSpiAccessibleCacheItem>();
|
||||
qDBusRegisterMetaType<QSpiAccessibleCacheArray>();
|
||||
qDBusRegisterMetaType<QSpiObjectReference>();
|
||||
qDBusRegisterMetaType<QSpiObjectReferenceArray>();
|
||||
qDBusRegisterMetaType<QSpiAttributeSet>();
|
||||
qDBusRegisterMetaType<QSpiAction>();
|
||||
qDBusRegisterMetaType<QSpiActionArray>();
|
||||
qDBusRegisterMetaType<QSpiEventListener>();
|
||||
qDBusRegisterMetaType<QSpiEventListenerArray>();
|
||||
qDBusRegisterMetaType<QSpiDeviceEvent>();
|
||||
qDBusRegisterMetaType<QSpiAppUpdate>();
|
||||
qDBusRegisterMetaType<QSpiRelationArrayEntry>();
|
||||
qDBusRegisterMetaType<QSpiRelationArray>();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef Q_SPI_STRUCT_MARSHALLERS_H
|
||||
#define Q_SPI_STRUCT_MARSHALLERS_H
|
||||
|
||||
#include <QtCore/qlist.h>
|
||||
#include <QtCore/qpair.h>
|
||||
#include <QtDBus/QDBusArgument>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtDBus/QDBusObjectPath>
|
||||
|
||||
QT_BEGIN_HEADER
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
typedef QList <int> QSpiIntList;
|
||||
typedef QList <uint> QSpiUIntList;
|
||||
|
||||
// FIXME: make this copy on write
|
||||
struct QSpiObjectReference
|
||||
{
|
||||
QString service;
|
||||
QDBusObjectPath path;
|
||||
|
||||
QSpiObjectReference();
|
||||
QSpiObjectReference(const QDBusConnection& connection, const QDBusObjectPath& path)
|
||||
: service(connection.baseService()), path(path) {}
|
||||
};
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiObjectReference &address);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiObjectReference &address);
|
||||
|
||||
typedef QList <QSpiObjectReference> QSpiObjectReferenceArray;
|
||||
|
||||
struct QSpiAccessibleCacheItem
|
||||
{
|
||||
QSpiObjectReference path;
|
||||
QSpiObjectReference application;
|
||||
QSpiObjectReference parent;
|
||||
QList <QSpiObjectReference> children;
|
||||
QStringList supportedInterfaces;
|
||||
QString name;
|
||||
uint role;
|
||||
QString description;
|
||||
QSpiUIntList state;
|
||||
};
|
||||
|
||||
typedef QList <QSpiAccessibleCacheItem> QSpiAccessibleCacheArray;
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiAccessibleCacheItem &item);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiAccessibleCacheItem &item);
|
||||
|
||||
struct QSpiAction
|
||||
{
|
||||
QString name;
|
||||
QString description;
|
||||
QString keyBinding;
|
||||
};
|
||||
|
||||
typedef QList <QSpiAction> QSpiActionArray;
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiAction &action);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiAction &action);
|
||||
|
||||
struct QSpiEventListener
|
||||
{
|
||||
QString listenerAddress;
|
||||
QString eventName;
|
||||
};
|
||||
|
||||
typedef QList <QSpiEventListener> QSpiEventListenerArray;
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiEventListener &action);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiEventListener &action);
|
||||
|
||||
typedef QPair < unsigned int, QList < QSpiObjectReference > > QSpiRelationArrayEntry;
|
||||
typedef QList< QSpiRelationArrayEntry > QSpiRelationArray;
|
||||
|
||||
//a(iisv)
|
||||
struct QSpiTextRange {
|
||||
int startOffset;
|
||||
int endOffset;
|
||||
QString contents;
|
||||
QVariant v;
|
||||
};
|
||||
typedef QList <QSpiTextRange> QSpiTextRangeList;
|
||||
typedef QMap <QString, QString> QSpiAttributeSet;
|
||||
|
||||
enum QSpiAppUpdateType {
|
||||
QSPI_APP_UPDATE_ADDED = 0,
|
||||
QSPI_APP_UPDATE_REMOVED = 1
|
||||
};
|
||||
|
||||
struct QSpiAppUpdate {
|
||||
int type; /* Is an application added or removed */
|
||||
QString address; /* D-Bus address of application added or removed */
|
||||
};
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiAppUpdate &update);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiAppUpdate &update);
|
||||
|
||||
struct QSpiDeviceEvent {
|
||||
unsigned int type;
|
||||
int id;
|
||||
int hardwareCode;
|
||||
int modifiers;
|
||||
int timestamp;
|
||||
QString text;
|
||||
bool isText;
|
||||
};
|
||||
|
||||
QDBusArgument &operator<<(QDBusArgument &argument, const QSpiDeviceEvent &event);
|
||||
const QDBusArgument &operator>>(const QDBusArgument &argument, QSpiDeviceEvent &event);
|
||||
|
||||
void qSpiInitializeStructTypes();
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
Q_DECLARE_METATYPE(QSpiIntList)
|
||||
Q_DECLARE_METATYPE(QSpiUIntList)
|
||||
Q_DECLARE_METATYPE(QSpiObjectReference)
|
||||
Q_DECLARE_METATYPE(QSpiObjectReferenceArray)
|
||||
Q_DECLARE_METATYPE(QSpiAccessibleCacheItem)
|
||||
Q_DECLARE_METATYPE(QSpiAccessibleCacheArray)
|
||||
Q_DECLARE_METATYPE(QSpiAction)
|
||||
Q_DECLARE_METATYPE(QSpiActionArray)
|
||||
Q_DECLARE_METATYPE(QSpiEventListener)
|
||||
Q_DECLARE_METATYPE(QSpiEventListenerArray)
|
||||
Q_DECLARE_METATYPE(QSpiRelationArrayEntry)
|
||||
Q_DECLARE_METATYPE(QSpiRelationArray)
|
||||
Q_DECLARE_METATYPE(QSpiTextRange)
|
||||
Q_DECLARE_METATYPE(QSpiTextRangeList)
|
||||
Q_DECLARE_METATYPE(QSpiAttributeSet)
|
||||
Q_DECLARE_METATYPE(QSpiAppUpdate)
|
||||
Q_DECLARE_METATYPE(QSpiDeviceEvent)
|
||||
|
||||
QT_END_HEADER
|
||||
#endif /* Q_SPI_STRUCT_MARSHALLERS_H */
|
||||
|
|
@ -21,3 +21,4 @@ include(input/input.pri)
|
|||
include(devicediscovery/devicediscovery.pri)
|
||||
include(services/services.pri)
|
||||
include(themes/themes.pri)
|
||||
include(linuxaccessibility/linuxaccessibility.pri)
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@
|
|||
#include <QtGui/QScreen>
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
#include <qpa/qplatformaccessibility.h>
|
||||
#include "../../../platformsupport/linuxaccessibility/bridge_p.h"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -117,7 +118,7 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters)
|
|||
m_fontDatabase.reset(new QGenericUnixFontDatabase());
|
||||
m_inputContext.reset(QPlatformInputContextFactory::create());
|
||||
#ifndef QT_NO_ACCESSIBILITY
|
||||
m_accessibility.reset(new QPlatformAccessibility());
|
||||
m_accessibility.reset(new QSpiAccessibleBridge());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ SUBDIRS=\
|
|||
modeltest \
|
||||
networkselftest \
|
||||
qaccessibility \
|
||||
qaccessibilitylinux \
|
||||
qcomplextext \
|
||||
qfocusevent \
|
||||
qnetworkaccessmanager_and_qprogressdialog \
|
||||
|
|
@ -45,7 +46,9 @@ cross_compile: SUBDIRS -= \
|
|||
atwrapper \
|
||||
compiler
|
||||
|
||||
wince*|!contains(QT_CONFIG, accessibility):SUBDIRS -= qaccessibility
|
||||
wince*|!contains(QT_CONFIG, accessibility): SUBDIRS -= qaccessibility
|
||||
|
||||
!contains(QT_CONFIG, accessibility)|!contains(QT_CONFIG, xcb): SUBDIRS -= qaccessibilitylinux
|
||||
|
||||
!mac: SUBDIRS -= \
|
||||
macgui \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
CONFIG += testcase
|
||||
TARGET = tst_qaccessibilitylinux
|
||||
SOURCES += tst_qaccessibilitylinux.cpp \
|
||||
../../../../src/platformsupport/linuxaccessibility/dbusconnection.cpp \
|
||||
../../../../src/platformsupport/linuxaccessibility/struct_marshallers.cpp
|
||||
|
||||
CONFIG += gui
|
||||
CONFIG += link_pkgconfig
|
||||
|
||||
QT += gui widgets dbus testlib
|
||||
|
||||
PKGCONFIG += atspi-2
|
||||
|
|
@ -0,0 +1,467 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/
|
||||
**
|
||||
** This file is part of the QtGui module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** GNU Lesser General Public License Usage
|
||||
** This file may be used under the terms of the GNU Lesser General Public
|
||||
** License version 2.1 as published by the Free Software Foundation and
|
||||
** appearing in the file LICENSE.LGPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU Lesser
|
||||
** General Public License version 2.1 requirements will be met:
|
||||
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU General
|
||||
** Public License version 3.0 as published by the Free Software Foundation
|
||||
** and appearing in the file LICENSE.GPL included in the packaging of this
|
||||
** file. Please review the following information to ensure the GNU General
|
||||
** Public License version 3.0 requirements will be met:
|
||||
** http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
** Other Usage
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtTest/QtTest>
|
||||
#include <QtGui>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QLineEdit>
|
||||
#include <QtWidgets/QListWidget>
|
||||
#include <QtWidgets/QTreeWidget>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
|
||||
#include <QDBusArgument>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
|
||||
#include <atspi/atspi-constants.h>
|
||||
|
||||
#include "../../../../src/plugins/platforms/linuxaccessibility/dbusconnection.h"
|
||||
#include "../../../../src/plugins/platforms/linuxaccessibility/struct_marshallers.h"
|
||||
|
||||
#define COMPARE3(v1, v2, v3) QCOMPARE(v1, v3); QCOMPARE(v2, v3);
|
||||
|
||||
class AccessibleTestWindow : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AccessibleTestWindow()
|
||||
{
|
||||
DBusConnection c;
|
||||
m_address = c.connection().baseService().toLatin1().data();
|
||||
new QHBoxLayout(this);
|
||||
}
|
||||
QString dbusAddress() const { return m_address; }
|
||||
|
||||
void addWidget(QWidget* widget)
|
||||
{
|
||||
layout()->addWidget(widget);
|
||||
widget->show();
|
||||
QTest::qWaitForWindowShown(widget);
|
||||
}
|
||||
|
||||
void clearChildren()
|
||||
{
|
||||
qDeleteAll(children());
|
||||
new QHBoxLayout(this);
|
||||
}
|
||||
|
||||
private:
|
||||
QString m_address;
|
||||
QString m_bus;
|
||||
};
|
||||
|
||||
|
||||
class tst_QtAtSpi : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
|
||||
void testLabel();
|
||||
void testLineEdit();
|
||||
void testListWidget();
|
||||
void testTreeWidget();
|
||||
void testTextEdit();
|
||||
void testSlider();
|
||||
|
||||
void cleanupTestCase();
|
||||
|
||||
private:
|
||||
void registerDbus();
|
||||
static QString getParent(QDBusInterface *interface);
|
||||
static QStringList getChildren(QDBusInterface *interface);
|
||||
QDBusInterface *getInterface(const QString &path, const QString &interfaceName);
|
||||
|
||||
AccessibleTestWindow *m_window;
|
||||
|
||||
QString bus;
|
||||
QString address;
|
||||
QDBusInterface *root; // the root object on dbus (for the app)
|
||||
QDBusInterface *rootApplication;
|
||||
QDBusInterface *mainWindow;
|
||||
|
||||
DBusConnection dbus;
|
||||
};
|
||||
|
||||
// helper to find children of a dbus object
|
||||
QStringList tst_QtAtSpi::getChildren(QDBusInterface *interface)
|
||||
{
|
||||
QSpiObjectReferenceArray list;
|
||||
interface->call(QDBus::Block, "GetChildren").arguments().first().value<QDBusArgument>() >> list;
|
||||
|
||||
Q_ASSERT(interface->property("ChildCount").toInt() == list.count());
|
||||
|
||||
QStringList children;
|
||||
Q_FOREACH (const QSpiObjectReference &ref, list)
|
||||
children << ref.path.path();
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
QString tst_QtAtSpi::getParent(QDBusInterface *interface)
|
||||
{
|
||||
if (!interface->isValid())
|
||||
return QString();
|
||||
|
||||
QVariant var = interface->property("Parent");
|
||||
if (!var.canConvert<QSpiObjectReference>()) {
|
||||
qWarning() << "Invalid parent";
|
||||
return QString();
|
||||
}
|
||||
QSpiObjectReference parent = var.value<QSpiObjectReference>();
|
||||
return parent.path.path();
|
||||
}
|
||||
|
||||
// helper to get dbus object
|
||||
QDBusInterface *tst_QtAtSpi::getInterface(const QString &path, const QString &interfaceName)
|
||||
{
|
||||
return new QDBusInterface(address, path, interfaceName, dbus.connection(), this);
|
||||
}
|
||||
|
||||
|
||||
void tst_QtAtSpi::initTestCase()
|
||||
{
|
||||
// Oxygen style creates many extra items, it's simply unusable here
|
||||
qDebug() << "Using plastique style...";
|
||||
qApp->setStyle("plastique");
|
||||
qApp->setApplicationName("tst_QtAtSpi app");
|
||||
dbus = DBusConnection();
|
||||
|
||||
m_window = new AccessibleTestWindow();
|
||||
m_window->show();
|
||||
|
||||
// this has the side-effect of immediately activating accessibility
|
||||
qDebug() << "Explicitly activating accessibility...";
|
||||
delete QAccessible::queryAccessibleInterface(m_window);
|
||||
|
||||
QTest::qWaitForWindowShown(m_window);
|
||||
|
||||
address = m_window->dbusAddress();
|
||||
registerDbus();
|
||||
|
||||
QStringList appChildren = getChildren(root);
|
||||
QString window = appChildren.at(0);
|
||||
mainWindow = getInterface(window, "org.a11y.atspi.Accessible");
|
||||
}
|
||||
|
||||
void tst_QtAtSpi::cleanupTestCase()
|
||||
{
|
||||
delete mainWindow;
|
||||
delete rootApplication;
|
||||
delete root;
|
||||
delete m_window;
|
||||
}
|
||||
|
||||
void tst_QtAtSpi::registerDbus()
|
||||
{
|
||||
QVERIFY(dbus.connection().isConnected());
|
||||
|
||||
root = getInterface("/org/a11y/atspi/accessible/root",
|
||||
"org.a11y.atspi.Accessible");
|
||||
|
||||
rootApplication = getInterface("/org/a11y/atspi/accessible/root",
|
||||
"org.a11y.atspi.Application");
|
||||
QVERIFY(root->isValid());
|
||||
QVERIFY(rootApplication->isValid());
|
||||
|
||||
QStringList appChildren = getChildren(root);
|
||||
QString window = appChildren.at(0);
|
||||
mainWindow = getInterface(window, "org.a11y.atspi.Accessible");
|
||||
}
|
||||
|
||||
#define ROOTPATH "/org/a11y/atspi/accessible"
|
||||
|
||||
void tst_QtAtSpi::testLabel()
|
||||
{
|
||||
QLabel *l = new QLabel(m_window);
|
||||
l->setText("Hello A11y");
|
||||
m_window->addWidget(l);
|
||||
|
||||
// Application
|
||||
QCOMPARE(getParent(mainWindow), QLatin1String(ATSPI_DBUS_PATH_ROOT));
|
||||
QStringList children = getChildren(mainWindow);
|
||||
|
||||
QDBusInterface *labelInterface = getInterface(children.at(0), "org.a11y.atspi.Accessible");
|
||||
QVERIFY(labelInterface->isValid());
|
||||
QCOMPARE(labelInterface->property("Name").toString(), QLatin1String("Hello A11y"));
|
||||
QCOMPARE(getChildren(labelInterface).count(), 0);
|
||||
QCOMPARE(labelInterface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("label"));
|
||||
QCOMPARE(labelInterface->call(QDBus::Block, "GetRole").arguments().first().toUInt(), 29u);
|
||||
QCOMPARE(getParent(labelInterface), mainWindow->path());
|
||||
|
||||
l->setText("New text");
|
||||
QCOMPARE(labelInterface->property("Name").toString(), l->text());
|
||||
|
||||
m_window->clearChildren();
|
||||
delete labelInterface;
|
||||
}
|
||||
|
||||
void tst_QtAtSpi::testLineEdit()
|
||||
{
|
||||
QLineEdit *lineEdit = new QLineEdit(m_window);
|
||||
lineEdit->setText("a11y test QLineEdit");
|
||||
m_window->addWidget(lineEdit);
|
||||
|
||||
QStringList children = getChildren(mainWindow);
|
||||
|
||||
QDBusInterface *accessibleInterface = getInterface(children.at(0), "org.a11y.atspi.Accessible");
|
||||
QDBusInterface *editableTextInterface = getInterface(children.at(0), "org.a11y.atspi.EditableText");
|
||||
QDBusInterface *textInterface = getInterface(children.at(0), "org.a11y.atspi.Text");
|
||||
QVERIFY(accessibleInterface->isValid());
|
||||
QVERIFY(editableTextInterface->isValid());
|
||||
QVERIFY(textInterface->isValid());
|
||||
|
||||
QCOMPARE(accessibleInterface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("text"));
|
||||
QCOMPARE(textInterface->call(QDBus::Block,"GetText", 5, -1).arguments().first().toString(), QLatin1String("test QLineEdit"));
|
||||
QString newText = "Text has changed!";
|
||||
editableTextInterface->call(QDBus::Block, "SetTextContents", newText);
|
||||
COMPARE3(lineEdit->text(), textInterface->call(QDBus::Block, "GetText", 0, -1).arguments().first().toString(), newText);
|
||||
QCOMPARE(textInterface->call(QDBus::Block, "GetText", 0, 4).arguments().first().toString(), QLatin1String("Text"));
|
||||
editableTextInterface->call(QDBus::Block, "DeleteText", 4, 8);
|
||||
COMPARE3(lineEdit->text(), "Te" + textInterface->call(QDBus::Block, "GetText", 2, 10).arguments().first().toString() + "ed!", QLatin1String("Text changed!"));
|
||||
editableTextInterface->call(QDBus::Block, "InsertText", 12, " again ", 6);
|
||||
QCOMPARE(lineEdit->text(), QLatin1String("Text changed again!"));
|
||||
COMPARE3(lineEdit->text().length(), textInterface->property("CharacterCount").toInt(), 19);
|
||||
|
||||
textInterface->call(QDBus::Block, "SetCaretOffset", 4);
|
||||
COMPARE3(lineEdit->cursorPosition(), textInterface->property("CaretOffset").toInt(), 4);
|
||||
|
||||
textInterface->call(QDBus::Block, "AddSelection", 1, 4);
|
||||
QList<QVariant> data = textInterface->call(QDBus::Block, "GetSelection", 0).arguments();
|
||||
COMPARE3(data.at(0).toInt(), lineEdit->selectionStart(), 1);
|
||||
QCOMPARE(data.at(1).toInt(), 4);
|
||||
QCOMPARE(lineEdit->selectedText().length(), 3);
|
||||
QCOMPARE(textInterface->call(QDBus::Block, "GetNSelections").arguments().first().toInt(), 1);
|
||||
textInterface->call(QDBus::Block, "SetSelection", 0, 0, 5);
|
||||
data = textInterface->call(QDBus::Block, "GetSelection", 0).arguments();
|
||||
COMPARE3(data.at(0).toInt(), lineEdit->selectionStart(), 0);
|
||||
COMPARE3(data.at(1).toInt(), lineEdit->selectedText().length(), 5);
|
||||
textInterface->call(QDBus::Block, "RemoveSelection", 0);
|
||||
QCOMPARE(lineEdit->selectionStart(), -1);
|
||||
QCOMPARE(textInterface->call(QDBus::Block, "GetNSelections").arguments().first().toInt(), 0);
|
||||
|
||||
m_window->clearChildren();
|
||||
delete accessibleInterface;
|
||||
delete textInterface;
|
||||
delete editableTextInterface;
|
||||
}
|
||||
|
||||
void tst_QtAtSpi::testListWidget()
|
||||
{
|
||||
QListWidget *lw = new QListWidget;
|
||||
lw->addItem("Hello");
|
||||
lw->addItem("Good morning");
|
||||
lw->addItem("Good bye");
|
||||
m_window->addWidget(lw);
|
||||
|
||||
QStringList children = getChildren(mainWindow);
|
||||
QDBusInterface *listIface = getInterface(children.at(0), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(listIface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("list"));
|
||||
QStringList tableChildren = getChildren(listIface);
|
||||
QCOMPARE(tableChildren.size(), 3);
|
||||
|
||||
QDBusInterface *cell1 = getInterface(tableChildren.at(0), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell1->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("list item"));
|
||||
QCOMPARE(cell1->property("Name").toString(), QLatin1String("Hello"));
|
||||
|
||||
QDBusInterface *cell2 = getInterface(tableChildren.at(1), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell2->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("list item"));
|
||||
QCOMPARE(cell2->property("Name").toString(), QLatin1String("Good morning"));
|
||||
|
||||
QDBusInterface *cell3 = getInterface(tableChildren.at(2), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell3->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("list item"));
|
||||
QCOMPARE(cell3->property("Name").toString(), QLatin1String("Good bye"));
|
||||
|
||||
delete cell1; delete cell2; delete cell3;
|
||||
m_window->clearChildren();
|
||||
delete listIface;
|
||||
}
|
||||
|
||||
void tst_QtAtSpi::testTreeWidget()
|
||||
{
|
||||
QTreeWidget *tree = new QTreeWidget;
|
||||
tree->setColumnCount(2);
|
||||
tree->setHeaderLabels(QStringList() << "Header 1" << "Header 2");
|
||||
|
||||
QTreeWidgetItem *top1 = new QTreeWidgetItem(QStringList() << "0.0" << "0.1");
|
||||
tree->addTopLevelItem(top1);
|
||||
|
||||
QTreeWidgetItem *top2 = new QTreeWidgetItem(QStringList() << "1.0" << "1.1");
|
||||
tree->addTopLevelItem(top2);
|
||||
|
||||
QTreeWidgetItem *child1 = new QTreeWidgetItem(QStringList() << "1.0 0.0" << "1.0 0.1");
|
||||
top2->addChild(child1);
|
||||
|
||||
m_window->addWidget(tree);
|
||||
|
||||
QStringList children = getChildren(mainWindow);
|
||||
QDBusInterface *treeIface = getInterface(children.at(0), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(treeIface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("tree"));
|
||||
QStringList tableChildren = getChildren(treeIface);
|
||||
|
||||
QCOMPARE(tableChildren.size(), 6);
|
||||
|
||||
QDBusInterface *cell1 = getInterface(tableChildren.at(0), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell1->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("column header"));
|
||||
QCOMPARE(cell1->property("Name").toString(), QLatin1String("Header 1"));
|
||||
|
||||
QDBusInterface *cell2 = getInterface(tableChildren.at(1), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell2->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("column header"));
|
||||
QCOMPARE(cell2->property("Name").toString(), QLatin1String("Header 2"));
|
||||
|
||||
QDBusInterface *cell3 = getInterface(tableChildren.at(2), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell3->property("Name").toString(), QLatin1String("0.0"));
|
||||
|
||||
QDBusInterface *cell4 = getInterface(tableChildren.at(3), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell4->property("Name").toString(), QLatin1String("0.1"));
|
||||
|
||||
tree->expandItem(top2);
|
||||
tableChildren = getChildren(treeIface);
|
||||
QCOMPARE(tableChildren.size(), 8);
|
||||
|
||||
QDBusInterface *cell5 = getInterface(tableChildren.at(6), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell5->property("Name").toString(), QLatin1String("1.0 0.0"));
|
||||
|
||||
QDBusInterface *cell6 = getInterface(tableChildren.at(7), "org.a11y.atspi.Accessible");
|
||||
QCOMPARE(cell6->property("Name").toString(), QLatin1String("1.0 0.1"));
|
||||
|
||||
|
||||
QDBusInterface *treeTableIface = getInterface(children.at(0), "org.a11y.atspi.Table");
|
||||
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetRowAtIndex", 0).arguments().first().toInt(), -1);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetRowAtIndex", 1).arguments().first().toInt(), -1);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetRowAtIndex", 2).arguments().first().toInt(), 0);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetRowAtIndex", 3).arguments().first().toInt(), 0);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetRowAtIndex", 4).arguments().first().toInt(), 1);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetRowAtIndex", 5).arguments().first().toInt(), 1);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetRowAtIndex", 6).arguments().first().toInt(), 2);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetRowAtIndex", 7).arguments().first().toInt(), 2);
|
||||
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetColumnAtIndex", 0).arguments().first().toInt(), 0);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetColumnAtIndex", 1).arguments().first().toInt(), 1);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetColumnAtIndex", 2).arguments().first().toInt(), 0);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetColumnAtIndex", 3).arguments().first().toInt(), 1);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetColumnAtIndex", 4).arguments().first().toInt(), 0);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetColumnAtIndex", 5).arguments().first().toInt(), 1);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetColumnAtIndex", 6).arguments().first().toInt(), 0);
|
||||
QCOMPARE(treeTableIface->call(QDBus::Block, "GetColumnAtIndex", 7).arguments().first().toInt(), 1);
|
||||
|
||||
delete treeTableIface;
|
||||
delete cell1; delete cell2; delete cell3; delete cell4; delete cell5; delete cell6;
|
||||
m_window->clearChildren();
|
||||
delete treeIface;
|
||||
}
|
||||
|
||||
void tst_QtAtSpi::testTextEdit()
|
||||
{
|
||||
QTextEdit *textEdit = new QTextEdit(m_window);
|
||||
textEdit->setText("<html><head></head><body>This is a <b>sample</b> text.<br />"
|
||||
"How are you today</body></html>");
|
||||
textEdit->show();
|
||||
m_window->addWidget(textEdit);
|
||||
|
||||
QStringList children = getChildren(mainWindow);
|
||||
QDBusInterface *accessibleInterface = getInterface(children.at(0), "org.a11y.atspi.Accessible");
|
||||
QDBusInterface *editableTextInterface = getInterface(children.at(0), "org.a11y.atspi.EditableText");
|
||||
QDBusInterface *textInterface = getInterface(children.at(0), "org.a11y.atspi.Text");
|
||||
QVERIFY(accessibleInterface->isValid());
|
||||
QVERIFY(editableTextInterface->isValid());
|
||||
QVERIFY(textInterface->isValid());
|
||||
|
||||
QList<QVariant> callResult;
|
||||
|
||||
QDBusMessage msg = textInterface->call(QDBus::Block, "GetText", 0, 5);
|
||||
callResult = msg.arguments();
|
||||
QCOMPARE(callResult.at(0).toString(), QLatin1String("This "));
|
||||
|
||||
msg = textInterface->call(QDBus::Block, "GetTextAtOffset", 12, (uint) ATSPI_TEXT_BOUNDARY_WORD_START);
|
||||
callResult = msg.arguments();
|
||||
|
||||
QEXPECT_FAIL("", "Word should contain space at end according to atspi.", Continue);
|
||||
QCOMPARE(callResult.at(0).toString(), QLatin1String("sample "));
|
||||
QCOMPARE(callResult.at(1).toInt(), 10);
|
||||
QEXPECT_FAIL("", "Due to missing space the count is off by one.", Continue);
|
||||
QCOMPARE(callResult.at(2).toInt(), 17);
|
||||
|
||||
// Check if at least CharacterExtents and RangeExtents give a consistent result
|
||||
QDBusReply<QRect> replyRect20 = textInterface->call(QDBus::Block, "GetCharacterExtents", 20, ATSPI_COORD_TYPE_SCREEN);
|
||||
QVERIFY(replyRect20.isValid());
|
||||
QRect r1 = replyRect20.value();
|
||||
QDBusReply<QRect> replyRect21 = textInterface->call(QDBus::Block, "GetCharacterExtents", 21, ATSPI_COORD_TYPE_SCREEN);
|
||||
QRect r2 = replyRect21.value();
|
||||
QDBusReply<QRect> reply = textInterface->call(QDBus::Block, "GetRangeExtents", 20, 21, ATSPI_COORD_TYPE_SCREEN);
|
||||
QRect rect = reply.value();
|
||||
QCOMPARE(rect, r1|r2);
|
||||
|
||||
m_window->clearChildren();
|
||||
delete textInterface;
|
||||
}
|
||||
|
||||
void tst_QtAtSpi::testSlider()
|
||||
{
|
||||
QSlider *slider = new QSlider(m_window);
|
||||
slider->setMinimum(2);
|
||||
slider->setMaximum(5);
|
||||
slider->setValue(3);
|
||||
m_window->addWidget(slider);
|
||||
|
||||
QStringList children = getChildren(mainWindow);
|
||||
|
||||
QDBusInterface *accessibleInterface = getInterface(children.at(0), "org.a11y.atspi.Accessible");
|
||||
QDBusInterface *valueInterface = getInterface(children.at(0), "org.a11y.atspi.Value");
|
||||
QVERIFY(accessibleInterface->isValid());
|
||||
QVERIFY(valueInterface->isValid());
|
||||
|
||||
QCOMPARE(valueInterface->property("CurrentValue").toInt(), 3);
|
||||
QCOMPARE(valueInterface->property("MinimumValue").toInt(), 2);
|
||||
QCOMPARE(valueInterface->property("MaximumValue").toInt(), 5);
|
||||
|
||||
valueInterface->setProperty("CurrentValue", 4);
|
||||
QCOMPARE(valueInterface->property("CurrentValue").toInt(), 4);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QtAtSpi)
|
||||
#include "tst_qaccessibilitylinux.moc"
|
||||
|
||||
Loading…
Reference in New Issue