Windows: Refactor cursor handling.

Applying scaling to the pixmaps used in pixmap cursors
requires applying a scale factor in a code path
now in a constructor of QWindowsWindowCursorData (nested
into QWindowsWindowCursor). This needs to be split and
the code paths for cursors created from a Qt::CursorShape
value and pixmap cursors need to be further separated.

Replace the QSharedDataPointer-based QWindowsWindowCursor
class by a simple, non-copyable class CursorHandle
managing the HCURSOR handle and pass it around using a
QSharedPointer. Split the cache in QWindowsCursor into one based
on Qt::CursorShape and one based on the cache key aggregated
from the pixmap cache keys (using QWindowsPixmapCursorCacheKey
renamed from QWindowsCursorCacheKey), simplifying the standard case
based on Qt::CursorShape.

Reuse class CursorHandle in
QWindowsOleDropSource::CursorEntryCursorEntry, which used a
similar class.

Remove QWindowsCursor::createSystemCursor().

Avoid the construction of temporary QCursor objects for the
standard cursors constructed from using resource pixmaps by
introducing a struct PixmapCursor containing pixmap
and hotspot.

Task-number: QTBUG-49511
Change-Id: I5393d64bd70f7dab68c0a8c2255c7685ac367b2f
Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
bb10
Friedemann Kleint 2015-11-16 16:48:42 +01:00
parent 8da24d8a5c
commit 296eb88e1c
5 changed files with 112 additions and 177 deletions

View File

