Windows QPA: Fix drag cursor and hotspot for pixmaps with DPR.

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 <joerg.bornemann@theqtcompany.com>
Reviewed-by: Alexandru Croitor <alexandru.croitor@theqtcompany.com>
Reviewed-by: Morten Johan Sørvig <morten.sorvig@theqtcompany.com>
This commit is contained in:
Friedemann Kleint 2016-01-29 13:40:00 +01:00
parent 3cd69671db
commit 50489f2e41

View File

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