Fix IAccessible2 for Windows, enable MSAA/IAccessible for MinGW.

Commit 5e9089135b had some problems:
* It left out the cast to IServiceProvider in the refactoring of
   QueryInterface. This broke IAccessible2.
* It also failed to enable the codepath for MinGW inside wrap(), which
  effectively caused MSAA for MinGW to be disabled.

It also adds an autotest to the bridge (finally). It is simple,
but it should help avoiding committing stuff that completely breaks
the bridge.

Change-Id: I459d89c3bdb93e54ddea85872b50fc1dba0fe4a0
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
bb10
Jan-Arve Saether 2012-03-27 07:09:22 +02:00 committed by Qt by Nokia
parent 6540a42ee0
commit 8d28f263aa
4 changed files with 116 additions and 5 deletions

View File

@ -169,7 +169,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI
{
HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface);
if (!SUCCEEDED(hr)) {
if (id == IID_IAccessible2) {
if (id == IID_IServiceProvider) {
*iface = (IServiceProvider*)this;
} else if (id == IID_IAccessible2) {
*iface = (IAccessible2*)this;
} else if (id == IID_IAccessibleAction) {
if (accessible->actionInterface())

View File

@ -232,9 +232,6 @@ QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface)
*/
IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc)
{
#ifdef Q_CC_MINGW
return 0;
#else
if (!acc)
return 0;
#ifdef Q_CC_MINGW
@ -245,7 +242,6 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc)
IAccessible *iacc = 0;
wacc->QueryInterface(IID_IAccessible, (void**)&iacc);
return iacc;
#endif
}
/*!

View File

@ -13,3 +13,8 @@ wince*: {
}
mac: CONFIG += insignificant_test # QTBUG-22812
win32 {
!*g++: include(../../../../src/3rdparty/iaccessible2/iaccessible2.pri)
LIBS += -loleacc -loleaut32 -lole32
}

View File

@ -40,6 +40,18 @@
****************************************************************************/
#include <QtCore/qglobal.h>
#ifdef Q_OS_WIN
# include <QtCore/qt_windows.h>
# include <oleacc.h>
# include <servprov.h>
# include <winuser.h>
# ifndef Q_CC_MINGW
# include <Accessible2.h>
# include <AccessibleAction.h>
# include <AccessibleComponent.h>
# endif
#endif
#include <QtTest/QtTest>
#include <QtGui>
#include <QtWidgets>
@ -270,6 +282,7 @@ private slots:
void accessibleName();
void labelTest();
void accelerators();
void bridgeTest();
protected slots:
void onClicked();
@ -2942,5 +2955,100 @@ void tst_QAccessibility::accelerators()
QTestAccessibility::clearEvents();
}
void tst_QAccessibility::bridgeTest()
{
// For now this is a simple test to see if the bridge is working at all.
// Ideally it should be extended to test all aspects of the bridge.
#ifdef Q_OS_WIN
// First, test MSAA part of bridge
QWidget *window = new QWidget;
QVBoxLayout *lay = new QVBoxLayout(window);
QPushButton *button = new QPushButton(tr("Push me"), window);
QLineEdit *le = new QLineEdit(window);
lay->addWidget(button);
lay->addWidget(le);
window->show();
QTest::qWaitForWindowShown(window);
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(button);
QPoint buttonPos = button->mapToGlobal(QPoint(0,0));
QRect buttonRect = iface->rect();
QCOMPARE(buttonRect.topLeft(), buttonPos);
// All set, now test the bridge.
POINT pt;
pt.x = buttonRect.center().x();
pt.y = buttonRect.center().y();
IAccessible *iacc;
VARIANT varChild;
HRESULT hr = ::AccessibleObjectFromPoint(pt, &iacc, &varChild);
QVERIFY(SUCCEEDED(hr));
VARIANT varSELF;
varSELF.vt = VT_I4;
varSELF.lVal = 0;
// **** Test get_accRole ****
VARIANT varRole;
hr = iacc->get_accRole(varSELF, &varRole);
QVERIFY(SUCCEEDED(hr));
QCOMPARE(varRole.vt, (VARTYPE)VT_I4);
QCOMPARE(varRole.lVal, (LONG)ROLE_SYSTEM_PUSHBUTTON);
// **** Test accLocation ****
long x, y, w, h;
hr = iacc->accLocation(&x, &y, &w, &h, varSELF);
QCOMPARE(buttonRect, QRect(x, y, w, h));
#ifndef Q_CC_MINGW
// Test IAccessible2 part of bridge
IServiceProvider *pService = 0;
hr = iacc->QueryInterface(IID_IServiceProvider, (void **)&pService);
if (SUCCEEDED(hr)) {
IAccessible2 *pIA2 = 0;
hr = pService->QueryService(IID_IAccessible, IID_IAccessible2, (void**)&pIA2);
if (SUCCEEDED(hr) && pIA2) {
// The control supports IAccessible2.
// pIA2 is the reference to the accessible object's IAccessible2 interface.
/***** Test IAccessibleComponent *****/
IAccessibleComponent *ia2Component = 0;
hr = pIA2->QueryInterface(IID_IAccessibleComponent, (void**)&ia2Component);
QVERIFY(SUCCEEDED(hr));
long x, y;
hr = ia2Component->get_locationInParent(&x, &y);
QVERIFY(SUCCEEDED(hr));
QCOMPARE(button->pos(), QPoint(x, y));
ia2Component->Release();
/***** Test IAccessibleAction *****/
IAccessibleAction *ia2Action = 0;
hr = pIA2->QueryInterface(IID_IAccessibleAction, (void**)&ia2Action);
QVERIFY(SUCCEEDED(hr));
QVERIFY(ia2Action);
long nActions;
ia2Action->nActions(&nActions);
QVERIFY(nActions >= 1); // "Press" and "SetFocus"
BSTR actionName;
ia2Action->get_name(0, &actionName);
QString name((QChar*)actionName);
QCOMPARE(name, QAccessibleActionInterface::pressAction());
ia2Action->Release();
// Done testing
pIA2->Release();
}
pService->Release();
}
#endif
iacc->Release();
QTestAccessibility::clearEvents();
#endif
}
QTEST_MAIN(tst_QAccessibility)
#include "tst_qaccessibility.moc"