mirror of
				https://github.com/kunkundi/crossdesk.git
				synced 2025-10-26 20:25:34 +08:00 
			
		
		
		
	[feat] display switch supported on Windows platform
This commit is contained in:
		| @@ -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: | ||||
|   | ||||
| @@ -36,7 +36,7 @@ class ScreenCapturer { | ||||
|   virtual int Pause(int monitor_index) = 0; | ||||
|   virtual int Resume(int monitor_index) = 0; | ||||
|  | ||||
|   virtual std::vector<DisplayInfo> GetDisplayList() = 0; | ||||
|   virtual std::vector<DisplayInfo> GetDisplayInfoList() = 0; | ||||
|   virtual int SwitchTo(int monitor_index) = 0; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -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); | ||||
|  | ||||
|   | ||||
| @@ -28,7 +28,7 @@ class ScreenCapturerWgc : public ScreenCapturer, | ||||
|   virtual int Pause(int monitor_index) override; | ||||
|   virtual int Resume(int monitor_index) override; | ||||
|  | ||||
|   std::vector<DisplayInfo> GetDisplayList() { return display_list_; } | ||||
|   std::vector<DisplayInfo> 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<DisplayInfo> display_list_; | ||||
|   std::vector<DisplayInfo> display_info_list_; | ||||
|   int monitor_index_ = 0; | ||||
|  | ||||
|  private: | ||||
|   | ||||
| @@ -57,13 +57,9 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) { | ||||
|     ImVec2 btn_size_actual = ImGui::GetItemRectSize(); | ||||
|  | ||||
|     if (ImGui::BeginPopup("display")) { | ||||
|       std::vector<ScreenCapturer::DisplayInfo> 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; | ||||
|   | ||||
| @@ -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_; | ||||
|  | ||||
|   | ||||
| @@ -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<std::string> 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<ScreenCapturer::DisplayInfo> display_info_list_; | ||||
|   uint64_t last_frame_time_; | ||||
|   char client_id_[10] = ""; | ||||
|   char client_id_display_[12] = ""; | ||||
|   | ||||
| @@ -251,6 +251,24 @@ void Render::OnReceiveAudioBufferCb(const char *data, size_t size, | ||||
|   SDL_QueueAudio(render->output_dev_, data, (uint32_t)size); | ||||
| } | ||||
|  | ||||
| std::vector<std::string> restore_display_list(char **display_list, | ||||
|                                               size_t display_num) { | ||||
|   std::vector<std::string> 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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user