summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowscursor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowscursor.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp168
1 files changed, 147 insertions, 21 deletions
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 800b79347c..c769eb04a4 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -43,15 +43,17 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/private/qguiapplication_p.h> // getPixmapCursor()
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/QDebug>
#include <QtCore/QScopedArrayPointer>
-static void initResources()
+static bool initResources()
{
#if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG)
Q_INIT_RESOURCE(cursors);
#endif
+ return true;
}
QT_BEGIN_NAMESPACE
@@ -92,9 +94,14 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c)
\sa QWindowsWindowCursor
*/
-HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot)
+HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor)
{
HCURSOR cur = 0;
+ scaleFactor /= pixmap.devicePixelRatioF();
+ if (!qFuzzyCompare(scaleFactor, 1)) {
+ pixmap = pixmap.scaled((scaleFactor * QSizeF(pixmap.size())).toSize(),
+ Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ }
QBitmap mask = pixmap.mask();
if (mask.isNull()) {
mask = QBitmap(pixmap.size());
@@ -202,17 +209,43 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits,
}
// Create a cursor from image and mask of the format QImage::Format_Mono.
-static HCURSOR createBitmapCursor(const QCursor &cursor)
+static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1)
{
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);
+ QImage bbits = cursor.bitmap()->toImage();
+ QImage mbits = cursor.mask()->toImage();
+ scaleFactor /= bbits.devicePixelRatioF();
+ if (!qFuzzyCompare(scaleFactor, 1)) {
+ const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize();
+ bbits = bbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ mbits = mbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
+ }
+ bbits = bbits.convertToFormat(QImage::Format_Mono);
+ mbits = mbits.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 QSize systemCursorSize(const QPlatformScreen *screen = Q_NULLPTR)
+{
+ const QSize primaryScreenCursorSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR));
+ if (screen) {
+ // Correct the size if the DPI value of the screen differs from
+ // that of the primary screen.
+ if (const QScreen *primaryQScreen = QGuiApplication::primaryScreen()) {
+ const QPlatformScreen *primaryScreen = primaryQScreen->handle();
+ if (screen != primaryScreen) {
+ const qreal logicalDpi = screen->logicalDpi().first;
+ const qreal primaryScreenLogicalDpi = primaryScreen->logicalDpi().first;
+ if (!qFuzzyCompare(logicalDpi, primaryScreenLogicalDpi))
+ return (QSizeF(primaryScreenCursorSize) * logicalDpi / primaryScreenLogicalDpi).toSize();
+ }
+ }
+ }
+ return primaryScreenCursorSize;
+}
+
static inline QSize standardCursorSize() { return QSize(32, 32); }
#if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG)
@@ -242,7 +275,8 @@ static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &syst
return QWindowsCursor::PixmapCursor(rawImage, hotSpot);
}
-QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
+QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape,
+ const QPlatformScreen *screen)
{
// Non-standard Windows cursors are created from bitmaps
static const uchar vsplit_bits[] = {
@@ -410,13 +444,13 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor
switch (cursorShape) {
case Qt::SplitVCursor:
- return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, vsplit_bits, vsplitm_bits);
+ return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, vsplit_bits, vsplitm_bits);
case Qt::SplitHCursor:
- return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, hsplit_bits, hsplitm_bits);
+ return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, hsplit_bits, hsplitm_bits);
case Qt::OpenHandCursor:
- return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, openhand_bits, openhandm_bits);
+ return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, openhand_bits, openhandm_bits);
case Qt::ClosedHandCursor:
- return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
+ return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, closedhand_bits, closedhandm_bits);
case Qt::DragCopyCursor:
return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0));
case Qt::DragMoveCursor:
@@ -436,7 +470,7 @@ struct QWindowsCustomPngCursor {
int hotSpotY;
};
-QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape)
+QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen)
{
static const QWindowsCustomPngCursor pngCursors[] = {
{ Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 },
@@ -462,14 +496,14 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor
{ Qt::DragLinkCursor, 64, "draglinkcursor_64.png", 0, 0 }
};
- const int cursorSize = GetSystemMetrics(SM_CXCURSOR);
+ const QSize cursorSize = systemCursorSize(screen);
const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]);
const QWindowsCustomPngCursor *bestFit = 0;
int sizeDelta = INT_MAX;
for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) {
if (s->shape != cursorShape)
continue;
- const int currentSizeDelta = qMax(s->size, cursorSize) - qMin(s->size, cursorSize);
+ const int currentSizeDelta = qMax(s->size, cursorSize.width()) - qMin(s->size, cursorSize.width());
if (currentSizeDelta < sizeDelta) {
bestFit = s;
if (currentSizeDelta == 0)
@@ -492,7 +526,7 @@ struct QWindowsStandardCursorMapping {
LPCWSTR resource;
};
-HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
+HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen)
{
Q_ASSERT(cursorShape != Qt::BitmapCursor);
@@ -515,7 +549,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
switch (cursorShape) {
case Qt::BlankCursor: {
- QImage blank = QImage(systemCursorSize(), QImage::Format_Mono);
+ QImage blank = QImage(systemCursorSize(screen), QImage::Format_Mono);
blank.fill(0); // ignore color table
return createBitmapCursor(blank, blank);
}
@@ -526,7 +560,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape)
case Qt::DragCopyCursor:
case Qt::DragMoveCursor:
case Qt::DragLinkCursor:
- return QWindowsCursor::createPixmapCursor(customCursor(cursorShape));
+ return QWindowsCursor::createPixmapCursor(customCursor(cursorShape, screen));
default:
break;
}
@@ -555,7 +589,7 @@ CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape)
{
StandardCursorCache::Iterator it = m_standardCursorCache.find(shape);
if (it == m_standardCursorCache.end()) {
- if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape))
+ if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape, m_screen))
it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc)));
}
return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle);
@@ -582,17 +616,21 @@ 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) : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot());
+ ? createBitmapCursor(c, scaleFactor)
+ : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot(), scaleFactor);
it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc)));
}
return it.value();
}
-QWindowsCursor::QWindowsCursor()
+QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen)
+ : m_screen(screen)
{
- initResources();
+ static const bool dummy = initResources();
+ Q_UNUSED(dummy)
}
/*!
@@ -654,6 +692,94 @@ void QWindowsCursor::setPos(const QPoint &pos)
SetCursorPos(pos.x() , pos.y());
}
+QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const
+{
+ switch (action) {
+ case Qt::CopyAction:
+ if (m_copyDragCursor.isNull())
+ m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor, m_screen).pixmap;
+ return m_copyDragCursor;
+ case Qt::TargetMoveAction:
+ case Qt::MoveAction:
+ if (m_moveDragCursor.isNull())
+ m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor, m_screen).pixmap;
+ return m_moveDragCursor;
+ case Qt::LinkAction:
+ if (m_linkDragCursor.isNull())
+ m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor, m_screen).pixmap;
+ return m_linkDragCursor;
+ default:
+ break;
+ }
+
+ static const char * const ignoreDragCursorXpmC[] = {
+ "24 30 3 1",
+ ". c None",
+ "a c #000000",
+ "X c #FFFFFF",
+ "aa......................",
+ "aXa.....................",
+ "aXXa....................",
+ "aXXXa...................",
+ "aXXXXa..................",
+ "aXXXXXa.................",
+ "aXXXXXXa................",
+ "aXXXXXXXa...............",
+ "aXXXXXXXXa..............",
+ "aXXXXXXXXXa.............",
+ "aXXXXXXaaaa.............",
+ "aXXXaXXa................",
+ "aXXaaXXa................",
+ "aXa..aXXa...............",
+ "aa...aXXa...............",
+ "a.....aXXa..............",
+ "......aXXa.....XXXX.....",
+ ".......aXXa..XXaaaaXX...",
+ ".......aXXa.XaaaaaaaaX..",
+ "........aa.XaaaXXXXaaaX.",
+ "...........XaaaaX..XaaX.",
+ "..........XaaXaaaX..XaaX",
+ "..........XaaXXaaaX.XaaX",
+ "..........XaaX.XaaaXXaaX",
+ "..........XaaX..XaaaXaaX",
+ "...........XaaX..XaaaaX.",
+ "...........XaaaXXXXaaaX.",
+ "............XaaaaaaaaX..",
+ ".............XXaaaaXX...",
+ "...............XXXX....."};
+
+ if (m_ignoreDragCursor.isNull()) {
+#if !defined (Q_OS_WINCE)
+ HCURSOR cursor = LoadCursor(NULL, IDC_NO);
+ ICONINFO iconInfo = {0, 0, 0, 0, 0};
+ GetIconInfo(cursor, &iconInfo);
+ BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0};
+
+ if (iconInfo.hbmColor
+ && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
+ && bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
+ const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
+ uchar *colorBits = new uchar[colorBitsLength];
+ GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
+ const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
+ bmColor.bmWidthBytes, QImage::Format_ARGB32);
+
+ m_ignoreDragCursor = QPixmap::fromImage(colorImage);
+ delete [] colorBits;
+ } else {
+ m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
+ }
+
+ DeleteObject(iconInfo.hbmMask);
+ DeleteObject(iconInfo.hbmColor);
+ DestroyCursor(cursor);
+#else // !Q_OS_WINCE
+ m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC);
+#endif // !Q_OS_WINCE
+ }
+ return m_ignoreDragCursor;
+}
+
/*!
\class QWindowsWindowCursor
\brief Per-Window cursor. Contains a QCursor and manages its associated system