Bring back Mac dependent code in QBoxLayout, QGridLayout
[profile/ivi/qtbase.git] / tests / auto / other / qaccessibility / tst_qaccessibility.cpp
index a0faafc..9d61470 100644 (file)
@@ -1,38 +1,38 @@
 /****************************************************************************
 **
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the test suite of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
 ** 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.
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia 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.
-**
-**
-**
+** 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.
 **
 **
 ** $QT_END_LICENSE$
 ****************************************************************************/
 
 
+#include <QtCore/qglobal.h>
+#ifdef Q_OS_WIN
+# include <QtCore/qt_windows.h>
+# include <oleacc.h>
+# include <servprov.h>
+# include <winuser.h>
+# ifdef QT_SUPPORTS_IACCESSIBLE2
+#  include <Accessible2.h>
+#  include <AccessibleAction.h>
+#  include <AccessibleComponent.h>
+#  include <AccessibleEditableText.h>
+#  include <AccessibleText.h>
+# endif
+#endif
 #include <QtTest/QtTest>
 #include <QtGui>
 #include <QtWidgets>
 #include <math.h>
+#include <qpa/qplatformnativeinterface.h>
 
 #if defined(Q_OS_WIN) && defined(interface)
 #   undef interface
@@ -252,7 +267,7 @@ private slots:
     void mdiAreaTest();
     void mdiSubWindowTest();
     void lineEditTest();
-    void workspaceTest();
+    void groupBoxTest();
     void dialogButtonBoxTest();
     void dialTest();
     void rubberBandTest();
@@ -269,6 +284,7 @@ private slots:
     void accessibleName();
     void labelTest();
     void accelerators();
+    void bridgeTest();
 
 protected slots:
     void onClicked();
@@ -278,52 +294,6 @@ private:
 
 const double Q_PI = 3.14159265358979323846;
 
-QString eventName(const int ev)
-{
-    switch(ev) {
-    case 0x0001: return "SoundPlayed";
-    case 0x0002: return "Alert";
-    case 0x0003: return "ForegroundChanged";
-    case 0x0004: return "MenuStart";
-    case 0x0005: return "MenuEnd";
-    case 0x0006: return "PopupMenuStart";
-    case 0x0007: return "PopupMenuEnd";
-    case 0x000C: return "ContextHelpStart";
-    case 0x000D: return "ContextHelpEnd";
-    case 0x000E: return "DragDropStart";
-    case 0x000F: return "DragDropEnd";
-    case 0x0010: return "DialogStart";
-    case 0x0011: return "DialogEnd";
-    case 0x0012: return "ScrollingStart";
-    case 0x0013: return "ScrollingEnd";
-    case 0x0018: return "MenuCommand";
-
-    case 0x0116: return "TableModelChanged";
-    case 0x011B: return "TextCaretMoved";
-
-    case 0x8000: return "ObjectCreated";
-    case 0x8001: return "ObjectDestroyed";
-    case 0x8002: return "ObjectShow";
-    case 0x8003: return "ObjectHide";
-    case 0x8004: return "ObjectReorder";
-    case 0x8005: return "Focus";
-    case 0x8006: return "Selection";
-    case 0x8007: return "SelectionAdd";
-    case 0x8008: return "SelectionRemove";
-    case 0x8009: return "SelectionWithin";
-    case 0x800A: return "StateChanged";
-    case 0x800B: return "LocationChanged";
-    case 0x800C: return "NameChanged";
-    case 0x800D: return "DescriptionChanged";
-    case 0x800E: return "ValueChanged";
-    case 0x800F: return "ParentChanged";
-    case 0x80A0: return "HelpChanged";
-    case 0x80B0: return "DefaultActionChanged";
-    case 0x80C0: return "AcceleratorChanged";
-    default: return "Unknown Event";
-    }
-}
-
 QAccessible::State state(QWidget * const widget)
 {
     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(widget);
@@ -401,10 +371,10 @@ void tst_QAccessibility::cleanup()
     const EventList list = QTestAccessibility::events();
     if (!list.isEmpty()) {
         qWarning("%d accessibility event(s) were not handled in testfunction '%s':", list.count(),
-                 QString(QTest::currentTestFunction()).toAscii().constData());
+                 QString(QTest::currentTestFunction()).toLatin1().constData());
         for (int i = 0; i < list.count(); ++i)
-            qWarning(" %d: Object: %p Event: '%s' (%d) Child: %d", i + 1, list.at(i).object,
-                     eventName(list.at(i).event).toAscii().constData(), list.at(i).event, list.at(i).child);
+            qWarning(" %d: Object: %p Event: '%s' Child: %d", i + 1, list.at(i)->object(),
+                     qAccessibleEventString(list.at(i)->type()), list.at(i)->child());
     }
     QTestAccessibility::clearEvents();
 }
@@ -415,20 +385,24 @@ void tst_QAccessibility::eventTest()
     button->setObjectName(QString("Olaf"));
 
     button->show();
-    QVERIFY_EVENT(button, 0, QAccessible::ObjectShow);
+    QAccessibleEvent showEvent(button, QAccessible::ObjectShow);
+    // some platforms might send other events first, (such as state change event active=1)
+    QVERIFY(QTestAccessibility::containsEvent(&showEvent));
     button->setFocus(Qt::MouseFocusReason);
     QTestAccessibility::clearEvents();
     QTest::mouseClick(button, Qt::LeftButton, 0);
-    QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
-    QVERIFY_EVENT(button, 0, QAccessible::StateChanged);
 
     button->setAccessibleName("Olaf the second");
-    QVERIFY_EVENT(button, 0, QAccessible::NameChanged);
+    QAccessibleEvent nameEvent(button, QAccessible::NameChanged);
+    QVERIFY_EVENT(&nameEvent);
     button->setAccessibleDescription("This is a button labeled Olaf");
-    QVERIFY_EVENT(button, 0, QAccessible::DescriptionChanged);
+    QAccessibleEvent descEvent(button, QAccessible::DescriptionChanged);
+    QVERIFY_EVENT(&descEvent);
 
     button->hide();
