From dc05f2405f06152e8fac61d89e3381d242dc3631 Mon Sep 17 00:00:00 2001 From: dijunkun Date: Thu, 8 May 2025 17:40:14 +0800 Subject: [PATCH] [feat] add display selection method for Windows platform --- src/screen_capturer/screen_capturer.h | 15 +++- .../windows/screen_capturer_wgc.cpp | 82 +++++++++++++++++-- .../windows/screen_capturer_wgc.h | 10 +++ src/screen_capturer/windows/wgc_session.h | 1 - src/single_window/control_bar.cpp | 22 +++++ 5 files changed, 121 insertions(+), 9 deletions(-) diff --git a/src/screen_capturer/screen_capturer.h b/src/screen_capturer/screen_capturer.h index ece553b..308e407 100644 --- a/src/screen_capturer/screen_capturer.h +++ b/src/screen_capturer/screen_capturer.h @@ -11,7 +11,18 @@ class ScreenCapturer { public: - typedef std::function cb_desktop_data; + typedef std::function cb_desktop_data; + + class DisplayInfo { + public: + void* handle = nullptr; + std::string name = ""; + bool is_primary = false; + int left = 0; + int top = 0; + int right = 0; + int bottom = 0; + }; public: virtual ~ScreenCapturer() {} @@ -21,6 +32,8 @@ class ScreenCapturer { virtual int Destroy() = 0; virtual int Start() = 0; virtual int Stop() = 0; + + virtual std::vector GetDisplayList() = 0; }; #endif \ No newline at end of file diff --git a/src/screen_capturer/windows/screen_capturer_wgc.cpp b/src/screen_capturer/windows/screen_capturer_wgc.cpp index 7c824cf..8dc252a 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.cpp +++ b/src/screen_capturer/windows/screen_capturer_wgc.cpp @@ -8,17 +8,36 @@ #include #include "libyuv.h" +#include "rd_log.h" + +static std::vector gs_display_list; + +std::string WideToUtf8(const wchar_t *wideStr) { + int size_needed = WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, nullptr, 0, + nullptr, nullptr); + std::string result(size_needed, 0); + WideCharToMultiByte(CP_UTF8, 0, wideStr, -1, &result[0], size_needed, nullptr, + nullptr); + result.pop_back(); + return result; +} BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc, [[maybe_unused]] LPRECT lprc, LPARAM data) { - MONITORINFOEX info_ex; - info_ex.cbSize = sizeof(MONITORINFOEX); + MONITORINFOEX monitor_info_; + monitor_info_.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(hmonitor, &info_ex); + if (GetMonitorInfo(hmonitor, &monitor_info_)) { + gs_display_list.push_back( + {(void *)hmonitor, WideToUtf8(monitor_info_.szDevice), + (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) ? true : false, + monitor_info_.rcMonitor.left, monitor_info_.rcMonitor.top, + monitor_info_.rcMonitor.right, monitor_info_.rcMonitor.bottom}); + } - if (info_ex.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER) return true; + if (monitor_info_.dwFlags == DISPLAY_DEVICE_MIRRORING_DRIVER) return true; - if (info_ex.dwFlags & MONITORINFOF_PRIMARY) { + if (monitor_info_.dwFlags & MONITORINFOF_PRIMARY) { *(HMONITOR *)data = hmonitor; } @@ -28,12 +47,13 @@ BOOL WINAPI EnumMonitorProc(HMONITOR hmonitor, [[maybe_unused]] HDC hdc, HMONITOR GetPrimaryMonitor() { HMONITOR hmonitor = nullptr; + gs_display_list.clear(); ::EnumDisplayMonitors(NULL, NULL, EnumMonitorProc, (LPARAM)&hmonitor); return hmonitor; } -ScreenCapturerWgc::ScreenCapturerWgc() {} +ScreenCapturerWgc::ScreenCapturerWgc() : monitor_(nullptr) {} ScreenCapturerWgc::~ScreenCapturerWgc() { Stop(); @@ -89,7 +109,17 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) { session_->RegisterObserver(this); - error = session_->Initialize(GetPrimaryMonitor()); + monitor_ = GetPrimaryMonitor(); + + display_list_ = gs_display_list; + + for (const auto &display : display_list_) { + LOG_INFO("Display Name: {}, Is Primary: {}, Bounds: ({}, {}) - ({}, {})", + display.name, (display.is_primary ? "Yes" : "No"), display.left, + display.top, display.right, display.bottom); + } + + error = session_->Initialize(monitor_); _inited = true; } while (0); @@ -139,6 +169,44 @@ int ScreenCapturerWgc::Stop() { return 0; } +int ScreenCapturerWgc::SwitchTo(int monitor_index) { + if (!_inited) return -1; + if (monitor_index >= display_list_.size()) { + LOG_ERROR("Invalid monitor index: {}", monitor_index); + return -3; + } + + LOG_INFO("Switching to monitor {}:{}", monitor_index, + display_list_[monitor_index].name); + + Stop(); + + if (session_) { + session_->Release(); + delete session_; + session_ = nullptr; + } + + session_ = new WgcSessionImpl(); + if (!session_) { + LOG_ERROR("Failed to create new WgcSessionImpl."); + return -4; + } + + session_->RegisterObserver(this); + + int err = session_->Initialize((HMONITOR)display_list_[monitor_index].handle); + if (err != 0) { + LOG_ERROR("Failed to re-initialize session on new monitor."); + return -5; + } + + monitor_ = (HMONITOR)display_list_[monitor_index].handle; + _inited = true; + + return Start(); +} + void ConvertABGRtoBGRA(const uint8_t *abgr_data, uint8_t *bgra_data, int width, int height, int abgr_stride, int bgra_stride) { for (int i = 0; i < height; ++i) { diff --git a/src/screen_capturer/windows/screen_capturer_wgc.h b/src/screen_capturer/windows/screen_capturer_wgc.h index 464c1f6..087ad47 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.h +++ b/src/screen_capturer/windows/screen_capturer_wgc.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "screen_capturer.h" #include "wgc_session.h" @@ -27,11 +28,20 @@ class ScreenCapturerWgc : public ScreenCapturer, int Pause(); int Resume(); + std::vector GetDisplayList() { return display_list_; } + + int SwitchTo(int monitor_index); + void OnFrame(const WgcSession::wgc_session_frame &frame); protected: void CleanUp(); + private: + HMONITOR monitor_; + MONITORINFOEX monitor_info_; + std::vector display_list_; + private: WgcSession *session_ = nullptr; diff --git a/src/screen_capturer/windows/wgc_session.h b/src/screen_capturer/windows/wgc_session.h index d7a3ebc..261c2b1 100644 --- a/src/screen_capturer/windows/wgc_session.h +++ b/src/screen_capturer/windows/wgc_session.h @@ -33,7 +33,6 @@ class WgcSession { virtual int Pause() = 0; virtual int Resume() = 0; - protected: virtual ~WgcSession(){}; }; diff --git a/src/single_window/control_bar.cpp b/src/single_window/control_bar.cpp index 601c931..ea42c82 100644 --- a/src/single_window/control_bar.cpp +++ b/src/single_window/control_bar.cpp @@ -80,6 +80,28 @@ int Render::ControlBar(std::shared_ptr& props) { 2.0f); } + // const char* items[] = {"1", "2", "3"}; + // static int item_selected_idx = 0; + // ImGui::Text("Display:"); + // ImGui::SameLine(); + // ImGui::SetNextItemWidth(25.0f); + // ImGuiComboFlags flags = + // ImGuiComboFlags_HeightSmall | ImGuiComboFlags_NoArrowButton; + // const char* combo_preview_value = items[item_selected_idx]; + // ImGui::SetWindowFontScale(1.2f); + // if (ImGui::BeginCombo("##display", combo_preview_value, flags)) { + // ImGui::SetWindowFontScale(0.5f); + // for (int n = 0; n < IM_ARRAYSIZE(items); n++) { + // const bool is_selected = (item_selected_idx == n); + // if (ImGui::Selectable(items[n], is_selected)) item_selected_idx = n; + + // if (is_selected) ImGui::SetItemDefaultFocus(); + // } + // ImGui::SetWindowFontScale(1.0f); + // ImGui::EndCombo(); + // } + // ImGui::SetWindowFontScale(1.0f); + ImGui::SameLine(); // audio capture button float disable_audio_x = ImGui::GetCursorScreenPos().x + 4;