Differentiate cached cursors with different hotspots or dpi scales

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ø <tor.arne.vestbo@qt.io>
Reviewed-by: Wladimir Leuschner <wladimir.leuschner@qt.io>
This commit is contained in:
Morteza Jamshidi 2024-10-01 16:26:58 +02:00
parent 9a3199fec2
commit 7ebdce3cde
4 changed files with 34 additions and 8 deletions

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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