diff options
-rw-r--r-- | src/gui/accessible/qaccessible2.cpp | 113 | ||||
-rw-r--r-- | src/gui/accessible/qaccessible2.h | 21 | ||||
-rw-r--r-- | src/plugins/accessible/widgets/qaccessiblewidgets.cpp | 62 | ||||
-rw-r--r-- | src/plugins/accessible/widgets/qaccessiblewidgets.h | 5 | ||||
-rw-r--r-- | src/plugins/accessible/widgets/simplewidgets.cpp | 7 | ||||
-rw-r--r-- | src/plugins/accessible/widgets/simplewidgets.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/windows/accessible/comutils.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/windows/accessible/iaccessible2.cpp | 129 | ||||
-rw-r--r-- | src/plugins/platforms/windows/accessible/iaccessible2.h | 6 | ||||
-rw-r--r-- | tests/auto/other/qaccessibility/qaccessibility.pro | 5 | ||||
-rw-r--r-- | tests/auto/other/qaccessibility/tst_qaccessibility.cpp | 181 |
11 files changed, 284 insertions, 253 deletions
diff --git a/src/gui/accessible/qaccessible2.cpp b/src/gui/accessible/qaccessible2.cpp index 41275628f2..4936846d6c 100644 --- a/src/gui/accessible/qaccessible2.cpp +++ b/src/gui/accessible/qaccessible2.cpp @@ -190,10 +190,6 @@ QT_BEGIN_NAMESPACE When implementing this interface you will almost certainly also want to implement \l QAccessibleTextInterface. - Since this interface can be implemented by means of the normal \l QAccessibleTextInterface, - \l QAccessibleSimpleEditableTextInterface provides a convenience implementation of this interface. - Consider inheriting \l QAccessibleSimpleEditableTextInterface instead. - \sa QAccessibleInterface \l{IAccessible2 Specification} @@ -206,14 +202,6 @@ QT_BEGIN_NAMESPACE */ /*! - \fn void QAccessibleEditableTextInterface::copyText(int startOffset, int endOffset) const - - Copies the text from \a startOffset to \a endOffset to the system clip board. - The \a startOffset is the first character that will be copied. - The \a endOffset is the first character that will not be copied. -*/ - -/*! \fn void QAccessibleEditableTextInterface::deleteText(int startOffset, int endOffset) Deletes the text from \a startOffset to \a endOffset. @@ -226,18 +214,6 @@ QT_BEGIN_NAMESPACE */ /*! - \fn void QAccessibleEditableTextInterface::cutText(int startOffset, int endOffset) - - Removes the text from \a startOffset to \a endOffset and puts it in the system clip board. -*/ - -/*! - \fn void QAccessibleEditableTextInterface::pasteText(int offset) - - Pastes text from the system clip board at the position \a offset. -*/ - -/*! \fn void QAccessibleEditableTextInterface::replaceText(int startOffset, int endOffset, const QString &text) Removes the text from \a startOffset to \a endOffset and instead inserts \a text. @@ -250,20 +226,7 @@ QT_BEGIN_NAMESPACE */ /*! - \class QAccessibleSimpleEditableTextInterface - \inmodule QtGui - \ingroup accessibility - \internal - - \brief The QAccessibleSimpleEditableTextInterface class is a convenience class for - text-based widgets. It can be inherited instead of \l QAccessibleEditableTextInterface. - - \sa QAccessibleInterface, QAccessibleEditableTextInterface - - \l{IAccessible2 Specification} -*/ - -/*! + \class QAccessibleValueInterface \class QAccessibleValueInterface \inmodule QtGui \ingroup accessibility @@ -667,80 +630,6 @@ QString Q_GUI_EXPORT qTextAtOffsetFromString(int offset, QAccessible2::BoundaryT return text.mid(*startOffset, *endOffset - *startOffset); } -QAccessibleSimpleEditableTextInterface::QAccessibleSimpleEditableTextInterface( - QAccessibleInterface *accessibleInterface) - : iface(accessibleInterface) -{ - Q_ASSERT(iface); -} - -#ifndef QT_NO_CLIPBOARD -static QString textForRange(QAccessibleInterface *iface, int startOffset, int endOffset) -{ - return iface->text(QAccessible::Value).mid(startOffset, endOffset - startOffset); -} -#endif - -/*! \reimp */ -void QAccessibleSimpleEditableTextInterface::copyText(int startOffset, int endOffset) const -{ -#ifdef QT_NO_CLIPBOARD - Q_UNUSED(startOffset); - Q_UNUSED(endOffset); -#else - QGuiApplication::clipboard()->setText(textForRange(iface, startOffset, endOffset)); -#endif -} - -/*! \reimp */ -void QAccessibleSimpleEditableTextInterface::deleteText(int startOffset, int endOffset) -{ - QString txt = iface->text(QAccessible::Value); - txt.remove(startOffset, endOffset - startOffset); - iface->setText(QAccessible::Value, txt); -} - -/*! \reimp */ -void QAccessibleSimpleEditableTextInterface::insertText(int offset, const QString &text) -{ - QString txt = iface->text(QAccessible::Value); - txt.insert(offset, text); - iface->setText(QAccessible::Value, txt); -} - -/*! \reimp */ -void QAccessibleSimpleEditableTextInterface::cutText(int startOffset, int endOffset) -{ -#ifdef QT_NO_CLIPBOARD - Q_UNUSED(startOffset); - Q_UNUSED(endOffset); -#else - QString sub = textForRange(iface, startOffset, endOffset); - deleteText(startOffset, endOffset); - QGuiApplication::clipboard()->setText(sub); -#endif -} - -/*! \reimp */ -void QAccessibleSimpleEditableTextInterface::pasteText(int offset) -{ -#ifdef QT_NO_CLIPBOARD - Q_UNUSED(offset); -#else - QString txt = iface->text(QAccessible::Value); - txt.insert(offset, QGuiApplication::clipboard()->text()); - iface->setText(QAccessible::Value, txt); -#endif -} - -/*! \reimp */ -void QAccessibleSimpleEditableTextInterface::replaceText(int startOffset, int endOffset, const QString &text) -{ - QString txt = iface->text(QAccessible::Value); - txt.replace(startOffset, endOffset - startOffset, text); - iface->setText(QAccessible::Value, txt); -} - QT_END_NAMESPACE #endif // QT_NO_ACCESSIBILITY diff --git a/src/gui/accessible/qaccessible2.h b/src/gui/accessible/qaccessible2.h index 922fb73b7d..91f6b73f3e 100644 --- a/src/gui/accessible/qaccessible2.h +++ b/src/gui/accessible/qaccessible2.h @@ -97,30 +97,9 @@ class Q_GUI_EXPORT QAccessibleEditableTextInterface public: virtual ~QAccessibleEditableTextInterface() {} - virtual void copyText(int startOffset, int endOffset) const = 0; virtual void deleteText(int startOffset, int endOffset) = 0; virtual void insertText(int offset, const QString &text) = 0; - virtual void cutText(int startOffset, int endOffset) = 0; - virtual void pasteText(int offset) = 0; virtual void replaceText(int startOffset, int endOffset, const QString &text) = 0; - virtual void setAttributes(int startOffset, int endOffset, const QString &attributes) = 0; -}; - -class Q_GUI_EXPORT QAccessibleSimpleEditableTextInterface: public QAccessibleEditableTextInterface -{ -public: - explicit QAccessibleSimpleEditableTextInterface(QAccessibleInterface *accessibleInterface); //### - - void copyText(int startOffset, int endOffset) const; - void deleteText(int startOffset, int endOffset); - void insertText(int offset, const QString &text); - void cutText(int startOffset, int endOffset); - void pasteText(int offset); - void replaceText(int startOffset, int endOffset, const QString &text); - inline void setAttributes(int, int, const QString &) {} - -private: - QAccessibleInterface *iface; }; class Q_GUI_EXPORT QAccessibleValueInterface diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp index a002b8bf26..f6ec940b58 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.cpp +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.cpp @@ -142,12 +142,20 @@ void QAccessibleTextEdit::setText(QAccessible::Text t, const QString &text) textEdit()->setText(text); } +QAccessible::State QAccessibleTextEdit::state() const +{ + QAccessible::State st = QAccessibleWidget::state(); + if (textEdit()->isReadOnly()) + st.readOnly = true; + else + st.editable = true; + return st; +} + void *QAccessibleTextEdit::interface_cast(QAccessible::InterfaceType t) { if (t == QAccessible::TextInterface) return static_cast<QAccessibleTextInterface*>(this); - else if (t == QAccessible::EditableTextInterface) - return static_cast<QAccessibleEditableTextInterface*>(this); return QAccessibleWidget::interface_cast(t); } @@ -467,24 +475,9 @@ static QTextCursor cursorForRange(QTextEdit *textEdit, int startOffset, int endO QTextCursor cursor(textEdit->document()); cursor.setPosition(startOffset, QTextCursor::MoveAnchor); cursor.setPosition(endOffset, QTextCursor::KeepAnchor); - return cursor; } -void QAccessibleTextEdit::copyText(int startOffset, int endOffset) const -{ -#ifndef QT_NO_CLIPBOARD - QTextCursor previousCursor = textEdit()->textCursor(); - QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset); - - if (!cursor.hasSelection()) - return; - - textEdit()->setTextCursor(cursor); - textEdit()->copy(); - textEdit()->setTextCursor(previousCursor); -#endif -} void QAccessibleTextEdit::deleteText(int startOffset, int endOffset) { @@ -501,34 +494,6 @@ void QAccessibleTextEdit::insertText(int offset, const QString &text) cursor.insertText(text); } -void QAccessibleTextEdit::cutText(int startOffset, int endOffset) -{ -#ifndef QT_NO_CLIPBOARD - QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset); - - if (!cursor.hasSelection()) - return; - - textEdit()->setTextCursor(cursor); - textEdit()->cut(); -#endif -} - -void QAccessibleTextEdit::pasteText(int offset) -{ - QTextEdit *edit = textEdit(); - - QTextCursor oldCursor = edit->textCursor(); - QTextCursor newCursor = oldCursor; - newCursor.setPosition(offset); - - edit->setTextCursor(newCursor); -#ifndef QT_NO_CLIPBOARD - edit->paste(); -#endif - edit->setTextCursor(oldCursor); -} - void QAccessibleTextEdit::replaceText(int startOffset, int endOffset, const QString &text) { QTextCursor cursor = cursorForRange(textEdit(), startOffset, endOffset); @@ -537,13 +502,6 @@ void QAccessibleTextEdit::replaceText(int startOffset, int endOffset, const QStr cursor.insertText(text); } -void QAccessibleTextEdit::setAttributes(int startOffset, int endOffset, const QString &attributes) -{ - // TODO - Q_UNUSED(startOffset); - Q_UNUSED(endOffset); - Q_UNUSED(attributes); -} #endif // QT_NO_TEXTEDIT #ifndef QT_NO_STACKEDWIDGET diff --git a/src/plugins/accessible/widgets/qaccessiblewidgets.h b/src/plugins/accessible/widgets/qaccessiblewidgets.h index 79ac5ae7b5..dba645570a 100644 --- a/src/plugins/accessible/widgets/qaccessiblewidgets.h +++ b/src/plugins/accessible/widgets/qaccessiblewidgets.h @@ -73,6 +73,7 @@ public: QString text(QAccessible::Text t) const; void setText(QAccessible::Text t, const QString &text); + QAccessible::State state() const; void *interface_cast(QAccessible::InterfaceType t); @@ -98,13 +99,9 @@ public: void scrollToSubstring(int startIndex, int endIndex); // QAccessibleEditableTextInterface - void copyText(int startOffset, int endOffset) const; void deleteText(int startOffset, int endOffset); void insertText(int offset, const QString &text); - void cutText(int startOffset, int endOffset); - void pasteText(int offset); void replaceText(int startOffset, int endOffset, const QString &text); - void setAttributes(int startOffset, int endOffset, const QString &attributes); protected: QTextEdit *textEdit() const; diff --git a/src/plugins/accessible/widgets/simplewidgets.cpp b/src/plugins/accessible/widgets/simplewidgets.cpp index 0fa6dc9990..cc10f598f6 100644 --- a/src/plugins/accessible/widgets/simplewidgets.cpp +++ b/src/plugins/accessible/widgets/simplewidgets.cpp @@ -575,7 +575,7 @@ QStringList QAccessibleGroupBox::keyBindingsForAction(const QString &) const \a name is propagated to the QAccessibleWidget constructor. */ QAccessibleLineEdit::QAccessibleLineEdit(QWidget *w, const QString &name) -: QAccessibleWidget(w, QAccessible::EditableText, name), QAccessibleSimpleEditableTextInterface(this) +: QAccessibleWidget(w, QAccessible::EditableText, name) { addControllingSignal(QLatin1String("textChanged(const QString&)")); addControllingSignal(QLatin1String("returnPressed()")); @@ -626,6 +626,9 @@ QAccessible::State QAccessibleLineEdit::state() const QLineEdit *l = lineEdit(); if (l->isReadOnly()) state.readOnly = true; + else + state.editable = true; + if (l->echoMode() != QLineEdit::Normal) state.passwordEdit = true; state.selectable = true; @@ -643,8 +646,6 @@ void *QAccessibleLineEdit::interface_cast(QAccessible::InterfaceType t) { if (t == QAccessible::TextInterface) return static_cast<QAccessibleTextInterface*>(this); - else if (t == QAccessible::EditableTextInterface) - return static_cast<QAccessibleEditableTextInterface*>(this); return QAccessibleWidget::interface_cast(t); } diff --git a/src/plugins/accessible/widgets/simplewidgets.h b/src/plugins/accessible/widgets/simplewidgets.h index 74c1da405d..baded3d76b 100644 --- a/src/plugins/accessible/widgets/simplewidgets.h +++ b/src/plugins/accessible/widgets/simplewidgets.h @@ -137,8 +137,7 @@ private: #endif #ifndef QT_NO_LINEEDIT -class QAccessibleLineEdit : public QAccessibleWidget, public QAccessibleTextInterface, - public QAccessibleSimpleEditableTextInterface +class QAccessibleLineEdit : public QAccessibleWidget, public QAccessibleTextInterface { public: explicit QAccessibleLineEdit(QWidget *o, const QString &name = QString()); diff --git a/src/plugins/platforms/windows/accessible/comutils.h b/src/plugins/platforms/windows/accessible/comutils.h index 4d8e603899..40b89ed991 100644 --- a/src/plugins/platforms/windows/accessible/comutils.h +++ b/src/plugins/platforms/windows/accessible/comutils.h @@ -54,6 +54,11 @@ class QVariant; bool QVariantToVARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out); +inline QString BSTRToQString(const BSTR &bstr) +{ + return QString((QChar*)bstr); +} + inline BSTR QStringToBSTR(const QString &str) { return SysAllocStringLen((OLECHAR*)str.unicode(), str.length()); diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 71a26aff6b..5a82936a03 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -45,6 +45,7 @@ #include "qwindowsaccessibility.h" #include <QtGui/qaccessible2.h> +#include <QtGui/qclipboard.h> #include <QtWidgets/qapplication.h> #include <QtCore/qdebug.h> @@ -241,9 +242,11 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI } else if (id == IID_IAccessibleComponent) { *iface = (IAccessibleComponent*)this; } else if (id == IID_IAccessibleEditableText) { - //if (accessible->editableTextInterface()) { - //*iface = (IAccessibleEditableText*)this; - //} + if (accessible->editableTextInterface() || + accessible->role() == QAccessible::EditableText) + { + *iface = (IAccessibleEditableText*)this; + } } else if (id == IID_IAccessibleHyperlink) { //*iface = (IAccessibleHyperlink*)this; } else if (id == IID_IAccessibleHypertext) { @@ -673,6 +676,126 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *backgr } /**************************************************************\ + * IAccessibleEditableText * + **************************************************************/ +#ifndef QT_NO_CLIPBOARD +/*! + \internal + + if \a endOffset == -1 it means end of the text +*/ +QString QWindowsIA2Accessible::textForRange(int startOffset, int endOffset) const +{ + if (QAccessibleTextInterface *textIface = accessible->textInterface()) { + if (endOffset == IA2_TEXT_OFFSET_LENGTH) + endOffset = textIface->characterCount(); + return textIface->text(startOffset, endOffset); + } + QString txt = accessible->text(QAccessible::Value); + if (endOffset == IA2_TEXT_OFFSET_LENGTH) + endOffset = txt.length(); + return txt.mid(startOffset, endOffset - startOffset); +} +#endif + +/*! + \internal +*/ +void QWindowsIA2Accessible::replaceTextFallback(long startOffset, long endOffset, const QString &txt) +{ + QString t = textForRange(0, -1); + if (endOffset == IA2_TEXT_OFFSET_LENGTH) + endOffset = t.length(); + if (endOffset - startOffset == 0) { + t.insert(startOffset, txt); + } else { + t.replace(startOffset, endOffset - startOffset, txt); + } + accessible->setText(QAccessible::Value, t); +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::copyText(long startOffset, long endOffset) +{ + accessibleDebugClientCalls(accessible); +#ifndef QT_NO_CLIPBOARD + const QString t = textForRange(startOffset, endOffset); + QGuiApplication::clipboard()->setText(t); + return S_OK; +#else + return E_NOTIMPL; +#endif +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::deleteText(long startOffset, long endOffset) +{ + accessibleDebugClientCalls(accessible); + if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) + editableTextIface->deleteText(startOffset, endOffset); + else + replaceTextFallback(startOffset, endOffset, QString()); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::insertText(long offset, BSTR *text) +{ + accessibleDebugClientCalls(accessible); + const QString txt(BSTRToQString(*text)); + if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) + editableTextIface->insertText(offset, txt); + else + replaceTextFallback(offset, offset, txt); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::cutText(long startOffset, long endOffset) +{ + accessibleDebugClientCalls(accessible); +#ifndef QT_NO_CLIPBOARD + const QString t = textForRange(startOffset, endOffset); + if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) + editableTextIface->deleteText(startOffset, endOffset); + else + replaceTextFallback(startOffset, endOffset, QString()); + QGuiApplication::clipboard()->setText(t); + return S_OK; +#else + return E_NOTIMPL; +#endif +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::pasteText(long offset) +{ + accessibleDebugClientCalls(accessible); +#ifndef QT_NO_CLIPBOARD + const QString txt = QGuiApplication::clipboard()->text(); + if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) + editableTextIface->insertText(offset, txt); + else + replaceTextFallback(offset, offset, txt); + return S_OK; +#else + return E_NOTIMPL; +#endif +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::replaceText(long startOffset, long endOffset, BSTR *text) +{ + accessibleDebugClientCalls(accessible); + const QString txt(BSTRToQString(*text)); + if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) + editableTextIface->replaceText(startOffset, endOffset, txt); + else + replaceTextFallback(startOffset, endOffset, txt); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::setAttributes(long /*startOffset*/, long /*endOffset*/, BSTR * /*attributes*/) +{ + return E_NOTIMPL; +} + + +/**************************************************************\ * IAccessibleTable2 * **************************************************************/ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_cellAt( long row, long column, IUnknown **cell) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index 0f9d3b3c41..bfd9031e88 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -73,7 +73,7 @@ QT_BEGIN_NAMESPACE class QWindowsIA2Accessible : public QWindowsMsaaAccessible, public IAccessibleAction, public IAccessibleComponent, - /*public IAccessibleEditableText,*/ + public IAccessibleEditableText, public IAccessibleTable2, public IAccessibleTableCell, public IAccessibleText, @@ -122,7 +122,6 @@ public: 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); @@ -130,7 +129,6 @@ public: 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); @@ -265,6 +263,8 @@ private: HRESULT wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount); uint uniqueID() const; QByteArray IIDToString(REFIID id); + QString textForRange(int startOffset, int endOffset) const; + void replaceTextFallback(long startOffset, long endOffset, const QString &txt); }; diff --git a/tests/auto/other/qaccessibility/qaccessibility.pro b/tests/auto/other/qaccessibility/qaccessibility.pro index 0c224ad0a8..ac8b6c87a8 100644 --- a/tests/auto/other/qaccessibility/qaccessibility.pro +++ b/tests/auto/other/qaccessibility/qaccessibility.pro @@ -13,6 +13,9 @@ wince*: { } win32 { - !*g++: include(../../../../src/3rdparty/iaccessible2/iaccessible2.pri) + !*g++ { + include(../../../../src/3rdparty/iaccessible2/iaccessible2.pri) + DEFINES += QT_SUPPORTS_IACCESSIBLE2 + } LIBS += -loleacc -loleaut32 -lole32 } diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 2a4013347e..df7588465d 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -46,16 +46,19 @@ # include <oleacc.h> # include <servprov.h> # include <winuser.h> -# ifndef Q_CC_MINGW +# 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 @@ -1560,12 +1563,6 @@ void tst_QAccessibility::textEditTest() QCOMPARE(iface->textInterface()->characterRect(5).size(), QSize(fm.width(" "), fm.height())); QCOMPARE(iface->textInterface()->characterRect(6).size(), QSize(fm.width("w"), fm.height())); - iface->editableTextInterface()->copyText(6, 11); - QCOMPARE(QApplication::clipboard()->text(), QLatin1String("world")); - iface->editableTextInterface()->cutText(12, 16); - QCOMPARE(QApplication::clipboard()->text(), QLatin1String("how ")); - QCOMPARE(iface->textInterface()->text(12, 15), QLatin1String("are")); - QTestAccessibility::clearEvents(); // select text @@ -2922,6 +2919,28 @@ 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. @@ -2931,27 +2950,31 @@ void tst_QAccessibility::bridgeTest() QWidget *window = new QWidget; QVBoxLayout *lay = new QVBoxLayout(window); QPushButton *button = new QPushButton(tr("Push me"), window); - QLineEdit *le = new QLineEdit(window); + QTextEdit *te = new QTextEdit(window); + te->setText(QLatin1String("hello world\nhow are you today?\n")); lay->addWidget(button); - lay->addWidget(le); + lay->addWidget(te); window->show(); QTest::qWaitForWindowShown(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 *iacc; + IAccessible *iaccButton; VARIANT varChild; - HRESULT hr = ::AccessibleObjectFromPoint(pt, &iacc, &varChild); + HRESULT hr = ::AccessibleObjectFromPoint(pt, &iaccButton, &varChild); QVERIFY(SUCCEEDED(hr)); VARIANT varSELF; varSELF.vt = VT_I4; @@ -2959,7 +2982,7 @@ void tst_QAccessibility::bridgeTest() // **** Test get_accRole **** VARIANT varRole; - hr = iacc->get_accRole(varSELF, &varRole); + hr = iaccButton->get_accRole(varSELF, &varRole); QVERIFY(SUCCEEDED(hr)); QCOMPARE(varRole.vt, (VARTYPE)VT_I4); @@ -2967,52 +2990,106 @@ void tst_QAccessibility::bridgeTest() // **** Test accLocation **** long x, y, w, h; - hr = iacc->accLocation(&x, &y, &w, &h, varSELF); + hr = iaccButton->accLocation(&x, &y, &w, &h, varSELF); QCOMPARE(buttonRect, QRect(x, y, w, h)); -#ifndef Q_CC_MINGW +#ifdef QT_SUPPORTS_IACCESSIBLE2 // 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. + 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(); - /***** 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(); + /************************************************** + * 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 - iacc->Release(); + iaccTextEdit->Release(); + + iaccWindow->Release(); QTestAccessibility::clearEvents(); #endif } |