summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-03-25 18:07:17 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-04-19 17:52:45 +0200
commit0d57da067b47eac51ea725d267069d6e616cf586 (patch)
tree2af737bd8e8ea2063a485e9f66471a457d5eab3f
parentc2059ac80db30d0322f53bf0c224263a934c49bc (diff)
Let platform plugin decide if accessibility is active
Change-Id: I881a8ff3fedf3db73ee37046a4363c70960a92a6 Reviewed-by: Jan Arve Sæther <jan-arve.saether@digia.com>
-rw-r--r--src/3rdparty/atspi2/atspi2.pri2
-rw-r--r--src/3rdparty/atspi2/xml/Bus.xml17
-rw-r--r--src/gui/accessible/qaccessible.cpp21
-rw-r--r--src/gui/accessible/qplatformaccessibility.cpp1
-rw-r--r--src/gui/accessible/qplatformaccessibility.h5
-rw-r--r--src/platformsupport/linuxaccessibility/bridge.cpp8
-rw-r--r--src/platformsupport/linuxaccessibility/bridge_p.h1
-rw-r--r--src/platformsupport/linuxaccessibility/dbusconnection.cpp51
-rw-r--r--src/platformsupport/linuxaccessibility/dbusconnection_p.h2
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h1
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm5
-rw-r--r--src/plugins/platforms/cocoa/qnsviewaccessibility.mm19
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp4
-rw-r--r--tests/auto/other/qaccessibility/qaccessibility.pro2
-rw-r--r--tests/auto/other/qaccessibility/tst_qaccessibility.cpp5
-rw-r--r--tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp8
16 files changed, 94 insertions, 58 deletions
diff --git a/src/3rdparty/atspi2/atspi2.pri b/src/3rdparty/atspi2/atspi2.pri
index 1b2ac51b85..5a6dc6d839 100644
--- a/src/3rdparty/atspi2/atspi2.pri
+++ b/src/3rdparty/atspi2/atspi2.pri
@@ -2,7 +2,7 @@
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
+DBUS_INTERFACES = $$PWD/xml/Socket.xml $$PWD/xml/Bus.xml
QDBUSXML2CPP_INTERFACE_HEADER_FLAGS = -i struct_marshallers_p.h
INCLUDEPATH += $$PWD
diff --git a/src/3rdparty/atspi2/xml/Bus.xml b/src/3rdparty/atspi2/xml/Bus.xml
new file mode 100644
index 0000000000..5a33e335a1
--- /dev/null
+++ b/src/3rdparty/atspi2/xml/Bus.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.a11y.Status">
+ <property type="b" name="IsEnabled" access="readwrite">
+ </property>
+ <property type="b" name="ScreenReaderEnabled" access="readwrite">
+ </property>
+ </interface>
+ <interface name="org.a11y.Bus">
+ <method name="GetAddress">
+ <arg type="s" name="address" direction="out">
+ </arg>
+ </method>
+ </interface>
+</node>
+
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 4fd595ed5a..18157f8e2f 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -441,7 +441,6 @@ Q_GLOBAL_STATIC(QAccessiblePluginsHash, qAccessiblePlugins);
QAccessible::UpdateHandler QAccessible::updateHandler = 0;
QAccessible::RootObjectHandler QAccessible::rootObjectHandler = 0;
-static bool accessibility_active = false;
static bool cleanupAdded = false;
#ifndef QT_NO_ACCESSIBILITY
@@ -584,7 +583,6 @@ Q_GLOBAL_STATIC(QAccessibleCache, qAccessibleCache)
*/
QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
{
- accessibility_active = true;
if (!object)
return 0;
@@ -699,19 +697,26 @@ QAccessibleInterface *QAccessible::accessibleInterface(Id id)
/*!
- Returns true if an accessibility implementation has been requested
- during the runtime of the application; otherwise returns false.
+ Returns true if the platform requested accessibility information.
- Use this function to prevent potentially expensive notifications via
- updateAccessibility().
+ This function will return false until a tool such as a screen reader
+ accessed the accessibility framework. It is still possible to use
+ \l QAccessible::queryAccessibleInterface even if accessibility is not
+ active. But there will be no notifications sent to the platform.
+
+ It is recommended to use this function to prevent expensive notifications
+ via updateAccessibility() when they are not needed.
*/
bool QAccessible::isActive()
{
- return accessibility_active;
+#ifndef QT_NO_ACCESSIBILITY
+ if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
+ return pfAccessibility->isActive();
+#endif
+ return false;
}
-
/*!
Sets the root object of the accessible objects of this application
to \a object. All other accessible objects are reachable using object
diff --git a/src/gui/accessible/qplatformaccessibility.cpp b/src/gui/accessible/qplatformaccessibility.cpp
index 2e36e5ac71..490fb7a407 100644
--- a/src/gui/accessible/qplatformaccessibility.cpp
+++ b/src/gui/accessible/qplatformaccessibility.cpp
@@ -73,6 +73,7 @@ Q_GLOBAL_STATIC(QVector<QAccessibleBridge *>, bridges)
\sa QAccessible
*/
QPlatformAccessibility::QPlatformAccessibility()
+ : m_active(false)
{
}
diff --git a/src/gui/accessible/qplatformaccessibility.h b/src/gui/accessible/qplatformaccessibility.h
index 26a22e492d..f86a9b6157 100644
--- a/src/gui/accessible/qplatformaccessibility.h
+++ b/src/gui/accessible/qplatformaccessibility.h
@@ -69,6 +69,11 @@ public:
virtual void initialize();
virtual void cleanup();
+ inline bool isActive() const { return m_active; }
+ inline void setActive(bool active) { m_active = active; }
+
+private:
+ bool m_active;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/linuxaccessibility/bridge.cpp b/src/platformsupport/linuxaccessibility/bridge.cpp
index 181feeba6a..350c67f1ed 100644
--- a/src/platformsupport/linuxaccessibility/bridge.cpp
+++ b/src/platformsupport/linuxaccessibility/bridge.cpp
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
*/
QSpiAccessibleBridge::QSpiAccessibleBridge()
- : cache(0), dec(0), dbusAdaptor(0), m_enabled(false)
+ : cache(0), dec(0), dbusAdaptor(0)
{
dbusConnection = new DBusConnection();
connect(dbusConnection, SIGNAL(enabledChanged(bool)), this, SLOT(enabledChanged(bool)));
@@ -70,7 +70,7 @@ QSpiAccessibleBridge::QSpiAccessibleBridge()
void QSpiAccessibleBridge::enabledChanged(bool enabled)
{
- m_enabled = enabled;
+ setActive(enabled);
updateStatus();
}
@@ -87,7 +87,7 @@ QDBusConnection QSpiAccessibleBridge::dBusConnection() const
void QSpiAccessibleBridge::updateStatus()
{
// create the adaptor to handle everything if we are in enabled state
- if (!dbusAdaptor && m_enabled) {
+ if (!dbusAdaptor && isActive()) {
qSpiInitializeStructTypes();
initializeConstantMappings();
@@ -106,7 +106,7 @@ void QSpiAccessibleBridge::notifyAccessibilityUpdate(QAccessibleEvent *event)
{
if (!dbusAdaptor)
return;
- if (m_enabled)
+ if (isActive())
dbusAdaptor->notify(event);
}
diff --git a/src/platformsupport/linuxaccessibility/bridge_p.h b/src/platformsupport/linuxaccessibility/bridge_p.h
index 8a02847d3d..0e1624c522 100644
--- a/src/platformsupport/linuxaccessibility/bridge_p.h
+++ b/src/platformsupport/linuxaccessibility/bridge_p.h
@@ -76,7 +76,6 @@ private:
DeviceEventControllerAdaptor *dec;
AtSpiAdaptor *dbusAdaptor;
DBusConnection* dbusConnection;
- bool m_enabled;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/src/platformsupport/linuxaccessibility/dbusconnection.cpp
index a37b99c105..18915f8e08 100644
--- a/src/platformsupport/linuxaccessibility/dbusconnection.cpp
+++ b/src/platformsupport/linuxaccessibility/dbusconnection.cpp
@@ -48,6 +48,7 @@
#include <qdebug.h>
#include <QDBusConnectionInterface>
+#include "bus_interface.h"
QT_BEGIN_NAMESPACE
@@ -81,21 +82,24 @@ void DBusConnection::serviceRegistered()
{
// listen to enabled changes
QDBusConnection c = QDBusConnection::sessionBus();
- // FXIME check for changes of enabled state
-// if (!c.connect(A11Y_SERVICE, A11Y_PATH, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged"), this, SLOT(enabledStateChanged(QDBusVariant))))
-// qWarning() << "Could not listen to accessibility enabled state changes.";
-
- // check if it's enabled right away
- QDBusMessage enabledMessage = QDBusMessage::createMethodCall(A11Y_SERVICE, A11Y_PATH, QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("Get"));
- QList<QVariant> args;
- args << QStringLiteral("org.a11y.Status") << QStringLiteral("IsEnabled");
- enabledMessage.setArguments(args);
- c.callWithCallback(enabledMessage, this, SLOT(enabledStateCallback(QDBusVariant)), SLOT(dbusError(QDBusError)));
-}
+ OrgA11yStatusInterface *a11yStatus = new OrgA11yStatusInterface(A11Y_SERVICE, A11Y_PATH, c, this);
+
+ // a11yStatus->isEnabled() returns always true (since Gnome 3.6)
+ bool enabled = a11yStatus->screenReaderEnabled();
+ if (enabled != m_enabled) {
+ m_enabled = enabled;
+ if (m_a11yConnection.isConnected()) {
+ emit enabledChanged(m_enabled);
+ } else {
+ QDBusConnection c = QDBusConnection::sessionBus();
+ QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String("org.a11y.Bus"),
+ QLatin1String("/org/a11y/bus"),
+ QLatin1String("org.a11y.Bus"), QLatin1String("GetAddress"));
+ c.callWithCallback(m, this, SLOT(connectA11yBus(QString)), SLOT(dbusError(QDBusError)));
+ }
+ }
-void DBusConnection::dbusError(const QDBusError &error)
-{
- qWarning() << "Accessibility encountered a DBus error:" << error;
+ // connect(a11yStatus, ); QtDbus doesn't support notifications for property changes yet
}
void DBusConnection::serviceUnregistered()
@@ -103,20 +107,6 @@ void DBusConnection::serviceUnregistered()
emit enabledChanged(false);
}
-void DBusConnection::enabledStateCallback(const QDBusVariant &enabled)
-{
- m_enabled = enabled.variant().toBool();
- if (m_a11yConnection.isConnected()) {
- emit enabledChanged(m_enabled);
- } else {
- QDBusConnection c = QDBusConnection::sessionBus();
- QDBusMessage m = QDBusMessage::createMethodCall(QLatin1String("org.a11y.Bus"),
- QLatin1String("/org/a11y/bus"),
- QLatin1String("org.a11y.Bus"), QLatin1String("GetAddress"));
- c.callWithCallback(m, this, SLOT(connectA11yBus(QString)), SLOT(dbusError(QDBusError)));
- }
-}
-
void DBusConnection::connectA11yBus(const QString &address)
{
if (address.isEmpty()) {
@@ -129,6 +119,11 @@ void DBusConnection::connectA11yBus(const QString &address)
emit enabledChanged(true);
}
+void DBusConnection::dbusError(const QDBusError &error)
+{
+ qWarning() << "Accessibility encountered a DBus error:" << error;
+}
+
/*!
Returns the DBus connection that got established.
Or an invalid connection if not yet connected.
diff --git a/src/platformsupport/linuxaccessibility/dbusconnection_p.h b/src/platformsupport/linuxaccessibility/dbusconnection_p.h
index 2d55ccb547..70f6fb80ac 100644
--- a/src/platformsupport/linuxaccessibility/dbusconnection_p.h
+++ b/src/platformsupport/linuxaccessibility/dbusconnection_p.h
@@ -67,8 +67,6 @@ Q_SIGNALS:
private Q_SLOTS:
void serviceRegistered();
void serviceUnregistered();
- void enabledStateCallback(const QDBusVariant &enabled);
-// void enabledStateChanged(const QDBusVariant &);
void connectA11yBus(const QString &address);
void dbusError(const QDBusError &error);
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index e7ea3d8f8d..68145ec914 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -63,7 +63,6 @@ QT_END_NAMESPACE
QWindow *m_window;
QCocoaWindow *m_platformWindow;
Qt::MouseButtons m_buttons;
- QAccessibleInterface *m_accessibleRoot;
QString m_composingText;
bool m_sendKeyEvent;
QStringList *currentCustomDragTypes;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 568cc4bebf..52e2d781ee 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -121,7 +121,6 @@ static QTouchDevice *touchDevice = 0;
m_window = window;
m_platformWindow = platformWindow;
- m_accessibleRoot = 0;
m_sendKeyEvent = false;
#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
@@ -130,15 +129,13 @@ static QTouchDevice *touchDevice = 0;
static bool skipAccessibilityForInspectorWindows = false;
if (!skipAccessibilityForInspectorWindows) {
- m_accessibleRoot = window->accessibleRoot();
+ // m_accessibleRoot = window->accessibleRoot();
AccessibilityInspector *inspector = new AccessibilityInspector(window);
skipAccessibilityForInspectorWindows = true;
inspector->inspectWindow(window);
skipAccessibilityForInspectorWindows = false;
}
-#else
- m_accessibleRoot = window->accessibleRoot();
#endif
[self registerDragTypes];
diff --git a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
index e3b8cf6532..c43c0b5068 100644
--- a/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qnsviewaccessibility.mm
@@ -45,6 +45,7 @@
#include "qcocoahelpers.h"
#include "qcocoaaccessibility.h"
#include "qcocoaaccessibilityelement.h"
+#include <qpa/qplatformintegration.h>
#include <QtGui/private/qaccessible2_p.h>
#include <QtCore/QDebug>
@@ -60,22 +61,26 @@
}
- (id)accessibilityAttributeValue:(NSString *)attribute {
+
+ // activate accessibility updates
+ QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
+
if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
- if (m_accessibleRoot)
- return QCocoaAccessible::macRole(m_accessibleRoot);
+ if (m_window->accessibleRoot())
+ return QCocoaAccessible::macRole(m_window->accessibleRoot());
return NSAccessibilityUnknownRole;
} else if ([attribute isEqualToString:NSAccessibilityRoleDescriptionAttribute]) {
return NSAccessibilityRoleDescriptionForUIElement(self);
} else if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
- if (!m_accessibleRoot)
+ if (!m_window->accessibleRoot())
return [super accessibilityAttributeValue:attribute];
// Create QCocoaAccessibleElements for each child if the
// root accessible interface.
- int numKids = m_accessibleRoot->childCount();
+ int numKids = m_window->accessibleRoot()->childCount();
NSMutableArray *kids = [NSMutableArray arrayWithCapacity:numKids];
for (int i = 0; i < numKids; ++i) {
- QAccessibleInterface *child = m_accessibleRoot->child(i);
+ QAccessibleInterface *child = m_window->accessibleRoot()->child(i);
Q_ASSERT(child);
QAccessible::Id childAxid = QAccessible::uniqueId(child);
QCocoaAccessibleElement *element = [QCocoaAccessibleElement createElementWithId:childAxid parent:self];
@@ -90,10 +95,10 @@
}
- (id)accessibilityHitTest:(NSPoint)point {
- if (!m_accessibleRoot)
+ if (!m_window->accessibleRoot())
return [super accessibilityHitTest:point];
- QAccessibleInterface *childInterface = m_accessibleRoot->childAt(point.x, qt_mac_flipYCoordinate(point.y));
+ QAccessibleInterface *childInterface = m_window->accessibleRoot()->childAt(point.x, qt_mac_flipYCoordinate(point.y));
// No child found, meaning we hit the NSView
if (!childInterface) {
return [super accessibilityHitTest:point];
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
index f222deeeac..63b4370dc2 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
@@ -52,7 +52,9 @@
#include <QtCore/qsettings.h>
#include <QtGui/qaccessible.h>
#include <QtGui/private/qaccessible2_p.h>
+#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformintegration.h>
#include <QtGui/qwindow.h>
#include <QtGui/qguiapplication.h>
@@ -245,6 +247,8 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W
if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) {
/* For UI Automation */
} else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) {
+ // Start handling accessibility internally
+ QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true);
#if 1
// Ignoring all requests while starting up
// ### Maybe QPA takes care of this???
diff --git a/tests/auto/other/qaccessibility/qaccessibility.pro b/tests/auto/other/qaccessibility/qaccessibility.pro
index 071b0bb66c..70f6633195 100644
--- a/tests/auto/other/qaccessibility/qaccessibility.pro
+++ b/tests/auto/other/qaccessibility/qaccessibility.pro
@@ -1,7 +1,7 @@
CONFIG += testcase
TARGET = tst_qaccessibility
requires(contains(QT_CONFIG,accessibility))
-QT += testlib gui-private widgets-private
+QT += testlib core-private gui-private widgets-private
SOURCES += tst_qaccessibility.cpp
unix:!mac:LIBS+=-lm
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
index 4e0b3298fc..af8e4472ed 100644
--- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
+++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp
@@ -63,6 +63,9 @@
#include <QtWidgets/private/qaccessiblewidget_p.h>
#include <math.h>
#include <qpa/qplatformnativeinterface.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformaccessibility.h>
+#include <QtGui/private/qguiapplication_p.h>
#if defined(Q_OS_WIN) && defined(interface)
# undef interface
@@ -311,6 +314,8 @@ void tst_QAccessibility::onClicked()
void tst_QAccessibility::initTestCase()
{
QTestAccessibility::initialize();
+ QPlatformIntegration *pfIntegration = QGuiApplicationPrivate::platformIntegration();
+ pfIntegration->accessibility()->setActive(true);
}
void tst_QAccessibility::cleanupTestCase()
diff --git a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
index 15b8089525..79fd29f2a1 100644
--- a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
+++ b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp
@@ -55,6 +55,7 @@
#include <QDBusReply>
#include "atspi/atspi-constants.h"
+#include "bus_interface.h"
#include "dbusconnection_p.h"
#include "struct_marshallers_p.h"
@@ -154,16 +155,21 @@ QDBusInterface *tst_QAccessibilityLinux::getInterface(const QString &path, const
return new QDBusInterface(address, path, interfaceName, dbus.connection(), this);
}
-
void tst_QAccessibilityLinux::initTestCase()
{
// Oxygen style creates many extra items, it's simply unusable here
qApp->setStyle("fusion");
qApp->setApplicationName("tst_QAccessibilityLinux app");
+ // Pretend we are a screen reader
+ QDBusConnection c = QDBusConnection::sessionBus();
+ OrgA11yStatusInterface *a11yStatus = new OrgA11yStatusInterface(QStringLiteral("org.a11y.Bus"), QStringLiteral("/org/a11y/bus"), c, this);
+ a11yStatus->setScreenReaderEnabled(true);
+
QTRY_VERIFY(dbus.isEnabled());
QTRY_VERIFY(dbus.connection().isConnected());
address = dbus.connection().baseService().toLatin1().data();
+ QVERIFY(!address.isEmpty());
m_window = new AccessibleTestWindow();
m_window->show();