@ -67,19 +67,14 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap);
\ingroup qt-lighthouse-win
*/
QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c)
: shape(c.shape()), bitmapCacheKey(0), maskCacheKey(0)
QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
: bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0)
{
if (shape == Qt::BitmapCursor) {
const qint64 pixmapCacheKey = c.pixmap().cacheKey();
if (pixmapCacheKey) {
bitmapCacheKey = pixmapCacheKey;
} else {
Q_ASSERT(c.bitmap());
Q_ASSERT(c.mask());
bitmapCacheKey = c.bitmap()->cacheKey();
maskCacheKey = c.mask()->cacheKey();
}
if (!bitmapCacheKey) {
Q_ASSERT(c.bitmap());
Q_ASSERT(c.mask());
bitmapCacheKey = c.bitmap()->cacheKey();
maskCacheKey = c.mask()->cacheKey();
}
}
@ -206,6 +201,17 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
#endif
}
// Create a cursor from image and mask of the format QImage::Format_Mono.
static HCURSOR createBitmapCursor(const QCursor &cursor)
{
Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap());
const QImage bbits = cursor.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
const QImage mbits = cursor.mask()->toImage().convertToFormat(QImage::Format_Mono);
const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm);
}
static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); }
static inline QSize standardCursorSize() { return QSize(32, 32); }
@ -215,7 +221,7 @@ static inline QSize standardCursorSize() { return QSize(32, 32); }
// createBitmapCursor() only work for standard sizes (32,48,64...), which does
// not work when scaling the 16x16 openhand cursor bitmaps to 150% (resulting
// in a non-standard 24x24 size).
static QCursor createPixmapCursorFromData(const QSize &systemCursorSize,
static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &systemCursorSize,
// The cursor size the bitmap is targeted for
const QSize &bitmapTargetCursorSize,
// The actual size of the bitmap data
@ -233,10 +239,10 @@ static QCursor createPixmapCursorFromData(const QSize &systemCursorSize,
rawImage = rawImage.transformed(transform, Qt::SmoothTransformation);
}
const QPoint hotSpot(rawImage.width() / 2, rawImage.height() / 2);
return QCursor(rawImage, hotSpot.x(), hotSpot.y());
return QWindowsCursor::PixmapCursor(rawImage, hotSpot);
}
QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
{
// Non-standard Windows cursors are created from bitmaps
static const uchar vsplit_bits[] = {
@ -412,14 +418,14 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
case Qt::ClosedHandCursor:
return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
case Qt::DragCopyCursor:
return QCursor(QPixmap(copyDragCursorXpmC), 0, 0);
return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0));
case Qt::DragMoveCursor:
return QCursor(QPixmap(moveDragCursorXpmC), 0, 0);
return QWindowsCursor::PixmapCursor(QPixmap(moveDragCursorXpmC), QPoint(0, 0));
case Qt::DragLinkCursor:
return QCursor(QPixmap(linkDragCursorXpmC), 0, 0);
return QWindowsCursor::PixmapCursor(QPixmap(linkDragCursorXpmC), QPoint(0, 0));
}
return QCursor();
return QWindowsCursor::PixmapCursor();
}
#else // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
struct QWindowsCustomPngCursor {
@ -430,7 +436,7 @@ struct QWindowsCustomPngCursor {
int hotSpotY;
};
QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
{
static const QWindowsCustomPngCursor pngCursors[] = {
{ Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 },
@ -473,11 +479,11 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
}
if (!bestFit)
return QCursor();
return PixmapCursor();
const QPixmap rawImage(QStringLiteral(":/qt-project.org/windows/cursors/images/") +
QString::fromLatin1(bestFit->fileName));
return QCursor(rawImage, bestFit->hotSpotX, bestFit->hotSpotY);
return PixmapCursor(rawImage, QPoint(bestFit->hotSpotX, bestFit->hotSpotY));
}
#endif // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG
@ -486,8 +492,10 @@ struct QWindowsStandardCursorMapping {
LPCWSTR resource;
};
HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
{
Q_ASSERT(cursorShape != Qt::BitmapCursor);
static const QWindowsStandardCursorMapping standardCursors[] = {
{ Qt::ArrowCursor, IDC_ARROW},
{ Qt::UpArrowCursor, IDC_UPARROW },
@ -505,18 +513,7 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
{ Qt::PointingHandCursor, IDC_HAND }
};
const Qt::CursorShape cursorShape = c.shape();
switch (cursorShape) {
case Qt::BitmapCursor: {
const QPixmap pixmap = c.pixmap();
if (!pixmap.isNull())
return QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
const QImage bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono);
const QImage mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono);
const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1));
const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1));
return createBitmapCursor(bbits, mbits, c.hotSpot(), invb, invm);
}
case Qt::BlankCursor: {
QImage blank = QImage(systemCursorSize(), QImage::Format_Mono);
blank.fill(0); // ignore color table
@ -529,7 +526,7 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
case Qt::DragCopyCursor:
case Qt::DragMoveCursor:
case Qt::DragLinkCursor:
return createSystemCursor(customCursor(cursorShape));
return QWindowsCursor::createPixmapCursor(customCursor(cursorShape));
default:
break;
}
@ -554,37 +551,41 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c)
\brief Return cached standard cursor resources or create new ones.
*/
QWindowsWindowCursor QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
{
const QWindowsCursorCacheKey key(shape);
CursorCache::iterator it = m_cursorCache.find(key);
if (it == m_cursorCache.end())
it = m_cursorCache.insert(key, QWindowsWindowCursor(QCursor(shape)));
return it.value();
StandardCursorCache::Iterator it = m_standardCursorCache.find(shape);
if (it == m_standardCursorCache.end()) {
if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape))
it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc)));
}
return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle);
}
/*!
\brief Return cached pixmap cursor or create new one.
*/
QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c)
CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c)
{
const QWindowsCursorCacheKey cacheKey(c);
CursorCache::iterator it = m_cursorCache.find(cacheKey);
if (it == m_cursorCache.end()) {
if (m_cursorCache.size() > 50) {
const QWindowsPixmapCursorCacheKey cacheKey(c);
PixmapCursorCache::iterator it = m_pixmapCursorCache.find(cacheKey);
if (it == m_pixmapCursorCache.end()) {
if (m_pixmapCursorCache.size() > 50) {
// Prevent the cursor cache from growing indefinitely hitting GDI resource
// limits if new pixmap cursors are created repetitively by purging out
// all-noncurrent pixmap cursors (QTBUG-43515)
const HCURSOR currentCursor = GetCursor();
for (it = m_cursorCache.begin(); it != m_cursorCache.end() ; ) {
if (it.key().bitmapCacheKey && it.value().handle() != currentCursor)
it = m_cursorCache.erase(it);
for (it = m_pixmapCursorCache.begin(); it != m_pixmapCursorCache.end() ; ) {
if (it.value()->handle() != currentCursor)
it = m_pixmapCursorCache.erase(it);
else
++it;
}
}
it = m_cursorCache.insert(cacheKey, QWindowsWindowCursor(c));
const QPixmap pixmap = c.pixmap();
const HCURSOR hc = pixmap.isNull()
? createBitmapCursor(c) : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc)));
}
return it.value();
}
@ -606,13 +607,13 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window)
if (!window)
return;
if (!cursorIn) {
QWindowsWindow::baseWindowOf(window)->setCursor(QWindowsWindowCursor());
QWindowsWindow::baseWindowOf(window)->setCursor(CursorHandlePtr(new CursorHandle));
return;
}
const QWindowsWindowCursor wcursor =
const CursorHandlePtr wcursor =
cursorIn->shape() == Qt::BitmapCursor ?
pixmapWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape());
if (wcursor.handle()) {
if (wcursor->handle()) {
QWindowsWindow::baseWindowOf(window)->setCursor(wcursor);
} else {
qWarning("%s: Unable to obtain system cursor for %d",
@ -658,78 +659,11 @@ void QWindowsCursor::setPos(const QPoint &pos)
\brief Per-Window cursor. Contains a QCursor and manages its associated system
cursor handle resource.
Based on QSharedDataPointer, so that it can be passed around and
used as a property of QWindowsBaseWindow.
\internal
\ingroup qt-lighthouse-win
\sa QWindowsCursor
*/
class QWindowsWindowCursorData : public QSharedData
{
public:
QWindowsWindowCursorData() : m_cursor(Qt::ArrowCursor), m_handle(0) {}
explicit QWindowsWindowCursorData(const QCursor &c);
~QWindowsWindowCursorData();
const QCursor m_cursor;
const HCURSOR m_handle;
};
QWindowsWindowCursorData::QWindowsWindowCursorData(const QCursor &c) :
m_cursor(c),
m_handle(QWindowsCursor::createSystemCursor(c))
{
}
QWindowsWindowCursorData::~QWindowsWindowCursorData()
{
if (m_handle)
DestroyCursor(m_handle);
}
QWindowsWindowCursor::QWindowsWindowCursor() :
m_data(new QWindowsWindowCursorData)
{
}
QWindowsWindowCursor::QWindowsWindowCursor(const QCursor &c) :
m_data(new QWindowsWindowCursorData(c))
{
}
QWindowsWindowCursor::~QWindowsWindowCursor()
{
}
QWindowsWindowCursor::QWindowsWindowCursor(const QWindowsWindowCursor &rhs) :
m_data(rhs.m_data)
{
}
QWindowsWindowCursor & QWindowsWindowCursor::operator =(const QWindowsWindowCursor &rhs)
{
if (this != &rhs)
m_data.operator =(rhs.m_data);
return *this;
}
bool QWindowsWindowCursor::isNull() const
{
return m_data->m_handle == 0;
}
QCursor QWindowsWindowCursor::cursor() const
{
return m_data->m_cursor;
}
HCURSOR QWindowsWindowCursor::handle() const
{
return m_data->m_handle;
}
QT_END_NAMESPACE
#endif // !QT_NO_CURSOR

View File

@ -37,51 +37,49 @@
#include "qtwindows_additional.h"
#include <qpa/qplatformcursor.h>
#include <QtCore/QSharedDataPointer>
#include <QtCore/QSharedPointer>
#include <QtCore/QHash>
QT_BEGIN_NAMESPACE
class QWindowsWindowCursorData;
struct QWindowsCursorCacheKey
struct QWindowsPixmapCursorCacheKey
{
explicit QWindowsCursorCacheKey(const QCursor &c);
explicit QWindowsCursorCacheKey(Qt::CursorShape s) : shape(s), bitmapCacheKey(0), maskCacheKey(0) {}
QWindowsCursorCacheKey() : shape(Qt::CustomCursor), bitmapCacheKey(0), maskCacheKey(0) {}
explicit QWindowsPixmapCursorCacheKey(const QCursor &c);
Qt::CursorShape shape;
qint64 bitmapCacheKey;
qint64 maskCacheKey;
};
inline bool operator==(const QWindowsCursorCacheKey &k1, const QWindowsCursorCacheKey &k2)
inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPixmapCursorCacheKey &k2)
{
return k1.shape == k2.shape && k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey;
}
inline uint qHash(const QWindowsCursorCacheKey &k, uint seed) Q_DECL_NOTHROW
inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) Q_DECL_NOTHROW
{
return (uint(k.shape) + uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed;
}
class QWindowsWindowCursor
class CursorHandle
{
Q_DISABLE_COPY(CursorHandle)
public:
QWindowsWindowCursor();
explicit QWindowsWindowCursor(const QCursor &c);
~QWindowsWindowCursor();
QWindowsWindowCursor(const QWindowsWindowCursor &c);
QWindowsWindowCursor &operator=(const QWindowsWindowCursor &c);
explicit CursorHandle(HCURSOR hcursor = Q_NULLPTR) : m_hcursor(hcursor) {}
~CursorHandle()
{
if (m_hcursor)
DestroyCursor(m_hcursor);
}
bool isNull() const;
QCursor cursor() const;
HCURSOR handle() const;
bool isNull() const { return !m_hcursor; }
HCURSOR handle() const { return m_hcursor; }
private:
QSharedDataPointer<QWindowsWindowCursorData> m_data;
const HCURSOR m_hcursor;
};
typedef QSharedPointer<CursorHandle> CursorHandlePtr;
class QWindowsCursor : public QPlatformCursor
{
public:
@ -91,6 +89,13 @@ public:
CursorSuppressed // Cursor suppressed by touch interaction (Windows 8).
};
struct PixmapCursor {
explicit PixmapCursor(const QPixmap &pix = QPixmap(), const QPoint &h = QPoint()) : pixmap(pix), hotSpot(h) {}
QPixmap pixmap;
QPoint hotSpot;
};
QWindowsCursor();
void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE;
@ -98,18 +103,22 @@ public:
void setPos(const QPoint &pos) Q_DECL_OVERRIDE;
static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot);
static HCURSOR createSystemCursor(const QCursor &c);
static QCursor customCursor(Qt::CursorShape cursorShape);
static HCURSOR createPixmapCursor(const PixmapCursor &pc) { return createPixmapCursor(pc.pixmap, pc.hotSpot); }
static PixmapCursor customCursor(Qt::CursorShape cursorShape);
static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape);
static QPoint mousePosition();
static CursorState cursorState();
QWindowsWindowCursor standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
QWindowsWindowCursor pixmapWindowCursor(const QCursor &c);
CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor);
CursorHandlePtr pixmapWindowCursor(const QCursor &c);
private:
typedef QHash<QWindowsCursorCacheKey, QWindowsWindowCursor> CursorCache;
typedef QHash<Qt::CursorShape, CursorHandlePtr> StandardCursorCache;
typedef QHash<QWindowsPixmapCursorCacheKey, CursorHandlePtr> PixmapCursorCache;
CursorCache m_cursorCache;
StandardCursorCache m_standardCursorCache;
PixmapCursorCache m_pixmapCursorCache;
};
QT_END_NAMESPACE