-    QVERIFY_EVENT(button, 0, QAccessible::ObjectHide);
+    QAccessibleEvent hideEvent(button, QAccessible::ObjectHide);
+    // some platforms might send other events first, (such as state change event active=1)
+    QVERIFY(QTestAccessibility::containsEvent(&hideEvent));
 
     delete button;
 }
@@ -598,7 +572,7 @@ static QWidget *createWidgets()
 
     int i = 0;
     box->addWidget(new QComboBox(w));
-    box->addWidget(new QPushButton(QString::fromAscii("widget text %1").arg(i++), w));
+    box->addWidget(new QPushButton(QString::fromLatin1("widget text %1").arg(i++), w));
     box->addWidget(new QHeaderView(Qt::Vertical, w));
     box->addWidget(new QTreeView(w));
     box->addWidget(new QTreeWidget(w));
@@ -608,30 +582,30 @@ static QWidget *createWidgets()
     box->addWidget(new QTableWidget(w));
     box->addWidget(new QCalendarWidget(w));
     box->addWidget(new QDialogButtonBox(w));
-    box->addWidget(new QGroupBox(QString::fromAscii("widget text %1").arg(i++), w));
+    box->addWidget(new QGroupBox(QString::fromLatin1("widget text %1").arg(i++), w));
     box->addWidget(new QFrame(w));
-    box->addWidget(new QLineEdit(QString::fromAscii("widget text %1").arg(i++), w));
+    box->addWidget(new QLineEdit(QString::fromLatin1("widget text %1").arg(i++), w));
     box->addWidget(new QProgressBar(w));
     box->addWidget(new QTabWidget(w));
-    box->addWidget(new QCheckBox(QString::fromAscii("widget text %1").arg(i++), w));
-    box->addWidget(new QRadioButton(QString::fromAscii("widget text %1").arg(i++), w));
+    box->addWidget(new QCheckBox(QString::fromLatin1("widget text %1").arg(i++), w));
+    box->addWidget(new QRadioButton(QString::fromLatin1("widget text %1").arg(i++), w));
     box->addWidget(new QDial(w));
     box->addWidget(new QScrollBar(w));
     box->addWidget(new QSlider(w));
     box->addWidget(new QDateTimeEdit(w));
     box->addWidget(new QDoubleSpinBox(w));
     box->addWidget(new QSpinBox(w));
-    box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
+    box->addWidget(new QLabel(QString::fromLatin1("widget text %1").arg(i++), w));
     box->addWidget(new QLCDNumber(w));
     box->addWidget(new QStackedWidget(w));
     box->addWidget(new QToolBox(w));
-    box->addWidget(new QLabel(QString::fromAscii("widget text %1").arg(i++), w));
-    box->addWidget(new QTextEdit(QString::fromAscii("widget text %1").arg(i++), w));
+    box->addWidget(new QLabel(QString::fromLatin1("widget text %1").arg(i++), w));
+    box->addWidget(new QTextEdit(QString::fromLatin1("widget text %1").arg(i++), w));
 
     /* Not in the list
      * QAbstractItemView, QGraphicsView, QScrollArea,
      * QToolButton, QDockWidget, QFocusFrame, QMainWindow, QMenu, QMenuBar, QSizeGrip, QSplashScreen, QSplitterHandle,
-     * QStatusBar, QSvgWidget, QTabBar, QToolBar, QWorkspace, QSplitter
+     * QStatusBar, QSvgWidget, QTabBar, QToolBar, QSplitter
      */
     return w;
 }
@@ -732,16 +706,21 @@ void tst_QAccessibility::hideShowTest()
     window->show();
     QVERIFY(!state(window).invisible);
     QVERIFY(!state(child).invisible);
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectShow)));
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectShow)));
+
+    QAccessibleEvent show(window, QAccessible::ObjectShow);
+    QVERIFY(QTestAccessibility::containsEvent(&show));
+    QAccessibleEvent showChild(child, QAccessible::ObjectShow);
+    QVERIFY(QTestAccessibility::containsEvent(&showChild));
     QTestAccessibility::clearEvents();
 
     // hide() and veryfy that both window and child are invisible and get ObjectHide events.
     window->hide();
     QVERIFY(state(window).invisible);
     QVERIFY(state(child).invisible);
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(window, 0, QAccessible::ObjectHide)));
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(child, 0, QAccessible::ObjectHide)));
+    QAccessibleEvent hide(window, QAccessible::ObjectHide);
+    QVERIFY(QTestAccessibility::containsEvent(&hide));
+    QAccessibleEvent hideChild(child, QAccessible::ObjectHide);
+    QVERIFY(QTestAccessibility::containsEvent(&hideChild));
     QTestAccessibility::clearEvents();
 
     delete window;
