From 7ebdce3cde422002e37e16a1a3882626ec6ab5ff Mon Sep 17 00:00:00 2001 From: Morteza Jamshidi Date: Tue, 1 Oct 2024 16:26:58 +0200 Subject: [PATCH] Differentiate cached cursors with different hotspots or dpi scales MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Increased cache accuracy by adding cursor hotspot and dpi scale to the QWindowsPixmapCursorCacheKey. Also added cursor hotspot to the QXcbCursorCacheKey. With this change qt supports creating cursors based on the same disk file but with different hotspot or dpi scale Fixes: QTBUG-122381 Change-Id: I1ed6f8fab7f72fe5b658c4f68fa86bc8a033040f Reviewed-by: Tor Arne Vestbø Reviewed-by: Wladimir Leuschner --- src/plugins/platforms/windows/qwindowscursor.cpp | 13 ++++++++----- src/plugins/platforms/windows/qwindowscursor.h | 15 +++++++++++++-- src/plugins/platforms/xcb/qxcbcursor.cpp | 2 ++ src/plugins/platforms/xcb/qxcbcursor.h | 12 +++++++++++- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 7760cddc771..89532574405 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -39,8 +39,8 @@ using namespace Qt::Literals::StringLiterals; \internal */ -QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) - : bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0) +QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c, qreal scaleFactor) + : bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0), scaleFactor(scaleFactor) { if (!bitmapCacheKey) { Q_ASSERT(!c.bitmap().isNull()); @@ -48,6 +48,8 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) bitmapCacheKey = c.bitmap().cacheKey(); maskCacheKey = c.mask().cacheKey(); } + hotspotCacheKey.x = c.hotSpot().x(); + hotspotCacheKey.y = c.hotSpot().y(); } /*! @@ -531,7 +533,8 @@ POINT QWindowsCursor::m_cursorPositionCache = {0,0}; CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c) { - const QWindowsPixmapCursorCacheKey cacheKey(c); + const qreal scaleFactor = QHighDpiScaling::factor(m_screen); + const QWindowsPixmapCursorCacheKey cacheKey(c, scaleFactor); PixmapCursorCache::iterator it = m_pixmapCursorCache.find(cacheKey); if (it == m_pixmapCursorCache.end()) { if (m_pixmapCursorCache.size() > 50) { @@ -546,7 +549,6 @@ CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c) ++it; } } - const qreal scaleFactor = QHighDpiScaling::factor(m_screen); const QPixmap pixmap = c.pixmap(); const HCURSOR hc = pixmap.isNull() ? createBitmapCursor(c, scaleFactor) @@ -776,7 +778,8 @@ HCURSOR QWindowsCursor::hCursor(const QCursor &c) const { const Qt::CursorShape shape = c.shape(); if (shape == Qt::BitmapCursor) { - const auto pit = m_pixmapCursorCache.constFind(QWindowsPixmapCursorCacheKey(c)); + const qreal scaleFactor = QHighDpiScaling::factor(m_screen); + const auto pit = m_pixmapCursorCache.constFind(QWindowsPixmapCursorCacheKey(c, scaleFactor)); if (pit != m_pixmapCursorCache.constEnd()) return pit.value()->handle(); } else { diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index 4f0c7bc093b..c57b495e080 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -14,15 +14,26 @@ QT_BEGIN_NAMESPACE struct QWindowsPixmapCursorCacheKey { - explicit QWindowsPixmapCursorCacheKey(const QCursor &c); + explicit QWindowsPixmapCursorCacheKey(const QCursor &c, qreal scaleFactor); qint64 bitmapCacheKey; qint64 maskCacheKey; + union { + qint64 hashKey; + struct { + qint32 x; + qint32 y; + }; + } hotspotCacheKey; + qreal scaleFactor; }; inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPixmapCursorCacheKey &k2) { - return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey; + return k1.bitmapCacheKey == k2.bitmapCacheKey && + k1.maskCacheKey == k2.maskCacheKey && + k1.hotspotCacheKey.hashKey == k2.hotspotCacheKey.hashKey && + k1.scaleFactor == k2.scaleFactor; } inline size_t qHash(const QWindowsPixmapCursorCacheKey &k, size_t seed) noexcept diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index dc9ed46956f..d1d95f79f08 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -247,6 +247,8 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c) maskCacheKey = c.mask().cacheKey(); } } + hotspotCacheKey.x = c.hotSpot().x(); + hotspotCacheKey.y = c.hotSpot().y(); } #endif // !QT_NO_CURSOR diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h index bf26861e8f3..5ec553119da 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.h +++ b/src/plugins/platforms/xcb/qxcbcursor.h @@ -23,11 +23,21 @@ struct QXcbCursorCacheKey Qt::CursorShape shape; qint64 bitmapCacheKey; qint64 maskCacheKey; + union { + qint64 hashKey; + struct { + qint32 x; + qint32 y; + }; + } hotspotCacheKey; }; inline bool operator==(const QXcbCursorCacheKey &k1, const QXcbCursorCacheKey &k2) { - return k1.shape == k2.shape && k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey; + return k1.shape == k2.shape && + k1.bitmapCacheKey == k2.bitmapCacheKey && + k1.maskCacheKey == k2.maskCacheKey && + k1.hotspotCacheKey.hashKey == k2.hotspotCacheKey.hashKey; } inline size_t qHash(const QXcbCursorCacheKey &k, size_t seed) noexcept