View File

@ -218,23 +218,14 @@ public:
STDMETHOD(GiveFeedback)(DWORD dwEffect);
private:
class DragCursorHandle {
Q_DISABLE_COPY(DragCursorHandle)
public:
DragCursorHandle(HCURSOR c) : cursor(c) {}
~DragCursorHandle() { DestroyCursor(cursor); }
const HCURSOR cursor;
};
typedef QSharedPointer<DragCursorHandle> DragCursorHandlePtr;
struct CursorEntry {
CursorEntry() : cacheKey(0) {}
CursorEntry(const QPixmap &p, qint64 cK, const DragCursorHandlePtr &c, const QPoint &h) :
CursorEntry(const QPixmap &p, qint64 cK, const CursorHandlePtr &c, const QPoint &h) :
pixmap(p), cacheKey(cK), cursor(c), hotSpot(h) {}
QPixmap pixmap;
qint64 cacheKey; // Cache key of cursor
DragCursorHandlePtr cursor;
CursorHandlePtr cursor;
QPoint hotSpot;
};
@ -275,7 +266,7 @@ QWindowsOleDropSource::~QWindowsOleDropSource()
QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e)
{
d << "CursorEntry:" << e.pixmap.size() << '#' << e.cacheKey
<< "HCURSOR" << e.cursor->cursor << "hotspot:" << e.hotSpot;
<< "HCURSOR" << e.cursor->handle() << "hotspot:" << e.hotSpot;
return d;
}
#endif // !QT_NO_DEBUG_STREAM
@ -345,7 +336,7 @@ void QWindowsOleDropSource::createCursors()
}
if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot)) {
const CursorEntry entry(newPixmap, cacheKey, DragCursorHandlePtr(new DragCursorHandle(sysCursor)), newHotSpot);
const CursorEntry entry(newPixmap, cacheKey, CursorHandlePtr(new CursorHandle(sysCursor)), newHotSpot);
if (it == m_cursors.end())
m_cursors.insert(action, entry);
else
@ -458,7 +449,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect)
const CursorEntry &e = it.value();
switch (m_mode) {
case MouseDrag:
SetCursor(e.cursor->cursor);
SetCursor(e.cursor->handle());
break;
case TouchDrag:
if (!m_touchDragWindow)
@ -718,16 +709,16 @@ QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
switch (action) {
case Qt::CopyAction:
if (m_copyDragCursor.isNull())
m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap();
m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap;
return m_copyDragCursor;
case Qt::TargetMoveAction:
case Qt::MoveAction:
if (m_moveDragCursor.isNull())
m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap();
m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap;
return m_moveDragCursor;
case Qt::LinkAction:
if (m_linkDragCursor.isNull())
m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap();
m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap;
return m_linkDragCursor;
default:
break;

View File

@ -928,6 +928,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_hdc(0),
m_windowState(Qt::WindowNoState),
m_opacity(1.0),
m_cursor(new CursorHandle),
m_dropTarget(0),
m_savedStyle(0),
m_format(aWindow->requestedFormat()),
@ -2113,13 +2114,13 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
#ifndef QT_NO_CURSOR
// Return the default cursor (Arrow) from QWindowsCursor's cache.
static inline QWindowsWindowCursor defaultCursor(const QWindow *w)
static inline CursorHandlePtr defaultCursor(const QWindow *w)
{
if (QScreen *screen = w->screen())
if (const QPlatformScreen *platformScreen = screen->handle())
if (QPlatformCursor *cursor = platformScreen->cursor())
return static_cast<QWindowsCursor *>(cursor)->standardWindowCursor(Qt::ArrowCursor);
return QWindowsWindowCursor(Qt::ArrowCursor);
return CursorHandlePtr(new CursorHandle(QWindowsCursor::createCursorFromShape(Qt::ArrowCursor)));
}
// Check whether to apply a new cursor. Either the window in question is
@ -2133,7 +2134,7 @@ static inline bool applyNewCursor(const QWindow *w)
for (const QWindow *p = underMouse; p ; p = p->parent()) {
if (p == w)
return true;
if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull())
if (!QWindowsWindow::baseWindowOf(p)->cursor()->isNull())
return false;
}
return false;
@ -2149,25 +2150,25 @@ static inline bool applyNewCursor(const QWindow *w)
void QWindowsWindow::applyCursor()
{
#ifndef QT_NO_CURSOR
if (m_cursor.isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel.
if (const QWindow *p = window()->parent()) {
QWindowsWindow::baseWindowOf(p)->applyCursor();
} else {
SetCursor(defaultCursor(window()).handle());
SetCursor(defaultCursor(window())->handle());
}
} else {
SetCursor(m_cursor.handle());
SetCursor(m_cursor->handle());
}
#endif
}
void QWindowsWindow::setCursor(const QWindowsWindowCursor &c)
void QWindowsWindow::setCursor(const CursorHandlePtr &c)
{
#ifndef QT_NO_CURSOR
if (c.handle() != m_cursor.handle()) {
if (c->handle() != m_cursor->handle()) {
const bool apply = applyNewCursor(window());
qCDebug(lcQpaWindows) << window() << __FUNCTION__
<< c.cursor().shape() << " doApply=" << apply;
<< c->handle() << " doApply=" << apply;
m_cursor = c;
if (apply)
applyCursor();

View File

@ -225,9 +225,9 @@ public:
#endif // !Q_OS_WINCE
#ifndef QT_NO_CURSOR
QWindowsWindowCursor cursor() const { return m_cursor; }
CursorHandlePtr cursor() const { return m_cursor; }
#endif
void setCursor(const QWindowsWindowCursor &c);
void setCursor(const CursorHandlePtr &c);
void applyCursor();
inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; }
@ -278,7 +278,7 @@ private:
Qt::WindowState m_windowState;
qreal m_opacity;
#ifndef QT_NO_CURSOR
QWindowsWindowCursor m_cursor;
CursorHandlePtr m_cursor;
#endif
QWindowsOleDropTarget *m_dropTarget;
unsigned m_savedStyle;