@@ -777,6 +756,7 @@ void tst_QAccessibility::actionTest()
     {
     QPushButton *button = new QPushButton;
     button->show();
+    QVERIFY(QTest::qWaitForWindowExposed(button));
     button->clearFocus();
     QCOMPARE(button->hasFocus(), false);
     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(button);
@@ -814,21 +794,65 @@ void tst_QAccessibility::applicationTest()
 
 void tst_QAccessibility::mainWindowTest()
 {
+    {
     QMainWindow *mw = new QMainWindow;
     mw->resize(300, 200);
     mw->show(); // triggers layout
+    qApp->setActiveWindow(mw);
 
     QLatin1String name = QLatin1String("I am the main window");
     mw->setWindowTitle(name);
-    QTest::qWaitForWindowShown(mw);
-    QVERIFY_EVENT(mw, 0, QAccessible::ObjectShow);
+    QVERIFY(QTest::qWaitForWindowActive(mw));
 
-    QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(mw);
-    QCOMPARE(interface->text(QAccessible::Name), name);
-    QCOMPARE(interface->role(), QAccessible::Window);
-    delete interface;
+    // The order of events is not really that important.
+    QAccessibleEvent show(mw, QAccessible::ObjectShow);
+    QVERIFY(QTestAccessibility::containsEvent(&show));
+    QAccessible::State activeState;
+    activeState.active = true;
+    QAccessibleStateChangeEvent active(mw, activeState);
+    QVERIFY(QTestAccessibility::containsEvent(&active));
+
+    QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(mw);
+    QCOMPARE(iface->text(QAccessible::Name), name);
+    QCOMPARE(iface->role(), QAccessible::Window);
+    QVERIFY(iface->state().active);
+
+
+    delete iface;
     delete mw;
+    }
     QTestAccessibility::clearEvents();
+
+    {
+    QWindow window;
+    window.setGeometry(80, 80, 40, 40);
+    window.show();
+    QTRY_VERIFY(QGuiApplication::focusWindow() == &window);
+
+//    We currently don't have an accessible interface for QWindow
+//    the active state is either in the QMainWindow or QQuickView
+//    QAIPtr windowIface(QAccessible::queryAccessibleInterface(&window));
+//    QVERIFY(windowIface->state().active);
+
+    QAccessible::State activeState;
+    activeState.active = true;
+    QAccessibleStateChangeEvent active(&window, activeState);
+    QVERIFY_EVENT(&active);
+
+    QWindow child;
+    child.setParent(&window);
+    child.setGeometry(10, 10, 20, 20);
+    child.show();
+
+    child.requestActivateWindow();
+    QTRY_VERIFY(QGuiApplication::focusWindow() == &child);
+
+    QAccessibleStateChangeEvent deactivate(&window, activeState);
+    QVERIFY_EVENT(&deactivate); // deactivation of parent
+
+    QAccessibleStateChangeEvent activeChild(&child, activeState);
+    QVERIFY_EVENT(&activeChild);
+    }
 }
 
 class CounterButton : public QPushButton {
@@ -898,14 +922,14 @@ void tst_QAccessibility::buttonTest()
     interface = QAccessible::queryAccessibleInterface(&toggleButton);
     actionInterface = interface->actionInterface();
     QCOMPARE(interface->role(), QAccessible::CheckBox);
-    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
-    QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::checkAction()), QString("Checks the checkbox"));
+    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::toggleAction() << QAccessibleActionInterface::setFocusAction());
+    QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::toggleAction()), QString("Toggles the state"));
     QVERIFY(!toggleButton.isChecked());
     QVERIFY(!interface->state().checked);
-    actionInterface->doAction(QAccessibleActionInterface::checkAction());
+    actionInterface->doAction(QAccessibleActionInterface::toggleAction());
     QTest::qWait(500);
     QVERIFY(toggleButton.isChecked());
-    QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::uncheckAction());
+    QCOMPARE(actionInterface->actionNames().at(0), QAccessibleActionInterface::toggleAction());
     QVERIFY(interface->state().checked);
     delete interface;
 
@@ -929,31 +953,48 @@ void tst_QAccessibility::buttonTest()
     delete menu;
     }
 
+
+    QTestAccessibility::clearEvents();
+    {
     // test check box
     interface = QAccessible::queryAccessibleInterface(&checkBox);
     actionInterface = interface->actionInterface();
     QCOMPARE(interface->role(), QAccessible::CheckBox);
-    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
+    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::toggleAction() << QAccessibleActionInterface::setFocusAction());
     QVERIFY(!interface->state().checked);
-    actionInterface->doAction(QAccessibleActionInterface::checkAction());
+    actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+
     QTest::qWait(500);
-    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::uncheckAction() << QAccessibleActionInterface::setFocusAction());
+    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::toggleAction() << QAccessibleActionInterface::setFocusAction());
     QVERIFY(interface->state().checked);
     QVERIFY(checkBox.isChecked());
+    QAccessible::State st;
+    st.checked = true;
+    QAccessibleStateChangeEvent ev(&checkBox, st);
+    QVERIFY_EVENT(&ev);
+    checkBox.setChecked(false);
+    QVERIFY_EVENT(&ev);
     delete interface;
+    }
 
+    {
     // test radiobutton
     interface = QAccessible::queryAccessibleInterface(&radio);
     actionInterface = interface->actionInterface();
     QCOMPARE(interface->role(), QAccessible::RadioButton);
-    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
+    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::toggleAction() << QAccessibleActionInterface::setFocusAction());
     QVERIFY(!interface->state().checked);
-    actionInterface->doAction(QAccessibleActionInterface::checkAction());
+    actionInterface->doAction(QAccessibleActionInterface::toggleAction());
     QTest::qWait(500);
-    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::checkAction() << QAccessibleActionInterface::setFocusAction());
+    QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::toggleAction() << QAccessibleActionInterface::setFocusAction());
     QVERIFY(interface->state().checked);
-    QVERIFY(checkBox.isChecked());
+    QVERIFY(radio.isChecked());
+    QAccessible::State st;
+    st.checked = true;
+    QAccessibleStateChangeEvent ev(&radio, st);
+    QVERIFY_EVENT(&ev);
     delete interface;
+    }
 
 //    // test standard toolbutton
 //    QVERIFY(QAccessible::queryAccessibleInterface(&toolbutton, &test));
@@ -1003,8 +1044,6 @@ void tst_QAccessibility::buttonTest()
 //    QCOMPARE(test->actionText(test->defaultAction(2), QAccessible::Name, 2), QString("Open"));
 //    QCOMPARE(test->state(2), (int)QAccessible::HasPopup);
 //    test->release();
-
-    QTestAccessibility::clearEvents();
 }
 
 void tst_QAccessibility::scrollBarTest()
