diff --git a/platform.cpp b/platform.cpp index 08e47609df..0cb89ef5b5 100644 --- a/platform.cpp +++ b/platform.cpp @@ -197,6 +197,7 @@ void Platform::setSoftWareCursor(bool set) disconnect(Cursors::self(), &Cursors::positionChanged, this, &Platform::triggerCursorRepaint); disconnect(Cursors::self(), &Cursors::currentCursorChanged, this, &Platform::triggerCursorRepaint); } + triggerCursorRepaint(); } void Platform::triggerCursorRepaint() diff --git a/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp index a5e46ce660..77ae267106 100644 --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -555,7 +555,7 @@ void SceneOpenGL::insertWait() * Render cursor texture in case hardware cursor is disabled. * Useful for screen recording apps or backends that can't do planes. */ -void SceneOpenGL2::paintCursor() +void SceneOpenGL2::paintCursor(const QRegion &rendered) { Cursor* cursor = Cursors::self()->currentCursor(); @@ -566,6 +566,18 @@ void SceneOpenGL2::paintCursor() return; } + // 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); + QRegion region; + for (const QRect &rect : rendered) { + region |= rect.translated(-cursorPos).intersected(cursorRect); + } + if (region.isEmpty()) { + return; + } + // lazy init texture cursor only in case we need software rendering if (!m_cursorTexture) { auto updateCursorTexture = [this] { @@ -585,9 +597,6 @@ void SceneOpenGL2::paintCursor() } // get cursor position in projection coordinates - const qreal scale = cursor->image().devicePixelRatio(); - const QPoint cursorPos = cursor->pos() - cursor->hotspot(); - const QRect cursorRect(QPoint(0, 0), m_cursorTexture->size() / scale); QMatrix4x4 mvp = m_projectionMatrix; mvp.translate(cursorPos.x(), cursorPos.y()); @@ -599,7 +608,7 @@ void SceneOpenGL2::paintCursor() m_cursorTexture->bind(); ShaderBinder binder(ShaderTrait::MapTexture); binder.shader()->setUniform(GLShader::ModelViewProjectionMatrix, mvp); - m_cursorTexture->render(QRegion(cursorRect), cursorRect); + m_cursorTexture->render(region, cursorRect); m_cursorTexture->unbind(); glDisable(GL_BLEND); } @@ -645,7 +654,7 @@ qint64 SceneOpenGL::paint(const QRegion &damage, const QList &toplev updateProjectionMatrix(); paintScreen(&mask, damage.intersected(geo), repaint, &update, &valid, projectionMatrix(), geo, scaling); // call generic implementation - paintCursor(); + paintCursor(valid); GLVertexBuffer::streamingBuffer()->endOfFrame(); diff --git a/plugins/scenes/opengl/scene_opengl.h b/plugins/scenes/opengl/scene_opengl.h index 60dca99e82..8d02e420e8 100644 --- a/plugins/scenes/opengl/scene_opengl.h +++ b/plugins/scenes/opengl/scene_opengl.h @@ -123,7 +123,7 @@ protected: Scene::Window *createWindow(Toplevel *t) override; void finalDrawWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data) override; void updateProjectionMatrix() override; - void paintCursor() override; + void paintCursor(const QRegion ®ion) override; private: void performPaintWindow(EffectWindowImpl* w, int mask, const QRegion ®ion, WindowPaintData& data); diff --git a/plugins/scenes/qpainter/scene_qpainter.cpp b/plugins/scenes/qpainter/scene_qpainter.cpp index e4bac24414..2750a594e7 100644 --- a/plugins/scenes/qpainter/scene_qpainter.cpp +++ b/plugins/scenes/qpainter/scene_qpainter.cpp @@ -110,7 +110,7 @@ qint64 SceneQPainter::paint(const QRegion &_damage, const QList &top QRegion updateRegion, validRegion; paintScreen(&mask, damage.intersected(geometry), QRegion(), &updateRegion, &validRegion); overallUpdate = overallUpdate.united(updateRegion); - paintCursor(); + paintCursor(updateRegion); m_painter->restore(); m_painter->end(); @@ -128,7 +128,7 @@ qint64 SceneQPainter::paint(const QRegion &_damage, const QList &top QRegion updateRegion, validRegion; paintScreen(&mask, damage, QRegion(), &updateRegion, &validRegion); - paintCursor(); + paintCursor(updateRegion); m_backend->showOverlay(); m_painter->end(); @@ -149,7 +149,7 @@ void SceneQPainter::paintBackground(const QRegion ®ion) } } -void SceneQPainter::paintCursor() +void SceneQPainter::paintCursor(const QRegion &rendered) { if (!kwinApp()->platform()->usesSoftwareCursor()) { return; @@ -160,9 +160,11 @@ void SceneQPainter::paintCursor() if (img.isNull()) { return; } - const QPoint cursorPos = cursor->pos(); - const QPoint hotspot = cursor->hotspot(); - m_painter->drawImage(cursorPos - hotspot, img); + + m_painter->save(); + m_painter->setClipRegion(rendered.intersected(cursor->geometry())); + m_painter->drawImage(cursor->geometry(), img); + m_painter->restore(); } void SceneQPainter::paintEffectQuickView(EffectQuickView *w) diff --git a/plugins/scenes/qpainter/scene_qpainter.h b/plugins/scenes/qpainter/scene_qpainter.h index 8a727d096f..1e03571ca4 100644 --- a/plugins/scenes/qpainter/scene_qpainter.h +++ b/plugins/scenes/qpainter/scene_qpainter.h @@ -50,7 +50,7 @@ public: protected: void paintBackground(const QRegion ®ion) override; Scene::Window *createWindow(Toplevel *toplevel) override; - void paintCursor() override; + void paintCursor(const QRegion ®ion) override; void paintEffectQuickView(EffectQuickView *w) override; private: diff --git a/plugins/scenes/xrender/scene_xrender.cpp b/plugins/scenes/xrender/scene_xrender.cpp index 1e93ce7029..1243caa22a 100644 --- a/plugins/scenes/xrender/scene_xrender.cpp +++ b/plugins/scenes/xrender/scene_xrender.cpp @@ -1326,9 +1326,9 @@ Scene *XRenderFactory::create(QObject *parent) const #endif -void KWin::SceneXrender::paintCursor() +void KWin::SceneXrender::paintCursor(const QRegion ®ion) { - + Q_UNUSED(region) } void KWin::SceneXrender::paintEffectQuickView(KWin::EffectQuickView *w) diff --git a/plugins/scenes/xrender/scene_xrender.h b/plugins/scenes/xrender/scene_xrender.h index 4a93d6fa63..22f7cea0b1 100644 --- a/plugins/scenes/xrender/scene_xrender.h +++ b/plugins/scenes/xrender/scene_xrender.h @@ -166,7 +166,7 @@ protected: void paintBackground(const QRegion ®ion) override; void paintGenericScreen(int mask, const ScreenPaintData &data) override; void paintDesktop(int desktop, int mask, const QRegion ®ion, ScreenPaintData &data) override; - void paintCursor() override; + void paintCursor(const QRegion ®ion) override; void paintEffectQuickView(EffectQuickView *w) override; private: explicit SceneXrender(XRenderBackend *backend, QObject *parent = nullptr); diff --git a/scene.h b/scene.h index fc25ae5cc9..f03fb2132e 100644 --- a/scene.h +++ b/scene.h @@ -208,7 +208,7 @@ protected: void paintScreen(int *mask, const QRegion &damage, const QRegion &repaint, QRegion *updateRegion, QRegion *validRegion, const QMatrix4x4 &projection = QMatrix4x4(), const QRect &outputGeometry = QRect(), const qreal screenScale = 1.0); // Render cursor texture in case hardware cursor is disabled/non-applicable - virtual void paintCursor() = 0; + virtual void paintCursor(const QRegion ®ion) = 0; friend class EffectsHandlerImpl; // called after all effects had their paintScreen() called void finalPaintScreen(int mask, const QRegion ®ion, ScreenPaintData& data);