diff --git a/plugins/platforms/drm/drm_backend.cpp b/plugins/platforms/drm/drm_backend.cpp index 2467cce3dd..c15f3f4f44 100644 --- a/plugins/platforms/drm/drm_backend.cpp +++ b/plugins/platforms/drm/drm_backend.cpp @@ -152,14 +152,16 @@ void DrmBackend::reactivate() return; } m_active = true; - DrmBuffer *c = m_cursor[(m_cursorIndex + 1) % 2]; - const QPoint cp = Cursor::pos() - softwareCursorHotspot(); - for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { - DrmOutput *o = *it; - o->pageFlipped(); - o->blank(); - o->showCursor(c); - o->moveCursor(cp); + if (!usesSoftwareCursor()) { + DrmBuffer *c = m_cursor[(m_cursorIndex + 1) % 2]; + const QPoint cp = Cursor::pos() - softwareCursorHotspot(); + for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { + DrmOutput *o = *it; + o->pageFlipped(); + o->blank(); + o->showCursor(c); + o->moveCursor(cp); + } } // restart compositor m_pageFlipsPending = 0; @@ -473,6 +475,9 @@ void DrmBackend::initCursor() connect(waylandServer()->seat(), &KWayland::Server::SeatInterface::hasPointerChanged, this, [this] { m_cursorEnabled = waylandServer()->seat()->hasPointer(); + if (usesSoftwareCursor()) { + return; + } for (auto it = m_outputs.constBegin(); it != m_outputs.constEnd(); ++it) { if (m_cursorEnabled) { (*it)->showCursor(m_cursor[m_cursorIndex]); @@ -494,12 +499,18 @@ void DrmBackend::initCursor() } else { cursorSize.setHeight(64); } - m_cursor[0] = createBuffer(cursorSize); - m_cursor[0]->map(QImage::Format_ARGB32_Premultiplied); - m_cursor[0]->image()->fill(Qt::transparent); - m_cursor[1] = createBuffer(cursorSize); - m_cursor[1]->map(QImage::Format_ARGB32_Premultiplied); - m_cursor[1]->image()->fill(Qt::transparent); + auto createCursor = [this, cursorSize] (int index) { + m_cursor[index] = createBuffer(cursorSize); + if (!m_cursor[index]->map(QImage::Format_ARGB32_Premultiplied)) { + return false; + } + m_cursor[index]->image()->fill(Qt::transparent); + return true; + }; + if (!createCursor(0) || !createCursor(1)) { + setSoftWareCursor(true); + return; + } // now we have screens and can set cursors, so start tracking connect(this, &DrmBackend::cursorChanged, this, &DrmBackend::updateCursor); connect(Cursor::self(), &Cursor::posChanged, this, &DrmBackend::moveCursor); @@ -519,6 +530,9 @@ void DrmBackend::setCursor() void DrmBackend::updateCursor() { + if (usesSoftwareCursor()) { + return; + } const QImage &cursorImage = softwareCursor(); if (cursorImage.isNull()) { hideCursor(); diff --git a/plugins/platforms/fbdev/fb_backend.cpp b/plugins/platforms/fbdev/fb_backend.cpp index 95b0925e6c..fc7ed42c78 100644 --- a/plugins/platforms/fbdev/fb_backend.cpp +++ b/plugins/platforms/fbdev/fb_backend.cpp @@ -38,7 +38,6 @@ namespace KWin FramebufferBackend::FramebufferBackend(QObject *parent) : Platform(parent) { - setSoftWareCursor(true); } FramebufferBackend::~FramebufferBackend() @@ -61,6 +60,7 @@ QPainterBackend *FramebufferBackend::createQPainterBackend() void FramebufferBackend::init() { + setSoftWareCursor(true); LogindIntegration *logind = LogindIntegration::self(); auto takeControl = [logind, this]() { if (logind->hasSessionControl()) { diff --git a/plugins/platforms/fbdev/scene_qpainter_fb_backend.cpp b/plugins/platforms/fbdev/scene_qpainter_fb_backend.cpp index 7399bad34c..732d5f31fe 100644 --- a/plugins/platforms/fbdev/scene_qpainter_fb_backend.cpp +++ b/plugins/platforms/fbdev/scene_qpainter_fb_backend.cpp @@ -87,19 +87,4 @@ bool FramebufferQPainterBackend::usesOverlayWindow() const return false; } -void FramebufferQPainterBackend::renderCursor(QPainter *painter) -{ - if (!m_backend->usesSoftwareCursor()) { - return; - } - const QImage img = m_backend->softwareCursor(); - if (img.isNull()) { - return; - } - const QPoint cursorPos = Cursor::pos(); - const QPoint hotspot = m_backend->softwareCursorHotspot(); - painter->drawImage(cursorPos - hotspot, img); - m_backend->markCursorAsRendered(); -} - } diff --git a/plugins/platforms/fbdev/scene_qpainter_fb_backend.h b/plugins/platforms/fbdev/scene_qpainter_fb_backend.h index f089533956..73d6268bb0 100644 --- a/plugins/platforms/fbdev/scene_qpainter_fb_backend.h +++ b/plugins/platforms/fbdev/scene_qpainter_fb_backend.h @@ -39,7 +39,6 @@ public: bool usesOverlayWindow() const override; void prepareRenderingFrame() override; void present(int mask, const QRegion &damage) override; - void renderCursor(QPainter *painter) override; private: QImage m_renderBuffer; diff --git a/plugins/platforms/virtual/scene_qpainter_virtual_backend.cpp b/plugins/platforms/virtual/scene_qpainter_virtual_backend.cpp index 9027538093..84ccecf5af 100644 --- a/plugins/platforms/virtual/scene_qpainter_virtual_backend.cpp +++ b/plugins/platforms/virtual/scene_qpainter_virtual_backend.cpp @@ -70,19 +70,4 @@ bool VirtualQPainterBackend::usesOverlayWindow() const return false; } -void VirtualQPainterBackend::renderCursor(QPainter *painter) -{ - if (!m_backend->usesSoftwareCursor()) { - return; - } - const QImage img = m_backend->softwareCursor(); - if (img.isNull()) { - return; - } - const QPoint cursorPos = Cursor::pos(); - const QPoint hotspot = m_backend->softwareCursorHotspot(); - painter->drawImage(cursorPos - hotspot, img); - m_backend->markCursorAsRendered(); -} - } diff --git a/plugins/platforms/virtual/scene_qpainter_virtual_backend.h b/plugins/platforms/virtual/scene_qpainter_virtual_backend.h index a81e9589a0..3c91195ae4 100644 --- a/plugins/platforms/virtual/scene_qpainter_virtual_backend.h +++ b/plugins/platforms/virtual/scene_qpainter_virtual_backend.h @@ -42,7 +42,6 @@ public: void prepareRenderingFrame() override; void present(int mask, const QRegion &damage) override; void screenGeometryChanged(const QSize &size) override; - void renderCursor(QPainter *painter) override; private: QImage m_backBuffer; diff --git a/plugins/platforms/virtual/virtual_backend.cpp b/plugins/platforms/virtual/virtual_backend.cpp index b231fbb5e5..396b56cd54 100644 --- a/plugins/platforms/virtual/virtual_backend.cpp +++ b/plugins/platforms/virtual/virtual_backend.cpp @@ -42,7 +42,6 @@ VirtualBackend::VirtualBackend(QObject *parent) qDebug() << "Screenshots saved to: " << m_screenshotDir->path(); } } - setSoftWareCursor(true); setSupportsPointerWarping(true); } @@ -50,6 +49,7 @@ VirtualBackend::~VirtualBackend() = default; void VirtualBackend::init() { + setSoftWareCursor(true); m_size = initialWindowSize(); setReady(true); waylandServer()->seat()->setHasPointer(true); diff --git a/scene.cpp b/scene.cpp index 7d9f3d2dd1..834a731e60 100644 --- a/scene.cpp +++ b/scene.cpp @@ -964,7 +964,8 @@ void WindowPixmap::create() if (isValid() || toplevel()->isDeleted()) { return; } - if (toplevel()->surface()) { + // always update from Buffer on Wayland, don't try using XPixmap + if (kwinApp()->shouldUseWaylandForCompositing()) { // use Buffer updateBuffer(); if ((m_buffer || !m_fbo.isNull()) && m_subSurface.isNull()) { diff --git a/scene_qpainter.cpp b/scene_qpainter.cpp index bd4b9dd961..477aefd5f3 100644 --- a/scene_qpainter.cpp +++ b/scene_qpainter.cpp @@ -73,11 +73,6 @@ void QPainterBackend::setFailed(const QString &reason) m_failed = true; } -void QPainterBackend::renderCursor(QPainter *painter) -{ - Q_UNUSED(painter) -} - bool QPainterBackend::perScreenRendering() const { return false; @@ -163,6 +158,7 @@ qint64 SceneQPainter::paint(QRegion damage, ToplevelList toplevels) QRegion updateRegion, validRegion; paintScreen(&mask, damage.intersected(geometry), QRegion(), &updateRegion, &validRegion); overallUpdate = overallUpdate.united(updateRegion); + paintCursor(); m_painter->restore(); m_painter->end(); @@ -171,6 +167,8 @@ qint64 SceneQPainter::paint(QRegion damage, ToplevelList toplevels) m_backend->present(mask, overallUpdate); } else { m_painter->begin(m_backend->buffer()); + m_painter->setClipping(true); + m_painter->setClipRegion(damage); if (m_backend->needsFullRepaint()) { mask |= Scene::PAINT_SCREEN_BACKGROUND_FIRST; damage = QRegion(0, 0, displayWidth(), displayHeight()); @@ -178,7 +176,7 @@ qint64 SceneQPainter::paint(QRegion damage, ToplevelList toplevels) QRegion updateRegion, validRegion; paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion); - m_backend->renderCursor(m_painter.data()); + paintCursor(); m_backend->showOverlay(); m_painter->end(); @@ -197,6 +195,21 @@ void SceneQPainter::paintBackground(QRegion region) m_painter->drawRects(region.rects()); } +void SceneQPainter::paintCursor() +{ + if (!kwinApp()->platform()->usesSoftwareCursor()) { + return; + } + const QImage img = kwinApp()->platform()->softwareCursor(); + if (img.isNull()) { + return; + } + const QPoint cursorPos = Cursor::pos(); + const QPoint hotspot = kwinApp()->platform()->softwareCursorHotspot(); + m_painter->drawImage(cursorPos - hotspot, img); + kwinApp()->platform()->markCursorAsRendered(); +} + Scene::Window *SceneQPainter::createWindow(Toplevel *toplevel) { return new SceneQPainter::Window(this, toplevel); @@ -267,10 +280,10 @@ void SceneQPainter::Window::performPaint(int mask, QRegion region, WindowPaintDa QPainter *scenePainter = m_scene->painter(); QPainter *painter = scenePainter; + painter->save(); painter->setClipRegion(region); painter->setClipping(true); - painter->save(); painter->translate(x(), y()); if (mask & PAINT_WINDOW_TRANSFORMED) { painter->translate(data.xTranslation(), data.yTranslation()); @@ -317,9 +330,6 @@ void SceneQPainter::Window::performPaint(int mask, QRegion region, WindowPaintDa } painter->restore(); - - painter->setClipRegion(QRegion()); - painter->setClipping(false); } void SceneQPainter::Window::renderShadow(QPainter* painter) diff --git a/scene_qpainter.h b/scene_qpainter.h index f5b3af0023..2292142662 100644 --- a/scene_qpainter.h +++ b/scene_qpainter.h @@ -80,7 +80,6 @@ public: **/ virtual QImage *bufferForScreen(int screenId); virtual bool needsFullRepaint() const = 0; - virtual void renderCursor(QPainter *painter); /** * Whether the rendering needs to be split per screen. * Default implementation returns @c false. @@ -130,6 +129,7 @@ protected: private: explicit SceneQPainter(QPainterBackend *backend, QObject *parent = nullptr); + void paintCursor(); QScopedPointer m_backend; QScopedPointer m_painter; class Window;