diff options
author | Sérgio Martins <sergio.martins.qnx@kdab.com> | 2012-09-07 12:00:30 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-10-11 16:07:33 +0200 |
commit | 2c9886dfb9d448b08794d88ea112076c2744f194 (patch) | |
tree | b569067de827a34cc24c37014d77bf4de30afea7 /src | |
parent | cad818ae17c5537a2bbf733806719eafa8227032 (diff) |
Fix performance bottleneck in QQuickWindow::mouseMoveEvent().
When a mouse move event is received, a lot of time is spent looking
for items with cursors, recursively.
With this patch, it will only recur into item hierarchies that
contain cursors.
Not having cursors is much more common than having them.
Benchmark included:
Before: 15 msecs per iteration (total: 62, iterations: 4)
After: 0.000064 msecs per iteration (total: 68, iterations: 1048576)
Task-number: QTBUG-27054
Change-Id: I3a5441652ca1c0b8d2cbc5683013562174f5af4a
Reviewed-by: Alan Alpert <416365416c@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 28 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 3 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 19 |
3 files changed, 42 insertions, 8 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 76fbe9b012..783994666c 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -2180,6 +2180,10 @@ void QQuickItemPrivate::addChild(QQuickItem *child) childItems.append(child); + QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); + if (childPrivate->extra.isAllocated()) + incrementCursorCount(childPrivate->extra.value().numItemsWithCursor); + markSortedChildrenDirty(child); dirty(QQuickItemPrivate::ChildrenChanged); @@ -2197,6 +2201,10 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) childItems.removeOne(child); Q_ASSERT(!childItems.contains(child)); + QQuickItemPrivate *childPrivate = QQuickItemPrivate::get(child); + if (childPrivate->extra.isAllocated()) + incrementCursorCount(-childPrivate->extra.value().numItemsWithCursor); + markSortedChildrenDirty(child); dirty(QQuickItemPrivate::ChildrenChanged); @@ -6012,8 +6020,20 @@ void QQuickItem::setAcceptHoverEvents(bool enabled) d->hoverEnabled = enabled; } +void QQuickItemPrivate::incrementCursorCount(int delta) +{ #ifndef QT_NO_CURSOR + Q_Q(QQuickItem); + extra.value().numItemsWithCursor += delta; + QQuickItem *parent = q->parentItem(); + if (parent) { + QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent); + parentPrivate->incrementCursorCount(delta); + } +#endif +} +#ifndef QT_NO_CURSOR /*! Returns the cursor shape for this item. @@ -6059,6 +6079,7 @@ void QQuickItem::setCursor(const QCursor &cursor) } if (!d->hasCursor) { + d->incrementCursorCount(+1); d->hasCursor = true; if (d->window) { QPointF pos = d->window->mapFromGlobal(QGuiApplicationPrivate::lastCursorPosition.toPoint()); @@ -6079,6 +6100,7 @@ void QQuickItem::unsetCursor() Q_D(QQuickItem); if (!d->hasCursor) return; + d->incrementCursorCount(-1); d->hasCursor = false; if (d->extra.isAllocated()) d->extra->cursor = QCursor(); @@ -7047,7 +7069,11 @@ void QQuickItemLayer::updateMatrix() QQuickItemPrivate::ExtraData::ExtraData() : z(0), scale(1), rotation(0), opacity(1), contents(0), screenAttached(0), layoutDirectionAttached(0), - keyHandler(0), layer(0), effectRefCount(0), hideRefCount(0), + keyHandler(0), layer(0), +#ifndef QT_NO_CURSOR + numItemsWithCursor(0), +#endif + effectRefCount(0), hideRefCount(0), opacityNode(0), clipNode(0), rootNode(0), beforePaintNode(0), acceptedMouseButtons(0), origin(QQuickItem::Center) { diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 6f2642e1ae..1f372b5764 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -344,6 +344,7 @@ public: mutable QQuickItemLayer *layer; #ifndef QT_NO_CURSOR QCursor cursor; + int numItemsWithCursor; #endif QPointF userTransformOriginPoint; @@ -574,6 +575,8 @@ public: static void start(QElapsedTimer &); static qint64 elapsed(QElapsedTimer &); static qint64 restart(QElapsedTimer &); + + void incrementCursorCount(int delta); }; /* diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index b657094e29..7cc645f48a 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1893,13 +1893,18 @@ QQuickItem *QQuickWindowPrivate::findCursorItem(QQuickItem *item, const QPointF return 0; } - QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); - for (int ii = children.count() - 1; ii >= 0; --ii) { - QQuickItem *child = children.at(ii); - if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled) - continue; - if (QQuickItem *cursorItem = findCursorItem(child, scenePos)) - return cursorItem; + const int numCursorsInHierarchy = itemPrivate->extra.isAllocated() ? itemPrivate->extra.value().numItemsWithCursor : 0; + const int numChildrenWithCursor = itemPrivate->hasCursor ? numCursorsInHierarchy-1 : numCursorsInHierarchy; + + if (numChildrenWithCursor > 0) { + QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); + for (int ii = children.count() - 1; ii >= 0; --ii) { + QQuickItem *child = children.at(ii); + if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled) + continue; + if (QQuickItem *cursorItem = findCursorItem(child, scenePos)) + return cursorItem; + } } if (itemPrivate->hasCursor) { |