From c8eeefbd7ddb6724c7b2ea8ec282046edd8e74c7 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sun, 25 Oct 2020 17:19:07 +0200 Subject: [PATCH] platform/drm: Fix clipped HiDPI hardware cursors If an output is rotated, we will compute a transform matrix for the cursor plane to rotate its contents. In order to compute that matrix we need the rect of the cursor in the device-independent pixels, the scale factor and the output transform. The problem is that we provide a rect of the cursor in the native pixels. This may result in the cursor being partially or fully clipped. CCBUG: 424589 --- cursor.cpp | 5 +++++ cursor.h | 1 + plugins/platforms/drm/drm_output.cpp | 7 ++++--- plugins/scenes/opengl/scene_opengl.cpp | 3 +-- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/cursor.cpp b/cursor.cpp index bb9555f259..7686d2ce92 100644 --- a/cursor.cpp +++ b/cursor.cpp @@ -147,6 +147,11 @@ QRect Cursor::geometry() const return QRect(m_pos - hotspot(), image().size()); } +QRect Cursor::rect() const +{ + return QRect(QPoint(0, 0), image().size() / image().devicePixelRatio()); +} + QPoint Cursor::pos() { doGetPos(); diff --git a/cursor.h b/cursor.h index 883cb540d6..da707631db 100644 --- a/cursor.h +++ b/cursor.h @@ -163,6 +163,7 @@ public: QImage image() const { return m_image; } QPoint hotspot() const { return m_hotspot; } QRect geometry() const; + QRect rect() const; void updateCursor(const QImage &image, const QPoint &hotspot); void markAsRendered() { diff --git a/plugins/platforms/drm/drm_output.cpp b/plugins/platforms/drm/drm_output.cpp index 3f680f8248..9d2e50d5d7 100644 --- a/plugins/platforms/drm/drm_output.cpp +++ b/plugins/platforms/drm/drm_output.cpp @@ -136,7 +136,8 @@ void DrmOutput::updateCursor() if (m_deleted) { return; } - QImage cursorImage = Cursors::self()->currentCursor()->image(); + const Cursor *cursor = Cursors::self()->currentCursor(); + const QImage cursorImage = cursor->image(); if (cursorImage.isNull()) { return; } @@ -146,14 +147,14 @@ void DrmOutput::updateCursor() QPainter p; p.begin(c); - p.setWorldTransform(logicalToNativeMatrix(cursorImage.rect(), scale(), transform()).toTransform()); + p.setWorldTransform(logicalToNativeMatrix(cursor->rect(), scale(), transform()).toTransform()); p.drawImage(QPoint(0, 0), cursorImage); p.end(); } void DrmOutput::moveCursor(Cursor *cursor, const QPoint &globalPos) { - const QMatrix4x4 hotspotMatrix = logicalToNativeMatrix(cursor->image().rect(), scale(), transform()); + const QMatrix4x4 hotspotMatrix = logicalToNativeMatrix(cursor->rect(), scale(), transform()); const QMatrix4x4 monitorMatrix = logicalToNativeMatrix(geometry(), scale(), transform()); QPoint pos = monitorMatrix.map(globalPos); diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp index 77ae267106..bb4650377d 100644 --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -568,8 +568,7 @@ void SceneOpenGL2::paintCursor(const QRegion &rendered) // figure out which part of the cursor needs to be repainted const QPoint cursorPos = cursor->pos() - cursor->hotspot(); - const qreal scale = cursor->image().devicePixelRatio(); - const QRect cursorRect(QPoint(0, 0), cursor->image().size() / scale); + const QRect cursorRect = cursor->rect(); QRegion region; for (const QRect &rect : rendered) { region |= rect.translated(-cursorPos).intersected(cursorRect);