From 4ba4f17a6b23bda769e4f24673c6e0a3af8f76d6 Mon Sep 17 00:00:00 2001 From: dijunkun Date: Tue, 18 Nov 2025 16:24:28 +0800 Subject: [PATCH] [feat] capture cursor when connected to a web client --- src/gui/render.cpp | 5 +++-- src/gui/render.h | 1 + src/gui/render_callback.cpp | 15 +++++++++++++++ src/screen_capturer/linux/screen_capturer_x11.cpp | 2 +- src/screen_capturer/linux/screen_capturer_x11.h | 7 ++++++- .../macosx/screen_capturer_sck.cpp | 4 ++-- src/screen_capturer/macosx/screen_capturer_sck.h | 2 +- .../macosx/screen_capturer_sck_impl.mm | 8 +++++--- src/screen_capturer/screen_capturer.h | 2 +- .../windows/screen_capturer_wgc.cpp | 4 ++-- src/screen_capturer/windows/screen_capturer_wgc.h | 2 +- src/screen_capturer/windows/wgc_session.h | 2 +- src/screen_capturer/windows/wgc_session_impl.cpp | 4 ++-- src/screen_capturer/windows/wgc_session_impl.h | 2 +- 14 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/gui/render.cpp b/src/gui/render.cpp index 5f6d658..8efb218 100644 --- a/src/gui/render.cpp +++ b/src/gui/render.cpp @@ -329,8 +329,9 @@ int Render::ScreenCapturerInit() { int Render::StartScreenCapturer() { if (screen_capturer_) { - LOG_INFO("Start screen capturer"); - screen_capturer_->Start(); + LOG_INFO("Start screen capturer, show cursor: {}", show_cursor_); + + screen_capturer_->Start(show_cursor_); } return 0; diff --git a/src/gui/render.h b/src/gui/render.h index ab6d7e0..eb3faa1 100644 --- a/src/gui/render.h +++ b/src/gui/render.h @@ -316,6 +316,7 @@ class Render { bool start_speaker_capturer_ = false; bool speaker_capturer_is_started_ = false; bool start_keyboard_capturer_ = true; + bool show_cursor_ = false; bool keyboard_capturer_is_started_ = false; bool foucs_on_main_window_ = false; bool foucs_on_stream_window_ = false; diff --git a/src/gui/render_callback.cpp b/src/gui/render_callback.cpp index c7321ca..d657cf1 100644 --- a/src/gui/render_callback.cpp +++ b/src/gui/render_callback.cpp @@ -464,6 +464,13 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id, #else render->start_mouse_controller_ = true; #endif + if (std::all_of(render->connection_status_.begin(), + render->connection_status_.end(), [](const auto& kv) { + return kv.first.find("web") != std::string::npos; + })) { + render->show_cursor_ = true; + } + break; } case ConnectionStatus::Closed: { @@ -486,6 +493,14 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id, render->connection_status_.erase(remote_id); } + + if (std::all_of(render->connection_status_.begin(), + render->connection_status_.end(), [](const auto& kv) { + return kv.first.find("web") == std::string::npos; + })) { + render->show_cursor_ = false; + } + break; } default: diff --git a/src/screen_capturer/linux/screen_capturer_x11.cpp b/src/screen_capturer/linux/screen_capturer_x11.cpp index 5f6aeff..d928fd7 100644 --- a/src/screen_capturer/linux/screen_capturer_x11.cpp +++ b/src/screen_capturer/linux/screen_capturer_x11.cpp @@ -86,7 +86,7 @@ int ScreenCapturerX11::Destroy() { return 0; } -int ScreenCapturerX11::Start() { +int ScreenCapturerX11::Start(bool show_cursor) { if (running_) return 0; running_ = true; paused_ = false; diff --git a/src/screen_capturer/linux/screen_capturer_x11.h b/src/screen_capturer/linux/screen_capturer_x11.h index 7387b18..b40dcb5 100644 --- a/src/screen_capturer/linux/screen_capturer_x11.h +++ b/src/screen_capturer/linux/screen_capturer_x11.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,7 @@ class ScreenCapturerX11 : public ScreenCapturer { public: int Init(const int fps, cb_desktop_data cb) override; int Destroy() override; - int Start() override; + int Start(bool show_cursor) override; int Stop() override; int Pause(int monitor_index) override; @@ -54,6 +55,7 @@ class ScreenCapturerX11 : public ScreenCapturer { std::atomic running_{false}; std::atomic paused_{false}; std::atomic monitor_index_{0}; + std::atomic show_cursor_{true}; int fps_ = 60; cb_desktop_data callback_; std::vector display_info_list_; @@ -61,6 +63,9 @@ class ScreenCapturerX11 : public ScreenCapturer { // 缓冲区 std::vector y_plane_; std::vector uv_plane_; + + // 鼠标光标相关 + void DrawCursor(XImage* image, int x, int y); }; } // namespace crossdesk #endif \ No newline at end of file diff --git a/src/screen_capturer/macosx/screen_capturer_sck.cpp b/src/screen_capturer/macosx/screen_capturer_sck.cpp index bc85765..9cbfcfd 100644 --- a/src/screen_capturer/macosx/screen_capturer_sck.cpp +++ b/src/screen_capturer/macosx/screen_capturer_sck.cpp @@ -28,8 +28,8 @@ int ScreenCapturerSck::Destroy() { return 0; } -int ScreenCapturerSck::Start() { - screen_capturer_sck_impl_->Start(); +int ScreenCapturerSck::Start(bool show_cursor) { + screen_capturer_sck_impl_->Start(show_cursor); return 0; } diff --git a/src/screen_capturer/macosx/screen_capturer_sck.h b/src/screen_capturer/macosx/screen_capturer_sck.h index fcbfa60..42c3ac6 100644 --- a/src/screen_capturer/macosx/screen_capturer_sck.h +++ b/src/screen_capturer/macosx/screen_capturer_sck.h @@ -26,7 +26,7 @@ class ScreenCapturerSck : public ScreenCapturer { public: int Init(const int fps, cb_desktop_data cb) override; int Destroy() override; - int Start() override; + int Start(bool show_cursor) override; int Stop() override; int Pause(int monitor_index) override; diff --git a/src/screen_capturer/macosx/screen_capturer_sck_impl.mm b/src/screen_capturer/macosx/screen_capturer_sck_impl.mm index d8aa181..002ca71 100644 --- a/src/screen_capturer/macosx/screen_capturer_sck_impl.mm +++ b/src/screen_capturer/macosx/screen_capturer_sck_impl.mm @@ -57,7 +57,7 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSckImpl : public ScreenCapturer { public: int Init(const int fps, cb_desktop_data cb) override; - int Start() override; + int Start(bool show_cursor) override; int SwitchTo(int monitor_index) override; @@ -80,6 +80,7 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSckImpl : public ScreenCapturer { int width_ = 0; int height_ = 0; int fps_ = 60; + bool show_cursor_ = false; public: // Called by SckHelper when shareable content is returned by ScreenCaptureKit. `content` will be @@ -246,7 +247,8 @@ int ScreenCapturerSckImpl::Init(const int fps, cb_desktop_data cb) { return 0; } -int ScreenCapturerSckImpl::Start() { +int ScreenCapturerSckImpl::Start(bool show_cursor) { + show_cursor_ = show_cursor; StartOrReconfigureCapturer(); return 0; } @@ -328,7 +330,7 @@ void ScreenCapturerSckImpl::OnShareableContentCreated(SCShareableContent *conten excludingWindows:@[]]; SCStreamConfiguration *config = [[SCStreamConfiguration alloc] init]; config.pixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; - config.showsCursor = false; + config.showsCursor = show_cursor_; config.width = filter.contentRect.size.width * filter.pointPixelScale; config.height = filter.contentRect.size.height * filter.pointPixelScale; config.captureResolution = SCCaptureResolutionAutomatic; diff --git a/src/screen_capturer/screen_capturer.h b/src/screen_capturer/screen_capturer.h index 9e957be..0b5e0a4 100644 --- a/src/screen_capturer/screen_capturer.h +++ b/src/screen_capturer/screen_capturer.h @@ -24,7 +24,7 @@ class ScreenCapturer { public: virtual int Init(const int fps, cb_desktop_data cb) = 0; virtual int Destroy() = 0; - virtual int Start() = 0; + virtual int Start(bool show_cursor) = 0; virtual int Stop() = 0; virtual int Pause(int monitor_index) = 0; virtual int Resume(int monitor_index) = 0; diff --git a/src/screen_capturer/windows/screen_capturer_wgc.cpp b/src/screen_capturer/windows/screen_capturer_wgc.cpp index 01416a1..d6f9b09 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.cpp +++ b/src/screen_capturer/windows/screen_capturer_wgc.cpp @@ -152,7 +152,7 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) { int ScreenCapturerWgc::Destroy() { return 0; } -int ScreenCapturerWgc::Start() { +int ScreenCapturerWgc::Start(bool show_cursor) { if (running_ == true) { LOG_ERROR("Screen capturer already running"); return 0; @@ -172,7 +172,7 @@ int ScreenCapturerWgc::Start() { if (sessions_[i].running_) { LOG_ERROR("Session {} is already running", i); } else { - sessions_[i].session_->Start(); + sessions_[i].session_->Start(show_cursor); if (i != 0) { sessions_[i].session_->Pause(); diff --git a/src/screen_capturer/windows/screen_capturer_wgc.h b/src/screen_capturer/windows/screen_capturer_wgc.h index 0a209d7..3a21d9f 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.h +++ b/src/screen_capturer/windows/screen_capturer_wgc.h @@ -24,7 +24,7 @@ class ScreenCapturerWgc : public ScreenCapturer, int Init(const int fps, cb_desktop_data cb) override; int Destroy() override; - int Start() override; + int Start(bool show_cursor) override; int Stop() override; int Pause(int monitor_index) override; diff --git a/src/screen_capturer/windows/wgc_session.h b/src/screen_capturer/windows/wgc_session.h index 0fb3a5d..ff8471e 100644 --- a/src/screen_capturer/windows/wgc_session.h +++ b/src/screen_capturer/windows/wgc_session.h @@ -29,7 +29,7 @@ class WgcSession { virtual void RegisterObserver(wgc_session_observer* observer) = 0; - virtual int Start() = 0; + virtual int Start(bool show_cursor) = 0; virtual int Stop() = 0; virtual int Pause() = 0; diff --git a/src/screen_capturer/windows/wgc_session_impl.cpp b/src/screen_capturer/windows/wgc_session_impl.cpp index d64ca7d..9014c0a 100644 --- a/src/screen_capturer/windows/wgc_session_impl.cpp +++ b/src/screen_capturer/windows/wgc_session_impl.cpp @@ -55,7 +55,7 @@ void WgcSessionImpl::RegisterObserver(wgc_session_observer* observer) { observer_ = observer; } -int WgcSessionImpl::Start() { +int WgcSessionImpl::Start(bool show_cursor) { std::lock_guard locker(lock_); if (is_running_) return 0; @@ -91,7 +91,7 @@ int WgcSessionImpl::Start() { capture_session_.StartCapture(); - capture_session_.IsCursorCaptureEnabled(false); + capture_session_.IsCursorCaptureEnabled(show_cursor); error = 0; } catch (winrt::hresult_error) { diff --git a/src/screen_capturer/windows/wgc_session_impl.h b/src/screen_capturer/windows/wgc_session_impl.h index 4af3145..cf0e4ff 100644 --- a/src/screen_capturer/windows/wgc_session_impl.h +++ b/src/screen_capturer/windows/wgc_session_impl.h @@ -48,7 +48,7 @@ class WgcSessionImpl : public WgcSession { void RegisterObserver(wgc_session_observer* observer) override; - int Start() override; + int Start(bool show_cursor) override; int Stop() override; int Pause() override;