summaryrefslogtreecommitdiffstats
path: root/src/gui/accessible
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/gui/accessible
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/gui/accessible')
-rw-r--r--src/gui/accessible/accessible.pri25
-rw-r--r--src/gui/accessible/qaccessible.cpp1094
-rw-r--r--src/gui/accessible/qaccessible.h428
-rw-r--r--src/gui/accessible/qaccessible2.cpp205
-rw-r--r--src/gui/accessible/qaccessible2.h246
-rw-r--r--src/gui/accessible/qaccessible_mac.mm2469
-rw-r--r--src/gui/accessible/qaccessible_mac_carbon.cpp119
-rw-r--r--src/gui/accessible/qaccessible_mac_cocoa.mm239
-rw-r--r--src/gui/accessible/qaccessible_mac_p.h479
-rw-r--r--src/gui/accessible/qaccessible_unix.cpp134
-rw-r--r--src/gui/accessible/qaccessible_win.cpp1217
-rw-r--r--src/gui/accessible/qaccessiblebridge.cpp158
-rw-r--r--src/gui/accessible/qaccessiblebridge.h92
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp410
-rw-r--r--src/gui/accessible/qaccessibleobject.h140
-rw-r--r--src/gui/accessible/qaccessibleplugin.cpp107
-rw-r--r--src/gui/accessible/qaccessibleplugin.h87
-rw-r--r--src/gui/accessible/qaccessiblewidget.cpp1031
-rw-r--r--src/gui/accessible/qaccessiblewidget.h141
19 files changed, 8821 insertions, 0 deletions
diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri
new file mode 100644
index 0000000000..31362ffded
--- /dev/null
+++ b/src/gui/accessible/accessible.pri
@@ -0,0 +1,25 @@
+# Qt accessibility module
+
+contains(QT_CONFIG, accessibility) {
+ HEADERS += accessible/qaccessible.h \
+ accessible/qaccessible2.h \
+ accessible/qaccessibleobject.h \
+ accessible/qaccessiblewidget.h \
+ accessible/qaccessibleplugin.h
+ SOURCES += accessible/qaccessible.cpp \
+ accessible/qaccessible2.cpp \
+ accessible/qaccessibleobject.cpp \
+ accessible/qaccessiblewidget.cpp \
+ accessible/qaccessibleplugin.cpp
+
+ mac:!embedded:!qpa {
+ HEADERS += accessible/qaccessible_mac_p.h
+ OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm \
+ accessible/qaccessible_mac_cocoa.mm
+ } else:win32 {
+ SOURCES += accessible/qaccessible_win.cpp
+ } else {
+ HEADERS += accessible/qaccessiblebridge.h
+ SOURCES += accessible/qaccessible_unix.cpp accessible/qaccessiblebridge.cpp
+ }
+}
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
new file mode 100644
index 0000000000..abe68f8108
--- /dev/null
+++ b/src/gui/accessible/qaccessible.cpp
@@ -0,0 +1,1094 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessible.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qaccessibleplugin.h"
+#include "qaccessiblewidget.h"
+#include "qapplication.h"
+#include "qhash.h"
+#include "qmetaobject.h"
+#include "qmutex.h"
+#include <private/qfactoryloader_p.h>
+
+#include "qwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAccessible
+ \brief The QAccessible class provides enums and static functions
+ relating to accessibility.
+
+ \ingroup accessibility
+
+
+ Accessible applications can be used by people who are not able to
+ use applications by conventional means.
+
+ The functions in this class are used for communication between
+ accessible applications (also called AT Servers) and
+ accessibility tools (AT Clients), such as screen readers and
+ braille displays. Clients and servers communicate in the following way:
+
+ \list
+ \o \e{AT Servers} notify the clients about events through calls to the
+ updateAccessibility() function.
+
+ \o \e{AT Clients} request information about the objects in the server.
+ The QAccessibleInterface class is the core interface, and encapsulates
+ this information in a pure virtual API. Implementations of the interface
+ are provided by Qt through the queryAccessibleInterface() API.
+ \endlist
+
+ The communication between servers and clients is initialized by
+ the setRootObject() function. Function pointers can be installed
+ to replace or extend the default behavior of the static functions
+ in QAccessible.
+
+ Qt supports Microsoft Active Accessibility (MSAA), Mac OS X
+ Accessibility, and the Unix/X11 AT-SPI standard. Other backends
+ can be supported using QAccessibleBridge.
+
+ In addition to QAccessible's static functions, Qt offers one
+ generic interface, QAccessibleInterface, that can be used to wrap
+ all widgets and objects (e.g., QPushButton). This single
+ interface provides all the metadata necessary for the assistive
+ technologies. Qt provides implementations of this interface for
+ its built-in widgets as plugins.
+
+ When you develop custom widgets, you can create custom subclasses
+ of QAccessibleInterface and distribute them as plugins (using
+ QAccessiblePlugin) or compile them into the application.
+ Likewise, Qt's predefined accessibility support can be built as
+ plugin (the default) or directly into the Qt library. The main
+ advantage of using plugins is that the accessibility classes are
+ only loaded into memory if they are actually used; they don't
+ slow down the common case where no assistive technology is being
+ used.
+
+ Qt also includes two convenience classes, QAccessibleObject and
+ QAccessibleWidget, that inherit from QAccessibleInterface and
+ provide the lowest common denominator of metadata (e.g., widget
+ geometry, window title, basic help text). You can use them as
+ base classes when wrapping your custom QObject or QWidget
+ subclasses.
+
+ \sa QAccessibleInterface
+*/
+
+/*!
+ \enum QAccessible::Action
+
+ This enum describes the possible types of action that can occur.
+
+ \value DefaultAction
+ \value Press
+ \value SetFocus
+ \value Increase
+ \value Decrease
+ \value Accept
+ \value Cancel
+ \value Select
+ \value ClearSelection
+ \value RemoveSelection
+ \value ExtendSelection
+ \value AddToSelection
+
+ \value FirstStandardAction
+ \value LastStandardAction
+*/
+
+/*!
+ \enum QAccessible::Method
+
+ This enum describes the possible types of methods that can be
+ invoked on an accessible object.
+
+ \value ListSupportedMethods
+ \value SetCursorPosition
+ \value GetCursorPosition
+
+ \omitvalue ForegroundColor
+ \omitvalue BackgroundColor
+
+ \sa QAccessibleInterface::invokeMethod()
+*/
+
+/*!
+ \fn QSet<Method> QAccessibleInterface::supportedMethods()
+ \since 4.3
+
+ Returns a QSet of \l{QAccessible::}{Method}s that are supported by this
+ accessible interface.
+
+ \sa QAccessible::Method invokeMethod()
+*/
+
+/*!
+ \enum QAccessible::StateFlag
+
+ This enum type defines bit flags that can be combined to indicate
+ the state of an accessible object. The values are:
+
+ \value Animated The object's appearance changes frequently.
+ \value Busy The object cannot accept input at the moment.
+ \value Checked The object's check box is checked.
+ \value Collapsed The object is collapsed, e.g. a closed listview item, or an iconified window.
+ \value DefaultButton The object represents the default button in a dialog.
+ \value Expanded The object is expandable, and currently the children are visible.
+ \value ExtSelectable The object supports extended selection.
+ \value Focusable The object can receive focus. Only objects in the active window can receive focus.
+ \value Focused The object has keyboard focus.
+ \value HasPopup The object opens a popup.
+ \value HotTracked The object's appearance is sensitive to the mouse cursor position.
+ \value Invisible The object is not visible to the user.
+ \value Linked The object is linked to another object, e.g. a hyperlink.
+ \value Marqueed The object displays scrolling contents, e.g. a log view.
+ \value Mixed The state of the object is not determined, e.g. a tri-state check box that is neither checked nor unchecked.
+ \value Modal The object blocks input from other objects.
+ \value Movable The object can be moved.
+ \value MultiSelectable The object supports multiple selected items.
+ \value Normal The normal state.
+ \value Offscreen The object is clipped by the visible area. Objects that are off screen are also invisible.
+ \value Pressed The object is pressed.
+ \value Protected The object is password protected, e.g. a line edit for entering a Password.
+ \value ReadOnly The object can usually be edited, but is explicitly set to read-only.
+ \value Selectable The object is selectable.
+ \value Selected The object is selected.
+ \value SelfVoicing The object describes itself through speech or sound.
+ \value Sizeable The object can be resized, e.g. top-level windows.
+ \value Traversed The object is linked and has been visited.
+ \value Unavailable The object is unavailable to the user, e.g. a disabled widget.
+ \omitvalue Moveable
+ \omitvalue HasInvokeExtension
+
+ Implementations of QAccessibleInterface::state() return a combination
+ of these flags.
+*/
+
+/*!
+ \enum QAccessible::Event
+
+ This enum type defines accessible event types.
+
+ \value AcceleratorChanged
+ \value Alert A system alert (e.g., a message from a QMessageBox)
+ \value ContextHelpEnd Context help (QWhatsThis) for an object is finished.
+ \value ContextHelpStart Context help (QWhatsThis) for an object is initiated.
+ \value DefaultActionChanged The default QAccessible::Action for the accessible object changed
+ \value DescriptionChanged The objects QAccessible::Description changed.
+ \value DialogEnd A dialog (QDialog) is been hidden
+ \value DialogStart A dialog (QDialog) has been set visible.
+ \value DragDropEnd A Drag & Drop operation is about to finished.
+ \value DragDropStart A Drag & Drop operation is about to be initiated.
+ \value Focus An object has gained keyboard focus.
+ \value ForegroundChanged A window has been activated (i.e., a new window has gained focus on the desktop)
+ \value HelpChanged The QAccessible::Help text property of an object has changed
+ \value LocationChanged An objects location on the screen changed
+ \value MenuCommand A menu item is triggered.
+ \value MenuEnd A menu has been closed (Qt uses PopupMenuEnd for all menus)
+ \value MenuStart A menu has been opened on the menubar (Qt uses PopupMenuStart for all menus)
+ \value NameChanged The QAccessible::Name property of an object has changed
+ \value ObjectCreated A new object is created.
+ \value ObjectDestroyed An object is deleted.
+ \value ObjectHide An object is hidden (i.e., with QWidget::hide()). Any children the object that is hidden has do not send this event.
+ It is not send when an object is hidden as it is being obcured by others.
+ \value ObjectReorder A layout or item view has added, removed, or moved an object (Qt does not use this event).
+ \value ObjectShow An object is displayed (i.e., with QWidget::show()).
+ \value ParentChanged An objects parent object changed.
+ \value PopupMenuEnd A popup menu has closed.
+ \value PopupMenuStart A popupmenu has opened.
+ \value ScrollingEnd A scrollbar scroll operation has ended (the mouse has released the slider handle)
+ \value ScrollingStart A scrollbar scroll operation is about to start (i.e., the mouse has pressed on the slider handle)
+ \value Selection The selection has changed in a menu or item view.
+ \value SelectionAdd An item has been added to the selection in an item view.
+ \value SelectionRemove An item has been removed from an item view selection.
+ \value SelectionWithin Several changes to a selection has occurred in an item view.
+ \value SoundPlayed A sound has been played by an object
+ \value StateChanged The QAccessible::State of an object has changed.
+ \value ValueChanged The QAccessible::Value of an object has changed.
+*/
+
+/*!
+ \enum QAccessible::Role
+
+ This enum defines the role of an accessible object. The roles are:
+
+ \value AlertMessage An object that is used to alert the user.
+ \value Animation An object that displays an animation.
+ \value Application The application's main window.
+ \value Assistant An object that provids interactive help.
+ \value Border An object that represents a border.
+ \value ButtonDropDown A button that drops down a list of items.
+ \value ButtonDropGrid A button that drops down a grid.
+ \value ButtonMenu A button that drops down a menu.
+ \value Canvas An object that displays graphics that the user can interact with.
+ \value Caret An object that represents the system caret (text cursor).
+ \value Cell A cell in a table.
+ \value Chart An object that displays a graphical representation of data.
+ \value CheckBox An object that represents an option that can be checked or unchecked. Some options provide a "mixed" state, e.g. neither checked nor unchecked.
+ \value Client The client area in a window.
+ \value Clock A clock displaying time.
+ \value Column A column of cells, usually within a table.
+ \value ColumnHeader A header for a column of data.
+ \value ComboBox A list of choices that the user can select from.
+ \value Cursor An object that represents the mouse cursor.
+ \value Dial An object that represents a dial or knob.
+ \value Dialog A dialog box.
+ \value Document A document window, usually in an MDI environment.
+ \value EditableText Editable text
+ \value Equation An object that represents a mathematical equation.
+ \value Graphic A graphic or picture, e.g. an icon.
+ \value Grip A grip that the user can drag to change the size of widgets.
+ \value Grouping An object that represents a logical grouping of other objects.
+ \value HelpBalloon An object that displays help in a separate, short lived window.
+ \value HotkeyField A hotkey field that allows the user to enter a key sequence.
+ \value Indicator An indicator that represents a current value or item.
+ \value LayeredPane An object that can contain layered children, e.g. in a stack.
+ \value Link A link to something else.
+ \value List A list of items, from which the user can select one or more items.
+ \value ListItem An item in a list of items.
+ \value MenuBar A menu bar from which menus are opened by the user.
+ \value MenuItem An item in a menu or menu bar.
+ \value NoRole The object has no role. This usually indicates an invalid object.
+ \value PageTab A page tab that the user can select to switch to a different page in a dialog.
+ \value PageTabList A list of page tabs.
+ \value Pane A generic container.
+ \value PopupMenu A menu which lists options that the user can select to perform an action.
+ \value ProgressBar The object displays the progress of an operation in progress.
+ \value PropertyPage A property page where the user can change options and settings.
+ \value PushButton A button.
+ \value RadioButton An object that represents an option that is mutually exclusive with other options.
+ \value Row A row of cells, usually within a table.
+ \value RowHeader A header for a row of data.
+ \value ScrollBar A scroll bar, which allows the user to scroll the visible area.
+ \value Separator A separator that divides space into logical areas.
+ \value Slider A slider that allows the user to select a value within a given range.
+ \value Sound An object that represents a sound.
+ \value SpinBox A spin box widget that allows the user to enter a value within a given range.
+ \value Splitter A splitter distributing available space between its child widgets.
+ \value StaticText Static text, such as labels for other widgets.
+ \value StatusBar A status bar.
+ \value Table A table representing data in a grid of rows and columns.
+ \value TitleBar The title bar caption of a window.
+ \value ToolBar A tool bar, which groups widgets that the user accesses frequently.
+ \value ToolTip A tool tip which provides information about other objects.
+ \value Tree A list of items in a tree structure.
+ \value TreeItem An item in a tree structure.
+ \value UserRole The first value to be used for user defined roles.
+ \value Whitespace Blank space between other objects.
+ \value Window A top level window.
+*/
+
+/*!
+ \enum QAccessible::RelationFlag
+
+ This enum type defines bit flags that can be combined to indicate
+ the relationship between two accessible objects.
+
+ \value Unrelated The objects are unrelated.
+ \value Self The objects are the same.
+ \value Ancestor The first object is a parent of the second object.
+ \value Child The first object is a direct child of the second object.
+ \value Descendent The first object is an indirect child of the second object.
+ \value Sibling The objects are siblings.
+
+ \value Up The first object is above the second object.
+ \value Down The first object is below the second object.
+ \value Left The first object is left of the second object.
+ \value Right The first object is right of the second object.
+ \value Covers The first object covers the second object.
+ \value Covered The first object is covered by the second object.
+
+ \value FocusChild The first object is the second object's focus child.
+ \value Label The first object is the label of the second object.
+ \value Labelled The first object is labelled by the second object.
+ \value Controller The first object controls the second object.
+ \value Controlled The first object is controlled by the second object.
+
+ \omitvalue HierarchyMask
+ \omitvalue GeometryMask
+ \omitvalue LogicalMask
+
+ Implementations of relationTo() return a combination of these flags.
+ Some values are mutually exclusive.
+
+ Implementations of navigate() can accept only one distinct value.
+*/
+
+/*!
+ \enum QAccessible::Text
+
+ This enum specifies string information that an accessible object
+ returns.
+
+ \value Name The name of the object. This can be used both
+ as an identifier or a short description by
+ accessible clients.
+ \value Description A short text describing the object.
+ \value Value The value of the object.
+ \value Help A longer text giving information about how to use the object.
+ \value Accelerator The keyboard shortcut that executes the object's default action.
+ \value UserText The first value to be used for user defined text.
+*/
+
+/*!
+ \fn QAccessibleInterface::~QAccessibleInterface()
+
+ Destroys the object.
+*/
+
+/*!
+ \fn void QAccessible::initialize()
+ \internal
+*/
+
+/*!
+ \fn void QAccessible::cleanup()
+ \internal
+*/
+
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QAccessibleFactoryInterface_iid, QLatin1String("/accessible")))
+#endif
+
+Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories)
+
+QAccessible::UpdateHandler QAccessible::updateHandler = 0;
+QAccessible::RootObjectHandler QAccessible::rootObjectHandler = 0;
+
+static bool accessibility_active = false;
+static bool cleanupAdded = false;
+static void qAccessibleCleanup()
+{
+ qAccessibleFactories()->clear();
+}
+
+/*!
+ \typedef QAccessible::InterfaceFactory
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet doc/src/snippets/code/src_gui_accessible_qaccessible.cpp 1
+
+ The function receives a QString and a QObject pointer, where the
+ QString is the key identifying the interface. The QObject is used
+ to pass on to the QAccessibleInterface so that it can hold a reference
+ to it.
+
+ If the key and the QObject does not have a corresponding
+ QAccessibleInterface, a null-pointer will be returned.
+
+ Installed factories are called by queryAccessibilityInterface() until
+ one provides an interface.
+*/
+
+/*!
+ \typedef QAccessible::UpdateHandler
+
+ \internal
+
+ A function pointer type. Use a function with this prototype to install
+ your own update function.
+
+ The function is called by updateAccessibility().
+*/
+
+/*!
+ \typedef QAccessible::RootObjectHandler
+
+ \internal
+
+ A function pointer type. Use a function with this prototype to install
+ your own root object handler.
+
+ The function is called by setRootObject().
+*/
+
+/*!
+ Installs the InterfaceFactory \a factory. The last factory added
+ is the first one used by queryAccessibleInterface().
+*/
+void QAccessible::installFactory(InterfaceFactory factory)
+{
+ if (!factory)
+ return;
+
+ if (!cleanupAdded) {
+ qAddPostRoutine(qAccessibleCleanup);
+ cleanupAdded = true;
+ }
+ if (qAccessibleFactories()->contains(factory))
+ return;
+ qAccessibleFactories()->append(factory);
+}
+
+/*!
+ Removes \a factory from the list of installed InterfaceFactories.
+*/
+void QAccessible::removeFactory(InterfaceFactory factory)
+{
+ qAccessibleFactories()->removeAll(factory);
+}
+
+/*!
+ \internal
+
+ Installs the given \a handler as the function to be used by
+ updateAccessibility(), and returns the previously installed
+ handler.
+*/
+QAccessible::UpdateHandler QAccessible::installUpdateHandler(UpdateHandler handler)
+{
+ UpdateHandler old = updateHandler;
+ updateHandler = handler;
+ return old;
+}
+
+/*!
+ Installs the given \a handler as the function to be used by setRootObject(),
+ and returns the previously installed handler.
+*/
+QAccessible::RootObjectHandler QAccessible::installRootObjectHandler(RootObjectHandler handler)
+{
+ RootObjectHandler old = rootObjectHandler;
+ rootObjectHandler = handler;
+ return old;
+}
+
+/*!
+ If a QAccessibleInterface implementation exists for the given \a object,
+ this function returns a pointer to the implementation; otherwise it
+ returns 0.
+
+ The function calls all installed factory functions (from most
+ recently installed to least recently installed) until one is found
+ that provides an interface for the class of \a object. If no
+ factory can provide an accessibility implementation for the class
+ the function loads installed accessibility plugins, and tests if
+ any of the plugins can provide the implementation.
+
+ If no implementation for the object's class is available, the
+ function tries to find an implementation for the object's parent
+ class, using the above strategy.
+
+ \warning The caller is responsible for deleting the returned
+ interface after use.
+*/
+QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object)
+{
+ accessibility_active = true;
+ QAccessibleInterface *iface = 0;
+ if (!object)
+ return 0;
+
+ QEvent e(QEvent::AccessibilityPrepare);
+ QApplication::sendEvent(object, &e);
+
+ const QMetaObject *mo = object->metaObject();
+ while (mo) {
+ const QLatin1String cn(mo->className());
+ for (int i = qAccessibleFactories()->count(); i > 0; --i) {
+ InterfaceFactory factory = qAccessibleFactories()->at(i - 1);
+ iface = factory(cn, object);
+ if (iface)
+ return iface;
+ }
+#ifndef QT_NO_LIBRARY
+ QAccessibleFactoryInterface *factory = qobject_cast<QAccessibleFactoryInterface*>(loader()->instance(cn));
+ if (factory) {
+ iface = factory->create(cn, object);
+ if (iface)
+ return iface;
+ }
+#endif
+ mo = mo->superClass();
+ }
+
+ QWidget *widget = qobject_cast<QWidget*>(object);
+ if (widget)
+ return new QAccessibleWidget(widget);
+ else if (object == qApp)
+ return new QAccessibleApplication();
+
+ return 0;
+}
+
+/*!
+ Returns true if an accessibility implementation has been requested
+ during the runtime of the application; otherwise returns false.
+
+ Use this function to prevent potentially expensive notifications via
+ updateAccessibility().
+*/
+bool QAccessible::isActive()
+{
+ return accessibility_active;
+}
+
+/*!
+ \fn void QAccessible::setRootObject(QObject *object)
+
+ Sets the root accessible object of this application to \a object.
+ All other accessible objects in the application can be reached by the
+ client using object navigation.
+
+ You should never need to call this function. Qt sets the QApplication
+ object as the root object immediately before the event loop is entered
+ in QApplication::exec().
+
+ Use QAccessible::installRootObjectHandler() to redirect the function
+ call to a customized handler function.
+
+ \sa queryAccessibleInterface()
+*/
+
+/*!
+ \fn void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
+
+ Notifies accessibility clients about a change in \a object's
+ accessibility information.
+
+ \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.
+
+ Call this function whenever the state of your accessible object or
+ one of its sub-elements has been changed either programmatically
+ (e.g. by calling QLabel::setText()) or by user interaction.
+
+ If there are no accessibility tools listening to this event, the
+ performance penalty for calling this function is small, but if determining
+ the parameters of the call is expensive you can test isActive() to
+ avoid unnecessary computations.
+*/
+
+
+/*!
+ \class QAccessibleInterface
+ \brief The QAccessibleInterface class defines an interface that exposes information
+ about accessible objects.
+
+ \ingroup accessibility
+
+ Accessibility tools (also called AT Clients), such as screen readers
+ or braille displays, require high-level information about
+ accessible objects in an application. Accessible objects provide
+ specialized input and output methods, making it possible for users
+ to use accessibility tools with enabled applications (AT Servers).
+
+ Every element that the user needs to interact with or react to is
+ an accessible object, and should provide this information. These
+ are mainly visual objects, such as widgets and widget elements, but
+ can also be content, such as sounds.
+
+ The AT client uses three basic concepts to acquire information
+ about any accessible object in an application:
+ \list
+ \i \e Properties The client can read information about
+ accessible objects. In some cases the client can also modify these
+ properties; such as text in a line edit.
+ \i \e Actions The client can invoke actions like pressing a button
+ or .
+ \i \e{Relationships and Navigation} The client can traverse from one
+ accessible object to another, using the relationships between objects.
+ \endlist
+
+ The QAccessibleInterface defines the API for these three concepts.
+
+ \section1 Relationships and Navigation
+
+ The functions childCount() and indexOfChild() return the number of
+ children of an accessible object and the index a child object has
+ in its parent. The childAt() function returns the index of a child
+ at a given position.
+
+ The relationTo() function provides information about how two
+ different objects relate to each other, and navigate() allows
+ traversing from one object to another object with a given
+ relationship.
+
+ \section1 Properties
+
+ The central property of an accessible objects is what role() it
+ has. Different objects can have the same role, e.g. both the "Add
+ line" element in a scroll bar and the \c OK button in a dialog have
+ the same role, "button". The role implies what kind of
+ interaction the user can perform with the user interface element.
+
+ An object's state() property is a combination of different state
+ flags and can describe both how the object's state differs from a
+ "normal" state, e.g. it might be unavailable, and also how it
+ behaves, e.g. it might be selectable.
+
+ The text() property provides textual information about the object.
+ An object usually has a name, but can provide extended information
+ such as a description, help text, or information about any
+ keyboard accelerators it provides. Some objects allow changing the
+ text() property through the setText() function, but this
+ information is in most cases read-only.
+
+ The rect() property provides information about the geometry of an
+ accessible object. This information is usually only available for
+ visual objects.
+
+ \section1 Actions and Selection
+
+ To enable the user to interact with an accessible object the
+ object must expose information about the actions that it can
+ perform. userActionCount() returns the number of actions supported by
+ an accessible object, and actionText() returns textual information
+ about those actions. doAction() invokes an action.
+
+ Objects that support selections can define actions to change the selection.
+
+ \section2 Objects and children
+
+ A QAccessibleInterface provides information about the accessible
+ object, and can also provide information for the children of that
+ object if those children don't provide a QAccessibleInterface
+ implementation themselves. This is practical if the object has
+ many similar children (e.g. items in a list view), or if the
+ children are an integral part of the object itself, for example, the
+ different sections in a scroll bar.
+
+ If an accessible object provides information about its children
+ through one QAccessibleInterface, the children are referenced
+ using indexes. The index is 1-based for the children, i.e. 0
+ refers to the object itself, 1 to the first child, 2 to the second
+ child, and so on.
+
+ All functions in QAccessibleInterface that take a child index
+ relate to the object itself if the index is 0, or to the child
+ specified. If a child provides its own interface implementation
+ (which can be retrieved through navigation) asking the parent for
+ information about that child will usually not succeed.
+
+ \sa QAccessible
+*/
+
+/*!
+ \fn bool QAccessibleInterface::isValid() const
+
+ Returns true if all the data necessary to use this interface
+ implementation is valid (e.g. all pointers are non-null);
+ otherwise returns false.
+
+ \sa object()
+*/
+
+/*!
+ \fn QObject *QAccessibleInterface::object() const
+
+ Returns a pointer to the QObject this interface implementation provides
+ information for.
+
+ \sa isValid()
+*/
+
+/*!
+ \fn int QAccessibleInterface::childCount() const
+
+ Returns the number of children that belong to this object. A child
+ can provide accessibility information on its own (e.g. a child
+ widget), or be a sub-element of this accessible object.
+
+ All objects provide this information.
+
+ \sa indexOfChild()
+*/
+
+/*!
+ \fn int QAccessibleInterface::indexOfChild(const QAccessibleInterface *child) const
+
+ Returns the 1-based index of the object \a child in this object's
+ children list, or -1 if \a child is not a child of this object. 0
+ is not a possible return value.
+
+ All objects provide this information about their children.
+
+ \sa childCount()
+*/
+
+/*!
+ \fn QAccessible::Relation QAccessibleInterface::relationTo(int child,
+const QAccessibleInterface *other, int otherChild) const
+
+ Returns the relationship between this object's \a child and the \a
+ other object's \a otherChild. If \a child is 0 the object's own relation
+ is returned.
+
+ The returned value indicates the relation of the called object to
+ the \a other object, e.g. if this object is a child of \a other
+ the return value will be \c Child.
+
+ The return value is a combination of the bit flags in the
+ QAccessible::Relation enumeration.
+
+ All objects provide this information.
+
+ \sa indexOfChild(), navigate()
+*/
+
+/*!
+ \fn int QAccessibleInterface::childAt(int x, int y) const
+
+ Returns the 1-based index of the child that contains the screen
+ coordinates (\a x, \a y). This function returns 0 if the point is
+ positioned on the object itself. If the tested point is outside
+ the boundaries of the object this function returns -1.
+
+ This function is only relyable for visible objects (invisible
+ object might not be laid out correctly).
+
+ All visual objects provide this information.
+
+ \sa rect()
+*/
+
+/*!
+ \fn int QAccessibleInterface::navigate(RelationFlag relation, int entry, QAccessibleInterface
+**target) const
+
+ Navigates from this object to an object that has a relationship
+ \a relation to this object, and returns the respective object in
+ \a target. It is the caller's responsibility to delete *\a target
+ after use.
+
+ If an object is found, \a target is set to point to the object, and
+ the index of the child of \a target is returned. The return value
+ is 0 if \a target itself is the requested object. \a target is set
+ to null if this object is the target object (i.e. the requested
+ object is a handled by this object).
+
+ If no object is found \a target is set to null, and the return
+ value is -1.
+
+ The \a entry parameter has two different meanings:
+ \list
+ \i \e{Hierarchical and Logical relationships} -- if multiple objects with
+ the requested relationship exist \a entry specifies which one to
+ return. \a entry is 1-based, e.g. use 1 to get the first (and
+ possibly only) object with the requested relationship.
+
+ The following code demonstrates how to use this function to
+ navigate to the first child of an object:
+
+ \snippet doc/src/snippets/code/src_gui_accessible_qaccessible.cpp 0
+
+ \i \e{Geometric relationships} -- the index of the child from
+ which to start navigating in the specified direction. \a entry
+ can be 0 to navigate to a sibling of this object, or non-null to
+ navigate within contained children that don't provide their own
+ accessible information.
+ \endlist
+
+ Note that the \c Descendent value for \a relation is not supported.
+
+ All objects support navigation.
+
+ \sa relationTo(), childCount()
+*/
+
+/*!
+ \fn QString QAccessibleInterface::text(Text t, int child) const
+
+ Returns the value of the text property \a t of the object, or of
+ the object's child if \a child is not 0.
+
+ The \l Name is a string used by clients to identify, find, or
+ announce an accessible object for the user. All objects must have
+ a name that is unique within their container. The name can be
+ used differently by clients, so the name should both give a
+ short description of the object and be unique.
+
+ An accessible object's \l Description provides textual information
+ about an object's visual appearance. The description is primarily
+ used to provide greater context for vision-impaired users, but is
+ also used for context searching or other applications. Not all
+ objects have a description. An "OK" button would not need a
+ description, but a tool button that shows a picture of a smiley
+ would.
+
+ The \l Value of an accessible object represents visual information
+ contained by the object, e.g. the text in a line edit. Usually,
+ the value can be modified by the user. Not all objects have a
+ value, e.g. static text labels don't, and some objects have a
+ state that already is the value, e.g. toggle buttons.
+
+ The \l Help text provides information about the function and
+ usage of an accessible object. Not all objects provide this
+ information.
+
+ The \l Accelerator is a keyboard shortcut that activates the
+ object's default action. A keyboard shortcut is the underlined
+ character in the text of a menu, menu item or widget, and is
+ either the character itself, or a combination of this character
+ and a modifier key like Alt, Ctrl or Shift. Command controls like
+ tool buttons also have shortcut keys and usually display them in
+ their tooltip.
+
+ All objects provide a string for \l Name.
+
+ \sa role(), state()
+*/
+
+/*!
+ \fn void QAccessibleInterface::setText(Text t, int child, const QString &text)
+
+ Sets the text property \a t of the object, or of the object's
+ child if \a child is not 0, to \a text.
+
+ Note that the text properties of most objects are read-only.
+
+ \sa text()
+*/
+
+/*!
+ \fn QRect QAccessibleInterface::rect(int child) const
+
+ Returns the geometry of the object, or of the object's child if \a child
+ is not 0. The geometry is in screen coordinates.
+
+ This function is only reliable for visible objects (invisible
+ objects might not be laid out correctly).
+
+ All visual objects provide this information.
+
+ \sa childAt()
+*/
+
+/*!
+ \fn QAccessible::Role QAccessibleInterface::role(int child) const
+
+ Returns the role of the object, or of the object's child if \a child
+ is not 0. The role of an object is usually static.
+
+ All accessible objects have a role.
+
+ \sa text(), state()
+*/
+
+/*!
+ \fn QAccessible::State QAccessibleInterface::state(int child) const
+
+ Returns the current state of the object, or of the object's child if
+ \a child is not 0. The returned value is a combination of the flags in
+ the QAccessible::StateFlag enumeration.
+
+ All accessible objects have a state.
+
+ \sa text(), role()
+*/
+
+/*!
+ \fn int QAccessibleInterface::userActionCount(int child) const
+
+ Returns the number of custom actions of the object, or of the
+ object's child if \a child is not 0.
+
+ The \c Action type enumerates predefined actions: these
+ are not included in the returned value.
+
+ \sa actionText(), doAction()
+*/
+
+/*!
+ \fn QString QAccessibleInterface::actionText(int action, Text t, int child) const
+
+ Returns the text property \a t of the action \a action supported by
+ the object, or of the object's child if \a child is not 0.
+
+ \sa text(), userActionCount()
+*/
+
+/*!
+ \fn bool QAccessibleInterface::doAction(int action, int child, const QVariantList &params)
+
+ Asks the object, or the object's \a child if \a child is not 0, to
+ execute \a action using the parameters, \a params. Returns true if
+ the action could be executed; otherwise returns false.
+
+ \a action can be a predefined or a custom action.
+
+ \sa userActionCount(), actionText()
+*/
+
+/*!
+ \fn QColor QAccessibleInterface::backgroundColor()
+ \internal
+*/
+
+/*!
+ \fn QAccessibleEditableTextInterface *QAccessibleInterface::editableTextInterface()
+ \internal
+*/
+
+/*!
+ \fn QColor QAccessibleInterface::foregroundColor()
+ \internal
+*/
+
+/*!
+ \fn QAccessibleTextInterface *QAccessibleInterface::textInterface()
+ \internal
+*/
+
+/*!
+ \fn QAccessibleValueInterface *QAccessibleInterface::valueInterface()
+ \internal
+*/
+
+/*!
+ \fn QAccessibleTableInterface *QAccessibleInterface::tableInterface()
+ \internal
+*/
+
+/*!
+ \fn QAccessibleActionInterface *QAccessibleInterface::actionInterface()
+ \internal
+*/
+
+/*!
+ \fn QAccessibleImageInterface *QAccessibleInterface::imageInterface()
+ \internal
+*/
+
+/*!
+ \class QAccessibleEvent
+ \brief The QAccessibleEvent class is used to query addition
+ accessibility information about complex widgets.
+
+ The event can be of type QEvent::AccessibilityDescription or
+ QEvent::AccessibilityHelp.
+
+ Some QAccessibleInterface implementations send QAccessibleEvents
+ to the widget they wrap to obtain the description or help text of
+ a widget or of its children. The widget can answer by calling
+ setValue() with the requested information.
+
+ The default QWidget::event() implementation simply sets the text
+ to be the widget's \l{QWidget::toolTip}{tooltip} (for \l
+ AccessibilityDescription event) or its
+ \l{QWidget::whatsThis}{"What's This?" text} (for \l
+ AccessibilityHelp event).
+
+ \ingroup accessibility
+ \ingroup events
+*/
+
+/*!
+ \fn QAccessibleEvent::QAccessibleEvent(Type type, int child)
+
+ Constructs an accessibility event of the given \a type, which
+ must be QEvent::AccessibilityDescription or
+ QEvent::AccessibilityHelp.
+
+ \a child is the (1-based) index of the child to which the request
+ applies. If \a child is 0, the request is for the widget itself.
+
+ \sa child()
+*/
+
+/*!
+ \fn int QAccessibleEvent::child() const
+
+ Returns the (1-based) index of the child to which the request
+ applies. If the child is 0, the request is for the widget itself.
+*/
+
+/*!
+ \fn QString QAccessibleEvent::value() const
+
+ Returns the text set using setValue().
+
+ \sa setValue()
+*/
+
+/*!
+ \fn void QAccessibleEvent::setValue(const QString &text)
+
+ Set the description or help text for the given child() to \a
+ text, thereby answering the request.
+
+ \sa value()
+*/
+
+/*!
+ \since 4.2
+
+ Invokes a \a method on \a child with the given parameters \a params
+ and returns the result of the operation as QVariant.
+
+ Note that the type of the returned QVariant depends on the action.
+
+ Returns an invalid QVariant if the object doesn't support the action.
+*/
+QVariant QAccessibleInterface::invokeMethod(Method method, int child, const QVariantList &params)
+{
+ if (!(state(0) & HasInvokeExtension))
+ return QVariant();
+
+ return static_cast<QAccessibleInterfaceEx *>(this)->invokeMethodEx(method, child, params);
+}
+
+QVariant QAccessibleInterfaceEx::virtual_hook(const QVariant &)
+{
+ return QVariant();
+}
+
+/*! \internal */
+QAccessible2Interface *QAccessibleInterface::cast_helper(QAccessible2::InterfaceType t)
+{
+ if (state(0) & HasInvokeExtension)
+ return static_cast<QAccessibleInterfaceEx *>(this)->interface_cast(t);
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
new file mode 100644
index 0000000000..c71417352b
--- /dev/null
+++ b/src/gui/accessible/qaccessible.h
@@ -0,0 +1,428 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLE_H
+#define QACCESSIBLE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qset.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qvariant.h>
+#include <QtGui/qcolor.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAccessibleInterface;
+
+class Q_GUI_EXPORT QAccessible
+{
+public:
+ enum Event {
+ SoundPlayed = 0x0001,
+ Alert = 0x0002,
+ ForegroundChanged = 0x0003,
+ MenuStart = 0x0004,
+ MenuEnd = 0x0005,
+ PopupMenuStart = 0x0006,
+ PopupMenuEnd = 0x0007,
+ ContextHelpStart = 0x000C,
+ ContextHelpEnd = 0x000D,
+ DragDropStart = 0x000E,
+ DragDropEnd = 0x000F,
+ DialogStart = 0x0010,
+ DialogEnd = 0x0011,
+ ScrollingStart = 0x0012,
+ ScrollingEnd = 0x0013,
+
+ MenuCommand = 0x0018,
+
+ ObjectCreated = 0x8000,
+ ObjectDestroyed = 0x8001,
+ ObjectShow = 0x8002,
+ ObjectHide = 0x8003,
+ ObjectReorder = 0x8004,
+ Focus = 0x8005,
+ Selection = 0x8006,
+ SelectionAdd = 0x8007,
+ SelectionRemove = 0x8008,
+ SelectionWithin = 0x8009,
+ StateChanged = 0x800A,
+ LocationChanged = 0x800B,
+ NameChanged = 0x800C,
+ DescriptionChanged = 0x800D,
+ ValueChanged = 0x800E,
+ ParentChanged = 0x800F,
+ HelpChanged = 0x80A0,
+ DefaultActionChanged = 0x80B0,
+ AcceleratorChanged = 0x80C0
+ };
+
+ enum StateFlag {
+ Normal = 0x00000000,
+ Unavailable = 0x00000001,
+ Selected = 0x00000002,
+ Focused = 0x00000004,
+ Pressed = 0x00000008,
+ Checked = 0x00000010,
+ Mixed = 0x00000020,
+ ReadOnly = 0x00000040,
+ HotTracked = 0x00000080,
+ DefaultButton = 0x00000100,
+ Expanded = 0x00000200,
+ Collapsed = 0x00000400,
+ Busy = 0x00000800,
+ // Floating = 0x00001000,
+ Marqueed = 0x00002000,
+ Animated = 0x00004000,
+ Invisible = 0x00008000,
+ Offscreen = 0x00010000,
+ Sizeable = 0x00020000,
+ Movable = 0x00040000,
+#ifdef QT3_SUPPORT
+ Moveable = Movable,
+#endif
+ SelfVoicing = 0x00080000,
+ Focusable = 0x00100000,
+ Selectable = 0x00200000,
+ Linked = 0x00400000,
+ Traversed = 0x00800000,
+ MultiSelectable = 0x01000000,
+ ExtSelectable = 0x02000000,
+ //AlertLow = 0x04000000,
+ //AlertMedium = 0x08000000,
+ //AlertHigh = 0x10000000, /* reused for HasInvokeExtension */
+ Protected = 0x20000000,
+ HasPopup = 0x40000000,
+ Modal = 0x80000000,
+
+ HasInvokeExtension = 0x10000000 // internal
+ };
+ Q_DECLARE_FLAGS(State, StateFlag)
+
+ enum Role {
+ NoRole = 0x00000000,
+ TitleBar = 0x00000001,
+ MenuBar = 0x00000002,
+ ScrollBar = 0x00000003,
+ Grip = 0x00000004,
+ Sound = 0x00000005,
+ Cursor = 0x00000006,
+ Caret = 0x00000007,
+ AlertMessage = 0x00000008,
+ Window = 0x00000009,
+ Client = 0x0000000A,
+ PopupMenu = 0x0000000B,
+ MenuItem = 0x0000000C,
+ ToolTip = 0x0000000D,
+ Application = 0x0000000E,
+ Document = 0x0000000F,
+ Pane = 0x00000010,
+ Chart = 0x00000011,
+ Dialog = 0x00000012,
+ Border = 0x00000013,
+ Grouping = 0x00000014,
+ Separator = 0x00000015,
+ ToolBar = 0x00000016,
+ StatusBar = 0x00000017,
+ Table = 0x00000018,
+ ColumnHeader = 0x00000019,
+ RowHeader = 0x0000001A,
+ Column = 0x0000001B,
+ Row = 0x0000001C,
+ Cell = 0x0000001D,
+ Link = 0x0000001E,
+ HelpBalloon = 0x0000001F,
+ Assistant = 0x00000020,
+ List = 0x00000021,
+ ListItem = 0x00000022,
+ Tree = 0x00000023,
+ TreeItem = 0x00000024,
+ PageTab = 0x00000025,
+ PropertyPage = 0x00000026,
+ Indicator = 0x00000027,
+ Graphic = 0x00000028,
+ StaticText = 0x00000029,
+ EditableText = 0x0000002A, // Editable, selectable, etc.
+ PushButton = 0x0000002B,
+ CheckBox = 0x0000002C,
+ RadioButton = 0x0000002D,
+ ComboBox = 0x0000002E,
+ // DropList = 0x0000002F,
+ ProgressBar = 0x00000030,
+ Dial = 0x00000031,
+ HotkeyField = 0x00000032,
+ Slider = 0x00000033,
+ SpinBox = 0x00000034,
+ Canvas = 0x00000035,
+ Animation = 0x00000036,
+ Equation = 0x00000037,
+ ButtonDropDown = 0x00000038,
+ ButtonMenu = 0x00000039,
+ ButtonDropGrid = 0x0000003A,
+ Whitespace = 0x0000003B,
+ PageTabList = 0x0000003C,
+ Clock = 0x0000003D,
+ Splitter = 0x0000003E,
+ // Additional Qt roles where enum value does not map directly to MSAA:
+ LayeredPane = 0x0000003F,
+ UserRole = 0x0000ffff
+ };
+
+ enum Text {
+ Name = 0,
+ Description,
+ Value,
+ Help,
+ Accelerator,
+ UserText = 0x0000ffff
+ };
+
+ enum RelationFlag {
+ Unrelated = 0x00000000,
+ Self = 0x00000001,
+ Ancestor = 0x00000002,
+ Child = 0x00000004,
+ Descendent = 0x00000008,
+ Sibling = 0x00000010,
+ HierarchyMask = 0x000000ff,
+
+ Up = 0x00000100,
+ Down = 0x00000200,
+ Left = 0x00000400,
+ Right = 0x00000800,
+ Covers = 0x00001000,
+ Covered = 0x00002000,
+ GeometryMask = 0x0000ff00,
+
+ FocusChild = 0x00010000,
+ Label = 0x00020000,
+ Labelled = 0x00040000,
+ Controller = 0x00080000,
+ Controlled = 0x00100000,
+ LogicalMask = 0x00ff0000
+ };
+ Q_DECLARE_FLAGS(Relation, RelationFlag)
+
+ enum Action {
+ DefaultAction = 0,
+ Press = -1,
+ FirstStandardAction = Press,
+ SetFocus = -2,
+ Increase = -3,
+ Decrease = -4,
+ Accept = -5,
+ Cancel = -6,
+ Select = -7,
+ ClearSelection = -8,
+ RemoveSelection = -9,
+ ExtendSelection = -10,
+ AddToSelection = -11,
+ LastStandardAction = AddToSelection
+ };
+
+ enum Method {
+ ListSupportedMethods = 0,
+ SetCursorPosition = 1,
+ GetCursorPosition = 2,
+ ForegroundColor = 3,
+ BackgroundColor = 4
+ };
+
+ typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*);
+ typedef void(*UpdateHandler)(QObject*, int who, Event reason);
+ typedef void(*RootObjectHandler)(QObject*);
+
+ static void installFactory(InterfaceFactory);
+ static void removeFactory(InterfaceFactory);
+ static UpdateHandler installUpdateHandler(UpdateHandler);
+ static RootObjectHandler installRootObjectHandler(RootObjectHandler);
+
+ static QAccessibleInterface *queryAccessibleInterface(QObject *);
+ static void updateAccessibility(QObject *, int who, Event reason);
+ static bool isActive();
+ static void setRootObject(QObject*);
+
+ static void initialize();
+ static void cleanup();
+
+private:
+ static UpdateHandler updateHandler;
+ static RootObjectHandler rootObjectHandler;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAccessible::State)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QAccessible::Relation)
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QSet<QAccessible::Method>)
+QT_BEGIN_NAMESPACE
+
+namespace QAccessible2
+{
+ enum InterfaceType
+ {
+ TextInterface,
+ EditableTextInterface,
+ ValueInterface,
+ TableInterface,
+ ActionInterface,
+ ImageInterface
+ };
+}
+
+class QAccessible2Interface;
+class QAccessibleTextInterface;
+class QAccessibleEditableTextInterface;
+class QAccessibleValueInterface;
+class QAccessibleTableInterface;
+class QAccessibleActionInterface;
+class QAccessibleImageInterface;
+
+class Q_GUI_EXPORT QAccessibleInterface : public QAccessible
+{
+public:
+ virtual ~QAccessibleInterface() {}
+ // check for valid pointers
+ virtual bool isValid() const = 0;
+ virtual QObject *object() const = 0;
+
+ // hierarchy
+ virtual int childCount() const = 0;
+ virtual int indexOfChild(const QAccessibleInterface *) const = 0;
+
+ // relations
+ virtual Relation relationTo(int child, const QAccessibleInterface *other,
+ int otherChild) const = 0;
+ virtual int childAt(int x, int y) const = 0;
+
+ // navigation
+ virtual int navigate(RelationFlag relation, int index, QAccessibleInterface **iface) const = 0;
+
+ // properties and state
+ virtual QString text(Text t, int child) const = 0;
+ virtual void setText(Text t, int child, const QString &text) = 0;
+ virtual QRect rect(int child) const = 0;
+ virtual Role role(int child) const = 0;
+ virtual State state(int child) const = 0;
+
+ // action
+ virtual int userActionCount(int child) const = 0;
+ virtual QString actionText(int action, Text t, int child) const = 0;
+ virtual bool doAction(int action, int child, const QVariantList &params = QVariantList()) = 0;
+
+ QVariant invokeMethod(Method method, int child = 0,
+ const QVariantList &params = QVariantList());
+
+ inline QSet<Method> supportedMethods()
+ { return qvariant_cast<QSet<Method> >(invokeMethod(ListSupportedMethods)); }
+
+ inline QColor foregroundColor()
+ { return qvariant_cast<QColor>(invokeMethod(ForegroundColor)); }
+
+ inline QColor backgroundColor()
+ { return qvariant_cast<QColor>(invokeMethod(BackgroundColor)); }
+
+ inline QAccessibleTextInterface *textInterface()
+ { return reinterpret_cast<QAccessibleTextInterface *>(cast_helper(QAccessible2::TextInterface)); }
+
+ inline QAccessibleEditableTextInterface *editableTextInterface()
+ { return reinterpret_cast<QAccessibleEditableTextInterface *>(cast_helper(QAccessible2::EditableTextInterface)); }
+
+ inline QAccessibleValueInterface *valueInterface()
+ { return reinterpret_cast<QAccessibleValueInterface *>(cast_helper(QAccessible2::ValueInterface)); }
+
+ inline QAccessibleTableInterface *tableInterface()
+ { return reinterpret_cast<QAccessibleTableInterface *>(cast_helper(QAccessible2::TableInterface)); }
+
+ inline QAccessibleActionInterface *actionInterface()
+ { return reinterpret_cast<QAccessibleActionInterface *>(cast_helper(QAccessible2::ActionInterface)); }
+
+ inline QAccessibleImageInterface *imageInterface()
+ { return reinterpret_cast<QAccessibleImageInterface *>(cast_helper(QAccessible2::ImageInterface)); }
+
+private:
+ QAccessible2Interface *cast_helper(QAccessible2::InterfaceType);
+};
+
+class Q_GUI_EXPORT QAccessibleInterfaceEx: public QAccessibleInterface
+{
+public:
+ virtual QVariant invokeMethodEx(Method method, int child, const QVariantList &params) = 0;
+ virtual QVariant virtual_hook(const QVariant &data);
+ virtual QAccessible2Interface *interface_cast(QAccessible2::InterfaceType)
+ { return 0; }
+};
+
+
+class Q_GUI_EXPORT QAccessibleEvent : public QEvent
+{
+public:
+ inline QAccessibleEvent(Type type, int child);
+ inline int child() const { return c; }
+ inline QString value() const { return val; }
+ inline void setValue(const QString &aText) { val = aText; }
+
+private:
+ int c;
+ QString val;
+};
+
+inline QAccessibleEvent::QAccessibleEvent(Type atype, int achild)
+ : QEvent(atype), c(achild) {}
+
+#define QAccessibleInterface_iid "com.trolltech.Qt.QAccessibleInterface"
+Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACCESSIBLE_H
diff --git a/src/gui/accessible/qaccessible2.cpp b/src/gui/accessible/qaccessible2.cpp
new file mode 100644
index 0000000000..36187f5315
--- /dev/null
+++ b/src/gui/accessible/qaccessible2.cpp
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessible2.h"
+#include "qapplication.h"
+#include "qclipboard.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \namespace QAccessible2
+ \ingroup accessibility
+ \internal
+ \preliminary
+
+ \brief The QAccessible2 namespace defines constants relating to
+ IAccessible2-based interfaces
+
+ \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
+*/
+
+/*!
+ \class QAccessibleTextInterface
+
+ \ingroup accessibility
+ \internal
+ \preliminary
+
+ \brief The QAccessibleTextInterface class implements support for
+ the IAccessibleText interface.
+
+ \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
+*/
+
+/*!
+ \class QAccessibleEditableTextInterface
+ \ingroup accessibility
+ \internal
+ \preliminary
+
+ \brief The QAccessibleEditableTextInterface class implements support for
+ the IAccessibleEditableText interface.
+
+ \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
+*/
+
+/*!
+ \class QAccessibleSimpleEditableTextInterface
+ \ingroup accessibility
+ \internal
+ \preliminary
+
+ \brief The QAccessibleSimpleEditableTextInterface class is a convenience class for
+ text-based widgets.
+
+ \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
+*/
+
+/*!
+ \class QAccessibleValueInterface
+ \ingroup accessibility
+ \internal
+ \preliminary
+
+ \brief The QAccessibleValueInterface class implements support for
+ the IAccessibleValue interface.
+
+ \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
+*/
+
+/*!
+ \class QAccessibleActionInterface
+ \ingroup accessibility
+ \internal
+ \preliminary
+
+ \brief The QAccessibleActionInterface class implements support for
+ the IAccessibleAction interface.
+
+ \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
+*/
+
+/*!
+ \class QAccessibleImageInterface
+ \ingroup accessibility
+ \internal
+ \preliminary
+
+ \brief The QAccessibleImageInterface class implements support for
+ the IAccessibleImage interface.
+
+ \link http://www.linux-foundation.org/en/Accessibility/IAccessible2 IAccessible2 Specification \endlink
+*/
+
+QAccessibleSimpleEditableTextInterface::QAccessibleSimpleEditableTextInterface(
+ QAccessibleInterface *accessibleInterface)
+ : iface(accessibleInterface)
+{
+ Q_ASSERT(iface);
+}
+
+#ifndef QT_NO_CLIPBOARD
+static QString textForRange(QAccessibleInterface *iface, int startOffset, int endOffset)
+{
+ return iface->text(QAccessible::Value, 0).mid(startOffset, endOffset - startOffset);
+}
+#endif
+
+void QAccessibleSimpleEditableTextInterface::copyText(int startOffset, int endOffset)
+{
+#ifdef QT_NO_CLIPBOARD
+ Q_UNUSED(startOffset);
+ Q_UNUSED(endOffset);
+#else
+ QApplication::clipboard()->setText(textForRange(iface, startOffset, endOffset));
+#endif
+}
+
+void QAccessibleSimpleEditableTextInterface::deleteText(int startOffset, int endOffset)
+{
+ QString txt = iface->text(QAccessible::Value, 0);
+ txt.remove(startOffset, endOffset - startOffset);
+ iface->setText(QAccessible::Value, 0, txt);
+}
+
+void QAccessibleSimpleEditableTextInterface::insertText(int offset, const QString &text)
+{
+ QString txt = iface->text(QAccessible::Value, 0);
+ txt.insert(offset, text);
+ iface->setText(QAccessible::Value, 0, txt);
+}
+
+void QAccessibleSimpleEditableTextInterface::cutText(int startOffset, int endOffset)
+{
+#ifdef QT_NO_CLIPBOARD
+ Q_UNUSED(startOffset);
+ Q_UNUSED(endOffset);
+#else
+ QString sub = textForRange(iface, startOffset, endOffset);
+ deleteText(startOffset, endOffset);
+ QApplication::clipboard()->setText(sub);
+#endif
+}
+
+void QAccessibleSimpleEditableTextInterface::pasteText(int offset)
+{
+#ifdef QT_NO_CLIPBOARD
+ Q_UNUSED(offset);
+#else
+ QString txt = iface->text(QAccessible::Value, 0);
+ txt.insert(offset, QApplication::clipboard()->text());
+ iface->setText(QAccessible::Value, 0, txt);
+#endif
+}
+
+void QAccessibleSimpleEditableTextInterface::replaceText(int startOffset, int endOffset, const QString &text)
+{
+ QString txt = iface->text(QAccessible::Value, 0);
+ txt.replace(startOffset, endOffset - startOffset, text);
+ iface->setText(QAccessible::Value, 0, txt);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h
new file mode 100644
index 0000000000..65ab7166c6
--- /dev/null
+++ b/src/gui/accessible/qaccessible2.h
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLE2_H
+#define QACCESSIBLE2_H
+
+#include <QtGui/qaccessible.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACCESSIBILITY
+
+namespace QAccessible2
+{
+ enum CoordinateType
+ {
+ RelativeToScreen = 0,
+ RelativeToParent = 1
+ };
+
+ enum BoundaryType {
+ CharBoundary,
+ WordBoundary,
+ SentenceBoundary,
+ ParagraphBoundary,
+ LineBoundary,
+ NoBoundary
+ };
+}
+
+class Q_GUI_EXPORT QAccessible2Interface
+{
+public:
+ virtual ~QAccessible2Interface() {}
+};
+
+// catch-all functions. If an accessible class doesn't implement interface T, return 0
+inline QAccessible2Interface *qAccessibleValueCastHelper() { return 0; }
+inline QAccessible2Interface *qAccessibleTextCastHelper() { return 0; }
+inline QAccessible2Interface *qAccessibleEditableTextCastHelper() { return 0; }
+inline QAccessible2Interface *qAccessibleTableCastHelper() { return 0; }
+inline QAccessible2Interface *qAccessibleActionCastHelper() { return 0; }
+inline QAccessible2Interface *qAccessibleImageCastHelper() { return 0; }
+
+#define Q_ACCESSIBLE_OBJECT \
+ public: \
+ QAccessible2Interface *interface_cast(QAccessible2::InterfaceType t) \
+ { \
+ switch (t) { \
+ case QAccessible2::TextInterface: \
+ return qAccessibleTextCastHelper(); \
+ case QAccessible2::EditableTextInterface: \
+ return qAccessibleEditableTextCastHelper(); \
+ case QAccessible2::ValueInterface: \
+ return qAccessibleValueCastHelper(); \
+ case QAccessible2::TableInterface: \
+ return qAccessibleTableCastHelper(); \
+ case QAccessible2::ActionInterface: \
+ return qAccessibleActionCastHelper(); \
+ case QAccessible2::ImageInterface: \
+ return qAccessibleImageCastHelper(); \
+ } \
+ return 0; \
+ } \
+ private:
+
+class Q_GUI_EXPORT QAccessibleTextInterface: public QAccessible2Interface
+{
+public:
+ inline QAccessible2Interface *qAccessibleTextCastHelper() { return this; }
+
+ virtual ~QAccessibleTextInterface() {}
+
+ virtual void addSelection(int startOffset, int endOffset) = 0;
+ virtual QString attributes(int offset, int *startOffset, int *endOffset) = 0;
+ virtual int cursorPosition() = 0;
+ virtual QRect characterRect(int offset, QAccessible2::CoordinateType coordType) = 0;
+ virtual int selectionCount() = 0;
+ virtual int offsetAtPoint(const QPoint &point, QAccessible2::CoordinateType coordType) = 0;
+ virtual void selection(int selectionIndex, int *startOffset, int *endOffset) = 0;
+ virtual QString text(int startOffset, int endOffset) = 0;
+ virtual QString textBeforeOffset (int offset, QAccessible2::BoundaryType boundaryType,
+ int *startOffset, int *endOffset) = 0;
+ virtual QString textAfterOffset(int offset, QAccessible2::BoundaryType boundaryType,
+ int *startOffset, int *endOffset) = 0;
+ virtual QString textAtOffset(int offset, QAccessible2::BoundaryType boundaryType,
+ int *startOffset, int *endOffset) = 0;
+ virtual void removeSelection(int selectionIndex) = 0;
+ virtual void setCursorPosition(int position) = 0;
+ virtual void setSelection(int selectionIndex, int startOffset, int endOffset) = 0;
+ virtual int characterCount() = 0;
+ virtual void scrollToSubstring(int startIndex, int endIndex) = 0;
+};
+
+class Q_GUI_EXPORT QAccessibleEditableTextInterface: public QAccessible2Interface
+{
+public:
+ inline QAccessible2Interface *qAccessibleEditableTextCastHelper() { return this; }
+
+ virtual ~QAccessibleEditableTextInterface() {}
+
+ virtual void copyText(int startOffset, int endOffset) = 0;
+ virtual void deleteText(int startOffset, int endOffset) = 0;
+ virtual void insertText(int offset, const QString &text) = 0;
+ virtual void cutText(int startOffset, int endOffset) = 0;
+ virtual void pasteText(int offset) = 0;
+ virtual void replaceText(int startOffset, int endOffset, const QString &text) = 0;
+ virtual void setAttributes(int startOffset, int endOffset, const QString &attributes) = 0;
+};
+
+class Q_GUI_EXPORT QAccessibleSimpleEditableTextInterface: public QAccessibleEditableTextInterface
+{
+public:
+ QAccessibleSimpleEditableTextInterface(QAccessibleInterface *accessibleInterface);
+
+ void copyText(int startOffset, int endOffset);
+ void deleteText(int startOffset, int endOffset);
+ void insertText(int offset, const QString &text);
+ void cutText(int startOffset, int endOffset);
+ void pasteText(int offset);
+ void replaceText(int startOffset, int endOffset, const QString &text);
+ inline void setAttributes(int, int, const QString &) {}
+
+private:
+ QAccessibleInterface *iface;
+};
+
+class Q_GUI_EXPORT QAccessibleValueInterface: public QAccessible2Interface
+{
+public:
+ inline QAccessible2Interface *qAccessibleValueCastHelper() { return this; }
+
+ virtual ~QAccessibleValueInterface() {}
+
+ virtual QVariant currentValue() = 0;
+ virtual void setCurrentValue(const QVariant &value) = 0;
+ virtual QVariant maximumValue() = 0;
+ virtual QVariant minimumValue() = 0;
+};
+
+class Q_GUI_EXPORT QAccessibleTableInterface: public QAccessible2Interface
+{
+public:
+ inline QAccessible2Interface *qAccessibleTableCastHelper() { return this; }
+
+ virtual QAccessibleInterface *accessibleAt(int row, int column) = 0;
+ virtual QAccessibleInterface *caption() = 0;
+ virtual int childIndex(int rowIndex, int columnIndex) = 0;
+ virtual QString columnDescription(int column) = 0;
+ virtual int columnSpan(int row, int column) = 0;
+ virtual QAccessibleInterface *columnHeader() = 0;
+ virtual int columnIndex(int childIndex) = 0;
+ virtual int columnCount() = 0;
+ virtual int rowCount() = 0;
+ virtual int selectedColumnCount() = 0;
+ virtual int selectedRowCount() = 0;
+ virtual QString rowDescription(int row) = 0;
+ virtual int rowSpan(int row, int column) = 0;
+ virtual QAccessibleInterface *rowHeader() = 0;
+ virtual int rowIndex(int childIndex) = 0;
+ virtual int selectedRows(int maxRows, QList<int> *rows) = 0;
+ virtual int selectedColumns(int maxColumns, QList<int> *columns) = 0;
+ virtual QAccessibleInterface *summary() = 0;
+ virtual bool isColumnSelected(int column) = 0;
+ virtual bool isRowSelected(int row) = 0;
+ virtual bool isSelected(int row, int column) = 0;
+ virtual void selectRow(int row) = 0;
+ virtual void selectColumn(int column) = 0;
+ virtual void unselectRow(int row) = 0;
+ virtual void unselectColumn(int column) = 0;
+ virtual void cellAtIndex(int index, int *row, int *column, int *rowSpan,
+ int *columnSpan, bool *isSelected) = 0;
+};
+
+class Q_GUI_EXPORT QAccessibleActionInterface : public QAccessible2Interface
+{
+public:
+ inline QAccessible2Interface *qAccessibleActionCastHelper() { return this; }
+
+ virtual int actionCount() = 0;
+ virtual void doAction(int actionIndex) = 0;
+ virtual QString description(int actionIndex) = 0;
+ virtual QString name(int actionIndex) = 0;
+ virtual QString localizedName(int actionIndex) = 0;
+ virtual QStringList keyBindings(int actionIndex) = 0;
+};
+
+class Q_GUI_EXPORT QAccessibleImageInterface : public QAccessible2Interface
+{
+public:
+ inline QAccessible2Interface *qAccessibleImageCastHelper() { return this; }
+
+ virtual QString imageDescription() = 0;
+ virtual QSize imageSize() = 0;
+ virtual QRect imagePosition(QAccessible2::CoordinateType coordType) = 0;
+};
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/accessible/qaccessible_mac.mm b/src/gui/accessible/qaccessible_mac.mm
new file mode 100644
index 0000000000..d01c1c9733
--- /dev/null
+++ b/src/gui/accessible/qaccessible_mac.mm
@@ -0,0 +1,2469 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessible.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+#include "qaccessible_mac_p.h"
+#include "qhash.h"
+#include "qset.h"
+#include "qpointer.h"
+#include "qapplication.h"
+#include "qmainwindow.h"
+#include "qtextdocument.h"
+#include "qdebug.h"
+#include "qabstractslider.h"
+#include "qsplitter.h"
+#include "qtabwidget.h"
+#include "qlistview.h"
+#include "qtableview.h"
+#include "qdockwidget.h"
+
+#include <private/qt_mac_p.h>
+#include <private/qwidget_p.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Set up platform defines. There is a one-to-one correspondence between the
+ Carbon and Cocoa roles and attributes, but the prefix and type changes.
+*/
+#ifdef QT_MAC_USE_COCOA
+typedef NSString * const QAXRoleType;
+#define QAXApplicationRole NSAccessibilityApplicationRole
+#define QAXButtonRole NSAccessibilityButtonRole
+#define QAXCancelAction NSAccessibilityCancelAction
+#define QAXCheckBoxRole NSAccessibilityCheckBoxRole
+#define QAXChildrenAttribute NSAccessibilityChildrenAttribute
+#define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute
+#define QAXCloseButtonAttribute NSAccessibilityCloseButtonAttribute
+#define QAXColumnRole NSAccessibilityColumnRole
+#define QAXConfirmAction NSAccessibilityConfirmAction
+#define QAXContentsAttribute NSAccessibilityContentsAttribute
+#define QAXDecrementAction NSAccessibilityDecrementAction
+#define QAXDecrementArrowSubrole NSAccessibilityDecrementArrowSubrole
+#define QAXDecrementPageSubrole NSAccessibilityDecrementPageSubrole
+#define QAXDescriptionAttribute NSAccessibilityDescriptionAttribute
+#define QAXEnabledAttribute NSAccessibilityEnabledAttribute
+#define QAXExpandedAttribute NSAccessibilityExpandedAttribute
+#define QAXFocusedAttribute NSAccessibilityFocusedAttribute
+#define QAXFocusedUIElementChangedNotification NSAccessibilityFocusedUIElementChangedNotification
+#define QAXFocusedWindowChangedNotification NSAccessibilityFocusedWindowChangedNotification
+#define QAXGroupRole NSAccessibilityGroupRole
+#define QAXGrowAreaAttribute NSAccessibilityGrowAreaAttribute
+#define QAXGrowAreaRole NSAccessibilityGrowAreaRole
+#define QAXHelpAttribute NSAccessibilityHelpAttribute
+#define QAXHorizontalOrientationValue NSAccessibilityHorizontalOrientationValue
+#define QAXHorizontalScrollBarAttribute NSAccessibilityHorizontalScrollBarAttribute
+#define QAXIncrementAction NSAccessibilityIncrementAction
+#define QAXIncrementArrowSubrole NSAccessibilityIncrementArrowSubrole
+#define QAXIncrementPageSubrole NSAccessibilityIncrementPageSubrole
+#define QAXIncrementorRole NSAccessibilityIncrementorRole
+#define QAXLinkedUIElementsAttribute NSAccessibilityLinkedUIElementsAttribute
+#define QAXListRole NSAccessibilityListRole
+#define QAXMainAttribute NSAccessibilityMainAttribute
+#define QAXMaxValueAttribute NSAccessibilityMaxValueAttribute
+#define QAXMenuBarRole NSAccessibilityMenuBarRole
+#define QAXMenuButtonRole NSAccessibilityMenuButtonRole
+#define QAXMenuClosedNotification NSAccessibilityMenuClosedNotification
+#define QAXMenuItemRole NSAccessibilityMenuItemRole
+#define QAXMenuOpenedNotification NSAccessibilityMenuOpenedNotification
+#define QAXMenuRole NSAccessibilityMenuRole
+#define QAXMinValueAttribute NSAccessibilityMinValueAttribute
+#define QAXMinimizeButtonAttribute NSAccessibilityMinimizeButtonAttribute
+#define QAXMinimizedAttribute NSAccessibilityMinimizedAttribute
+#define QAXNextContentsAttribute NSAccessibilityNextContentsAttribute
+#define QAXOrientationAttribute NSAccessibilityOrientationAttribute
+#define QAXParentAttribute NSAccessibilityParentAttribute
+#define QAXPickAction NSAccessibilityPickAction
+#define QAXPopUpButtonRole NSAccessibilityPopUpButtonRole
+#define QAXPositionAttribute NSAccessibilityPositionAttribute
+#define QAXPressAction NSAccessibilityPressAction
+#define QAXPreviousContentsAttribute NSAccessibilityPreviousContentsAttribute
+#define QAXProgressIndicatorRole NSAccessibilityProgressIndicatorRole
+#define QAXRadioButtonRole NSAccessibilityRadioButtonRole
+#define QAXRoleAttribute NSAccessibilityRoleAttribute
+#define QAXRoleDescriptionAttribute NSAccessibilityRoleDescriptionAttribute
+#define QAXRowRole NSAccessibilityRowRole
+#define QAXRowsAttribute NSAccessibilityRowsAttribute
+#define QAXScrollAreaRole NSAccessibilityScrollAreaRole
+#define QAXScrollBarRole NSAccessibilityScrollBarRole
+#define QAXSelectedAttribute NSAccessibilitySelectedAttribute
+#define QAXSelectedChildrenAttribute NSAccessibilitySelectedChildrenAttribute
+#define QAXSelectedRowsAttribute NSAccessibilitySelectedRowsAttribute
+#define QAXSizeAttribute NSAccessibilitySizeAttribute
+#define QAXSliderRole NSAccessibilitySliderRole
+#define QAXSplitGroupRole NSAccessibilitySplitGroupRole
+#define QAXSplitterRole NSAccessibilitySplitterRole
+#define QAXSplittersAttribute NSAccessibilitySplittersAttribute
+#define QAXStaticTextRole NSAccessibilityStaticTextRole
+#define QAXSubroleAttribute NSAccessibilitySubroleAttribute
+#define QAXSubroleAttribute NSAccessibilitySubroleAttribute
+#define QAXTabGroupRole NSAccessibilityTabGroupRole
+#define QAXTableRole NSAccessibilityTableRole
+#define QAXTabsAttribute NSAccessibilityTabsAttribute
+#define QAXTextFieldRole NSAccessibilityTextFieldRole
+#define QAXTitleAttribute NSAccessibilityTitleAttribute
+#define QAXTitleUIElementAttribute NSAccessibilityTitleUIElementAttribute
+#define QAXToolbarButtonAttribute NSAccessibilityToolbarButtonAttribute
+#define QAXToolbarRole NSAccessibilityToolbarRole
+#define QAXTopLevelUIElementAttribute NSAccessibilityTopLevelUIElementAttribute
+#define QAXUnknownRole NSAccessibilityUnknownRole
+#define QAXValueAttribute NSAccessibilityValueAttribute
+#define QAXValueChangedNotification NSAccessibilityValueChangedNotification
+#define QAXValueIndicatorRole NSAccessibilityValueIndicatorRole
+#define QAXVerticalOrientationValue NSAccessibilityVerticalOrientationValue
+#define QAXVerticalScrollBarAttribute NSAccessibilityVerticalScrollBarAttribute
+#define QAXVisibleRowsAttribute NSAccessibilityVisibleRowsAttribute
+#define QAXWindowAttribute NSAccessibilityWindowAttribute
+#define QAXWindowCreatedNotification NSAccessibilityWindowCreatedNotification
+#define QAXWindowMovedNotification NSAccessibilityWindowMovedNotification
+#define QAXWindowRole NSAccessibilityWindowRole
+#define QAXZoomButtonAttribute NSAccessibilityZoomButtonAttribute
+#else
+typedef CFStringRef const QAXRoleType;
+#define QAXApplicationRole kAXApplicationRole
+#define QAXButtonRole kAXButtonRole
+#define QAXCancelAction kAXCancelAction
+#define QAXCheckBoxRole kAXCheckBoxRole
+#define QAXChildrenAttribute kAXChildrenAttribute
+#define QAXCloseButtonAttribute kAXCloseButtonAttribute
+#define QAXColumnRole kAXColumnRole
+#define QAXConfirmAction kAXConfirmAction
+#define QAXContentsAttribute kAXContentsAttribute
+#define QAXDecrementAction kAXDecrementAction
+#define QAXDecrementArrowSubrole kAXDecrementArrowSubrole
+#define QAXDecrementPageSubrole kAXDecrementPageSubrole
+#define QAXDescriptionAttribute kAXDescriptionAttribute
+#define QAXEnabledAttribute kAXEnabledAttribute
+#define QAXExpandedAttribute kAXExpandedAttribute
+#define QAXFocusedAttribute kAXFocusedAttribute
+#define QAXFocusedUIElementChangedNotification kAXFocusedUIElementChangedNotification
+#define QAXFocusedWindowChangedNotification kAXFocusedWindowChangedNotification
+#define QAXGroupRole kAXGroupRole
+#define QAXGrowAreaAttribute kAXGrowAreaAttribute
+#define QAXGrowAreaRole kAXGrowAreaRole
+#define QAXHelpAttribute kAXHelpAttribute
+#define QAXHorizontalOrientationValue kAXHorizontalOrientationValue
+#define QAXHorizontalScrollBarAttribute kAXHorizontalScrollBarAttribute
+#define QAXIncrementAction kAXIncrementAction
+#define QAXIncrementArrowSubrole kAXIncrementArrowSubrole
+#define QAXIncrementPageSubrole kAXIncrementPageSubrole
+#define QAXIncrementorRole kAXIncrementorRole
+#define QAXLinkedUIElementsAttribute kAXLinkedUIElementsAttribute
+#define QAXListRole kAXListRole
+#define QAXMainAttribute kAXMainAttribute
+#define QAXMaxValueAttribute kAXMaxValueAttribute
+#define QAXMenuBarRole kAXMenuBarRole
+#define QAXMenuButtonRole kAXMenuButtonRole
+#define QAXMenuClosedNotification kAXMenuClosedNotification
+#define QAXMenuItemRole kAXMenuItemRole
+#define QAXMenuOpenedNotification kAXMenuOpenedNotification
+#define QAXMenuRole kAXMenuRole
+#define QAXMinValueAttribute kAXMinValueAttribute
+#define QAXMinimizeButtonAttribute kAXMinimizeButtonAttribute
+#define QAXMinimizedAttribute kAXMinimizedAttribute
+#define QAXNextContentsAttribute kAXNextContentsAttribute
+#define QAXOrientationAttribute kAXOrientationAttribute
+#define QAXParentAttribute kAXParentAttribute
+#define QAXPickAction kAXPickAction
+#define QAXPopUpButtonRole kAXPopUpButtonRole
+#define QAXPositionAttribute kAXPositionAttribute
+#define QAXPressAction kAXPressAction
+#define QAXPreviousContentsAttribute kAXPreviousContentsAttribute
+#define QAXProgressIndicatorRole kAXProgressIndicatorRole
+#define QAXRadioButtonRole kAXRadioButtonRole
+#define QAXRoleAttribute kAXRoleAttribute
+#define QAXRoleDescriptionAttribute kAXRoleDescriptionAttribute
+#define QAXRowRole kAXRowRole
+#define QAXRowsAttribute kAXRowsAttribute
+#define QAXScrollAreaRole kAXScrollAreaRole
+#define QAXScrollBarRole kAXScrollBarRole
+#define QAXSelectedAttribute kAXSelectedAttribute
+#define QAXSelectedChildrenAttribute kAXSelectedChildrenAttribute
+#define QAXSelectedRowsAttribute kAXSelectedRowsAttribute
+#define QAXSizeAttribute kAXSizeAttribute
+#define QAXSliderRole kAXSliderRole
+#define QAXSplitGroupRole kAXSplitGroupRole
+#define QAXSplitterRole kAXSplitterRole
+#define QAXSplittersAttribute kAXSplittersAttribute
+#define QAXStaticTextRole kAXStaticTextRole
+#define QAXSubroleAttribute kAXSubroleAttribute
+#define QAXTabGroupRole kAXTabGroupRole
+#define QAXTableRole kAXTableRole
+#define QAXTabsAttribute kAXTabsAttribute
+#define QAXTextFieldRole kAXTextFieldRole
+#define QAXTitleAttribute kAXTitleAttribute
+#define QAXTitleUIElementAttribute kAXTitleUIElementAttribute
+#define QAXToolbarButtonAttribute kAXToolbarButtonAttribute
+#define QAXToolbarRole kAXToolbarRole
+#define QAXTopLevelUIElementAttribute kAXTopLevelUIElementAttribute
+#define QAXUnknownRole kAXUnknownRole
+#define QAXValueAttribute kAXValueAttribute
+#define QAXValueChangedNotification kAXValueChangedNotification
+#define QAXValueIndicatorRole kAXValueIndicatorRole
+#define QAXVerticalOrientationValue kAXVerticalOrientationValue
+#define QAXVerticalScrollBarAttribute kAXVerticalScrollBarAttribute
+#define QAXVisibleRowsAttribute kAXVisibleRowsAttribute
+#define QAXWindowAttribute kAXWindowAttribute
+#define QAXWindowCreatedNotification kAXWindowCreatedNotification
+#define QAXWindowMovedNotification kAXWindowMovedNotification
+#define QAXWindowRole kAXWindowRole
+#define QAXZoomButtonAttribute kAXZoomButtonAttribute
+#endif
+
+
+/*****************************************************************************
+ Externals
+ *****************************************************************************/
+extern bool qt_mac_is_macsheet(const QWidget *w); //qwidget_mac.cpp
+extern bool qt_mac_is_macdrawer(const QWidget *w); //qwidget_mac.cpp
+
+/*****************************************************************************
+ QAccessible Bindings
+ *****************************************************************************/
+//hardcoded bindings between control info and (known) QWidgets
+struct QAccessibleTextBinding {
+ int qt;
+ QAXRoleType mac;
+ bool settable;
+} text_bindings[][10] = {
+ { { QAccessible::MenuItem, QAXMenuItemRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::MenuBar, QAXMenuBarRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ScrollBar, QAXScrollBarRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Grip, QAXGrowAreaRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Window, QAXWindowRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Dialog, QAXWindowRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::AlertMessage, QAXWindowRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ToolTip, QAXWindowRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::HelpBalloon, QAXWindowRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::PopupMenu, QAXMenuRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Application, QAXApplicationRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Pane, QAXGroupRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Grouping, QAXGroupRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Separator, QAXSplitterRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ToolBar, QAXToolbarRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::PageTab, QAXRadioButtonRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ButtonMenu, QAXMenuButtonRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ButtonDropDown, QAXPopUpButtonRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::SpinBox, QAXIncrementorRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Slider, QAXSliderRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ProgressBar, QAXProgressIndicatorRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ComboBox, QAXPopUpButtonRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::RadioButton, QAXRadioButtonRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::CheckBox, QAXCheckBoxRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::StaticText, QAXStaticTextRole, false },
+ { QAccessible::Name, QAXValueAttribute, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Table, QAXTableRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::StatusBar, QAXStaticTextRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Column, QAXColumnRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ColumnHeader, QAXColumnRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Row, QAXRowRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::RowHeader, QAXRowRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Cell, QAXTextFieldRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::PushButton, QAXButtonRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::EditableText, QAXTextFieldRole, true },
+ { -1, 0, false }
+ },
+ { { QAccessible::Link, QAXTextFieldRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Indicator, QAXValueIndicatorRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Splitter, QAXSplitGroupRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::List, QAXListRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::ListItem, QAXStaticTextRole, false },
+ { -1, 0, false }
+ },
+ { { QAccessible::Cell, QAXStaticTextRole, false },
+ { -1, 0, false }
+ },
+ { { -1, 0, false } }
+};
+
+class QAInterface;
+static CFStringRef macRole(const QAInterface &interface);
+
+QDebug operator<<(QDebug debug, const QAInterface &interface)
+{
+ if (interface.isValid() == false)
+ debug << "invalid interface";
+ else
+ debug << interface.object() << "id" << interface.id() << "role" << hex << interface.role();
+ return debug;
+}
+
+// The root of the Qt accessible hiearchy.
+static QObject *rootObject = 0;
+
+
+bool QAInterface::operator==(const QAInterface &other) const
+{
+ if (isValid() == false || other.isValid() == false)
+ return (isValid() && other.isValid());
+
+ // walk up the parent chain, comparing child indexes, until we reach
+ // an interface that has a QObject.
+ QAInterface currentThis = *this;
+ QAInterface currentOther = other;
+
+ while (currentThis.object() == 0) {
+ if (currentOther.object() != 0)
+ return false;
+
+ // fail if the child indexes in the two hirearchies don't match.
+ if (currentThis.parent().indexOfChild(currentThis) !=
+ currentOther.parent().indexOfChild(currentOther))
+ return false;
+
+ currentThis = currentThis.parent();
+ currentOther = currentOther.parent();
+ }
+
+ return (currentThis.object() == currentOther.object() && currentThis.id() == currentOther.id());
+}
+
+bool QAInterface::operator!=(const QAInterface &other) const
+{
+ return !operator==(other);
+}
+
+uint qHash(const QAInterface &item)
+{
+ if (item.isValid())
+ return qHash(item.object()) + qHash(item.id());
+ else
+ return qHash(item.cachedObject()) + qHash(item.id());
+}
+
+QAInterface QAInterface::navigate(RelationFlag relation, int entry) const
+{
+ if (!checkValid())
+ return QAInterface();
+
+ // On a QAccessibleInterface that handles its own children we can short-circut
+ // the navigation if this QAInterface refers to one of the children:
+ if (child != 0) {
+ // The Ancestor interface will always be the same QAccessibleInterface with
+ // a child value of 0.
+ if (relation == QAccessible::Ancestor)
+ return QAInterface(*this, 0);
+
+ // The child hiearchy is only one level deep, so navigating to a child
+ // of a child is not possible.
+ if (relation == QAccessible::Child) {
+ return QAInterface();
+ }
+ }
+ QAccessibleInterface *child_iface = 0;
+
+ const int status = base.interface->navigate(relation, entry, &child_iface);
+
+ if (status == -1)
+ return QAInterface(); // not found;
+
+ // Check if target is a child of this interface.
+ if (!child_iface) {
+ return QAInterface(*this, status);
+ } else {
+ // Target is child_iface or a child of that (status decides).
+ return QAInterface(child_iface, status);
+ }
+}
+
+QAElement::QAElement()
+:elementRef(0)
+{}
+
+QAElement::QAElement(AXUIElementRef elementRef)
+:elementRef(elementRef)
+{
+ if (elementRef != 0) {
+ CFRetain(elementRef);
+ CFRetain(object());
+ }
+}
+
+QAElement::QAElement(const QAElement &element)
+:elementRef(element.elementRef)
+{
+ if (elementRef != 0) {
+ CFRetain(elementRef);
+ CFRetain(object());
+ }
+}
+
+QAElement::QAElement(HIObjectRef object, int child)
+{
+#ifndef QT_MAC_USE_COCOA
+ if (object == 0) {
+ elementRef = 0; // Create invalid QAElement.
+ } else {
+ elementRef = AXUIElementCreateWithHIObjectAndIdentifier(object, child);
+ CFRetain(object);
+ }
+#else
+ Q_UNUSED(object);
+ Q_UNUSED(child);
+#endif
+}
+
+QAElement::~QAElement()
+{
+ if (elementRef != 0) {
+ CFRelease(object());
+ CFRelease(elementRef);
+ }
+}
+
+void QAElement::operator=(const QAElement &other)
+{
+ if (*this == other)
+ return;
+
+ if (elementRef != 0) {
+ CFRelease(object());
+ CFRelease(elementRef);
+ }
+
+ elementRef = other.elementRef;
+
+ if (elementRef != 0) {
+ CFRetain(elementRef);
+ CFRetain(object());
+ }
+}
+
+bool QAElement::operator==(const QAElement &other) const
+{
+ if (elementRef == 0 || other.elementRef == 0)
+ return (elementRef == other.elementRef);
+
+ return CFEqual(elementRef, other.elementRef);
+}
+
+uint qHash(QAElement element)
+{
+ return qHash(element.object()) + qHash(element.id());
+}
+
+#ifndef QT_MAC_USE_COCOA
+static QInterfaceFactory *createFactory(const QAInterface &interface);
+#endif
+Q_GLOBAL_STATIC(QAccessibleHierarchyManager, accessibleHierarchyManager);
+
+/*
+ Reomves all accessibility info accosiated with the sender object.
+*/
+void QAccessibleHierarchyManager::objectDestroyed(QObject *object)
+{
+ HIObjectRef hiObject = qobjectHiobjectHash.value(object);
+ delete qobjectElementHash.value(object);
+ qobjectElementHash.remove(object);
+ hiobjectInterfaceHash.remove(hiObject);
+}
+
+/*
+ Removes all stored items.
+*/
+void QAccessibleHierarchyManager::reset()
+{
+ qDeleteAll(qobjectElementHash);
+ qobjectElementHash.clear();
+ hiobjectInterfaceHash.clear();
+ qobjectHiobjectHash.clear();
+}
+
+QAccessibleHierarchyManager *QAccessibleHierarchyManager::instance()
+{
+ return accessibleHierarchyManager();
+}
+
+#ifndef QT_MAC_USE_COCOA
+static bool isItemView(const QAInterface &interface)
+{
+ QObject *object = interface.object();
+ return (interface.role() == QAccessible::List || interface.role() == QAccessible::Table
+ || (object && qobject_cast<QAbstractItemView *>(interface.object()))
+ || (object && object->objectName() == QLatin1String("qt_scrollarea_viewport")
+ && qobject_cast<QAbstractItemView *>(object->parent())));
+}
+#endif
+
+static bool isTabWidget(const QAInterface &interface)
+{
+ if (QObject *object = interface.object())
+ return (object->inherits("QTabWidget") && interface.id() == 0);
+ return false;
+}
+
+static bool isStandaloneTabBar(const QAInterface &interface)
+{
+ QObject *object = interface.object();
+ if (interface.role() == QAccessible::PageTabList && object)
+ return (qobject_cast<QTabWidget *>(object->parent()) == 0);
+
+ return false;
+}
+
+static bool isEmbeddedTabBar(const QAInterface &interface)
+{
+ QObject *object = interface.object();
+ if (interface.role() == QAccessible::PageTabList && object)
+ return (qobject_cast<QTabWidget *>(object->parent()));
+
+ return false;
+}
+
+/*
+ Decides if a QAInterface is interesting from an accessibility users point of view.
+*/
+bool isItInteresting(const QAInterface &interface)
+{
+ // Mac accessibility does not have an attribute that corresponds to the Invisible/Offscreen
+ // state, so we disable the interface here.
+ const QAccessible::State state = interface.state();
+ if (state & QAccessible::Invisible ||
+ state & QAccessible::Offscreen )
+ return false;
+
+ const QAccessible::Role role = interface.role();
+
+ if (QObject * const object = interface.object()) {
+ const QString className = QLatin1String(object->metaObject()->className());
+
+ // VoiceOver focusing on tool tips can be confusing. The contents of the
+ // tool tip is avalible through the description attribute anyway, so
+ // we disable accessibility for tool tips.
+ if (className == QLatin1String("QTipLabel"))
+ return false;
+
+ // Hide TabBars that has a QTabWidget parent (the tab widget handles the accessibility)
+ if (isEmbeddedTabBar(interface))
+ return false;
+
+ // Hide docked dockwidgets. ### causes infinitie loop in the apple accessibility code.
+ /* if (QDockWidget *dockWidget = qobject_cast<QDockWidget *>(object)) {
+ if (dockWidget->isFloating() == false)
+ return false;
+ }
+ */
+ }
+
+ // Client is a generic role returned by plain QWidgets or other
+ // widgets that does not have separate QAccessible interface, such
+ // as the TabWidget. Return false unless macRole gives the interface
+ // a special role.
+ if (role == QAccessible::Client && macRole(interface) == CFStringRef(QAXUnknownRole))
+ return false;
+
+ // Some roles are not interesting:
+ if (role == QAccessible::Border || // QFrame
+ role == QAccessible::Application || // We use the system-provided application element.
+ role == QAccessible::MenuItem) // The system also provides the menu items.
+ return false;
+
+ // It is probably better to access the toolbar buttons directly than having
+ // to navigate through the toolbar.
+ if (role == QAccessible::ToolBar)
+ return false;
+
+ return true;
+}
+
+QAElement QAccessibleHierarchyManager::registerInterface(QObject *object, int child)
+{
+#ifndef QT_MAC_USE_COCOA
+ return registerInterface(QAInterface(QAccessible::queryAccessibleInterface(object), child));
+#else
+ Q_UNUSED(object);
+ Q_UNUSED(child);
+ return QAElement();
+#endif
+}
+
+/*
+ Creates a QAXUIelement that corresponds to the given QAInterface.
+*/
+QAElement QAccessibleHierarchyManager::registerInterface(const QAInterface &interface)
+{
+#ifndef QT_MAC_USE_COCOA
+ if (interface.isValid() == false)
+ return QAElement();
+ QAInterface objectInterface = interface.objectInterface();
+
+ QObject * qobject = objectInterface.object();
+ HIObjectRef hiobject = objectInterface.hiObject();
+ if (qobject == 0 || hiobject == 0)
+ return QAElement();
+
+ if (qobjectElementHash.contains(qobject) == false) {
+ registerInterface(qobject, hiobject, createFactory(interface));
+ HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(interface));
+ }
+
+ return QAElement(hiobject, interface.id());
+#else
+ Q_UNUSED(interface);
+ return QAElement();
+#endif
+}
+
+#ifndef QT_MAC_USE_COCOA
+#include "qaccessible_mac_carbon.cpp"
+#endif
+
+void QAccessibleHierarchyManager::registerInterface(QObject * qobject, HIObjectRef hiobject, QInterfaceFactory *interfaceFactory)
+{
+#ifndef QT_MAC_USE_COCOA
+ if (qobjectElementHash.contains(qobject) == false) {
+ qobjectElementHash.insert(qobject, interfaceFactory);
+ qobjectHiobjectHash.insert(qobject, hiobject);
+ connect(qobject, SIGNAL(destroyed(QObject *)), SLOT(objectDestroyed(QObject *)));
+ }
+
+ if (hiobjectInterfaceHash.contains(hiobject) == false) {
+ hiobjectInterfaceHash.insert(hiobject, interfaceFactory);
+ installAcessibilityEventHandler(hiobject);
+ }
+#else
+ Q_UNUSED(qobject);
+ Q_UNUSED(hiobject);
+ Q_UNUSED(interfaceFactory);
+#endif
+}
+
+void QAccessibleHierarchyManager::registerChildren(const QAInterface &interface)
+{
+ QObject * const object = interface.object();
+ if (object == 0)
+ return;
+
+ QInterfaceFactory *interfaceFactory = qobjectElementHash.value(object);
+
+ if (interfaceFactory == 0)
+ return;
+
+ interfaceFactory->registerChildren();
+}
+
+QAInterface QAccessibleHierarchyManager::lookup(const AXUIElementRef &element)
+{
+ if (element == 0)
+ return QAInterface();
+#ifndef QT_MAC_USE_COCOA
+ HIObjectRef hiObject = AXUIElementGetHIObject(element);
+
+ QInterfaceFactory *factory = hiobjectInterfaceHash.value(hiObject);
+ if (factory == 0) {
+ return QAInterface();
+ }
+
+ UInt64 id;
+ AXUIElementGetIdentifier(element, &id);
+ return factory->interface(id);
+#else
+ return QAInterface();
+#endif
+}
+
+QAInterface QAccessibleHierarchyManager::lookup(const QAElement &element)
+{
+ return lookup(element.element());
+}
+
+QAElement QAccessibleHierarchyManager::lookup(const QAInterface &interface)
+{
+ if (interface.isValid() == false)
+ return QAElement();
+
+ QInterfaceFactory *factory = qobjectElementHash.value(interface.objectInterface().object());
+ if (factory == 0)
+ return QAElement();
+
+ return factory->element(interface);
+}
+
+QAElement QAccessibleHierarchyManager::lookup(QObject * const object, int id)
+{
+ QInterfaceFactory *factory = qobjectElementHash.value(object);
+ if (factory == 0)
+ return QAElement();
+
+ return factory->element(id);
+}
+
+/*
+ Standard interface mapping, return the stored interface
+ or HIObjectRef, and there is an one-to-one mapping between
+ the identifier and child.
+*/
+class QStandardInterfaceFactory : public QInterfaceFactory
+{
+public:
+ QStandardInterfaceFactory(const QAInterface &interface)
+ : m_interface(interface), object(interface.hiObject())
+ {
+ CFRetain(object);
+ }
+
+ ~QStandardInterfaceFactory()
+ {
+ CFRelease(object);
+ }
+
+
+ QAInterface interface(UInt64 identifier)
+ {
+ const int child = identifier;
+ return QAInterface(m_interface, child);
+ }
+
+ QAElement element(int id)
+ {
+ return QAElement(object, id);
+ }
+
+ QAElement element(const QAInterface &interface)
+ {
+ if (interface.object() == 0)
+ return QAElement();
+ return QAElement(object, interface.id());
+ }
+
+ void registerChildren()
+ {
+ const int childCount = m_interface.childCount();
+ for (int i = 1; i <= childCount; ++i) {
+ accessibleHierarchyManager()->registerInterface(m_interface.navigate(QAccessible::Child, i));
+ }
+ }
+
+private:
+ QAInterface m_interface;
+ HIObjectRef object;
+};
+
+/*
+ Interface mapping where that creates one HIObject for each interface child.
+*/
+class QMultipleHIObjectFactory : public QInterfaceFactory
+{
+public:
+ QMultipleHIObjectFactory(const QAInterface &interface)
+ : m_interface(interface)
+ { }
+
+ ~QMultipleHIObjectFactory()
+ {
+ foreach (HIObjectRef object, objects) {
+ CFRelease(object);
+ }
+ }
+
+ QAInterface interface(UInt64 identifier)
+ {
+ const int child = identifier;
+ return QAInterface(m_interface, child);
+ }
+
+ QAElement element(int child)
+ {
+ if (child == 0)
+ return QAElement(m_interface.hiObject(), 0);
+
+ if (child > objects.count())
+ return QAElement();
+
+ return QAElement(objects.at(child - 1), child);
+ }
+
+ void registerChildren()
+ {
+#ifndef QT_MAC_USE_COCOA
+ const int childCount = m_interface.childCount();
+ for (int i = 1; i <= childCount; ++i) {
+ HIObjectRef hiobject;
+ HIObjectCreate(kObjectQtAccessibility, 0, &hiobject);
+ objects.append(hiobject);
+ accessibleHierarchyManager()->registerInterface(m_interface.object(), hiobject, this);
+ HIObjectSetAccessibilityIgnored(hiobject, !isItInteresting(m_interface.navigate(QAccessible::Child, i)));
+ }
+#endif
+ }
+
+private:
+ QAInterface m_interface;
+ QList<HIObjectRef> objects;
+};
+
+class QItemViewInterfaceFactory : public QInterfaceFactory
+{
+public:
+ QItemViewInterfaceFactory(const QAInterface &interface)
+ : m_interface(interface), object(interface.hiObject())
+ {
+ CFRetain(object);
+ columnCount = 0;
+ if (QTableView * tableView = qobject_cast<QTableView *>(interface.parent().object())) {
+ if (tableView->model())
+ columnCount = tableView->model()->columnCount();
+ if (tableView->verticalHeader())
+ ++columnCount;
+ }
+ }
+
+ ~QItemViewInterfaceFactory()
+ {
+ CFRelease(object);
+ }
+
+ QAInterface interface(UInt64 identifier)
+ {
+ if (identifier == 0)
+ return m_interface;
+
+ if (m_interface.role() == QAccessible::List)
+ return m_interface.childAt(identifier);
+
+ if (m_interface.role() == QAccessible::Table) {
+ const int index = identifier;
+ if (index == 0)
+ return m_interface; // return the item view interface.
+
+ const int rowIndex = (index - 1) / (columnCount + 1);
+ const int cellIndex = (index - 1) % (columnCount + 1);
+/*
+ qDebug() << "index" << index;
+ qDebug() << "rowIndex" << rowIndex;
+ qDebug() << "cellIndex" << cellIndex;
+*/
+ const QAInterface rowInterface = m_interface.childAt(rowIndex + 1);
+
+ if ((cellIndex) == 0) // Is it a row?
+ return rowInterface;
+ else {
+ return rowInterface.childAt(cellIndex);
+ }
+ }
+
+ return QAInterface();
+ }
+
+ QAElement element(int id)
+ {
+ if (id != 0) {
+ return QAElement();
+ }
+ return QAElement(object, 0);
+ }
+
+ QAElement element(const QAInterface &interface)
+ {
+ if (interface.object() && interface.object() == m_interface.object()) {
+ return QAElement(object, 0);
+ } else if (m_interface.role() == QAccessible::List) {
+ if (interface.parent().object() && interface.parent().object() == m_interface.object())
+ return QAElement(object, m_interface.indexOfChild(interface));
+ } else if (m_interface.role() == QAccessible::Table) {
+ QAInterface currentInterface = interface;
+ int index = 0;
+
+ while (currentInterface.isValid() && currentInterface.object() == 0) {
+ const QAInterface parentInterface = currentInterface.parent();
+/*
+ qDebug() << "current index" << index;
+ qDebug() << "current interface" << interface;
+
+ qDebug() << "parent interface" << parentInterface;
+ qDebug() << "grandparent interface" << parentInterface.parent();
+ qDebug() << "childCount" << interface.childCount();
+ qDebug() << "index of child" << parentInterface.indexOfChild(currentInterface);
+*/
+ index += ((parentInterface.indexOfChild(currentInterface) - 1) * (currentInterface.childCount() + 1)) + 1;
+ currentInterface = parentInterface;
+// qDebug() << "new current interface" << currentInterface;
+ }
+ if (currentInterface.object() == m_interface.object())
+ return QAElement(object, index);
+
+
+ }
+ return QAElement();
+ }
+
+ void registerChildren()
+ {
+ // Item view child interfraces don't have their own qobjects, so there is nothing to register here.
+ }
+
+private:
+ QAInterface m_interface;
+ HIObjectRef object;
+ int columnCount; // for table views;
+};
+
+#ifndef QT_MAC_USE_COCOA
+static bool managesChildren(const QAInterface &interface)
+{
+ return (interface.childCount() > 0 && interface.childAt(1).id() > 0);
+}
+
+static QInterfaceFactory *createFactory(const QAInterface &interface)
+{
+ if (isItemView(interface)) {
+ return new QItemViewInterfaceFactory(interface);
+ } if (managesChildren(interface)) {
+ return new QMultipleHIObjectFactory(interface);
+ }
+
+ return new QStandardInterfaceFactory(interface);
+}
+#endif
+
+QList<QAElement> lookup(const QList<QAInterface> &interfaces)
+{
+ QList<QAElement> elements;
+ foreach (const QAInterface &interface, interfaces)
+ if (interface.isValid()) {
+ const QAElement element = accessibleHierarchyManager()->lookup(interface);
+ if (element.isValid())
+ elements.append(element);
+ }
+ return elements;
+}
+
+// Debug output helpers:
+/*
+static QString nameForEventKind(UInt32 kind)
+{
+ switch(kind) {
+ case kEventAccessibleGetChildAtPoint: return QString("GetChildAtPoint"); break;
+ case kEventAccessibleGetAllAttributeNames: return QString("GetAllAttributeNames"); break;
+ case kEventAccessibleGetNamedAttribute: return QString("GetNamedAttribute"); break;
+ case kEventAccessibleSetNamedAttribute: return QString("SetNamedAttribute"); break;
+ case kEventAccessibleGetAllActionNames: return QString("GetAllActionNames"); break;
+ case kEventAccessibleGetFocusedChild: return QString("GetFocusedChild"); break;
+ default:
+ return QString("Unknown accessibility event type: %1").arg(kind);
+ break;
+ };
+}
+*/
+#ifndef QT_MAC_USE_COCOA
+static bool qt_mac_append_cf_uniq(CFMutableArrayRef array, CFTypeRef value)
+{
+ if (value == 0)
+ return false;
+
+ CFRange range;
+ range.location = 0;
+ range.length = CFArrayGetCount(array);
+ if(!CFArrayContainsValue(array, range, value)) {
+ CFArrayAppendValue(array, value);
+ return true;
+ }
+ return false;
+}
+
+static OSStatus setAttributeValue(EventRef event, const QList<QAElement> &elements)
+{
+ CFMutableArrayRef array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
+ foreach (const QAElement &element, elements) {
+ if (element.isValid())
+ CFArrayAppendValue(array, element.element());
+ }
+
+ const OSStatus err = SetEventParameter(event, kEventParamAccessibleAttributeValue,
+ typeCFTypeRef, sizeof(array), &array);
+ CFRelease(array);
+ return err;
+}
+#endif //QT_MAC_USE_COCOA
+
+/*
+ Gets the AccessibleObject parameter from an event.
+*/
+static inline AXUIElementRef getAccessibleObjectParameter(EventRef event)
+{
+ AXUIElementRef element;
+ GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0,
+ sizeof(element), 0, &element);
+ return element;
+}
+
+/*
+ The application event handler makes sure that all top-level qt windows are registered
+ before any accessibility events are handeled.
+*/
+#ifndef QT_MAC_USE_COCOA
+static OSStatus applicationEventHandler(EventHandlerCallRef next_ref, EventRef event, void *)
+{
+ QAInterface rootInterface(QAccessible::queryAccessibleInterface(rootObject ? rootObject : qApp), 0);
+ accessibleHierarchyManager()->registerChildren(rootInterface);
+
+ return CallNextEventHandler(next_ref, event);
+}
+
+/*
+ Returns the value for element by combining the QAccessibility::Checked and
+ QAccessibility::Mixed flags into an int value that the Mac accessibilty
+ system understands. This works for check boxes, radio buttons, and the like.
+ The return values are:
+ 0: unchecked
+ 1: checked
+ 2: undecided
+*/
+static int buttonValue(QAInterface element)
+{
+ const QAccessible::State state = element.state();
+ if (state & QAccessible::Mixed)
+ return 2;
+ else if(state & QAccessible::Checked)
+ return 1;
+ else
+ return 0;
+}
+
+static QString getValue(const QAInterface &interface)
+{
+ const QAccessible::Role role = interface.role();
+ if (role == QAccessible::RadioButton || role == QAccessible::CheckBox)
+ return QString::number(buttonValue(interface));
+ else
+ return interface.text(QAccessible::Value);
+}
+#endif //QT_MAC_USE_COCOA
+
+/*
+ Translates a QAccessible::Role into a mac accessibility role.
+*/
+static CFStringRef macRole(const QAInterface &interface)
+{
+ const QAccessible::Role qtRole = interface.role();
+
+// qDebug() << "role for" << interface.object() << "interface role" << hex << qtRole;
+
+ // Qt accessibility: QAccessible::Splitter contains QAccessible::Grip.
+ // Mac accessibility: AXSplitGroup contains AXSplitter.
+ if (qtRole == QAccessible::Grip) {
+ const QAInterface parent = interface.parent();
+ if (parent.isValid() && parent.role() == QAccessible::Splitter)
+ return CFStringRef(QAXSplitterRole);
+ }
+
+ // Tab widgets and standalone tab bars get the kAXTabGroupRole. Accessibility
+ // for tab bars emebedded in a tab widget is handled by the tab widget.
+ if (isTabWidget(interface) || isStandaloneTabBar(interface))
+ return kAXTabGroupRole;
+
+ if (QObject *object = interface.object()) {
+ // ### The interface for an abstract scroll area returns the generic "Client"
+ // role, so we have to to an extra detect on the QObject here.
+ if (object->inherits("QAbstractScrollArea") && interface.id() == 0)
+ return CFStringRef(QAXScrollAreaRole);
+
+ if (object->inherits("QDockWidget"))
+ return CFStringRef(QAXUnknownRole);
+ }
+
+ int i = 0;
+ int testRole = text_bindings[i][0].qt;
+ while (testRole != -1) {
+ if (testRole == qtRole)
+ return CFStringRef(text_bindings[i][0].mac);
+ ++i;
+ testRole = text_bindings[i][0].qt;
+ }
+
+// qDebug() << "got unknown role!" << interface << interface.parent();
+
+ return CFStringRef(QAXUnknownRole);
+}
+
+/*
+ Translates a QAccessible::Role and an attribute name into a QAccessible::Text, taking into
+ account execptions listed in text_bindings.
+*/
+#ifndef QT_MAC_USE_COCOA
+static int textForRoleAndAttribute(QAccessible::Role role, CFStringRef attribute)
+{
+ // Search for exception, return it if found.
+ int testRole = text_bindings[0][0].qt;
+ int i = 0;
+ while (testRole != -1) {
+ if (testRole == role) {
+ int j = 1;
+ int qtRole = text_bindings[i][j].qt;
+ CFStringRef testAttribute = CFStringRef(text_bindings[i][j].mac);
+ while (qtRole != -1) {
+ if (CFStringCompare(attribute, testAttribute, 0) == kCFCompareEqualTo) {
+ return (QAccessible::Text)qtRole;
+ }
+ ++j;
+ testAttribute = CFStringRef(text_bindings[i][j].mac); /// ### custom compare
+ qtRole = text_bindings[i][j].qt; /// ### custom compare
+ }
+ break;
+ }
+ ++i;
+ testRole = text_bindings[i][0].qt;
+ }
+
+ // Return default mappping
+ if (CFStringCompare(attribute, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo)
+ return QAccessible::Name;
+ else if (CFStringCompare(attribute, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo)
+ return QAccessible::Value;
+ else if (CFStringCompare(attribute, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo)
+ return QAccessible::Help;
+ else if (CFStringCompare(attribute, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo)
+ return QAccessible::Description;
+ else
+ return -1;
+}
+
+/*
+ Returns the subrole string constant for the interface if it has one,
+ else returns an empty string.
+*/
+static QCFString subrole(const QAInterface &interface)
+{
+ const QAInterface parent = interface.parent();
+ if (parent.isValid() == false)
+ return QCFString();
+
+ if (parent.role() == QAccessible::ScrollBar) {
+ QCFString subrole;
+ switch(interface.id()) {
+ case 1: subrole = CFStringRef(QAXDecrementArrowSubrole); break;
+ case 2: subrole = CFStringRef(QAXDecrementPageSubrole); break;
+ case 4: subrole = CFStringRef(QAXIncrementPageSubrole); break;
+ case 5: subrole = CFStringRef(QAXIncrementArrowSubrole); break;
+ default:
+ break;
+ }
+ return subrole;
+ }
+ return QCFString();
+}
+
+// Gets the scroll bar orientation by asking the QAbstractSlider object directly.
+static Qt::Orientation scrollBarOrientation(const QAInterface &scrollBar)
+{
+ QObject *const object = scrollBar.object();
+ if (QAbstractSlider * const sliderObject = qobject_cast<QAbstractSlider * const>(object))
+ return sliderObject->orientation();
+
+ return Qt::Vertical; // D'oh! The interface wasn't a scroll bar.
+}
+
+static QAInterface scrollAreaGetScrollBarInterface(const QAInterface &scrollArea, Qt::Orientation orientation)
+{
+ if (macRole(scrollArea) != CFStringRef(CFStringRef(QAXScrollAreaRole)))
+ return QAInterface();
+
+ // Child 1 is the contents widget, 2 and 3 are the scroll bar containers wich contains possible scroll bars.
+ for (int i = 2; i <= 3; ++i) {
+ QAInterface scrollBarContainer = scrollArea.childAt(i);
+ for (int i = 1; i <= scrollBarContainer.childCount(); ++i) {
+ QAInterface scrollBar = scrollBarContainer.childAt(i);
+ if (scrollBar.isValid() &&
+ scrollBar.role() == QAccessible::ScrollBar &&
+ scrollBarOrientation(scrollBar) == orientation)
+ return scrollBar;
+ }
+ }
+
+ return QAInterface();
+}
+
+static bool scrollAreaHasScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
+{
+ return scrollAreaGetScrollBarInterface(scrollArea, orientation).isValid();
+}
+
+static QAElement scrollAreaGetScrollBar(const QAInterface &scrollArea, Qt::Orientation orientation)
+{
+ return accessibleHierarchyManager()->lookup(scrollAreaGetScrollBarInterface(scrollArea, orientation));
+}
+
+static QAElement scrollAreaGetContents(const QAInterface &scrollArea)
+{
+ // Child 1 is the contents widget,
+ return accessibleHierarchyManager()->lookup(scrollArea.navigate(QAccessible::Child, 1));
+}
+
+static QAElement tabWidgetGetContents(const QAInterface &interface)
+{
+ // A kAXTabGroup has a kAXContents attribute, which consists of the
+ // ui elements for the current tab page. Get the current tab page
+ // from the QStackedWidget, where the current visible page can
+ // be found at index 1.
+ QAInterface stackedWidget = interface.childAt(1);
+ accessibleHierarchyManager()->registerChildren(stackedWidget);
+ QAInterface tabPageInterface = stackedWidget.childAt(1);
+ return accessibleHierarchyManager()->lookup(tabPageInterface);
+}
+
+static QList<QAElement> tabBarGetTabs(const QAInterface &interface)
+{
+ // Get the tabs by searching for children with the "PageTab" role.
+ // This filters out the left/right navigation buttons.
+ accessibleHierarchyManager()->registerChildren(interface);
+ QList<QAElement> tabs;
+ const int numChildren = interface.childCount();
+ for (int i = 1; i < numChildren + 1; ++i) {
+ QAInterface child = interface.navigate(QAccessible::Child, i);
+ if (child.isValid() && child.role() == QAccessible::PageTab) {
+ tabs.append(accessibleHierarchyManager()->lookup(child));
+ }
+ }
+ return tabs;
+}
+
+static QList<QAElement> tabWidgetGetTabs(const QAInterface &interface)
+{
+ // Each QTabWidget has two children, a QStackedWidget and a QTabBar.
+ // Get the tabs from the QTabBar.
+ return tabBarGetTabs(interface.childAt(2));
+}
+
+static QList<QAElement> tabWidgetGetChildren(const QAInterface &interface)
+{
+ // The children for a kAXTabGroup should consist of the tabs and the
+ // contents of the current open tab page.
+ QList<QAElement> children = tabWidgetGetTabs(interface);
+ children += tabWidgetGetContents(interface);
+ return children;
+}
+#endif //QT_MAC_USE_COCOA
+
+/*
+ Returns the label (buddy) interface for interface, or 0 if it has none.
+*/
+/*
+static QAInterface findLabel(const QAInterface &interface)
+{
+ return interface.navigate(QAccessible::Label, 1);
+}
+*/
+/*
+ Returns a list of interfaces this interface labels, or an empty list if it doesn't label any.
+*/
+/*
+static QList<QAInterface> findLabelled(const QAInterface &interface)
+{
+ QList<QAInterface> interfaceList;
+
+ int count = 1;
+ const QAInterface labelled = interface.navigate(QAccessible::Labelled, count);
+ while (labelled.isValid()) {
+ interfaceList.append(labelled);
+ ++count;
+ }
+ return interfaceList;
+}
+*/
+/*
+ Tests if the given QAInterface has data for a mac attribute.
+*/
+#ifndef QT_MAC_USE_COCOA
+static bool supportsAttribute(CFStringRef attribute, const QAInterface &interface)
+{
+ const int text = textForRoleAndAttribute(interface.role(), attribute);
+
+ // Special case: Static texts don't have a title.
+ if (interface.role() == QAccessible::StaticText && attribute == CFStringRef(QAXTitleAttribute))
+ return false;
+
+ // Return true if we the attribute matched a QAccessible::Role and we get text for that role from the interface.
+ if (text != -1) {
+ if (text == QAccessible::Value) // Special case for Value, see getValue()
+ return !getValue(interface).isEmpty();
+ else
+ return !interface.text((QAccessible::Text)text).isEmpty();
+ }
+
+ if (CFStringCompare(attribute, CFStringRef(QAXChildrenAttribute), 0) == kCFCompareEqualTo) {
+ if (interface.childCount() > 0)
+ return true;
+ }
+
+ if (CFStringCompare(attribute, CFStringRef(QAXSubroleAttribute), 0) == kCFCompareEqualTo) {
+ return (subrole(interface) != QCFString());
+ }
+
+ return false;
+}
+
+static void appendIfSupported(CFMutableArrayRef array, CFStringRef attribute, const QAInterface &interface)
+{
+ if (supportsAttribute(attribute, interface))
+ qt_mac_append_cf_uniq(array, attribute);
+}
+
+/*
+ Returns the names of the attributes the give QAInterface supports.
+*/
+static OSStatus getAllAttributeNames(EventRef event, const QAInterface &interface, EventHandlerCallRef next_ref)
+{
+ // Call system event handler.
+ OSStatus err = CallNextEventHandler(next_ref, event);
+ if(err != noErr && err != eventNotHandledErr)
+ return err;
+ CFMutableArrayRef attrs = 0;
+ GetEventParameter(event, kEventParamAccessibleAttributeNames, typeCFMutableArrayRef, 0,
+ sizeof(attrs), 0, &attrs);
+
+ if (!attrs)
+ return eventNotHandledErr;
+
+ // Append attribute names that are always supported.
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPositionAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSizeAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRoleAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXEnabledAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXWindowAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTopLevelUIElementAttribute));
+
+ // Append these names if the QInterafceItem returns any data for them.
+ appendIfSupported(attrs, CFStringRef(QAXTitleAttribute), interface);
+ appendIfSupported(attrs, CFStringRef(QAXValueAttribute), interface);
+ appendIfSupported(attrs, CFStringRef(QAXDescriptionAttribute), interface);
+ appendIfSupported(attrs, CFStringRef(QAXLinkedUIElementsAttribute), interface);
+ appendIfSupported(attrs, CFStringRef(QAXHelpAttribute), interface);
+ appendIfSupported(attrs, CFStringRef(QAXTitleUIElementAttribute), interface);
+ appendIfSupported(attrs, CFStringRef(QAXChildrenAttribute), interface);
+ appendIfSupported(attrs, CFStringRef(QAXSubroleAttribute), interface);
+
+ // Append attribute names based on the interaface role.
+ switch (interface.role()) {
+ case QAccessible::Window:
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMainAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizedAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXCloseButtonAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXZoomButtonAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinimizeButtonAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXToolbarButtonAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXGrowAreaAttribute));
+ break;
+ case QAccessible::RadioButton:
+ case QAccessible::CheckBox:
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMinValueAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXMaxValueAttribute));
+ break;
+ case QAccessible::ScrollBar:
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
+ break;
+ case QAccessible::Splitter:
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSplittersAttribute));
+ break;
+ case QAccessible::Table:
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXRowsAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVisibleRowsAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXSelectedRowsAttribute));
+ break;
+ default:
+ break;
+ }
+
+ // Append attribute names based on the mac accessibility role.
+ const QCFString mac_role = macRole(interface);
+ if (mac_role == CFStringRef(QAXSplitterRole)) {
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXPreviousContentsAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXNextContentsAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXOrientationAttribute));
+ } else if (mac_role == CFStringRef(QAXScrollAreaRole)) {
+ if (scrollAreaHasScrollBar(interface, Qt::Horizontal))
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXHorizontalScrollBarAttribute));
+ if (scrollAreaHasScrollBar(interface, Qt::Vertical))
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXVerticalScrollBarAttribute));
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
+ } else if (mac_role == CFStringRef(QAXTabGroupRole)) {
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXTabsAttribute));
+ // Only tab widgets can have the contents attribute, there is no way of getting
+ // the contents from a QTabBar.
+ if (isTabWidget(interface))
+ qt_mac_append_cf_uniq(attrs, CFStringRef(QAXContentsAttribute));
+ }
+
+ return noErr;
+}
+
+static void handleStringAttribute(EventRef event, QAccessible::Text text, const QAInterface &interface)
+{
+ QString str = interface.text(text);
+ if (str.isEmpty())
+ return;
+
+ // Remove any html markup from the text string, or VoiceOver will read the html tags.
+ static QTextDocument document;
+ document.setHtml(str);
+ str = document.toPlainText();
+
+ CFStringRef cfstr = QCFString::toCFStringRef(str);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(cfstr), &cfstr);
+}
+
+/*
+ Handles the parent attribute for a interface.
+ There are basically three cases here:
+ 1. interface is a HIView and has only HIView children.
+ 2. interface is a HIView but has children that is not a HIView
+ 3. interface is not a HIView.
+*/
+static OSStatus handleChildrenAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+ // Add the children for this interface to the global QAccessibelHierachyManager.
+ accessibleHierarchyManager()->registerChildren(interface);
+
+ if (isTabWidget(interface)) {
+ QList<QAElement> children = tabWidgetGetChildren(interface);
+ const int childCount = children.count();
+
+ CFMutableArrayRef array = 0;
+ array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
+ for (int i = 0; i < childCount; ++i) {
+ qt_mac_append_cf_uniq(array, children.at(i).element());
+ }
+
+ OSStatus err;
+ err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
+ if (err != noErr)
+ qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
+
+ return noErr;
+ }
+
+ const QList<QAElement> children = lookup(interface.children());
+ const int childCount = children.count();
+
+ OSStatus err = eventNotHandledErr;
+ if (interface.isHIView())
+ err = CallNextEventHandler(next_ref, event);
+
+ CFMutableArrayRef array = 0;
+ int arraySize = 0;
+ if (err == noErr) {
+ CFTypeRef obj = 0;
+ err = GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, NULL , sizeof(obj), NULL, &obj);
+ if (err == noErr && obj != 0) {
+ array = (CFMutableArrayRef)obj;
+ arraySize = CFArrayGetCount(array);
+ }
+ }
+
+ if (array) {
+ CFArrayRemoveAllValues(array);
+ for (int i = 0; i < childCount; ++i) {
+ qt_mac_append_cf_uniq(array, children.at(i).element());
+ }
+ } else {
+ array = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks);
+ for (int i = 0; i < childCount; ++i) {
+ qt_mac_append_cf_uniq(array, children.at(i).element());
+ }
+
+ err = SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFArrayRef, sizeof(array), &array);
+ if (err != noErr)
+ qWarning("Qt:Internal error (%s:%d)", __FILE__, __LINE__);
+ }
+
+ return noErr;
+}
+
+/*
+
+*/
+static OSStatus handleParentAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+ OSStatus err = eventNotHandledErr;
+ if (interface.isHIView()) {
+ err = CallNextEventHandler(next_ref, event);
+ }
+ if (err == noErr)
+ return err;
+
+ const QAInterface parentInterface = interface.navigate(QAccessible::Ancestor, 1);
+ const QAElement parentElement = accessibleHierarchyManager()->lookup(parentInterface);
+
+ if (parentElement.isValid() == false)
+ return eventNotHandledErr;
+
+ AXUIElementRef elementRef = parentElement.element();
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
+ return noErr;
+}
+#endif
+
+struct IsWindowTest
+{
+ static inline bool test(const QAInterface &interface)
+ {
+ return (interface.role() == QAccessible::Window);
+ }
+};
+
+struct IsWindowAndNotDrawerOrSheetTest
+{
+ static inline bool test(const QAInterface &interface)
+ {
+ QWidget * const widget = qobject_cast<QWidget*>(interface.object());
+ return (interface.role() == QAccessible::Window &&
+ widget && widget->isWindow() &&
+ !qt_mac_is_macdrawer(widget) &&
+ !qt_mac_is_macsheet(widget));
+ }
+};
+
+/*
+ Navigates up the iterfaces ancestor hierachy until a QAccessibleInterface that
+ passes the Test is found. If we reach a interface that is a HIView we stop the
+ search and call AXUIElementCopyAttributeValue.
+*/
+template <typename TestType>
+OSStatus navigateAncestors(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, CFStringRef attribute)
+{
+ if (interface.isHIView())
+ return CallNextEventHandler(next_ref, event);
+
+ QAInterface current = interface;
+ QAElement element;
+ while (current.isValid()) {
+ if (TestType::test(interface)) {
+ element = accessibleHierarchyManager()->lookup(current);
+ break;
+ }
+
+ // If we reach an InterfaceItem that is a HiView we can hand of the search to
+ // the system event handler. This is the common case.
+ if (current.isHIView()) {
+ CFTypeRef value = 0;
+ const QAElement currentElement = accessibleHierarchyManager()->lookup(current);
+ AXError err = AXUIElementCopyAttributeValue(currentElement.element(), attribute, &value);
+ AXUIElementRef newElement = (AXUIElementRef)value;
+
+ if (err == noErr)
+ element = QAElement(newElement);
+
+ if (newElement != 0)
+ CFRelease(newElement);
+ break;
+ }
+
+ QAInterface next = current.parent();
+ if (next.isValid() == false)
+ break;
+ if (next == current)
+ break;
+ current = next;
+ }
+
+ if (element.isValid() == false)
+ return eventNotHandledErr;
+
+
+ AXUIElementRef elementRef = element.element();
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef,
+ sizeof(elementRef), &elementRef);
+ return noErr;
+}
+
+/*
+ Returns the top-level window for an interface, which is the closest ancestor interface that
+ has the Window role, but is not a sheet or a drawer.
+*/
+#ifndef QT_MAC_USE_COCOA
+static OSStatus handleWindowAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+ return navigateAncestors<IsWindowAndNotDrawerOrSheetTest>(next_ref, event, interface, CFStringRef(QAXWindowAttribute));
+}
+
+/*
+ Returns the top-level window for an interface, which is the closest ancestor interface that
+ has the Window role. (Can also be a sheet or a drawer)
+*/
+static OSStatus handleTopLevelUIElementAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+ return navigateAncestors<IsWindowTest>(next_ref, event, interface, CFStringRef(QAXTopLevelUIElementAttribute));
+}
+
+/*
+ Returns the tab buttons for an interface.
+*/
+static OSStatus handleTabsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+ Q_UNUSED(next_ref);
+ if (isTabWidget(interface))
+ return setAttributeValue(event, tabWidgetGetTabs(interface));
+ else
+ return setAttributeValue(event, tabBarGetTabs(interface));
+}
+
+static OSStatus handlePositionAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
+{
+ QPoint qpoint(interface.rect().topLeft());
+ HIPoint point;
+ point.x = qpoint.x();
+ point.y = qpoint.y();
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHIPoint, sizeof(point), &point);
+ return noErr;
+}
+
+static OSStatus handleSizeAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
+{
+ QSize qSize(interface.rect().size());
+ HISize size;
+ size.width = qSize.width();
+ size.height = qSize.height();
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeHISize, sizeof(size), &size);
+ return noErr;
+}
+
+static OSStatus handleSubroleAttribute(EventHandlerCallRef, EventRef event, const QAInterface &interface)
+{
+ const QCFString role = subrole(interface);
+ CFStringRef rolestr = (CFStringRef)role;
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(rolestr), &rolestr);
+ return noErr;
+}
+
+static OSStatus handleOrientationAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+ QObject *const object = interface.object();
+ Qt::Orientation orientation;
+ if (interface.role() == QAccessible::ScrollBar) {
+ orientation = scrollBarOrientation(interface);
+ } else if (QSplitterHandle * const splitter = qobject_cast<QSplitterHandle * const>(object)) {
+ // Qt reports the layout orientation, but we want the splitter handle orientation.
+ orientation = (splitter->orientation() == Qt::Horizontal) ? Qt::Vertical : Qt::Horizontal;
+ } else {
+ return CallNextEventHandler(next_ref, event);
+ }
+ const CFStringRef orientationString = (orientation == Qt::Vertical)
+ ? CFStringRef(QAXVerticalOrientationValue) : CFStringRef(QAXHorizontalOrientationValue);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef, sizeof(orientationString), &orientationString);
+ return noErr;
+}
+
+/*
+ Figures out the next or previous contents for a splitter.
+*/
+static OSStatus handleSplitterContentsAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface, QCFString nextOrPrev)
+{
+ if (interface.isValid() == false || interface.role() != QAccessible::Grip)
+ return eventNotHandledErr;
+
+ const QAInterface parent = interface.parent();
+ if (parent.isValid() == false)
+ return CallNextEventHandler(next_ref, event);
+
+ if (parent.role() != QAccessible::Splitter)
+ return CallNextEventHandler(next_ref, event);
+
+ const QSplitter * const splitter = qobject_cast<const QSplitter * const>(parent.object());
+ if (splitter == 0)
+ return CallNextEventHandler(next_ref, event);
+
+ QWidget * const splitterHandle = qobject_cast<QWidget * const>(interface.object());
+ const int splitterHandleIndex = splitter->indexOf(splitterHandle);
+ const int widgetIndex = (nextOrPrev == QCFString(CFStringRef(QAXPreviousContentsAttribute))) ? splitterHandleIndex - 1 : splitterHandleIndex;
+ const QAElement contentsElement = accessibleHierarchyManager()->lookup(splitter->widget(widgetIndex), 0);
+ return setAttributeValue(event, QList<QAElement>() << contentsElement);
+}
+
+/*
+ Creates a list of all splitter handles the splitter contains.
+*/
+static OSStatus handleSplittersAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+ const QSplitter * const splitter = qobject_cast<const QSplitter * const>(interface.object());
+ if (splitter == 0)
+ return CallNextEventHandler(next_ref, event);
+
+ accessibleHierarchyManager()->registerChildren(interface);
+
+ QList<QAElement> handles;
+ const int visibleSplitterCount = splitter->count() -1; // skip first handle, it's always invisible.
+ for (int i = 0; i < visibleSplitterCount; ++i)
+ handles.append(accessibleHierarchyManager()->lookup(splitter->handle(i + 1), 0));
+
+ return setAttributeValue(event, handles);
+}
+
+// This handler gets the scroll bars for a scroll area
+static OSStatus handleScrollBarAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &scrollArea, Qt::Orientation orientation)
+{
+ QAElement scrollBar = scrollAreaGetScrollBar(scrollArea, orientation);
+ if (scrollBar.isValid() == false)
+ return CallNextEventHandler(next_ref, event);
+
+ AXUIElementRef elementRef = scrollBar.element();
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, sizeof(elementRef), &elementRef);
+ return noErr;
+}
+
+// This handler gets the contents for a scroll area or tab widget.
+static OSStatus handleContentsAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+ const QCFString mac_role = macRole(interface);
+
+ QAElement contents;
+
+ if (mac_role == kAXTabGroupRole) {
+ contents = tabWidgetGetContents(interface);
+ } else {
+ contents = scrollAreaGetContents(interface);
+ if (contents.isValid() == false)
+ return CallNextEventHandler(next_ref, event);
+ }
+
+ return setAttributeValue(event, QList<QAElement>() << contents);
+}
+
+static OSStatus handleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
+{
+ QList<QAElement> rows = lookup(tableView.children());
+
+ // kill the first row which is the horizontal header.
+ rows.removeAt(0);
+
+ return setAttributeValue(event, rows);
+}
+
+static OSStatus handleVisibleRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
+{
+ QList<QAElement> visibleRows;
+
+ QList<QAInterface> rows = tableView.children();
+ // kill the first row which is the horizontal header.
+ rows.removeAt(0);
+
+ foreach (const QAInterface &interface, rows)
+ if ((interface.state() & QAccessible::Invisible) == false)
+ visibleRows.append(accessibleHierarchyManager()->lookup(interface));
+
+ return setAttributeValue(event, visibleRows);
+}
+
+static OSStatus handleSelectedRowsAttribute(EventHandlerCallRef, EventRef event, QAInterface &tableView)
+{
+ QList<QAElement> selectedRows;
+ foreach (const QAInterface &interface, tableView.children())
+ if ((interface.state() & QAccessible::Selected))
+ selectedRows.append(accessibleHierarchyManager()->lookup(interface));
+
+ return setAttributeValue(event, selectedRows);
+}
+
+static OSStatus getNamedAttribute(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+ CFStringRef var;
+ GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
+ sizeof(var), 0, &var);
+
+ if (CFStringCompare(var, CFStringRef(QAXChildrenAttribute), 0) == kCFCompareEqualTo) {
+ return handleChildrenAttribute(next_ref, event, interface);
+ } else if(CFStringCompare(var, CFStringRef(QAXTopLevelUIElementAttribute), 0) == kCFCompareEqualTo) {
+ return handleTopLevelUIElementAttribute(next_ref, event, interface);
+ } else if(CFStringCompare(var, CFStringRef(QAXWindowAttribute), 0) == kCFCompareEqualTo) {
+ return handleWindowAttribute(next_ref, event, interface);
+ } else if(CFStringCompare(var, CFStringRef(QAXParentAttribute), 0) == kCFCompareEqualTo) {
+ return handleParentAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXPositionAttribute), 0) == kCFCompareEqualTo) {
+ return handlePositionAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXSizeAttribute), 0) == kCFCompareEqualTo) {
+ return handleSizeAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXRoleAttribute), 0) == kCFCompareEqualTo) {
+ CFStringRef role = macRole(interface);
+// ###
+// QWidget * const widget = qobject_cast<QWidget *>(interface.object());
+// if (role == CFStringRef(QAXUnknownRole) && widget && widget->isWindow())
+// role = CFStringRef(QAXWindowRole);
+
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
+ sizeof(role), &role);
+
+ } else if (CFStringCompare(var, CFStringRef(QAXEnabledAttribute), 0) == kCFCompareEqualTo) {
+ Boolean val = !((interface.state() & QAccessible::Unavailable))
+ && !((interface.state() & QAccessible::Invisible));
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ } else if (CFStringCompare(var, CFStringRef(QAXExpandedAttribute), 0) == kCFCompareEqualTo) {
+ Boolean val = (interface.state() & QAccessible::Expanded);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ } else if (CFStringCompare(var, CFStringRef(QAXSelectedAttribute), 0) == kCFCompareEqualTo) {
+ Boolean val = (interface.state() & QAccessible::Selection);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ } else if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
+ Boolean val = (interface.state() & QAccessible::Focus);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ } else if (CFStringCompare(var, CFStringRef(QAXSelectedChildrenAttribute), 0) == kCFCompareEqualTo) {
+ const int cc = interface.childCount();
+ QList<QAElement> selected;
+ for (int i = 1; i <= cc; ++i) {
+ const QAInterface child_iface = interface.navigate(QAccessible::Child, i);
+ if (child_iface.isValid() && child_iface.state() & QAccessible::Selected)
+ selected.append(accessibleHierarchyManager()->lookup(child_iface));
+ }
+
+ return setAttributeValue(event, selected);
+
+ } else if (CFStringCompare(var, CFStringRef(QAXCloseButtonAttribute), 0) == kCFCompareEqualTo) {
+ if(interface.object() && interface.object()->isWidgetType()) {
+ Boolean val = true; //do we want to add a WState for this?
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXZoomButtonAttribute), 0) == kCFCompareEqualTo) {
+ if(interface.object() && interface.object()->isWidgetType()) {
+ QWidget *widget = (QWidget*)interface.object();
+ Boolean val = (widget->windowFlags() & Qt::WindowMaximizeButtonHint);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXMinimizeButtonAttribute), 0) == kCFCompareEqualTo) {
+ if(interface.object() && interface.object()->isWidgetType()) {
+ QWidget *widget = (QWidget*)interface.object();
+ Boolean val = (widget->windowFlags() & Qt::WindowMinimizeButtonHint);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXToolbarButtonAttribute), 0) == kCFCompareEqualTo) {
+ if(interface.object() && interface.object()->isWidgetType()) {
+ QWidget *widget = (QWidget*)interface.object();
+ Boolean val = qobject_cast<QMainWindow *>(widget) != 0;
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXGrowAreaAttribute), 0) == kCFCompareEqualTo) {
+ if(interface.object() && interface.object()->isWidgetType()) {
+ Boolean val = true; //do we want to add a WState for this?
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXMinimizedAttribute), 0) == kCFCompareEqualTo) {
+ if (interface.object() && interface.object()->isWidgetType()) {
+ QWidget *widget = (QWidget*)interface.object();
+ Boolean val = (widget->windowState() & Qt::WindowMinimized);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeBoolean,
+ sizeof(val), &val);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXSubroleAttribute), 0) == kCFCompareEqualTo) {
+ return handleSubroleAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXRoleDescriptionAttribute), 0) == kCFCompareEqualTo) {
+#if !defined(QT_MAC_USE_COCOA)
+ if (HICopyAccessibilityRoleDescription) {
+ const CFStringRef roleDescription = HICopyAccessibilityRoleDescription(macRole(interface), 0);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFStringRef,
+ sizeof(roleDescription), &roleDescription);
+ } else
+#endif
+ {
+ // Just use Qt::Description on 10.3
+ handleStringAttribute(event, QAccessible::Description, interface);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXTitleAttribute), 0) == kCFCompareEqualTo) {
+ const QAccessible::Role role = interface.role();
+ const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
+ handleStringAttribute(event, text, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXValueAttribute), 0) == kCFCompareEqualTo) {
+ const QAccessible::Role role = interface.role();
+ const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
+ if (role == QAccessible::CheckBox || role == QAccessible::RadioButton) {
+ int value = buttonValue(interface);
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
+ } else {
+ handleStringAttribute(event, text, interface);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXDescriptionAttribute), 0) == kCFCompareEqualTo) {
+ const QAccessible::Role role = interface.role();
+ const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
+ handleStringAttribute(event, text, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXLinkedUIElementsAttribute), 0) == kCFCompareEqualTo) {
+ return CallNextEventHandler(next_ref, event);
+ } else if (CFStringCompare(var, CFStringRef(QAXHelpAttribute), 0) == kCFCompareEqualTo) {
+ const QAccessible::Role role = interface.role();
+ const QAccessible::Text text = (QAccessible::Text)textForRoleAndAttribute(role, var);
+ handleStringAttribute(event, text, interface);
+ } else if (CFStringCompare(var, kAXTitleUIElementAttribute, 0) == kCFCompareEqualTo) {
+ return CallNextEventHandler(next_ref, event);
+ } else if (CFStringCompare(var, CFStringRef(QAXTabsAttribute), 0) == kCFCompareEqualTo) {
+ return handleTabsAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
+ // tabs we first go to the tab bar which is child #2.
+ QAInterface tabBarInterface = interface.childAt(2);
+ return handleTabsAttribute(next_ref, event, tabBarInterface);
+ } else if (CFStringCompare(var, CFStringRef(QAXMinValueAttribute), 0) == kCFCompareEqualTo) {
+ if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
+ uint value = 0;
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
+ } else {
+ return CallNextEventHandler(next_ref, event);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXMaxValueAttribute), 0) == kCFCompareEqualTo) {
+ if (interface.role() == QAccessible::RadioButton || interface.role() == QAccessible::CheckBox) {
+ uint value = 2;
+ SetEventParameter(event, kEventParamAccessibleAttributeValue, typeUInt32, sizeof(value), &value);
+ } else {
+ return CallNextEventHandler(next_ref, event);
+ }
+ } else if (CFStringCompare(var, CFStringRef(QAXOrientationAttribute), 0) == kCFCompareEqualTo) {
+ return handleOrientationAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXPreviousContentsAttribute), 0) == kCFCompareEqualTo) {
+ return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXPreviousContentsAttribute));
+ } else if (CFStringCompare(var, CFStringRef(QAXNextContentsAttribute), 0) == kCFCompareEqualTo) {
+ return handleSplitterContentsAttribute(next_ref, event, interface, CFStringRef(QAXNextContentsAttribute));
+ } else if (CFStringCompare(var, CFStringRef(QAXSplittersAttribute), 0) == kCFCompareEqualTo) {
+ return handleSplittersAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXHorizontalScrollBarAttribute), 0) == kCFCompareEqualTo) {
+ return handleScrollBarAttribute(next_ref, event, interface, Qt::Horizontal);
+ } else if (CFStringCompare(var, CFStringRef(QAXVerticalScrollBarAttribute), 0) == kCFCompareEqualTo) {
+ return handleScrollBarAttribute(next_ref, event, interface, Qt::Vertical);
+ } else if (CFStringCompare(var, CFStringRef(QAXContentsAttribute), 0) == kCFCompareEqualTo) {
+ return handleContentsAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXRowsAttribute), 0) == kCFCompareEqualTo) {
+ return handleRowsAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXVisibleRowsAttribute), 0) == kCFCompareEqualTo) {
+ return handleVisibleRowsAttribute(next_ref, event, interface);
+ } else if (CFStringCompare(var, CFStringRef(QAXSelectedRowsAttribute), 0) == kCFCompareEqualTo) {
+ return handleSelectedRowsAttribute(next_ref, event, interface);
+ } else {
+ return CallNextEventHandler(next_ref, event);
+ }
+ return noErr;
+}
+
+static OSStatus isNamedAttributeSettable(EventRef event, const QAInterface &interface)
+{
+ CFStringRef var;
+ GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
+ sizeof(var), 0, &var);
+ Boolean settable = false;
+ if (CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
+ settable = true;
+ } else {
+ for (int r = 0; text_bindings[r][0].qt != -1; r++) {
+ if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
+ for (int a = 1; text_bindings[r][a].qt != -1; a++) {
+ if (CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
+ settable = text_bindings[r][a].settable;
+ break;
+ }
+ }
+ }
+ }
+ }
+ SetEventParameter(event, kEventParamAccessibleAttributeSettable, typeBoolean,
+ sizeof(settable), &settable);
+ return noErr;
+}
+
+static OSStatus getChildAtPoint(EventHandlerCallRef next_ref, EventRef event, QAInterface &interface)
+{
+ Q_UNUSED(next_ref);
+ if (interface.isValid() == false)
+ return eventNotHandledErr;
+
+ // Add the children for this interface to the global QAccessibelHierachyManager.
+ accessibleHierarchyManager()->registerChildren(interface);
+
+ Point where;
+ GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(where), 0, &where);
+ const QAInterface childInterface = interface.childAt(where.h, where.v);
+
+ if (childInterface.isValid() == false || childInterface == interface)
+ return eventNotHandledErr;
+
+ const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
+ if (element.isValid() == false)
+ return eventNotHandledErr;
+
+ AXUIElementRef elementRef = element.element();
+ CFRetain(elementRef);
+ SetEventParameter(event, kEventParamAccessibleChild, typeCFTypeRef,
+ sizeof(elementRef), &elementRef);
+
+ return noErr;
+}
+
+/*
+ Returns a list of actions the given interface supports.
+ Currently implemented by getting the interface role and deciding based on that.
+*/
+static QList<QAccessible::Action> supportedPredefinedActions(const QAInterface &interface)
+{
+ QList<QAccessible::Action> actions;
+ switch (interface.role()) {
+ default:
+ // Most things can be pressed.
+ actions.append(QAccessible::Press);
+ break;
+ }
+
+ return actions;
+}
+
+/*
+ Translates a predefined QAccessible::Action to a Mac action constant.
+ Returns an empty string if the Qt Action has no mac equivalent.
+*/
+static QCFString translateAction(const QAccessible::Action action)
+{
+ switch (action) {
+ case QAccessible::Press:
+ return CFStringRef(QAXPressAction);
+ break;
+ case QAccessible::Increase:
+ return CFStringRef(QAXIncrementAction);
+ break;
+ case QAccessible::Decrease:
+ return CFStringRef(QAXDecrementAction);
+ break;
+ case QAccessible::Accept:
+ return CFStringRef(QAXConfirmAction);
+ break;
+ case QAccessible::Select:
+ return CFStringRef(QAXPickAction);
+ break;
+ case QAccessible::Cancel:
+ return CFStringRef(QAXCancelAction);
+ break;
+ default:
+ return QCFString();
+ break;
+ }
+}
+
+/*
+ Translates between a Mac action constant and a QAccessible::Action.
+ Returns QAccessible::Default action if there is no Qt predefined equivalent.
+*/
+static QAccessible::Action translateAction(const CFStringRef actionName)
+{
+ if(CFStringCompare(actionName, CFStringRef(QAXPressAction), 0) == kCFCompareEqualTo) {
+ return QAccessible::Press;
+ } else if(CFStringCompare(actionName, CFStringRef(QAXIncrementAction), 0) == kCFCompareEqualTo) {
+ return QAccessible::Increase;
+ } else if(CFStringCompare(actionName, CFStringRef(QAXDecrementAction), 0) == kCFCompareEqualTo) {
+ return QAccessible::Decrease;
+ } else if(CFStringCompare(actionName, CFStringRef(QAXConfirmAction), 0) == kCFCompareEqualTo) {
+ return QAccessible::Accept;
+ } else if(CFStringCompare(actionName, CFStringRef(QAXPickAction), 0) == kCFCompareEqualTo) {
+ return QAccessible::Select;
+ } else if(CFStringCompare(actionName, CFStringRef(QAXCancelAction), 0) == kCFCompareEqualTo) {
+ return QAccessible::Cancel;
+ } else {
+ return QAccessible::DefaultAction;
+ }
+}
+#endif // QT_MAC_USE_COCOA
+
+/*
+ Copies the translated names all supported actions for an interface into the kEventParamAccessibleActionNames
+ event parameter.
+*/
+#ifndef QT_MAC_USE_COCOA
+static OSStatus getAllActionNames(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+ Q_UNUSED(next_ref);
+
+ CFMutableArrayRef actions = 0;
+ GetEventParameter(event, kEventParamAccessibleActionNames, typeCFMutableArrayRef, 0,
+ sizeof(actions), 0, &actions);
+
+ // Add supported predefined actions.
+ const QList<QAccessible::Action> predefinedActions = supportedPredefinedActions(interface);
+ for (int i = 0; i < predefinedActions.count(); ++i) {
+ const QCFString action = translateAction(predefinedActions.at(i));
+ if (action != QCFString())
+ qt_mac_append_cf_uniq(actions, action);
+ }
+
+ // Add user actions
+ const int actionCount = interface.userActionCount();
+ for (int i = 0; i < actionCount; ++i) {
+ const QString actionName = interface.actionText(i, QAccessible::Name);
+ qt_mac_append_cf_uniq(actions, QCFString::toCFStringRef(actionName));
+ }
+
+ return noErr;
+}
+#endif
+
+/*
+ Handles the perforNamedAction event.
+*/
+#ifndef QT_MAC_USE_COCOA
+static OSStatus performNamedAction(EventHandlerCallRef next_ref, EventRef event, const QAInterface& interface)
+{
+ Q_UNUSED(next_ref);
+
+ CFStringRef act;
+ GetEventParameter(event, kEventParamAccessibleActionName, typeCFStringRef, 0,
+ sizeof(act), 0, &act);
+
+ const QAccessible::Action action = translateAction(act);
+
+ // Perform built-in action
+ if (action != QAccessible::DefaultAction) {
+ interface.doAction(action, QVariantList());
+ return noErr;
+ }
+
+ // Search for user-defined actions and perform it if found.
+ const int actCount = interface.userActionCount();
+ const QString qAct = QCFString::toQString(act);
+ for(int i = 0; i < actCount; i++) {
+ if(interface.actionText(i, QAccessible::Name) == qAct) {
+ interface.doAction(i, QVariantList());
+ break;
+ }
+ }
+ return noErr;
+}
+
+static OSStatus setNamedAttribute(EventHandlerCallRef next_ref, EventRef event, const QAInterface &interface)
+{
+ Q_UNUSED(next_ref);
+ Q_UNUSED(event);
+
+ CFStringRef var;
+ GetEventParameter(event, kEventParamAccessibleAttributeName, typeCFStringRef, 0,
+ sizeof(var), 0, &var);
+ if(CFStringCompare(var, CFStringRef(QAXFocusedAttribute), 0) == kCFCompareEqualTo) {
+ CFTypeRef val;
+ if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
+ sizeof(val), 0, &val) == noErr) {
+ if(CFGetTypeID(val) == CFBooleanGetTypeID() &&
+ CFEqual(static_cast<CFBooleanRef>(val), kCFBooleanTrue)) {
+ interface.doAction(QAccessible::SetFocus);
+ }
+ }
+ } else {
+ bool found = false;
+ for(int r = 0; text_bindings[r][0].qt != -1; r++) {
+ if(interface.role() == (QAccessible::Role)text_bindings[r][0].qt) {
+ for(int a = 1; text_bindings[r][a].qt != -1; a++) {
+ if(CFStringCompare(var, CFStringRef(text_bindings[r][a].mac), 0) == kCFCompareEqualTo) {
+ if(!text_bindings[r][a].settable) {
+ } else {
+ CFTypeRef val;
+ if(GetEventParameter(event, kEventParamAccessibleAttributeValue, typeCFTypeRef, 0,
+ sizeof(val), 0, &val) == noErr) {
+ if(CFGetTypeID(val) == CFStringGetTypeID())
+ interface.setText((QAccessible::Text)text_bindings[r][a].qt,
+ QCFString::toQString(static_cast<CFStringRef>(val)));
+
+ }
+ }
+ found = true;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return noErr;
+}
+
+/*
+ This is the main accessibility event handler.
+*/
+static OSStatus accessibilityEventHandler(EventHandlerCallRef next_ref, EventRef event, void *data)
+{
+ Q_UNUSED(data)
+
+ // Return if this event is not a AccessibleGetNamedAttribute event.
+ const UInt32 eclass = GetEventClass(event);
+ if (eclass != kEventClassAccessibility)
+ return eventNotHandledErr;
+
+ // Get the AXUIElementRef and QAInterface pointer
+ AXUIElementRef element = 0;
+ GetEventParameter(event, kEventParamAccessibleObject, typeCFTypeRef, 0, sizeof(element), 0, &element);
+ QAInterface interface = accessibleHierarchyManager()->lookup(element);
+ if (interface.isValid() == false)
+ return eventNotHandledErr;
+
+ const UInt32 ekind = GetEventKind(event);
+ OSStatus status = noErr;
+ switch (ekind) {
+ case kEventAccessibleGetAllAttributeNames:
+ status = getAllAttributeNames(event, interface, next_ref);
+ break;
+ case kEventAccessibleGetNamedAttribute:
+ status = getNamedAttribute(next_ref, event, interface);
+ break;
+ case kEventAccessibleIsNamedAttributeSettable:
+ status = isNamedAttributeSettable(event, interface);
+ break;
+ case kEventAccessibleGetChildAtPoint:
+ status = getChildAtPoint(next_ref, event, interface);
+ break;
+ case kEventAccessibleGetAllActionNames:
+ status = getAllActionNames(next_ref, event, interface);
+ break;
+ case kEventAccessibleGetFocusedChild:
+ status = CallNextEventHandler(next_ref, event);
+ break;
+ case kEventAccessibleSetNamedAttribute:
+ status = setNamedAttribute(next_ref, event, interface);
+ break;
+ case kEventAccessiblePerformNamedAction:
+ status = performNamedAction(next_ref, event, interface);
+ break;
+ default:
+ status = CallNextEventHandler(next_ref, event);
+ break;
+ };
+ return status;
+}
+#endif
+
+void QAccessible::initialize()
+{
+#ifndef QT_MAC_USE_COCOA
+ registerQtAccessibilityHIObjectSubclass();
+ installApplicationEventhandler();
+#endif
+}
+
+// Sets thre root object for the application
+void QAccessible::setRootObject(QObject *object)
+{
+ // Call installed root object handler if we have one
+ if (rootObjectHandler) {
+ rootObjectHandler(object);
+ return;
+ }
+
+ rootObject = object;
+}
+
+void QAccessible::cleanup()
+{
+ accessibleHierarchyManager()->reset();
+#ifndef QT_MAC_USE_COCOA
+ removeEventhandler(applicationEventHandlerUPP);
+ removeEventhandler(objectCreateEventHandlerUPP);
+ removeEventhandler(accessibilityEventHandlerUPP);
+#endif
+}
+
+void QAccessible::updateAccessibility(QObject *object, int child, Event reason)
+{
+ // Call installed update handler if we have one.
+ if (updateHandler) {
+ updateHandler(object, child, reason);
+ return;
+ }
+
+#ifndef QT_MAC_USE_COCOA
+ // Return if the mac accessibility is not enabled.
+ if(!AXAPIEnabled())
+ return;
+
+ // Work around crash, disable accessiblity for focus frames.
+ if (qstrcmp(object->metaObject()->className(), "QFocusFrame") == 0)
+ return;
+
+// qDebug() << "updateAccessibility" << object << child << hex << reason;
+
+ if (reason == ObjectShow) {
+ QAInterface interface = QAInterface(QAccessible::queryAccessibleInterface(object), child);
+ accessibleHierarchyManager()->registerInterface(interface);
+ }
+
+ const QAElement element = accessibleHierarchyManager()->lookup(object, child);
+ if (element.isValid() == false)
+ return;
+
+
+ CFStringRef notification = 0;
+ if(object && object->isWidgetType() && reason == ObjectCreated) {
+ notification = CFStringRef(QAXWindowCreatedNotification);
+ } else if(reason == ValueChanged) {
+ notification = CFStringRef(QAXValueChangedNotification);
+ } else if(reason == MenuStart) {
+ notification = CFStringRef(QAXMenuOpenedNotification);
+ } else if(reason == MenuEnd) {
+ notification = CFStringRef(QAXMenuClosedNotification);
+ } else if(reason == LocationChanged) {
+ notification = CFStringRef(QAXWindowMovedNotification);
+ } else if(reason == ObjectShow || reason == ObjectHide ) {
+ // When a widget is deleted we get a ObjectHide before the destroyed(QObject *)
+ // signal is emitted (which makes sense). However, at this point we are in the
+ // middle of the QWidget destructor which means that we have to be careful when
+ // using the widget pointer. Since we can't control what the accessibilty interfaces
+ // does when navigate() is called below we ignore the hide update in this case.
+ // (the widget will be deleted soon anyway.)
+ extern QWidgetPrivate * qt_widget_private(QWidget *);
+ if (QWidget *widget = qobject_cast<QWidget*>(object)) {
+ if (qt_widget_private(widget)->data.in_destructor)
+ return;
+
+ // Check widget parent as well, special case for preventing crash
+ // when the viewport() of an abstract scroll area is hidden when
+ // the QWidget destructor hides all its children.
+ QWidget *parentWidget = widget->parentWidget();
+ if (parentWidget && qt_widget_private(parentWidget)->data.in_destructor)
+ return;
+ }
+
+ // There is no equivalent Mac notification for ObjectShow/Hide, so we call HIObjectSetAccessibilityIgnored
+ // and isItIntersting which will mark the HIObject accociated with the element as ignored if the
+ // QAccessible::Invisible state bit is set.
+ QAInterface interface = accessibleHierarchyManager()->lookup(element);
+ if (interface.isValid()) {
+ HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(interface));
+ }
+
+ // If the interface manages its own children, also check if we should ignore those.
+ if (isItemView(interface) == false && managesChildren(interface)) {
+ for (int i = 1; i <= interface.childCount(); ++i) {
+ QAInterface childInterface = interface.navigate(QAccessible::Child, i);
+ if (childInterface.isValid() && childInterface.isHIView() == false) {
+ const QAElement element = accessibleHierarchyManager()->lookup(childInterface);
+ if (element.isValid()) {
+ HIObjectSetAccessibilityIgnored(element.object(), !isItInteresting(childInterface));
+ }
+ }
+ }
+ }
+
+ } else if(reason == Focus) {
+ if(object && object->isWidgetType()) {
+ QWidget *w = static_cast<QWidget*>(object);
+ if(w->isWindow())
+ notification = CFStringRef(QAXFocusedWindowChangedNotification);
+ else
+ notification = CFStringRef(QAXFocusedUIElementChangedNotification);
+ }
+ }
+
+ if (!notification)
+ return;
+
+ AXNotificationHIObjectNotify(notification, element.object(), element.id());
+#endif
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/gui/accessible/qaccessible_mac_carbon.cpp b/src/gui/accessible/qaccessible_mac_carbon.cpp
new file mode 100644
index 0000000000..2e8a7628e8
--- /dev/null
+++ b/src/gui/accessible/qaccessible_mac_carbon.cpp
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+static OSStatus applicationEventHandler(EventHandlerCallRef next_ref, EventRef event, void *data);
+static EventHandlerUPP applicationEventHandlerUPP = 0;
+static EventTypeSpec application_events[] = {
+ { kEventClassAccessibility, kEventAccessibleGetChildAtPoint },
+ { kEventClassAccessibility, kEventAccessibleGetNamedAttribute }
+};
+
+static CFStringRef kObjectQtAccessibility = CFSTR("com.trolltech.qt.accessibility");
+static EventHandlerUPP objectCreateEventHandlerUPP = 0;
+static EventTypeSpec objectCreateEvents[] = {
+ { kEventClassHIObject, kEventHIObjectConstruct },
+ { kEventClassHIObject, kEventHIObjectInitialize },
+ { kEventClassHIObject, kEventHIObjectDestruct },
+ { kEventClassHIObject, kEventHIObjectPrintDebugInfo }
+};
+
+static OSStatus accessibilityEventHandler(EventHandlerCallRef next_ref, EventRef event, void *data);
+static EventHandlerUPP accessibilityEventHandlerUPP = 0;
+static EventTypeSpec accessibilityEvents[] = {
+ { kEventClassAccessibility, kEventAccessibleGetChildAtPoint },
+ { kEventClassAccessibility, kEventAccessibleGetFocusedChild },
+ { kEventClassAccessibility, kEventAccessibleGetAllAttributeNames },
+ { kEventClassAccessibility, kEventAccessibleGetNamedAttribute },
+ { kEventClassAccessibility, kEventAccessibleSetNamedAttribute },
+ { kEventClassAccessibility, kEventAccessibleIsNamedAttributeSettable },
+ { kEventClassAccessibility, kEventAccessibleGetAllActionNames },
+ { kEventClassAccessibility, kEventAccessiblePerformNamedAction },
+ { kEventClassAccessibility, kEventAccessibleGetNamedActionDescription }
+};
+
+static void installAcessibilityEventHandler(HIObjectRef hiObject)
+{
+ if (!accessibilityEventHandlerUPP)
+ accessibilityEventHandlerUPP = NewEventHandlerUPP(accessibilityEventHandler);
+
+ InstallHIObjectEventHandler(hiObject, accessibilityEventHandlerUPP,
+ GetEventTypeCount(accessibilityEvents),
+ accessibilityEvents, 0, 0);
+}
+
+static OSStatus objectCreateEventHandler(EventHandlerCallRef next_ref, EventRef event, void *data)
+{
+ Q_UNUSED(data)
+ Q_UNUSED(event)
+ Q_UNUSED(next_ref)
+ return noErr;
+}
+
+static void registerQtAccessibilityHIObjectSubclass()
+{
+ if (!objectCreateEventHandlerUPP)
+ objectCreateEventHandlerUPP = NewEventHandlerUPP(objectCreateEventHandler);
+ OSStatus err = HIObjectRegisterSubclass(kObjectQtAccessibility, 0, 0, objectCreateEventHandlerUPP,
+ GetEventTypeCount(objectCreateEvents), objectCreateEvents, 0, 0);
+ if (err && err != hiObjectClassExistsErr)
+ qWarning("qaccessible_mac internal error: Could not register accessibility HIObject subclass");
+}
+
+static void installApplicationEventhandler()
+{
+ if (!applicationEventHandlerUPP)
+ applicationEventHandlerUPP = NewEventHandlerUPP(applicationEventHandler);
+
+ OSStatus err = InstallApplicationEventHandler(applicationEventHandlerUPP,
+ GetEventTypeCount(application_events), application_events,
+ 0, 0);
+
+ if (err && err != eventHandlerAlreadyInstalledErr)
+ qWarning("qaccessible_mac internal error: Could not install application accessibility event handler");
+}
+
+static void removeEventhandler(EventHandlerUPP eventHandler)
+{
+ if (eventHandler) {
+ DisposeEventHandlerUPP(eventHandler);
+ eventHandler = 0;
+ }
+}
diff --git a/src/gui/accessible/qaccessible_mac_cocoa.mm b/src/gui/accessible/qaccessible_mac_cocoa.mm
new file mode 100644
index 0000000000..60b967ab39
--- /dev/null
+++ b/src/gui/accessible/qaccessible_mac_cocoa.mm
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qaccessible.h"
+#include "qaccessible_mac_p.h"
+#include "qdebug.h"
+#include "qtabwidget.h"
+
+#include <private/qt_mac_p.h>
+#include <private/qcocoaview_mac_p.h>
+#include <private/qwidget_p.h>
+
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#ifdef QT_MAC_USE_COCOA
+
+QT_BEGIN_NAMESPACE
+
+//#define MAC_ACCESSIBILTY_DEVELOPER_MODE
+
+#ifndef QT_NO_DEBUG_STREAM
+#ifdef MAC_ACCESSIBILTY_DEVELOPER_MODE
+#define MAC_ACCESSIBILTY_DEBUG QT_PREPEND_NAMESPACE(qDebug)
+#else
+#define MAC_ACCESSIBILTY_DEBUG if (0) QT_PREPEND_NAMESPACE(qDebug)
+#endif
+#else
+#define MAC_ACCESSIBILTY_DEBUG if (0) QT_PREPEND_NAMESPACE(QNoDebug)
+#endif
+
+typedef QMap<QAccessible::Role, NSString *> QMacAccessibiltyRoleMap;
+Q_GLOBAL_STATIC(QMacAccessibiltyRoleMap, qMacAccessibiltyRoleMap);
+
+static QAInterface interfaceForView(QT_MANGLE_NAMESPACE(QCocoaView) *view)
+{
+ return QAInterface(QAccessible::queryAccessibleInterface([view qt_qwidget]));
+}
+
+/*
+ Set up mappings from Qt accessibilty roles to Mac accessibilty roles.
+*/
+static void populateRoleMap()
+{
+ QMacAccessibiltyRoleMap &roleMap = *qMacAccessibiltyRoleMap();
+ roleMap[QAccessible::MenuItem] = NSAccessibilityMenuItemRole;
+ roleMap[QAccessible::MenuBar] = NSAccessibilityMenuBarRole;
+ roleMap[QAccessible::ScrollBar] = NSAccessibilityScrollBarRole;
+ roleMap[QAccessible::Grip] = NSAccessibilityGrowAreaRole;
+ roleMap[QAccessible::Window] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::Dialog] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::AlertMessage] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::ToolTip] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::HelpBalloon] = NSAccessibilityWindowRole;
+ roleMap[QAccessible::PopupMenu] = NSAccessibilityMenuRole;
+ roleMap[QAccessible::Application] = NSAccessibilityApplicationRole;
+ roleMap[QAccessible::Pane] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Grouping] = NSAccessibilityGroupRole;
+ roleMap[QAccessible::Separator] = NSAccessibilitySplitterRole;
+ roleMap[QAccessible::ToolBar] = NSAccessibilityToolbarRole;
+ roleMap[QAccessible::PageTab] = NSAccessibilityRadioButtonRole;
+ roleMap[QAccessible::ButtonMenu] = NSAccessibilityMenuButtonRole;
+ roleMap[QAccessible::ButtonDropDown] = NSAccessibilityPopUpButtonRole;
+ roleMap[QAccessible::SpinBox] = NSAccessibilityIncrementorRole;
+ roleMap[QAccessible::Slider] = NSAccessibilitySliderRole;
+ roleMap[QAccessible::ProgressBar] = NSAccessibilityProgressIndicatorRole;
+ roleMap[QAccessible::ComboBox] = NSAccessibilityPopUpButtonRole;
+ roleMap[QAccessible::RadioButton] = NSAccessibilityRadioButtonRole;
+ roleMap[QAccessible::CheckBox] = NSAccessibilityCheckBoxRole;
+ roleMap[QAccessible::StaticText] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Table] = NSAccessibilityTableRole;
+ roleMap[QAccessible::StatusBar] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Column] = NSAccessibilityColumnRole;
+ roleMap[QAccessible::ColumnHeader] = NSAccessibilityColumnRole;
+ roleMap[QAccessible::Row] = NSAccessibilityRowRole;
+ roleMap[QAccessible::RowHeader] = NSAccessibilityRowRole;
+ roleMap[QAccessible::Cell] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::PushButton] = NSAccessibilityButtonRole;
+ roleMap[QAccessible::EditableText] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::Link] = NSAccessibilityTextFieldRole;
+ roleMap[QAccessible::Indicator] = NSAccessibilityValueIndicatorRole;
+ roleMap[QAccessible::Splitter] = NSAccessibilitySplitGroupRole;
+ roleMap[QAccessible::List] = NSAccessibilityListRole;
+ roleMap[QAccessible::ListItem] = NSAccessibilityStaticTextRole;
+ roleMap[QAccessible::Cell] = NSAccessibilityStaticTextRole;
+}
+
+/*
+ Returns a Mac accessibility role for the given interface, or
+ NSAccessibilityUnknownRole if no role mapping is found.
+*/
+static NSString *macRoleForInterface(QAInterface interface)
+{
+ const QAccessible::Role qtRole = interface.role();
+ QMacAccessibiltyRoleMap &roleMap = *qMacAccessibiltyRoleMap();
+
+ if (roleMap.isEmpty())
+ populateRoleMap();
+
+ MAC_ACCESSIBILTY_DEBUG() << "role for" << interface.object() << "interface role" << hex << qtRole;
+
+ if (roleMap.contains(qtRole)) {
+ MAC_ACCESSIBILTY_DEBUG() << "return" << roleMap[qtRole];
+ return roleMap[qtRole];
+ }
+
+ MAC_ACCESSIBILTY_DEBUG() << "return NSAccessibilityUnknownRole";
+ return NSAccessibilityUnknownRole;
+}
+
+/*
+ Is the interface a QTabBar embedded in a QTabWidget?
+ (as opposed to a stand-alone tab bar)
+*/
+static bool isEmbeddedTabBar(const QAInterface &interface)
+{
+ QObject *object = interface.object();
+ if (interface.role() == QAccessible::PageTabList && object)
+ return (qobject_cast<QTabWidget *>(object->parent()));
+
+ return false;
+}
+
+static bool isInterfaceIgnored(QAInterface interface)
+{
+ // Mac accessibility does not have an attribute that corresponds to the
+ // Invisible/Offscreen state. Use the ignore facility to disable them.
+ const QAccessible::State state = interface.state();
+ if (state & QAccessible::Invisible ||
+ state & QAccessible::Offscreen )
+ return false;
+
+ // Hide QTabBars that has a QTabWidget parent (the QTabWidget handles the accessibility)
+ if (isEmbeddedTabBar(interface))
+ return false;
+
+ if (QObject * const object = interface.object()) {
+ const QString className = QLatin1String(object->metaObject()->className());
+
+ // Prevent VoiceOver from focusing on tool tips by ignoring those
+ // interfaces. Shifting VoiceOver focus to the tool tip is confusing
+ // and the contents of the tool tip is avalible through the description
+ // attribute anyway.
+ if (className == QLatin1String("QTipLabel"))
+ return false;
+ }
+
+ // Hide interfaces with an unknown role. When developing it's often useful to disable
+ // this check to see all interfaces in the hierarchy.
+#ifndef MAC_ACCESSIBILTY_DEVELOPER_MODE
+ return [macRoleForInterface(interface) isEqualToString: NSAccessibilityUnknownRole];
+#else
+ return NO;
+#endif
+}
+
+QT_END_NAMESPACE
+
+@implementation QT_MANGLE_NAMESPACE(QCocoaView) (Accessibility)
+
+- (BOOL)accessibilityIsIgnored
+{
+ QT_PREPEND_NAMESPACE(QAInterface) interface = QT_PREPEND_NAMESPACE(interfaceForView)(self);
+ return isInterfaceIgnored(interface);
+}
+
+- (NSArray *)accessibilityAttributeNames
+{
+ QT_PREPEND_NAMESPACE(QAInterface) interface = QT_PREPEND_NAMESPACE(interfaceForView)(self);
+
+ static NSArray *attributes = nil;
+ if (attributes == nil) {
+ attributes = [super accessibilityAttributeNames];
+
+ }
+ return attributes;
+}
+
+- (id)accessibilityAttributeValue:(NSString *)attribute
+{
+ MAC_ACCESSIBILTY_DEBUG() << "accessibilityAttributeValue" << self <<
+ QT_PREPEND_NAMESPACE(QCFString)::toQString(reinterpret_cast<CFStringRef>(attribute));
+
+ QT_PREPEND_NAMESPACE(QAInterface) interface = QT_PREPEND_NAMESPACE(interfaceForView)(self);
+
+ // Switch on the attribute name and call the appropriate handler function.
+ // Pass the call on to the NSView class for attributes we don't handle.
+ if ([attribute isEqualToString:@"AXRole"]) {
+ return macRoleForInterface(interface);
+ } else {
+ return [super accessibilityAttributeValue:attribute];
+ }
+}
+
+@end
+
+#endif // QT_MAC_USE_COCOA
+
+#endif // QT_NO_ACCESSIBILITY
+
diff --git a/src/gui/accessible/qaccessible_mac_p.h b/src/gui/accessible/qaccessible_mac_p.h
new file mode 100644
index 0000000000..9acb5d3aef
--- /dev/null
+++ b/src/gui/accessible/qaccessible_mac_p.h
@@ -0,0 +1,479 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLE_MAC_P_H
+#define QACCESSIBLE_MAC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+
+#include <qglobal.h>
+#include <private/qt_mac_p.h>
+#include <qaccessible.h>
+#include <qwidget.h>
+#include <qdebug.h>
+
+//#define Q_ACCESSIBLE_MAC_DEBUG
+
+QT_BEGIN_NAMESPACE
+
+/*
+ QAccessibleInterfaceWrapper wraps QAccessibleInterface and adds
+ a ref count. QAccessibleInterfaceWrapper is a "by-value" class.
+*/
+class Q_AUTOTEST_EXPORT QAccessibleInterfaceWrapper
+{
+public:
+ QAccessibleInterfaceWrapper()
+ : interface(0), childrenIsRegistered(new bool(false)), refCount(new int(1)) { }
+
+ QAccessibleInterfaceWrapper(QAccessibleInterface *interface)
+ :interface(interface), childrenIsRegistered(new bool(false)), refCount(new int(1)) { }
+
+ ~QAccessibleInterfaceWrapper()
+ {
+ if (--(*refCount) == 0) {
+ delete interface;
+ delete refCount;
+ delete childrenIsRegistered;
+ }
+ }
+
+ QAccessibleInterfaceWrapper(const QAccessibleInterfaceWrapper &other)
+ :interface(other.interface), childrenIsRegistered(other.childrenIsRegistered), refCount(other.refCount)
+ {
+ ++(*refCount);
+ }
+
+ void operator=(const QAccessibleInterfaceWrapper &other)
+ {
+ if (other.interface == interface)
+ return;
+
+ if (--(*refCount) == 0) {
+ delete interface;
+ delete refCount;
+ delete childrenIsRegistered;
+ }
+
+ interface = other.interface;
+ childrenIsRegistered = other.childrenIsRegistered;
+ refCount = other.refCount;
+ ++(*refCount);
+ }
+
+ QAccessibleInterface *interface;
+ bool *childrenIsRegistered;
+private:
+ int *refCount;
+};
+
+/*
+ QAInterface represents one accessiblity item. It hides the fact that
+ one QAccessibleInterface may represent more than one item, and it also
+ automates the memory management for QAccessibleInterfaces using the
+ QAccessibleInterfaceWrapper wrapper class.
+
+ It has the same API as QAccessibleInterface, minus the child parameter
+ in the functions.
+*/
+class Q_AUTOTEST_EXPORT QAInterface : public QAccessible
+{
+public:
+ QAInterface()
+ : base(QAccessibleInterfaceWrapper())
+ { }
+
+ QAInterface(QAccessibleInterface *interface, int child = 0)
+ {
+ if (interface == 0 || child > interface->childCount()) {
+ base = QAccessibleInterfaceWrapper();
+ } else {
+ base = QAccessibleInterfaceWrapper(interface);
+ m_cachedObject = interface->object();
+ this->child = child;
+ }
+ }
+
+ QAInterface(QAccessibleInterfaceWrapper wrapper, int child = 0)
+ :base(wrapper), m_cachedObject(wrapper.interface->object()), child(child)
+ { }
+
+ QAInterface(const QAInterface &other, int child)
+ {
+ if (other.isValid() == false || child > other.childCount()) {
+ base = QAccessibleInterfaceWrapper();
+ } else {
+ base = other.base;
+ m_cachedObject = other.m_cachedObject;
+ this->child = child;
+ }
+ }
+
+ bool operator==(const QAInterface &other) const;
+ bool operator!=(const QAInterface &other) const;
+
+ inline QString actionText (int action, Text text) const
+ { return base.interface->actionText(action, text, child); }
+
+ QAInterface childAt(int x, int y) const
+ {
+ if (!checkValid())
+ return QAInterface();
+
+ const int foundChild = base.interface->childAt(x, y);
+
+ if (foundChild == -1)
+ return QAInterface();
+
+ if (child == 0)
+ return navigate(QAccessible::Child, foundChild);
+
+ if (foundChild == child)
+ return *this;
+ return QAInterface();
+ }
+
+ int indexOfChild(const QAInterface &child) const
+ {
+ if (!checkValid())
+ return -1;
+
+ if (*this != child.parent())
+ return -1;
+
+ if (object() == child.object())
+ return child.id();
+
+ return base.interface->indexOfChild(child.base.interface);
+ }
+
+ inline int childCount() const
+ {
+ if (!checkValid())
+ return 0;
+
+ if (child != 0)
+ return 0;
+ return base.interface->childCount();
+ }
+
+ QList<QAInterface> children() const
+ {
+ if (!checkValid())
+ return QList<QAInterface>();
+
+ QList<QAInterface> children;
+ for (int i = 1; i <= childCount(); ++i) {
+ children.append(navigate(QAccessible::Child, i));
+ }
+ return children;
+ }
+
+ QAInterface childAt(int index) const
+ {
+ return navigate(QAccessible::Child, index);
+ }
+
+ inline void doAction(int action, const QVariantList &params = QVariantList()) const
+ {
+ if (!checkValid())
+ return;
+
+ base.interface->doAction(action, child, params);
+ }
+
+ QAInterface navigate(RelationFlag relation, int entry) const;
+
+ inline QObject * object() const
+ {
+ if (!checkValid())
+ return 0;
+
+ return base.interface->object();
+ }
+
+ QAInterface objectInterface() const
+ {
+ if (!checkValid())
+ return QAInterface();
+
+ QObject *obj = object();
+ QAInterface current = *this;
+ while (obj == 0)
+ {
+ QAInterface parent = current.parent();
+ if (parent.isValid() == false)
+ break;
+ obj = parent.object();
+ current = parent;
+ }
+ return current;
+ }
+
+ inline HIObjectRef hiObject() const
+ {
+ if (!checkValid())
+ return 0;
+ QWidget * const widget = qobject_cast<QWidget * const>(object());
+ if (widget)
+ return (HIObjectRef)widget->winId();
+ else
+ return 0;
+ }
+
+ inline QObject * cachedObject() const
+ {
+ if (!checkValid())
+ return 0;
+ return m_cachedObject;
+ }
+
+ inline QRect rect() const
+ {
+ if (!checkValid())
+ return QRect();
+ return base.interface->rect(child);
+ }
+
+ inline Role role() const
+ {
+ if (!checkValid())
+ return QAccessible::NoRole;
+ return base.interface->role(child);
+ }
+
+ inline void setText(Text t, const QString &text) const
+ {
+ if (!checkValid())
+ return;
+ base.interface->setText(t, child, text);
+ }
+
+ inline State state() const
+ {
+ if (!checkValid())
+ return 0;
+ return base.interface->state(child);
+ }
+
+ inline QString text (Text text) const
+ {
+ if (!checkValid())
+ return QString();
+ return base.interface->text(text, child);
+ }
+
+ inline QString value() const
+ { return text(QAccessible::Value); }
+
+ inline QString name() const
+ { return text(QAccessible::Name); }
+
+ inline int userActionCount() const
+ {
+ if (!checkValid())
+ return 0;
+ return base.interface->userActionCount(child);
+ }
+
+ inline QString className() const
+ {
+ if (!checkValid())
+ return QString();
+ return QLatin1String(base.interface->object()->metaObject()->className());
+ }
+
+ inline bool isHIView() const
+ { return (child == 0 && object() != 0); }
+
+ inline int id() const
+ { return child; }
+
+ inline bool isValid() const
+ {
+ return (base.interface != 0 && base.interface->isValid());
+ }
+
+ QAInterface parent() const
+ { return navigate(QAccessible::Ancestor, 1); }
+
+ QAccessibleInterfaceWrapper interfaceWrapper() const
+ { return base; }
+
+protected:
+ bool checkValid() const
+ {
+ const bool valid = isValid();
+#ifdef Q_ACCESSIBLE_MAC_DEBUG
+ if (!valid)
+ qFatal("QAccessible_mac: tried to use invalid interface.");
+#endif
+ return valid;
+ }
+
+ QAccessibleInterfaceWrapper base;
+ QObject *m_cachedObject;
+ int child;
+};
+
+Q_AUTOTEST_EXPORT QDebug operator<<(QDebug debug, const QAInterface &interface);
+
+/*
+ QAElement is a thin wrapper around an AXUIElementRef that automates
+ the ref-counting.
+*/
+class Q_AUTOTEST_EXPORT QAElement
+{
+public:
+ QAElement();
+ explicit QAElement(AXUIElementRef elementRef);
+ QAElement(const QAElement &element);
+ QAElement(HIObjectRef, int child);
+ ~QAElement();
+
+ inline HIObjectRef object() const
+ {
+#ifndef Q_WS_MAC64
+ return AXUIElementGetHIObject(elementRef);
+#else
+ return 0;
+#endif
+ }
+
+ inline int id() const
+ {
+ UInt64 theId;
+#ifndef QT_MAC_USE_COCOA
+ AXUIElementGetIdentifier(elementRef, &theId);
+#else
+ theId = 0;
+#endif
+ return theId;
+ }
+
+ inline AXUIElementRef element() const
+ {
+ return elementRef;
+ }
+
+ inline bool isValid() const
+ {
+ return (elementRef != 0);
+ }
+
+ void operator=(const QAElement &other);
+ bool operator==(const QAElement &other) const;
+private:
+ AXUIElementRef elementRef;
+};
+
+
+class QInterfaceFactory
+{
+public:
+ virtual QAInterface interface(UInt64 identifier) = 0;
+ virtual QAElement element(int id) = 0;
+ virtual QAElement element(const QAInterface &interface)
+ {
+ return element(interface.id());
+ }
+ virtual void registerChildren() = 0;
+ virtual ~QInterfaceFactory() {}
+};
+
+/*
+ QAccessibleHierarchyManager bridges the Mac and Qt accessibility hierarchies.
+ There is a one-to-one relationship between QAElements on the Mac side
+ and QAInterfaces on the Qt side, and this class provides lookup functions
+ that translates between these to items.
+
+ The identity of a QAInterface is determined by its QAccessibleInterface and
+ child identifier, and the identity of a QAElement is determined by its
+ HIObjectRef and identifier.
+
+ QAccessibleHierarchyManager receives QObject::destroyed() signals and deletes
+ the accessibility objects for destroyed objects.
+*/
+class Q_AUTOTEST_EXPORT QAccessibleHierarchyManager : public QObject
+{
+Q_OBJECT
+public:
+ ~QAccessibleHierarchyManager() { reset(); }
+ static QAccessibleHierarchyManager *instance();
+ void reset();
+
+ QAElement registerInterface(QObject *object, int child);
+ QAElement registerInterface(const QAInterface &interface);
+ void registerInterface(QObject *object, HIObjectRef hiobject, QInterfaceFactory *interfaceFactory);
+
+ void registerChildren(const QAInterface &interface);
+
+ QAInterface lookup(const AXUIElementRef &element);
+ QAInterface lookup(const QAElement &element);
+ QAElement lookup(const QAInterface &interface);
+ QAElement lookup(QObject * const object, int id);
+private slots:
+ void objectDestroyed(QObject *);
+private:
+ typedef QHash<QObject *, QInterfaceFactory *> QObjectElementHash;
+ typedef QHash<HIObjectRef, QInterfaceFactory *> HIObjectInterfaceHash;
+ typedef QHash<QObject *, HIObjectRef> QObjectHIObjectHash;
+
+ QObjectElementHash qobjectElementHash;
+ HIObjectInterfaceHash hiobjectInterfaceHash;
+ QObjectHIObjectHash qobjectHiobjectHash;
+};
+
+Q_AUTOTEST_EXPORT bool isItInteresting(const QAInterface &interface);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/accessible/qaccessible_unix.cpp b/src/gui/accessible/qaccessible_unix.cpp
new file mode 100644
index 0000000000..f04d075543
--- /dev/null
+++ b/src/gui/accessible/qaccessible_unix.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessible.h"
+#include "qaccessiblebridge.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qcoreapplication.h"
+#include "qmutex.h"
+#include "qvector.h"
+#include "private/qfactoryloader_p.h"
+
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QAccessibleBridgeFactoryInterface_iid, QLatin1String("/accessiblebridge")))
+#endif
+Q_GLOBAL_STATIC(QVector<QAccessibleBridge *>, bridges)
+static bool isInit = false;
+
+void QAccessible::initialize()
+{
+ if (isInit)
+ return;
+ isInit = true;
+
+ if (qgetenv("QT_ACCESSIBILITY") != "1")
+ return;
+#ifndef QT_NO_LIBRARY
+ const QStringList l = loader()->keys();
+ for (int i = 0; i < l.count(); ++i) {
+ if (QAccessibleBridgeFactoryInterface *factory =
+ qobject_cast<QAccessibleBridgeFactoryInterface*>(loader()->instance(l.at(i)))) {
+ QAccessibleBridge * bridge = factory->create(l.at(i));
+ if (bridge)
+ bridges()->append(bridge);
+ }
+ }
+#endif
+}
+
+void QAccessible::cleanup()
+{
+ qDeleteAll(*bridges());
+}
+
+void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
+{
+ Q_ASSERT(o);
+
+ if (updateHandler) {
+ updateHandler(o, who, reason);
+ return;
+ }
+
+ initialize();
+ if (bridges()->isEmpty())
+ return;
+
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(o);
+ if (!iface)
+ return;
+
+ for (int i = 0; i < bridges()->count(); ++i)
+ bridges()->at(i)->notifyAccessibilityUpdate(reason, iface, who);
+ delete iface;
+}
+
+void QAccessible::setRootObject(QObject *o)
+{
+ if (rootObjectHandler) {
+ rootObjectHandler(o);
+ return;
+ }
+
+ initialize();
+ if (bridges()->isEmpty())
+ return;
+
+ if (!o)
+ return;
+
+ for (int i = 0; i < bridges()->count(); ++i) {
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(o);
+ bridges()->at(i)->setRootObject(iface);
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
+
diff --git a/src/gui/accessible/qaccessible_win.cpp b/src/gui/accessible/qaccessible_win.cpp
new file mode 100644
index 0000000000..caa21043d8
--- /dev/null
+++ b/src/gui/accessible/qaccessible_win.cpp
@@ -0,0 +1,1217 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qaccessible.h"
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qapplication.h"
+#include <private/qsystemlibrary_p.h>
+#include "qmessagebox.h" // ### dependency
+#include "qt_windows.h"
+#include "qwidget.h"
+#include "qsettings.h"
+
+#include <winuser.h>
+#if !defined(WINABLEAPI)
+# if defined(Q_WS_WINCE)
+# include <bldver.h>
+# endif
+# include <winable.h>
+#endif
+
+#include <oleacc.h>
+#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
+#include <comdef.h>
+#endif
+
+#ifdef Q_WS_WINCE
+#include "qguifunctions_wince.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+//#define DEBUG_SHOW_ATCLIENT_COMMANDS
+#ifdef DEBUG_SHOW_ATCLIENT_COMMANDS
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <qdebug.h>
+QT_END_INCLUDE_NAMESPACE
+
+static const char *roleString(QAccessible::Role role)
+{
+ static const char *roles[] = {
+ "NoRole" /* = 0x00000000 */,
+ "TitleBar" /* = 0x00000001 */,
+ "MenuBar" /* = 0x00000002 */,
+ "ScrollBar" /* = 0x00000003 */,
+ "Grip" /* = 0x00000004 */,
+ "Sound" /* = 0x00000005 */,
+ "Cursor" /* = 0x00000006 */,
+ "Caret" /* = 0x00000007 */,
+ "AlertMessage" /* = 0x00000008 */,
+ "Window" /* = 0x00000009 */,
+ "Client" /* = 0x0000000A */,
+ "PopupMenu" /* = 0x0000000B */,
+ "MenuItem" /* = 0x0000000C */,
+ "ToolTip" /* = 0x0000000D */,
+ "Application" /* = 0x0000000E */,
+ "Document" /* = 0x0000000F */,
+ "Pane" /* = 0x00000010 */,
+ "Chart" /* = 0x00000011 */,
+ "Dialog" /* = 0x00000012 */,
+ "Border" /* = 0x00000013 */,
+ "Grouping" /* = 0x00000014 */,
+ "Separator" /* = 0x00000015 */,
+ "ToolBar" /* = 0x00000016 */,
+ "StatusBar" /* = 0x00000017 */,
+ "Table" /* = 0x00000018 */,
+ "ColumnHeader" /* = 0x00000019 */,
+ "RowHeader" /* = 0x0000001A */,
+ "Column" /* = 0x0000001B */,
+ "Row" /* = 0x0000001C */,
+ "Cell" /* = 0x0000001D */,
+ "Link" /* = 0x0000001E */,
+ "HelpBalloon" /* = 0x0000001F */,
+ "Assistant" /* = 0x00000020 */,
+ "List" /* = 0x00000021 */,
+ "ListItem" /* = 0x00000022 */,
+ "Tree" /* = 0x00000023 */,
+ "TreeItem" /* = 0x00000024 */,
+ "PageTab" /* = 0x00000025 */,
+ "PropertyPage" /* = 0x00000026 */,
+ "Indicator" /* = 0x00000027 */,
+ "Graphic" /* = 0x00000028 */,
+ "StaticText" /* = 0x00000029 */,
+ "EditableText" /* = 0x0000002A */, // Editable, selectable, etc.
+ "PushButton" /* = 0x0000002B */,
+ "CheckBox" /* = 0x0000002C */,
+ "RadioButton" /* = 0x0000002D */,
+ "ComboBox" /* = 0x0000002E */,
+ "DropList" /* = 0x0000002F */, // commented out
+ "ProgressBar" /* = 0x00000030 */,
+ "Dial" /* = 0x00000031 */,
+ "HotkeyField" /* = 0x00000032 */,
+ "Slider" /* = 0x00000033 */,
+ "SpinBox" /* = 0x00000034 */,
+ "Canvas" /* = 0x00000035 */,
+ "Animation" /* = 0x00000036 */,
+ "Equation" /* = 0x00000037 */,
+ "ButtonDropDown" /* = 0x00000038 */,
+ "ButtonMenu" /* = 0x00000039 */,
+ "ButtonDropGrid" /* = 0x0000003A */,
+ "Whitespace" /* = 0x0000003B */,
+ "PageTabList" /* = 0x0000003C */,
+ "Clock" /* = 0x0000003D */,
+ "Splitter" /* = 0x0000003E */,
+ "LayeredPane" /* = 0x0000003F */,
+ "UserRole" /* = 0x0000ffff*/
+ };
+
+ if (role >=0x40)
+ role = QAccessible::UserRole;
+ return roles[int(role)];
+}
+
+void showDebug(const char* funcName, const QAccessibleInterface *iface)
+{
+ qDebug() << "Role:" << roleString(iface->role(0))
+ << "Name:" << iface->text(QAccessible::Name, 0)
+ << "State:" << QString::number(int(iface->state(0)), 16)
+ << QLatin1String(funcName);
+}
+#else
+# define showDebug(f, iface)
+#endif
+
+void QAccessible::initialize()
+{
+
+}
+void QAccessible::cleanup()
+{
+
+}
+
+void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
+{
+ Q_ASSERT(o);
+
+ if (updateHandler) {
+ updateHandler(o, who, reason);
+ return;
+ }
+
+ QString soundName;
+ switch (reason) {
+ case PopupMenuStart:
+ soundName = QLatin1String("MenuPopup");
+ break;
+
+ case MenuCommand:
+ soundName = QLatin1String("MenuCommand");
+ break;
+
+ case Alert:
+ {
+#ifndef QT_NO_MESSAGEBOX
+ QMessageBox *mb = qobject_cast<QMessageBox*>(o);
+ if (mb) {
+ switch (mb->icon()) {
+ case QMessageBox::Warning:
+ soundName = QLatin1String("SystemExclamation");
+ break;
+ case QMessageBox::Critical:
+ soundName = QLatin1String("SystemHand");
+ break;
+ case QMessageBox::Information:
+ soundName = QLatin1String("SystemAsterisk");
+ break;
+ default:
+ break;
+ }
+ } else
+#endif // QT_NO_MESSAGEBOX
+ {
+ soundName = QLatin1String("SystemAsterisk");
+ }
+
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (soundName.size()) {
+#ifndef QT_NO_SETTINGS
+ QSettings settings(QLatin1String("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\.Default\\") + soundName,
+ QSettings::NativeFormat);
+ QString file = settings.value(QLatin1String(".Current/.")).toString();
+#else
+ QString file;
+#endif
+ if (!file.isEmpty()) {
+ PlaySound(reinterpret_cast<const wchar_t *>(soundName.utf16()), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT);
+ }
+ }
+
+ if (!isActive())
+ return;
+
+ typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG);
+
+#if defined(Q_WS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0
+ // There is no user32.lib nor NotifyWinEvent for CE
+ return;
+#else
+ static PtrNotifyWinEvent ptrNotifyWinEvent = 0;
+ static bool resolvedNWE = false;
+ if (!resolvedNWE) {
+ resolvedNWE = true;
+ ptrNotifyWinEvent = (PtrNotifyWinEvent)QSystemLibrary::resolve(QLatin1String("user32"), "NotifyWinEvent");
+ }
+ if (!ptrNotifyWinEvent)
+ return;
+
+ // An event has to be associated with a window,
+ // so find the first parent that is a widget.
+ QWidget *w = 0;
+ if (o->isWidgetType()) {
+ w = (QWidget*)o;
+ } else {
+ QObject *p = o;
+ while ((p = p->parent()) != 0) {
+ if (p->isWidgetType()) {
+ w = (QWidget*)p;
+ break;
+ }
+ }
+ }
+
+ if (!w) {
+ if (reason != QAccessible::ContextHelpStart &&
+ reason != QAccessible::ContextHelpEnd)
+ w = QApplication::focusWidget();
+ if (!w) {
+ w = QApplication::activeWindow();
+
+ if (!w)
+ return;
+
+// ### Fixme
+// if (!w) {
+// w = qApp->mainWidget();
+// if (!w)
+// return;
+// }
+ }
+ }
+
+ if (reason != MenuCommand) { // MenuCommand is faked
+ ptrNotifyWinEvent(reason, w->winId(), OBJID_CLIENT, who);
+ }
+#endif // Q_WS_WINCE
+}
+
+void QAccessible::setRootObject(QObject *o)
+{
+ if (rootObjectHandler) {
+ rootObjectHandler(o);
+ }
+}
+
+class QWindowsEnumerate : public IEnumVARIANT
+{
+public:
+ QWindowsEnumerate(const QVector<int> &a)
+ : ref(0), current(0),array(a)
+ {
+ }
+
+ virtual ~QWindowsEnumerate() {}
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum);
+ HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched);
+ HRESULT STDMETHODCALLTYPE Reset();
+ HRESULT STDMETHODCALLTYPE Skip(unsigned long celt);
+
+private:
+ ULONG ref;
+ ULONG current;
+ QVector<int> array;
+};
+
+HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *iface)
+{
+ *iface = 0;
+ if (id == IID_IUnknown)
+ *iface = (IUnknown*)this;
+ else if (id == IID_IEnumVARIANT)
+ *iface = (IEnumVARIANT*)this;
+
+ if (*iface) {
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+ULONG STDMETHODCALLTYPE QWindowsEnumerate::AddRef()
+{
+ return ++ref;
+}
+
+ULONG STDMETHODCALLTYPE QWindowsEnumerate::Release()
+{
+ if (!--ref) {
+ delete this;
+ return 0;
+ }
+ return ref;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum)
+{
+ QWindowsEnumerate *penum = 0;
+ *ppEnum = 0;
+
+ penum = new QWindowsEnumerate(array);
+ if (!penum)
+ return E_OUTOFMEMORY;
+ penum->current = current;
+ penum->array = array;
+ penum->AddRef();
+ *ppEnum = penum;
+
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched)
+{
+ if (pCeltFetched)
+ *pCeltFetched = 0;
+
+ ULONG l;
+ for (l = 0; l < celt; l++) {
+ VariantInit(&rgVar[l]);
+ if ((current+1) > (ULONG)array.size()) {
+ *pCeltFetched = l;
+ return S_FALSE;
+ }
+
+ rgVar[l].vt = VT_I4;
+ rgVar[l].lVal = array[(int)current];
+ ++current;
+ }
+ *pCeltFetched = l;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Reset()
+{
+ current = 0;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt)
+{
+ current += celt;
+ if (current > (ULONG)array.size()) {
+ current = array.size();
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
+/*
+*/
+class QWindowsAccessible : public IAccessible, IOleWindow, QAccessible
+{
+public:
+ QWindowsAccessible(QAccessibleInterface *a)
+ : ref(0), accessible(a)
+ {
+ }
+
+ virtual ~QWindowsAccessible()
+ {
+ delete accessible;
+ }
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ HRESULT STDMETHODCALLTYPE GetTypeInfoCount(unsigned int *);
+ HRESULT STDMETHODCALLTYPE GetTypeInfo(unsigned int, unsigned long, ITypeInfo **);
+ HRESULT STDMETHODCALLTYPE GetIDsOfNames(const _GUID &, wchar_t **, unsigned int, unsigned long, long *);
+ HRESULT STDMETHODCALLTYPE Invoke(long, const _GUID &, unsigned long, unsigned short, tagDISPPARAMS *, tagVARIANT *, tagEXCEPINFO *, unsigned int *);
+
+ HRESULT STDMETHODCALLTYPE accHitTest(long xLeft, long yTop, VARIANT *pvarID);
+ HRESULT STDMETHODCALLTYPE accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID);
+ HRESULT STDMETHODCALLTYPE accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd);
+ HRESULT STDMETHODCALLTYPE get_accChild(VARIANT varChildID, IDispatch** ppdispChild);
+ HRESULT STDMETHODCALLTYPE get_accChildCount(long* pcountChildren);
+ HRESULT STDMETHODCALLTYPE get_accParent(IDispatch** ppdispParent);
+
+ HRESULT STDMETHODCALLTYPE accDoDefaultAction(VARIANT varID);
+ HRESULT STDMETHODCALLTYPE get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction);
+ HRESULT STDMETHODCALLTYPE get_accDescription(VARIANT varID, BSTR* pszDescription);
+ HRESULT STDMETHODCALLTYPE get_accHelp(VARIANT varID, BSTR *pszHelp);
+ HRESULT STDMETHODCALLTYPE get_accHelpTopic(BSTR *pszHelpFile, VARIANT varChild, long *pidTopic);
+ HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut);
+ HRESULT STDMETHODCALLTYPE get_accName(VARIANT varID, BSTR* pszName);
+ HRESULT STDMETHODCALLTYPE put_accName(VARIANT varChild, BSTR szName);
+ HRESULT STDMETHODCALLTYPE get_accRole(VARIANT varID, VARIANT *pvarRole);
+ HRESULT STDMETHODCALLTYPE get_accState(VARIANT varID, VARIANT *pvarState);
+ HRESULT STDMETHODCALLTYPE get_accValue(VARIANT varID, BSTR* pszValue);
+ HRESULT STDMETHODCALLTYPE put_accValue(VARIANT varChild, BSTR szValue);
+
+ HRESULT STDMETHODCALLTYPE accSelect(long flagsSelect, VARIANT varID);
+ HRESULT STDMETHODCALLTYPE get_accFocus(VARIANT *pvarID);
+ HRESULT STDMETHODCALLTYPE get_accSelection(VARIANT *pvarChildren);
+
+ HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
+ HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
+
+private:
+ ULONG ref;
+ QAccessibleInterface *accessible;
+};
+
+static inline BSTR QStringToBSTR(const QString &str)
+{
+ BSTR bstrVal;
+
+ int wlen = str.length()+1;
+ bstrVal = SysAllocStringByteLen(0, wlen*2);
+ memcpy(bstrVal, str.unicode(), sizeof(QChar)*(wlen));
+ bstrVal[wlen] = 0;
+
+ return bstrVal;
+}
+
+/*
+*/
+IAccessible *qt_createWindowsAccessible(QAccessibleInterface *access)
+{
+ QWindowsAccessible *acc = new QWindowsAccessible(access);
+ IAccessible *iface;
+ acc->QueryInterface(IID_IAccessible, (void**)&iface);
+
+ return iface;
+}
+
+/*
+ IUnknown
+*/
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::QueryInterface(REFIID id, LPVOID *iface)
+{
+ *iface = 0;
+ if (id == IID_IUnknown)
+ *iface = (IUnknown*)(IDispatch*)this;
+ else if (id == IID_IDispatch)
+ *iface = (IDispatch*)this;
+ else if (id == IID_IAccessible)
+ *iface = (IAccessible*)this;
+ else if (id == IID_IOleWindow)
+ *iface = (IOleWindow*)this;
+ else
+ return E_NOINTERFACE;
+
+ AddRef();
+ return S_OK;
+}
+
+ULONG STDMETHODCALLTYPE QWindowsAccessible::AddRef()
+{
+ return ++ref;
+}
+
+ULONG STDMETHODCALLTYPE QWindowsAccessible::Release()
+{
+ if (!--ref) {
+ delete this;
+ return 0;
+ }
+ return ref;
+}
+
+/*
+ IDispatch
+*/
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfoCount(unsigned int * pctinfo)
+{
+ // We don't use a type library
+ *pctinfo = 0;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfo(unsigned int, unsigned long, ITypeInfo **pptinfo)
+{
+ // We don't use a type library
+ *pptinfo = 0;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetIDsOfNames(const _GUID &, wchar_t **rgszNames, unsigned int, unsigned long, long *rgdispid)
+{
+#if !defined(Q_CC_BOR) && !defined(Q_CC_GNU)
+ // PROPERTIES: Hierarchical
+ if (_bstr_t(rgszNames[0]) == _bstr_t(L"accParent"))
+ rgdispid[0] = DISPID_ACC_PARENT;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accChildCount"))
+ rgdispid[0] = DISPID_ACC_CHILDCOUNT;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accChild"))
+ rgdispid[0] = DISPID_ACC_CHILD;
+
+ // PROPERTIES: Descriptional
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accName("))
+ rgdispid[0] = DISPID_ACC_NAME;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accValue"))
+ rgdispid[0] = DISPID_ACC_VALUE;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accDescription"))
+ rgdispid[0] = DISPID_ACC_DESCRIPTION;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accRole"))
+ rgdispid[0] = DISPID_ACC_ROLE;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accState"))
+ rgdispid[0] = DISPID_ACC_STATE;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accHelp"))
+ rgdispid[0] = DISPID_ACC_HELP;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accHelpTopic"))
+ rgdispid[0] = DISPID_ACC_HELPTOPIC;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accKeyboardShortcut"))
+ rgdispid[0] = DISPID_ACC_KEYBOARDSHORTCUT;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accFocus"))
+ rgdispid[0] = DISPID_ACC_FOCUS;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accSelection"))
+ rgdispid[0] = DISPID_ACC_SELECTION;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accDefaultAction"))
+ rgdispid[0] = DISPID_ACC_DEFAULTACTION;
+
+ // METHODS
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accSelect"))
+ rgdispid[0] = DISPID_ACC_SELECT;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accLocation"))
+ rgdispid[0] = DISPID_ACC_LOCATION;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accNavigate"))
+ rgdispid[0] = DISPID_ACC_NAVIGATE;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accHitTest"))
+ rgdispid[0] = DISPID_ACC_HITTEST;
+ else if(_bstr_t(rgszNames[0]) == _bstr_t(L"accDoDefaultAction"))
+ rgdispid[0] = DISPID_ACC_DODEFAULTACTION;
+ else
+ return DISP_E_UNKNOWNINTERFACE;
+
+ return S_OK;
+#else
+ Q_UNUSED(rgszNames);
+ Q_UNUSED(rgdispid);
+
+ return DISP_E_MEMBERNOTFOUND;
+#endif
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::Invoke(long dispIdMember, const _GUID &, unsigned long, unsigned short wFlags, tagDISPPARAMS *pDispParams, tagVARIANT *pVarResult, tagEXCEPINFO *, unsigned int *)
+{
+ HRESULT hr = DISP_E_MEMBERNOTFOUND;
+
+ switch(dispIdMember)
+ {
+ case DISPID_ACC_PARENT:
+ if (wFlags == DISPATCH_PROPERTYGET) {
+ if (!pVarResult)
+ return E_INVALIDARG;
+ hr = get_accParent(&pVarResult->pdispVal);
+ } else {
+ hr = DISP_E_MEMBERNOTFOUND;
+ }
+ break;
+
+ case DISPID_ACC_CHILDCOUNT:
+ if (wFlags == DISPATCH_PROPERTYGET) {
+ if (!pVarResult)
+ return E_INVALIDARG;
+ hr = get_accChildCount(&pVarResult->lVal);
+ } else {
+ hr = DISP_E_MEMBERNOTFOUND;
+ }
+ break;
+
+ case DISPID_ACC_CHILD:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accChild(pDispParams->rgvarg[0], &pVarResult->pdispVal);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_NAME:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accName(pDispParams->rgvarg[0], &pVarResult->bstrVal);
+ else if (wFlags == DISPATCH_PROPERTYPUT)
+ hr = put_accName(pDispParams->rgvarg[0], pVarResult->bstrVal);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_VALUE:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accValue(pDispParams->rgvarg[0], &pVarResult->bstrVal);
+ else if (wFlags == DISPATCH_PROPERTYPUT)
+ hr = put_accValue(pDispParams->rgvarg[0], pVarResult->bstrVal);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_DESCRIPTION:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accDescription(pDispParams->rgvarg[0], &pVarResult->bstrVal);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_ROLE:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accRole(pDispParams->rgvarg[0], pVarResult);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_STATE:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accState(pDispParams->rgvarg[0], pVarResult);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_HELP:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accHelp(pDispParams->rgvarg[0], &pVarResult->bstrVal);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_HELPTOPIC:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accHelpTopic(&pDispParams->rgvarg[2].bstrVal, pDispParams->rgvarg[1], &pDispParams->rgvarg[0].lVal);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_KEYBOARDSHORTCUT:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accKeyboardShortcut(pDispParams->rgvarg[0], &pVarResult->bstrVal);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_FOCUS:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accFocus(pVarResult);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_SELECTION:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accSelection(pVarResult);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_DEFAULTACTION:
+ if (wFlags == DISPATCH_PROPERTYGET)
+ hr = get_accDefaultAction(pDispParams->rgvarg[0], &pVarResult->bstrVal);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_SELECT:
+ if (wFlags == DISPATCH_METHOD)
+ hr = accSelect(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_LOCATION:
+ if (wFlags == DISPATCH_METHOD)
+ hr = accLocation(&pDispParams->rgvarg[4].lVal, &pDispParams->rgvarg[3].lVal, &pDispParams->rgvarg[2].lVal, &pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0]);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_NAVIGATE:
+ if (wFlags == DISPATCH_METHOD)
+ hr = accNavigate(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0], pVarResult);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_HITTEST:
+ if (wFlags == DISPATCH_METHOD)
+ hr = accHitTest(pDispParams->rgvarg[1].lVal, pDispParams->rgvarg[0].lVal, pVarResult);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ case DISPID_ACC_DODEFAULTACTION:
+ if (wFlags == DISPATCH_METHOD)
+ hr = accDoDefaultAction(pDispParams->rgvarg[0]);
+ else
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+
+ default:
+ hr = DISP_E_MEMBERNOTFOUND;
+ break;
+ }
+
+ if (!SUCCEEDED(hr)) {
+ return hr;
+ }
+ return hr;
+}
+
+/*
+ IAccessible
+*/
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ int control = accessible->childAt(xLeft, yTop);
+ if (control == -1) {
+ (*pvarID).vt = VT_EMPTY;
+ return S_FALSE;
+ }
+ QAccessibleInterface *acc = 0;
+ if (control)
+ accessible->navigate(Child, control, &acc);
+ if (!acc) {
+ (*pvarID).vt = VT_I4;
+ (*pvarID).lVal = control;
+ return S_OK;
+ }
+
+ QWindowsAccessible* wacc = new QWindowsAccessible(acc);
+ IDispatch *iface = 0;
+ wacc->QueryInterface(IID_IDispatch, (void**)&iface);
+ if (iface) {
+ (*pvarID).vt = VT_DISPATCH;
+ (*pvarID).pdispVal = iface;
+ return S_OK;
+ } else {
+ delete wacc;
+ }
+
+ (*pvarID).vt = VT_EMPTY;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QRect rect = accessible->rect(varID.lVal);
+ if (rect.isValid()) {
+ *pxLeft = rect.x();
+ *pyTop = rect.y();
+ *pcxWidth = rect.width();
+ *pcyHeight = rect.height();
+ } else {
+ *pxLeft = 0;
+ *pyTop = 0;
+ *pcxWidth = 0;
+ *pcyHeight = 0;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QAccessibleInterface *acc = 0;
+ int control = -1;
+ switch(navDir) {
+ case NAVDIR_FIRSTCHILD:
+ control = accessible->navigate(Child, 1, &acc);
+ break;
+ case NAVDIR_LASTCHILD:
+ control = accessible->navigate(Child, accessible->childCount(), &acc);
+ break;
+ case NAVDIR_NEXT:
+ case NAVDIR_PREVIOUS:
+ if (!varStart.lVal){
+ QAccessibleInterface *parent = 0;
+ accessible->navigate(Ancestor, 1, &parent);
+ if (parent) {
+ int index = parent->indexOfChild(accessible);
+ index += (navDir == NAVDIR_NEXT) ? 1 : -1;
+ if (index > 0 && index <= parent->childCount())
+ control = parent->navigate(Child, index, &acc);
+ delete parent;
+ }
+ } else {
+ int index = varStart.lVal;
+ index += (navDir == NAVDIR_NEXT) ? 1 : -1;
+ if (index > 0 && index <= accessible->childCount())
+ control = accessible->navigate(Child, index, &acc);
+ }
+ break;
+ case NAVDIR_UP:
+ control = accessible->navigate(Up, varStart.lVal, &acc);
+ break;
+ case NAVDIR_DOWN:
+ control = accessible->navigate(Down, varStart.lVal, &acc);
+ break;
+ case NAVDIR_LEFT:
+ control = accessible->navigate(Left, varStart.lVal, &acc);
+ break;
+ case NAVDIR_RIGHT:
+ control = accessible->navigate(Right, varStart.lVal, &acc);
+ break;
+ default:
+ break;
+ }
+ if (control == -1) {
+ (*pvarEnd).vt = VT_EMPTY;
+ return S_FALSE;
+ }
+ if (!acc) {
+ (*pvarEnd).vt = VT_I4;
+ (*pvarEnd).lVal = control;
+ return S_OK;
+ }
+
+ QWindowsAccessible* wacc = new QWindowsAccessible(acc);
+
+ IDispatch *iface = 0;
+ wacc->QueryInterface(IID_IDispatch, (void**)&iface);
+ if (iface) {
+ (*pvarEnd).vt = VT_DISPATCH;
+ (*pvarEnd).pdispVal = iface;
+ return S_OK;
+ } else {
+ delete wacc;
+ }
+
+ (*pvarEnd).vt = VT_EMPTY;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (varChildID.vt == VT_EMPTY)
+ return E_INVALIDARG;
+
+ QAccessibleInterface *acc = 0;
+ RelationFlag rel = varChildID.lVal ? Child : Self;
+ accessible->navigate(rel, varChildID.lVal, &acc);
+
+ if (acc) {
+ QWindowsAccessible* wacc = new QWindowsAccessible(acc);
+ wacc->QueryInterface(IID_IDispatch, (void**)ppdispChild);
+ return S_OK;
+ }
+
+ *ppdispChild = 0;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ *pcountChildren = accessible->childCount();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispParent)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QAccessibleInterface *acc = 0;
+ accessible->navigate(Ancestor, 1, &acc);
+ if (acc) {
+ QWindowsAccessible* wacc = new QWindowsAccessible(acc);
+ wacc->QueryInterface(IID_IDispatch, (void**)ppdispParent);
+
+ if (*ppdispParent)
+ return S_OK;
+ }
+
+ *ppdispParent = 0;
+ return S_FALSE;
+}
+
+/*
+ Properties and methods
+*/
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ return accessible->doAction(DefaultAction, varID.lVal, QVariantList()) ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QString def = accessible->actionText(DefaultAction, Name, varID.lVal);
+ if (def.isEmpty()) {
+ *pszDefaultAction = 0;
+ return S_FALSE;
+ }
+
+ *pszDefaultAction = QStringToBSTR(def);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QString descr = accessible->text(Description, varID.lVal);
+ if (descr.size()) {
+ *pszDescription = QStringToBSTR(descr);
+ return S_OK;
+ }
+
+ *pszDescription = 0;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QString help = accessible->text(Help, varID.lVal);
+ if (help.size()) {
+ *pszHelp = QStringToBSTR(help);
+ return S_OK;
+ }
+
+ *pszHelp = 0;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
+{
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QString sc = accessible->text(Accelerator, varID.lVal);
+ if (sc.size()) {
+ *pszKeyboardShortcut = QStringToBSTR(sc);
+ return S_OK;
+ }
+
+ *pszKeyboardShortcut = 0;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* pszName)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QString n = accessible->text(Name, varID.lVal);
+ if (n.size()) {
+ *pszName = QStringToBSTR(n);
+ return S_OK;
+ }
+
+ *pszName = 0;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accName(VARIANT, BSTR)
+{
+ showDebug(__FUNCTION__, accessible);
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ Role role = accessible->role(varID.lVal);
+ if (role != NoRole) {
+ if (role == LayeredPane)
+ role = QAccessible::Pane;
+ (*pvarRole).vt = VT_I4;
+ (*pvarRole).lVal = role;
+ } else {
+ (*pvarRole).vt = VT_EMPTY;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ (*pvarState).vt = VT_I4;
+ (*pvarState).lVal = accessible->state(varID.lVal);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* pszValue)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QString value = accessible->text(Value, varID.lVal);
+ if (!value.isNull()) {
+ *pszValue = QStringToBSTR(value);
+ return S_OK;
+ }
+
+ *pszValue = 0;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accValue(VARIANT, BSTR)
+{
+ showDebug(__FUNCTION__, accessible);
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIANT varID)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ bool res = false;
+
+ if (flagsSelect & SELFLAG_TAKEFOCUS)
+ res = accessible->doAction(SetFocus, varID.lVal, QVariantList());
+ if (flagsSelect & SELFLAG_TAKESELECTION) {
+ accessible->doAction(ClearSelection, 0, QVariantList());
+ res = accessible->doAction(AddToSelection, varID.lVal, QVariantList());
+ }
+ if (flagsSelect & SELFLAG_EXTENDSELECTION)
+ res = accessible->doAction(ExtendSelection, varID.lVal, QVariantList());
+ if (flagsSelect & SELFLAG_ADDSELECTION)
+ res = accessible->doAction(AddToSelection, varID.lVal, QVariantList());
+ if (flagsSelect & SELFLAG_REMOVESELECTION)
+ res = accessible->doAction(RemoveSelection, varID.lVal, QVariantList());
+
+ return res ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QAccessibleInterface *acc = 0;
+ int control = accessible->navigate(FocusChild, 1, &acc);
+ if (control == -1) {
+ (*pvarID).vt = VT_EMPTY;
+ return S_FALSE;
+ }
+ if (!acc || control == 0) {
+ (*pvarID).vt = VT_I4;
+ (*pvarID).lVal = control ? control : CHILDID_SELF;
+ return S_OK;
+ }
+
+ QWindowsAccessible* wacc = new QWindowsAccessible(acc);
+ IDispatch *iface = 0;
+ wacc->QueryInterface(IID_IDispatch, (void**)&iface);
+ if (iface) {
+ (*pvarID).vt = VT_DISPATCH;
+ (*pvarID).pdispVal = iface;
+ return S_OK;
+ } else {
+ delete wacc;
+ }
+
+ (*pvarID).vt = VT_EMPTY;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren)
+{
+ showDebug(__FUNCTION__, accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ int cc = accessible->childCount();
+ QVector<int> sel(cc);
+ int selIndex = 0;
+ for (int i = 1; i <= cc; ++i) {
+ QAccessibleInterface *child = 0;
+ int i2 = accessible->navigate(Child, i, &child);
+ bool isSelected = false;
+ if (child) {
+ isSelected = child->state(0) & Selected;
+ delete child;
+ child = 0;
+ } else {
+ isSelected = accessible->state(i2) & Selected;
+ }
+ if (isSelected)
+ sel[selIndex++] = i;
+ }
+ sel.resize(selIndex);
+ if (sel.isEmpty()) {
+ (*pvarChildren).vt = VT_EMPTY;
+ return S_FALSE;
+ }
+ if (sel.size() == 1) {
+ (*pvarChildren).vt = VT_I4;
+ (*pvarChildren).lVal = sel[0];
+ return S_OK;
+ }
+ IEnumVARIANT *iface = new QWindowsEnumerate(sel);
+ IUnknown *uiface;
+ iface->QueryInterface(IID_IUnknown, (void**)&uiface);
+ (*pvarChildren).vt = VT_UNKNOWN;
+ (*pvarChildren).punkVal = uiface;
+
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetWindow(HWND *phwnd)
+{
+ *phwnd = 0;
+ if (!accessible->isValid())
+ return E_UNEXPECTED;
+
+ QObject *o = accessible->object();
+ if (!o || !o->isWidgetType())
+ return E_FAIL;
+
+ *phwnd = static_cast<QWidget*>(o)->winId();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsAccessible::ContextSensitiveHelp(BOOL)
+{
+ return S_OK;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/gui/accessible/qaccessiblebridge.cpp b/src/gui/accessible/qaccessiblebridge.cpp
new file mode 100644
index 0000000000..e151bb6752
--- /dev/null
+++ b/src/gui/accessible/qaccessiblebridge.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblebridge.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAccessibleBridge
+ \brief The QAccessibleBridge class is the base class for
+ accessibility back-ends.
+
+ \ingroup accessibility
+
+ Qt supports Microsoft Active Accessibility (MSAA), Mac OS X
+ Accessibility, and the Unix/X11 AT-SPI standard. By subclassing
+ QAccessibleBridge, you can support other backends than the
+ predefined ones.
+
+ Currently, custom bridges are only supported on Unix. We might
+ add support for them on other platforms as well if there is
+ enough demand.
+
+ \sa QAccessible, QAccessibleBridgePlugin
+*/
+
+/*!
+ \fn QAccessibleBridge::~QAccessibleBridge()
+
+ Destroys the accessibility bridge object.
+*/
+
+/*!
+ \fn void QAccessibleBridge::setRootObject(QAccessibleInterface *object)
+
+ This function is called by Qt at application startup to set the
+ root accessible object of the application to \a object. All other
+ accessible objects in the application can be reached by the
+ client using object navigation.
+*/
+
+/*!
+ \fn void QAccessibleBridge::notifyAccessibilityUpdate(int reason, QAccessibleInterface *interface, int child)
+
+ This function is called by Qt to notify the bridge about a change
+ in the accessibility information for object wrapped by the given
+ \a interface.
+
+ \a reason specifies the cause of the change. It can take values
+ of type QAccessible::Event.
+
+ \a child is the (1-based) index of the child element that has
+ changed. When \a child is 0, the object itself has changed.
+
+ \sa QAccessible::updateAccessibility()
+*/
+
+/*!
+ \class QAccessibleBridgePlugin
+ \brief The QAccessibleBridgePlugin class provides an abstract
+ base for accessibility bridge plugins.
+
+ \ingroup plugins
+ \ingroup accessibility
+
+ Writing an accessibility bridge plugin is achieved by subclassing
+ this base class, reimplementing the pure virtual functions keys()
+ and create(), and exporting the class with the
+ Q_EXPORT_PLUGIN2() macro.
+
+ \sa QAccessibleBridge, QAccessiblePlugin, {How to Create Qt Plugins}
+*/
+
+/*!
+ Constructs an accessibility bridge plugin with the given \a
+ parent. This is invoked automatically by the Q_EXPORT_PLUGIN2()
+ macro.
+*/
+QAccessibleBridgePlugin::QAccessibleBridgePlugin(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+/*!
+ Destroys the accessibility bridge plugin.
+
+ You never have to call this explicitly. Qt destroys a plugin
+ automatically when it is no longer used.
+*/
+QAccessibleBridgePlugin::~QAccessibleBridgePlugin()
+{
+
+}
+
+/*!
+ \fn QStringList QAccessibleBridgePlugin::keys() const
+
+ Returns the list of keys this plugins supports.
+
+ These keys must be the names of the bridges that this
+ plugin provides.
+
+ \sa create()
+*/
+
+/*!
+ \fn QAccessibleBridge *QAccessibleBridgePlugin::create(const QString &key)
+
+ Creates and returns the QAccessibleBridge object corresponding to
+ the given \a key. Keys are case sensitive.
+
+ \sa keys()
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/gui/accessible/qaccessiblebridge.h b/src/gui/accessible/qaccessiblebridge.h
new file mode 100644
index 0000000000..d5e35df33f
--- /dev/null
+++ b/src/gui/accessible/qaccessiblebridge.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEBRIDGE_H
+#define QACCESSIBLEBRIDGE_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAccessibleInterface;
+
+class QAccessibleBridge
+{
+public:
+ virtual ~QAccessibleBridge() {}
+ virtual void setRootObject(QAccessibleInterface *) = 0;
+ virtual void notifyAccessibilityUpdate(int, QAccessibleInterface*, int) = 0;
+};
+
+struct Q_GUI_EXPORT QAccessibleBridgeFactoryInterface : public QFactoryInterface
+{
+ virtual QAccessibleBridge *create(const QString& name) = 0;
+};
+
+#define QAccessibleBridgeFactoryInterface_iid "com.trolltech.Qt.QAccessibleBridgeFactoryInterface"
+Q_DECLARE_INTERFACE(QAccessibleBridgeFactoryInterface, QAccessibleBridgeFactoryInterface_iid)
+
+class Q_GUI_EXPORT QAccessibleBridgePlugin : public QObject, public QAccessibleBridgeFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QAccessibleBridgeFactoryInterface:QFactoryInterface)
+public:
+ explicit QAccessibleBridgePlugin(QObject *parent = 0);
+ ~QAccessibleBridgePlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QAccessibleBridge *create(const QString &key) = 0;
+};
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACCESSIBLEBRIDGE_H
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
new file mode 100644
index 0000000000..1d2d1da806
--- /dev/null
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessibleobject.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qapplication.h"
+#include "qwidget.h"
+#include "qpointer.h"
+#include "qmetaobject.h"
+#include "qvarlengtharray.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAccessibleObjectPrivate
+{
+public:
+ QPointer<QObject> object;
+
+ QList<QByteArray> actionList() const;
+};
+
+QList<QByteArray> QAccessibleObjectPrivate::actionList() const
+{
+ QList<QByteArray> actionList;
+
+ if (!object)
+ return actionList;
+
+ const QMetaObject *mo = object->metaObject();
+ Q_ASSERT(mo);
+
+ QByteArray defaultAction = QMetaObject::normalizedSignature(
+ mo->classInfo(mo->indexOfClassInfo("DefaultSlot")).value());
+
+ for (int i = 0; i < mo->methodCount(); ++i) {
+ const QMetaMethod member = mo->method(i);
+ if (member.methodType() != QMetaMethod::Slot && member.access() != QMetaMethod::Public)
+ continue;
+
+ if (!qstrcmp(member.tag(), "QACCESSIBLE_SLOT")) {
+ if (member.signature() == defaultAction)
+ actionList.prepend(defaultAction);
+ else
+ actionList << member.signature();
+ }
+ }
+
+ return actionList;
+}
+
+/*!
+ \class QAccessibleObject
+ \brief The QAccessibleObject class implements parts of the
+ QAccessibleInterface for QObjects.
+
+ \ingroup accessibility
+
+ This class is mainly provided for convenience. All subclasses of
+ the QAccessibleInterface that provide implementations of non-widget objects
+ should use this class as their base class.
+
+ \sa QAccessible, QAccessibleWidget
+*/
+
+/*!
+ Creates a QAccessibleObject for \a object.
+*/
+QAccessibleObject::QAccessibleObject(QObject *object)
+{
+ d = new QAccessibleObjectPrivate;
+ d->object = object;
+}
+
+/*!
+ Destroys the QAccessibleObject.
+
+ This only happens when a call to release() decrements the internal
+ reference counter to zero.
+*/
+QAccessibleObject::~QAccessibleObject()
+{
+ delete d;
+}
+
+/*!
+ \reimp
+*/
+QObject *QAccessibleObject::object() const
+{
+#ifndef QT_NO_DEBUG
+ if (!d->object)
+ qWarning("QAccessibleInterface is invalid. Crash pending...");
+#endif
+ return d->object;
+}
+
+/*!
+ \reimp
+*/
+bool QAccessibleObject::isValid() const
+{
+ return !d->object.isNull();
+}
+
+/*! \reimp */
+QRect QAccessibleObject::rect(int) const
+{
+ return QRect();
+}
+
+/*! \reimp */
+void QAccessibleObject::setText(Text, int, const QString &)
+{
+}
+
+/*! \reimp */
+int QAccessibleObject::userActionCount(int) const
+{
+ return 0;
+}
+
+/*! \reimp */
+bool QAccessibleObject::doAction(int, int, const QVariantList &)
+{
+ return false;
+}
+
+static const char * const action_text[][5] =
+{
+ // Name, Description, Value, Help, Accelerator
+ { "Press", "", "", "", "Space" },
+ { "SetFocus", "Passes focus to this widget", "", "", "" },
+ { "Increase", "", "", "", "" },
+ { "Decrease", "", "", "", "" },
+ { "Accept", "", "", "", "" },
+ { "Cancel", "", "", "", "" },
+ { "Select", "", "", "", "" },
+ { "ClearSelection", "", "", "", "" },
+ { "RemoveSelection", "", "", "", "" },
+ { "ExtendSelection", "", "", "", "" },
+ { "AddToSelection", "", "", "", "" }
+};
+
+/*! \reimp */
+QString QAccessibleObject::actionText(int action, Text t, int child) const
+{
+ if (child || action > FirstStandardAction || action < LastStandardAction || t > Accelerator)
+ return QString();
+
+ return QString::fromLatin1(action_text[-(action - FirstStandardAction)][t]);
+}
+
+
+/*!
+ \class QAccessibleApplication
+ \brief The QAccessibleApplication class implements the QAccessibleInterface for QApplication.
+
+ \internal
+
+ \ingroup accessibility
+*/
+
+/*!
+ Creates a QAccessibleApplication for the QApplication object referenced by qApp.
+*/
+QAccessibleApplication::QAccessibleApplication()
+: QAccessibleObject(qApp)
+{
+}
+
+// all toplevel widgets except popups and the desktop
+static QWidgetList topLevelWidgets()
+{
+ QWidgetList list;
+ const QWidgetList tlw(QApplication::topLevelWidgets());
+ for (int i = 0; i < tlw.count(); ++i) {
+ QWidget *w = tlw.at(i);
+ if (!(w->windowType() == Qt::Popup) && !(w->windowType() == Qt::Desktop))
+ list.append(w);
+ }
+
+ return list;
+}
+
+/*! \reimp */
+int QAccessibleApplication::childCount() const
+{
+ return topLevelWidgets().count();
+}
+
+/*! \reimp */
+int QAccessibleApplication::indexOfChild(const QAccessibleInterface *child) const
+{
+ if (!child->object()->isWidgetType())
+ return -1;
+
+ const QWidgetList tlw(topLevelWidgets());
+ int index = tlw.indexOf(static_cast<QWidget*>(child->object()));
+ if (index != -1)
+ ++index;
+ return index;
+}
+
+/*! \reimp */
+int QAccessibleApplication::childAt(int x, int y) const
+{
+ const QWidgetList tlw(topLevelWidgets());
+ for (int i = 0; i < tlw.count(); ++i) {
+ QWidget *w = tlw.at(i);
+ if (w->frameGeometry().contains(x,y))
+ return i+1;
+ }
+ return -1;
+}
+
+/*! \reimp */
+QAccessible::Relation QAccessibleApplication::relationTo(int child, const
+ QAccessibleInterface *other, int otherChild) const
+{
+ QObject *o = other ? other->object() : 0;
+ if (!o)
+ return Unrelated;
+
+ if(o == object()) {
+ if (child && !otherChild)
+ return Child;
+ if (!child && otherChild)
+ return Ancestor;
+ if (!child && !otherChild)
+ return Self;
+ }
+
+ QWidgetList tlw(topLevelWidgets());
+ if (tlw.contains(qobject_cast<QWidget*>(o)))
+ return Ancestor;
+
+ for (int i = 0; i < tlw.count(); ++i) {
+ QWidget *w = tlw.at(i);
+ QObjectList cl = w->findChildren<QObject *>(QString());
+ if (cl.contains(o))
+ return Ancestor;
+ }
+
+ return Unrelated;
+}
+
+/*! \reimp */
+int QAccessibleApplication::navigate(RelationFlag relation, int entry,
+ QAccessibleInterface **target) const
+{
+ if (!target)
+ return -1;
+
+ *target = 0;
+ QObject *targetObject = 0;
+
+ switch (relation) {
+ case Self:
+ targetObject = object();
+ break;
+ case Child:
+ if (entry > 0 && entry <= childCount()) {
+ const QWidgetList tlw(topLevelWidgets());
+ if (tlw.count() >= entry)
+ targetObject = tlw.at(entry-1);
+ } else {
+ return -1;
+ }
+ break;
+ case FocusChild:
+ targetObject = QApplication::activeWindow();
+ break;
+ default:
+ break;
+ }
+ *target = QAccessible::queryAccessibleInterface(targetObject);
+ return *target ? 0 : -1;
+}
+
+/*! \reimp */
+QString QAccessibleApplication::text(Text t, int) const
+{
+ switch (t) {
+ case Name:
+ if (QApplication::activeWindow())
+ return QApplication::activeWindow()->windowTitle();
+ break;
+ case Description:
+ return QApplication::applicationFilePath();
+ default:
+ break;
+ }
+ return QString();
+}
+
+/*! \reimp */
+QAccessible::Role QAccessibleApplication::role(int) const
+{
+ return Application;
+}
+
+/*! \reimp */
+QAccessible::State QAccessibleApplication::state(int) const
+{
+ return QApplication::activeWindow() ? Focused : Normal;
+}
+
+/*! \reimp */
+int QAccessibleApplication::userActionCount(int) const
+{
+ return 1;
+}
+
+/*! \reimp */
+bool QAccessibleApplication::doAction(int action, int child, const QVariantList &param)
+{
+ if (action == 0 || action == 1) {
+ QWidget *w = 0;
+ w = QApplication::activeWindow();
+ if (!w)
+ w = topLevelWidgets().at(0);
+ if (!w)
+ return false;
+ w->activateWindow();
+ return true;
+ }
+ return QAccessibleObject::doAction(action, child, param);
+}
+
+/*! \reimp */
+QString QAccessibleApplication::actionText(int action, Text text, int child) const
+{
+ QString str;
+ if ((action == 0 || action == 1) && !child) switch (text) {
+ case Name:
+ return QApplication::tr("Activate");
+ case Description:
+ return QApplication::tr("Activates the program's main window");
+ default:
+ break;
+ }
+ return QAccessibleObject::actionText(action, text, child);
+}
+
+// ### Qt 5: remove me - binary compatibility hack
+QAccessibleObjectEx::QAccessibleObjectEx(QObject *object)
+{
+ d = new QAccessibleObjectPrivate;
+ d->object = object;
+}
+bool QAccessibleObjectEx::isValid() const
+{ return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::isValid(); }
+QObject *QAccessibleObjectEx::object() const
+{ return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::object(); }
+QRect QAccessibleObjectEx::rect(int child) const
+{ return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::rect(child); }
+void QAccessibleObjectEx::setText(Text t, int child, const QString &text)
+{ reinterpret_cast<QAccessibleObject *>(this)->QAccessibleObject::setText(t, child, text); }
+int QAccessibleObjectEx::userActionCount(int child) const
+{ return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::userActionCount(child); }
+bool QAccessibleObjectEx::doAction(int action, int child, const QVariantList &params)
+{ return reinterpret_cast<QAccessibleObject *>(this)->QAccessibleObject::doAction(action, child, params); }
+QString QAccessibleObjectEx::actionText(int action, Text t, int child) const
+{ return reinterpret_cast<const QAccessibleObject *>(this)->QAccessibleObject::actionText(action, t, child); }
+QAccessibleObjectEx::~QAccessibleObjectEx()
+{ delete d; }
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ACCESSIBILITY
diff --git a/src/gui/accessible/qaccessibleobject.h b/src/gui/accessible/qaccessibleobject.h
new file mode 100644
index 0000000000..0eb9399028
--- /dev/null
+++ b/src/gui/accessible/qaccessibleobject.h
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEOBJECT_H
+#define QACCESSIBLEOBJECT_H
+
+#include <QtGui/qaccessible.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAccessibleObjectPrivate;
+class QObject;
+
+class Q_GUI_EXPORT QAccessibleObject : public QAccessibleInterface
+{
+public:
+ explicit QAccessibleObject(QObject *object);
+
+ bool isValid() const;
+ QObject *object() const;
+
+ // properties
+ QRect rect(int child) const;
+ void setText(Text t, int child, const QString &text);
+
+ // actions
+ int userActionCount(int child) const;
+ bool doAction(int action, int child, const QVariantList &params);
+ QString actionText(int action, Text t, int child) const;
+
+protected:
+ virtual ~QAccessibleObject();
+
+private:
+ friend class QAccessibleObjectEx;
+ QAccessibleObjectPrivate *d;
+ Q_DISABLE_COPY(QAccessibleObject)
+};
+
+class Q_GUI_EXPORT QAccessibleObjectEx : public QAccessibleInterfaceEx
+{
+public:
+ explicit QAccessibleObjectEx(QObject *object);
+
+ bool isValid() const;
+ QObject *object() const;
+
+ // properties
+ QRect rect(int child) const;
+ void setText(Text t, int child, const QString &text);
+
+ // actions
+ int userActionCount(int child) const;
+ bool doAction(int action, int child, const QVariantList &params);
+ QString actionText(int action, Text t, int child) const;
+
+protected:
+ virtual ~QAccessibleObjectEx();
+
+private:
+ QAccessibleObjectPrivate *d;
+ Q_DISABLE_COPY(QAccessibleObjectEx)
+};
+
+class Q_GUI_EXPORT QAccessibleApplication : public QAccessibleObject
+{
+public:
+ QAccessibleApplication();
+
+ // relations
+ int childCount() const;
+ int indexOfChild(const QAccessibleInterface*) const;
+ Relation relationTo(int, const QAccessibleInterface *, int) const;
+
+ // navigation
+ int childAt(int x, int y) const;
+ int navigate(RelationFlag, int, QAccessibleInterface **) const;
+
+ // properties and state
+ QString text(Text t, int child) const;
+ Role role(int child) const;
+ State state(int child) const;
+
+ // actions
+ int userActionCount(int child) const;
+ bool doAction(int action, int child, const QVariantList &params);
+ QString actionText(int action, Text t, int child) const;
+};
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACCESSIBLEOBJECT_H
diff --git a/src/gui/accessible/qaccessibleplugin.cpp b/src/gui/accessible/qaccessibleplugin.cpp
new file mode 100644
index 0000000000..f52d4b1807
--- /dev/null
+++ b/src/gui/accessible/qaccessibleplugin.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessibleplugin.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qaccessible.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAccessiblePlugin
+ \brief The QAccessiblePlugin class provides an abstract base for
+ accessibility plugins.
+
+ \ingroup plugins
+ \ingroup accessibility
+
+ Writing an accessibility plugin is achieved by subclassing this
+ base class, reimplementing the pure virtual functions keys() and
+ create(), and exporting the class with the Q_EXPORT_PLUGIN2()
+ macro.
+
+ \sa QAccessibleBridgePlugin, {How to Create Qt Plugins}
+*/
+
+/*!
+ Constructs an accessibility plugin with the given \a parent. This
+ is invoked automatically by the Q_EXPORT_PLUGIN2() macro.
+*/
+QAccessiblePlugin::QAccessiblePlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the accessibility plugin.
+
+ You never have to call this explicitly. Qt destroys a plugin
+ automatically when it is no longer used.
+*/
+QAccessiblePlugin::~QAccessiblePlugin()
+{
+}
+
+/*!
+ \fn QStringList QAccessiblePlugin::keys() const
+
+ Returns the list of keys this plugin supports.
+
+ These keys must be the class names that this plugin provides
+ an accessibility implementation for.
+
+ \sa create()
+*/
+
+/*!
+ \fn QAccessibleInterface *QAccessiblePlugin::create(const QString &key, QObject *object)
+
+ Creates and returns a QAccessibleInterface implementation for the
+ class \a key and the object \a object. Keys are case sensitive.
+
+ \sa keys()
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_ACCESSIBILITY
diff --git a/src/gui/accessible/qaccessibleplugin.h b/src/gui/accessible/qaccessibleplugin.h
new file mode 100644
index 0000000000..dcf794e752
--- /dev/null
+++ b/src/gui/accessible/qaccessibleplugin.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEPLUGIN_H
+#define QACCESSIBLEPLUGIN_H
+
+#include <QtGui/qaccessible.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QStringList;
+class QAccessibleInterface;
+
+struct Q_GUI_EXPORT QAccessibleFactoryInterface : public QAccessible, public QFactoryInterface
+{
+ virtual QAccessibleInterface* create(const QString &key, QObject *object) = 0;
+};
+
+#define QAccessibleFactoryInterface_iid "com.trolltech.Qt.QAccessibleFactoryInterface"
+Q_DECLARE_INTERFACE(QAccessibleFactoryInterface, QAccessibleFactoryInterface_iid)
+
+class QAccessiblePluginPrivate;
+
+class Q_GUI_EXPORT QAccessiblePlugin : public QObject, public QAccessibleFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QAccessibleFactoryInterface:QFactoryInterface)
+public:
+ explicit QAccessiblePlugin(QObject *parent = 0);
+ ~QAccessiblePlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QAccessibleInterface *create(const QString &key, QObject *object) = 0;
+};
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACCESSIBLEPLUGIN_H
diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp
new file mode 100644
index 0000000000..2b2cec0f02
--- /dev/null
+++ b/src/gui/accessible/qaccessiblewidget.cpp
@@ -0,0 +1,1031 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qaccessiblewidget.h"
+
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qaction.h"
+#include "qapplication.h"
+#include "qgroupbox.h"
+#include "qlabel.h"
+#include "qtooltip.h"
+#include "qwhatsthis.h"
+#include "qwidget.h"
+#include "qdebug.h"
+#include <qmath.h>
+#include <QRubberBand>
+#include <QtGui/QFocusFrame>
+#include <QtGui/QMenu>
+
+QT_BEGIN_NAMESPACE
+
+static QList<QWidget*> childWidgets(const QWidget *widget)
+{
+ QList<QObject*> list = widget->children();
+ QList<QWidget*> widgets;
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(list.at(i));
+ if (w && !w->isWindow()
+ && !qobject_cast<QFocusFrame*>(w)
+#if !defined(QT_NO_MENU)
+ && !qobject_cast<QMenu*>(w)
+#endif
+ && w->objectName() != QLatin1String("qt_rubberband"))
+ widgets.append(w);
+ }
+ return widgets;
+}
+
+static QString buddyString(const QWidget *widget)
+{
+ if (!widget)
+ return QString();
+ QWidget *parent = widget->parentWidget();
+ if (!parent)
+ return QString();
+#ifndef QT_NO_SHORTCUT
+ QObjectList ol = parent->children();
+ for (int i = 0; i < ol.size(); ++i) {
+ QLabel *label = qobject_cast<QLabel*>(ol.at(i));
+ if (label && label->buddy() == widget)
+ return label->text();
+ }
+#endif
+
+#ifndef QT_NO_GROUPBOX
+ QGroupBox *groupbox = qobject_cast<QGroupBox*>(parent);
+ if (groupbox)
+ return groupbox->title();
+#endif
+
+ return QString();
+}
+
+QString Q_GUI_EXPORT qt_accStripAmp(const QString &text)
+{
+ return QString(text).remove(QLatin1Char('&'));
+}
+
+QString Q_GUI_EXPORT qt_accHotKey(const QString &text)
+{
+#ifndef QT_NO_SHORTCUT
+ if (text.isEmpty())
+ return text;
+
+ int fa = 0;
+ QChar ac;
+ while ((fa = text.indexOf(QLatin1Char('&'), fa)) != -1) {
+ ++fa;
+ if (fa < text.length()) {
+ // ignore "&&"
+ if (text.at(fa) == QLatin1Char('&')) {
+ ++fa;
+ continue;
+ } else {
+ ac = text.at(fa);
+ break;
+ }
+ }
+ }
+ if (ac.isNull())
+ return QString();
+ return (QString)QKeySequence(Qt::ALT) + ac.toUpper();
+#else
+ Q_UNUSED(text);
+ return QString();
+#endif
+}
+
+class QAccessibleWidgetPrivate : public QAccessible
+{
+public:
+ QAccessibleWidgetPrivate()
+ :role(Client)
+ {}
+
+ Role role;
+ QString name;
+ QString description;
+ QString value;
+ QString help;
+ QString accelerator;
+ QStringList primarySignals;
+ const QAccessibleInterface *asking;
+};
+
+/*!
+ \class QAccessibleWidget
+ \brief The QAccessibleWidget class implements the QAccessibleInterface for QWidgets.
+
+ \ingroup accessibility
+
+ This class is convenient to use as a base class for custom
+ implementations of QAccessibleInterfaces that provide information
+ about widget objects.
+
+ The class provides functions to retrieve the parentObject() (the
+ widget's parent widget), and the associated widget(). Controlling
+ signals can be added with addControllingSignal(), and setters are
+ provided for various aspects of the interface implementation, for
+ example setValue(), setDescription(), setAccelerator(), and
+ setHelp().
+
+ \sa QAccessible, QAccessibleObject
+*/
+
+/*!
+ Creates a QAccessibleWidget object for widget \a w.
+ \a role and \a name are optional parameters that set the object's
+ role and name properties.
+*/
+QAccessibleWidget::QAccessibleWidget(QWidget *w, Role role, const QString &name)
+: QAccessibleObject(w)
+{
+ Q_ASSERT(widget());
+ d = new QAccessibleWidgetPrivate();
+ d->role = role;
+ d->name = name;
+ d->asking = 0;
+}
+
+/*!
+ Destroys this object.
+*/
+QAccessibleWidget::~QAccessibleWidget()
+{
+ delete d;
+}
+
+/*!
+ Returns the associated widget.
+*/
+QWidget *QAccessibleWidget::widget() const
+{
+ return qobject_cast<QWidget*>(object());
+}
+
+/*!
+ Returns the associated widget's parent object, which is either the
+ parent widget, or qApp for top-level widgets.
+*/
+QObject *QAccessibleWidget::parentObject() const
+{
+ QObject *parent = object()->parent();
+ if (!parent)
+ parent = qApp;
+ return parent;
+}
+
+/*! \reimp */
+int QAccessibleWidget::childAt(int x, int y) const
+{
+ QWidget *w = widget();
+ if (!w->isVisible())
+ return -1;
+ QPoint gp = w->mapToGlobal(QPoint(0, 0));
+ if (!QRect(gp.x(), gp.y(), w->width(), w->height()).contains(x, y))
+ return -1;
+
+ QWidgetList list = childWidgets(w);
+ int ccount = childCount();
+
+ // a complex child
+ if (list.size() < ccount) {
+ for (int i = 1; i <= ccount; ++i) {
+ if (rect(i).contains(x, y))
+ return i;
+ }
+ return 0;
+ }
+
+ QPoint rp = w->mapFromGlobal(QPoint(x, y));
+ for (int i = 0; i<list.size(); ++i) {
+ QWidget *child = list.at(i);
+ if (!child->isWindow() && !child->isHidden() && child->geometry().contains(rp)) {
+ return i + 1;
+ }
+ }
+ return 0;
+}
+
+/*! \reimp */
+QRect QAccessibleWidget::rect(int child) const
+{
+ if (child) {
+ qWarning("QAccessibleWidget::rect: This implementation does not support subelements! "
+ "(ID %d unknown for %s)", child, widget()->metaObject()->className());
+ }
+
+ QWidget *w = widget();
+ if (!w->isVisible())
+ return QRect();
+ QPoint wpos = w->mapToGlobal(QPoint(0, 0));
+
+ return QRect(wpos.x(), wpos.y(), w->width(), w->height());
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <private/qobject_p.h>
+QT_END_INCLUDE_NAMESPACE
+
+class QACConnectionObject : public QObject
+{
+ Q_DECLARE_PRIVATE(QObject)
+public:
+ inline bool isSender(const QObject *receiver, const char *signal) const
+ { return d_func()->isSender(receiver, signal); }
+ inline QObjectList receiverList(const char *signal) const
+ { return d_func()->receiverList(signal); }
+ inline QObjectList senderList() const
+ { return d_func()->senderList(); }
+};
+
+/*!
+ Registers \a signal as a controlling signal.
+
+ An object is a Controller to any other object connected to a
+ controlling signal.
+*/
+void QAccessibleWidget::addControllingSignal(const QString &signal)
+{
+ QByteArray s = QMetaObject::normalizedSignature(signal.toAscii());
+ if (object()->metaObject()->indexOfSignal(s) < 0)
+ qWarning("Signal %s unknown in %s", s.constData(), object()->metaObject()->className());
+ d->primarySignals << QLatin1String(s);
+}
+
+/*!
+ Sets the value of this interface implementation to \a value.
+
+ The default implementation of text() returns the set value for
+ the Value text.
+
+ Note that the object wrapped by this interface is not modified.
+*/
+void QAccessibleWidget::setValue(const QString &value)
+{
+ d->value = value;
+}
+
+/*!
+ Sets the description of this interface implementation to \a desc.
+
+ The default implementation of text() returns the set value for
+ the Description text.
+
+ Note that the object wrapped by this interface is not modified.
+*/
+void QAccessibleWidget::setDescription(const QString &desc)
+{
+ d->description = desc;
+}
+
+/*!
+ Sets the help of this interface implementation to \a help.
+
+ The default implementation of text() returns the set value for
+ the Help text.
+
+ Note that the object wrapped by this interface is not modified.
+*/
+void QAccessibleWidget::setHelp(const QString &help)
+{
+ d->help = help;
+}
+
+/*!
+ Sets the accelerator of this interface implementation to \a accel.
+
+ The default implementation of text() returns the set value for
+ the Accelerator text.
+
+ Note that the object wrapped by this interface is not modified.
+*/
+void QAccessibleWidget::setAccelerator(const QString &accel)
+{
+ d->accelerator = accel;
+}
+
+static inline bool isAncestor(const QObject *obj, const QObject *child)
+{
+ while (child) {
+ if (child == obj)
+ return true;
+ child = child->parent();
+ }
+ return false;
+}
+
+
+/*! \reimp */
+QAccessible::Relation QAccessibleWidget::relationTo(int child,
+ const QAccessibleInterface *other, int otherChild) const
+{
+ Relation relation = Unrelated;
+ if (d->asking == this) // recursive call
+ return relation;
+
+ QObject *o = other ? other->object() : 0;
+ if (!o)
+ return relation;
+
+ QWidget *focus = widget()->focusWidget();
+ if (object() == focus && isAncestor(o, focus))
+ relation |= FocusChild;
+
+ QACConnectionObject *connectionObject = (QACConnectionObject*)object();
+ for (int sig = 0; sig < d->primarySignals.count(); ++sig) {
+ if (connectionObject->isSender(o, d->primarySignals.at(sig).toAscii())) {
+ relation |= Controller;
+ break;
+ }
+ }
+ // test for passive relationships.
+ // d->asking protects from endless recursion.
+ d->asking = this;
+ int inverse = other->relationTo(otherChild, this, child);
+ d->asking = 0;
+
+ if (inverse & Controller)
+ relation |= Controlled;
+ if (inverse & Label)
+ relation |= Labelled;
+
+ if(o == object()) {
+ if (child && !otherChild)
+ return relation | Child;
+ if (!child && otherChild)
+ return relation | Ancestor;
+ if (!child && !otherChild)
+ return relation | Self;
+ }
+
+ QObject *parent = object()->parent();
+ if (o == parent)
+ return relation | Child;
+
+ if (o->parent() == parent) {
+ relation |= Sibling;
+ QAccessibleInterface *sibIface = QAccessible::queryAccessibleInterface(o);
+ Q_ASSERT(sibIface);
+ QRect wg = rect(0);
+ QRect sg = sibIface->rect(0);
+ if (wg.intersects(sg)) {
+ QAccessibleInterface *pIface = 0;
+ sibIface->navigate(Ancestor, 1, &pIface);
+ if (pIface && !((sibIface->state(0) | state(0)) & Invisible)) {
+ int wi = pIface->indexOfChild(this);
+ int si = pIface->indexOfChild(sibIface);
+
+ if (wi > si)
+ relation |= QAccessible::Covers;
+ else
+ relation |= QAccessible::Covered;
+ }
+ delete pIface;
+ } else {
+ QPoint wc = wg.center();
+ QPoint sc = sg.center();
+ if (wc.x() < sc.x())
+ relation |= QAccessible::Left;
+ else if(wc.x() > sc.x())
+ relation |= QAccessible::Right;
+ if (wc.y() < sc.y())
+ relation |= QAccessible::Up;
+ else if (wc.y() > sc.y())
+ relation |= QAccessible::Down;
+ }
+ delete sibIface;
+
+ return relation;
+ }
+
+ if (isAncestor(o, object()))
+ return relation | Descendent;
+ if (isAncestor(object(), o))
+ return relation | Ancestor;
+
+ return relation;
+}
+
+/*! \reimp */
+int QAccessibleWidget::navigate(RelationFlag relation, int entry,
+ QAccessibleInterface **target) const
+{
+ if (!target)
+ return -1;
+
+ *target = 0;
+ QObject *targetObject = 0;
+
+ QWidgetList childList = childWidgets(widget());
+ bool complexWidget = childList.size() < childCount();
+
+ switch (relation) {
+ // Hierarchical
+ case Self:
+ targetObject = object();
+ break;
+ case Child:
+ if (complexWidget) {
+ if (entry > 0 && entry <= childCount())
+ return entry;
+ return -1;
+ }else {
+ if (entry > 0 && childList.size() >= entry)
+ targetObject = childList.at(entry - 1);
+ }
+ break;
+ case Ancestor:
+ {
+ if (entry <= 0)
+ return -1;
+ targetObject = widget()->parentWidget();
+ int i;
+ for (i = entry; i > 1 && targetObject; --i)
+ targetObject = targetObject->parent();
+ if (!targetObject && i == 1)
+ targetObject = qApp;
+ }
+ break;
+ case Sibling:
+ {
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!iface)
+ return -1;
+
+ iface->navigate(Child, entry, target);
+ delete iface;
+ if (*target)
+ return 0;
+ }
+ break;
+
+ // Geometrical
+ case QAccessible::Left:
+ if (complexWidget && entry) {
+ if (entry < 2 || widget()->height() > widget()->width() + 20) // looks vertical
+ return -1;
+ return entry - 1;
+ }
+ // fall through
+ case QAccessible::Right:
+ if (complexWidget && entry) {
+ if (entry >= childCount() || widget()->height() > widget()->width() + 20) // looks vertical
+ return -1;
+ return entry + 1;
+ }
+ // fall through
+ case QAccessible::Up:
+ if (complexWidget && entry) {
+ if (entry < 2 || widget()->width() > widget()->height() + 20) // looks horizontal
+ return - 1;
+ return entry - 1;
+ }
+ // fall through
+ case QAccessible::Down:
+ if (complexWidget && entry) {
+ if (entry >= childCount() || widget()->width() > widget()->height() + 20) // looks horizontal
+ return - 1;
+ return entry + 1;
+ } else {
+ QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!pIface)
+ return -1;
+
+ QRect startg = rect(0);
+ QPoint startc = startg.center();
+ QAccessibleInterface *candidate = 0;
+ int mindist = 100000;
+ int sibCount = pIface->childCount();
+ for (int i = 0; i < sibCount; ++i) {
+ QAccessibleInterface *sibling = 0;
+ pIface->navigate(Child, i+1, &sibling);
+ Q_ASSERT(sibling);
+ if ((relationTo(0, sibling, 0) & Self) || (sibling->state(0) & QAccessible::Invisible)) {
+ //ignore ourself and invisible siblings
+ delete sibling;
+ continue;
+ }
+
+ QRect sibg = sibling->rect(0);
+ QPoint sibc = sibg.center();
+ QPoint sibp;
+ QPoint startp;
+ QPoint distp;
+ switch (relation) {
+ case QAccessible::Left:
+ startp = QPoint(startg.left(), startg.top() + startg.height() / 2);
+ sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2);
+ if (QPoint(sibc - startc).x() >= 0) {
+ delete sibling;
+ continue;
+ }
+ distp = sibp - startp;
+ break;
+ case QAccessible::Right:
+ startp = QPoint(startg.right(), startg.top() + startg.height() / 2);
+ sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2);
+ if (QPoint(sibc - startc).x() <= 0) {
+ delete sibling;
+ continue;
+ }
+ distp = sibp - startp;
+ break;
+ case QAccessible::Up:
+ startp = QPoint(startg.left() + startg.width() / 2, startg.top());
+ sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom());
+ if (QPoint(sibc - startc).y() >= 0) {
+ delete sibling;
+ continue;
+ }
+ distp = sibp - startp;
+ break;
+ case QAccessible::Down:
+ startp = QPoint(startg.left() + startg.width() / 2, startg.bottom());
+ sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top());
+ if (QPoint(sibc - startc).y() <= 0) {
+ delete sibling;
+ continue;
+ }
+ distp = sibp - startp;
+ break;
+ default:
+ break;
+ }
+
+ int dist = (int)qSqrt((qreal)distp.x() * distp.x() + distp.y() * distp.y());
+ if (dist < mindist) {
+ delete candidate;
+ candidate = sibling;
+ mindist = dist;
+ } else {
+ delete sibling;
+ }
+ }
+ delete pIface;
+ *target = candidate;
+ if (*target)
+ return 0;
+ }
+ break;
+ case Covers:
+ if (entry > 0) {
+ QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!pIface)
+ return -1;
+
+ QRect r = rect(0);
+ int sibCount = pIface->childCount();
+ QAccessibleInterface *sibling = 0;
+ for (int i = pIface->indexOfChild(this) + 1; i <= sibCount && entry; ++i) {
+ pIface->navigate(Child, i, &sibling);
+ if (!sibling || (sibling->state(0) & Invisible)) {
+ delete sibling;
+ sibling = 0;
+ continue;
+ }
+ if (sibling->rect(0).intersects(r))
+ --entry;
+ if (!entry)
+ break;
+ delete sibling;
+ sibling = 0;
+ }
+ delete pIface;
+ *target = sibling;
+ if (*target)
+ return 0;
+ }
+ break;
+ case Covered:
+ if (entry > 0) {
+ QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!pIface)
+ return -1;
+
+ QRect r = rect(0);
+ int index = pIface->indexOfChild(this);
+ QAccessibleInterface *sibling = 0;
+ for (int i = 1; i < index && entry; ++i) {
+ pIface->navigate(Child, i, &sibling);
+ Q_ASSERT(sibling);
+ if (!sibling || (sibling->state(0) & Invisible)) {
+ delete sibling;
+ sibling = 0;
+ continue;
+ }
+ if (sibling->rect(0).intersects(r))
+ --entry;
+ if (!entry)
+ break;
+ delete sibling;
+ sibling = 0;
+ }
+ delete pIface;
+ *target = sibling;
+ if (*target)
+ return 0;
+ }
+ break;
+
+ // Logical
+ case FocusChild:
+ {
+ if (widget()->hasFocus()) {
+ targetObject = object();
+ break;
+ }
+
+ QWidget *fw = widget()->focusWidget();
+ if (!fw)
+ return -1;
+
+ if (isAncestor(widget(), fw) || fw == widget())
+ targetObject = fw;
+ /* ###
+ QWidget *parent = fw;
+ while (parent && !targetObject) {
+ parent = parent->parentWidget();
+ if (parent == widget())
+ targetObject = fw;
+ }
+ */
+ }
+ break;
+ case Label:
+ if (entry > 0) {
+ QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject());
+ if (!pIface)
+ return -1;
+
+ // first check for all siblings that are labels to us
+ // ideally we would go through all objects and check, but that
+ // will be too expensive
+ int sibCount = pIface->childCount();
+ QAccessibleInterface *candidate = 0;
+ for (int i = 0; i < sibCount && entry; ++i) {
+ pIface->navigate(Child, i+1, &candidate);
+ Q_ASSERT(candidate);
+ if (candidate->relationTo(0, this, 0) & Label)
+ --entry;
+ if (!entry)
+ break;
+ delete candidate;
+ candidate = 0;
+ }
+ if (!candidate) {
+ if (pIface->relationTo(0, this, 0) & Label)
+ --entry;
+ if (!entry)
+ candidate = pIface;
+ }
+ if (pIface != candidate)
+ delete pIface;
+
+ *target = candidate;
+ if (*target)
+ return 0;
+ }
+ break;
+ case Labelled: // only implemented in subclasses
+ break;
+ case Controller:
+ if (entry > 0) {
+ // check all senders we are connected to,
+ // and figure out which one are controllers to us
+ QACConnectionObject *connectionObject = (QACConnectionObject*)object();
+ QObjectList allSenders = connectionObject->senderList();
+ QObjectList senders;
+ for (int s = 0; s < allSenders.size(); ++s) {
+ QObject *sender = allSenders.at(s);
+ QAccessibleInterface *candidate = QAccessible::queryAccessibleInterface(sender);
+ if (!candidate)
+ continue;
+ if (candidate->relationTo(0, this, 0)&Controller)
+ senders << sender;
+ delete candidate;
+ }
+ if (entry <= senders.size())
+ targetObject = senders.at(entry-1);
+ }
+ break;
+ case Controlled:
+ if (entry > 0) {
+ QObjectList allReceivers;
+ QACConnectionObject *connectionObject = (QACConnectionObject*)object();
+ for (int sig = 0; sig < d->primarySignals.count(); ++sig) {
+ QObjectList receivers = connectionObject->receiverList(d->primarySignals.at(sig).toAscii());
+ allReceivers += receivers;
+ }
+ if (entry <= allReceivers.size())
+ targetObject = allReceivers.at(entry-1);
+ }
+ break;
+ default:
+ break;
+ }
+
+ *target = QAccessible::queryAccessibleInterface(targetObject);
+ return *target ? 0 : -1;
+}
+
+/*! \reimp */
+int QAccessibleWidget::childCount() const
+{
+ QWidgetList cl = childWidgets(widget());
+ return cl.size();
+}
+
+/*! \reimp */
+int QAccessibleWidget::indexOfChild(const QAccessibleInterface *child) const
+{
+ QWidgetList cl = childWidgets(widget());
+ int index = cl.indexOf(qobject_cast<QWidget *>(child->object()));
+ if (index != -1)
+ ++index;
+ return index;
+}
+
+// from qwidget.cpp
+extern QString qt_setWindowTitle_helperHelper(const QString &, const QWidget*);
+
+/*! \reimp */
+QString QAccessibleWidget::text(Text t, int child) const
+{
+ QString str;
+
+ switch (t) {
+ case Name:
+ if (!d->name.isEmpty()) {
+ str = d->name;
+ } else if (!widget()->accessibleName().isEmpty()) {
+ str = widget()->accessibleName();
+ } else if (!child && widget()->isWindow()) {
+ if (widget()->isMinimized())
+ str = qt_setWindowTitle_helperHelper(widget()->windowIconText(), widget());
+ else
+ str = qt_setWindowTitle_helperHelper(widget()->windowTitle(), widget());
+ } else {
+ str = qt_accStripAmp(buddyString(widget()));
+ }
+ break;
+ case Description:
+ if (!d->description.isEmpty())
+ str = d->description;
+ else if (!widget()->accessibleDescription().isEmpty())
+ str = widget()->accessibleDescription();
+#ifndef QT_NO_TOOLTIP
+ else
+ str = widget()->toolTip();
+#endif
+ break;
+ case Help:
+ if (!d->help.isEmpty())
+ str = d->help;
+#ifndef QT_NO_WHATSTHIS
+ else
+ str = widget()->whatsThis();
+#endif
+ break;
+ case Accelerator:
+ if (!d->accelerator.isEmpty())
+ str = d->accelerator;
+ else
+ str = qt_accHotKey(buddyString(widget()));
+ break;
+ case Value:
+ str = d->value;
+ break;
+ default:
+ break;
+ }
+ return str;
+}
+
+#ifndef QT_NO_ACTION
+
+/*! \reimp */
+int QAccessibleWidget::userActionCount(int child) const
+{
+ if (child)
+ return 0;
+ return widget()->actions().count();
+}
+
+/*! \reimp */
+QString QAccessibleWidget::actionText(int action, Text t, int child) const
+{
+ if (action == DefaultAction)
+ action = SetFocus;
+
+ if (action > 0 && !child) {
+ QAction *act = widget()->actions().value(action - 1);
+ if (act) {
+ switch (t) {
+ case Name:
+ return act->text();
+ case Description:
+ return act->toolTip();
+#ifndef QT_NO_SHORTCUT
+ case Accelerator:
+ return act->shortcut().toString();
+#endif
+ default:
+ break;
+ }
+ }
+ }
+
+ return QAccessibleObject::actionText(action, t, child);
+}
+
+/*! \reimp */
+bool QAccessibleWidget::doAction(int action, int child, const QVariantList &params)
+{
+ if (action == SetFocus || action == DefaultAction) {
+ if (child || !widget()->isEnabled())
+ return false;
+ if (widget()->focusPolicy() != Qt::NoFocus)
+ widget()->setFocus();
+ else if (widget()->isWindow())
+ widget()->activateWindow();
+ else
+ return false;
+ return true;
+ } else if (action > 0) {
+ if (QAction *act = widget()->actions().value(action - 1)) {
+ act->trigger();
+ return true;
+ }
+ }
+ return QAccessibleObject::doAction(action, child, params);
+}
+
+#endif // QT_NO_ACTION
+
+/*! \reimp */
+QAccessible::Role QAccessibleWidget::role(int child) const
+{
+ if (!child)
+ return d->role;
+
+ QWidgetList childList = childWidgets(widget());
+ if (childList.count() > 0 && child <= childList.count()) {
+ QWidget *targetWidget = childList.at(child - 1);
+ QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(targetWidget);
+ if (iface) {
+ QAccessible::Role role = iface->role(0);
+ delete iface;
+ return role;
+ }
+ }
+
+ return NoRole;
+}
+
+/*! \reimp */
+QAccessible::State QAccessibleWidget::state(int child) const
+{
+ if (child)
+ return Normal;
+
+ QAccessible::State state = Normal;
+
+ QWidget *w = widget();
+ if (w->testAttribute(Qt::WA_WState_Visible) == false)
+ state |= Invisible;
+ if (w->focusPolicy() != Qt::NoFocus && w->isActiveWindow())
+ state |= Focusable;
+ if (w->hasFocus())
+ state |= Focused;
+ if (!w->isEnabled())
+ state |= Unavailable;
+ if (w->isWindow()) {
+ if (w->windowFlags() & Qt::WindowSystemMenuHint)
+ state |= Movable;
+ if (w->minimumSize() != w->maximumSize())
+ state |= Sizeable;
+ }
+
+ return state;
+}
+
+// ### Qt 5: remove me - binary compatibility hack
+QAccessibleWidgetEx::QAccessibleWidgetEx(QWidget *o, Role role, const QString& name)
+ : QAccessibleObjectEx(o)
+{
+ Q_ASSERT(widget());
+ d = new QAccessibleWidgetPrivate();
+ d->role = role;
+ d->name = name;
+ d->asking = 0;
+}
+
+int QAccessibleWidgetEx::childCount() const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::childCount(); }
+int QAccessibleWidgetEx::indexOfChild(const QAccessibleInterface *child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::indexOfChild(child); }
+QAccessible::Relation QAccessibleWidgetEx::relationTo(int child, const QAccessibleInterface *other, int otherChild) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::relationTo(child, other, otherChild); }
+
+int QAccessibleWidgetEx::childAt(int x, int y) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::childAt(x, y); }
+QRect QAccessibleWidgetEx::rect(int child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::rect(child); }
+int QAccessibleWidgetEx::navigate(RelationFlag rel, int entry, QAccessibleInterface **target) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::navigate(rel, entry, target); }
+
+QString QAccessibleWidgetEx::text(Text t, int child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::text(t, child); }
+QAccessible::Role QAccessibleWidgetEx::role(int child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::role(child); }
+QAccessible::State QAccessibleWidgetEx::state(int child) const
+{ return (reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::state(child))
+ | HasInvokeExtension; }
+
+QString QAccessibleWidgetEx::actionText(int action, Text t, int child) const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::actionText(action, t, child); }
+bool QAccessibleWidgetEx::doAction(int action, int child, const QVariantList &params)
+{ return reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::doAction(action, child, params); }
+
+QAccessibleWidgetEx::~QAccessibleWidgetEx()
+{ delete d; }
+QWidget *QAccessibleWidgetEx::widget() const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::widget(); }
+QObject *QAccessibleWidgetEx::parentObject() const
+{ return reinterpret_cast<const QAccessibleWidget *>(this)->QAccessibleWidget::parentObject(); }
+
+void QAccessibleWidgetEx::addControllingSignal(const QString &signal)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::addControllingSignal(signal); }
+void QAccessibleWidgetEx::setValue(const QString &value)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setValue(value); }
+void QAccessibleWidgetEx::setDescription(const QString &desc)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setDescription(desc); }
+void QAccessibleWidgetEx::setHelp(const QString &help)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setHelp(help); }
+void QAccessibleWidgetEx::setAccelerator(const QString &accel)
+{ reinterpret_cast<QAccessibleWidget *>(this)->QAccessibleWidget::setAccelerator(accel); }
+
+QVariant QAccessibleWidgetEx::invokeMethodEx(Method method, int child, const QVariantList & /*params*/)
+{
+ if (child)
+ return QVariant();
+
+ switch (method) {
+ case ListSupportedMethods: {
+ QSet<QAccessible::Method> set;
+ set << ListSupportedMethods << ForegroundColor << BackgroundColor;
+ return QVariant::fromValue(set);
+ }
+ case ForegroundColor:
+ return widget()->palette().color(widget()->foregroundRole());
+ case BackgroundColor:
+ return widget()->palette().color(widget()->backgroundRole());
+ default:
+ return QVariant();
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ACCESSIBILITY
diff --git a/src/gui/accessible/qaccessiblewidget.h b/src/gui/accessible/qaccessiblewidget.h
new file mode 100644
index 0000000000..ef22e05c60
--- /dev/null
+++ b/src/gui/accessible/qaccessiblewidget.h
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QACCESSIBLEWIDGET_H
+#define QACCESSIBLEWIDGET_H
+
+#include <QtGui/qaccessibleobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_ACCESSIBILITY
+
+class QAccessibleWidgetPrivate;
+
+class Q_GUI_EXPORT QAccessibleWidget : public QAccessibleObject
+{
+public:
+ explicit QAccessibleWidget(QWidget *o, Role r = Client, const QString& name = QString());
+
+ int childCount() const;
+ int indexOfChild(const QAccessibleInterface *child) const;
+ Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const;
+
+ int childAt(int x, int y) const;
+ QRect rect(int child) const;
+ int navigate(RelationFlag rel, int entry, QAccessibleInterface **target) const;
+
+ QString text(Text t, int child) const;
+ Role role(int child) const;
+ State state(int child) const;
+
+#ifndef QT_NO_ACTION
+ int userActionCount(int child) const;
+ QString actionText(int action, Text t, int child) const;
+ bool doAction(int action, int child, const QVariantList &params);
+#endif
+
+protected:
+ ~QAccessibleWidget();
+ QWidget *widget() const;
+ QObject *parentObject() const;
+
+ void addControllingSignal(const QString &signal);
+ void setValue(const QString &value);
+ void setDescription(const QString &desc);
+ void setHelp(const QString &help);
+ void setAccelerator(const QString &accel);
+
+private:
+ friend class QAccessibleWidgetEx;
+ QAccessibleWidgetPrivate *d;
+ Q_DISABLE_COPY(QAccessibleWidget)
+};
+
+class Q_GUI_EXPORT QAccessibleWidgetEx : public QAccessibleObjectEx
+{
+public:
+ explicit QAccessibleWidgetEx(QWidget *o, Role r = Client, const QString& name = QString());
+
+ int childCount() const;
+ int indexOfChild(const QAccessibleInterface *child) const;
+ Relation relationTo(int child, const QAccessibleInterface *other, int otherChild) const;
+
+ int childAt(int x, int y) const;
+ QRect rect(int child) const;
+ int navigate(RelationFlag rel, int entry, QAccessibleInterface **target) const;
+
+ QString text(Text t, int child) const;
+ Role role(int child) const;
+ State state(int child) const;
+
+ QString actionText(int action, Text t, int child) const;
+ bool doAction(int action, int child, const QVariantList &params);
+
+ QVariant invokeMethodEx(Method method, int child, const QVariantList &params);
+
+protected:
+ ~QAccessibleWidgetEx();
+ QWidget *widget() const;
+ QObject *parentObject() const;
+
+ void addControllingSignal(const QString &signal);
+ void setValue(const QString &value);
+ void setDescription(const QString &desc);
+ void setHelp(const QString &help);
+ void setAccelerator(const QString &accel);
+
+private:
+ QAccessibleWidgetPrivate *d;
+ Q_DISABLE_COPY(QAccessibleWidgetEx)
+};
+
+#endif // QT_NO_ACCESSIBILITY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QACCESSIBLEWIDGET_H