From 9f44013fb5f4c5170e2d43f230cb601958be39b2 Mon Sep 17 00:00:00 2001 From: Jan Grulich Date: Wed, 5 Jan 2022 11:41:56 +0100 Subject: [PATCH] Screencast: update PW buffer with only mouse cursor metadata on cursor change As of now, we update cursor metadata only when the screen content changes, but this results into not having smooth cursor movement. We can update only mouse cursor location when it changes and send an empty buffer with mouse cursor metadata so clients can have update mouse location. --- src/plugins/screencast/screencaststream.cpp | 34 +++++++++++++++++++++ src/plugins/screencast/screencaststream.h | 3 ++ 2 files changed, 37 insertions(+) diff --git a/src/plugins/screencast/screencaststream.cpp b/src/plugins/screencast/screencaststream.cpp index 2932e62a90..18a56ae26a 100644 --- a/src/plugins/screencast/screencaststream.cpp +++ b/src/plugins/screencast/screencaststream.cpp @@ -305,6 +305,8 @@ bool ScreenCastStream::createStream() connect(Cursors::self(), &Cursors::positionChanged, this, [this] { recordFrame(QRegion{m_cursor.lastRect} | cursorGeometry(Cursors::self()->currentCursor())); }); + } else if (m_cursor.mode == KWaylandServer::ScreencastV1Interface::Metadata) { + connect(Cursors::self(), &Cursors::positionChanged, this, &ScreenCastStream::recordCursor); } return true; @@ -458,6 +460,38 @@ void ScreenCastStream::recordFrame(const QRegion &damagedRegion) tryEnqueue(buffer); } +void ScreenCastStream::recordCursor() +{ + Q_ASSERT(!m_stopped); + + if (m_pendingBuffer) { + qCWarning(KWIN_SCREENCAST) << "Dropping a screencast cursor update because the compositor is slow"; + return; + } + + const char *error = ""; + auto state = pw_stream_get_state(pwStream, &error); + if (state != PW_STREAM_STATE_STREAMING) { + if (error) { + qCWarning(KWIN_SCREENCAST) << "Failed to record cursor position: stream is not active" << error; + } + return; + } + + struct pw_buffer *buffer = pw_stream_dequeue_buffer(pwStream); + + if (!buffer) { + return; + } + + struct spa_buffer *spa_buffer = buffer->buffer; + spa_buffer->datas[0].chunk->size = 0; + sendCursorData(Cursors::self()->currentCursor(), + (spa_meta_cursor *) spa_buffer_find_meta_data (spa_buffer, SPA_META_Cursor, sizeof (spa_meta_cursor))); + + tryEnqueue(buffer); +} + void ScreenCastStream::tryEnqueue(pw_buffer *buffer) { m_pendingBuffer = buffer; diff --git a/src/plugins/screencast/screencaststream.h b/src/plugins/screencast/screencaststream.h index 829eb84c4d..b53c5b3ab1 100644 --- a/src/plugins/screencast/screencaststream.h +++ b/src/plugins/screencast/screencaststream.h @@ -55,6 +55,9 @@ public: void setCursorMode(KWaylandServer::ScreencastV1Interface::CursorMode mode, qreal scale, const QRect &viewport); +public Q_SLOTS: + void recordCursor(); + Q_SIGNALS: void streamReady(quint32 nodeId); void startStreaming();