@@ -1016,12 +1055,14 @@ void tst_QAccessibility::scrollBarTest()
     scrollBar->resize(200, 50);
     scrollBar->show();
     QVERIFY(!scrollBarInterface->state().invisible);
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectShow)));
+    QAccessibleEvent show(scrollBar, QAccessible::ObjectShow);
+    QVERIFY(QTestAccessibility::containsEvent(&show));
     QTestAccessibility::clearEvents();
 
     scrollBar->hide();
     QVERIFY(scrollBarInterface->state().invisible);
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(scrollBar, 0, QAccessible::ObjectHide)));
+    QAccessibleEvent hide(scrollBar, QAccessible::ObjectHide);
+    QVERIFY(QTestAccessibility::containsEvent(&hide));
     QTestAccessibility::clearEvents();
 
     // Test that the left/right subcontrols are set to unavailable when the scrollBar is at the minimum/maximum.
@@ -1437,6 +1478,8 @@ void tst_QAccessibility::spinBoxTest()
     QVERIFY(interface);
     QCOMPARE(interface->role(), QAccessible::SpinBox);
 
+    QVERIFY(QTest::qWaitForWindowExposed(spinBox));
+
     const QRect widgetRect = spinBox->geometry();
     const QRect accessibleRect = interface->rect();
     QCOMPARE(accessibleRect, widgetRect);
@@ -1461,9 +1504,8 @@ void tst_QAccessibility::spinBoxTest()
     QTestAccessibility::clearEvents();
     QTest::keyPress(spinBox, Qt::Key_Up);
     QTest::qWait(200);
-    EventList events = QTestAccessibility::events();
-    QTestAccessibilityEvent expectedEvent(spinBox, 0, (int)QAccessible::ValueChanged);
-    QVERIFY(events.contains(expectedEvent));
+    QAccessibleValueChangeEvent expectedEvent(spinBox, spinBox->value());
+    QVERIFY(QTestAccessibility::containsEvent(&expectedEvent));
     delete spinBox;
     QTestAccessibility::clearEvents();
 }
@@ -1476,6 +1518,8 @@ void tst_QAccessibility::doubleSpinBoxTest()
     QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(doubleSpinBox);
     QVERIFY(interface);
 
+    QVERIFY(QTest::qWaitForWindowExposed(doubleSpinBox));
+
     const QRect widgetRect = doubleSpinBox->geometry();
     const QRect accessibleRect = interface->rect();
     QCOMPARE(accessibleRect, widgetRect);
@@ -1493,31 +1537,89 @@ void tst_QAccessibility::doubleSpinBoxTest()
     QTestAccessibility::clearEvents();
 }
 
+static QRect characterRect(const QTextEdit &edit, int offset)
+{
+    QTextBlock block = edit.document()->findBlock(offset);
+    QTextLayout *layout = block.layout();
+    QPointF layoutPosition = layout->position();
+    int relativeOffset = offset - block.position();
+    QTextLine line = layout->lineForTextPosition(relativeOffset);
+    QFontMetrics fm(edit.font());
+    QChar ch = edit.document()->characterAt(offset);
+    int w = fm.width(ch);
+    int h = fm.height();
+
+    qreal x = line.cursorToX(relativeOffset);
+    QRect r(layoutPosition.x() + x, layoutPosition.y() + line.y(), w, h);
+    r.moveTo(edit.viewport()->mapToGlobal(r.topLeft()));
+
+    return r;
+}
+
 void tst_QAccessibility::textEditTest()
 {
-    {
-    QTextEdit edit;
-    int startOffset;
-    int endOffset;
-    QString text = "hello world\nhow are you today?\n";
-    edit.setText(text);
-    edit.show();
+    for (int pass = 0; pass < 2; ++pass) {
+        {
+        QTextEdit edit;
+        int startOffset;
+        int endOffset;
+        // create two blocks of text. The first block has two lines.
+        QString text = "<p>hello world.<br/>How are you today?</p><p>I'm fine, thanks</p>";
+        edit.setHtml(text);
+        if (pass == 1) {
+            QFont font("Helvetica");
+            font.setPointSizeF(12.5);
+            font.setWordSpacing(1.1);
+            edit.setFont(font);
+        }
 
-    QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit);
-    QCOMPARE(iface->text(QAccessible::Value), text);
-    QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
-    QCOMPARE(startOffset, 6);
-    QCOMPARE(endOffset, 11);
-    QCOMPARE(iface->textInterface()->textAtOffset(14, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("how are you today?"));
-    QCOMPARE(startOffset, 12);
-    QCOMPARE(endOffset, 30);
-    QCOMPARE(iface->textInterface()->characterCount(), 31);
-    QFontMetrics fm(edit.font());
-    QCOMPARE(iface->textInterface()->characterRect(0, QAccessible2::RelativeToParent).size(), QSize(fm.width("h"), fm.height()));
-    QCOMPARE(iface->textInterface()->characterRect(5, QAccessible2::RelativeToParent).size(), QSize(fm.width(" "), fm.height()));
-    QCOMPARE(iface->textInterface()->characterRect(6, QAccessible2::RelativeToParent).size(), QSize(fm.width("w"), fm.height()));
+        edit.show();
+        QTest::qWaitForWindowShown(&edit);
+        QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&edit);
+        QCOMPARE(iface->text(QAccessible::Value), edit.toPlainText());
+        QCOMPARE(iface->textInterface()->textAtOffset(8, QAccessible2::WordBoundary, &startOffset, &endOffset), QString("world"));
+        QCOMPARE(startOffset, 6);
+        QCOMPARE(endOffset, 11);
+        QCOMPARE(iface->textInterface()->textAtOffset(15, QAccessible2::LineBoundary, &startOffset, &endOffset), QString("How are you today?"));
+        QCOMPARE(startOffset, 13);
+        QCOMPARE(endOffset, 31);
+        QCOMPARE(iface->textInterface()->characterCount(), 48);
+        QFontMetrics fm(edit.font());
+        QCOMPARE(iface->textInterface()->characterRect(0).size(), QSize(fm.width("h"), fm.height()));
+        QCOMPARE(iface->textInterface()->characterRect(5).size(), QSize(fm.width(" "), fm.height()));
+        QCOMPARE(iface->textInterface()->characterRect(6).size(), QSize(fm.width("w"), fm.height()));
+
+        int offset = 10;
+        QCOMPARE(iface->textInterface()->text(offset, offset + 1), QStringLiteral("d"));
+        QCOMPARE(iface->textInterface()->characterRect(offset), characterRect(edit, offset));
+        offset = 13;
+        QCOMPARE(iface->textInterface()->text(offset, offset + 1), QStringLiteral("H"));
+        QCOMPARE(iface->textInterface()->characterRect(offset), characterRect(edit, offset));
+        offset = 21;
+        QCOMPARE(iface->textInterface()->text(offset, offset + 1), QStringLiteral("y"));
+        QCOMPARE(iface->textInterface()->characterRect(offset), characterRect(edit, offset));
+        offset = 32;
+        QCOMPARE(iface->textInterface()->text(offset, offset + 1), QStringLiteral("I"));
+        QCOMPARE(iface->textInterface()->characterRect(offset), characterRect(edit, offset));
+
+        QTestAccessibility::clearEvents();
+
+        // select text
+        QTextCursor c = edit.textCursor();
+        c.setPosition(2);
+        c.setPosition(4, QTextCursor::KeepAnchor);
+        edit.setTextCursor(c);
+        QAccessibleTextSelectionEvent sel(&edit, 2, 4);
+        QVERIFY_EVENT(&sel);
+
+        edit.selectAll();
+        int end = edit.textCursor().position();
+        sel.setCursorPosition(end);
+        sel.setSelection(0, end);
+        QVERIFY_EVENT(&sel);
+        }
+        QTestAccessibility::clearEvents();
     }
-    QTestAccessibility::clearEvents();
 }
 
 void tst_QAccessibility::textBrowserTest()
