From 532ad0eb513fc9b2239abdd3aba401cb4ec92630 Mon Sep 17 00:00:00 2001 From: dijunkun Date: Mon, 28 Apr 2025 20:49:11 +0800 Subject: [PATCH] [feat] support multi-stream and enable stream windows docking --- src/single_window/control_bar.cpp | 149 ++++++------- src/single_window/control_window.cpp | 303 +++++++++++++-------------- src/single_window/main_window.cpp | 4 +- src/single_window/render.cpp | 77 ++++--- src/single_window/render.h | 17 +- src/single_window/stream_window.cpp | 55 ++++- 6 files changed, 311 insertions(+), 294 deletions(-) diff --git a/src/single_window/control_bar.cpp b/src/single_window/control_bar.cpp index 9424467..6621ae1 100644 --- a/src/single_window/control_bar.cpp +++ b/src/single_window/control_bar.cpp @@ -29,45 +29,45 @@ int LossRateDisplay(float loss_rate) { return 0; } -int Render::ControlBar(std::shared_ptr& properties) { +int Render::ControlBar(std::shared_ptr& props) { ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImVec2 mouse_button_pos = ImVec2(0, 0); - if (properties->control_bar_expand_) { - ImGui::SetCursorPosX(properties->is_control_bar_in_left_ - ? (properties->control_window_width_ + 5.0f) + if (props->control_bar_expand_) { + ImGui::SetCursorPosX(props->is_control_bar_in_left_ + ? (props->control_window_width_ + 5.0f) : 38.0f); // mouse control button ImDrawList* draw_list = ImGui::GetWindowDrawList(); - if (properties->is_control_bar_in_left_) { + if (props->is_control_bar_in_left_) { draw_list->AddLine(ImVec2(ImGui::GetCursorScreenPos().x - 5.0f, ImGui::GetCursorScreenPos().y - 7.0f), ImVec2(ImGui::GetCursorScreenPos().x - 5.0f, ImGui::GetCursorScreenPos().y - 7.0f + - properties->control_window_height_), + props->control_window_height_), IM_COL32(178, 178, 178, 255), 1.0f); } mouse_button_pos = ImGui::GetCursorScreenPos(); float disable_mouse_x = ImGui::GetCursorScreenPos().x + 4.0f; float disable_mouse_y = ImGui::GetCursorScreenPos().y + 4.0f; - std::string mouse = properties->mouse_control_button_pressed_ + std::string mouse = props->mouse_control_button_pressed_ ? ICON_FA_COMPUTER_MOUSE : ICON_FA_COMPUTER_MOUSE; if (ImGui::Button(mouse.c_str(), ImVec2(25, 25))) { - if (properties->connection_established_) { + if (props->connection_established_) { start_keyboard_capturer_ = !start_keyboard_capturer_; - properties->control_mouse_ = !properties->control_mouse_; - properties->mouse_control_button_pressed_ = - !properties->mouse_control_button_pressed_; - properties->mouse_control_button_label_ = - properties->mouse_control_button_pressed_ + props->control_mouse_ = !props->control_mouse_; + props->mouse_control_button_pressed_ = + !props->mouse_control_button_pressed_; + props->mouse_control_button_label_ = + props->mouse_control_button_pressed_ ? localization::release_mouse[localization_language_index_] : localization::control_mouse[localization_language_index_]; } } - if (!properties->mouse_control_button_pressed_) { + if (!props->mouse_control_button_pressed_) { draw_list->AddLine( ImVec2(disable_mouse_x, disable_mouse_y), ImVec2(disable_mouse_x + 16.0f, disable_mouse_y + 14.2f), @@ -86,26 +86,26 @@ int Render::ControlBar(std::shared_ptr& properties) { float disable_audio_y = ImGui::GetCursorScreenPos().y + 4.0f; // std::string audio = audio_capture_button_pressed_ ? ICON_FA_VOLUME_HIGH // : ICON_FA_VOLUME_XMARK; - std::string audio = properties->audio_capture_button_pressed_ + std::string audio = props->audio_capture_button_pressed_ ? ICON_FA_VOLUME_HIGH : ICON_FA_VOLUME_HIGH; if (ImGui::Button(audio.c_str(), ImVec2(25, 25))) { - if (properties->connection_established_) { - properties->audio_capture_button_pressed_ = - !properties->audio_capture_button_pressed_; - properties->audio_capture_button_label_ = - properties->audio_capture_button_pressed_ + if (props->connection_established_) { + props->audio_capture_button_pressed_ = + !props->audio_capture_button_pressed_; + props->audio_capture_button_label_ = + props->audio_capture_button_pressed_ ? localization::audio_capture[localization_language_index_] : localization::mute[localization_language_index_]; RemoteAction remote_action; remote_action.type = ControlType::audio_capture; - remote_action.a = properties->audio_capture_button_pressed_; - SendDataFrame(properties->peer_, (const char*)&remote_action, + remote_action.a = props->audio_capture_button_pressed_; + SendDataFrame(props->peer_, (const char*)&remote_action, sizeof(remote_action)); } } - if (!properties->audio_capture_button_pressed_) { + if (!props->audio_capture_button_pressed_) { draw_list->AddLine( ImVec2(disable_audio_x, disable_audio_y), ImVec2(disable_audio_x + 16.0f, disable_audio_y + 14.2f), @@ -121,19 +121,19 @@ int Render::ControlBar(std::shared_ptr& properties) { ImGui::SameLine(); // net traffic stats button bool button_color_style_pushed = false; - if (properties->net_traffic_stats_button_pressed_) { + if (props->net_traffic_stats_button_pressed_) { ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(66 / 255.0f, 150 / 255.0f, 250 / 255.0f, 1.0f)); button_color_style_pushed = true; } std::string net_traffic_stats = ICON_FA_SIGNAL; if (ImGui::Button(net_traffic_stats.c_str(), ImVec2(25, 25))) { - properties->net_traffic_stats_button_pressed_ = - !properties->net_traffic_stats_button_pressed_; - properties->control_window_height_is_changing_ = true; - properties->net_traffic_stats_button_pressed_time_ = ImGui::GetTime(); - properties->net_traffic_stats_button_label_ = - properties->net_traffic_stats_button_pressed_ + props->net_traffic_stats_button_pressed_ = + !props->net_traffic_stats_button_pressed_; + props->control_window_height_is_changing_ = true; + props->net_traffic_stats_button_pressed_time_ = ImGui::GetTime(); + props->net_traffic_stats_button_label_ = + props->net_traffic_stats_button_pressed_ ? localization::hide_net_traffic_stats [localization_language_index_] : localization::show_net_traffic_stats @@ -150,7 +150,7 @@ int Render::ControlBar(std::shared_ptr& properties) { fullscreen_button_pressed_ ? ICON_FA_COMPRESS : ICON_FA_EXPAND; if (ImGui::Button(fullscreen.c_str(), ImVec2(25, 25))) { fullscreen_button_pressed_ = !fullscreen_button_pressed_; - properties->fullscreen_button_label_ = + props->fullscreen_button_label_ = fullscreen_button_pressed_ ? localization::exit_fullscreen[localization_language_index_] : localization::fullscreen[localization_language_index_]; @@ -160,7 +160,7 @@ int Render::ControlBar(std::shared_ptr& properties) { } else { SDL_SetWindowFullscreen(stream_window_, SDL_FALSE); } - properties->reset_control_bar_pos_ = true; + props->reset_control_bar_pos_ = true; } ImGui::SameLine(); @@ -174,40 +174,39 @@ int Render::ControlBar(std::shared_ptr& properties) { ImGui::SameLine(); - if (!properties->is_control_bar_in_left_) { + if (!props->is_control_bar_in_left_) { draw_list->AddLine(ImVec2(ImGui::GetCursorScreenPos().x - 3.0f, ImGui::GetCursorScreenPos().y - 7.0f), ImVec2(ImGui::GetCursorScreenPos().x - 3.0f, ImGui::GetCursorScreenPos().y - 7.0f + - properties->control_window_height_), + props->control_window_height_), IM_COL32(178, 178, 178, 255), 1.0f); } } - ImGui::SetCursorPosX(properties->is_control_bar_in_left_ - ? (properties->control_window_width_ * 2 - 20.0f) + ImGui::SetCursorPosX(props->is_control_bar_in_left_ + ? (props->control_window_width_ * 2 - 20.0f) : 5.0f); std::string control_bar = - properties->control_bar_expand_ - ? (properties->is_control_bar_in_left_ ? ICON_FA_ANGLE_LEFT - : ICON_FA_ANGLE_RIGHT) - : (properties->is_control_bar_in_left_ ? ICON_FA_ANGLE_RIGHT - : ICON_FA_ANGLE_LEFT); + props->control_bar_expand_ + ? (props->is_control_bar_in_left_ ? ICON_FA_ANGLE_LEFT + : ICON_FA_ANGLE_RIGHT) + : (props->is_control_bar_in_left_ ? ICON_FA_ANGLE_RIGHT + : ICON_FA_ANGLE_LEFT); if (ImGui::Button(control_bar.c_str(), ImVec2(15, 25))) { - properties->control_bar_expand_ = !properties->control_bar_expand_; - properties->control_bar_button_pressed_time_ = ImGui::GetTime(); - properties->control_window_width_is_changing_ = true; + props->control_bar_expand_ = !props->control_bar_expand_; + props->control_bar_button_pressed_time_ = ImGui::GetTime(); + props->control_window_width_is_changing_ = true; - if (!properties->control_bar_expand_) { - properties->control_window_height_ = 40; - properties->net_traffic_stats_button_pressed_ = false; + if (!props->control_bar_expand_) { + props->control_window_height_ = 40; + props->net_traffic_stats_button_pressed_ = false; } } - if (properties->net_traffic_stats_button_pressed_ && - properties->control_bar_expand_) { - NetTrafficStats(properties); + if (props->net_traffic_stats_button_pressed_ && props->control_bar_expand_) { + NetTrafficStats(props); } ImGui::PopStyleVar(); @@ -215,17 +214,15 @@ int Render::ControlBar(std::shared_ptr& properties) { return 0; } -int Render::NetTrafficStats( - std::shared_ptr& properties) { - ImGui::SetCursorPos(ImVec2(properties->is_control_bar_in_left_ - ? (properties->control_window_width_ + 5.0f) +int Render::NetTrafficStats(std::shared_ptr& props) { + ImGui::SetCursorPos(ImVec2(props->is_control_bar_in_left_ + ? (props->control_window_width_ + 5.0f) : 5.0f, 40.0f)); - if (ImGui::BeginTable( - "NetTrafficStats", 4, ImGuiTableFlags_BordersH, - ImVec2(properties->control_window_max_width_ - 10.0f, - properties->control_window_max_height_ - 40.0f))) { + if (ImGui::BeginTable("NetTrafficStats", 4, ImGuiTableFlags_BordersH, + ImVec2(props->control_window_max_width_ - 10.0f, + props->control_window_max_height_ - 40.0f))) { ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch); @@ -246,55 +243,43 @@ int Render::NetTrafficStats( ImGui::Text("%s", localization::video[localization_language_index_].c_str()); ImGui::TableNextColumn(); - BitrateDisplay( - (int)properties->net_traffic_stats_.video_inbound_stats.bitrate); + BitrateDisplay((int)props->net_traffic_stats_.video_inbound_stats.bitrate); ImGui::TableNextColumn(); - BitrateDisplay( - (int)properties->net_traffic_stats_.video_outbound_stats.bitrate); + BitrateDisplay((int)props->net_traffic_stats_.video_outbound_stats.bitrate); ImGui::TableNextColumn(); - LossRateDisplay( - properties->net_traffic_stats_.video_inbound_stats.loss_rate); + LossRateDisplay(props->net_traffic_stats_.video_inbound_stats.loss_rate); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("%s", localization::audio[localization_language_index_].c_str()); ImGui::TableNextColumn(); - BitrateDisplay( - (int)properties->net_traffic_stats_.audio_inbound_stats.bitrate); + BitrateDisplay((int)props->net_traffic_stats_.audio_inbound_stats.bitrate); ImGui::TableNextColumn(); - BitrateDisplay( - (int)properties->net_traffic_stats_.audio_outbound_stats.bitrate); + BitrateDisplay((int)props->net_traffic_stats_.audio_outbound_stats.bitrate); ImGui::TableNextColumn(); - LossRateDisplay( - properties->net_traffic_stats_.audio_inbound_stats.loss_rate); + LossRateDisplay(props->net_traffic_stats_.audio_inbound_stats.loss_rate); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("%s", localization::data[localization_language_index_].c_str()); ImGui::TableNextColumn(); - BitrateDisplay( - (int)properties->net_traffic_stats_.data_inbound_stats.bitrate); + BitrateDisplay((int)props->net_traffic_stats_.data_inbound_stats.bitrate); ImGui::TableNextColumn(); - BitrateDisplay( - (int)properties->net_traffic_stats_.data_outbound_stats.bitrate); + BitrateDisplay((int)props->net_traffic_stats_.data_outbound_stats.bitrate); ImGui::TableNextColumn(); - LossRateDisplay( - properties->net_traffic_stats_.data_inbound_stats.loss_rate); + LossRateDisplay(props->net_traffic_stats_.data_inbound_stats.loss_rate); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("%s", localization::total[localization_language_index_].c_str()); ImGui::TableNextColumn(); - BitrateDisplay( - (int)properties->net_traffic_stats_.total_inbound_stats.bitrate); + BitrateDisplay((int)props->net_traffic_stats_.total_inbound_stats.bitrate); ImGui::TableNextColumn(); - BitrateDisplay( - (int)properties->net_traffic_stats_.total_outbound_stats.bitrate); + BitrateDisplay((int)props->net_traffic_stats_.total_outbound_stats.bitrate); ImGui::TableNextColumn(); - LossRateDisplay( - properties->net_traffic_stats_.total_inbound_stats.loss_rate); + LossRateDisplay(props->net_traffic_stats_.total_inbound_stats.loss_rate); ImGui::EndTable(); } diff --git a/src/single_window/control_window.cpp b/src/single_window/control_window.cpp index 9a23c7c..fd49f01 100644 --- a/src/single_window/control_window.cpp +++ b/src/single_window/control_window.cpp @@ -1,42 +1,41 @@ #include "rd_log.h" #include "render.h" -int Render::ControlWindow( - std::shared_ptr &properties) { +int Render::ControlWindow(std::shared_ptr &props) { double time_duration = - ImGui::GetTime() - properties->control_bar_button_pressed_time_; - if (properties->control_window_width_is_changing_) { - if (properties->control_bar_expand_) { - properties->control_window_width_ = - (float)(properties->control_window_min_width_ + - (properties->control_window_max_width_ - - properties->control_window_min_width_) * + ImGui::GetTime() - props->control_bar_button_pressed_time_; + if (props->control_window_width_is_changing_) { + if (props->control_bar_expand_) { + props->control_window_width_ = + (float)(props->control_window_min_width_ + + (props->control_window_max_width_ - + props->control_window_min_width_) * 4 * time_duration); } else { - properties->control_window_width_ = - (float)(properties->control_window_max_width_ - - (properties->control_window_max_width_ - - properties->control_window_min_width_) * + props->control_window_width_ = + (float)(props->control_window_max_width_ - + (props->control_window_max_width_ - + props->control_window_min_width_) * 4 * time_duration); } } time_duration = - ImGui::GetTime() - properties->net_traffic_stats_button_pressed_time_; - if (properties->control_window_height_is_changing_) { - if (properties->control_bar_expand_ && - properties->net_traffic_stats_button_pressed_) { - properties->control_window_height_ = - (float)(properties->control_window_min_height_ + - (properties->control_window_max_height_ - - properties->control_window_min_height_) * + ImGui::GetTime() - props->net_traffic_stats_button_pressed_time_; + if (props->control_window_height_is_changing_) { + if (props->control_bar_expand_ && + props->net_traffic_stats_button_pressed_) { + props->control_window_height_ = + (float)(props->control_window_min_height_ + + (props->control_window_max_height_ - + props->control_window_min_height_) * 4 * time_duration); - } else if (properties->control_bar_expand_ && - !properties->net_traffic_stats_button_pressed_) { - properties->control_window_height_ = - (float)(properties->control_window_max_height_ - - (properties->control_window_max_height_ - - properties->control_window_min_height_) * + } else if (props->control_bar_expand_ && + !props->net_traffic_stats_button_pressed_) { + props->control_window_height_ = + (float)(props->control_window_max_height_ - + (props->control_window_max_height_ - + props->control_window_min_height_) * 4 * time_duration); } } @@ -48,224 +47,202 @@ int Render::ControlWindow( ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); - ImGui::SetNextWindowSize(ImVec2(properties->control_window_width_, - properties->control_window_height_), - ImGuiCond_Always); + ImGui::SetNextWindowSize( + ImVec2(props->control_window_width_, props->control_window_height_), + ImGuiCond_Always); - if (0 == properties->control_winodw_pos_.x && - 0 == properties->control_winodw_pos_.y) { + if (0 == props->control_winodw_pos_.x && 0 == props->control_winodw_pos_.y) { ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_ + 1), ImGuiCond_Once); } - if (properties->reset_control_bar_pos_) { + if (props->reset_control_bar_pos_) { float new_control_window_pos_x, new_control_window_pos_y, new_cursor_pos_x, new_cursor_pos_y; // set control window pos - new_control_window_pos_x = properties->control_winodw_pos_.x; - if (properties->control_winodw_pos_.y < - properties->stream_render_rect_last_.y) { - new_control_window_pos_y = properties->stream_render_rect_.y - - (properties->stream_render_rect_last_.y - - properties->control_winodw_pos_.y); + new_control_window_pos_x = props->control_winodw_pos_.x; + if (props->control_winodw_pos_.y < props->stream_render_rect_last_.y) { + new_control_window_pos_y = + props->stream_render_rect_.y - + (props->stream_render_rect_last_.y - props->control_winodw_pos_.y); if (fullscreen_button_pressed_ && new_control_window_pos_y < 0) { new_control_window_pos_y = 0; } else if (!fullscreen_button_pressed_ && new_control_window_pos_y < (title_bar_height_ + 1)) { new_control_window_pos_y = title_bar_height_ + 1; } - } else if (properties->control_winodw_pos_.y + - properties->control_window_height_ > - properties->stream_render_rect_last_.y + - properties->stream_render_rect_last_.h) { - new_control_window_pos_y = properties->stream_render_rect_.y + - properties->stream_render_rect_.h + - (properties->control_winodw_pos_.y - - properties->stream_render_rect_last_.y - - properties->stream_render_rect_last_.h); - if (new_control_window_pos_y > properties->sub_stream_window_height_ - - properties->control_window_height_) { - new_control_window_pos_y = properties->sub_stream_window_height_ - - properties->control_window_height_; + } else if (props->control_winodw_pos_.y + props->control_window_height_ > + props->stream_render_rect_last_.y + + props->stream_render_rect_last_.h) { + new_control_window_pos_y = + props->stream_render_rect_.y + props->stream_render_rect_.h + + (props->control_winodw_pos_.y - props->stream_render_rect_last_.y - + props->stream_render_rect_last_.h); + if (new_control_window_pos_y > + props->sub_stream_window_height_ - props->control_window_height_) { + new_control_window_pos_y = + props->sub_stream_window_height_ - props->control_window_height_; } - } else if (properties->control_winodw_pos_.y + - properties->control_window_height_ == - properties->stream_render_rect_last_.y + - properties->stream_render_rect_last_.h) { - new_control_window_pos_y = properties->stream_render_rect_.y + - properties->stream_render_rect_.h - - properties->control_window_height_; + } else if (props->control_winodw_pos_.y + props->control_window_height_ == + props->stream_render_rect_last_.y + + props->stream_render_rect_last_.h) { + new_control_window_pos_y = props->stream_render_rect_.y + + props->stream_render_rect_.h - + props->control_window_height_; } else { new_control_window_pos_y = - (properties->control_winodw_pos_.y - - properties->stream_render_rect_last_.y) / - (float)(properties->stream_render_rect_last_.h) * - properties->stream_render_rect_.h + - properties->stream_render_rect_.y; + (props->control_winodw_pos_.y - props->stream_render_rect_last_.y) / + (float)(props->stream_render_rect_last_.h) * + props->stream_render_rect_.h + + props->stream_render_rect_.y; } ImGui::SetNextWindowPos( ImVec2(new_control_window_pos_x, new_control_window_pos_y), ImGuiCond_Always); - if (0 != properties->mouse_diff_control_bar_pos_x_ && - 0 != properties->mouse_diff_control_bar_pos_y_) { + if (0 != props->mouse_diff_control_bar_pos_x_ && + 0 != props->mouse_diff_control_bar_pos_y_) { // set cursor pos new_cursor_pos_x = - new_control_window_pos_x + properties->mouse_diff_control_bar_pos_x_; + new_control_window_pos_x + props->mouse_diff_control_bar_pos_x_; new_cursor_pos_y = - new_control_window_pos_y + properties->mouse_diff_control_bar_pos_y_; + new_control_window_pos_y + props->mouse_diff_control_bar_pos_y_; SDL_WarpMouseInWindow(stream_window_, (int)new_cursor_pos_x, (int)new_cursor_pos_y); } - properties->reset_control_bar_pos_ = false; - } else if (!properties->reset_control_bar_pos_ && + props->reset_control_bar_pos_ = false; + } else if (!props->reset_control_bar_pos_ && ImGui::IsMouseReleased(ImGuiPopupFlags_MouseButtonLeft) || - properties->control_window_width_is_changing_) { - if (properties->control_winodw_pos_.x <= - properties->sub_stream_window_width_ / 2) { + props->control_window_width_is_changing_) { + if (props->control_winodw_pos_.x <= props->sub_stream_window_width_ / 2) { float pos_x = 0; float pos_y = - (properties->control_winodw_pos_.y >= + (props->control_winodw_pos_.y >= (fullscreen_button_pressed_ ? 0 : (title_bar_height_ + 1)) && - properties->control_winodw_pos_.y <= - properties->sub_stream_window_height_ - - properties->control_window_height_) - ? properties->control_winodw_pos_.y - : (properties->control_winodw_pos_.y < - (fullscreen_button_pressed_ ? 0 + props->control_winodw_pos_.y <= + props->sub_stream_window_height_ - props->control_window_height_) + ? props->control_winodw_pos_.y + : (props->control_winodw_pos_.y < (fullscreen_button_pressed_ + ? 0 : (title_bar_height_ + 1)) ? (fullscreen_button_pressed_ ? 0 : (title_bar_height_ + 1)) - : (properties->sub_stream_window_height_ - - properties->control_window_height_)); + : (props->sub_stream_window_height_ - + props->control_window_height_)); - if (properties->control_bar_expand_) { - if (properties->control_window_width_ >= - properties->control_window_max_width_) { - properties->control_window_width_ = - properties->control_window_max_width_; - properties->control_window_width_is_changing_ = false; + if (props->control_bar_expand_) { + if (props->control_window_width_ >= props->control_window_max_width_) { + props->control_window_width_ = props->control_window_max_width_; + props->control_window_width_is_changing_ = false; } else { - properties->control_window_width_is_changing_ = true; + props->control_window_width_is_changing_ = true; } } else { - if (properties->control_window_width_ <= - properties->control_window_min_width_) { - properties->control_window_width_ = - properties->control_window_min_width_; - properties->control_window_width_is_changing_ = false; + if (props->control_window_width_ <= props->control_window_min_width_) { + props->control_window_width_ = props->control_window_min_width_; + props->control_window_width_is_changing_ = false; } else { - properties->control_window_width_is_changing_ = true; + props->control_window_width_is_changing_ = true; } } ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y), ImGuiCond_Always); - properties->is_control_bar_in_left_ = true; - } else if (properties->control_winodw_pos_.x > - properties->sub_stream_window_width_ / 2) { + props->is_control_bar_in_left_ = true; + } else if (props->control_winodw_pos_.x > + props->sub_stream_window_width_ / 2) { float pos_x = 0; float pos_y = - (properties->control_winodw_pos_.y >= + (props->control_winodw_pos_.y >= (fullscreen_button_pressed_ ? 0 : (title_bar_height_ + 1)) && - properties->control_winodw_pos_.y <= - properties->sub_stream_window_height_ - - properties->control_window_height_) - ? properties->control_winodw_pos_.y - : (properties->control_winodw_pos_.y < - (fullscreen_button_pressed_ ? 0 + props->control_winodw_pos_.y <= + props->sub_stream_window_height_ - props->control_window_height_) + ? props->control_winodw_pos_.y + : (props->control_winodw_pos_.y < (fullscreen_button_pressed_ + ? 0 : (title_bar_height_ + 1)) ? (fullscreen_button_pressed_ ? 0 : (title_bar_height_ + 1)) - : (properties->sub_stream_window_height_ - - properties->control_window_height_)); + : (props->sub_stream_window_height_ - + props->control_window_height_)); - if (properties->control_bar_expand_) { - if (properties->control_window_width_ >= - properties->control_window_max_width_) { - properties->control_window_width_ = - properties->control_window_max_width_; - properties->control_window_width_is_changing_ = false; - pos_x = properties->sub_stream_window_width_ - - properties->control_window_max_width_; + if (props->control_bar_expand_) { + if (props->control_window_width_ >= props->control_window_max_width_) { + props->control_window_width_ = props->control_window_max_width_; + props->control_window_width_is_changing_ = false; + pos_x = props->sub_stream_window_width_ - + props->control_window_max_width_; } else { - properties->control_window_width_is_changing_ = true; - pos_x = properties->sub_stream_window_width_ - - properties->control_window_width_; + props->control_window_width_is_changing_ = true; + pos_x = + props->sub_stream_window_width_ - props->control_window_width_; } } else { - if (properties->control_window_width_ <= - properties->control_window_min_width_) { - properties->control_window_width_ = - properties->control_window_min_width_; - properties->control_window_width_is_changing_ = false; - pos_x = properties->sub_stream_window_width_ - - properties->control_window_min_width_; + if (props->control_window_width_ <= props->control_window_min_width_) { + props->control_window_width_ = props->control_window_min_width_; + props->control_window_width_is_changing_ = false; + pos_x = props->sub_stream_window_width_ - + props->control_window_min_width_; } else { - properties->control_window_width_is_changing_ = true; - pos_x = properties->sub_stream_window_width_ - - properties->control_window_width_; + props->control_window_width_is_changing_ = true; + pos_x = + props->sub_stream_window_width_ - props->control_window_width_; } } ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y), ImGuiCond_Always); - properties->is_control_bar_in_left_ = false; + props->is_control_bar_in_left_ = false; } } - if (properties->control_bar_expand_ && - properties->control_window_height_is_changing_) { - if (properties->net_traffic_stats_button_pressed_) { - if (properties->control_window_height_ >= - properties->control_window_max_height_) { - properties->control_window_height_ = - properties->control_window_max_height_; - properties->control_window_height_is_changing_ = false; + if (props->control_bar_expand_ && props->control_window_height_is_changing_) { + if (props->net_traffic_stats_button_pressed_) { + if (props->control_window_height_ >= props->control_window_max_height_) { + props->control_window_height_ = props->control_window_max_height_; + props->control_window_height_is_changing_ = false; } else { - properties->control_window_height_is_changing_ = true; + props->control_window_height_is_changing_ = true; } } else { - if (properties->control_window_height_ <= - properties->control_window_min_height_) { - properties->control_window_height_ = - properties->control_window_min_height_; - properties->control_window_height_is_changing_ = false; + if (props->control_window_height_ <= props->control_window_min_height_) { + props->control_window_height_ = props->control_window_min_height_; + props->control_window_height_is_changing_ = false; } else { - properties->control_window_height_is_changing_ = true; + props->control_window_height_is_changing_ = true; } } } ImGui::Begin("ControlWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | - ImGuiWindowFlags_NoScrollbar); + ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoDocking); ImGui::PopStyleVar(); - properties->control_winodw_pos_ = ImGui::GetWindowPos(); - SDL_GetMouseState(&properties->mouse_pos_x_, &properties->mouse_pos_y_); - properties->mouse_diff_control_bar_pos_x_ = - properties->mouse_pos_x_ - properties->control_winodw_pos_.x; - properties->mouse_diff_control_bar_pos_y_ = - properties->mouse_pos_y_ - properties->control_winodw_pos_.y; + props->control_winodw_pos_ = ImGui::GetWindowPos(); + SDL_GetMouseState(&props->mouse_pos_x_, &props->mouse_pos_y_); + props->mouse_diff_control_bar_pos_x_ = + props->mouse_pos_x_ - props->control_winodw_pos_.x; + props->mouse_diff_control_bar_pos_y_ = + props->mouse_pos_y_ - props->control_winodw_pos_.y; ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); static bool a, b, c, d, e; - ImGui::SetNextWindowPos(ImVec2(properties->is_control_bar_in_left_ - ? properties->control_winodw_pos_.x - - properties->control_window_width_ - : properties->control_winodw_pos_.x, - properties->control_winodw_pos_.y), - ImGuiCond_Always); + ImGui::SetNextWindowPos( + ImVec2(props->is_control_bar_in_left_ + ? props->control_winodw_pos_.x - props->control_window_width_ + : props->control_winodw_pos_.x, + props->control_winodw_pos_.y), + ImGuiCond_Always); ImGui::SetWindowFontScale(0.5f); - ImGui::BeginChild("ControlBar", - ImVec2(properties->control_window_width_ * 2, - properties->control_window_height_), - ImGuiChildFlags_Border, ImGuiWindowFlags_NoDecoration); + ImGui::BeginChild( + "ControlBar", + ImVec2(props->control_window_width_ * 2, props->control_window_height_), + ImGuiChildFlags_Border, ImGuiWindowFlags_NoDecoration); ImGui::SetWindowFontScale(1.0f); ImGui::PopStyleColor(); - ControlBar(properties); - properties->control_bar_hovered_ = ImGui::IsWindowHovered(); + ControlBar(props); + props->control_bar_hovered_ = ImGui::IsWindowHovered(); ImGui::EndChild(); ImGui::End(); diff --git a/src/single_window/main_window.cpp b/src/single_window/main_window.cpp index cbd749c..bf5b145 100644 --- a/src/single_window/main_window.cpp +++ b/src/single_window/main_window.cpp @@ -29,8 +29,8 @@ int Render::MainWindow() { RecentConnectionsWindow(); StatusBar(); - for (auto& properties : client_properties_) { - ConnectionStatusWindow(properties.second); + for (auto& it : client_properties_) { + ConnectionStatusWindow(it.second); } return 0; diff --git a/src/single_window/render.cpp b/src/single_window/render.cpp index c9d50d4..dcd5d28 100644 --- a/src/single_window/render.cpp +++ b/src/single_window/render.cpp @@ -559,7 +559,8 @@ int Render::SetupFontAndStyle() { io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls io.ConfigFlags |= - ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking // Load Fonts ImFontConfig config; @@ -712,7 +713,7 @@ int Render::DrawStreamWindow() { ImVec2(stream_window_width_, fullscreen_button_pressed_ ? 0 : title_bar_height_), ImGuiCond_Always); - ImGui::Begin("StreamRender", nullptr, + ImGui::Begin("StreamWindowTitleBar", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBringToFrontOnFocus); ImGui::PopStyleColor(); @@ -932,6 +933,38 @@ void Render::CleanupFactories() { } } +void Render::CleanupPeer(std::string host_name, + std::shared_ptr props) { + if (props->dst_buffer_) { + thumbnail_->SaveToThumbnail( + (char*)props->dst_buffer_, props->video_width_, props->video_height_, + host_name, props->remote_host_name_, + props->remember_password_ ? props->remote_password_ : ""); + } + + PeerPtr* peer_client = props->peer_; + if (peer_client) { + std::string client_id; + if (host_name == client_id_) { + client_id = "C-" + std::string(client_id_); + } else { + client_id = client_id_; + } + LOG_INFO("[{}] Leave connection [{}]", client_id, host_name); + LeaveConnection(peer_client, host_name.c_str()); + LOG_INFO("Destroy peer [{}]", client_id); + DestroyPeer(&peer_client); + } + + client_properties_.erase(host_name); + + if (client_properties_.empty()) { + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); + } +} + void Render::CleanupPeers() { if (peer_) { LOG_INFO("[{}] Leave connection [{}]", client_id_, client_id_); @@ -943,28 +976,10 @@ void Render::CleanupPeers() { for (auto& it : client_properties_) { auto props = it.second; - if (props->dst_buffer_) { - thumbnail_->SaveToThumbnail( - (char*)props->dst_buffer_, props->video_width_, props->video_height_, - it.first, props->remote_host_name_, - props->remember_password_ ? props->remote_password_ : ""); - } - - std::string host_name = it.first; - PeerPtr* peer_client = props->peer_; - if (peer_client) { - std::string client_id; - if (host_name == client_id_) { - client_id = "C-" + std::string(client_id_); - } else { - client_id = client_id_; - } - LOG_INFO("[{}] Leave connection [{}]", client_id, host_name); - LeaveConnection(peer_client, host_name.c_str()); - LOG_INFO("Destroy peer [{}]", client_id); - DestroyPeer(&peer_client); - } + CleanupPeer(it.first, props); } + + client_properties_.clear(); } void Render::UpdateRenderRect() { @@ -989,29 +1004,27 @@ void Render::UpdateRenderRect() { float video_ratio_reverse = (float)props->video_height_ / (float)props->video_width_; - float render_area_width = stream_window_width_; - float render_area_height = - stream_window_height_ - - (fullscreen_button_pressed_ ? 0 : title_bar_height_); + float render_area_width = props->render_window_width_; + float render_area_height = props->render_window_height_; props->stream_render_rect_last_ = props->stream_render_rect_; if (render_area_width < render_area_height * video_ratio) { props->stream_render_rect_ = { - 0, + (int)props->render_window_x_, (int)(abs(render_area_height - render_area_width * video_ratio_reverse) / 2 + - (fullscreen_button_pressed_ ? 0 : title_bar_height_)), + (int)props->render_window_y_), (int)render_area_width, (int)(render_area_width * video_ratio_reverse)}; } else if (render_area_width > render_area_height * video_ratio) { props->stream_render_rect_ = { (int)abs(render_area_width - render_area_height * video_ratio) / 2, - fullscreen_button_pressed_ ? 0 : (int)title_bar_height_, - (int)(render_area_height * video_ratio), (int)render_area_height}; + (int)props->render_window_y_, (int)(render_area_height * video_ratio), + (int)render_area_height}; } else { props->stream_render_rect_ = { - 0, fullscreen_button_pressed_ ? 0 : (int)title_bar_height_, + (int)props->render_window_x_, (int)props->render_window_y_, (int)render_area_width, (int)render_area_height}; } } diff --git a/src/single_window/render.h b/src/single_window/render.h index 0489160..5ab896a 100644 --- a/src/single_window/render.h +++ b/src/single_window/render.h @@ -77,6 +77,12 @@ class Render { int video_width_ = 0; int video_height_ = 0; size_t video_size_ = 0; + bool tab_selected_ = false; + bool tab_opened_ = true; + float render_window_x_ = 0; + float render_window_y_ = 0; + float render_window_width_ = 0; + float render_window_height_ = 0; std::string fullscreen_button_label_ = "Fullscreen"; std::string net_traffic_stats_button_label_ = "Show Net Traffic Stats"; std::string mouse_control_button_label_ = "Mouse Control"; @@ -110,6 +116,8 @@ class Render { void HandleStreamWindow(); void Cleanup(); void CleanupFactories(); + void CleanupPeer(std::string host_name, + std::shared_ptr props); void CleanupPeers(); void UpdateRenderRect(); void ProcessSdlEvent(); @@ -123,12 +131,11 @@ class Render { int RemoteWindow(); int RecentConnectionsWindow(); int SettingWindow(); - int ControlWindow(std::shared_ptr &properties); - int ControlBar(std::shared_ptr &properties); + int ControlWindow(std::shared_ptr &props); + int ControlBar(std::shared_ptr &props); int AboutWindow(); int StatusBar(); - int ConnectionStatusWindow( - std::shared_ptr &properties); + int ConnectionStatusWindow(std::shared_ptr &props); int ShowRecentConnections(); private: @@ -146,7 +153,7 @@ class Render { int DrawMainWindow(); int DrawStreamWindow(); int ConfirmDeleteConnection(); - int NetTrafficStats(std::shared_ptr &properties); + int NetTrafficStats(std::shared_ptr &props); public: static void OnReceiveVideoBufferCb(const XVideoFrame *video_frame, diff --git a/src/single_window/stream_window.cpp b/src/single_window/stream_window.cpp index 2251f61..4b3ebe6 100644 --- a/src/single_window/stream_window.cpp +++ b/src/single_window/stream_window.cpp @@ -6,22 +6,57 @@ int Render::StreamWindow() { ImGui::SetNextWindowPos( ImVec2(0, fullscreen_button_pressed_ ? 0 : title_bar_height_), ImGuiCond_Always); - ImGui::SetNextWindowSize( - ImVec2(stream_window_width_, stream_window_height_ - title_bar_height_), - ImGuiCond_Always); - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1, 1, 1, 0)); - ImGui::PushStyleColor(ImGuiCol_Border, - ImVec4(178 / 255.0f, 178 / 255.0f, 178 / 255.0f, - fullscreen_button_pressed_ ? 0 : 1.0f)); + ImGui::SetNextWindowSize(ImVec2(stream_window_width_, stream_window_height_), + ImGuiCond_Always); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_DockingEmptyBg, ImVec4(0, 0, 0, 0)); ImGui::Begin("VideoBg", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBringToFrontOnFocus); - ImGui::PopStyleColor(2); - for (auto &properties : client_properties_) { - ControlWindow(properties.second); + ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); + ImGui::DockSpace( + dockspace_id, ImVec2(stream_window_width_, stream_window_height_), + ImGuiDockNodeFlags_AutoHideTabBar | ImGuiDockNodeFlags_KeepAliveOnly); + + ImGui::PopStyleColor(3); + ImGui::PopStyleVar(); + + for (auto& it : client_properties_) { + auto& props = it.second; + + // ImGui::SetNextWindowPos( + // ImVec2(0, fullscreen_button_pressed_ ? 0 : title_bar_height_), + // ImGuiCond_Once); + ImGui::SetNextWindowSize( + ImVec2(stream_window_width_, stream_window_height_), ImGuiCond_Once); + ImGui::SetWindowFontScale(0.5f); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::Begin(props->remote_id_.c_str(), nullptr, + ImGuiWindowFlags_NoTitleBar); + ImGui::PopStyleColor(2); + ImGui::PopStyleVar(); + ImGui::SetWindowFontScale(1.0f); + + ImVec2 stream_window_pos = ImGui::GetWindowPos(); + ImGuiViewport* viewport = ImGui::GetWindowViewport(); + ImVec2 stream_window_size = ImGui::GetWindowSize(); + props->render_window_x_ = stream_window_pos.x; + props->render_window_y_ = stream_window_pos.y; + props->render_window_width_ = stream_window_size.x; + props->render_window_height_ = stream_window_size.y; + + ControlWindow(props); + + ImGui::End(); } + UpdateRenderRect(); + ImGui::End(); return 0;