fix wrong cursor hotspot under Wayland on VMs

This commit is contained in:
Andrey Butirsky 2021-08-02 09:03:07 +00:00 committed by David Edmundson
parent 47e38b7141
commit 998bbf4eba
3 changed files with 15 additions and 7 deletions

View file

@ -103,7 +103,8 @@ bool DrmOutput::hideCursor()
bool DrmOutput::showCursor() bool DrmOutput::showCursor()
{ {
bool visibleBefore = m_pipeline->isCursorVisible(); 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 if (RenderLoopPrivate::get(m_renderLoop)->presentMode == RenderLoopPrivate::SyncMode::Adaptive
&& !visibleBefore && !visibleBefore
&& m_pipeline->isCursorVisible()) { && m_pipeline->isCursorVisible()) {
@ -149,7 +150,7 @@ bool DrmOutput::updateCursor()
p.setWorldTransform(logicalToNativeMatrix(cursor->rect(), 1, transform()).toTransform()); p.setWorldTransform(logicalToNativeMatrix(cursor->rect(), 1, transform()).toTransform());
p.drawImage(QPoint(0, 0), cursorImage); p.drawImage(QPoint(0, 0), cursorImage);
p.end(); 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 if (RenderLoopPrivate::get(m_renderLoop)->presentMode == RenderLoopPrivate::SyncMode::Adaptive
&& m_pipeline->isCursorVisible()) { && m_pipeline->isCursorVisible()) {
m_renderLoop->scheduleRepaint(); m_renderLoop->scheduleRepaint();

View file

@ -305,18 +305,24 @@ bool DrmPipeline::checkTestBuffer()
return false; return false;
} }
bool DrmPipeline::setCursor(const QSharedPointer<DrmDumbBuffer> &buffer) bool DrmPipeline::setCursor(const QSharedPointer<DrmDumbBuffer> &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; return true;
} }
const QSize &s = buffer ? buffer->size() : QSize(64, 64); 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); qCWarning(KWIN_DRM) << "Could not set cursor:" << strerror(errno);
return false; return false;
} }
m_cursor.buffer = buffer; m_cursor.buffer = buffer;
m_cursor.dirty = false; m_cursor.dirty = false;
m_cursor.hotspot = hotspot;
return true; return true;
} }
@ -374,7 +380,7 @@ bool DrmPipeline::setActive(bool active)
} }
if (m_active) { if (m_active) {
// enable cursor (again) // enable cursor (again)
setCursor(m_cursor.buffer); setCursor(m_cursor.buffer, m_cursor.hotspot);
} }
return success; return success;
} }

View file

@ -54,7 +54,7 @@ public:
bool test(const QVector<DrmPipeline*> &pipelines); bool test(const QVector<DrmPipeline*> &pipelines);
bool modeset(int modeIndex); bool modeset(int modeIndex);
bool setCursor(const QSharedPointer<DrmDumbBuffer> &buffer); bool setCursor(const QSharedPointer<DrmDumbBuffer> &buffer, const QPoint &hotspot = QPoint());
bool setActive(bool enable); bool setActive(bool enable);
bool setGammaRamp(const GammaRamp &ramp); bool setGammaRamp(const GammaRamp &ramp);
bool setTransformation(const DrmPlane::Transformations &transform); bool setTransformation(const DrmPlane::Transformations &transform);
@ -103,6 +103,7 @@ private:
bool m_legacyNeedsModeset = true; bool m_legacyNeedsModeset = true;
struct { struct {
QPoint pos = QPoint(100, 100); QPoint pos = QPoint(100, 100);
QPoint hotspot;
QSharedPointer<DrmDumbBuffer> buffer; QSharedPointer<DrmDumbBuffer> buffer;
bool dirty = true;// we don't know what the current state is bool dirty = true;// we don't know what the current state is
} m_cursor; } m_cursor;