[feat] display switch supported on Windows platform

This commit is contained in:
dijunkun
2025-05-15 16:37:03 +08:00
parent 5eff530ab9
commit a6beb48b1f
8 changed files with 65 additions and 22 deletions

View File

@@ -43,6 +43,8 @@ typedef struct {
typedef struct { typedef struct {
char host_name[64]; char host_name[64];
size_t host_name_size; size_t host_name_size;
char **display_list;
size_t display_num;
} HostInfo; } HostInfo;
typedef struct { typedef struct {

View File

@@ -36,7 +36,7 @@ class ScreenCapturer {
virtual int Pause(int monitor_index) = 0; virtual int Pause(int monitor_index) = 0;
virtual int Resume(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; virtual int SwitchTo(int monitor_index) = 0;
}; };

View File

@@ -107,15 +107,15 @@ int ScreenCapturerWgc::Init(const int fps, cb_desktop_data cb) {
monitor_ = GetPrimaryMonitor(); 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"); LOG_ERROR("No display found");
return -1; return -1;
} }
for (int i = 0; i < display_list_.size(); i++) { for (int i = 0; i < display_info_list_.size(); i++) {
const auto &display = display_list_[i]; const auto &display = display_info_list_[i];
LOG_INFO( LOG_INFO(
"index: {}, display name: {}, is primary: {}, bounds: ({}, {}) - " "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_, LOG_INFO("Default on monitor {}:{}", monitor_index_,
display_list_[monitor_index_].name); display_info_list_[monitor_index_].name);
return 0; return 0;
} }
@@ -217,11 +217,11 @@ int ScreenCapturerWgc::Stop() {
int ScreenCapturerWgc::SwitchTo(int monitor_index) { int ScreenCapturerWgc::SwitchTo(int monitor_index) {
if (monitor_index_ == monitor_index) { if (monitor_index_ == monitor_index) {
LOG_INFO("Already on monitor {}:{}", monitor_index_, LOG_INFO("Already on monitor {}:{}", monitor_index_,
display_list_[monitor_index_].name); display_info_list_[monitor_index_].name);
return 0; return 0;
} }
if (monitor_index >= display_list_.size()) { if (monitor_index >= display_info_list_.size()) {
LOG_ERROR("Invalid monitor index: {}", monitor_index); LOG_ERROR("Invalid monitor index: {}", monitor_index);
return -1; return -1;
} }
@@ -235,7 +235,7 @@ int ScreenCapturerWgc::SwitchTo(int monitor_index) {
monitor_index_ = monitor_index; monitor_index_ = monitor_index;
LOG_INFO("Switching to monitor {}:{}", monitor_index_, LOG_INFO("Switching to monitor {}:{}", monitor_index_,
display_list_[monitor_index_].name); display_info_list_[monitor_index_].name);
Resume(monitor_index); Resume(monitor_index);

View File

@@ -28,7 +28,7 @@ class ScreenCapturerWgc : public ScreenCapturer,
virtual int Pause(int monitor_index) override; virtual int Pause(int monitor_index) override;
virtual int Resume(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); int SwitchTo(int monitor_index);
@@ -40,7 +40,7 @@ class ScreenCapturerWgc : public ScreenCapturer,
private: private:
HMONITOR monitor_; HMONITOR monitor_;
MONITORINFOEX monitor_info_; MONITORINFOEX monitor_info_;
std::vector<DisplayInfo> display_list_; std::vector<DisplayInfo> display_info_list_;
int monitor_index_ = 0; int monitor_index_ = 0;
private: private:

View File

@@ -57,13 +57,9 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
ImVec2 btn_size_actual = ImGui::GetItemRectSize(); ImVec2 btn_size_actual = ImGui::GetItemRectSize();
if (ImGui::BeginPopup("display")) { if (ImGui::BeginPopup("display")) {
std::vector<ScreenCapturer::DisplayInfo> display_list;
if (screen_capturer_) {
display_list = screen_capturer_->GetDisplayList();
}
ImGui::SetWindowFontScale(0.5f); ImGui::SetWindowFontScale(0.5f);
for (int i = 0; i < display_list.size(); i++) { for (int i = 0; i < props->display_names_.size(); i++) {
if (ImGui::Selectable(display_list[i].name.c_str())) { if (ImGui::Selectable(props->display_names_[i].c_str())) {
selected_display_ = i + 1; selected_display_ = i + 1;
RemoteAction remote_action; RemoteAction remote_action;

View File

@@ -842,8 +842,26 @@ void Render::MainLoop() {
} }
if (!host_info_sent_ && screen_width_ > 0 && screen_height_ > 0) { if (!host_info_sent_ && screen_width_ > 0 && screen_height_ > 0) {
std::string host_name = GetHostName();
RemoteAction remote_action; 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; remote_action.type = ControlType::host_infomation;
memcpy(&remote_action.i.host_name, host_name.data(), host_name.size()); memcpy(&remote_action.i.host_name, host_name.data(), host_name.size());
remote_action.i.host_name_size = 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->stream_texture_) {
if (props->video_width_ != props->texture_width_ || if (props->video_width_ != props->texture_width_ ||
props->video_height_ != props->texture_height_) { props->video_height_ != props->texture_height_) {
LOG_WARN("Resolution changed, old: [{}x{}], new: [{}x{}]", // LOG_WARN("Resolution changed, old: [{}x{}], new: [{}x{}]",
props->texture_width_, props->texture_height_, // props->texture_width_, props->texture_height_,
props->video_width_, props->video_height_); // props->video_width_, props->video_height_);
props->texture_width_ = props->video_width_; props->texture_width_ = props->video_width_;
props->texture_height_ = props->video_height_; props->texture_height_ = props->video_height_;

View File

@@ -97,6 +97,7 @@ class Render {
std::string mouse_control_button_label_ = "Mouse Control"; std::string mouse_control_button_label_ = "Mouse Control";
std::string audio_capture_button_label_ = "Audio Capture"; std::string audio_capture_button_label_ = "Audio Capture";
std::string remote_host_name_ = ""; std::string remote_host_name_ = "";
std::vector<std::string> display_names_;
SDL_Texture *stream_texture_ = nullptr; SDL_Texture *stream_texture_ = nullptr;
SDL_Rect stream_render_rect_; SDL_Rect stream_render_rect_;
SDL_Rect stream_render_rect_last_; SDL_Rect stream_render_rect_last_;
@@ -389,6 +390,7 @@ class Render {
DeviceControllerFactory *device_controller_factory_ = nullptr; DeviceControllerFactory *device_controller_factory_ = nullptr;
MouseController *mouse_controller_ = nullptr; MouseController *mouse_controller_ = nullptr;
KeyboardCapturer *keyboard_capturer_ = nullptr; KeyboardCapturer *keyboard_capturer_ = nullptr;
std::vector<ScreenCapturer::DisplayInfo> display_info_list_;
uint64_t last_frame_time_; uint64_t last_frame_time_;
char client_id_[10] = ""; char client_id_[10] = "";
char client_id_display_[12] = ""; char client_id_display_[12] = "";

View File

@@ -251,6 +251,24 @@ void Render::OnReceiveAudioBufferCb(const char *data, size_t size,
SDL_QueueAudio(render->output_dev_, data, (uint32_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, void Render::OnReceiveDataBufferCb(const char *data, size_t size,
const char *user_id, size_t user_id_size, const char *user_id, size_t user_id_size,
void *user_data) { 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, props->remote_host_name_ = std::string(remote_action.i.host_name,
remote_action.i.host_name_size); remote_action.i.host_name_size);
LOG_INFO("Remote hostname: [{}]", props->remote_host_name_); 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 { } else {
// remote // remote