From a6beb48b1f994bd55f96d1ce6192f3e67ed7ed5a Mon Sep 17 00:00:00 2001 From: dijunkun Date: Thu, 15 May 2025 16:37:03 +0800 Subject: [PATCH] [feat] display switch supported on Windows platform --- src/device_controller/device_controller.h | 4 ++- src/screen_capturer/screen_capturer.h | 2 +- .../windows/screen_capturer_wgc.cpp | 16 ++++++------ .../windows/screen_capturer_wgc.h | 4 +-- src/single_window/control_bar.cpp | 8 ++---- src/single_window/render.cpp | 26 ++++++++++++++++--- src/single_window/render.h | 2 ++ src/single_window/render_callback_func.cpp | 25 ++++++++++++++++++ 8 files changed, 65 insertions(+), 22 deletions(-) diff --git a/src/device_controller/device_controller.h b/src/device_controller/device_controller.h index f690518..8367f97 100644 --- a/src/device_controller/device_controller.h +++ b/src/device_controller/device_controller.h @@ -43,6 +43,8 @@ typedef struct { typedef struct { char host_name[64]; size_t host_name_size; + char **display_list; + size_t display_num; } HostInfo; typedef struct { @@ -57,7 +59,7 @@ typedef struct { } RemoteAction; // int key_code, bool is_down -typedef void (*OnKeyAction)(int, bool, void*); +typedef void (*OnKeyAction)(int, bool, void *); class DeviceController { public: diff --git a/src/screen_capturer/screen_capturer.h b/src/screen_capturer/screen_capturer.h index 7ed08ac..1027022 100644 --- a/src/screen_capturer/screen_capturer.h +++ b/src/screen_capturer/screen_capturer.h @@ -36,7 +36,7 @@ class ScreenCapturer { virtual int Pause(int monitor_index) = 0; virtual int Resume(int monitor_index) = 0; - virtual std::vector GetDisplayList() = 0; + virtual std::vector GetDisplayInfoList() = 0; virtual int SwitchTo(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 36343d1..7da17a1 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.cpp +++ b/src/screen_capturer/windows/screen_capturer_wgc.cpp @@ -107,15 +107,15 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) { monitor_ = GetPrimaryMonitor(); - display_list_ = gs_display_list; + display_info_list_ = gs_display_list; - if (display_list_.empty()) { + if (display_info_list_.empty()) { LOG_ERROR("No display found"); return -1; } - for (int i = 0; i < display_list_.size(); i++) { - const auto &display = display_list_[i]; + for (int i = 0; i < display_info_list_.size(); i++) { + const auto &display = display_info_list_[i]; LOG_INFO( "index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - " "({}, {})", @@ -134,7 +134,7 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) { } LOG_INFO("Default on monitor {}:{}", monitor_index_, - display_list_[monitor_index_].name); + display_info_list_[monitor_index_].name); return 0; } @@ -217,11 +217,11 @@ int ScreenCapturerWgc::Stop() { int ScreenCapturerWgc::SwitchTo(int monitor_index) { if (monitor_index_ == monitor_index) { LOG_INFO("Already on monitor {}:{}", monitor_index_, - display_list_[monitor_index_].name); + display_info_list_[monitor_index_].name); return 0; } - if (monitor_index >= display_list_.size()) { + if (monitor_index >= display_info_list_.size()) { LOG_ERROR("Invalid monitor index: {}", monitor_index); return -1; } @@ -235,7 +235,7 @@ int ScreenCapturerWgc::SwitchTo(int monitor_index) { monitor_index_ = monitor_index; LOG_INFO("Switching to monitor {}:{}", monitor_index_, - display_list_[monitor_index_].name); + display_info_list_[monitor_index_].name); Resume(monitor_index); diff --git a/src/screen_capturer/windows/screen_capturer_wgc.h b/src/screen_capturer/windows/screen_capturer_wgc.h index 64263a8..ef8d2c6 100644 --- a/src/screen_capturer/windows/screen_capturer_wgc.h +++ b/src/screen_capturer/windows/screen_capturer_wgc.h @@ -28,7 +28,7 @@ class ScreenCapturerWgc : public ScreenCapturer, virtual int Pause(int monitor_index) override; virtual int Resume(int monitor_index) override; - std::vector GetDisplayList() { return display_list_; } + std::vector GetDisplayInfoList() { return display_info_list_; } int SwitchTo(int monitor_index); @@ -40,7 +40,7 @@ class ScreenCapturerWgc : public ScreenCapturer, private: HMONITOR monitor_; MONITORINFOEX monitor_info_; - std::vector display_list_; + std::vector display_info_list_; int monitor_index_ = 0; private: diff --git a/src/single_window/control_bar.cpp b/src/single_window/control_bar.cpp index a831a42..3eb6dd7 100644 --- a/src/single_window/control_bar.cpp +++ b/src/single_window/control_bar.cpp @@ -57,13 +57,9 @@ int Render::ControlBar(std::shared_ptr& props) { ImVec2 btn_size_actual = ImGui::GetItemRectSize(); if (ImGui::BeginPopup("display")) { - std::vector display_list; - if (screen_capturer_) { - display_list = screen_capturer_->GetDisplayList(); - } ImGui::SetWindowFontScale(0.5f); - for (int i = 0; i < display_list.size(); i++) { - if (ImGui::Selectable(display_list[i].name.c_str())) { + for (int i = 0; i < props->display_names_.size(); i++) { + if (ImGui::Selectable(props->display_names_[i].c_str())) { selected_display_ = i + 1; RemoteAction remote_action; diff --git a/src/single_window/render.cpp b/src/single_window/render.cpp index 59ea0f6..17b4cd4 100644 --- a/src/single_window/render.cpp +++ b/src/single_window/render.cpp @@ -842,8 +842,26 @@ void Render::MainLoop() { } if (!host_info_sent_ && screen_width_ > 0 && screen_height_ > 0) { - std::string host_name = GetHostName(); RemoteAction remote_action; + if (screen_capturer_) { + display_info_list_ = screen_capturer_->GetDisplayInfoList(); + } + + remote_action.i.display_num = display_info_list_.size(); + remote_action.i.display_list = + (char**)malloc(remote_action.i.display_num * sizeof(char*)); + for (int i = 0; i < remote_action.i.display_num; i++) { + LOG_INFO("Local display [{}:{}]", i + 1, display_info_list_[i].name); + remote_action.i.display_list[i] = + (char*)malloc(display_info_list_[i].name.length() + 1); + strncpy(remote_action.i.display_list[i], + display_info_list_[i].name.c_str(), + display_info_list_[i].name.length()); + remote_action.i.display_list[i][display_info_list_[i].name.length()] = + '\0'; + } + + std::string host_name = GetHostName(); remote_action.type = ControlType::host_infomation; memcpy(&remote_action.i.host_name, host_name.data(), host_name.size()); remote_action.i.host_name_size = host_name.size(); @@ -1136,9 +1154,9 @@ void Render::ProcessSdlEvent() { if (props->stream_texture_) { if (props->video_width_ != props->texture_width_ || props->video_height_ != props->texture_height_) { - LOG_WARN("Resolution changed, old: [{}x{}], new: [{}x{}]", - props->texture_width_, props->texture_height_, - props->video_width_, props->video_height_); + // LOG_WARN("Resolution changed, old: [{}x{}], new: [{}x{}]", + // props->texture_width_, props->texture_height_, + // props->video_width_, props->video_height_); props->texture_width_ = props->video_width_; props->texture_height_ = props->video_height_; diff --git a/src/single_window/render.h b/src/single_window/render.h index 78a2653..1ae3ef0 100644 --- a/src/single_window/render.h +++ b/src/single_window/render.h @@ -97,6 +97,7 @@ class Render { std::string mouse_control_button_label_ = "Mouse Control"; std::string audio_capture_button_label_ = "Audio Capture"; std::string remote_host_name_ = ""; + std::vector display_names_; SDL_Texture *stream_texture_ = nullptr; SDL_Rect stream_render_rect_; SDL_Rect stream_render_rect_last_; @@ -389,6 +390,7 @@ class Render { DeviceControllerFactory *device_controller_factory_ = nullptr; MouseController *mouse_controller_ = nullptr; KeyboardCapturer *keyboard_capturer_ = nullptr; + std::vector display_info_list_; uint64_t last_frame_time_; char client_id_[10] = ""; char client_id_display_[12] = ""; diff --git a/src/single_window/render_callback_func.cpp b/src/single_window/render_callback_func.cpp index 2f1845a..00790fc 100644 --- a/src/single_window/render_callback_func.cpp +++ b/src/single_window/render_callback_func.cpp @@ -251,6 +251,24 @@ void Render::OnReceiveAudioBufferCb(const char *data, size_t size, SDL_QueueAudio(render->output_dev_, data, (uint32_t)size); } +std::vector restore_display_list(char **display_list, + size_t display_num) { + std::vector result; + result.reserve(display_num); // 预分配空间,提升效率 + + for (size_t i = 0; i < display_num; i++) { + if (display_list[i] != nullptr) { + // 直接用std::string构造函数复制C字符串 + result.emplace_back(display_list[i]); + } else { + // 如果遇到nullptr指针,放空字符串或者处理错误 + result.emplace_back(""); + } + } + + return result; +} + void Render::OnReceiveDataBufferCb(const char *data, size_t size, const char *user_id, size_t user_id_size, void *user_data) { @@ -271,6 +289,13 @@ void Render::OnReceiveDataBufferCb(const char *data, size_t size, props->remote_host_name_ = std::string(remote_action.i.host_name, remote_action.i.host_name_size); LOG_INFO("Remote hostname: [{}]", props->remote_host_name_); + + props->display_names_ = restore_display_list(remote_action.i.display_list, + remote_action.i.display_num); + + for (int i = 0; i < props->display_names_.size(); i++) { + LOG_INFO("Remote display [{}:{}]", i + 1, props->display_names_[i]); + } } } else { // remote