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();
}
void tst_QQuickAccessible::ignoredTest()
{
    QScopedPointer<QQuickView> window(new QQuickView());
    window->setSource(testFileUrl("ignored.qml"));
    window->show();

    QQuickItem *contentItem = window->contentItem();
    QVERIFY(contentItem);
    QQuickItem *rootItem = contentItem->childItems().first();
    QVERIFY(rootItem);

    // the window becomes active
    QAccessible::State activatedChange;
    activatedChange.active = true;

    QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(window.data());
    QVERIFY(iface);
    QAccessibleInterface *rectangleA = iface->child(0);

    QCOMPARE(rectangleA->role(), QAccessible::StaticText);
    QCOMPARE(rectangleA->text(QAccessible::Name), QLatin1String("A"));
    static const char *expected = "BEFIHD";
    // check if node "C" and "G" is skipped and that the order is as expected.
    for (int i = 0; i < rectangleA->childCount(); ++i) {
        QAccessibleInterface *child = rectangleA->child(i);
        QCOMPARE(child->text(QAccessible::Name), QString(QLatin1Char(expected[i])));
    }
    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(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();
}
Example #4
0
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren)
{
    showDebug(__FUNCTION__, accessible);
    if (!accessible->isValid())
        return E_FAIL;

    *pcountChildren = accessible->childCount();
    return S_OK;
}
    static jintArray childIdListForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
    {
        QAccessibleInterface *iface = interfaceFromId(objectId);
        if (iface) {
            jintArray jArray = env->NewIntArray(jsize(iface->childCount()));
            for (int i = 0; i < iface->childCount(); ++i) {
                QAccessibleInterface *child = iface->child(i);
                if (child) {
                    QAccessible::Id ifaceId = QAccessible::uniqueId(child);
                    jint jid = ifaceId;
                    env->SetIntArrayRegion(jArray, i, 1, &jid);
                }
            }
            return jArray;
        }

        return env->NewIntArray(jsize(0));
    }
