diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp index c201076199d5e0f43127792ce8b3efb8a8f43c21..fe01326bbc2751d271cbdf609680b974da2ec0e6 100644 --- a/src/quick/accessible/qaccessiblequickitem.cpp +++ b/src/quick/accessible/qaccessiblequickitem.cpp @@ -82,17 +82,42 @@ bool QAccessibleQuickItem::clipsChildren() const return static_cast<QQuickItem *>(item())->clip(); } +QAccessibleInterface *QAccessibleQuickItem::childAt(int x, int y) const +{ + if (item()->clip()) { + if (!rect().contains(x, y)) + return 0; + } + + const QList<QQuickItem*> kids = accessibleUnignoredChildren(item(), true); + for (int i = kids.count() - 1; i >= 0; --i) { + QAccessibleInterface *childIface = QAccessible::queryAccessibleInterface(kids.at(i)); + if (QAccessibleInterface *childChild = childIface->childAt(x, y)) + return childChild; + if (childIface && !childIface->state().invisible) { + if (childIface->rect().contains(x, y)) + return childIface; + } + } + + return 0; +} + QAccessibleInterface *QAccessibleQuickItem::parent() const { QQuickItem *parent = item()->parentItem(); + QQuickWindow *window = item()->window(); + QQuickItem *ci = window ? window->contentItem() : 0; + while (parent && parent != ci) + parent = parent->parentItem(); + if (parent) { - QQuickWindow *window = item()->window(); - // Jump out to the scene widget if the parent is the root item. - // There are two root items, QQuickWindow::rootItem and - // QQuickView::declarativeRoot. The former is the true root item, - // but is not a part of the accessibility tree. Check if we hit - // it here and return an interface for the scene instead. - if (window && (parent == window->contentItem())) { + if (parent == ci) { + // Jump out to the scene widget if the parent is the root item. + // There are two root items, QQuickWindow::rootItem and + // QQuickView::declarativeRoot. The former is the true root item, + // but is not a part of the accessibility tree. Check if we hit + // it here and return an interface for the scene instead. return QAccessible::queryAccessibleInterface(window); } else { return QAccessible::queryAccessibleInterface(parent); @@ -121,6 +146,19 @@ int QAccessibleQuickItem::indexOfChild(const QAccessibleInterface *iface) const return kids.indexOf(static_cast<QQuickItem*>(iface->object())); } +QList<QQuickItem *> accessibleUnignoredChildren(QQuickItem *item, bool paintOrder) +{ + QList<QQuickItem *> items; + QList<QQuickItem*> childItems = paintOrder ? QQuickItemPrivate::get(item)->paintOrderChildItems() + : item->childItems(); + Q_FOREACH (QQuickItem *child, childItems) { + QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(child); + if (itemPrivate->isAccessible) + items.append(child); + } + return items; +} + QList<QQuickItem *> QAccessibleQuickItem::childItems() const { if ( role() == QAccessible::Button || @@ -133,13 +171,7 @@ QList<QQuickItem *> QAccessibleQuickItem::childItems() const role() == QAccessible::ProgressBar) return QList<QQuickItem *>(); - QList<QQuickItem *> items; - Q_FOREACH (QQuickItem *child, item()->childItems()) { - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(child); - if (itemPrivate->isAccessible) - items.append(child); - } - return items; + return accessibleUnignoredChildren(item()); } QAccessible::State QAccessibleQuickItem::state() const diff --git a/src/quick/accessible/qaccessiblequickitem_p.h b/src/quick/accessible/qaccessiblequickitem_p.h index 5cf120a802bc377d6e2a503fa7bd39c61c1f7ea3..84e82fff8668f76beb954770b9a05f1d180fb786 100644 --- a/src/quick/accessible/qaccessiblequickitem_p.h +++ b/src/quick/accessible/qaccessiblequickitem_p.h @@ -53,6 +53,7 @@ public: QRect viewRect() const; bool clipsChildren() const; + QAccessibleInterface *childAt(int x, int y) const; QAccessibleInterface *parent() const; QAccessibleInterface *child(int index) const; @@ -118,6 +119,7 @@ private: }; QRect itemScreenRect(QQuickItem *item); +QList<QQuickItem *> accessibleUnignoredChildren(QQuickItem *item, bool paintOrder = false); #endif // QT_NO_ACCESSIBILITY diff --git a/src/quick/accessible/qaccessiblequickview.cpp b/src/quick/accessible/qaccessiblequickview.cpp index cfd62b877d850fb6c05511d254891ce5ce65bbb0..db0b042d3b5f7dcb806efcae3fbc8b1e24433935 100644 --- a/src/quick/accessible/qaccessiblequickview.cpp +++ b/src/quick/accessible/qaccessiblequickview.cpp @@ -53,7 +53,7 @@ QAccessibleQuickWindow::QAccessibleQuickWindow(QQuickWindow *object) QQuickItem *QAccessibleQuickWindow::rootItem() const { if (QQuickItem *ci = window()->contentItem()) { - const QList<QQuickItem *> &childItems = ci->childItems(); + const QList<QQuickItem *> &childItems = accessibleUnignoredChildren(ci); if (!childItems.isEmpty()) return childItems.first(); } @@ -110,56 +110,17 @@ QString QAccessibleQuickWindow::text(QAccessible::Text text) const return window()->title(); } - -/*! - \internal - - Can also return \a item itself - */ -static QQuickItem *childAt_helper(QQuickItem *item, int x, int y) -{ - if (!item->isVisible() || !item->isEnabled()) - return 0; - - if (item->flags() & QQuickItem::ItemClipsChildrenToShape) { - if (!itemScreenRect(item).contains(x, y)) - return 0; - } - - QAccessibleInterface *accessibleInterface = QAccessible::queryAccessibleInterface(item); - // this item has no Accessible attached property - if (!accessibleInterface) - return 0; - - if (accessibleInterface->childCount() == 0) { - return (itemScreenRect(item).contains(x, y)) ? item : 0; - } - - QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); - - QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); - for (int i = children.count() - 1; i >= 0; --i) { - QQuickItem *child = children.at(i); - if (QQuickItem *childChild = childAt_helper(child, x, y)) - return childChild; - } - - QRect screenRect = itemScreenRect(item); - - if (screenRect.contains(x, y)) - return item; - - return 0; -} - QAccessibleInterface *QAccessibleQuickWindow::childAt(int x, int y) const { Q_ASSERT(window()); - QQuickItem *root = rootItem(); - if (root) { - if (QQuickItem *item = childAt_helper(root, x, y)) - return QAccessible::queryAccessibleInterface(item); - return QAccessible::queryAccessibleInterface(root); + for (int i = childCount() - 1; i >= 0; --i) { + QAccessibleInterface *childIface = child(i); + if (childIface && !childIface->state().invisible) { + if (QAccessibleInterface *iface = childIface->childAt(x, y)) + return iface; + if (childIface->rect().contains(x, y)) + return childIface; + } } return 0; } diff --git a/src/quick/accessible/qqmlaccessible.cpp b/src/quick/accessible/qqmlaccessible.cpp index 65d321d0a1a1a1ae817dee4ff6e4545d17f9e1ca..53eb6a7a0d671eb3f9496a981eff4f7f32bbcb00 100644 --- a/src/quick/accessible/qqmlaccessible.cpp +++ b/src/quick/accessible/qqmlaccessible.cpp @@ -54,27 +54,6 @@ QQmlAccessible::~QQmlAccessible() { } -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; -} - QAccessible::State QQmlAccessible::state() const { QAccessible::State state; diff --git a/src/quick/accessible/qqmlaccessible_p.h b/src/quick/accessible/qqmlaccessible_p.h index 38e3dcff5947083e14ccf6847be77731f5c05d0b..5948f06cb592bc7964a409a00feffadb8acafc09 100644 --- a/src/quick/accessible/qqmlaccessible_p.h +++ b/src/quick/accessible/qqmlaccessible_p.h @@ -64,7 +64,6 @@ public: void *interface_cast(QAccessible::InterfaceType t); virtual QRect viewRect() const = 0; - QAccessibleInterface *childAt(int, int) const; QAccessible::State state() const; QStringList actionNames() const; @@ -72,7 +71,6 @@ public: QStringList keyBindingsForAction(const QString &actionName) const; protected: - virtual bool clipsChildren() const = 0; // For subclasses, use instantiateObject factory method outside the class. QQmlAccessible(QObject *object); };