From 50489f2e41b42ae391580a01e76f255ae98de1cf Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 29 Jan 2016 13:40:00 +0100 Subject: [PATCH] Windows QPA: Fix drag cursor and hotspot for pixmaps with DPR. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce separate scale factors for hot spot and pixmap and set the devicePixelRatio of the scaled pixmap to 1 matching that of the target pixmap which will be converted to a Windows cursor. Change-Id: I0b0f6c6a79589ec954b5a1a09a86b87c91b5147d Task-number: QTBUG-46068 Reviewed-by: Joerg Bornemann Reviewed-by: Alexandru Croitor Reviewed-by: Morten Johan Sørvig --- .../platforms/windows/qwindowsdrag.cpp | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index c2e8c2426a..18e67ff1a3 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -282,30 +282,33 @@ void QWindowsOleDropSource::createCursors() const bool hasPixmap = !pixmap.isNull(); // Find screen for drag. Could be obtained from QDrag::source(), but that might be a QWidget. - - qreal scaleFactor = 1; - QPlatformCursor *platformCursor = Q_NULLPTR; - if (const QPlatformScreen *platformScreen = QWindowsContext::instance()->screenManager().screenAtDp(QWindowsCursor::mousePosition())) { - scaleFactor = QHighDpiScaling::factor(platformScreen); - platformCursor = platformScreen->cursor(); + const QPlatformScreen *platformScreen = QWindowsContext::instance()->screenManager().screenAtDp(QWindowsCursor::mousePosition()); + if (!platformScreen) { + if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) + platformScreen = primaryScreen->handle(); } - if (!platformCursor && QGuiApplication::primaryScreen()) - platformCursor = QGuiApplication::primaryScreen()->handle()->cursor(); + Q_ASSERT(platformScreen); + QPlatformCursor *platformCursor = platformScreen->cursor(); + + qreal pixmapScaleFactor = 1; + qreal hotSpotScaleFactor = 1; + if (m_mode != TouchDrag) { // Touch drag: pixmap is shown in a separate QWindow, which will be scaled.) + hotSpotScaleFactor = QHighDpiScaling::factor(platformScreen); + pixmapScaleFactor = hotSpotScaleFactor / pixmap.devicePixelRatio(); + } + QPixmap scaledPixmap = qFuzzyCompare(pixmapScaleFactor, 1.0) + ? pixmap + : pixmap.scaled((QSizeF(pixmap.size()) * pixmapScaleFactor).toSize(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + scaledPixmap.setDevicePixelRatio(1); - const bool scalePixmap = hasPixmap - && m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled. - && (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio())); - const QPixmap scaledPixmap = scalePixmap - ? pixmap.scaled((QSizeF(pixmap.size()) * scaleFactor).toSize(), - Qt::KeepAspectRatio, Qt::SmoothTransformation) - : pixmap; Qt::DropAction actions[] = { Qt::MoveAction, Qt::CopyAction, Qt::LinkAction, Qt::IgnoreAction }; int actionCount = int(sizeof(actions) / sizeof(actions[0])); if (!hasPixmap) --actionCount; // No Qt::IgnoreAction unless pixmap - const QPoint hotSpot = scalePixmap - ? (QPointF(drag->hotSpot()) * scaleFactor).toPoint() - : drag->hotSpot(); + const QPoint hotSpot = qFuzzyCompare(hotSpotScaleFactor, 1.0) + ? drag->hotSpot() + : (QPointF(drag->hotSpot()) * hotSpotScaleFactor).toPoint(); for (int cnum = 0; cnum < actionCount; ++cnum) { const Qt::DropAction action = actions[cnum]; QPixmap cursorPixmap = drag->dragCursor(action);