@@ -1572,14 +1674,13 @@ void tst_QAccessibility::mdiSubWindowTest()
     QMdiArea mdiArea;
     mdiArea.show();
     qApp->setActiveWindow(&mdiArea);
-#if defined(Q_OS_UNIX)
-    QCoreApplication::processEvents();
-    QTest::qWait(150);
-#endif
+    QVERIFY(QTest::qWaitForWindowActive(&mdiArea));
+
 
     const int subWindowCount =  5;
     for (int i = 0; i < subWindowCount; ++i) {
         QMdiSubWindow *window = mdiArea.addSubWindow(new QPushButton("QAccessibilityTest"));
+        window->setAttribute(Qt::WA_LayoutUsesWidgetRect);
         window->show();
         // Parts of this test requires that the sub windows are placed next
         // to each other. In order to achieve that QMdiArea must have
@@ -1658,6 +1759,9 @@ void tst_QAccessibility::mdiSubWindowTest()
     const QRect widgetGeometry = testWindow->contentsRect();
     const QPoint globalWidgetPos = QPoint(globalPos.x() + widgetGeometry.x(),
                                           globalPos.y() + widgetGeometry.y());
+#ifdef Q_OS_MAC
+    QSKIP("QTBUG-22812");
+#endif
     QCOMPARE(childRect(interface), QRect(globalWidgetPos, widgetGeometry.size()));
 
     // childAt
@@ -1676,8 +1780,10 @@ void tst_QAccessibility::mdiSubWindowTest()
 
 void tst_QAccessibility::lineEditTest()
 {
+    QWidget *toplevel = new QWidget;
+    {
     QLineEdit *le = new QLineEdit;
-    QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(le);
+    QAIPtr iface(QAccessible::queryAccessibleInterface(le));
     QVERIFY(iface);
     le->show();
 
@@ -1685,7 +1791,7 @@ void tst_QAccessibility::lineEditTest()
     QCOMPARE(iface->childCount(), 0);
     QVERIFY(iface->state().sizeable);
     QVERIFY(iface->state().movable);
-    QCOMPARE(bool(iface->state().focusable), le->isActiveWindow());
+    QVERIFY(iface->state().focusable);
     QVERIFY(iface->state().selectable);
     QVERIFY(iface->state().hasPopup);
     QCOMPARE(bool(iface->state().focused), le->hasFocus());
@@ -1708,13 +1814,12 @@ void tst_QAccessibility::lineEditTest()
     QVERIFY(!(iface->state().passwordEdit));
     QCOMPARE(iface->text(QAccessible::Value), secret);
 
-    QWidget *toplevel = new QWidget;
     le->setParent(toplevel);
     toplevel->show();
     QApplication::processEvents();
     QVERIFY(!(iface->state().sizeable));
     QVERIFY(!(iface->state().movable));
-    QCOMPARE(bool(iface->state().focusable), le->isActiveWindow());
+    QVERIFY(iface->state().focusable);
     QVERIFY(iface->state().selectable);
     QVERIFY(iface->state().hasPopup);
     QCOMPARE(bool(iface->state().focused), le->hasFocus());
@@ -1727,27 +1832,32 @@ void tst_QAccessibility::lineEditTest()
     le->setFocus(Qt::TabFocusReason);
     QTestAccessibility::clearEvents();
     le2->setFocus(Qt::TabFocusReason);
-    QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le2, 0, QAccessible::Focus)));
+    QAccessibleEvent ev(le2, QAccessible::Focus);
+    QTRY_VERIFY(QTestAccessibility::containsEvent(&ev));
 
     le->setText(QLatin1String("500"));
     le->setValidator(new QIntValidator());
     iface->setText(QAccessible::Value, QLatin1String("This text is not a number"));
     QCOMPARE(le->text(), QLatin1String("500"));
 
-    delete iface;
     delete le;
     delete le2;
-    QTestAccessibility::clearEvents();
+    }
 
-    // IA2
+    {
+    // Text interface to get the current text
     QString cite = "I always pass on good advice. It is the only thing to do with it. It is never of any use to oneself. --Oscar Wilde";
     QLineEdit *le3 = new QLineEdit(cite, toplevel);
-    iface = QAccessible::queryAccessibleInterface(le3);
+    le3->show();
+    QAIPtr iface(QAccessible::queryAccessibleInterface(le3));
     QAccessibleTextInterface* textIface = iface->textInterface();
     le3->deselect();
+    QTestAccessibility::clearEvents();
     le3->setCursorPosition(3);
     QCOMPARE(textIface->cursorPosition(), 3);
-    QTRY_VERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(le3, 0, QAccessible::TextCaretMoved)));
+
+    QAccessibleTextCursorEvent caretEvent(le3, 3);
+    QTRY_VERIFY(QTestAccessibility::containsEvent(&caretEvent));
     QCOMPARE(textIface->selectionCount(), 0);
     QTestAccessibility::clearEvents();
 
