Add a QHoverEvent ctor taking global mouse position; deprecate the other

The QSinglePointEvent ctor assumes that the given globalPos is correct,
so it was wrong that the QHoverEvent ctor passed along a local position
as global. It's better to require globalPos as an argument; and in fact
it seems that everywhere we construct a QHoverEvent, global position is
available, or possible to get by transformation (which is better than
resorting to QCursor::pos()).

Also, don't convert to QPoint: pointer events have qreal resolution and
there's no reason to truncate them.

Fixes: QTBUG-100324
Change-Id: I919455da36265988d3d149eb97563c9ed0d2c660
Pick-to: 6.3
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Shawn Rutledge 2022-01-31 16:09:38 +01:00
parent 5c6f8b2c67
commit 0a64a044b6
5 changed files with 42 additions and 14 deletions

View File

@ -1068,6 +1068,27 @@ Qt::MouseEventFlags QMouseEvent::flags() const
The \a type parameter must be QEvent::HoverEnter,
QEvent::HoverLeave, or QEvent::HoverMove.
The \a pos is the current mouse cursor's position relative to the
receiving widget, \a oldPos is its previous such position, and
\a globalPos is the mouse position in absolute coordinates.
\a modifiers hold the state of all keyboard modifiers at the time
of the event.
*/
QHoverEvent::QHoverEvent(Type type, const QPointF &pos, const QPointF &globalPos, const QPointF &oldPos,
Qt::KeyboardModifiers modifiers, const QPointingDevice *device)
: QSinglePointEvent(type, device, pos, pos, globalPos, Qt::NoButton, Qt::NoButton, modifiers), m_oldPos(oldPos)
{
}
#if QT_DEPRECATED_SINCE(6, 3)
/*!
\deprecated [6.3] Use the other constructor instead (global position is required).
Constructs a hover event object originating from \a device.
The \a type parameter must be QEvent::HoverEnter,
QEvent::HoverLeave, or QEvent::HoverMove.
The \a pos is the current mouse cursor's position relative to the
receiving widget, while \a oldPos is its previous such position.
\a modifiers hold the state of all keyboard modifiers at the time
@ -1078,6 +1099,7 @@ QHoverEvent::QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos,
: QSinglePointEvent(type, device, pos, pos, pos, Qt::NoButton, Qt::NoButton, modifiers), m_oldPos(oldPos)
{
}
#endif
/*!
\internal

View File

@ -281,9 +281,15 @@ class Q_GUI_EXPORT QHoverEvent : public QSinglePointEvent
{
Q_EVENT_DISABLE_COPY(QHoverEvent);
public:
QHoverEvent(Type type, const QPointF &pos, const QPointF &globalPos, const QPointF &oldPos,
Qt::KeyboardModifiers modifiers = Qt::NoModifier,
const QPointingDevice *device = QPointingDevice::primaryPointingDevice());
#if QT_DEPRECATED_SINCE(6, 3)
QT_DEPRECATED_VERSION_X_6_3("Use the other constructor")
QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos,
Qt::KeyboardModifiers modifiers = Qt::NoModifier,
const QPointingDevice *device = QPointingDevice::primaryPointingDevice());
#endif
~QHoverEvent();
QHoverEvent *clone() const override { return new QHoverEvent(*this); }

View File

@ -2073,7 +2073,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con
if (w->testAttribute(Qt::WA_Hover) &&
(!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
Q_ASSERT(instance());
QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos),
QHoverEvent he(QEvent::HoverLeave, QPointF(-1, -1), globalPosF, w->mapFromGlobal(globalPosF),
QGuiApplication::keyboardModifiers());
qApp->d_func()->notify_helper(w, &he);
}
@ -2081,19 +2081,19 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con
}
if (!enterList.isEmpty()) {
// Guard against QGuiApplicationPrivate::lastCursorPosition initialized to qInf(), qInf().
const QPoint globalPos = qIsInf(globalPosF.x())
? QPoint(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
: globalPosF.toPoint();
const QPoint windowPos = qAsConst(enterList).back()->window()->mapFromGlobal(globalPos);
const QPointF globalPos = qIsInf(globalPosF.x())
? QPointF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)
: globalPosF;
const QPointF windowPos = qAsConst(enterList).back()->window()->mapFromGlobal(globalPos);
for (auto it = enterList.crbegin(), end = enterList.crend(); it != end; ++it) {
auto *w = *it;
if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) {
const QPointF localPos = w->mapFromGlobal(globalPos);
QEnterEvent enterEvent(localPos, windowPos, globalPosF);
QEnterEvent enterEvent(localPos, windowPos, globalPos);
QCoreApplication::sendEvent(w, &enterEvent);
if (w->testAttribute(Qt::WA_Hover) &&
(!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
QHoverEvent he(QEvent::HoverEnter, localPos, QPoint(-1, -1),
QHoverEvent he(QEvent::HoverEnter, localPos, QPointF(-1, -1), globalPos,
QGuiApplication::keyboardModifiers());
qApp->d_func()->notify_helper(w, &he);
}
@ -2843,11 +2843,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
w = static_cast<QWidget *>(receiver);
relpos = mouse->position().toPoint();
QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos);
QPoint diff = relpos - w->mapFromGlobal(mouse->globalPosition().toPoint());
while (w) {
if (w->testAttribute(Qt::WA_Hover) &&
(!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff, mouse->modifiers());
QHoverEvent he(QEvent::HoverMove, relpos, mouse->globalPosition(), relpos - diff, mouse->modifiers());
d->notify_helper(w, &he);
}
if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation))

View File

@ -1511,11 +1511,11 @@ void tst_QHeaderView::testEvent()
void protected_QHeaderView::testEvent()
{
// No crashy please
QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(), QPoint());
QHoverEvent enterEvent(QEvent::HoverEnter, QPoint(), QPoint(), QPoint());
event(&enterEvent);
QHoverEvent eventLeave(QEvent::HoverLeave, QPoint(), QPoint());
QHoverEvent eventLeave(QEvent::HoverLeave, QPoint(), QPoint(), QPoint());
event(&eventLeave);
QHoverEvent eventMove(QEvent::HoverMove, QPoint(), QPoint());
QHoverEvent eventMove(QEvent::HoverMove, QPoint(), QPoint(), QPoint());
event(&eventMove);
}

View File

@ -1859,11 +1859,11 @@ void tst_QMainWindow::setCursor()
QVERIFY(QTest::qWaitForWindowActive(&mw));
QCOMPARE(cur.shape(), mw.cursor().shape());
QHoverEvent enterE(QEvent::HoverEnter, QPoint(10,10), QPoint());
QHoverEvent enterE(QEvent::HoverEnter, QPoint(10,10), QPoint(), QPoint());
mw.event(&enterE);
QCOMPARE(cur.shape(), mw.cursor().shape());
QHoverEvent leaveE(QEvent::HoverLeave, QPoint(), QPoint());
QHoverEvent leaveE(QEvent::HoverLeave, QPoint(), QPoint(), QPoint());
mw.event(&leaveE);
QCOMPARE(cur.shape(), mw.cursor().shape());
}