From 6f809058a6e0a4711bf23af118c091e683eea8bd Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Sun, 2 Jan 2022 20:41:18 +0000 Subject: [PATCH] [kicker] Cache position of hover enter events before replaying The triangle mouse blocks events that happen within a given region and conditions, then replays those events when those conditions get broken. If we intercept an enter event, we capture that under m_interceptedHoverItem so that if conditions change we can replay that hover enter event before we then start sending move events. Currently we replay that hover event using the current mouse position. This causes an issue for kickoff that has additional code to look for actual move events in order to avoid selecting the current item on scroll. Both codepaths are correct standalone, but together form a bug. This patch caches the relative position of a HoverEnter event. Should we replay the enter event, we do so with the position of the enter. We then can replay a HoverMove to get the up-to-date location. BUG: 447278 --- applets/kicker/plugin/trianglemousefilter.cpp | 10 +++++++++- applets/kicker/plugin/trianglemousefilter.h | 5 +++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/applets/kicker/plugin/trianglemousefilter.cpp b/applets/kicker/plugin/trianglemousefilter.cpp index 83b893377..858df676a 100644 --- a/applets/kicker/plugin/trianglemousefilter.cpp +++ b/applets/kicker/plugin/trianglemousefilter.cpp @@ -19,8 +19,14 @@ TriangleMouseFilter::TriangleMouseFilter(QQuickItem *parent) if (!m_interceptedHoverItem) { return; } + if (m_interceptedHoverEnterPosition) { + const auto targetPosition = mapToItem(m_interceptedHoverItem, m_interceptedHoverEnterPosition.value()); + QHoverEvent e(QEvent::HoverEnter, targetPosition, targetPosition); + qApp->sendEvent(m_interceptedHoverItem, &e); + m_interceptedHoverEnterPosition.reset(); + } const auto targetPosition = mapToItem(m_interceptedHoverItem, m_lastCursorPosition); - QHoverEvent e(QEvent::HoverEnter, targetPosition, targetPosition); + QHoverEvent e(QEvent::HoverMove, targetPosition, targetPosition); qApp->sendEvent(m_interceptedHoverItem, &e); }); }; @@ -45,6 +51,7 @@ bool TriangleMouseFilter::childMouseEventFilter(QQuickItem *item, QEvent *event) if (filterContains(position)) { if (event->type() == QEvent::HoverEnter) { + m_interceptedHoverEnterPosition = position; m_interceptedHoverItem = item; } @@ -62,6 +69,7 @@ bool TriangleMouseFilter::childMouseEventFilter(QQuickItem *item, QEvent *event) // if using this in a more general setting we might want to make this guarded by an option if (event->type() == QEvent::HoverEnter && !m_interceptionPos) { m_interceptedHoverItem = item; + m_interceptedHoverEnterPosition = position; if (m_filterTimeout > 0) { m_resetTimer.start(m_filterTimeout); } diff --git a/applets/kicker/plugin/trianglemousefilter.h b/applets/kicker/plugin/trianglemousefilter.h index e84b8fe2f..7c2b684c1 100644 --- a/applets/kicker/plugin/trianglemousefilter.h +++ b/applets/kicker/plugin/trianglemousefilter.h @@ -60,9 +60,10 @@ protected: private: bool filterContains(const QPointF &p) const; QTimer m_resetTimer; - std::optional m_interceptionPos; + std::optional m_interceptionPos; // point where we started intercepting QPointF m_lastCursorPosition; - QPointer m_interceptedHoverItem; + QPointer m_interceptedHoverItem; // item newly entered but the enter event was intercepted + std::optional m_interceptedHoverEnterPosition; // position of intercepted enter events Qt::Edge m_edge = Qt::RightEdge; int m_filterTimeout = 300; };