@@ -1776,6 +1886,7 @@ void tst_QAccessibility::lineEditTest()
     QCOMPARE(textIface->textAtOffset(8, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
     QCOMPARE(textIface->textAtOffset(25, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("advice"));
     QCOMPARE(textIface->textAtOffset(92, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1("oneself"));
+    QCOMPARE(textIface->textAtOffset(101, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(". --"));
 
     QCOMPARE(textIface->textBeforeOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
     QCOMPARE(textIface->textAfterOffset(5, QAccessible2::WordBoundary,&start,&end), QString::fromLatin1(" "));
@@ -1792,35 +1903,172 @@ void tst_QAccessibility::lineEditTest()
     QCOMPARE(textIface->textAtOffset(5, QAccessible2::LineBoundary,&start,&end), cite);
     QCOMPARE(textIface->textAtOffset(5, QAccessible2::NoBoundary,&start,&end), cite);
 
-    delete iface;
+    QTestAccessibility::clearEvents();
+    }
+
+    {
+    // Test events: cursor movement, selection, text changes
+    QString text = "Hello, world";
+    QLineEdit *lineEdit = new QLineEdit(text, toplevel);
+    lineEdit->show();
+    QTestAccessibility::clearEvents();
+    // cursor
+    lineEdit->setCursorPosition(5);
+    QAccessibleTextCursorEvent cursorEvent(lineEdit, 5);
+    QVERIFY_EVENT(&cursorEvent);
+    lineEdit->setCursorPosition(0);
+    cursorEvent.setCursorPosition(0);
+    QVERIFY_EVENT(&cursorEvent);
+
+    // selection
+    lineEdit->setSelection(2, 4);
+
+    QAccessibleTextSelectionEvent sel(lineEdit, 2, 2+4);
+    QVERIFY_EVENT(&sel);
+
+    lineEdit->selectAll();
+    sel.setSelection(0, lineEdit->text().length());
+    sel.setCursorPosition(lineEdit->text().length());
+    QVERIFY_EVENT(&sel);
+
+    lineEdit->setSelection(10, -4);
+    QCOMPARE(lineEdit->cursorPosition(), 6);
+    QAccessibleTextSelectionEvent sel2(lineEdit, 6, 10);
+    sel2.setCursorPosition(6);
+    QVERIFY_EVENT(&sel2);
+
+    lineEdit->deselect();
+    QAccessibleTextSelectionEvent sel3(lineEdit, -1, -1);
+    sel3.setCursorPosition(6);
+    QVERIFY_EVENT(&sel3);
+
+    // editing
+    lineEdit->clear();
+    // FIXME: improve redundant updates
+    QAccessibleTextRemoveEvent remove(lineEdit, 0, text);
+    QVERIFY_EVENT(&remove);
+
+    QAccessibleTextSelectionEvent noSel(lineEdit, -1, -1);
+    QVERIFY_EVENT(&noSel);
+    QAccessibleTextCursorEvent cursor(lineEdit, 0);
+    QVERIFY_EVENT(&cursor);
+
+    lineEdit->setText("foo");
+    cursorEvent.setCursorPosition(3);
+    QVERIFY_EVENT(&cursorEvent);
+
+    QAccessibleTextInsertEvent e(lineEdit, 0, "foo");
+    QVERIFY(QTestAccessibility::containsEvent(&e));
+
+    lineEdit->setText("bar");
+    QAccessibleTextUpdateEvent update(lineEdit, 0, "foo", "bar");
+    QVERIFY(QTestAccessibility::containsEvent(&update));
+
+    // FIXME check what extra events are around and get rid of them
+    QTestAccessibility::clearEvents();
+
+    QTestEventList keys;
+    keys.addKeyClick('D');
+    keys.simulate(lineEdit);
+
+    QAccessibleTextInsertEvent insertD(lineEdit, 3, "D");
+    QVERIFY_EVENT(&insertD);
+    keys.clear();
+    keys.addKeyClick('E');
+    keys.simulate(lineEdit);
+
+    QAccessibleTextInsertEvent insertE(lineEdit, 4, "E");
+    QVERIFY(QTestAccessibility::containsEvent(&insertE));
+    keys.clear();
+    keys.addKeyClick(Qt::Key_Left);
+    keys.addKeyClick(Qt::Key_Left);
+    keys.simulate(lineEdit);
+    cursorEvent.setCursorPosition(4);
+    QVERIFY(QTestAccessibility::containsEvent(&cursorEvent));
+    cursorEvent.setCursorPosition(3);
+    QVERIFY(QTestAccessibility::containsEvent(&cursorEvent));
+
+    keys.clear();
+    keys.addKeyClick('C');
+    keys.simulate(lineEdit);
+
+    QAccessibleTextInsertEvent insertC(lineEdit, 3, "C");
+    QVERIFY(QTestAccessibility::containsEvent(&insertC));
+
+    keys.clear();
+    keys.addKeyClick('O');
+    keys.simulate(lineEdit);
+    QAccessibleTextInsertEvent insertO(lineEdit, 4, "O");
+    QVERIFY(QTestAccessibility::containsEvent(&insertO));
+    }
     delete toplevel;
     QTestAccessibility::clearEvents();
 }
 
-void tst_QAccessibility::workspaceTest()
+void tst_QAccessibility::groupBoxTest()
 {
     {
-    QWorkspace workspace;
-    workspace.resize(400,300);
-    workspace.show();
-    const int subWindowCount =  3;
-    for (int i = 0; i < subWindowCount; ++i) {
-        QWidget *window = workspace.addWindow(new QWidget);
-        if (i > 0)
-            window->move(window->x() + 1, window->y());
-        window->show();
-        window->resize(70, window->height());
-    }
+    QGroupBox *groupBox = new QGroupBox();
+    QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(groupBox);
 
-    QWidgetList subWindows = workspace.windowList();
-    QCOMPARE(subWindows.count(), subWindowCount);
+    groupBox->setTitle(QLatin1String("Test QGroupBox"));
 
-    QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&workspace);
-    QVERIFY(interface);
-    QCOMPARE(interface->childCount(), subWindowCount);
+    QAccessibleEvent ev(groupBox, QAccessible::NameChanged);
+    QVERIFY_EVENT(&ev);
+
+    groupBox->setToolTip(QLatin1String("This group box will be used to test accessibility"));
+    QVBoxLayout *layout = new QVBoxLayout();
+    QRadioButton *rbutton = new QRadioButton();
+    layout->addWidget(rbutton);
+    groupBox->setLayout(layout);
+    QAccessibleInterface *rButtonIface = QAccessible::queryAccessibleInterface(rbutton);
+
+    QCOMPARE(iface->childCount(), 1);
+    QCOMPARE(iface->role(), QAccessible::Grouping);
+    QCOMPARE(iface->text(QAccessible::Name), QLatin1String("Test QGroupBox"));
+    QCOMPARE(iface->text(QAccessible::Description), QLatin1String("This group box will be used to test accessibility"));
+    QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > relations = rButtonIface->relations();
+    QVERIFY(relations.size() == 1);
+    QPair<QAccessibleInterface*, QAccessible::Relation> relation = relations.first();
+    QCOMPARE(relation.first->object(), groupBox);
+    QCOMPARE(relation.second, QAccessible::Label);
+
+    delete relation.first;
+
+    delete rButtonIface;
+    delete iface;
+    delete groupBox;
+    }
+
+    {
+    QGroupBox *groupBox = new QGroupBox();
+    QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(groupBox);
+    QVERIFY(!iface->state().checkable);
+    groupBox->setCheckable(true);
+
+    groupBox->setChecked(false);
+    QAccessible::State st;
+    st.checked = true;
+    QAccessibleStateChangeEvent ev(groupBox, st);
+    QVERIFY_EVENT(&ev);
+
+    QCOMPARE(iface->role(), QAccessible::CheckBox);
+    QAccessibleActionInterface *actionIface = iface->actionInterface();
+    QVERIFY(actionIface);
+    QAccessible::State state = iface->state();
+    QVERIFY(state.checkable);
+    QVERIFY(!state.checked);
+    QVERIFY(actionIface->actionNames().contains(QAccessibleActionInterface::toggleAction()));
+    actionIface->doAction(QAccessibleActionInterface::toggleAction());
+    QVERIFY(groupBox->isChecked());
+    state = iface->state();
+    QVERIFY(state.checked);
+    QAccessibleStateChangeEvent ev2(groupBox, st);
+    QVERIFY_EVENT(&ev2);
 
+    delete iface;
+    delete groupBox;
     }
-    QTestAccessibility::clearEvents();
 }
 
 bool accessibleInterfaceLeftOf(const QAccessibleInterface *a1, const QAccessibleInterface *a2)
@@ -1944,6 +2192,8 @@ void tst_QAccessibility::dialTest()
     QVERIFY(interface);
     QCOMPARE(interface->childCount(), 0);
 
+    QVERIFY(QTest::qWaitForWindowExposed(&dial));
+
     QCOMPARE(interface->text(QAccessible::Value), QString::number(dial.value()));
     QCOMPARE(interface->rect(), dial.geometry());
 
@@ -2118,11 +2368,20 @@ void tst_QAccessibility::listTest()
 
     // Check for events
     QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(1)).center());
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Selection)));
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 2, QAccessible::Focus)));
+    QAccessibleEvent selectionEvent(listView, QAccessible::Selection);
+    selectionEvent.setChild(2);
+    QAccessibleEvent focusEvent(listView, QAccessible::Focus);
+    focusEvent.setChild(2);
+    QVERIFY(QTestAccessibility::containsEvent(&selectionEvent));
+    QVERIFY(QTestAccessibility::containsEvent(&focusEvent));
     QTest::mouseClick(listView->viewport(), Qt::LeftButton, 0, listView->visualItemRect(listView->item(2)).center());
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Selection)));
-    QVERIFY(QTestAccessibility::events().contains(QTestAccessibilityEvent(listView, 3, QAccessible::Focus)));
+
+    QAccessibleEvent selectionEvent2(listView, QAccessible::Selection);
+    selectionEvent2.setChild(3);
+    QAccessibleEvent focusEvent2(listView, QAccessible::Focus);
+    focusEvent2.setChild(3);
+    QVERIFY(QTestAccessibility::containsEvent(&selectionEvent2));
+    QVERIFY(QTestAccessibility::containsEvent(&focusEvent2));
 
     listView->addItem("Munich");
     QCOMPARE(iface->childCount(), 4);
