From 33d51b8ce58896fd0078a670b10f8a9ee1e2e6ca Mon Sep 17 00:00:00 2001 From: dijunkun Date: Mon, 2 Mar 2026 15:42:44 +0800 Subject: [PATCH] [fix] reset to initial monitor on connection close via ResetToInitialMonitor to fix black screen --- src/gui/render_callback.cpp | 3 +++ .../linux/screen_capturer_x11.cpp | 4 ++++ .../linux/screen_capturer_x11.h | 2 ++ .../macosx/screen_capturer_sck.cpp | 7 ++++++ .../macosx/screen_capturer_sck.h | 1 + .../macosx/screen_capturer_sck_impl.mm | 22 ++++++++++++++++++ src/screen_capturer/screen_capturer.h | 1 + .../windows/screen_capturer_dxgi.cpp | 23 +++++++++++++++++++ .../windows/screen_capturer_dxgi.h | 2 ++ .../windows/screen_capturer_gdi.cpp | 11 +++++++++ .../windows/screen_capturer_gdi.h | 2 ++ .../windows/screen_capturer_wgc.cpp | 23 ++++++++++++++++++- .../windows/screen_capturer_wgc.h | 4 +++- .../windows/screen_capturer_win.cpp | 7 +++++- .../windows/screen_capturer_win.h | 3 ++- 15 files changed, 111 insertions(+), 4 deletions(-) diff --git a/src/gui/render_callback.cpp b/src/gui/render_callback.cpp index 41ace33..a4b9d76 100644 --- a/src/gui/render_callback.cpp +++ b/src/gui/render_callback.cpp @@ -897,6 +897,9 @@ void Render::OnConnectionStatusCb(ConnectionStatus status, const char* user_id, } render->connection_status_.erase(remote_id); + if (render->screen_capturer_) { + render->screen_capturer_->ResetToInitialMonitor(); + } } if (std::all_of(render->connection_status_.begin(), diff --git a/src/screen_capturer/linux/screen_capturer_x11.cpp b/src/screen_capturer/linux/screen_capturer_x11.cpp index 18bb2ad..8fabfa7 100644 --- a/src/screen_capturer/linux/screen_capturer_x11.cpp +++ b/src/screen_capturer/linux/screen_capturer_x11.cpp @@ -138,6 +138,10 @@ int ScreenCapturerX11::SwitchTo(int monitor_index) { return 0; } +int ScreenCapturerX11::ResetToInitialMonitor() { + monitor_index_ = initial_monitor_index_; + return 0; +} std::vector ScreenCapturerX11::GetDisplayInfoList() { return display_info_list_; } diff --git a/src/screen_capturer/linux/screen_capturer_x11.h b/src/screen_capturer/linux/screen_capturer_x11.h index 52dbce5..75131f4 100644 --- a/src/screen_capturer/linux/screen_capturer_x11.h +++ b/src/screen_capturer/linux/screen_capturer_x11.h @@ -42,6 +42,7 @@ class ScreenCapturerX11 : public ScreenCapturer { int Resume(int monitor_index) override; int SwitchTo(int monitor_index) override; + int ResetToInitialMonitor() override; std::vector GetDisplayInfoList() override; @@ -62,6 +63,7 @@ class ScreenCapturerX11 : public ScreenCapturer { std::atomic running_{false}; std::atomic paused_{false}; std::atomic monitor_index_{0}; + int initial_monitor_index_ = 0; std::atomic show_cursor_{true}; int fps_ = 60; cb_desktop_data callback_; diff --git a/src/screen_capturer/macosx/screen_capturer_sck.cpp b/src/screen_capturer/macosx/screen_capturer_sck.cpp index 9cbfcfd..a0d7441 100644 --- a/src/screen_capturer/macosx/screen_capturer_sck.cpp +++ b/src/screen_capturer/macosx/screen_capturer_sck.cpp @@ -62,6 +62,13 @@ int ScreenCapturerSck::SwitchTo(int monitor_index) { return -1; } +int ScreenCapturerSck::ResetToInitialMonitor() { + if (screen_capturer_sck_impl_) { + return screen_capturer_sck_impl_->ResetToInitialMonitor(); + } + return -1; +} + std::vector ScreenCapturerSck::GetDisplayInfoList() { if (screen_capturer_sck_impl_) { return screen_capturer_sck_impl_->GetDisplayInfoList(); diff --git a/src/screen_capturer/macosx/screen_capturer_sck.h b/src/screen_capturer/macosx/screen_capturer_sck.h index 42c3ac6..53493ea 100644 --- a/src/screen_capturer/macosx/screen_capturer_sck.h +++ b/src/screen_capturer/macosx/screen_capturer_sck.h @@ -33,6 +33,7 @@ class ScreenCapturerSck : public ScreenCapturer { int Resume(int monitor_index) override; int SwitchTo(int monitor_index) override; + int ResetToInitialMonitor() override; std::vector GetDisplayInfoList() override; diff --git a/src/screen_capturer/macosx/screen_capturer_sck_impl.mm b/src/screen_capturer/macosx/screen_capturer_sck_impl.mm index 14156ea..a7b0923 100644 --- a/src/screen_capturer/macosx/screen_capturer_sck_impl.mm +++ b/src/screen_capturer/macosx/screen_capturer_sck_impl.mm @@ -70,6 +70,7 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSckImpl : public ScreenCapturer { int Resume(int monitor_index) override { return 0; } std::vector GetDisplayInfoList() override { return display_info_list_; } + int ResetToInitialMonitor() override; private: std::vector display_info_list_; @@ -113,6 +114,7 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSckImpl : public ScreenCapturer { // Currently selected display, or 0 if the full desktop is selected. This capturer does not // support full-desktop capture, and will fall back to the first display. CGDirectDisplayID current_display_ = 0; + int initial_monitor_index_ = 0; }; std::string GetDisplayName(CGDirectDisplayID display_id) { @@ -261,6 +263,7 @@ int ScreenCapturerSckImpl::Init(const int fps, cb_desktop_data cb) { display_id_name_map_[display_id] = name; } + initial_monitor_index_ = 0; return 0; } @@ -295,6 +298,25 @@ int ScreenCapturerSckImpl::SwitchTo(int monitor_index) { return 0; } +int ScreenCapturerSckImpl::ResetToInitialMonitor() { + int target = initial_monitor_index_; + if (display_info_list_.empty()) return -1; + CGDirectDisplayID target_display = display_id_map_[target]; + if (current_display_ == target_display) return 0; + if (stream_) { + [stream_ stopCaptureWithCompletionHandler:^(NSError *error) { + std::lock_guard lock(lock_); + stream_ = nil; + current_display_ = target_display; + StartOrReconfigureCapturer(); + }]; + } else { + current_display_ = target_display; + StartOrReconfigureCapturer(); + } + return 0; +} + int ScreenCapturerSckImpl::Destroy() { std::lock_guard lock(lock_); if (stream_) { diff --git a/src/screen_capturer/screen_capturer.h b/src/screen_capturer/screen_capturer.h index 0b5e0a4..d129f61 100644 --- a/src/screen_capturer/screen_capturer.h +++ b/src/screen_capturer/screen_capturer.h @@ -31,6 +31,7 @@ class ScreenCapturer { virtual std::vector GetDisplayInfoList() = 0; virtual int SwitchTo(int monitor_index) = 0; + virtual int ResetToInitialMonitor() = 0; }; } // namespace crossdesk #endif \ No newline at end of file diff --git a/src/screen_capturer/windows/screen_capturer_dxgi.cpp b/src/screen_capturer/windows/screen_capturer_dxgi.cpp index b46f8ce..f497ffd 100644 --- a/src/screen_capturer/windows/screen_capturer_dxgi.cpp +++ b/src/screen_capturer/windows/screen_capturer_dxgi.cpp @@ -56,6 +56,7 @@ int ScreenCapturerDxgi::Init(const int fps, cb_desktop_data cb) { } monitor_index_ = 0; + initial_monitor_index_ = monitor_index_; return 0; } @@ -128,6 +129,28 @@ int ScreenCapturerDxgi::SwitchTo(int monitor_index) { return 0; } +int ScreenCapturerDxgi::ResetToInitialMonitor() { + if (display_info_list_.empty()) return -1; + int target = initial_monitor_index_; + if (target < 0 || target >= (int)display_info_list_.size()) return -1; + if (monitor_index_ == target) return 0; + if (running_) { + paused_ = true; + monitor_index_ = target; + ReleaseDuplication(); + if (!CreateDuplicationForMonitor(monitor_index_)) { + paused_ = false; + return -2; + } + paused_ = false; + LOG_INFO("DXGI: reset to initial monitor {}:{}", monitor_index_.load(), + display_info_list_[monitor_index_].name); + } else { + monitor_index_ = target; + } + return 0; +} + bool ScreenCapturerDxgi::InitializeDxgi() { UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; #ifdef _DEBUG diff --git a/src/screen_capturer/windows/screen_capturer_dxgi.h b/src/screen_capturer/windows/screen_capturer_dxgi.h index e5cdf6b..83e21f2 100644 --- a/src/screen_capturer/windows/screen_capturer_dxgi.h +++ b/src/screen_capturer/windows/screen_capturer_dxgi.h @@ -40,6 +40,7 @@ class ScreenCapturerDxgi : public ScreenCapturer { int Resume(int monitor_index) override; int SwitchTo(int monitor_index) override; + int ResetToInitialMonitor() override; std::vector GetDisplayInfoList() override { return display_info_list_; @@ -65,6 +66,7 @@ class ScreenCapturerDxgi : public ScreenCapturer { std::atomic running_{false}; std::atomic paused_{false}; std::atomic monitor_index_{0}; + int initial_monitor_index_ = 0; std::atomic show_cursor_{true}; std::thread thread_; int fps_ = 60; diff --git a/src/screen_capturer/windows/screen_capturer_gdi.cpp b/src/screen_capturer/windows/screen_capturer_gdi.cpp index a967245..7ee0b4e 100644 --- a/src/screen_capturer/windows/screen_capturer_gdi.cpp +++ b/src/screen_capturer/windows/screen_capturer_gdi.cpp @@ -73,6 +73,7 @@ int ScreenCapturerGdi::Init(const int fps, cb_desktop_data cb) { return -2; } monitor_index_ = 0; + initial_monitor_index_ = monitor_index_; return 0; } @@ -124,6 +125,16 @@ int ScreenCapturerGdi::SwitchTo(int monitor_index) { return 0; } +int ScreenCapturerGdi::ResetToInitialMonitor() { + if (display_info_list_.empty()) return -1; + int target = initial_monitor_index_; + if (target < 0 || target >= (int)display_info_list_.size()) return -1; + monitor_index_ = target; + LOG_INFO("GDI: reset to initial monitor {}:{}", monitor_index_.load(), + display_info_list_[monitor_index_].name); + return 0; +} + void ScreenCapturerGdi::CaptureLoop() { int interval_ms = fps_ > 0 ? (1000 / fps_) : 16; HDC screen_dc = GetDC(nullptr); diff --git a/src/screen_capturer/windows/screen_capturer_gdi.h b/src/screen_capturer/windows/screen_capturer_gdi.h index af30b78..4768490 100644 --- a/src/screen_capturer/windows/screen_capturer_gdi.h +++ b/src/screen_capturer/windows/screen_capturer_gdi.h @@ -36,6 +36,7 @@ class ScreenCapturerGdi : public ScreenCapturer { int Resume(int monitor_index) override; int SwitchTo(int monitor_index) override; + int ResetToInitialMonitor() override; std::vector GetDisplayInfoList() override { return display_info_list_; @@ -52,6 +53,7 @@ class ScreenCapturerGdi : public ScreenCapturer { std::atomic running_{false}; std::atomic paused_{false}; std::atomic monitor_index_{0}; + int initial_monitor_index_ = 0; std::atomic show_cursor_{true}; std::thread thread_; int fps_ = 60; diff --git a/src/screen_capturer/windows/screen_capturer_wgc.cpp b/src/screen_capturer/windows/screen_capturer_wgc.cpp index c63f852..bcc1cd7 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.cpp +++ b/src/screen_capturer/windows/screen_capturer_wgc.cpp @@ -147,6 +147,7 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) { LOG_INFO("Default on monitor {}:{}", monitor_index_, display_info_list_[monitor_index_].name); + initial_monitor_index_ = monitor_index_; return 0; } @@ -267,6 +268,26 @@ int ScreenCapturerWgc::SwitchTo(int monitor_index) { return 0; } +int ScreenCapturerWgc::ResetToInitialMonitor() { + if (display_info_list_.empty()) return -1; + if (initial_monitor_index_ < 0 || + initial_monitor_index_ >= static_cast(display_info_list_.size())) { + return -1; + } + if (monitor_index_ == initial_monitor_index_) { + return 0; + } + if (running_) { + Pause(monitor_index_); + } + monitor_index_ = initial_monitor_index_; + LOG_INFO("Reset to initial monitor {}:{}", monitor_index_, + display_info_list_[monitor_index_].name); + if (running_) { + Resume(monitor_index_); + } + return 0; +} void ScreenCapturerWgc::OnFrame(const WgcSession::wgc_session_frame& frame, int id) { if (!running_ || !on_data_) { @@ -337,4 +358,4 @@ void ScreenCapturerWgc::CleanUp() { sessions_.clear(); } } -} // namespace crossdesk +} // namespace crossdesk \ No newline at end of file diff --git a/src/screen_capturer/windows/screen_capturer_wgc.h b/src/screen_capturer/windows/screen_capturer_wgc.h index 1c8b721..dc507a5 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.h +++ b/src/screen_capturer/windows/screen_capturer_wgc.h @@ -34,6 +34,7 @@ class ScreenCapturerWgc : public ScreenCapturer, std::vector GetDisplayInfoList() { return display_info_list_; } int SwitchTo(int monitor_index); + int ResetToInitialMonitor() override; void OnFrame(const WgcSession::wgc_session_frame& frame, int id); @@ -45,6 +46,7 @@ class ScreenCapturerWgc : public ScreenCapturer, MONITORINFOEX monitor_info_; std::vector display_info_list_; int monitor_index_ = 0; + int initial_monitor_index_ = 0; private: class WgcSessionInfo { @@ -72,4 +74,4 @@ class ScreenCapturerWgc : public ScreenCapturer, std::mutex frame_mutex_; }; } // namespace crossdesk -#endif +#endif \ No newline at end of file diff --git a/src/screen_capturer/windows/screen_capturer_win.cpp b/src/screen_capturer/windows/screen_capturer_win.cpp index b0cf2e2..b59db06 100644 --- a/src/screen_capturer/windows/screen_capturer_win.cpp +++ b/src/screen_capturer/windows/screen_capturer_win.cpp @@ -148,6 +148,11 @@ int ScreenCapturerWin::SwitchTo(int monitor_index) { return impl_->SwitchTo(monitor_index); } +int ScreenCapturerWin::ResetToInitialMonitor() { + if (!impl_) return -1; + return impl_->ResetToInitialMonitor(); +} + std::vector ScreenCapturerWin::GetDisplayInfoList() { if (!impl_) return {}; return impl_->GetDisplayInfoList(); @@ -195,4 +200,4 @@ void ScreenCapturerWin::RebuildAliasesFromImpl() { } } -} // namespace crossdesk +} // namespace crossdesk \ No newline at end of file diff --git a/src/screen_capturer/windows/screen_capturer_win.h b/src/screen_capturer/windows/screen_capturer_win.h index 2b03179..4c9f10c 100644 --- a/src/screen_capturer/windows/screen_capturer_win.h +++ b/src/screen_capturer/windows/screen_capturer_win.h @@ -32,6 +32,7 @@ class ScreenCapturerWin : public ScreenCapturer { int Resume(int monitor_index) override; int SwitchTo(int monitor_index) override; + int ResetToInitialMonitor() override; std::vector GetDisplayInfoList() override; @@ -51,4 +52,4 @@ class ScreenCapturerWin : public ScreenCapturer { void RebuildAliasesFromImpl(); }; } // namespace crossdesk -#endif +#endif \ No newline at end of file