aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-10-26 14:03:30 +0200
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2022-10-31 22:52:33 +0100
commit7db67e59d45b47e45a2723808f23e8cdadf5065c (patch)
tree3993c28c02c2030c121b1ccf8f3cb88266cdf806 /src
parente306b4932e7e3a2a3c5014674c36d9c6ce5c8017 (diff)
QQuickHoverHandler: listen for parent changes, and update hasHoverInChild
A QQuickHoverHandler is normally created by the QML engine, but can sometimes also be created directly from C++. And for the latter case, QQuickHoverHandler::componentComplete() will not be called. This causes a problem, since it takes care of subscribing for hover events on the parent item. To support creating hover handlers from c++, we therefore need to also subscribe to hover events from the constructor. Moreover, since the parentItem can change at runtime, we also need a virtual function that informs it when the parent item changes, so that we can remove hover subscription from the old parent, and subscribe for it on the new parent. Pick-to: 6.4 Change-Id: I52f3cd16d6bbfbbe2e4c3c019efdc7f06c5f2c31 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/quick/handlers/qquickhoverhandler.cpp51
-rw-r--r--src/quick/handlers/qquickpointerhandler.cpp5
-rw-r--r--src/quick/handlers/qquickpointerhandler_p_p.h1
3 files changed, 44 insertions, 13 deletions
diff --git a/src/quick/handlers/qquickhoverhandler.cpp b/src/quick/handlers/qquickhoverhandler.cpp
index b82b071a7b..16e5ef5ef3 100644
--- a/src/quick/handlers/qquickhoverhandler.cpp
+++ b/src/quick/handlers/qquickhoverhandler.cpp
@@ -42,35 +42,58 @@ class QQuickHoverHandlerPrivate : public QQuickSinglePointHandlerPrivate
public:
void onEnabledChanged() override;
+ void onParentChanged(QQuickItem *oldParent, QQuickItem *newParent) override;
+
+ void updateHasHoverInChild(QQuickItem *item, bool hasHover);
};
void QQuickHoverHandlerPrivate::onEnabledChanged()
{
Q_Q(QQuickHoverHandler);
- if (auto parent = q->parentItem()) {
- QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(parent);
- itemPriv->setHasHoverInChild(enabled);
- // The DA needs to resolve which items and handlers should now be hovered or unhovered.
- // Marking the parent item dirty ensures that flushFrameSynchronousEvents() will be called from the render loop,
- // even if this change is not in response to a mouse event and no item has already marked itself dirty.
- itemPriv->dirty(QQuickItemPrivate::Content);
- }
+ if (auto parent = q->parentItem())
+ updateHasHoverInChild(parent, enabled);
if (!enabled)
q->setHovered(false);
+
+ QQuickSinglePointHandlerPrivate::onEnabledChanged();
+}
+
+void QQuickHoverHandlerPrivate::onParentChanged(QQuickItem *oldParent, QQuickItem *newParent)
+{
+ if (oldParent)
+ updateHasHoverInChild(oldParent, false);
+ if (newParent)
+ updateHasHoverInChild(newParent, true);
+
+ QQuickSinglePointHandlerPrivate::onParentChanged(oldParent, newParent);
+}
+
+void QQuickHoverHandlerPrivate::updateHasHoverInChild(QQuickItem *item, bool hasHover)
+{
+ QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
+ itemPriv->setHasHoverInChild(hasHover);
+ // The DA needs to resolve which items and handlers should now be hovered or unhovered.
+ // Marking the parent item dirty ensures that flushFrameSynchronousEvents() will be called from the render loop,
+ // even if this change is not in response to a mouse event and no item has already marked itself dirty.
+ itemPriv->dirty(QQuickItemPrivate::Content);
}
QQuickHoverHandler::QQuickHoverHandler(QQuickItem *parent)
: QQuickSinglePointHandler(*(new QQuickHoverHandlerPrivate), parent)
{
+ Q_D(QQuickHoverHandler);
// Tell QQuickPointerDeviceHandler::wantsPointerEvent() to ignore button state
- d_func()->acceptedButtons = Qt::NoButton;
+ d->acceptedButtons = Qt::NoButton;
+ if (parent)
+ d->updateHasHoverInChild(parent, true);
}
QQuickHoverHandler::~QQuickHoverHandler()
{
+ Q_D(QQuickHoverHandler);
if (auto parent = parentItem())
- QQuickItemPrivate::get(parent)->setHasHoverInChild(false);
+ d->updateHasHoverInChild(parent, false);
}
/*!
@@ -107,9 +130,13 @@ bool QQuickHoverHandler::event(QEvent *event)
void QQuickHoverHandler::componentComplete()
{
+ Q_D(QQuickHoverHandler);
QQuickSinglePointHandler::componentComplete();
- if (auto par = parentItem())
- QQuickItemPrivate::get(par)->setHasHoverInChild(true);
+
+ if (d->enabled) {
+ if (auto parent = parentItem())
+ d->updateHasHoverInChild(parent, true);
+ }
}
bool QQuickHoverHandler::wantsPointerEvent(QPointerEvent *event)
diff --git a/src/quick/handlers/qquickpointerhandler.cpp b/src/quick/handlers/qquickpointerhandler.cpp
index 96f87d6943..a851334b0e 100644
--- a/src/quick/handlers/qquickpointerhandler.cpp
+++ b/src/quick/handlers/qquickpointerhandler.cpp
@@ -597,15 +597,18 @@ QQuickItem *QQuickPointerHandler::parentItem() const
void QQuickPointerHandler::setParentItem(QQuickItem *p)
{
+ Q_D(QQuickPointerHandler);
if (QObject::parent() == p)
return;
qCDebug(lcHandlerParent) << "reparenting handler" << this << ":" << parent() << "->" << p;
- if (auto *oldParent = static_cast<QQuickItem *>(QObject::parent()))
+ auto *oldParent = static_cast<QQuickItem *>(QObject::parent());
+ if (oldParent)
QQuickItemPrivate::get(oldParent)->removePointerHandler(this);
setParent(p);
if (p)
QQuickItemPrivate::get(p)->addPointerHandler(this);
+ d->onParentChanged(oldParent, p);
emit parentChanged();
}
diff --git a/src/quick/handlers/qquickpointerhandler_p_p.h b/src/quick/handlers/qquickpointerhandler_p_p.h
index be2019618a..36797ef8b3 100644
--- a/src/quick/handlers/qquickpointerhandler_p_p.h
+++ b/src/quick/handlers/qquickpointerhandler_p_p.h
@@ -39,6 +39,7 @@ public:
bool dragOverThreshold(QVector2D delta) const;
bool dragOverThreshold(const QEventPoint &point) const;
+ virtual void onParentChanged(QQuickItem * /*oldParent*/, QQuickItem * /*newParent*/) {}
virtual void onEnabledChanged() {}
static QVector<QObject *> &deviceDeliveryTargets(const QInputDevice *device);