diff --git a/src/plugins/platforms/drm/drm_output.cpp b/src/plugins/platforms/drm/drm_output.cpp index 76382f499a..a8b9ba6ebc 100644 --- a/src/plugins/platforms/drm/drm_output.cpp +++ b/src/plugins/platforms/drm/drm_output.cpp @@ -103,7 +103,8 @@ bool DrmOutput::hideCursor() bool DrmOutput::showCursor() { bool visibleBefore = m_pipeline->isCursorVisible(); - if (m_pipeline->setCursor(m_cursor)) { + const Cursor * const cursor = Cursors::self()->currentCursor(); + if (m_pipeline->setCursor(m_cursor, logicalToNativeMatrix(cursor->rect(), scale(), transform()).map(cursor->hotspot()) )) { if (RenderLoopPrivate::get(m_renderLoop)->presentMode == RenderLoopPrivate::SyncMode::Adaptive && !visibleBefore && m_pipeline->isCursorVisible()) { @@ -149,7 +150,7 @@ bool DrmOutput::updateCursor() p.setWorldTransform(logicalToNativeMatrix(cursor->rect(), 1, transform()).toTransform()); p.drawImage(QPoint(0, 0), cursorImage); p.end(); - if (m_pipeline->setCursor(m_cursor)) { + if (m_pipeline->setCursor(m_cursor, logicalToNativeMatrix(cursor->rect(), scale(), transform()).map(cursor->hotspot()) )) { if (RenderLoopPrivate::get(m_renderLoop)->presentMode == RenderLoopPrivate::SyncMode::Adaptive && m_pipeline->isCursorVisible()) { m_renderLoop->scheduleRepaint(); diff --git a/src/plugins/platforms/drm/drm_pipeline.cpp b/src/plugins/platforms/drm/drm_pipeline.cpp index 45903b9c42..6b8571c4c8 100644 --- a/src/plugins/platforms/drm/drm_pipeline.cpp +++ b/src/plugins/platforms/drm/drm_pipeline.cpp @@ -305,18 +305,24 @@ bool DrmPipeline::checkTestBuffer() return false; } -bool DrmPipeline::setCursor(const QSharedPointer &buffer) +bool DrmPipeline::setCursor(const QSharedPointer &buffer, const QPoint &hotspot) { - if (!m_cursor.dirty && m_cursor.buffer == buffer) { + if (!m_cursor.dirty && m_cursor.buffer == buffer && m_cursor.hotspot == hotspot) { return true; } const QSize &s = buffer ? buffer->size() : QSize(64, 64); - if (drmModeSetCursor(m_gpu->fd(), m_crtc->id(), buffer ? buffer->handle() : 0, s.width(), s.height()) != 0) { + int ret = drmModeSetCursor2(m_gpu->fd(), m_crtc->id(), buffer ? buffer->handle() : 0, s.width(), s.height(), hotspot.x(), hotspot.y()); + if (ret == ENOTSUP) { + // for NVIDIA case that does not support drmModeSetCursor2 + ret = drmModeSetCursor(m_gpu->fd(), m_crtc->id(), buffer ? buffer->handle() : 0, s.width(), s.height()); + } + if (ret != 0) { qCWarning(KWIN_DRM) << "Could not set cursor:" << strerror(errno); return false; } m_cursor.buffer = buffer; m_cursor.dirty = false; + m_cursor.hotspot = hotspot; return true; } @@ -374,7 +380,7 @@ bool DrmPipeline::setActive(bool active) } if (m_active) { // enable cursor (again) - setCursor(m_cursor.buffer); + setCursor(m_cursor.buffer, m_cursor.hotspot); } return success; } diff --git a/src/plugins/platforms/drm/drm_pipeline.h b/src/plugins/platforms/drm/drm_pipeline.h index d49695a561..fda720fb1d 100644 --- a/src/plugins/platforms/drm/drm_pipeline.h +++ b/src/plugins/platforms/drm/drm_pipeline.h @@ -54,7 +54,7 @@ public: bool test(const QVector &pipelines); bool modeset(int modeIndex); - bool setCursor(const QSharedPointer &buffer); + bool setCursor(const QSharedPointer &buffer, const QPoint &hotspot = QPoint()); bool setActive(bool enable); bool setGammaRamp(const GammaRamp &ramp); bool setTransformation(const DrmPlane::Transformations &transform); @@ -103,6 +103,7 @@ private: bool m_legacyNeedsModeset = true; struct { QPoint pos = QPoint(100, 100); + QPoint hotspot; QSharedPointer buffer; bool dirty = true;// we don't know what the current state is } m_cursor;