summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/accessible/accessible.pri15
-rw-r--r--src/plugins/platforms/windows/accessible/comutils.cpp641
-rw-r--r--src/plugins/platforms/windows/accessible/comutils.h61
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp1467
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.h375
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp301
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.h (renamed from src/plugins/platforms/windows/qwindowsaccessibility.h)8
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp (renamed from src/plugins/platforms/windows/qwindowsaccessibility.cpp)511
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h138
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp2
-rw-r--r--src/plugins/platforms/windows/windows.pro3
12 files changed, 3115 insertions, 409 deletions
diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri
new file mode 100644
index 0000000000..bf25ad870c
--- /dev/null
+++ b/src/plugins/platforms/windows/accessible/accessible.pri
@@ -0,0 +1,15 @@
+
+SOURCES += \
+ $$PWD/qwindowsmsaaaccessible.cpp \
+ $$PWD/qwindowsaccessibility.cpp \
+ $$PWD/iaccessible2.cpp \
+ $$PWD/comutils.cpp
+
+HEADERS += \
+ $$PWD/qwindowsmsaaaccessible.h \
+ $$PWD/qwindowsaccessibility.h \
+ $$PWD/iaccessible2.h \
+ $$PWD/comutils.h
+
+
+include(../../../../3rdparty/iaccessible2/iaccessible2.pri)
diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp
new file mode 100644
index 0000000000..9a0fce20b8
--- /dev/null
+++ b/src/plugins/platforms/windows/accessible/comutils.cpp
@@ -0,0 +1,641 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <ocidl.h>
+#include <olectl.h>
+
+#include "comutils.h"
+#include <QtCore/qdatetime.h>
+#include <QtGui/qpixmap.h>
+#include <QtGui/qfont.h>
+
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qbytearray.h>
+#include <QtGui/qcolor.h>
+
+static DATE QDateTimeToDATE(const QDateTime &dt)
+{
+ if (!dt.isValid() || dt.isNull())
+ return 949998; // Special value for no date (01/01/4501)
+
+ SYSTEMTIME stime;
+ memset(&stime, 0, sizeof(stime));
+ QDate date = dt.date();
+ QTime time = dt.time();
+ if (date.isValid() && !date.isNull()) {
+ stime.wDay = date.day();
+ stime.wMonth = date.month();
+ stime.wYear = date.year();
+ }
+ if (time.isValid() && !time.isNull()) {
+ stime.wMilliseconds = time.msec();
+ stime.wSecond = time.second();
+ stime.wMinute = time.minute();
+ stime.wHour = time.hour();
+ }
+
+ double vtime;
+ SystemTimeToVariantTime(&stime, &vtime);
+
+ return vtime;
+}
+
+inline uint QColorToOLEColor(const QColor &col)
+{
+ return qRgba(col.blue(), col.green(), col.red(), 0x00);
+}
+
+bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out)
+{
+ QVariant qvar = var;
+ // "type" is the expected type, so coerce if necessary
+ QVariant::Type proptype = typeName.isEmpty() ? QVariant::Invalid : QVariant::nameToType(typeName);
+ if (proptype == QVariant::UserType && !typeName.isEmpty()) {
+ if (typeName == "short" || typeName == "char")
+ proptype = QVariant::Int;
+ else if (typeName == "float")
+ proptype = QVariant::Double;
+ }
+ if (proptype != QVariant::Invalid && proptype != QVariant::UserType && proptype != qvar.type()) {
+ if (qvar.canConvert(proptype))
+ qvar.convert(proptype);
+ else
+ qvar = QVariant(proptype);
+ }
+
+ if (out && arg.vt == (VT_VARIANT|VT_BYREF) && arg.pvarVal) {
+ return QVariantToVARIANT(var, *arg.pvarVal, typeName, false);
+ }
+
+ if (out && proptype == QVariant::UserType && typeName == "QVariant") {
+ VARIANT *pVariant = new VARIANT;
+ QVariantToVARIANT(var, *pVariant, QByteArray(), false);
+ arg.vt = VT_VARIANT|VT_BYREF;
+ arg.pvarVal = pVariant;
+ return true;
+ }
+
+ switch ((int)qvar.type()) {
+ case QVariant::String:
+ if (out && arg.vt == (VT_BSTR|VT_BYREF)) {
+ if (*arg.pbstrVal)
+ SysFreeString(*arg.pbstrVal);
+ *arg.pbstrVal = QStringToBSTR(qvar.toString());
+ arg.vt = VT_BSTR|VT_BYREF;
+ } else {
+ arg.vt = VT_BSTR;
+ arg.bstrVal = QStringToBSTR(qvar.toString());
+ if (out) {
+ arg.pbstrVal = new BSTR(arg.bstrVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::Int:
+ if (out && arg.vt == (VT_I4|VT_BYREF)) {
+ *arg.plVal = qvar.toInt();
+ } else {
+ arg.vt = VT_I4;
+ arg.lVal = qvar.toInt();
+ if (out) {
+ if (typeName == "short") {
+ arg.vt = VT_I2;
+ arg.piVal = new short(arg.lVal);
+ } else if (typeName == "char") {
+ arg.vt = VT_I1;
+ arg.pcVal= new char(arg.lVal);
+ } else {
+ arg.plVal = new long(arg.lVal);
+ }
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::UInt:
+ if (out && (arg.vt == (VT_UINT|VT_BYREF) || arg.vt == (VT_I4|VT_BYREF))) {
+ *arg.puintVal = qvar.toUInt();
+ } else {
+ arg.vt = VT_UINT;
+ arg.uintVal = qvar.toUInt();
+ if (out) {
+ arg.puintVal = new uint(arg.uintVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::LongLong:
+ if (out && arg.vt == (VT_CY|VT_BYREF)) {
+ arg.pcyVal->int64 = qvar.toLongLong();
+#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
+ } else if (out && arg.vt == (VT_I8|VT_BYREF)) {
+ *arg.pllVal = qvar.toLongLong();
+ } else {
+ arg.vt = VT_I8;
+ arg.llVal = qvar.toLongLong();
+ if (out) {
+ arg.pllVal = new LONGLONG(arg.llVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+#else
+ } else {
+ arg.vt = VT_CY;
+ arg.cyVal.int64 = qvar.toLongLong();
+ if (out) {
+ arg.pcyVal = new CY(arg.cyVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+#endif
+ break;
+
+ case QVariant::ULongLong:
+ if (out && arg.vt == (VT_CY|VT_BYREF)) {
+ arg.pcyVal->int64 = qvar.toULongLong();
+#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
+ } else if (out && arg.vt == (VT_UI8|VT_BYREF)) {
+ *arg.pullVal = qvar.toULongLong();
+ } else {
+ arg.vt = VT_UI8;
+ arg.ullVal = qvar.toULongLong();
+ if (out) {
+ arg.pullVal = new ULONGLONG(arg.ullVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+#else
+ } else {
+ arg.vt = VT_CY;
+ arg.cyVal.int64 = qvar.toULongLong();
+ if (out) {
+ arg.pcyVal = new CY(arg.cyVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+
+#endif
+
+ break;
+
+ case QVariant::Bool:
+ if (out && arg.vt == (VT_BOOL|VT_BYREF)) {
+ *arg.pboolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE;
+ } else {
+ arg.vt = VT_BOOL;
+ arg.boolVal = qvar.toBool() ? VARIANT_TRUE : VARIANT_FALSE;
+ if (out) {
+ arg.pboolVal = new short(arg.boolVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+ case QVariant::Double:
+ if (out && arg.vt == (VT_R8|VT_BYREF)) {
+ *arg.pdblVal = qvar.toDouble();
+ } else {
+ arg.vt = VT_R8;
+ arg.dblVal = qvar.toDouble();
+ if (out) {
+ if (typeName == "float") {
+ arg.vt = VT_R4;
+ arg.pfltVal = new float(arg.dblVal);
+ } else {
+ arg.pdblVal = new double(arg.dblVal);
+ }
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+ case QVariant::Color:
+ if (out && arg.vt == (VT_COLOR|VT_BYREF)) {
+
+ *arg.plVal = QColorToOLEColor(qvariant_cast<QColor>(qvar));
+ } else {
+ arg.vt = VT_COLOR;
+ arg.lVal = QColorToOLEColor(qvariant_cast<QColor>(qvar));
+ if (out) {
+ arg.plVal = new long(arg.lVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ case QVariant::Date:
+ case QVariant::Time:
+ case QVariant::DateTime:
+ if (out && arg.vt == (VT_DATE|VT_BYREF)) {
+ *arg.pdate = QDateTimeToDATE(qvar.toDateTime());
+ } else {
+ arg.vt = VT_DATE;
+ arg.date = QDateTimeToDATE(qvar.toDateTime());
+ if (out) {
+ arg.pdate = new DATE(arg.date);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+#if 0 // not a value with min/max semantics
+ case QVariant::Font:
+ if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) {
+ if (*arg.ppdispVal)
+ (*arg.ppdispVal)->Release();
+ *arg.ppdispVal = QFontToIFont(qvariant_cast<QFont>(qvar));
+ } else {
+ arg.vt = VT_DISPATCH;
+ arg.pdispVal = QFontToIFont(qvariant_cast<QFont>(qvar));
+ if (out) {
+ arg.ppdispVal = new IDispatch*(arg.pdispVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+ case QVariant::Pixmap:
+ if (out && arg.vt == (VT_DISPATCH|VT_BYREF)) {
+ if (*arg.ppdispVal)
+ (*arg.ppdispVal)->Release();
+ *arg.ppdispVal = QPixmapToIPicture(qvariant_cast<QPixmap>(qvar));
+ } else {
+ arg.vt = VT_DISPATCH;
+ arg.pdispVal = QPixmapToIPicture(qvariant_cast<QPixmap>(qvar));
+ if (out) {
+ arg.ppdispVal = new IDispatch*(arg.pdispVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+ case QVariant::Cursor:
+ {
+#ifndef QT_NO_CURSOR
+ int shape = qvariant_cast<QCursor>(qvar).shape();
+ if (out && (arg.vt & VT_BYREF)) {
+ switch (arg.vt & ~VT_BYREF) {
+ case VT_I4:
+ *arg.plVal = shape;
+ break;
+ case VT_I2:
+ *arg.piVal = shape;
+ break;
+ case VT_UI4:
+ *arg.pulVal = shape;
+ break;
+ case VT_UI2:
+ *arg.puiVal = shape;
+ break;
+ case VT_INT:
+ *arg.pintVal = shape;
+ break;
+ case VT_UINT:
+ *arg.puintVal = shape;
+ break;
+ }
+ } else {
+ arg.vt = VT_I4;
+ arg.lVal = shape;
+ if (out) {
+ arg.plVal = new long(arg.lVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+#endif
+ }
+ break;
+
+ case QVariant::List:
+ {
+ const QList<QVariant> list = qvar.toList();
+ const int count = list.count();
+ VARTYPE vt = VT_VARIANT;
+ QVariant::Type listType = QVariant::LastType; // == QVariant
+ if (!typeName.isEmpty() && typeName.startsWith("QList<")) {
+ const QByteArray listTypeName = typeName.mid(6, typeName.length() - 7); // QList<int> -> int
+ listType = QVariant::nameToType(listTypeName);
+ }
+
+ VARIANT variant;
+ void *pElement = &variant;
+ switch (listType) {
+ case QVariant::Int:
+ vt = VT_I4;
+ pElement = &variant.lVal;
+ break;
+ case QVariant::Double:
+ vt = VT_R8;
+ pElement = &variant.dblVal;
+ break;
+ case QVariant::DateTime:
+ vt = VT_DATE;
+ pElement = &variant.date;
+ break;
+ case QVariant::Bool:
+ vt = VT_BOOL;
+ pElement = &variant.boolVal;
+ break;
+ case QVariant::LongLong:
+#if !defined(Q_OS_WINCE) && defined(_MSC_VER) && _MSC_VER >= 1400
+ vt = VT_I8;
+ pElement = &variant.llVal;
+#else
+ vt = VT_CY;
+ pElement = &variant.cyVal;
+#endif
+ break;
+ default:
+ break;
+ }
+ SAFEARRAY *array = 0;
+ bool is2D = false;
+ // If the first element in the array is a list the whole list is
+ // treated as a 2D array. The column count is taken from the 1st element.
+ if (count) {
+ QVariantList col = list.at(0).toList();
+ int maxColumns = col.count();
+ if (maxColumns) {
+ is2D = true;
+ SAFEARRAYBOUND rgsabound[2] = { {0} };
+ rgsabound[0].cElements = count;
+ rgsabound[1].cElements = maxColumns;
+ array = SafeArrayCreate(VT_VARIANT, 2, rgsabound);
+ LONG rgIndices[2];
+ for (LONG i = 0; i < count; ++i) {
+ rgIndices[0] = i;
+ QVariantList columns = list.at(i).toList();
+ int columnCount = qMin(maxColumns, columns.count());
+ for (LONG j = 0; j < columnCount; ++j) {
+ QVariant elem = columns.at(j);
+ VariantInit(&variant);
+ QVariantToVARIANT(elem, variant, elem.typeName());
+ rgIndices[1] = j;
+ SafeArrayPutElement(array, rgIndices, pElement);
+ clearVARIANT(&variant);
+ }
+ }
+
+ }
+ }
+ if (!is2D) {
+ array = SafeArrayCreateVector(vt, 0, count);
+ for (LONG index = 0; index < count; ++index) {
+ QVariant elem = list.at(index);
+ if (listType != QVariant::LastType)
+ elem.convert(listType);
+ VariantInit(&variant);
+ QVariantToVARIANT(elem, variant, elem.typeName());
+ SafeArrayPutElement(array, &index, pElement);
+ clearVARIANT(&variant);
+ }
+ }
+ if (out && arg.vt == (VT_ARRAY|vt|VT_BYREF)) {
+ if (*arg.pparray)
+ SafeArrayDestroy(*arg.pparray);
+ *arg.pparray = array;
+ } else {
+ arg.vt = VT_ARRAY|vt;
+ arg.parray = array;
+ if (out) {
+ arg.pparray = new SAFEARRAY*(arg.parray);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ }
+ break;
+
+ case QVariant::StringList:
+ {
+ const QStringList list = qvar.toStringList();
+ const int count = list.count();
+ SAFEARRAY *array = SafeArrayCreateVector(VT_BSTR, 0, count);
+ for (LONG index = 0; index < count; ++index) {
+ QString elem = list.at(index);
+ BSTR bstr = QStringToBSTR(elem);
+ SafeArrayPutElement(array, &index, bstr);
+ SysFreeString(bstr);
+ }
+
+ if (out && arg.vt == (VT_ARRAY|VT_BSTR|VT_BYREF)) {
+ if (*arg.pparray)
+ SafeArrayDestroy(*arg.pparray);
+ *arg.pparray = array;
+ } else {
+ arg.vt = VT_ARRAY|VT_BSTR;
+ arg.parray = array;
+ if (out) {
+ arg.pparray = new SAFEARRAY*(arg.parray);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ }
+ break;
+
+ case QVariant::ByteArray:
+ {
+ const QByteArray bytes = qvar.toByteArray();
+ const uint count = bytes.count();
+ SAFEARRAY *array = SafeArrayCreateVector(VT_UI1, 0, count);
+ if (count) {
+ const char *data = bytes.constData();
+ char *dest;
+ SafeArrayAccessData(array, (void **)&dest);
+ memcpy(dest, data, count);
+ SafeArrayUnaccessData(array);
+ }
+
+ if (out && arg.vt == (VT_ARRAY|VT_UI1|VT_BYREF)) {
+ if (*arg.pparray)
+ SafeArrayDestroy(*arg.pparray);
+ *arg.pparray = array;
+ } else {
+ arg.vt = VT_ARRAY|VT_UI1;
+ arg.parray = array;
+ if (out) {
+ arg.pparray = new SAFEARRAY*(arg.parray);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ }
+ break;
+
+#ifdef QAX_SERVER
+ case QVariant::Rect:
+ case QVariant::Size:
+ case QVariant::Point:
+ {
+ typedef HRESULT(WINAPI* PGetRecordInfoFromTypeInfo)(ITypeInfo *, IRecordInfo **);
+ static PGetRecordInfoFromTypeInfo pGetRecordInfoFromTypeInfo = 0;
+ static bool resolved = false;
+ if (!resolved) {
+ QSystemLibrary oleaut32(QLatin1String("oleaut32"));
+ pGetRecordInfoFromTypeInfo = (PGetRecordInfoFromTypeInfo)oleaut32.resolve("GetRecordInfoFromTypeInfo");
+ resolved = true;
+ }
+ if (!pGetRecordInfoFromTypeInfo)
+ break;
+
+ ITypeInfo *typeInfo = 0;
+ IRecordInfo *recordInfo = 0;
+ CLSID clsid = qvar.type() == QVariant::Rect ? CLSID_QRect
+ :qvar.type() == QVariant::Size ? CLSID_QSize
+ :CLSID_QPoint;
+ qAxTypeLibrary->GetTypeInfoOfGuid(clsid, &typeInfo);
+ if (!typeInfo)
+ break;
+ pGetRecordInfoFromTypeInfo(typeInfo, &recordInfo);
+ typeInfo->Release();
+ if (!recordInfo)
+ break;
+
+ void *record = 0;
+ switch (qvar.type()) {
+ case QVariant::Rect:
+ {
+ QRect qrect(qvar.toRect());
+ recordInfo->RecordCreateCopy(&qrect, &record);
+ }
+ break;
+ case QVariant::Size:
+ {
+ QSize qsize(qvar.toSize());
+ recordInfo->RecordCreateCopy(&qsize, &record);
+ }
+ break;
+ case QVariant::Point:
+ {
+ QPoint qpoint(qvar.toPoint());
+ recordInfo->RecordCreateCopy(&qpoint, &record);
+ }
+ break;
+ }
+
+ arg.vt = VT_RECORD;
+ arg.pRecInfo = recordInfo,
+ arg.pvRecord = record;
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for records");
+ return false;
+ }
+ }
+ break;
+#endif // QAX_SERVER
+ case QVariant::UserType:
+ {
+ QByteArray subType = qvar.typeName();
+#ifdef QAX_SERVER
+ if (subType.endsWith('*'))
+ subType.truncate(subType.length() - 1);
+#endif
+ if (!qstrcmp(qvar.typeName(), "IDispatch*")) {
+ arg.vt = VT_DISPATCH;
+ arg.pdispVal = *(IDispatch**)qvar.data();
+ if (arg.pdispVal)
+ arg.pdispVal->AddRef();
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for IDispatch");
+ return false;
+ }
+ } else if (!qstrcmp(qvar.typeName(), "IDispatch**")) {
+ arg.vt = VT_DISPATCH;
+ arg.ppdispVal = *(IDispatch***)qvar.data();
+ if (out)
+ arg.vt |= VT_BYREF;
+ } else if (!qstrcmp(qvar.typeName(), "IUnknown*")) {
+ arg.vt = VT_UNKNOWN;
+ arg.punkVal = *(IUnknown**)qvar.data();
+ if (arg.punkVal)
+ arg.punkVal->AddRef();
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for IUnknown");
+ return false;
+ }
+#ifdef QAX_SERVER
+ } else if (qAxFactory()->metaObject(QString::fromLatin1(subType.constData()))) {
+ arg.vt = VT_DISPATCH;
+ void *user = *(void**)qvar.constData();
+// qVariantGet(qvar, user, qvar.typeName());
+ if (!user) {
+ arg.pdispVal = 0;
+ } else {
+ qAxFactory()->createObjectWrapper(static_cast<QObject*>(user), &arg.pdispVal);
+ }
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for subtype");
+ return false;
+ }
+#else
+ } else if (QMetaType::type(subType)) {
+ QAxObject *object = *(QAxObject**)qvar.constData();
+// qVariantGet(qvar, object, subType);
+ arg.vt = VT_DISPATCH;
+ object->queryInterface(IID_IDispatch, (void**)&arg.pdispVal);
+ if (out) {
+ qWarning("QVariantToVARIANT: out-parameter not supported for subtype");
+ return false;
+ }
+#endif
+ } else {
+ return false;
+ }
+ }
+ break;
+#endif
+
+ case QVariant::Invalid: // default-parameters not set
+ if (out && arg.vt == (VT_ERROR|VT_BYREF)) {
+ *arg.plVal = DISP_E_PARAMNOTFOUND;
+ } else {
+ arg.vt = VT_ERROR;
+ arg.lVal = DISP_E_PARAMNOTFOUND;
+ if (out) {
+ arg.plVal = new long(arg.lVal);
+ arg.vt |= VT_BYREF;
+ }
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ Q_ASSERT(!out || (arg.vt & VT_BYREF));
+ return true;
+}
+
diff --git a/src/plugins/platforms/windows/accessible/comutils.h b/src/plugins/platforms/windows/accessible/comutils.h
new file mode 100644
index 0000000000..08420cc46c
--- /dev/null
+++ b/src/plugins/platforms/windows/accessible/comutils.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef COMUTILS_H
+#define COMUTILS_H
+
+#if !defined(_WINDOWS_) && !defined(_WINDOWS_H) && !defined(__WINDOWS__)
+#error Must include windows.h first!
+#endif
+
+#include <ocidl.h>
+#include <QtCore/qstring.h>
+
+class QVariant;
+
+bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out);
+
+inline BSTR QStringToBSTR(const QString &str)
+{
+ return SysAllocStringLen((OLECHAR*)str.unicode(), str.length());
+}
+
+#endif // COMUTILS_H
+
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
new file mode 100644
index 0000000000..f22349714f
--- /dev/null
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
@@ -0,0 +1,1467 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "iaccessible2.h"
+#include "qwindowsaccessibility.h"
+
+#include <QtGui/qaccessible2.h>
+#include <QtWidgets/qapplication.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/**************************************************************\
+ * AccessibleApplication *
+ **************************************************************/
+// IUnknown
+HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOID *iface)
+{
+ *iface = 0;
+ if (id == IID_IUnknown) {
+ accessibleDebug("AccessibleApplication::QI(): IID_IUnknown");
+ *iface = (IUnknown*)this;
+ } else if (id == IID_IAccessibleApplication) {
+ accessibleDebug("AccessibleApplication::QI(): IID_IAccessibleApplication");
+ *iface = static_cast<IAccessibleApplication*>(this);
+ }
+
+ if (*iface) {
+ AddRef();
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+ULONG STDMETHODCALLTYPE AccessibleApplication::AddRef()
+{
+ return ++m_ref;
+}
+
+ULONG STDMETHODCALLTYPE AccessibleApplication::Release()
+{
+ if (!--m_ref) {
+ delete this;
+ return 0;
+ }
+ return m_ref;
+}
+
+/* IAccessibleApplication */
+HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name)
+{
+ const QString appName = QGuiApplication::applicationName();
+ *name = QStringToBSTR(appName);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appVersion(/* [retval][out] */ BSTR *version)
+{
+ const QString appName = QGuiApplication::applicationVersion();
+ *version = QStringToBSTR(appName);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out] */ BSTR *name)
+{
+ *name = ::SysAllocString(L"Qt");
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version)
+{
+ *version = ::SysAllocString(QT_UNICODE_LITERAL(QT_VERSION_STR));
+ return S_OK;
+}
+
+
+
+/*!
+ \internal
+ Client allocates and deallocates array
+ (see "Special Consideration when using Arrays", in Accessible2.idl)
+ */
+HRESULT STDMETHODCALLTYPE AccessibleRelation::get_target(
+ /* [in] */ long targetIndex,
+ /* [retval][out] */ IUnknown **target)
+{
+ if (targetIndex >= 0 && targetIndex < m_targets.count()) {
+ QAccessibleInterface *iface = m_targets.at(targetIndex);
+ *target = QWindowsAccessibility::wrap(iface);
+ if (*target)
+ return S_OK;
+ return E_FAIL;
+ }
+ return E_INVALIDARG;
+}
+
+/*!
+ \internal
+ Client allocates and deallocates \a targets array
+ (see "Special Consideration when using Arrays", in Accessible2.idl)
+ */
+HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets(
+ /* [in] */ long maxTargets, // Hmmm, ignore ???
+ /* [length_is][size_is][out] */ IUnknown **targets,
+ /* [retval][out] */ long *nTargets)
+{
+
+ const int numTargets = qMin((int)maxTargets, m_targets.count());
+ for (int i = 0; i < numTargets; ++i) {
+ QAccessibleInterface *iface = m_targets.at(i);
+ IAccessible *iacc = QWindowsAccessibility::wrap(iface);
+ if (!iacc)
+ return E_FAIL;
+ *targets = iacc;
+ ++targets;
+ }
+ *nTargets = numTargets;
+ // \a targets array is allocated by client.
+ return numTargets > 0 ? S_OK : S_FALSE;
+}
+
+
+/**************************************************************\
+ * *
+ * IUnknown *
+ * *
+ **************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface)
+{
+ *iface = 0;
+
+ QByteArray strIID = IIDToString(id);
+ if (!strIID.isEmpty()) {
+ QString ss; QDebug dbg(&ss); dbg << accessible;
+ accessibleDebug("QWindowsIA2Accessible::QI() - IID:%s, iface:%s ", strIID.constData(), qPrintable(ss));
+ }
+ 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 if (id == IID_IServiceProvider) {
+ *iface = (IServiceProvider*)this;
+ } else if (id == IID_IAccessible2) {
+ *iface = (IAccessible2*)this;
+ } else if (id == IID_IAccessibleAction) {
+ if (accessible->actionInterface())
+ *iface = (IAccessibleAction*)this;
+ } else if (id == IID_IAccessibleComponent) {
+ *iface = (IAccessibleComponent*)this;
+ } else if (id == IID_IAccessibleEditableText) {
+ //if (accessible->editableTextInterface()) {
+ //*iface = (IAccessibleEditableText*)this;
+ //}
+ } else if (id == IID_IAccessibleHyperlink) {
+ //*iface = (IAccessibleHyperlink*)this;
+ } else if (id == IID_IAccessibleHypertext) {
+ //*iface = (IAccessibleHypertext*)this;
+ } else if (id == IID_IAccessibleImage) {
+ //*iface = (IAccessibleImage*)this;
+ } else if (id == IID_IAccessibleRelation) {
+ *iface = (IAccessibleRelation*)this;
+ } else if (id == IID_IAccessibleTable) {
+ //*iface = (IAccessibleTable*)this; // not supported
+ } else if (id == IID_IAccessibleTable2) {
+ if (accessible->tableInterface())
+ *iface = (IAccessibleTable2*)this;
+ } else if (id == IID_IAccessibleTableCell) {
+ if (accessible->tableCellInterface())
+ *iface = (IAccessibleTableCell*)this;
+ } else if (id == IID_IAccessibleText) {
+ if (accessible->textInterface())
+ *iface = (IAccessibleText*)this;
+ } else if (id == IID_IAccessibleValue) {
+ if (accessible->valueInterface())
+ *iface = (IAccessibleValue*)this;
+ }
+ if (*iface) {
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::AddRef()
+{
+ return ++ref;
+}
+
+ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::Release()
+{
+ if (!--ref) {
+ delete this;
+ return 0;
+ }
+ return ref;
+}
+
+
+
+/**************************************************************\
+ * *
+ * IAccessible2 *
+ * *
+ **************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRelations(long *nRelations)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!nRelations)
+ return E_INVALIDARG;
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ return getRelationsHelper(0, 0, 0, nRelations);
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relation(long relationIndex, IAccessibleRelation **relation)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!relation)
+ return E_INVALIDARG;
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ return getRelationsHelper(relation, relationIndex, 1);
+}
+
+/*!
+ \internal
+ Client allocates and deallocates array
+ (see "Special Consideration when using Arrays", in Accessible2.idl)
+ */
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_relations(long maxRelations,
+ IAccessibleRelation **relations,
+ long *nRelations)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ return getRelationsHelper(relations, 0, maxRelations, nRelations);
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::role(long *ia2role)
+{
+ accessibleDebugClientCalls(accessible);
+ //### Change QAccessibleInterface::role() to return both MSAA and IA2 roles.
+ // When that is completed, we must patch the MSAA bridge not not return any
+ // IA2-specific roles from get_accRole().
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ *ia2role = accessible->role();
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollTo(enum IA2ScrollType /*scrollType*/)
+{
+ //### Ignore for now
+ return E_NOTIMPL;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollToPoint(enum IA2CoordinateType /*coordinateType*/, long /*x*/, long /*y*/)
+{
+ //### Ignore for now
+ return E_NOTIMPL;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_groupPosition(long *groupLevel,
+ long *similarItemsInGroup,
+ long *positionInGroup)
+{
+ // ### Ignore for now. Not sure what this is used for.....
+ *groupLevel = 0; // Not applicable
+ *similarItemsInGroup = 0; // Not applicable
+ *positionInGroup = 0; // Not applicable
+ return S_FALSE;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_states(AccessibleStates *states)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ if (!states)
+ return E_POINTER;
+ QAccessible::State st = accessible->state();
+ AccessibleStates ia2states = 0;
+ if (st.active)
+ ia2states |= IA2_STATE_ACTIVE;
+ if (st.invalid)
+ ia2states |= IA2_STATE_DEFUNCT;
+ if (st.editable)
+ ia2states |= IA2_STATE_EDITABLE;
+ if (st.multiLine)
+ ia2states |= IA2_STATE_MULTI_LINE;
+ if (st.selectableText)
+ ia2states |= IA2_STATE_SELECTABLE_TEXT;
+ if (st.supportsAutoCompletion)
+ ia2states |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
+
+ *states = ia2states;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedRole(BSTR *extendedRole)
+{
+ //###
+ *extendedRole = 0;
+ return E_NOTIMPL; // mozilla does this
+ //return S_FALSE;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedRole(BSTR *localizedExtendedRole)
+{
+ //###
+ *localizedExtendedRole = 0;
+ return E_NOTIMPL; // mozilla does this
+ //return S_FALSE;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nExtendedStates(long *nExtendedStates)
+{
+ // Who will ever intepret these values into something meaningful??
+ *nExtendedStates = 0;
+ return E_NOTIMPL; // mozilla does this
+ //return S_FALSE;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_extendedStates(long /*maxExtendedStates*/,
+ BSTR **extendedStates,
+ long *nExtendedStates)
+{
+ *extendedStates = 0;
+ *nExtendedStates = 0;
+ return E_NOTIMPL; // mozilla does this
+ //return S_FALSE;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedExtendedStates(long /*maxLocalizedExtendedStates*/,
+ BSTR **localizedExtendedStates,
+ long *nLocalizedExtendedStates)
+{
+ *localizedExtendedStates = 0;
+ *nLocalizedExtendedStates = 0;
+ return E_NOTIMPL; // mozilla does this
+ //return S_FALSE;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_uniqueID(long *outUniqueID)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ // ### FIXME SERIOUSLY, NOT A STABLE SOLUTION IF NODES ARE DELETED ETC
+ // Return 0 if no object and no parent. This is really an error case.
+ uint uid = uniqueID();
+ accessibleDebug("uniqueID: %08x", uid);
+
+ *outUniqueID = (long)uid;
+ return uid ? S_OK : S_FALSE;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_windowHandle(HWND *windowHandle)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ return GetWindow(windowHandle);
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_indexInParent(long *indexInParent)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ if (!indexInParent)
+ return E_INVALIDARG;
+ QAccessibleInterface *par = accessible->parent();
+ if (!par) {
+ *indexInParent = -1;
+ return S_FALSE;
+ }
+ int indexOfChild = par->indexOfChild(accessible);
+ delete par;
+ Q_ASSERT(indexOfChild >= 0);
+ *indexInParent = indexOfChild;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locale(IA2Locale *locale)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ IA2Locale res;
+ QLocale l;
+ res.country = QStringToBSTR(QLocale::countryToString(l.country()));
+ res.language = QStringToBSTR(QLocale::languageToString(l.language()));
+ *locale = res;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(BSTR *attributes)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *attributes = 0;//QStringToBSTR(QString());
+ return S_FALSE;
+}
+
+/**************************************************************\
+ * IAccessibleAction *
+ **************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::nActions(long *nActions)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *nActions = 0;
+
+ if (QAccessibleActionInterface *actionIface = actionInterface())
+ *nActions = actionIface->actionNames().count();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::doAction(long actionIndex)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ if (QAccessibleActionInterface *actionIface = actionInterface()) {
+ const QStringList actionNames = actionIface->actionNames();
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ actionIface->doAction(actionName);
+ return S_OK;
+ }
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_description(long actionIndex, BSTR *description)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *description = 0;
+ if (QAccessibleActionInterface *actionIface = actionInterface()) {
+ const QStringList actionNames = actionIface->actionNames();
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ *description = QStringToBSTR(actionIface->localizedActionDescription(actionName));
+ }
+ return *description ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ Q_UNUSED(nMaxBindings);
+ BSTR *arrayOfBindingsToReturn = 0;
+ int numBindings = 0;
+ if (QAccessibleActionInterface *actionIface = actionInterface()) {
+ const QStringList actionNames = actionIface->actionNames();
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ const QStringList keyBindings = actionIface->keyBindingsForAction(actionName);
+ numBindings = keyBindings.count();
+ if (numBindings > 0) {
+ // The IDL documents that the client must free with CoTaskMemFree
+ arrayOfBindingsToReturn = (BSTR*)::CoTaskMemAlloc(sizeof(BSTR) * numBindings);
+ for (int i = 0; i < numBindings; ++i)
+ arrayOfBindingsToReturn[i] = QStringToBSTR(keyBindings.at(i));
+ }
+ }
+ *keyBindings = arrayOfBindingsToReturn;
+ *nBindings = numBindings;
+
+ return numBindings ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_name(long actionIndex, BSTR *name)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *name = 0;
+ if (QAccessibleActionInterface *actionIface = actionInterface()) {
+ const QStringList actionNames = actionIface->actionNames();
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+ const QString actionName = actionNames.at(actionIndex);
+ *name = QStringToBSTR(actionName);
+ }
+ return *name ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_localizedName(long actionIndex, BSTR *localizedName)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *localizedName = 0;
+ if (QAccessibleActionInterface *actionIface = actionInterface()) {
+ const QStringList actionNames = actionIface->actionNames();
+ if (actionIndex < 0 || actionIndex >= actionNames.count())
+ return E_INVALIDARG;
+
+ const QString actionName = actionNames.at(actionIndex);
+ *localizedName = QStringToBSTR(actionIface->localizedActionName(actionName));
+ }
+ return *localizedName ? S_OK : S_FALSE;
+}
+
+/**************************************************************\
+ * IAccessibleComponent *
+ **************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, long *y)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QPoint topLeft = accessible->rect().topLeft();
+
+ if (QAccessibleInterface *parentIface = accessible->parent())
+ topLeft -= parentIface->rect().topLeft();
+
+ *x = topLeft.x();
+ *y = topLeft.y();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foreground)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ // IA2Color is a typedef for long
+ *foreground = (IA2Color)accessible->foregroundColor().rgb();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *background)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ // IA2Color is a typedef for long
+ *background = (IA2Color)accessible->backgroundColor().rgb();
+ return S_OK;
+}
+
+/**************************************************************\
+ * IAccessibleTable2 *
+ **************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long column, IUnknown **cell)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ *cell = 0;
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ if (QAccessibleInterface *qtCell = tableIface->cellAt(row, column)) {
+ *cell = QWindowsAccessibility::wrap(qtCell);
+ }
+ }
+ accessibleDebug("found cell? %p", *cell);
+ return *cell ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caption( IUnknown **captionInterface)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ *captionInterface = 0;
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ if (QAccessibleInterface *iface = tableIface->caption())
+ *captionInterface = QWindowsAccessibility::wrap(iface);
+ }
+ return *captionInterface ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnDescription( long column, BSTR *description)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ *description = 0;
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ const QString qtDesc = tableIface->columnDescription(column);
+ if (!qtDesc.isEmpty())
+ *description = QStringToBSTR(qtDesc);
+ }
+ return *description ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nColumns( long *columnCount)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ *columnCount = tableIface->columnCount();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nRows(long *rowCount)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ *rowCount = tableIface->rowCount();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedCells(long *cellCount)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ *cellCount = tableIface->selectedCellCount();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedColumns(long *columnCount)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ *columnCount = tableIface->selectedColumnCount();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelectedRows(long *rowCount)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ *rowCount = tableIface->selectedRowCount();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowDescription(long row, BSTR *description)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ *description = 0;
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ const QString qtDesc = tableIface->columnDescription(row);
+ if (!qtDesc.isEmpty())
+ *description = QStringToBSTR(qtDesc);
+ }
+ return *description ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedCells(IUnknown ***cells, long *nSelectedCells)
+{
+ accessibleDebugClientCalls(accessible);
+ Q_UNUSED(cells);
+ Q_UNUSED(nSelectedCells);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QList<QAccessibleInterface*> selectedCells = tableInterface()->selectedCells();
+ return wrapListOfCells(selectedCells, cells, nSelectedCells);
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **selectedColumns, long *nColumns)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ const QList<int> selectedIndices = tableIface->selectedColumns();
+ const int &count = selectedIndices.count();
+ long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0);
+ for (int i = 0; i < count; ++i)
+ selected[i] = selectedIndices.at(i);
+ *selectedColumns = selected;
+ *nColumns = count;
+ return count ? S_OK : S_FALSE;
+ }
+ return E_FAIL;
+
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selectedRows, long *nRows)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ const QList<int> selectedIndices = tableIface->selectedRows();
+ const int &count = selectedIndices.count();
+ long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0);
+ for (int i = 0; i < count; ++i)
+ selected[i] = selectedIndices.at(i);
+ *selectedRows = selected;
+ *nRows = count;
+ return count ? S_OK : S_FALSE;
+ }
+ return E_FAIL;
+
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_summary(IUnknown **summaryInterface)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ *summaryInterface = 0;
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ if (QAccessibleInterface *iface = tableIface->summary())
+ *summaryInterface = QWindowsAccessibility::wrap(iface);
+ }
+ return *summaryInterface ? S_OK : S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isColumnSelected(long column, boolean *isSelected)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ *isSelected = tableIface->isColumnSelected(column);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isRowSelected(long row, boolean *isSelected)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ *isSelected = tableIface->isRowSelected(row);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectRow(long row)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ bool ok = tableIface->selectRow(row);
+ return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails???
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::selectColumn(long column)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ bool ok = tableIface->selectColumn(column);
+ return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails???
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectRow(long row)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ bool ok = tableIface->unselectRow(row);
+ return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails???
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::unselectColumn(long column)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ if (QAccessibleTableInterface *tableIface = tableInterface()) {
+ bool ok = tableIface->unselectColumn(column);
+ return ok ? S_OK : E_INVALIDARG; //### Not sure of the return value if it fails???
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_modelChange( IA2TableModelChange * /*modelChange*/)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ return E_NOTIMPL;
+}
+
+/**************************************************************\
+ * IAccessibleTableCell *
+\**************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnExtent(long *nColumnsSpanned)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ *nColumnsSpanned = tableCellInterface()->columnExtent();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnHeaderCells(IUnknown ***cellAccessibles,
+ long *nColumnHeaderCells)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ const QList<QAccessibleInterface*> headerCells = tableCellInterface()->columnHeaderCells();
+ return wrapListOfCells(headerCells, cellAccessibles, nColumnHeaderCells);
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_columnIndex(long *columnIndex)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *columnIndex = tableCellInterface()->columnIndex();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowExtent(long *nRowsSpanned)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *nRowsSpanned = tableCellInterface()->rowExtent();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowHeaderCells(IUnknown ***cellAccessibles,
+ long *nRowHeaderCells)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ const QList<QAccessibleInterface*> headerCells = tableCellInterface()->rowHeaderCells();
+ return wrapListOfCells(headerCells, cellAccessibles, nRowHeaderCells);
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowIndex(long *rowIndex)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *rowIndex = tableCellInterface()->rowIndex();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_isSelected( boolean *isSelected)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ *isSelected = tableCellInterface()->isSelected();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, long *column,
+ long *rowExtents, long *columnExtents,
+ boolean *isSelected)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ tableCellInterface()->rowColumnExtents((int*)row, (int*)column, (int*)rowExtents, (int*)columnExtents, (bool*)isSelected);
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_table(IUnknown **table)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+
+ QAccessibleInterface *tableIface = tableCellInterface()->table();
+
+ *table = QWindowsAccessibility::wrap(tableIface);
+ return S_OK;
+}
+
+/**************************************************************\
+ * IAccessibleText *
+\**************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::addSelection(long startOffset,
+ long endOffset)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *text = textInterface()) {
+ text->addSelection(startOffset, endOffset);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset,
+ long *startOffset,
+ long *endOffset,
+ BSTR *textAttributes)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *text = textInterface()) {
+ const QString attrs = text->attributes(offset, (int*)startOffset, (int*)endOffset);
+ *textAttributes = QStringToBSTR(attrs);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_caretOffset(long *offset)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *text = textInterface()) {
+ *offset = text->cursorPosition();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_characterExtents(long offset,
+ enum IA2CoordinateType coordType,
+ long *x,
+ long *y,
+ long *width,
+ long *height)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *text = textInterface()) {
+ const QRect rect = text->characterRect(offset, (QAccessible2::CoordinateType)coordType);
+ *x = rect.x();
+ *y = rect.y();
+ *width = rect.width();
+ *height = rect.height();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nSelections(long *nSelections)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *text = textInterface()) {
+ *nSelections = text->selectionCount();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_offsetAtPoint(long x,
+ long y,
+ enum IA2CoordinateType coordType,
+ long *offset)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *text = textInterface()) {
+ *offset = text->offsetAtPoint(QPoint(x,y), (QAccessible2::CoordinateType)coordType);
+ return (*offset >=0 ? S_OK : S_FALSE);
+ }
+ return E_FAIL;
+
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionIndex,
+ long *startOffset,
+ long *endOffset)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *text = textInterface()) {
+ text->selection(selectionIndex, (int*)startOffset, (int*)endOffset);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_text(long startOffset,
+ long endOffset,
+ BSTR *text)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textif = textInterface()) {
+ const QString t = textif->text(startOffset, endOffset);
+ if (!t.isEmpty()) {
+ *text = QStringToBSTR(t);
+ return S_OK;
+ }
+ return E_INVALIDARG;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offset,
+ enum IA2TextBoundaryType boundaryType,
+ long *startOffset,
+ long *endOffset,
+ BSTR *text)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textIface = textInterface()) {
+ const QString txt = textIface->textBeforeOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
+ if (!txt.isEmpty()) {
+ *text = QStringToBSTR(txt);
+ return S_OK;
+ }
+ return S_FALSE;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset(
+ long offset,
+ enum IA2TextBoundaryType boundaryType,
+ long *startOffset,
+ long *endOffset,
+ BSTR *text)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textIface = textInterface()) {
+ const QString txt = textIface->textAfterOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
+ if (!txt.isEmpty()) {
+ *text = QStringToBSTR(txt);
+ return S_OK;
+ }
+ return S_FALSE;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset,
+ enum IA2TextBoundaryType boundaryType,
+ long *startOffset,
+ long *endOffset,
+ BSTR *text)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textIface = textInterface()) {
+ const QString txt = textIface->textAtOffset(offset, (QAccessible2::BoundaryType)boundaryType, (int*)startOffset, (int*)endOffset);
+ if (!txt.isEmpty()) {
+ *text = QStringToBSTR(txt);
+ return S_OK;
+ }
+ return S_FALSE;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::removeSelection(long selectionIndex)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textIface = textInterface()) {
+ textIface->removeSelection(selectionIndex);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCaretOffset(long offset)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textIface = textInterface()) {
+ textIface->setCursorPosition(offset);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setSelection(long selectionIndex,
+ long startOffset,
+ long endOffset)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textIface = textInterface()) {
+ textIface->setSelection(selectionIndex, startOffset, endOffset);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_nCharacters(long *nCharacters)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textIface = textInterface()) {
+ *nCharacters = textIface->characterCount();
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringTo(long startIndex,
+ long endIndex,
+ enum IA2ScrollType scrollType)
+{
+ accessibleDebugClientCalls(accessible);
+ if (QAccessibleTextInterface *textIface = textInterface()) {
+ Q_UNUSED(scrollType); //###
+ textIface->scrollToSubstring(startIndex, endIndex);
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::scrollSubstringToPoint(long startIndex,
+ long endIndex,
+ enum IA2CoordinateType coordinateType,
+ long x,
+ long y)
+{
+ Q_UNUSED(startIndex);
+ Q_UNUSED(endIndex);
+ Q_UNUSED(coordinateType);
+ Q_UNUSED(x);
+ Q_UNUSED(y);
+
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_newText(IA2TextSegment *newText)
+{
+ Q_UNUSED(newText);
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_oldText(IA2TextSegment *oldText)
+{
+ Q_UNUSED(oldText);
+ return E_NOTIMPL;
+}
+
+/**************************************************************\
+ * IAccessibleValue *
+ **************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_currentValue(VARIANT *currentValue)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ if (QAccessibleValueInterface *valueIface = valueInterface()) {
+ const QVariant var = valueIface->currentValue();
+ if (QVariantToVARIANT(var, *currentValue, QByteArray(), false))
+ return S_OK;
+
+ }
+ currentValue->vt = VT_EMPTY;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setCurrentValue(VARIANT value)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ HRESULT hr = S_FALSE;
+ if (QAccessibleValueInterface *valueIface = valueInterface()) {
+ hr = VariantChangeType(&value, &value, 0, VT_R8);
+ if (SUCCEEDED(hr)) {
+ // ### works only for numbers (not date, strings, etc)
+ valueIface->setCurrentValue(QVariant(value.dblVal));
+ }
+ }
+ return hr;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_maximumValue(VARIANT *maximumValue)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ if (QAccessibleValueInterface *valueIface = valueInterface()) {
+ const QVariant var = valueIface->maximumValue();
+ if (QVariantToVARIANT(var, *maximumValue, QByteArray(), false))
+ return S_OK;
+ }
+ maximumValue->vt = VT_EMPTY;
+ return S_FALSE;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_minimumValue(VARIANT *minimumValue)
+{
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
+ if (QAccessibleValueInterface *valueIface = valueInterface()) {
+ const QVariant var = valueIface->minimumValue();
+ if (QVariantToVARIANT(var, *minimumValue, QByteArray(), false))
+ return S_OK;
+ }
+ minimumValue->vt = VT_EMPTY;
+ return S_FALSE;
+}
+
+
+/**************************************************************\
+ * IServiceProvider *
+ **************************************************************/
+/*!
+ \internal
+ Reimplemented from IServiceProvider
+*/
+HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidService, REFIID riid, void **iface)
+{
+ if (!iface)
+ return E_POINTER;
+ Q_UNUSED(guidService);
+ *iface = 0;
+ accessibleDebug("QWindowsIA2Accessible::QS(): %s", IIDToString(riid).constData());
+ if (riid == IID_IAccessible || riid == IID_IUnknown || riid == IID_IDispatch) {
+ *iface = static_cast<IAccessible*>(this);
+ } else if (/*guidService == IID_IAccessible && */riid == IID_IAccessible2) {
+ *iface = static_cast<IAccessible2*>(this);
+ } else if (riid == IID_IAccessibleApplication) {
+ *iface = new AccessibleApplication;
+ return S_OK;
+ } else {
+ QueryInterface(riid, iface);
+ }
+ if (*iface) {
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+
+/*!
+ \internal
+ private function..
+ \a maxRelations max number of relations to return in \a relations
+ \a relations the array of relations matching
+ \a startIndex Index to start to return from,
+ it will return only that specific relation in \a relations
+
+ If \a relations is null, \a startIndex and \a maxRelations are ignored, causing
+ it to return the number of relations in \a nRelations
+*/
+HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations /* = 0*/)
+{
+ if (nRelations)
+ *nRelations = 0;
+ typedef QPair<QAccessibleInterface *, QAccessible::Relation> RelationEntry;
+ QVector<RelationEntry> rels = accessible->relations();
+ QMap<QAccessible::Relation, QAccessibleInterface *> relationMap;
+ for (QVector<RelationEntry>::const_iterator it = rels.constBegin(); it != rels.constEnd(); ++it)
+ {
+ RelationEntry e = *it;
+ relationMap.insertMulti(e.second, e.first);
+ }
+
+ QList<QAccessible::Relation> keys = relationMap.keys();
+ const int numRelations = keys.count();
+ if (relations) {
+ for (int i = startIndex; i < qMin(startIndex + (int)maxRelations, numRelations); ++i) {
+ QAccessible::Relation relation = keys.at(i);
+ QList<QAccessibleInterface*> targets = relationMap.values(relation);
+ AccessibleRelation *rel = new AccessibleRelation(targets, relation);
+ *relations = rel;
+ ++relations;
+ }
+ }
+ if (nRelations)
+ *nRelations = numRelations;
+
+ return numRelations > 0 ? S_OK : S_FALSE;
+}
+
+
+
+
+/*!
+ \internal
+ helper to wrap a QList<QAccessibleInterface*> inside an array of IAccessible*
+ The IAccessible* array is returned as a IUnknown*
+*/
+HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount)
+{
+ const int count = inputCells.count();
+ // Server allocates array
+ IUnknown **outputCells = count ? (IUnknown**)::CoTaskMemAlloc(sizeof(IUnknown*) * count ) : (IUnknown**)0;
+ for (int i = 0; i < count; ++i)
+ outputCells[i] = QWindowsAccessibility::wrap(inputCells.at(i));
+
+ *outputAccessibles = outputCells;
+ *nCellCount = count;
+ return count > 0 ? S_OK : S_FALSE;
+}
+
+uint QWindowsIA2Accessible::uniqueID() const
+{
+ uint uid = 0;
+ if (QObject *obj = accessible->object())
+ uid = qHash(obj);
+
+ if (!uid) {
+ QAccessibleInterface *acc = accessible;
+ QVector<int> indexOfNodes;
+ while (acc && !acc->object()) {
+ QAccessibleInterface *par = acc->parent();
+ indexOfNodes.append(par->indexOfChild(acc));
+ if (acc != accessible)
+ delete acc;
+ acc = par;
+ }
+ if (acc) {
+ if (acc->object()) {
+ uid = qHash(acc->object());
+ for (int i = 0; i < indexOfNodes.count(); ++i)
+ uid = qHash(uid + indexOfNodes.at(i));
+
+ }
+ if (acc != accessible)
+ delete acc;
+ }
+ }
+ return uid;
+}
+
+
+#define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid)
+
+QByteArray QWindowsIA2Accessible::IIDToString(REFIID id)
+{
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IServiceProvider);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible2);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleAction);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleApplication);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleComponent);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleEditableText);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHyperlink);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHypertext);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleImage);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleRelation);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable2);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTableCell);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleText);
+ IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleValue);
+
+ // else...
+ QByteArray strGuid;
+#if 0 // Can be useful for debugging, but normally we'd like to reduce the noise a bit...
+ OLECHAR szGuid[39]={0};
+ ::StringFromGUID2(id, szGuid, 39);
+ strGuid.reserve(40);
+ ::WideCharToMultiByte(CP_UTF8, 0, szGuid, 39, strGuid.data(), 39, NULL, NULL);
+ strGuid[38] = '\0';
+#endif
+ return strGuid;
+}
+
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h
new file mode 100644
index 0000000000..11889df9ec
--- /dev/null
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.h
@@ -0,0 +1,375 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef IACCESSIBLE2_H
+#define IACCESSIBLE2_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include "qwindowsmsaaaccessible.h"
+#include "comutils.h"
+
+#include "Accessible2.h"
+#include "AccessibleAction.h"
+#include "AccessibleApplication.h"
+#include "AccessibleComponent.h"
+#include "AccessibleEditableText.h"
+#include "AccessibleHyperlink.h"
+#include "AccessibleHypertext.h"
+#include "AccessibleImage.h"
+#include "AccessibleRelation.h"
+#include "AccessibleTable.h"
+#include "AccessibleTable2.h"
+#include "AccessibleTableCell.h"
+#include "AccessibleText.h"
+#include "AccessibleValue.h"
+
+#include "AccessibleEventID.h"
+#include "AccessibleRole.h"
+#include "AccessibleStates.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsIA2Accessible : public QWindowsMsaaAccessible,
+ public IAccessibleAction,
+ public IAccessibleComponent,
+ /*public IAccessibleEditableText,*/
+ public IAccessibleTable2,
+ public IAccessibleTableCell,
+ public IAccessibleText,
+ public IAccessibleValue,
+ public IServiceProvider
+{
+public:
+ QWindowsIA2Accessible(QAccessibleInterface *a) : QWindowsMsaaAccessible(a) {}
+
+ /* IUnknown */
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ /* IAccessible2 */
+ HRESULT STDMETHODCALLTYPE get_nRelations(long *nRelations);
+ HRESULT STDMETHODCALLTYPE get_relation(long relationIndex, IAccessibleRelation **relation);
+ HRESULT STDMETHODCALLTYPE get_relations(long maxRelations, IAccessibleRelation **relations, long *nRelations);
+ HRESULT STDMETHODCALLTYPE role(long *role);
+ HRESULT STDMETHODCALLTYPE scrollTo(enum IA2ScrollType scrollType);
+ HRESULT STDMETHODCALLTYPE scrollToPoint(enum IA2CoordinateType coordinateType, long x, long y);
+ HRESULT STDMETHODCALLTYPE get_groupPosition(long *groupLevel, long *similarItemsInGroup, long *positionInGroup);
+ HRESULT STDMETHODCALLTYPE get_states(AccessibleStates *states);
+ HRESULT STDMETHODCALLTYPE get_extendedRole(BSTR *extendedRole);
+ HRESULT STDMETHODCALLTYPE get_localizedExtendedRole(BSTR *localizedExtendedRole);
+ HRESULT STDMETHODCALLTYPE get_nExtendedStates(long *nExtendedStates);
+ HRESULT STDMETHODCALLTYPE get_extendedStates(long maxExtendedStates, BSTR **extendedStates, long *nExtendedStates);
+ HRESULT STDMETHODCALLTYPE get_localizedExtendedStates(long maxLocalizedExtendedStates, BSTR **localizedExtendedStates, long *nLocalizedExtendedStates);
+ HRESULT STDMETHODCALLTYPE get_uniqueID(long *uniqueID);
+ HRESULT STDMETHODCALLTYPE get_windowHandle(HWND *windowHandle);
+ HRESULT STDMETHODCALLTYPE get_indexInParent(long *indexInParent);
+ HRESULT STDMETHODCALLTYPE get_locale(IA2Locale *locale);
+ HRESULT STDMETHODCALLTYPE get_attributes(BSTR *attributes);
+
+ /* IAccessibleAction */
+ HRESULT STDMETHODCALLTYPE nActions(long *nActions);
+ HRESULT STDMETHODCALLTYPE doAction(long actionIndex);
+ HRESULT STDMETHODCALLTYPE get_description(long actionIndex, BSTR *description);
+ HRESULT STDMETHODCALLTYPE get_keyBinding(long actionIndex, long nMaxBindings, BSTR **keyBindings, long *nBindings);
+ HRESULT STDMETHODCALLTYPE get_name(long actionIndex, BSTR *name);
+ HRESULT STDMETHODCALLTYPE get_localizedName(long actionIndex, BSTR *localizedName);
+
+ /* IAccessibleComponent */
+ HRESULT STDMETHODCALLTYPE get_locationInParent(long *x,long *y);
+ HRESULT STDMETHODCALLTYPE get_foreground(IA2Color *foreground);
+ HRESULT STDMETHODCALLTYPE get_background(IA2Color *background);
+
+ /* IAccessibleEditableText */
+ /*
+ HRESULT STDMETHODCALLTYPE copyText(long startOffset, long endOffset);
+ HRESULT STDMETHODCALLTYPE deleteText(long startOffset, long endOffset);
+ HRESULT STDMETHODCALLTYPE insertText(long offset, BSTR *text);
+ HRESULT STDMETHODCALLTYPE cutText(long startOffset, long endOffset);
+ HRESULT STDMETHODCALLTYPE pasteText(long offset);
+ HRESULT STDMETHODCALLTYPE replaceText(long startOffset, long endOffset, BSTR *text);
+ HRESULT STDMETHODCALLTYPE setAttributes(long startOffset, long endOffset, BSTR *attributes);
+ */
+
+ /* IAccessibleTable2 */
+ HRESULT STDMETHODCALLTYPE get_cellAt( long row, long column, IUnknown **cell);
+ HRESULT STDMETHODCALLTYPE get_caption( IUnknown **accessible);
+ HRESULT STDMETHODCALLTYPE get_columnDescription( long column, BSTR *description);
+ HRESULT STDMETHODCALLTYPE get_nColumns( long *columnCount);
+ HRESULT STDMETHODCALLTYPE get_nRows( long *rowCount);
+ HRESULT STDMETHODCALLTYPE get_nSelectedCells( long *cellCount);
+ HRESULT STDMETHODCALLTYPE get_nSelectedColumns( long *columnCount);
+ HRESULT STDMETHODCALLTYPE get_nSelectedRows( long *rowCount);
+ HRESULT STDMETHODCALLTYPE get_rowDescription( long row, BSTR *description);
+ HRESULT STDMETHODCALLTYPE get_selectedCells( IUnknown ***cells, long *nSelectedCells);
+ HRESULT STDMETHODCALLTYPE get_selectedColumns( long **selectedColumns, long *nColumns);
+ HRESULT STDMETHODCALLTYPE get_selectedRows( long **selectedRows, long *nRows);
+ HRESULT STDMETHODCALLTYPE get_summary( IUnknown **accessible);
+ HRESULT STDMETHODCALLTYPE get_isColumnSelected( long column, boolean *isSelected);
+ HRESULT STDMETHODCALLTYPE get_isRowSelected( long row, boolean *isSelected);
+ HRESULT STDMETHODCALLTYPE selectRow( long row);
+ HRESULT STDMETHODCALLTYPE selectColumn( long column);
+ HRESULT STDMETHODCALLTYPE unselectRow( long row);
+ HRESULT STDMETHODCALLTYPE unselectColumn( long column);
+ HRESULT STDMETHODCALLTYPE get_modelChange( IA2TableModelChange *modelChange);
+
+ /* IAccessibleTableCell */
+ HRESULT STDMETHODCALLTYPE get_columnExtent(long *nColumnsSpanned);
+ HRESULT STDMETHODCALLTYPE get_columnHeaderCells(IUnknown ***cellAccessibles, long *nColumnHeaderCells);
+ HRESULT STDMETHODCALLTYPE get_columnIndex(long *columnIndex);
+ HRESULT STDMETHODCALLTYPE get_rowExtent(long *nRowsSpanned);
+ HRESULT STDMETHODCALLTYPE get_rowHeaderCells(IUnknown ***cellAccessibles, long *nRowHeaderCells);
+ HRESULT STDMETHODCALLTYPE get_rowIndex(long *rowIndex);
+ HRESULT STDMETHODCALLTYPE get_isSelected( boolean *isSelected);
+ HRESULT STDMETHODCALLTYPE get_rowColumnExtents(long *row, long *column,
+ long *rowExtents, long *columnExtents,
+ boolean *isSelected);
+ HRESULT STDMETHODCALLTYPE get_table(IUnknown **table);
+
+
+ /* IAccessibleText */
+ HRESULT STDMETHODCALLTYPE addSelection(long startOffset, long endOffset);
+ HRESULT STDMETHODCALLTYPE get_attributes(long offset, long *startOffset,
+ long *endOffset, BSTR *textAttributes);
+ HRESULT STDMETHODCALLTYPE get_caretOffset(long *offset);
+ HRESULT STDMETHODCALLTYPE get_characterExtents(long offset, enum IA2CoordinateType coordType,
+ long *x, long *y,
+ long *width, long *height);
+ HRESULT STDMETHODCALLTYPE get_nSelections(long *nSelections);
+ HRESULT STDMETHODCALLTYPE get_offsetAtPoint(long x, long y, enum IA2CoordinateType coordType, long *offset);
+ HRESULT STDMETHODCALLTYPE get_selection(long selectionIndex, long *startOffset, long *endOffset);
+ HRESULT STDMETHODCALLTYPE get_text(long startOffset, long endOffset, BSTR *text);
+ HRESULT STDMETHODCALLTYPE get_textBeforeOffset(long offset, enum IA2TextBoundaryType boundaryType,
+ long *startOffset, long *endOffset, BSTR *text);
+ HRESULT STDMETHODCALLTYPE get_textAfterOffset(long offset, enum IA2TextBoundaryType boundaryType,
+ long *startOffset, long *endOffset, BSTR *text);
+ HRESULT STDMETHODCALLTYPE get_textAtOffset(long offset, enum IA2TextBoundaryType boundaryType,
+ long *startOffset, long *endOffset, BSTR *text);
+ HRESULT STDMETHODCALLTYPE removeSelection(long selectionIndex);
+ HRESULT STDMETHODCALLTYPE setCaretOffset(long offset);
+ HRESULT STDMETHODCALLTYPE setSelection(long selectionIndex, long startOffset, long endOffset);
+ HRESULT STDMETHODCALLTYPE get_nCharacters(long *nCharacters);
+ HRESULT STDMETHODCALLTYPE scrollSubstringTo(long startIndex, long endIndex, enum IA2ScrollType scrollType);
+ HRESULT STDMETHODCALLTYPE scrollSubstringToPoint(long startIndex, long endIndex,
+ enum IA2CoordinateType coordinateType, long x, long y);
+ HRESULT STDMETHODCALLTYPE get_newText(IA2TextSegment *newText);
+ HRESULT STDMETHODCALLTYPE get_oldText(IA2TextSegment *oldText);
+
+ /* IAccessibleValue */
+ HRESULT STDMETHODCALLTYPE get_currentValue(VARIANT *currentValue);
+ HRESULT STDMETHODCALLTYPE setCurrentValue(VARIANT value);
+ HRESULT STDMETHODCALLTYPE get_maximumValue(VARIANT *maximumValue);
+ HRESULT STDMETHODCALLTYPE get_minimumValue(VARIANT *minimumValue);
+
+ /* IServiceProvider */
+ HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppv);
+
+ /* private helper functions */
+private:
+ inline QAccessibleTextInterface *textInterface() const {
+ return accessible->isValid() ? accessible->textInterface() : static_cast<QAccessibleTextInterface *>(0);
+ }
+
+ inline QAccessibleActionInterface *actionInterface() const {
+ return accessible->actionInterface();
+ }
+
+ inline QAccessibleValueInterface *valueInterface() const {
+ return accessible->valueInterface();
+ }
+
+ inline QAccessibleTableInterface *tableInterface() const {
+ return accessible->tableInterface();
+ }
+
+ inline QAccessibleTableCellInterface *tableCellInterface() const {
+ return accessible->tableCellInterface();
+ }
+
+ HRESULT getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations = 0);
+ HRESULT wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount);
+ uint uniqueID() const;
+ QByteArray IIDToString(REFIID id);
+
+private:
+ ULONG ref;
+
+};
+
+/**************************************************************\
+ * AccessibleApplication *
+ **************************************************************/
+class AccessibleApplication : public IAccessibleApplication
+{
+public:
+ AccessibleApplication() : m_ref(1)
+ {
+
+ }
+
+ virtual ~AccessibleApplication() {}
+
+ /* IUnknown */
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
+ ULONG STDMETHODCALLTYPE AddRef();
+ ULONG STDMETHODCALLTYPE Release();
+
+ /* IAccessibleApplication */
+ HRESULT STDMETHODCALLTYPE get_appName(/* [retval][out] */ BSTR *name);
+ HRESULT STDMETHODCALLTYPE get_appVersion(/* [retval][out] */ BSTR *version);
+ HRESULT STDMETHODCALLTYPE get_toolkitName(/* [retval][out] */ BSTR *name);
+ HRESULT STDMETHODCALLTYPE get_toolkitVersion(/* [retval][out] */ BSTR *version);
+private:
+ ULONG m_ref;
+};
+
+
+
+/**************************************************************\
+ * IAccessibleRelation *
+ **************************************************************/
+struct AccessibleRelation : public IAccessibleRelation
+{
+ AccessibleRelation(const QList<QAccessibleInterface *> &targets,
+ QAccessible::Relation relation)
+ : m_targets(targets), m_relation(relation), m_ref(1)
+ {
+ Q_ASSERT(m_targets.count());
+ }
+
+
+ /* IUnknown */
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface)
+ {
+ *iface = 0;
+ if (id == IID_IUnknown)
+ *iface = (IUnknown*)this;
+
+ if (*iface) {
+ AddRef();
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef()
+ {
+ return ++m_ref;
+ }
+
+ ULONG STDMETHODCALLTYPE Release()
+ {
+ if (!--m_ref) {
+ delete this;
+ return 0;
+ }
+ return m_ref;
+ }
+
+ /* IAccessibleRelation */
+ HRESULT STDMETHODCALLTYPE get_relationType(
+ /* [retval][out] */ BSTR *relationType)
+ {
+ *relationType = relationToBSTR(m_relation);
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE get_localizedRelationType(
+ /* [retval][out] */ BSTR *localizedRelationType)
+ {
+ // Who ever needs this???
+ *localizedRelationType = relationToBSTR(m_relation);
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE get_nTargets(
+ /* [retval][out] */ long *nTargets)
+ {
+ // ### always one target
+ *nTargets = m_targets.count();
+ return S_OK;
+ }
+
+ HRESULT STDMETHODCALLTYPE get_target(long targetIndex, IUnknown **target);
+
+
+ /*!
+ \internal
+ Client allocates and deallocates \a targets array
+ (see "Special Consideration when using Arrays", in Accessible2.idl)
+ */
+ HRESULT STDMETHODCALLTYPE get_targets(
+ /* [in] */ long maxTargets, // Hmmm, ignore ???
+ /* [length_is][size_is][out] */ IUnknown **targets,
+ /* [retval][out] */ long *nTargets);
+
+private:
+ static BSTR relationToBSTR(QAccessible::Relation relation)
+ {
+ wchar_t *constRelationString = 0;
+ switch (relation) {
+ case QAccessible::Controlled:
+ constRelationString = IA2_RELATION_CONTROLLED_BY;
+ break;
+ }
+
+ if (constRelationString) {
+ BSTR bstrVal;
+ const UINT wlen = (UINT)wcslen(constRelationString);
+ bstrVal = ::SysAllocStringLen(constRelationString, wlen);
+ return bstrVal;
+ }
+ return 0;
+ }
+
+
+ QList<QAccessibleInterface *> m_targets;
+ QAccessible::Relation m_relation;
+ ULONG m_ref;
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ACCESSIBILITY
+
+#endif // IACCESSIBLE2_H
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
new file mode 100644
index 0000000000..f409730600
--- /dev/null
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
@@ -0,0 +1,301 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+
+#include <private/qsystemlibrary_p.h>
+
+#include <QtCore/qlocale.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qsettings.h>
+#include <QtGui/qaccessible.h>
+#include <QtGui/qaccessible2.h>
+#include <QtGui/qplatformnativeinterface_qpa.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qguiapplication.h>
+#include <QtWidgets/qapplication.h>
+#include <QtWidgets/qgraphicsitem.h>
+#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qmessagebox.h>
+
+#include "qwindowsaccessibility.h"
+#include "iaccessible2.h"
+#include "comutils.h"
+
+#include <oleacc.h>
+
+//#include <uiautomationcoreapi.h>
+#ifndef UiaRootObjectId
+#define UiaRootObjectId -25
+#endif
+
+#include <winuser.h>
+#if !defined(WINABLEAPI)
+# if defined(Q_OS_WINCE)
+# include <bldver.h>
+# endif
+# include <winable.h>
+#endif
+
+#include <oleacc.h>
+#include <servprov.h>
+#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
+#include <comdef.h>
+#endif
+
+#ifdef Q_OS_WINCE
+#include "../qguifunctions_wince.h"
+#endif
+
+#include "../qtwindows_additional.h"
+
+
+// This stuff is used for widgets/items with no window handle:
+typedef QMap<int, QPair<QObject*,int> > NotifyMap;
+Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents)
+
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ \!internal
+ \class QWindowsAccessibility
+
+ Implements QPlatformAccessibility
+
+*/
+QWindowsAccessibility::QWindowsAccessibility()
+{
+}
+
+void QWindowsAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &event)
+{
+ QString soundName;
+ switch (event.type()) {
+ case QAccessible::PopupMenuStart:
+ soundName = QLatin1String("MenuPopup");
+ break;
+
+ case QAccessible::MenuCommand:
+ soundName = QLatin1String("MenuCommand");
+ break;
+
+ case QAccessible::Alert:
+ {
+ /* ### FIXME
+#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.isEmpty()) {
+#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);
+ }
+ }
+
+ typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG);
+
+#if defined(Q_OS_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 and that has a WId
+ QAccessibleInterface *iface = event.accessibleInterface();
+ QWindow *window = iface ? window_helper(iface) : 0;
+ delete iface;
+
+ if (!window) {
+ window = QGuiApplication::activeWindow();
+ if (!window)
+ return;
+ }
+
+ QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
+ HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", window);
+
+ static int eventNum = 0;
+ if (event.type() != QAccessible::MenuCommand) { // MenuCommand is faked
+ // See comment "SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE"
+ eventNum %= 50; //[0..49]
+ int eventId = - (eventNum - 1);
+
+ qAccessibleRecentSentEvents()->insert(eventId, qMakePair(event.object(), event.child()));
+ ptrNotifyWinEvent(event.type(), hWnd, OBJID_CLIENT, eventId );
+
+ ++eventNum;
+ }
+#endif // Q_OS_WINCE
+}
+
+
+/*!
+ \internal
+ helper to wrap a QAccessibleInterface inside a IAccessible*
+*/
+IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc)
+{
+ if (!acc)
+ return 0;
+ QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc);
+ IAccessible *iacc = 0;
+ wacc->QueryInterface(IID_IAccessible, (void**)&iacc);
+ return iacc;
+}
+
+/*!
+ \internal
+*/
+QPair<QObject*, int> QWindowsAccessibility::getCachedObject(int entryId)
+{
+ return qAccessibleRecentSentEvents()->value(entryId);
+}
+
+/*
+void QWindowsAccessibility::setRootObject(QObject *o)
+{
+
+}
+
+void QWindowsAccessibility::initialize()
+{
+
+}
+
+void QWindowsAccessibility::cleanup()
+{
+
+}
+
+*/
+
+bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
+{
+ if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) {
+ /* For UI Automation */
+ } else if ((DWORD)lParam == OBJID_CLIENT) {
+#if 1
+ // Ignoring all requests while starting up
+ // ### Maybe QPA takes care of this???
+ if (QApplication::startingUp() || QApplication::closingDown())
+ return false;
+#endif
+
+ typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN);
+ static PtrLresultFromObject ptrLresultFromObject = 0;
+ static bool oleaccChecked = false;
+
+ if (!oleaccChecked) {
+ oleaccChecked = true;
+#if !defined(Q_OS_WINCE)
+ ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject");
+#endif
+ }
+
+ if (ptrLresultFromObject) {
+ QWindow *window = QWindowsContext::instance()->findWindow(hwnd);
+ if (window) {
+ QAccessibleInterface *acc = window->accessibleRoot();
+ if (acc) {
+ if (IAccessible *iface = wrap(acc)) {
+ *lResult = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2
+ if (*lResult) {
+ iface->Release(); // the client will release the object again, and then it will destroy itself
+ }
+ return true;
+ } else {
+ delete acc;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.h b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
index 9294f23565..3b7069570b 100644
--- a/src/plugins/platforms/windows/qwindowsaccessibility.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.h
@@ -42,9 +42,12 @@
#ifndef QWINDOWSACCESSIBILITY_H
#define QWINDOWSACCESSIBILITY_H
-#include "qtwindowsglobal.h"
+#include "../qtwindowsglobal.h"
+#include "../qwindowscontext.h"
#include <QtGui/QPlatformAccessibility>
+#include <oleacc.h>
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -59,6 +62,9 @@ public:
virtual void initialize();
virtual void cleanup();
*/
+ static IAccessible *wrap(QAccessibleInterface *acc);
+
+ static QPair<QObject*, int> getCachedObject(int entryId);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
index 134b1c81ce..ca3ce0a614 100644
--- a/src/plugins/platforms/windows/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
@@ -42,104 +42,44 @@
#include <QtCore/QtConfig>
#ifndef QT_NO_ACCESSIBILITY
-
+#include "qwindowsmsaaaccessible.h"
#include "qwindowsaccessibility.h"
-#include "qwindowscontext.h"
-
-#include <private/qsystemlibrary_p.h>
+#include <oleacc.h>
+#include <servprov.h>
+#include <winuser.h>
+#include "comutils.h"
+#include <QtCore/qdebug.h>
#include <QtCore/qmap.h>
-#include <QtCore/qsettings.h>
-#include <QtCore/qsharedpointer.h>
#include <QtCore/qpair.h>
-#include <QtWidgets/qapplication.h>
-#include <QtWidgets/qmessagebox.h>
-#include <QtWidgets/qgraphicsitem.h>
-#include <QtWidgets/qgraphicsview.h>
+#include <QtCore/qsettings.h>
#include <QtGui/qaccessible.h>
+#include <QtGui/qaccessible2.h>
+#include <QtGui/qguiapplication.h>
#include <QtGui/qplatformnativeinterface_qpa.h>
#include <QtGui/qwindow.h>
-#include <QtGui/qaccessible2.h>
-#include <oleacc.h>
+#include <QtWidgets/qapplication.h>
+#include <QtWidgets/qgraphicsitem.h>
+#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qmessagebox.h>
//#include <uiautomationcoreapi.h>
#ifndef UiaRootObjectId
#define UiaRootObjectId -25
#endif
-#include <winuser.h>
-#if !defined(WINABLEAPI)
-# if defined(Q_OS_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_OS_WINCE
-#include "qguifunctions_wince.h"
-#endif
-
-#include "qtwindows_additional.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_DEBUG
-QT_BEGIN_INCLUDE_NAMESPACE
-# include <qdebug.h>
-QT_END_INCLUDE_NAMESPACE
-static inline bool debug_accessibility()
-{
- static signed int debugging = -1;
- if (debugging == -1)
- debugging = qgetenv("QT_DEBUG_ACCESSIBILITY").toInt();
- return !!debugging;
-}
-# define accessibleDebug !debug_accessibility() ? (void)0 : qDebug
-#else
-# define accessibleDebug()
+#include "../qguifunctions_wince.h"
#endif
-//#define DEBUG_SHOW_ATCLIENT_COMMANDS
-#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS)
-void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface)
-{
- QString str;
- QDebug dbg(&str);
- dbg << iface << QLatin1String(funcName);
- accessibleDebug("%s", qPrintable(str));
-}
-# define accessibleDebugClientCalls(iface) accessibleDebugClientCalls_helper(Q_FUNC_INFO, iface)
-#else
-# define accessibleDebugClientCalls(iface)
-#endif
-
-
-typedef QSharedPointer<QAccessibleInterface> QAIPointer;
-
-static bool compareAccessible(QAccessibleInterface *one, QAccessibleInterface *other)
-{
- if (one == other) return true;
- if (!one || !other) return false;
-
- if (one->object() && other->object() && (one->object() == other->object()))
- return true;
- QAIPointer onePar(one->parent());
- QAIPointer otherPar(other->parent());
+#include "../qtwindows_additional.h"
- if (compareAccessible(onePar.data(), otherPar.data()))
- return onePar->indexOfChild(one) == otherPar->indexOfChild(other);
- return false;
-}
-// This stuff is used for widgets/items with no window handle:
-typedef QMap<int, QPair<QObject*,int> > NotifyMap;
-Q_GLOBAL_STATIC(NotifyMap, qAccessibleRecentSentEvents)
-static int eventNum = 0;
+QT_BEGIN_NAMESPACE
class QWindowsEnumerate : public IEnumVARIANT
{
@@ -249,140 +189,60 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt)
return S_OK;
}
-/*
-*/
-class QWindowsAccessible : public IAccessible, IOleWindow
-{
-public:
- QWindowsAccessible(QAccessibleInterface *a)
- : ref(0), accessible(a)
- {
- }
-
- virtual ~QWindowsAccessible()
- {
- delete accessible;
- }
-
- /* IUnknown */
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
- /* IDispatch */
- 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 *);
-
- /* IAccessible */
- 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);
-
- /* IOleWindow */
- HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
- HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
-
-private:
- ULONG ref;
- QAccessibleInterface *accessible;
-
- QAIPointer childPointer(VARIANT varID)
- {
- return QAIPointer(accessible->child(varID.lVal - 1));
- }
-};
-
-static inline BSTR QStringToBSTR(const QString &str)
+static bool compareAccessible(QAccessibleInterface *one, QAccessibleInterface *other)
{
- BSTR bstrVal;
-
- int wlen = str.length()+1;
- bstrVal = SysAllocStringByteLen(0, wlen*2);
- memcpy(bstrVal, str.unicode(), sizeof(QChar)*(wlen));
- bstrVal[wlen] = 0;
-
- return bstrVal;
-}
-
-/*
-*/
+ if (one == other) return true;
+ if (!one || !other) return false;
-/*
- 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;
+ if (one->object() && other->object() && (one->object() == other->object()))
+ return true;
+ QAIPointer onePar(one->parent());
+ QAIPointer otherPar(other->parent());
- AddRef();
- return S_OK;
+ if (compareAccessible(onePar.data(), otherPar.data()))
+ return onePar->indexOfChild(one) == otherPar->indexOfChild(other);
+ return false;
}
-ULONG STDMETHODCALLTYPE QWindowsAccessible::AddRef()
+#ifndef QT_NO_DEBUG
+bool debug_accessibility()
{
- return ++ref;
+ static int debugging = -1;
+ if (debugging == -1)
+ debugging = qgetenv("QT_DEBUG_ACCESSIBILITY").toInt();
+ return !!debugging;
}
+#endif
-ULONG STDMETHODCALLTYPE QWindowsAccessible::Release()
+#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS)
+void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface)
{
- if (!--ref) {
- delete this;
- return 0;
- }
- return ref;
+ QString str;
+ QDebug dbg(&str);
+ dbg << iface << QLatin1String(funcName);
+ accessibleDebug("%s", qPrintable(str));
}
+#endif
/*
IDispatch
*/
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetTypeInfoCount(unsigned int * pctinfo)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::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)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::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)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetIDsOfNames(const _GUID &, wchar_t **rgszNames, unsigned int, unsigned long, long *rgdispid)
{
#if !defined(Q_CC_BOR) && !defined(Q_CC_GNU)
// PROPERTIES: Hierarchical
@@ -440,7 +300,13 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetIDsOfNames(const _GUID &, wchar
#endif
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::Invoke(long dispIdMember, const _GUID &, unsigned long, unsigned short wFlags, tagDISPPARAMS *pDispParams, tagVARIANT *pVarResult, tagEXCEPINFO *, unsigned int *)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::Invoke(long dispIdMember,
+ const _GUID &,
+ unsigned long,
+ unsigned short wFlags,
+ tagDISPPARAMS *pDispParams,
+ tagVARIANT *pVarResult,
+ tagEXCEPINFO *, unsigned int *)
{
HRESULT hr = DISP_E_MEMBERNOTFOUND;
@@ -621,9 +487,8 @@ IAccessible::accHitTest documents the value returned in pvarID like this:
| | | interface pointer |
+--------------------------------------------------------+-------------+-------------------------+
*/
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID)
{
-
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
@@ -637,9 +502,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop,
return S_OK;
}
} else {
- QWindowsAccessible* wacc = new QWindowsAccessible(child);
- IDispatch *iface = 0;
- wacc->QueryInterface(IID_IDispatch, (void**)&iface);
+ IAccessible *iface = QWindowsAccessibility::wrap(child);
if (iface) {
(*pvarID).vt = VT_DISPATCH;
(*pvarID).pdispVal = iface;
@@ -662,7 +525,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop,
can be ignored. All stuff prefixed with "moz" are information from that page.
*/
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -686,7 +549,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *py
}
// moz: [important, but no need to implement up/down/left/right]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -809,16 +672,14 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT v
(*pvarEnd).vt = VT_EMPTY;
return S_FALSE;
}
- QWindowsAccessible* wacc = new QWindowsAccessible(acc);
- IDispatch *iface = 0;
- wacc->QueryInterface(IID_IDispatch, (void**)&iface);
- if (iface) {
+ if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) {
(*pvarEnd).vt = VT_DISPATCH;
(*pvarEnd).pdispVal = iface;
return S_OK;
} else {
- delete wacc;
+ if (acc != accessible)
+ delete acc;
}
(*pvarEnd).vt = VT_EMPTY;
@@ -826,13 +687,13 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT v
}
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
return E_FAIL;
- if (varChildID.vt == VT_EMPTY)
+ if (varChildID.vt != VT_I4)
return E_INVALIDARG;
@@ -841,7 +702,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I
if (childIndex < 0) {
const int entry = childIndex;
- QPair<QObject*, int> ref = qAccessibleRecentSentEvents()->value(entry);
+ QPair<QObject*, int> ref = QWindowsAccessibility::getCachedObject(entry);
if (ref.first) {
acc = QAccessible::queryAccessibleInterface(ref.first);
if (acc && ref.second >= 0) {
@@ -851,6 +712,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I
return E_INVALIDARG;
acc = res;
}
+ } else {
+ qWarning("get_accChild got a negative varChildID, but did not find it in cache");
}
} else {
if (childIndex) {
@@ -868,17 +731,15 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, I
}
if (acc) {
- QWindowsAccessible* wacc = new QWindowsAccessible(acc);
- wacc->QueryInterface(IID_IDispatch, (void**)ppdispChild);
+ *ppdispChild = QWindowsAccessibility::wrap(acc);
return S_OK;
}
- *ppdispChild = 0;
- return S_FALSE;
+ return E_FAIL;
}
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChildCount(long* pcountChildren)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -889,7 +750,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChil
}
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispParent)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accParent(IDispatch** ppdispParent)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -897,11 +758,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispPa
QAccessibleInterface *acc = accessible->parent();
if (acc) {
- QWindowsAccessible* wacc = new QWindowsAccessible(acc);
- wacc->QueryInterface(IID_IDispatch, (void**)ppdispParent);
-
- if (*ppdispParent)
+ if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) {
+ *ppdispParent = iface;
return S_OK;
+ } else {
+ delete acc;
+ }
}
*ppdispParent = 0;
@@ -911,7 +773,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accParent(IDispatch** ppdispPa
/*
Properties and methods
*/
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accDoDefaultAction(VARIANT varID)
{
Q_UNUSED(varID);
accessibleDebugClientCalls(accessible);
@@ -928,7 +790,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID)
return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction)
{
Q_UNUSED(varID);
accessibleDebugClientCalls(accessible);
@@ -944,7 +806,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID
return *pszDefaultAction ? S_OK : S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -969,7 +831,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID,
return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -993,12 +855,12 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *p
return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
{
return DISP_E_MEMBERNOTFOUND;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut)
{
Q_UNUSED(varID);
accessibleDebugClientCalls(accessible);
@@ -1029,7 +891,7 @@ static QAccessibleInterface *relatedInterface(QAccessibleInterface *iface, QAcce
}
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* pszName)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accName(VARIANT varID, BSTR* pszName)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -1065,14 +927,14 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* p
return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accName(VARIANT, BSTR)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accName(VARIANT, BSTR)
{
accessibleDebugClientCalls(accessible);
return DISP_E_MEMBERNOTFOUND;
}
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -1100,7 +962,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT
}
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accState(VARIANT varID, VARIANT *pvarState)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -1176,11 +1038,15 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIAN
}
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* pszValue)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BSTR* pszValue)
{
accessibleDebugClientCalls(accessible);
- if (!accessible->isValid() || varID.lVal)
+ if (varID.vt != VT_I4)
+ return E_INVALIDARG;
+
+ if (!accessible->isValid() || varID.lVal) {
return E_FAIL;
+ }
QString value;
if (accessible->valueInterface()) {
@@ -1194,17 +1060,18 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR*
}
*pszValue = 0;
+ accessibleDebug("return S_FALSE");
return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::put_accValue(VARIANT, BSTR)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR)
{
accessibleDebugClientCalls(accessible);
return DISP_E_MEMBERNOTFOUND;
}
// moz: [important]
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIANT varID)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accSelect(long flagsSelect, VARIANT varID)
{
Q_UNUSED(flagsSelect);
Q_UNUSED(varID);
@@ -1250,7 +1117,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIAN
+-------------+------------------------------------------------------------------------------+
moz: [important]
*/
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accFocus(VARIANT *pvarID)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -1263,12 +1130,11 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID)
delete acc;
return S_OK;
} else {
- QWindowsAccessible* wacc = new QWindowsAccessible(acc);
- IDispatch *iface = 0;
- wacc->QueryInterface(IID_IDispatch, (void**)&iface);
- (*pvarID).vt = VT_DISPATCH;
- (*pvarID).pdispVal = iface;
- return S_OK;
+ if (IAccessible *iface = QWindowsAccessibility::wrap(acc)) {
+ (*pvarID).vt = VT_DISPATCH;
+ (*pvarID).pdispVal = iface;
+ return S_OK;
+ }
}
delete acc;
}
@@ -1276,7 +1142,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID)
return S_FALSE;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accSelection(VARIANT *pvarChildren)
{
accessibleDebugClientCalls(accessible);
if (!accessible->isValid())
@@ -1314,7 +1180,7 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChil
return S_OK;
}
-static QWindow *window_helper(const QAccessibleInterface *iface)
+QWindow *window_helper(const QAccessibleInterface *iface)
{
QWindow *window = iface->window();
if (!window) {
@@ -1329,9 +1195,15 @@ static QWindow *window_helper(const QAccessibleInterface *iface)
return window;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetWindow(HWND *phwnd)
+/**************************************************************\
+ * IOleWindow *
+ **************************************************************/
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::GetWindow(HWND *phwnd)
{
*phwnd = 0;
+ accessibleDebugClientCalls(accessible);
+ if (!accessible->isValid())
+ return E_FAIL;
if (!accessible->isValid())
return E_UNEXPECTED;
@@ -1342,184 +1214,15 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetWindow(HWND *phwnd)
QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
Q_ASSERT(platform);
*phwnd = (HWND)platform->nativeResourceForWindow("handle", window);
+ accessibleDebug("QWindowsAccessible::GetWindow(): %p", *phwnd);
return S_OK;
}
-HRESULT STDMETHODCALLTYPE QWindowsAccessible::ContextSensitiveHelp(BOOL)
+HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::ContextSensitiveHelp(BOOL)
{
return S_OK;
}
-
-QWindowsAccessibility::QWindowsAccessibility()
-{
-}
-
-
-void QWindowsAccessibility::notifyAccessibilityUpdate(const QAccessibleEvent &event)
-{
- QString soundName;
- switch (event.type()) {
- case QAccessible::PopupMenuStart:
- soundName = QLatin1String("MenuPopup");
- break;
-
- case QAccessible::MenuCommand:
- soundName = QLatin1String("MenuCommand");
- break;
-
- case QAccessible::Alert:
- {
- /* ### FIXME
-#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.isEmpty()) {
-#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);
- }
- }
-
- typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG);
-
-#if defined(Q_OS_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 and that has a WId
- QAccessibleInterface *iface = event.accessibleInterface();
- QWindow *window = iface ? window_helper(iface) : 0;
- delete iface;
-
- if (!window) {
- window = QGuiApplication::activeWindow();
- if (!window)
- return;
- }
-
- QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
- HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", window);
-
- if (event.type() != QAccessible::MenuCommand) { // MenuCommand is faked
- // See comment "SENDING EVENTS TO OBJECTS WITH NO WINDOW HANDLE"
- eventNum %= 50; //[0..49]
- int eventId = - eventNum - 1;
-
- qAccessibleRecentSentEvents()->insert(eventId, qMakePair(event.object(), event.child()));
- ptrNotifyWinEvent(event.type(), hWnd, OBJID_CLIENT, eventId );
-
- ++eventNum;
- }
-#endif // Q_OS_WINCE
-}
-
-/*
-void QWindowsAccessibility::setRootObject(QObject *o)
-{
-
-}
-
-void QWindowsAccessibility::initialize()
-{
-
-}
-
-void QWindowsAccessibility::cleanup()
-{
-
-}
-
-*/
-
-bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult)
-{
- if (static_cast<long>(lParam) == static_cast<long>(UiaRootObjectId)) {
- /* For UI Automation
- */
- } else if ((DWORD)lParam == OBJID_CLIENT) {
-#if 1
- // Ignoring all requests while starting up
- // ### Maybe QPA takes care of this???
- if (QApplication::startingUp() || QApplication::closingDown())
- return false;
-#endif
-
- typedef LRESULT (WINAPI *PtrLresultFromObject)(REFIID, WPARAM, LPUNKNOWN);
- static PtrLresultFromObject ptrLresultFromObject = 0;
- static bool oleaccChecked = false;
-
- if (!oleaccChecked) {
- oleaccChecked = true;
-#if !defined(Q_OS_WINCE)
- ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject");
-#endif
- }
-
- if (ptrLresultFromObject) {
- QWindow *window = QWindowsContext::instance()->findWindow(hwnd);
- if (window) {
- QAccessibleInterface *acc = window->accessibleRoot();
- if (acc) {
- QWindowsAccessible *winacc = new QWindowsAccessible(acc);
- IAccessible *iface;
- HRESULT hr = winacc->QueryInterface(IID_IAccessible, (void**)&iface);
- if (SUCCEEDED(hr)) {
- *lResult = ptrLresultFromObject(IID_IAccessible, wParam, iface); // ref == 2
- if (*lResult) {
- iface->Release(); // the client will release the object again, and then it will destroy itself
- }
- return true;
- }
- }
- }
- }
- }
- return false;
-}
-
QT_END_NAMESPACE
#endif //QT_NO_ACCESSIBILITY
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
new file mode 100644
index 0000000000..609f57b398
--- /dev/null
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QWINDOWSMSAAACCESSIBLE_H
+#define QWINDOWSMSAAACCESSIBLE_H
+
+#include <QtCore/QtConfig>
+#ifndef QT_NO_ACCESSIBILITY
+
+#include <oleacc.h>
+#include "Accessible2.h"
+#include <QtCore/qsharedpointer.h>
+#include <QtGui/qaccessible.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_DEBUG
+bool debug_accessibility();
+# define accessibleDebug !debug_accessibility() ? (void)0 : qDebug
+#else
+# define accessibleDebug()
+#endif
+
+#define DEBUG_SHOW_ATCLIENT_COMMANDS
+#if defined(DEBUG_SHOW_ATCLIENT_COMMANDS)
+void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleInterface *iface);
+# define accessibleDebugClientCalls(iface) accessibleDebugClientCalls_helper(Q_FUNC_INFO, iface)
+#else
+# define accessibleDebugClientCalls(iface)
+#endif
+
+typedef QSharedPointer<QAccessibleInterface> QAIPointer;
+
+QWindow *window_helper(const QAccessibleInterface *iface);
+
+/**************************************************************\
+ * QWindowsAccessible *
+ **************************************************************/
+class QWindowsMsaaAccessible : public IAccessible2, public IOleWindow
+{
+public:
+ QWindowsMsaaAccessible(QAccessibleInterface *a)
+ : accessible(a)
+ {
+ }
+
+ virtual ~QWindowsMsaaAccessible()
+ {
+ delete accessible;
+ }
+
+
+ /* IDispatch */
+ 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 *);
+
+ /* IAccessible */
+ 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);
+
+ /* IOleWindow */
+ HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
+ HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
+
+protected:
+ QAccessibleInterface *accessible;
+
+ QAIPointer childPointer(VARIANT varID)
+ {
+ return QAIPointer(accessible->child(varID.lVal - 1));
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ACCESSIBILITY
+
+#endif // QWINDOWSMSAAACCESSIBLE_H
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 2706e02cf8..e8050d5027 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -47,7 +47,7 @@
#include "qtwindowsglobal.h"
#include "qwindowsmime.h"
#include "qwindowsinputcontext.h"
-#include "qwindowsaccessibility.h"
+#include "accessible/qwindowsaccessibility.h"
#include "qwindowsscreen.h"
#include "qwindowstheme.h"
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 3c2ece58d0..7510cded50 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -55,8 +55,8 @@
#include "qwindowsclipboard.h"
#include "qwindowsdrag.h"
#include "qwindowsinputcontext.h"
-#include "qwindowsaccessibility.h"
#include "qwindowskeymapper.h"
+#include "accessible/qwindowsaccessibility.h"
#include <QtGui/QPlatformNativeInterface>
#include <QtGui/QWindowSystemInterface>
diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro
index bb41fe87fc..87bc7245c4 100644
--- a/src/plugins/platforms/windows/windows.pro
+++ b/src/plugins/platforms/windows/windows.pro
@@ -45,7 +45,6 @@ SOURCES += \
qwindowsdrag.cpp \
qwindowscursor.cpp \
qwindowsinputcontext.cpp \
- qwindowsaccessibility.cpp \
qwindowstheme.cpp \
qwindowsdialoghelpers.cpp \
qwindowsservices.cpp
@@ -73,7 +72,6 @@ HEADERS += \
qwindowscursor.h \
array.h \
qwindowsinputcontext.h \
- qwindowsaccessibility.h \
qwindowstheme.h \
qwindowsdialoghelpers.h \
qwindowsservices.h
@@ -151,5 +149,6 @@ contains(QT_CONFIG, freetype) {
OTHER_FILES += windows.json
+include(accessible/accessible.pri)
target.path += $$[QT_INSTALL_PLUGINS]/platforms
INSTALLS += target