// moz: [important]
HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accChildCount(long* pcountChildren)
{
    QAccessibleInterface *accessible = accessibleInterface();
    accessibleDebugClientCalls(accessible);
    if (!accessible)
        return E_FAIL;

    *pcountChildren = accessible->childCount();
    return S_OK;
}
Example #7
0
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren)
{
#ifdef DEBUG_SHOW_ATCLIENT_COMMANDS
    showDebug(__FUNCTION__, accessible);
#endif //DEBUG_SHOW_ATCLIENT_COMMANDS
    if (!accessible->isValid())
        return E_FAIL;

    *pcountChildren = accessible->childCount();
    return S_OK;
}
Example #8
0
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren)
{
#ifdef DEBUG_SHOW_ATCLIENT_COMMANDS
    showDebug(__FUNCTION__, accessible);
#endif //DEBUG_SHOW_ATCLIENT_COMMANDS
    if (!accessible->isValid())
        return E_FAIL;

    int cc = accessible->childCount();
    QVector<int> sel(cc);
    int selIndex = 0;
    for (int i = 1; i <= cc; ++i) {
        QAccessibleInterface *child = 0;
        int i2 = accessible->navigate(Child, i, &child);
        bool isSelected = false;
        if (child) {
            isSelected = child->state(0) & Selected;
            delete child;
            child = 0;
        } else {
            isSelected = accessible->state(i2) & Selected;
        }
        if (isSelected)
            sel[selIndex++] = i;
    }
    sel.resize(selIndex);
    if (sel.isEmpty()) {
        (*pvarChildren).vt = VT_EMPTY;
        return S_FALSE;
    }
    if (sel.size() == 1) {
        (*pvarChildren).vt = VT_I4;
        (*pvarChildren).lVal = sel[0];
        return S_OK;
    }
    IEnumVARIANT *iface = new QWindowsEnumerate(sel);
    IUnknown *uiface;
    iface->QueryInterface(IID_IUnknown, (void**)&uiface);
    (*pvarChildren).vt = VT_UNKNOWN;
    (*pvarChildren).punkVal = uiface;

    return S_OK;
}
Example #9
0
/*
    Recursiveley navigates the accessible hiearchy looking for an interface that
    passsed the Test (meaning it returns true).
*/
QAccessibleInterface *WidgetNavigator::recursiveSearch(TestBase *test, QAccessibleInterface *iface)
{
    QStack<QAccessibleInterface *> todoInterfaces;
    todoInterfaces.push(iface);

    while (todoInterfaces.isEmpty() == false) {
        QAccessibleInterface *testInterface = todoInterfaces.pop();

        if ((*test)(testInterface))
            return testInterface;

        const int numChildren = testInterface->childCount();
        for (int i = 0; i < numChildren; ++i) {
            QAccessibleInterface *childInterface = testInterface->child(i);
            if (childInterface) {
                todoInterfaces.push(childInterface);
            }
        }
    }
    return 0;
}
Example #10
0
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accSelection(VARIANT *pvarChildren)
{
    showDebug(__FUNCTION__, accessible);
    if (!accessible->isValid())
        return E_FAIL;

    int cc = accessible->childCount();
    QVector<int> sel(cc);
    int selIndex = 0;
    for (int i = 0; i < cc; ++i) {
        bool isSelected = false;
        QAccessibleInterface *child = accessible->child(i);
        if (child) {
            isSelected = child->state().selected;
            delete child;
        }
        if (isSelected)
            sel[selIndex++] = i+1;
    }
    sel.resize(selIndex);
    if (sel.isEmpty()) {
        (*pvarChildren).vt = VT_EMPTY;
        return S_FALSE;
    }
    if (sel.size() == 1) {
        (*pvarChildren).vt = VT_I4;
        (*pvarChildren).lVal = sel[0];
        return S_OK;
    }
    IEnumVARIANT *iface = new QWindowsEnumerate(sel);
    IUnknown *uiface;
    iface->QueryInterface(IID_IUnknown, (void**)&uiface);
    (*pvarChildren).vt = VT_UNKNOWN;
    (*pvarChildren).punkVal = uiface;

    return S_OK;
}
Example #11
0
// 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;
}
Example #12
0
HRESULT STDMETHODCALLTYPE QWindowsAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEnd)
{
#ifdef DEBUG_SHOW_ATCLIENT_COMMANDS
    showDebug(__FUNCTION__, accessible);
#endif //DEBUG_SHOW_ATCLIENT_COMMANDS
    if (!accessible->isValid())
        return E_FAIL;

    QAccessibleInterface *acc = 0;
    int control = -1;
    switch(navDir) {
    case NAVDIR_FIRSTCHILD:
        control = accessible->navigate(Child, 1, &acc);
        break;
    case NAVDIR_LASTCHILD:
        control = accessible->navigate(Child, accessible->childCount(), &acc);
        break;
    case NAVDIR_NEXT:
    case NAVDIR_PREVIOUS:
        if (!varStart.lVal){
            QAccessibleInterface *parent = 0;
            accessible->navigate(Ancestor, 1, &parent);
            if (parent) {
                int index = parent->indexOfChild(accessible);
                index += (navDir == NAVDIR_NEXT) ? 1 : -1;
                if (index > 0 && index <= parent->childCount())
                    control = parent->navigate(Child, index, &acc);
                delete parent;
            }
        } else {
            int index = varStart.lVal;
            index += (navDir == NAVDIR_NEXT) ? 1 : -1;
            if (index > 0 && index <= accessible->childCount())
                control = accessible->navigate(Child, index, &acc);
        }
        break;
    case NAVDIR_UP:
        control = accessible->navigate(Up, varStart.lVal, &acc);
        break;
    case NAVDIR_DOWN:
        control = accessible->navigate(Down, varStart.lVal, &acc);
        break;
    case NAVDIR_LEFT:
        control = accessible->navigate(Left, varStart.lVal, &acc);
        break;
    case NAVDIR_RIGHT:
        control = accessible->navigate(Right, varStart.lVal, &acc);
        break;
    default:
        break;
    }
    if (control == -1) {
        (*pvarEnd).vt = VT_EMPTY;
        return S_FALSE;
    }
    if (!acc) {
        (*pvarEnd).vt = VT_I4;
        (*pvarEnd).lVal = control;
        return S_OK;
    }

    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 */
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;
}