@@ -2564,7 +2823,11 @@ void tst_QAccessibility::comboBoxTest()
     { // not editable combobox
     QComboBox combo;
     combo.addItems(QStringList() << "one" << "two" << "three");
+    // Fully decorated windows have a minimum width of 160 on Windows.
+    combo.setMinimumWidth(200);
     combo.show();
+    QVERIFY(QTest::qWaitForWindowShown(&combo));
+
     QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(&combo);
     QCOMPARE(verifyHierarchy(iface), 0);
 
@@ -2589,13 +2852,14 @@ void tst_QAccessibility::comboBoxTest()
     QVERIFY(iface->actionInterface());
     QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction());
     iface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction());
-    QVERIFY(combo.view()->isVisible());
+    QTRY_VERIFY(combo.view()->isVisible());
 
     delete iface;
     }
 
     { // editable combobox
     QComboBox editableCombo;
+    editableCombo.setMinimumWidth(200);
     editableCombo.show();
     editableCombo.setEditable(true);
     editableCombo.addItems(QStringList() << "foo" << "bar" << "baz");
@@ -2654,7 +2918,8 @@ void tst_QAccessibility::labelTest()
 
     QCOMPARE(imageInterface->imageSize(), testPixmap.size());
     QCOMPARE(imageInterface->imageDescription(), QString::fromLatin1("Test Description"));
-    QCOMPARE(imageInterface->imagePosition(QAccessible2::RelativeToParent), imageLabel.geometry());
+    const QPoint labelPos = imageLabel.mapToGlobal(QPoint(0,0));
+    QCOMPARE(imageInterface->imagePosition().topLeft(), labelPos);
 
     delete acc_label;
 
@@ -2701,5 +2966,180 @@ void tst_QAccessibility::accelerators()
     QTestAccessibility::clearEvents();
 }
 
