summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2022-02-01 07:56:23 +0100
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2022-02-23 05:27:33 +0000
commit32b278b13bf0e2ef7ee4fdc8edfdfccdf190d4cb (patch)
tree079168c05cfe5e667631d6f34c9db7e79b5543e5
parent81ba148fc9ba9b71e261d46c500290690ee2ec63 (diff)
Make QGuiApplicationPrivate::lastCursorPosition.toPoint() safe to use
QGuiApplicationPrivate::lastCursorPosition is initialized with qInf(); so before Qt has seen a mouse move event, attempting to convert to QPoint is an error. It's best to have one place where we do the qIsInf() check rather than several (and otherwise prefer using the QPointF as-is rather than converting to QPoint at all). Introduce a helper class that contains a QPointF, and provides a safe conversion to QPoint, as well as simple accessors for clients using QPointF. Fixes: QTBUG-52472 Task-number: QTBUG-45045 Change-Id: I83fad1bfb658e03fa876344552f1d5bb751d9f81 Reviewed-by: Marc Mutz <marc.mutz@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> (cherry picked from commit c5792dcfd631abb4f9e2b92cd6e88d7e5c373406) Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r--src/gui/kernel/qguiapplication.cpp13
-rw-r--r--src/gui/kernel/qguiapplication_p.h15
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp2
3 files changed, 26 insertions, 4 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index c25f67faf8..8131c314d7 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -125,6 +125,7 @@
#include <qtgui_tracepoints_p.h>
#include <ctype.h>
+#include <limits>
QT_BEGIN_NAMESPACE
@@ -142,7 +143,7 @@ Q_GUI_EXPORT bool qt_is_gui_used = true;
Qt::MouseButtons QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
-QPointF QGuiApplicationPrivate::lastCursorPosition(qt_inf(), qt_inf());
+QGuiApplicationPrivate::QLastCursorPosition QGuiApplicationPrivate::lastCursorPosition;
QWindow *QGuiApplicationPrivate::currentMouseWindow = nullptr;
@@ -704,7 +705,7 @@ QGuiApplication::~QGuiApplication()
QGuiApplicationPrivate::desktopFileName = nullptr;
QGuiApplicationPrivate::mouse_buttons = Qt::NoButton;
QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
- QGuiApplicationPrivate::lastCursorPosition = {qreal(qInf()), qreal(qInf())};
+ QGuiApplicationPrivate::lastCursorPosition.reset();
QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr;
QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
QGuiApplicationPrivate::currentDragWindow = nullptr;
@@ -4140,6 +4141,14 @@ QPixmap QGuiApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape)
return QPixmap();
}
+QPoint QGuiApplicationPrivate::QLastCursorPosition::toPoint() const noexcept
+{
+ // Guard against the default initialization of qInf() (avoid UB or SIGFPE in conversion).
+ if (Q_UNLIKELY(qIsInf(thePoint.x())))
+ return QPoint(std::numeric_limits<int>::max(), std::numeric_limits<int>::max());
+ return thePoint.toPoint();
+}
+
void QGuiApplicationPrivate::notifyThemeChanged()
{
updatePalette();
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 5845d98374..a6c48c2bae 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -61,6 +61,7 @@
#include <QtCore/qnativeinterface.h>
#include <QtCore/private/qnativeinterface_p.h>
+#include <QtCore/private/qnumeric_p.h>
#include <QtCore/private/qthread_p.h>
#include <qpa/qwindowsysteminterface.h>
@@ -225,7 +226,19 @@ public:
virtual bool popupActive() { return false; }
static Qt::MouseButton mousePressButton;
- static QPointF lastCursorPosition;
+ static struct QLastCursorPosition {
+ constexpr inline QLastCursorPosition() noexcept : thePoint(qt_inf(), qt_inf()) {}
+ constexpr inline Q_IMPLICIT QLastCursorPosition(QPointF p) noexcept : thePoint(p) {}
+ constexpr inline Q_IMPLICIT operator QPointF() const noexcept { return thePoint; }
+ constexpr inline qreal x() const noexcept{ return thePoint.x(); }
+ constexpr inline qreal y() const noexcept{ return thePoint.y(); }
+ Q_GUI_EXPORT QPoint toPoint() const noexcept;
+
+ constexpr void reset() noexcept { *this = QLastCursorPosition{}; }
+
+ private:
+ QPointF thePoint;
+ } lastCursorPosition;
static QWindow *currentMouseWindow;
static QWindow *currentMousePressWindow;
static Qt::ApplicationState applicationState;
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 1501407a42..066c8b552f 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -413,7 +413,7 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event)
QWindowSystemInterfacePrivate::EnterEvent *systemEvent =
static_cast<QWindowSystemInterfacePrivate::EnterEvent *>
(QWindowSystemInterfacePrivate::peekWindowSystemEvent(QWindowSystemInterfacePrivate::Enter));
- const QPointF globalPosF = systemEvent ? systemEvent->globalPos : QGuiApplicationPrivate::lastCursorPosition;
+ const QPointF globalPosF = systemEvent ? systemEvent->globalPos : QPointF(QGuiApplicationPrivate::lastCursorPosition);
if (systemEvent) {
if (QWidgetWindow *enterWindow = qobject_cast<QWidgetWindow *>(systemEvent->enter))
{