void tst_QQuickAccessible::hitTest() { QQuickView *window = new QQuickView; window->setSource(testFileUrl("hittest.qml")); window->show(); QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(window); QVERIFY(windowIface); QAccessibleInterface *rootItem = windowIface->child(0); QRect rootRect = rootItem->rect(); // check the root item from app QAccessibleInterface *appIface = QAccessible::queryAccessibleInterface(qApp); QVERIFY(appIface); QAccessibleInterface *itemHit = appIface->childAt(rootRect.x() + 200, rootRect.y() + 50); QVERIFY(itemHit); QCOMPARE(itemHit->rect(), rootRect); QAccessibleInterface *rootItemIface; for (int c = 0; c < rootItem->childCount(); ++c) { QAccessibleInterface *iface = rootItem->child(c); QString name = iface->text(QAccessible::Name); if (name == QLatin1String("rect1")) { // hit rect1 QAccessibleInterface *rect1 = iface; QRect rect1Rect = rect1->rect(); QAccessibleInterface *rootItemIface = rootItem->childAt(rect1Rect.x() + 10, rect1Rect.y() + 10); QVERIFY(rootItemIface); QCOMPARE(rect1Rect, rootItemIface->rect()); QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect1")); // should also work from top level (app) QAccessibleInterface *app(QAccessible::queryAccessibleInterface(qApp)); QAccessibleInterface *itemHit2(topLevelChildAt(app, rect1Rect.x() + 10, rect1Rect.y() + 10)); QVERIFY(itemHit2); QCOMPARE(itemHit2->rect(), rect1Rect); QCOMPARE(itemHit2->text(QAccessible::Name), QLatin1String("rect1")); } else if (name == QLatin1String("rect2")) { QAccessibleInterface *rect2 = iface; // FIXME: This is seems broken on OS X // QCOMPARE(rect2->rect().translated(rootItem->rect().x(), rootItem->rect().y()), QRect(0, 50, 100, 100)); QAccessibleInterface *rect20 = rect2->child(0); QVERIFY(rect20); QCOMPARE(rect20->text(QAccessible::Name), QLatin1String("rect20")); QPoint p = rect20->rect().bottomRight() + QPoint(20, 20); QAccessibleInterface *rect201 = rect20->childAt(p.x(), p.y()); QVERIFY(rect201); QCOMPARE(rect201->text(QAccessible::Name), QLatin1String("rect201")); rootItemIface = topLevelChildAt(windowIface, p.x(), p.y()); QVERIFY(rootItemIface); QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect201")); } } delete window; QTestAccessibility::clearEvents(); }
void tst_QQuickAccessible::hitTest() { QQuickView *window = new QQuickView; window->setSource(testFileUrl("hittest.qml")); window->show(); QAccessibleInterface *windowIface = QAccessible::queryAccessibleInterface(window); QVERIFY(windowIface); QAccessibleInterface *rootItem = windowIface->child(0); QRect rootRect = rootItem->rect(); // check the root item from app QAccessibleInterface *appIface = QAccessible::queryAccessibleInterface(qApp); QVERIFY(appIface); QAccessibleInterface *itemHit(appIface->childAt(rootRect.x() + 200, rootRect.y() + 50)); QVERIFY(itemHit); QCOMPARE(rootRect, itemHit->rect()); // hit rect1 QAccessibleInterface *rect1(rootItem->child(0)); QRect rect1Rect = rect1->rect(); QAccessibleInterface *rootItemIface = rootItem->childAt(rect1Rect.x() + 10, rect1Rect.y() + 10); QVERIFY(rootItemIface); QCOMPARE(rect1Rect, rootItemIface->rect()); QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect1")); // should also work from top level (app) QAccessibleInterface *app(QAccessible::queryAccessibleInterface(qApp)); QAccessibleInterface *itemHit2(topLevelChildAt(app, rect1Rect.x() + 10, rect1Rect.y() + 10)); QVERIFY(itemHit2); QCOMPARE(itemHit2->rect(), rect1Rect); QCOMPARE(itemHit2->text(QAccessible::Name), QLatin1String("rect1")); // hit rect201 QAccessibleInterface *rect2(rootItem->child(1)); QVERIFY(rect2); // FIXME: This is seems broken on mac // QCOMPARE(rect2->rect().translated(rootItem->rect().x(), rootItem->rect().y()), QRect(0, 50, 100, 100)); QAccessibleInterface *rect20(rect2->child(0)); QVERIFY(rect20); QAccessibleInterface *rect201(rect20->child(1)); QVERIFY(rect201); QRect rect201Rect = rect201->rect(); rootItemIface = windowIface->childAt(rect201Rect.x() + 20, rect201Rect.y() + 20); QVERIFY(rootItemIface); QCOMPARE(rootItemIface->rect(), rect201Rect); QCOMPARE(rootItemIface->text(QAccessible::Name), QLatin1String("rect201")); delete window; QTestAccessibility::clearEvents(); }
void tst_QQuickAccessible::basicPropertiesTest() { QAccessibleInterface *app = QAccessible::queryAccessibleInterface(qApp); QCOMPARE(app->childCount(), 0); QQuickView *window = new QQuickView(); window->setSource(testFileUrl("statictext.qml")); window->show(); QCOMPARE(app->childCount(), 1); QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window); QVERIFY(iface); QCOMPARE(iface->childCount(), 1); QAccessibleInterface *item = iface->child(0); QVERIFY(item); QCOMPARE(item->childCount(), 2); QCOMPARE(item->rect().size(), QSize(400, 400)); QCOMPARE(item->role(), QAccessible::Client); QCOMPARE(iface->indexOfChild(item), 0); QAccessibleInterface *text = item->child(0); QVERIFY(text); QCOMPARE(text->childCount(), 0); QCOMPARE(text->text(QAccessible::Name), QLatin1String("Hello Accessibility")); QCOMPARE(text->rect().size(), QSize(200, 50)); QCOMPARE(text->rect().x(), item->rect().x() + 100); QCOMPARE(text->rect().y(), item->rect().y() + 20); QCOMPARE(text->role(), QAccessible::StaticText); QCOMPARE(item->indexOfChild(text), 0); QAccessibleInterface *text2 = item->child(1); QVERIFY(text2); QCOMPARE(text2->childCount(), 0); QCOMPARE(text2->text(QAccessible::Name), QLatin1String("The Hello 2 accessible text")); QCOMPARE(text2->rect().size(), QSize(100, 40)); QCOMPARE(text2->rect().x(), item->rect().x() + 100); QCOMPARE(text2->rect().y(), item->rect().y() + 40); QCOMPARE(text2->role(), QAccessible::StaticText); QCOMPARE(item->indexOfChild(text2), 1); QCOMPARE(iface->indexOfChild(text2), -1); QCOMPARE(text2->indexOfChild(item), -1); delete window; QTestAccessibility::clearEvents(); }
/* IAccessible IAccessible::accHitTest documents the value returned in pvarID like this: | *Point location* | *vt member* | *Value member* | +========================================================+=============+=========================+ | Outside of the object's boundaries, and either inside | VT_EMPTY | None. | | or outside of the object's bounding rectangle. | | | +--------------------------------------------------------+-------------+-------------------------+ | Within the object but not within a child element or a | VT_I4 | lVal is CHILDID_SELF | | child object. | | | +--------------------------------------------------------+-------------+-------------------------+ | Within a child element. | VT_I4 | lVal contains | | | | the child ID. | +--------------------------------------------------------+-------------+-------------------------+ | Within a child object. | VT_DISPATCH | pdispVal is set to the | | | | child object's IDispatch| | | | interface pointer | +--------------------------------------------------------+-------------+-------------------------+ */ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (!accessible) return E_FAIL; QAccessibleInterface *child = accessible->childAt(xLeft, yTop); if (child == 0) { // no child found, return this item if it contains the coordinates if (accessible->rect().contains(xLeft, yTop)) { (*pvarID).vt = VT_I4; (*pvarID).lVal = CHILDID_SELF; return S_OK; } } else { IAccessible *iface = QWindowsAccessibility::wrap(child); if (iface) { (*pvarID).vt = VT_DISPATCH; (*pvarID).pdispVal = iface; return S_OK; } } // Did not find anything (*pvarID).vt = VT_EMPTY; return S_FALSE; }
/* IAccessible IAccessible::accHitTest documents the value returned in pvarID like this: | *Point location* | *vt member* | *Value member* | +========================================================+=============+=========================+ | Outside of the object's boundaries, and either inside | VT_EMPTY | None. | | or outside of the object's bounding rectangle. | | | +--------------------------------------------------------+-------------+-------------------------+ | Within the object but not within a child element or a | VT_I4 | lVal is CHILDID_SELF | | child object. | | | +--------------------------------------------------------+-------------+-------------------------+ | Within a child element. | VT_I4 | lVal contains | | | | the child ID. | +--------------------------------------------------------+-------------+-------------------------+ | Within a child object. | VT_DISPATCH | pdispVal is set to the | | | | child object's IDispatch| | | | interface pointer | +--------------------------------------------------------+-------------+-------------------------+ */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; QAccessibleInterface *child = accessible->childAt(xLeft, yTop); if (child == 0) { // no child found, return this item if it contains the coordinates if (accessible->rect().contains(xLeft, yTop)) { (*pvarID).vt = VT_I4; (*pvarID).lVal = CHILDID_SELF; return S_OK; } } else { QWindowsAccessible* wacc = new QWindowsAccessible(child); IDispatch *iface = 0; wacc->QueryInterface(IID_IDispatch, (void**)&iface); if (iface) { (*pvarID).vt = VT_DISPATCH; (*pvarID).pdispVal = iface; return S_OK; } } // Did not find anything (*pvarID).vt = VT_EMPTY; return S_FALSE; }
/* Test that the QSpinBox buttons are correctly positioned with the Mac style. */ void tst_MacGui::spinBoxArrowButtons() { ColorWidget colorWidget; colorWidget.resize(200, 200); QSpinBox spinBox(&colorWidget); QSpinBox spinBox2(&colorWidget); spinBox2.move(0, 100); colorWidget.show(); QTest::qWait(100); // Grab an unfocused spin box. const QImage noFocus = grabWindowContents(&colorWidget).toImage(); // Set focus by clicking the less button. QAccessibleInterface *lessInterface = wn.find(QAccessible::Name, "Less", &spinBox); QEXPECT_FAIL("", "QTBUG-26372", Abort); QVERIFY(lessInterface); const int delay = 500; clickLater(lessInterface, Qt::LeftButton, delay); const int timeout = 1; QTestEventLoop::instance().enterLoop(timeout); // Grab a focused spin box. const QImage focus = grabWindowContents(&colorWidget).toImage(); // Compare the arrow area of the less button to see if it moved. const QRect lessRect = lessInterface->rect(); const QRect lessLocalRect(colorWidget.mapFromGlobal(lessRect.topLeft()), colorWidget.mapFromGlobal(lessRect.bottomRight())); const QRect compareRect = lessLocalRect.adjusted(5, 3, -5, -7); QVERIFY(noFocus.copy(compareRect) == focus.copy(compareRect)); }
/*! \reimp */ QAccessibleInterface *QAccessibleObject::childAt(int x, int y) const { for (int i = 0; i < childCount(); ++i) { QAccessibleInterface *childIface = child(i); Q_ASSERT(childIface); if (childIface->isValid() && childIface->rect().contains(x,y)) return childIface; } return 0; }
QAccessibleInterface *BrowserAccessibilityQt::childAt(int x, int y) const { for (int i = 0; i < childCount(); ++i) { QAccessibleInterface *childIface = child(i); Q_ASSERT(childIface); if (childIface->rect().contains(x,y)) return childIface; } return 0; }
QAccessibleInterface *QAccessibleMenuItem::childAt(int x, int y ) const { for (int i = childCount(); i >= 0; --i) { QAccessibleInterface *childInterface = child(i); if (childInterface->rect().contains(x,y)) { return childInterface; } delete childInterface; } return 0; }
static jobject screenRect(JNIEnv *env, jobject /*thiz*/, jint objectId) { QRect rect; QAccessibleInterface *iface = interfaceFromId(objectId); if (iface && iface->isValid()) { rect = iface->rect(); } jclass rectClass = env->FindClass("android/graphics/Rect"); jmethodID ctor = env->GetMethodID(rectClass, "<init>", "(IIII)V"); jobject jrect = env->NewObject(rectClass, ctor, rect.left(), rect.top(), rect.right(), rect.bottom()); return jrect; }
// moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (!accessible) return E_FAIL; QAccessibleInterface *acc = childPointer(accessible, varID); if (!acc || !acc->isValid()) return E_FAIL; const QRect rect = acc->rect(); *pxLeft = rect.x(); *pyTop = rect.y(); *pcxWidth = rect.width(); *pcyHeight = rect.height(); return S_OK; }
QAccessibleInterface *QQmlAccessible::childAt(int x, int y) const { // Note that this function will disregard stacking order. // (QAccessibleQuickView::childAt() does this correctly and more efficient) // If the item clips its children, we can return early if the coordinate is outside its rect if (clipsChildren()) { if (!rect().contains(x, y)) return 0; } for (int i = childCount() - 1; i >= 0; --i) { QAccessibleInterface *childIface = child(i); if (childIface && !childIface->state().invisible) { if (childIface->rect().contains(x, y)) return childIface; } } return 0; }
// moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; QRect rect; if (varID.lVal) { QAIPointer child = QAIPointer(accessible->child(varID.lVal - 1)); if (child->isValid()) rect = child->rect(); } else { rect = accessible->rect(); } *pxLeft = rect.x(); *pyTop = rect.y(); *pcxWidth = rect.width(); *pcyHeight = rect.height(); return S_OK; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varID) { #ifdef DEBUG_SHOW_ATCLIENT_COMMANDS showDebug(__FUNCTION__, accessible); #endif //DEBUG_SHOW_ATCLIENT_COMMANDS if (!accessible->isValid()) return E_FAIL; QRect rect = accessible->rect(varID.lVal); if (rect.isValid()) { *pxLeft = rect.x(); *pyTop = rect.y(); *pcxWidth = rect.width(); *pcyHeight = rect.height(); } else { *pxLeft = 0; *pyTop = 0; *pcxWidth = 0; *pcyHeight = 0; } return S_OK; }
// moz: [important, but no need to implement up/down/left/right] HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; QAccessibleInterface *acc = 0; switch (navDir) { case NAVDIR_FIRSTCHILD: acc = accessible->child(0); break; case NAVDIR_LASTCHILD: acc = accessible->child(accessible->childCount() - 1); break; case NAVDIR_NEXT: case NAVDIR_PREVIOUS: if (!varStart.lVal){ QAccessibleInterface *parent = accessible->parent(); if (parent) { int index = parent->indexOfChild(accessible); index += (navDir == NAVDIR_NEXT) ? 1 : -1; if (index >= 0 && index < parent->childCount()) acc = parent->child(index); delete parent; } } else { int index = varStart.lVal; index += (navDir == NAVDIR_NEXT) ? 1 : -1; if (index > 0 && index <= accessible->childCount()) acc = accessible->child(index - 1); } break; // Geometrical case NAVDIR_UP: case NAVDIR_DOWN: case NAVDIR_LEFT: case NAVDIR_RIGHT: if (QAccessibleInterface *pIface = accessible->parent()) { QRect startg = accessible->rect(); QPoint startc = startg.center(); QAccessibleInterface *candidate = 0; unsigned mindist = UINT_MAX; // will work on screen sizes at least up to 46340x46340 const int sibCount = pIface->childCount(); for (int i = 0; i < sibCount; ++i) { QAccessibleInterface *sibling = 0; sibling = pIface->child(i); Q_ASSERT(sibling); if ((accessible->relationTo(sibling) & QAccessible::Self) || sibling->state().invisible) { //ignore ourself and invisible siblings delete sibling; continue; } QRect sibg = sibling->rect(); QPoint sibc = sibg.center(); QPoint sibp; QPoint startp; QPoint distp; switch (navDir) { case NAVDIR_LEFT: startp = QPoint(startg.left(), startg.top() + startg.height() / 2); sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2); if (QPoint(sibc - startc).x() >= 0) { delete sibling; continue; } distp = sibp - startp; break; case NAVDIR_RIGHT: startp = QPoint(startg.right(), startg.top() + startg.height() / 2); sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2); if (QPoint(sibc - startc).x() <= 0) { delete sibling; continue; } distp = sibp - startp; break; case NAVDIR_UP: startp = QPoint(startg.left() + startg.width() / 2, startg.top()); sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom()); if (QPoint(sibc - startc).y() >= 0) { delete sibling; continue; } distp = sibp - startp; break; case NAVDIR_DOWN: startp = QPoint(startg.left() + startg.width() / 2, startg.bottom()); sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top()); if (QPoint(sibc - startc).y() <= 0) { delete sibling; continue; } distp = sibp - startp; break; default: break; } // Since we're *comparing* (and not measuring) distances, we can compare the // squared distance, (thus, no need to take the sqrt()). unsigned dist = distp.x() * distp.x() + distp.y() * distp.y(); if (dist < mindist) { delete candidate; candidate = sibling; mindist = dist; } else { delete sibling; } } delete pIface; acc = candidate; } break; default: break; } if (!acc) { (*pvarEnd).vt = VT_EMPTY; return S_FALSE; } QWindowsAccessible* wacc = new QWindowsAccessible(acc); IDispatch *iface = 0; wacc->QueryInterface(IID_IDispatch, (void**)&iface); if (iface) { (*pvarEnd).vt = VT_DISPATCH; (*pvarEnd).pdispVal = iface; return S_OK; } else { delete wacc; } (*pvarEnd).vt = VT_EMPTY; return S_FALSE; }
/*! \reimp */ QAccessible::Relation QAccessibleWidget::relationTo(int child, const QAccessibleInterface *other, int otherChild) const { Relation relation = Unrelated; if (d->asking == this) // recursive call return relation; QObject *o = other ? other->object() : 0; if (!o) return relation; QWidget *focus = widget()->focusWidget(); if (object() == focus && isAncestor(o, focus)) relation |= FocusChild; QACConnectionObject *connectionObject = (QACConnectionObject*)object(); for (int sig = 0; sig < d->primarySignals.count(); ++sig) { if (connectionObject->isSender(o, d->primarySignals.at(sig).toAscii())) { relation |= Controller; break; } } // test for passive relationships. // d->asking protects from endless recursion. d->asking = this; int inverse = other->relationTo(otherChild, this, child); d->asking = 0; if (inverse & Controller) relation |= Controlled; if (inverse & Label) relation |= Labelled; if(o == object()) { if (child && !otherChild) return relation | Child; if (!child && otherChild) return relation | Ancestor; if (!child && !otherChild) return relation | Self; } QObject *parent = object()->parent(); if (o == parent) return relation | Child; if (o->parent() == parent) { relation |= Sibling; QAccessibleInterface *sibIface = QAccessible::queryAccessibleInterface(o); Q_ASSERT(sibIface); QRect wg = rect(0); QRect sg = sibIface->rect(0); if (wg.intersects(sg)) { QAccessibleInterface *pIface = 0; sibIface->navigate(Ancestor, 1, &pIface); if (pIface && !((sibIface->state(0) | state(0)) & Invisible)) { int wi = pIface->indexOfChild(this); int si = pIface->indexOfChild(sibIface); if (wi > si) relation |= QAccessible::Covers; else relation |= QAccessible::Covered; } delete pIface; } else { QPoint wc = wg.center(); QPoint sc = sg.center(); if (wc.x() < sc.x()) relation |= QAccessible::Left; else if(wc.x() > sc.x()) relation |= QAccessible::Right; if (wc.y() < sc.y()) relation |= QAccessible::Up; else if (wc.y() > sc.y()) relation |= QAccessible::Down; } delete sibIface; return relation; } if (isAncestor(o, object())) return relation | Descendent; if (isAncestor(object(), o)) return relation | Ancestor; return relation; }
/*! \reimp */ int QAccessibleWidget::navigate(RelationFlag relation, int entry, QAccessibleInterface **target) const { if (!target) return -1; *target = 0; QObject *targetObject = 0; QWidgetList childList = childWidgets(widget()); bool complexWidget = childList.size() < childCount(); switch (relation) { // Hierarchical case Self: targetObject = object(); break; case Child: if (complexWidget) { if (entry > 0 && entry <= childCount()) return entry; return -1; }else { if (entry > 0 && childList.size() >= entry) targetObject = childList.at(entry - 1); } break; case Ancestor: { if (entry <= 0) return -1; targetObject = widget()->parentWidget(); int i; for (i = entry; i > 1 && targetObject; --i) targetObject = targetObject->parent(); if (!targetObject && i == 1) targetObject = qApp; } break; case Sibling: { QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(parentObject()); if (!iface) return -1; iface->navigate(Child, entry, target); delete iface; if (*target) return 0; } break; // Geometrical case QAccessible::Left: if (complexWidget && entry) { if (entry < 2 || widget()->height() > widget()->width() + 20) // looks vertical return -1; return entry - 1; } // fall through case QAccessible::Right: if (complexWidget && entry) { if (entry >= childCount() || widget()->height() > widget()->width() + 20) // looks vertical return -1; return entry + 1; } // fall through case QAccessible::Up: if (complexWidget && entry) { if (entry < 2 || widget()->width() > widget()->height() + 20) // looks horizontal return - 1; return entry - 1; } // fall through case QAccessible::Down: if (complexWidget && entry) { if (entry >= childCount() || widget()->width() > widget()->height() + 20) // looks horizontal return - 1; return entry + 1; } else { QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject()); if (!pIface) return -1; QRect startg = rect(0); QPoint startc = startg.center(); QAccessibleInterface *candidate = 0; int mindist = 100000; int sibCount = pIface->childCount(); for (int i = 0; i < sibCount; ++i) { QAccessibleInterface *sibling = 0; pIface->navigate(Child, i+1, &sibling); Q_ASSERT(sibling); if ((relationTo(0, sibling, 0) & Self) || (sibling->state(0) & QAccessible::Invisible)) { //ignore ourself and invisible siblings delete sibling; continue; } QRect sibg = sibling->rect(0); QPoint sibc = sibg.center(); QPoint sibp; QPoint startp; QPoint distp; switch (relation) { case QAccessible::Left: startp = QPoint(startg.left(), startg.top() + startg.height() / 2); sibp = QPoint(sibg.right(), sibg.top() + sibg.height() / 2); if (QPoint(sibc - startc).x() >= 0) { delete sibling; continue; } distp = sibp - startp; break; case QAccessible::Right: startp = QPoint(startg.right(), startg.top() + startg.height() / 2); sibp = QPoint(sibg.left(), sibg.top() + sibg.height() / 2); if (QPoint(sibc - startc).x() <= 0) { delete sibling; continue; } distp = sibp - startp; break; case QAccessible::Up: startp = QPoint(startg.left() + startg.width() / 2, startg.top()); sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.bottom()); if (QPoint(sibc - startc).y() >= 0) { delete sibling; continue; } distp = sibp - startp; break; case QAccessible::Down: startp = QPoint(startg.left() + startg.width() / 2, startg.bottom()); sibp = QPoint(sibg.left() + sibg.width() / 2, sibg.top()); if (QPoint(sibc - startc).y() <= 0) { delete sibling; continue; } distp = sibp - startp; break; default: break; } int dist = (int)qSqrt((qreal)distp.x() * distp.x() + distp.y() * distp.y()); if (dist < mindist) { delete candidate; candidate = sibling; mindist = dist; } else { delete sibling; } } delete pIface; *target = candidate; if (*target) return 0; } break; case Covers: if (entry > 0) { QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject()); if (!pIface) return -1; QRect r = rect(0); int sibCount = pIface->childCount(); QAccessibleInterface *sibling = 0; for (int i = pIface->indexOfChild(this) + 1; i <= sibCount && entry; ++i) { pIface->navigate(Child, i, &sibling); if (!sibling || (sibling->state(0) & Invisible)) { delete sibling; sibling = 0; continue; } if (sibling->rect(0).intersects(r)) --entry; if (!entry) break; delete sibling; sibling = 0; } delete pIface; *target = sibling; if (*target) return 0; } break; case Covered: if (entry > 0) { QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject()); if (!pIface) return -1; QRect r = rect(0); int index = pIface->indexOfChild(this); QAccessibleInterface *sibling = 0; for (int i = 1; i < index && entry; ++i) { pIface->navigate(Child, i, &sibling); Q_ASSERT(sibling); if (!sibling || (sibling->state(0) & Invisible)) { delete sibling; sibling = 0; continue; } if (sibling->rect(0).intersects(r)) --entry; if (!entry) break; delete sibling; sibling = 0; } delete pIface; *target = sibling; if (*target) return 0; } break; // Logical case FocusChild: { if (widget()->hasFocus()) { targetObject = object(); break; } QWidget *fw = widget()->focusWidget(); if (!fw) return -1; if (isAncestor(widget(), fw) || fw == widget()) targetObject = fw; /* ### QWidget *parent = fw; while (parent && !targetObject) { parent = parent->parentWidget(); if (parent == widget()) targetObject = fw; } */ } break; case Label: if (entry > 0) { QAccessibleInterface *pIface = QAccessible::queryAccessibleInterface(parentObject()); if (!pIface) return -1; // first check for all siblings that are labels to us // ideally we would go through all objects and check, but that // will be too expensive int sibCount = pIface->childCount(); QAccessibleInterface *candidate = 0; for (int i = 0; i < sibCount && entry; ++i) { const int childId = pIface->navigate(Child, i+1, &candidate); Q_ASSERT(childId >= 0); if (childId > 0) candidate = pIface; if (candidate->relationTo(childId, this, 0) & Label) --entry; if (!entry) break; if (candidate != pIface) delete candidate; candidate = 0; } if (!candidate) { if (pIface->relationTo(0, this, 0) & Label) --entry; if (!entry) candidate = pIface; } if (pIface != candidate) delete pIface; *target = candidate; if (*target) return 0; } break; case Labelled: // only implemented in subclasses break; case Controller: if (entry > 0) { // check all senders we are connected to, // and figure out which one are controllers to us QACConnectionObject *connectionObject = (QACConnectionObject*)object(); QObjectList allSenders = connectionObject->senderList(); QObjectList senders; for (int s = 0; s < allSenders.size(); ++s) { QObject *sender = allSenders.at(s); QAccessibleInterface *candidate = QAccessible::queryAccessibleInterface(sender); if (!candidate) continue; if (candidate->relationTo(0, this, 0)&Controller) senders << sender; delete candidate; } if (entry <= senders.size()) targetObject = senders.at(entry-1); } break; case Controlled: if (entry > 0) { QObjectList allReceivers; QACConnectionObject *connectionObject = (QACConnectionObject*)object(); for (int sig = 0; sig < d->primarySignals.count(); ++sig) { QObjectList receivers = connectionObject->receiverList(d->primarySignals.at(sig).toAscii()); allReceivers += receivers; } if (entry <= allReceivers.size()) targetObject = allReceivers.at(entry-1); } break; default: break; } *target = QAccessible::queryAccessibleInterface(targetObject); return *target ? 0 : -1; }