aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/accessible/qaccessiblequickitem.cpp
diff options
context:
space:
mode:
authorJan Arve Saether <jan-arve.saether@digia.com>2014-09-10 13:10:19 +0200
committerJan Arve Sæther <jan-arve.saether@theqtcompany.com>2014-10-21 08:05:08 +0200
commitdb16f3e56e73846bc70eab08869dfb57706db2bf (patch)
tree88326bc82b0e38caad05126ae81ceae2a8539fbb /src/quick/accessible/qaccessiblequickitem.cpp
parentd6661ca409ebf1e4a2fa21fa4f084f63f70052e3 (diff)
Improve hit testing so that it works better with ignored items
The hit testing won't work very well with the upcoming patch that changes which items that can be ignored. (basically it doesn't consider the isAccessible flag, so childAt_helper might return a node that was supposed to be ignored) Earlier this was a sensible optimization in order to avoid too many heap allocations and deallocations of interfaces, but these are cheap now, so we can do it the do it the 'proper way' (i.e. before this patch we didn't respect the a11y hierarchy as given by QAccessibleInterface child() and parent(). This also uses the QAccessibleInterface::rect() directly now instead of using the itemScreenRect() function, which was shared between QAccessibleQuickWindow and QAccessibleQuickItem. Since this changes the order of child interfaces to paint order (i.e. second child interface is on top of first child interface), we need to ensure that we hit test child interfaces in the correct order. They should now always be processed with the last interface first, and then return as soon as something is hit. Change-Id: Ie951fc3b48b7affd9f7e98687a1cbbe008857d2a Reviewed-by: Frederik Gladhorn <frederik.gladhorn@theqtcompany.com>
Diffstat (limited to 'src/quick/accessible/qaccessiblequickitem.cpp')
-rw-r--r--src/quick/accessible/qaccessiblequickitem.cpp60
1 files changed, 46 insertions, 14 deletions
diff --git a/src/quick/accessible/qaccessiblequickitem.cpp b/src/quick/accessible/qaccessiblequickitem.cpp
index c201076199..fe01326bbc 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