summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@nokia.com>2012-01-11 16:31:35 +0100
committerQt by Nokia <qt-info@nokia.com>2012-01-31 12:02:33 +0100
commitbf9bdf5328172db65aafaee74d8fb9cbeaa9cc16 (patch)
tree666ab14504b421d34f269b8ffd7a4f7210bbd133
parentcf52c268b036d808901313acc554587465bdd746 (diff)
Use events for accessibility updates.
The problem with the old updates is that it was impossible to send details about the update. For the Linux implementation to work properly with AT-SPI I need to know which state changed (currently I only get a generic "state changed" event) or which part of the text was changed for long texts (imagine a word processor sending updates). This also gives us more options when updating with events generated from not QObject based objects. Change-Id: If0b6c83c523092565eb48e79f3f6de5a1b905ea8 Reviewed-by: Jan-Arve Sæther <jan-arve.saether@nokia.com>
-rw-r--r--src/gui/accessible/qaccessible.cpp70
-rw-r--r--src/gui/accessible/qaccessible.h28
-rw-r--r--src/gui/accessible/qaccessiblebridge.h3
-rw-r--r--src/gui/accessible/qplatformaccessibility_qpa.cpp24
-rw-r--r--src/gui/accessible/qplatformaccessibility_qpa.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsaccessibility.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowsaccessibility.h4
-rw-r--r--src/testlib/qtestaccessible.h4
8 files changed, 104 insertions, 45 deletions
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index b9f80c3071..8610ef726d 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -654,13 +654,29 @@ void QAccessible::setRootObject(QObject *object)
}
/*!
- Notifies accessibility clients about a change in \a object's
- accessibility information.
+ \deprecated
- \a reason specifies the cause of the change, for example,
- \c ValueChange when the position of a slider has been changed. \a
- child is the (1-based) index of the child element that has changed.
- When \a child is 0, the object itself has changed.
+ Use the version with a single \l QAccessibleEvent paremeter instead.
+*/
+void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
+{
+ Q_ASSERT(object);
+
+ qWarning("QAccessible::updateAccessibility is deprecated.");
+
+ QAccessibleEvent event = QAccessibleEvent(reason, object, child);
+ updateAccessibility(event);
+}
+
+/*!
+ Notifies about a change that might be relevant for accessibility clients.
+
+ \a event gives the details about the change.
+ This includes the source of the change and what the actual change is.
+ There should be sufficient details delivered with this event to give meaningful notifications.
+
+ For example, the type \c ValueChange indicates that the position of
+ a slider has been changed.
Call this function whenever the state of your accessible object or
one of its sub-elements has been changed either programmatically
@@ -671,12 +687,10 @@ void QAccessible::setRootObject(QObject *object)
the parameters of the call is expensive you can test isActive() to
avoid unnecessary computations.
*/
-void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
+void QAccessible::updateAccessibility(const QAccessibleEvent &event)
{
- Q_ASSERT(object);
-
if (updateHandler) {
- updateHandler(object, child, reason);
+ updateHandler(event);
return;
}
@@ -684,9 +698,43 @@ void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
return;
if (QPlatformAccessibility *pfAccessibility = platformAccessibility())
- pfAccessibility->notifyAccessibilityUpdate(object, child, reason);
+ pfAccessibility->notifyAccessibilityUpdate(event);
}
+/*!
+ \class QAccessibleEvent
+ \brief The QAccessibleEvent is use to notify about changes that are
+ relevant for accessibility in the application.
+
+ \ingroup accessibility
+ \inmodule QtGui
+
+ This class should be created on the stack and used as parameter for
+ \l QAccessible::updateAccessibility().
+*/
+
+/*!
+ Returns the QAccessibleInterface associated with the event.
+
+ The caller of this function takes ownership of the returned interface.
+*/
+QAccessibleInterface *QAccessibleEvent::accessibleInterface() const
+{
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(m_object);
+ if (!iface)
+ return 0;
+
+ if (m_child >= 0) {
+ QAccessibleInterface *child = iface->child(m_child);
+ if (child) {
+ delete iface;
+ iface = child;
+ } else {
+ qWarning() << "Cannot creat accessible child interface for object: " << m_object << " index: " << m_child;
+ }
+ }
+ return iface;
+}
/*!
\class QAccessibleInterface
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 6726172cac..dc74ac1814 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
class QAccessibleInterface;
+class QAccessibleEvent;
class QWindow;
// We need to inherit QObject to expose the enums to QML.
@@ -326,7 +327,7 @@ public:
};
typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*);
- typedef void(*UpdateHandler)(QObject*, int who, Event reason);
+ typedef void(*UpdateHandler)(const QAccessibleEvent &event);
typedef void(*RootObjectHandler)(QObject*);
static void installFactory(InterfaceFactory);
@@ -335,7 +336,10 @@ public:
static RootObjectHandler installRootObjectHandler(RootObjectHandler);
static QAccessibleInterface *queryAccessibleInterface(QObject *);
+
static void updateAccessibility(QObject *object, int child, Event reason);
+ static void updateAccessibility(const QAccessibleEvent &event);
+
static bool isActive();
static void setRootObject(QObject *object);
@@ -425,6 +429,28 @@ public:
private:
};
+class Q_GUI_EXPORT QAccessibleEvent
+{
+public:
+ inline QAccessibleEvent(QAccessible::Event type, QObject *object, int child = -1)
+ : m_type(type), m_object(object), m_child(child)
+ {
+ Q_ASSERT(object);
+ }
+
+ QAccessible::Event type() const { return m_type; }
+ QObject *object() const { return m_object; }
+ int child() const { return m_child; }
+
+ QAccessibleInterface *accessibleInterface() const;
+
+private:
+ QAccessible::Event m_type;
+ QObject *m_object;
+ int m_child;
+};
+
+
#define QAccessibleInterface_iid "org.qt-project.Qt.QAccessibleInterface"
Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)
diff --git a/src/gui/accessible/qaccessiblebridge.h b/src/gui/accessible/qaccessiblebridge.h
index 3880f6291f..147bf30bd0 100644
--- a/src/gui/accessible/qaccessiblebridge.h
+++ b/src/gui/accessible/qaccessiblebridge.h
@@ -53,13 +53,14 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
class QAccessibleInterface;
+class QAccessibleEvent;
class QAccessibleBridge
{
public:
virtual ~QAccessibleBridge() {}
virtual void setRootObject(QAccessibleInterface *) = 0;
- virtual void notifyAccessibilityUpdate(int, QAccessibleInterface*, int) = 0;
+ virtual void notifyAccessibilityUpdate(const QAccessibleEvent &event) = 0;
};
struct Q_GUI_EXPORT QAccessibleBridgeFactoryInterface : public QFactoryInterface
diff --git a/src/gui/accessible/qplatformaccessibility_qpa.cpp b/src/gui/accessible/qplatformaccessibility_qpa.cpp
index bebef5cde5..9de11e7c1f 100644
--- a/src/gui/accessible/qplatformaccessibility_qpa.cpp
+++ b/src/gui/accessible/qplatformaccessibility_qpa.cpp
@@ -45,6 +45,8 @@
#include "qaccessiblebridge.h"
#include <QtGui/QGuiApplication>
+#include <QDebug>
+
QT_BEGIN_NAMESPACE
/* accessiblebridge plugin discovery stuff */
@@ -73,33 +75,15 @@ QPlatformAccessibility::~QPlatformAccessibility()
{
}
-void QPlatformAccessibility::notifyAccessibilityUpdate(QObject *o,
- int who,
- QAccessible::Event reason)
+void QPlatformAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &event)
{
initialize();
if (!bridges() || bridges()->isEmpty())
return;
- QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(o);
- if (!iface)
- return;
-
- // updates for List/Table/Tree should send child
- if (who) {
- QAccessibleInterface *child = iface->child(who - 1);
- if (child) {
- delete iface;
- iface = child;
- who = 0;
- }
- }
-
for (int i = 0; i < bridges()->count(); ++i)
- bridges()->at(i)->notifyAccessibilityUpdate(reason, iface, who);
- delete iface;
-
+ bridges()->at(i)->notifyAccessibilityUpdate(event);
}
void QPlatformAccessibility::setRootObject(QObject *o)
diff --git a/src/gui/accessible/qplatformaccessibility_qpa.h b/src/gui/accessible/qplatformaccessibility_qpa.h
index 22bb6651b1..364f87b0c9 100644
--- a/src/gui/accessible/qplatformaccessibility_qpa.h
+++ b/src/gui/accessible/qplatformaccessibility_qpa.h
@@ -57,7 +57,7 @@ public:
QPlatformAccessibility();
virtual ~QPlatformAccessibility();
- virtual void notifyAccessibilityUpdate(QObject *o, int who, QAccessible::Event reason);
+ virtual void notifyAccessibilityUpdate(const QAccessibleEvent &event);
virtual void setRootObject(QObject *o);
virtual void initialize();
virtual void cleanup();
diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/qwindowsaccessibility.cpp
index 4ecc8439a7..2678fd7f23 100644
--- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/qwindowsaccessibility.cpp
@@ -1296,10 +1296,10 @@ QWindowsAccessibility::QWindowsAccessibility()
}
-void QWindowsAccessibility::notifyAccessibilityUpdate(QObject *o, int who, QAccessible::Event reason)
+void QWindowsAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &event)
{
QString soundName;
- switch (reason) {
+ switch (event.type()) {
case QAccessible::PopupMenuStart:
soundName = QLatin1String("MenuPopup");
break;
@@ -1370,8 +1370,9 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QObject *o, int who, QAcce
// An event has to be associated with a window,
// so find the first parent that is a widget and that has a WId
- QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(o);
+ QAccessibleInterface *iface = event.accessibleInterface();
QWindow *window = iface ? window_helper(iface) : 0;
+ delete iface;
if (!window) {
window = QGuiApplication::activeWindow();
@@ -1382,18 +1383,17 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QObject *o, int who, QAcce
QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", window);
- if (reason != QAccessible::MenuCommand) { // MenuCommand is faked
+ if (event.type() != QAccessible::MenuCommand) { // MenuCommand is faked
// See comment "SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE"
eventNum %= 50; //[0..49]
int eventId = - eventNum - 1;
- qAccessibleRecentSentEvents()->insert(eventId, qMakePair(o, who));
- ptrNotifyWinEvent(reason, hWnd, OBJID_CLIENT, eventId );
+ qAccessibleRecentSentEvents()->insert(eventId, qMakePair(event.object(), event.child()));
+ ptrNotifyWinEvent(event.type(), hWnd, OBJID_CLIENT, eventId );
++eventNum;
}
#endif // Q_WS_WINCE
-
}
/*
diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.h b/src/plugins/platforms/windows/qwindowsaccessibility.h
index d3c9c11088..addd748523 100644
--- a/src/plugins/platforms/windows/qwindowsaccessibility.h
+++ b/src/plugins/platforms/windows/qwindowsaccessibility.h
@@ -50,12 +50,12 @@ class QWindowsAccessibility : public QPlatformAccessibility
public:
QWindowsAccessibility();
static bool handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult);
- virtual void notifyAccessibilityUpdate(QObject *o, int who, QAccessible::Event reason);
+ virtual void notifyAccessibilityUpdate(const QAccessibleEvent &event);
/*
virtual void setRootObject(QObject *o);
virtual void initialize();
virtual void cleanup();
-*/
+ */
};
#endif // QWINDOWSACCESSIBILITY_H
diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h
index 3bae7030ac..d402cc8cf8 100644
--- a/src/testlib/qtestaccessible.h
+++ b/src/testlib/qtestaccessible.h
@@ -134,10 +134,10 @@ private:
}
}
- static void updateHandler(QObject *o, int c, QAccessible::Event e)
+ static void updateHandler(const QAccessibleEvent &event)
{
// qDebug("updateHandler called: %p %d %d", o, c, (int)e);
- eventList().append(QTestAccessibilityEvent(o, c, (int)e));
+ eventList().append(QTestAccessibilityEvent(event.object(), event.child(), (int)event.type()));
}
static EventList &eventList()