+#ifdef QT_SUPPORTS_IACCESSIBLE2
+static IUnknown *queryIA2(IAccessible *acc, const IID &iid)
+{
+    IUnknown *resultInterface = 0;
+    IServiceProvider *pService = 0;
+    HRESULT hr = acc->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.
+            hr = pIA2->QueryInterface(iid, (void**)&resultInterface);
+            pIA2->Release();
+        }
+        // The control supports IAccessible2.
+        pService->Release();
+    }
+    return resultInterface;
+}
+#endif
+
+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);
+    QTextEdit *te = new QTextEdit(window);
+    te->setText(QLatin1String("hello world\nhow are you today?\n"));
+    lay->addWidget(button);
+    lay->addWidget(te);
+
+    window->show();
+    QVERIFY(QTest::qWaitForWindowExposed(window));
+
+
+    /**************************************************
+     *   QPushButton
+     **************************************************/
+    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 *iaccButton;
+
+    VARIANT varChild;
+    HRESULT hr = ::AccessibleObjectFromPoint(pt, &iaccButton, &varChild);
+    QVERIFY(SUCCEEDED(hr));
+    VARIANT varSELF;
+    varSELF.vt = VT_I4;
+    varSELF.lVal = 0;
+
+    // **** Test get_accRole ****
+    VARIANT varRole;
+    hr = iaccButton->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 = iaccButton->accLocation(&x, &y, &w, &h, varSELF);
+    QCOMPARE(buttonRect, QRect(x, y, w, h));
+
+#ifdef QT_SUPPORTS_IACCESSIBLE2
+    // Test IAccessible2 part of bridge
+    if (IAccessible2 *ia2Button = (IAccessible2*)queryIA2(iaccButton, IID_IAccessible2)) {
+        // The control supports IAccessible2.
+        // ia2Button is the reference to the accessible object's IAccessible2 interface.
+
+        /***** Test IAccessibleComponent *****/
+        IAccessibleComponent *ia2Component = 0;
+        hr = ia2Button->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 = ia2Button->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
+        ia2Button->Release();
+    }
+#endif
+    iaccButton->Release();
+
+    /**************************************************
+     *   QWidget
+     **************************************************/
+    QWindow *windowHandle = window->windowHandle();
+    QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface();
+    HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", windowHandle);
+
+    IAccessible *iaccWindow;
+    hr = ::AccessibleObjectFromWindow(hWnd, OBJID_CLIENT, IID_IAccessible, (void**)&iaccWindow);
+    QVERIFY(SUCCEEDED(hr));
+    hr = iaccWindow->get_accRole(varSELF, &varRole);
+    QVERIFY(SUCCEEDED(hr));
+
+    QCOMPARE(varRole.vt, (VARTYPE)VT_I4);
+    QCOMPARE(varRole.lVal, (LONG)ROLE_SYSTEM_CLIENT);
+
+    long nChildren;
+    hr = iaccWindow->get_accChildCount(&nChildren);
+    QVERIFY(SUCCEEDED(hr));
+    QCOMPARE(nChildren, (long)2);
+
+    /**************************************************
+     *   QTextEdit
+     **************************************************/
+    // Get the second child (the accessible interface for the text edit)
+    varChild.vt = VT_I4;
+    varChild.lVal = 2;
+    QVERIFY(iaccWindow);
+    IAccessible *iaccTextEdit;
+    hr = iaccWindow->get_accChild(varChild, (IDispatch**)&iaccTextEdit);
+    QVERIFY(SUCCEEDED(hr));
+    QVERIFY(iaccTextEdit);
+    hr = iaccTextEdit->get_accRole(varSELF, &varRole);
+    QVERIFY(SUCCEEDED(hr));
+
+    QCOMPARE(varRole.vt, (VARTYPE)VT_I4);
+    QCOMPARE(varRole.lVal, (LONG)ROLE_SYSTEM_TEXT);
+
+
+
+#ifdef QT_SUPPORTS_IACCESSIBLE2
+    if (IAccessibleEditableText *ia2TextEdit = (IAccessibleEditableText*)queryIA2(iaccTextEdit, IID_IAccessibleEditableText)) {
+        ia2TextEdit->copyText(6, 11);
+        QCOMPARE(QApplication::clipboard()->text(), QLatin1String("world"));
+        ia2TextEdit->cutText(12, 16);
+        QCOMPARE(QApplication::clipboard()->text(), QLatin1String("how "));
+        ia2TextEdit->Release();
+    }
+    if (IAccessibleText *ia2Text = (IAccessibleText*)queryIA2(iaccTextEdit, IID_IAccessibleText)) {
+        BSTR txt;
+        hr = ia2Text->get_text(12, 15, &txt);
+        QVERIFY(SUCCEEDED(hr));
+        QCOMPARE(QString((QChar*)txt), QLatin1String("are"));
+        ia2Text->Release();
+    }
+#endif
+    iaccTextEdit->Release();
+
+
+    iaccWindow->Release();
+    QTestAccessibility::clearEvents();
+#endif
+}
+
 QTEST_MAIN(tst_QAccessibility)
 #include "tst_qaccessibility.moc"