Compare commits

...

14 Commits

Author SHA1 Message Date
dijunkun
a94da8802f [feat] make MainWindow and ServerWindow use rounded corners 2026-02-26 18:06:07 +08:00
dijunkun
4e6f82d00c [feat] restrict the dragging range of the ControlWindow 2026-02-26 15:55:04 +08:00
dijunkun
5e2ad99ec0 [feat] update MiniRTC to resolve color distortion in the OpenH264 decoder 2026-02-25 17:48:30 +08:00
dijunkun
8ab50ea362 [feat] add video resolution and conection mode in NetTrafficStats window 2026-02-25 15:33:17 +08:00
dijunkun
25e9958a69 Merge branch 'file-transfer' of https://github.com/kunkundi/crossdesk into file-transfer 2026-02-24 17:56:21 +08:00
dijunkun
410ea8b96b [feat] update MiniRTC 2026-02-24 17:56:02 +08:00
dijunkun
e656664cad [chore] adjust file transfer save path button pos 2026-02-24 14:36:03 +08:00
dijunkun
0e6cee0961 [fix] fix stream window rendering height 2026-02-24 14:31:34 +08:00
dijunkun
42506b8c1d [ci] combine Linux amd64 and arm64 builds into a single job using matrix 2026-02-13 02:31:58 +08:00
dijunkun
e35365d162 [feat] disable and style minimize_to_tray checkbox for non-Windows platforms 2026-02-13 02:29:52 +08:00
dijunkun
bf1c0f796d [fix] fix Linux system certificate loading failure 2026-02-13 01:56:49 +08:00
dijunkun
547532b28c [fix] fix server window scaling issues on high-DPI displays 2026-02-13 01:26:10 +08:00
dijunkun
a91e23abf6 [fix] fix raw pointer issues when closing connections 2026-02-13 01:12:21 +08:00
dijunkun
2b324f636b [fix] fix macOS system certificate loading failure 2026-02-12 22:49:54 +08:00
25 changed files with 2522 additions and 2302 deletions

View File

@@ -15,76 +15,28 @@ env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs: jobs:
# Linux amd64 build-linux:
build-linux-amd64: name: Build Linux (${{ matrix.arch }})
name: Build on Ubuntu 22.04 amd64 runs-on: ${{ matrix.runner }}
runs-on: ubuntu-22.04
container:
image: crossdesk/ubuntu20.04:latest
options: --user root
steps:
- name: Extract version number
id: version
run: |
VERSION="${GITHUB_REF##*/}"
VERSION_NUM="${VERSION#v}"
echo "VERSION_NUM=${VERSION_NUM}" >> $GITHUB_ENV
- name: Set legal Debian version
shell: bash
id: set_deb_version
run: |
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d)
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
LEGAL_VERSION="v0.0.0-${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}"
else
LEGAL_VERSION="v${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}"
fi
echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV
echo "BUILD_DATE=${BUILD_DATE}" >> $GITHUB_ENV
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: recursive
- name: Build CrossDesk
env:
CUDA_PATH: /usr/local/cuda
XMAKE_GLOBALDIR: /data
run: |
ls -la $XMAKE_GLOBALDIR
xmake f --CROSSDESK_VERSION=${LEGAL_VERSION} --USE_CUDA=true --root -y
xmake b -vy --root crossdesk
- name: Package
run: |
chmod +x ./scripts/linux/pkg_amd64.sh
./scripts/linux/pkg_amd64.sh ${LEGAL_VERSION}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: crossdesk-linux-amd64-${{ env.LEGAL_VERSION }}
path: ${{ github.workspace }}/crossdesk-linux-amd64-${{ env.LEGAL_VERSION }}.deb
# Linux arm64
build-linux-arm64:
name: Build on Ubuntu 22.04 arm64
runs-on: ubuntu-22.04-arm
strategy: strategy:
matrix: matrix:
include: include:
- arch: amd64
runner: ubuntu-22.04
image: crossdesk/ubuntu20.04:latest
package_script: ./scripts/linux/pkg_amd64.sh
- arch: arm64 - arch: arm64
runner: ubuntu-22.04-arm
image: crossdesk/ubuntu20.04-arm64v8:latest image: crossdesk/ubuntu20.04-arm64v8:latest
package_script: ./scripts/linux/pkg_arm64.sh package_script: ./scripts/linux/pkg_arm64.sh
container: container:
image: ${{ matrix.image }} image: ${{ matrix.image }}
options: --user root options: --user root
steps: steps:
- name: Extract version number - name: Extract version number
id: version
run: | run: |
VERSION="${GITHUB_REF##*/}" VERSION="${GITHUB_REF##*/}"
VERSION_NUM="${VERSION#v}" VERSION_NUM="${VERSION#v}"
@@ -92,15 +44,16 @@ jobs:
- name: Set legal Debian version - name: Set legal Debian version
shell: bash shell: bash
id: set_deb_version
run: | run: |
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7) SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d) BUILD_DATE=$(TZ=Asia/Shanghai date +%Y%m%d)
if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then if [[ ! "${VERSION_NUM}" =~ ^[0-9] ]]; then
LEGAL_VERSION="v0.0.0-${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}" LEGAL_VERSION="v0.0.0-${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}"
else else
LEGAL_VERSION="v${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}" LEGAL_VERSION="v${VERSION_NUM}-${BUILD_DATE}-${SHORT_SHA}"
fi fi
echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV echo "LEGAL_VERSION=${LEGAL_VERSION}" >> $GITHUB_ENV
echo "BUILD_DATE=${BUILD_DATE}" >> $GITHUB_ENV echo "BUILD_DATE=${BUILD_DATE}" >> $GITHUB_ENV
@@ -313,7 +266,7 @@ jobs:
name: Publish Release name: Publish Release
if: startsWith(github.ref, 'refs/tags/v') if: startsWith(github.ref, 'refs/tags/v')
needs: needs:
[build-linux-amd64, build-linux-arm64, build-macos, build-windows-x64] [build-linux, build-macos, build-windows-x64]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

View File

@@ -0,0 +1,63 @@
#include "rounded_corner_button.h"
namespace crossdesk {
bool RoundedCornerButton(const char* label, const ImVec2& size, float rounding,
ImDrawFlags round_flags, bool enabled,
ImU32 normal_col, ImU32 hover_col, ImU32 active_col,
ImU32 border_col) {
ImGuiWindow* current_window = ImGui::GetCurrentWindow();
if (current_window->SkipItems) return false;
const ImGuiStyle& style = ImGui::GetStyle();
ImGuiID button_id = current_window->GetID(label);
ImVec2 cursor_pos = current_window->DC.CursorPos;
ImVec2 button_size = ImGui::CalcItemSize(size, 0.0f, 0.0f);
ImRect button_rect(cursor_pos, ImVec2(cursor_pos.x + button_size.x,
cursor_pos.y + button_size.y));
ImGui::ItemSize(button_rect);
if (!ImGui::ItemAdd(button_rect, button_id)) return false;
bool is_hovered = false, is_held = false;
bool is_pressed = false;
if (enabled) {
is_pressed =
ImGui::ButtonBehavior(button_rect, button_id, &is_hovered, &is_held);
}
if (normal_col == 0) normal_col = ImGui::GetColorU32(ImGuiCol_Button);
if (hover_col == 0) hover_col = ImGui::GetColorU32(ImGuiCol_ButtonHovered);
if (active_col == 0) active_col = ImGui::GetColorU32(ImGuiCol_ButtonActive);
if (border_col == 0) border_col = ImGui::GetColorU32(ImGuiCol_Border);
ImU32 fill_color = normal_col;
if (is_held && is_hovered)
fill_color = active_col;
else if (is_hovered)
fill_color = hover_col;
if (!enabled) fill_color = IM_COL32(120, 120, 120, 180);
ImDrawList* window_draw_list = ImGui::GetWindowDrawList();
window_draw_list->AddRectFilled(button_rect.Min, button_rect.Max, fill_color,
rounding, round_flags);
if (style.FrameBorderSize > 0.0f) {
window_draw_list->AddRect(button_rect.Min, button_rect.Max, border_col,
rounding, round_flags, style.FrameBorderSize);
}
ImU32 text_color =
ImGui::GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled);
const char* label_end = ImGui::FindRenderedTextEnd(label);
ImGui::PushStyleColor(ImGuiCol_Text,
ImGui::ColorConvertU32ToFloat4(text_color));
ImGui::RenderTextClipped(button_rect.Min, button_rect.Max, label, label_end,
nullptr, ImVec2(0.5f, 0.5f), &button_rect);
ImGui::PopStyleColor();
return is_pressed;
}
} // namespace crossdesk

View File

@@ -0,0 +1,20 @@
/*
* @Author: DI JUNKUN
* @Date: 2026-02-26
* Copyright (c) 2026 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _ROUNDED_CORNER_BUTTON_H_
#define _ROUNDED_CORNER_BUTTON_H_
#include "imgui.h"
#include "imgui_internal.h"
namespace crossdesk {
bool RoundedCornerButton(const char* label, const ImVec2& size, float rounding,
ImDrawFlags round_flags, bool enabled = true,
ImU32 normal_col = 0, ImU32 hover_col = 0,
ImU32 active_col = 0, ImU32 border_col = 0);
} // namespace crossdesk
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -205,11 +205,18 @@ static std::vector<std::string> browse = {
reinterpret_cast<const char*>(u8"浏览"), "Browse"}; reinterpret_cast<const char*>(u8"浏览"), "Browse"};
static std::vector<std::string> default_desktop = { static std::vector<std::string> default_desktop = {
reinterpret_cast<const char*>(u8"桌面"), "Desktop"}; reinterpret_cast<const char*>(u8"桌面"), "Desktop"};
#if _WIN32
static std::vector<std::string> minimize_to_tray = { static std::vector<std::string> minimize_to_tray = {
reinterpret_cast<const char*>(u8"退出时最小化到系统托盘:"), reinterpret_cast<const char*>(u8"退出时最小化到系统托盘:"),
"Minimize to system tray when exit:"}; "Minimize to system tray when exit:"};
static std::vector<std::string> resolution = {
reinterpret_cast<const char*>(u8"分辨率"), "Res"};
static std::vector<std::string> connection_mode = {
reinterpret_cast<const char*>(u8"连接模式"), "Mode"};
static std::vector<std::string> connection_mode_direct = {
reinterpret_cast<const char*>(u8"直连"), "Direct"};
static std::vector<std::string> connection_mode_relay = {
reinterpret_cast<const char*>(u8"中继"), "Relay"};
#if _WIN32
static std::vector<LPCWSTR> exit_program = {L"退出", L"Exit"}; static std::vector<LPCWSTR> exit_program = {L"退出", L"Exit"};
#endif #endif
#ifdef __APPLE__ #ifdef __APPLE__

View File

@@ -101,7 +101,7 @@ int Render::LocalWindow() {
ImGuiCol_WindowBg, ImGuiCol_WindowBg,
ImVec4(1.0f, 1.0f, 1.0f, 1.0f - (float)time_duration)); ImVec4(1.0f, 1.0f, 1.0f, 1.0f - (float)time_duration));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::Begin("ConnectionStatusWindow", nullptr, ImGui::Begin("ConnectionStatusWindow", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoSavedSettings); ImGuiWindowFlags_NoSavedSettings);
@@ -180,7 +180,7 @@ int Render::LocalWindow() {
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0, 1.0, 1.0, 1.0)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0, 1.0, 1.0, 1.0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::Begin("ResetPasswordWindow", nullptr, ImGui::Begin("ResetPasswordWindow", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |

View File

@@ -9,7 +9,7 @@ int Render::RecentConnectionsWindow() {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
float recent_connection_window_width = io.DisplaySize.x; float recent_connection_window_width = io.DisplaySize.x;
float recent_connection_window_height = float recent_connection_window_height =
io.DisplaySize.y * (0.46f - STATUS_BAR_HEIGHT); io.DisplaySize.y * (0.455f - STATUS_BAR_HEIGHT);
ImGui::SetNextWindowPos(ImVec2(0, io.DisplaySize.y * 0.55f), ImGui::SetNextWindowPos(ImVec2(0, io.DisplaySize.y * 0.55f),
ImGuiCond_Always); ImGuiCond_Always);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
@@ -256,7 +256,7 @@ int Render::ConfirmDeleteConnection() {
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0, 1.0, 1.0, 1.0)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0, 1.0, 1.0, 1.0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::Begin("ConfirmDeleteConnectionWindow", nullptr, ImGui::Begin("ConfirmDeleteConnectionWindow", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |

View File

@@ -195,7 +195,7 @@ int Render::ConnectTo(const std::string& remote_id, const char* password,
props->control_window_min_width_ = title_bar_height_ * 0.65f; props->control_window_min_width_ = title_bar_height_ * 0.65f;
props->control_window_min_height_ = title_bar_height_ * 1.3f; props->control_window_min_height_ = title_bar_height_ * 1.3f;
props->control_window_max_width_ = title_bar_height_ * 9.0f; props->control_window_max_width_ = title_bar_height_ * 9.0f;
props->control_window_max_height_ = title_bar_height_ * 6.0f; props->control_window_max_height_ = title_bar_height_ * 7.0f;
if (!props->peer_) { if (!props->peer_) {
LOG_INFO("Create peer [{}] instance failed", props->local_id_); LOG_INFO("Create peer [{}] instance failed", props->local_id_);

View File

@@ -298,7 +298,7 @@ SDL_HitTestResult Render::HitTestCallback(SDL_Window* window,
float mouse_grab_padding = render->title_bar_button_width_ * 0.16f; float mouse_grab_padding = render->title_bar_button_width_ * 0.16f;
if (area->y < render->title_bar_button_width_ && if (area->y < render->title_bar_button_width_ &&
area->y > mouse_grab_padding && area->y > mouse_grab_padding &&
area->x < window_width - render->title_bar_button_width_ * 4.0f && area->x < window_width - render->title_bar_button_width_ * 3.0f &&
area->x > mouse_grab_padding) { area->x > mouse_grab_padding) {
return SDL_HITTEST_DRAGGABLE; return SDL_HITTEST_DRAGGABLE;
} }
@@ -893,7 +893,7 @@ void Render::UpdateInteractions() {
mouse_controller_is_started_ = false; mouse_controller_is_started_ = false;
} }
if (start_keyboard_capturer_ && foucs_on_stream_window_) { if (start_keyboard_capturer_ && focus_on_stream_window_) {
if (!keyboard_capturer_is_started_) { if (!keyboard_capturer_is_started_) {
StartKeyboardCapturer(); StartKeyboardCapturer();
keyboard_capturer_is_started_ = true; keyboard_capturer_is_started_ = true;
@@ -914,9 +914,10 @@ int Render::CreateMainWindow() {
ImGui::SetCurrentContext(main_ctx_); ImGui::SetCurrentContext(main_ctx_);
if (!SDL_CreateWindowAndRenderer( if (!SDL_CreateWindowAndRenderer(
"Remote Desk", (int)main_window_width_, (int)main_window_height_, "CrossDesk Main Window", (int)main_window_width_,
(int)main_window_height_,
SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_BORDERLESS |
SDL_WINDOW_HIDDEN, SDL_WINDOW_HIDDEN | SDL_WINDOW_TRANSPARENT,
&main_window_, &main_renderer_)) { &main_window_, &main_renderer_)) {
LOG_ERROR("Error creating MainWindow and MainRenderer: {}", SDL_GetError()); LOG_ERROR("Error creating MainWindow and MainRenderer: {}", SDL_GetError());
return -1; return -1;
@@ -946,6 +947,8 @@ int Render::CreateMainWindow() {
// for window region action // for window region action
SDL_SetWindowHitTest(main_window_, HitTestCallback, this); SDL_SetWindowHitTest(main_window_, HitTestCallback, this);
SDL_SetRenderDrawBlendMode(main_renderer_, SDL_BLENDMODE_BLEND);
SetupFontAndStyle(&main_windows_system_chinese_font_); SetupFontAndStyle(&main_windows_system_chinese_font_);
ImGuiStyle& style = ImGui::GetStyle(); ImGuiStyle& style = ImGui::GetStyle();
@@ -1002,9 +1005,10 @@ int Render::CreateStreamWindow() {
ImGui::SetCurrentContext(stream_ctx_); ImGui::SetCurrentContext(stream_ctx_);
if (!SDL_CreateWindowAndRenderer( if (!SDL_CreateWindowAndRenderer(
"Stream window", (int)stream_window_width_, "CrossDesk Stream Window", (int)stream_window_width_,
(int)stream_window_height_, (int)stream_window_height_,
SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_BORDERLESS, SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_BORDERLESS |
SDL_WINDOW_TRANSPARENT,
&stream_window_, &stream_renderer_)) { &stream_window_, &stream_renderer_)) {
LOG_ERROR("Error creating stream_window_ and stream_renderer_: {}", LOG_ERROR("Error creating stream_window_ and stream_renderer_: {}",
SDL_GetError()); SDL_GetError());
@@ -1018,6 +1022,8 @@ int Render::CreateStreamWindow() {
// for window region action // for window region action
SDL_SetWindowHitTest(stream_window_, HitTestCallback, this); SDL_SetWindowHitTest(stream_window_, HitTestCallback, this);
SDL_SetRenderDrawBlendMode(stream_renderer_, SDL_BLENDMODE_BLEND);
SetupFontAndStyle(&stream_windows_system_chinese_font_); SetupFontAndStyle(&stream_windows_system_chinese_font_);
ImGuiStyle& style = ImGui::GetStyle(); ImGuiStyle& style = ImGui::GetStyle();
@@ -1073,12 +1079,12 @@ int Render::CreateServerWindow() {
return -1; return -1;
} }
ImGui::SetCurrentContext(server_ctx_); ImGui::SetCurrentContext(server_ctx_);
if (!SDL_CreateWindowAndRenderer("Server window", (int)server_window_width_, if (!SDL_CreateWindowAndRenderer(
(int)server_window_height_, "CrossDesk Server Window", (int)server_window_width_,
SDL_WINDOW_HIGH_PIXEL_DENSITY | (int)server_window_height_,
SDL_WINDOW_BORDERLESS | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_BORDERLESS |
SDL_WINDOW_TRANSPARENT, SDL_WINDOW_TRANSPARENT,
&server_window_, &server_renderer_)) { &server_window_, &server_renderer_)) {
LOG_ERROR("Error creating server_window_ and server_renderer_: {}", LOG_ERROR("Error creating server_window_ and server_renderer_: {}",
SDL_GetError()); SDL_GetError());
return -1; return -1;
@@ -1290,6 +1296,8 @@ int Render::DrawMainWindow() {
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y), ImGui::SetNextWindowSize(ImVec2(io.DisplaySize.x, io.DisplaySize.y),
ImGuiCond_Always); ImGuiCond_Always);
@@ -1298,6 +1306,7 @@ int Render::DrawMainWindow() {
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoBringToFrontOnFocus |
ImGuiWindowFlags_NoDocking); ImGuiWindowFlags_NoDocking);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
ImGui::PopStyleVar();
TitleBar(true); TitleBar(true);
@@ -1318,6 +1327,7 @@ int Render::DrawMainWindow() {
ImGui::Render(); ImGui::Render();
SDL_SetRenderScale(main_renderer_, io.DisplayFramebufferScale.x, SDL_SetRenderScale(main_renderer_, io.DisplayFramebufferScale.x,
io.DisplayFramebufferScale.y); io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(main_renderer_, 0, 0, 0, 0);
SDL_RenderClear(main_renderer_); SDL_RenderClear(main_renderer_);
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), main_renderer_); ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), main_renderer_);
SDL_RenderPresent(main_renderer_); SDL_RenderPresent(main_renderer_);
@@ -1367,6 +1377,7 @@ int Render::DrawStreamWindow() {
ImGui::Render(); ImGui::Render();
SDL_SetRenderScale(stream_renderer_, io.DisplayFramebufferScale.x, SDL_SetRenderScale(stream_renderer_, io.DisplayFramebufferScale.x,
io.DisplayFramebufferScale.y); io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(stream_renderer_, 0, 0, 0, 255);
SDL_RenderClear(stream_renderer_); SDL_RenderClear(stream_renderer_);
// std::shared_lock lock(client_properties_mutex_); // std::shared_lock lock(client_properties_mutex_);
@@ -1393,24 +1404,20 @@ int Render::DrawServerWindow() {
LOG_ERROR("Server context is null"); LOG_ERROR("Server context is null");
return -1; return -1;
} }
if (server_window_) {
int w = 0;
int h = 0;
SDL_GetWindowSize(server_window_, &w, &h);
if (w > 0 && h > 0) {
server_window_width_ = (float)w;
server_window_height_ = (float)h;
}
}
ImGui::SetCurrentContext(server_ctx_); ImGui::SetCurrentContext(server_ctx_);
ImGui_ImplSDLRenderer3_NewFrame(); ImGui_ImplSDLRenderer3_NewFrame();
ImGui_ImplSDL3_NewFrame(); ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame(); ImGui::NewFrame();
ImGuiIO& io = ImGui::GetIO();
server_window_width_ = io.DisplaySize.x;
server_window_height_ = io.DisplaySize.y;
ServerWindow(); ServerWindow();
ImGui::Render(); ImGui::Render();
SDL_SetRenderDrawColor(server_renderer_, 255, 255, 255, 255); SDL_SetRenderScale(server_renderer_, io.DisplayFramebufferScale.x,
io.DisplayFramebufferScale.y);
SDL_SetRenderDrawColor(server_renderer_, 0, 0, 0, 0);
SDL_RenderClear(server_renderer_); SDL_RenderClear(server_renderer_);
ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), server_renderer_); ImGui_ImplSDLRenderer3_RenderDrawData(ImGui::GetDrawData(), server_renderer_);
SDL_RenderPresent(server_renderer_); SDL_RenderPresent(server_renderer_);
@@ -2051,7 +2058,8 @@ void Render::UpdateRenderRect() {
(int)(render_area_width * video_ratio_reverse)}; (int)(render_area_width * video_ratio_reverse)};
} else if (render_area_width > render_area_height * video_ratio) { } else if (render_area_width > render_area_height * video_ratio) {
props->stream_render_rect_ = { props->stream_render_rect_ = {
(int)abs(render_area_width - render_area_height * video_ratio) / 2, (int)abs(render_area_width - render_area_height * video_ratio) / 2 +
(int)props->render_window_x_,
(int)props->render_window_y_, (int)(render_area_height * video_ratio), (int)props->render_window_y_, (int)(render_area_height * video_ratio),
(int)render_area_height}; (int)render_area_height};
} else { } else {
@@ -2176,7 +2184,7 @@ void Render::ProcessSdlEvent(const SDL_Event& event) {
case SDL_EVENT_WINDOW_FOCUS_GAINED: case SDL_EVENT_WINDOW_FOCUS_GAINED:
if (stream_window_ && if (stream_window_ &&
SDL_GetWindowID(stream_window_) == event.window.windowID) { SDL_GetWindowID(stream_window_) == event.window.windowID) {
foucs_on_stream_window_ = true; focus_on_stream_window_ = true;
} else if (main_window_ && } else if (main_window_ &&
SDL_GetWindowID(main_window_) == event.window.windowID) { SDL_GetWindowID(main_window_) == event.window.windowID) {
foucs_on_main_window_ = true; foucs_on_main_window_ = true;
@@ -2186,7 +2194,7 @@ void Render::ProcessSdlEvent(const SDL_Event& event) {
case SDL_EVENT_WINDOW_FOCUS_LOST: case SDL_EVENT_WINDOW_FOCUS_LOST:
if (stream_window_ && if (stream_window_ &&
SDL_GetWindowID(stream_window_) == event.window.windowID) { SDL_GetWindowID(stream_window_) == event.window.windowID) {
foucs_on_stream_window_ = false; focus_on_stream_window_ = false;
} else if (main_window_ && } else if (main_window_ &&
SDL_GetWindowID(main_window_) == event.window.windowID) { SDL_GetWindowID(main_window_) == event.window.windowID) {
foucs_on_main_window_ = false; foucs_on_main_window_ = false;
@@ -2200,7 +2208,7 @@ void Render::ProcessSdlEvent(const SDL_Event& event) {
case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP: case SDL_EVENT_MOUSE_BUTTON_UP:
case SDL_EVENT_MOUSE_WHEEL: case SDL_EVENT_MOUSE_WHEEL:
if (foucs_on_stream_window_) { if (focus_on_stream_window_) {
ProcessMouseEvent(event); ProcessMouseEvent(event);
} }
break; break;

View File

@@ -434,7 +434,7 @@ class Render {
bool show_cursor_ = false; bool show_cursor_ = false;
bool keyboard_capturer_is_started_ = false; bool keyboard_capturer_is_started_ = false;
bool foucs_on_main_window_ = false; bool foucs_on_main_window_ = false;
bool foucs_on_stream_window_ = false; bool focus_on_stream_window_ = false;
bool main_window_minimized_ = false; bool main_window_minimized_ = false;
uint32_t last_main_minimize_request_tick_ = 0; uint32_t last_main_minimize_request_tick_ = 0;
uint32_t last_stream_minimize_request_tick_ = 0; uint32_t last_stream_minimize_request_tick_ = 0;

View File

@@ -104,11 +104,10 @@ int Render::ProcessMouseEvent(const SDL_Event& event) {
} }
if (props->control_bar_hovered_ || props->display_selectable_hovered_) { if (props->control_bar_hovered_ || props->display_selectable_hovered_) {
remote_action.m.flag = MouseFlag::move; break;
} }
std::string msg = remote_action.to_json();
if (props->peer_) { if (props->peer_) {
std::string msg = remote_action.to_json();
SendDataFrame(props->peer_, msg.c_str(), msg.size(), SendDataFrame(props->peer_, msg.c_str(), msg.size(),
props->data_label_.c_str()); props->data_label_.c_str());
} }
@@ -154,8 +153,11 @@ int Render::ProcessMouseEvent(const SDL_Event& event) {
(float)(last_mouse_event.button.y - props->stream_render_rect_.y) / (float)(last_mouse_event.button.y - props->stream_render_rect_.y) /
render_height; render_height;
std::string msg = remote_action.to_json(); if (props->control_bar_hovered_) {
continue;
}
if (props->peer_) { if (props->peer_) {
std::string msg = remote_action.to_json();
SendDataFrame(props->peer_, msg.c_str(), msg.size(), SendDataFrame(props->peer_, msg.c_str(), msg.size(),
props->data_label_.c_str()); props->data_label_.c_str());
} }
@@ -448,9 +450,9 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size,
const double bps = const double bps =
(static_cast<double>(delta_bytes) * 8.0) / delta_seconds; (static_cast<double>(delta_bytes) * 8.0) / delta_seconds;
if (bps > 0.0) { if (bps > 0.0) {
const double capped = (std::min)( const double capped =
bps, (std::min)(bps, static_cast<double>(
static_cast<double>((std::numeric_limits<uint32_t>::max)())); (std::numeric_limits<uint32_t>::max)()));
estimated_rate_bps = static_cast<uint32_t>(capped); estimated_rate_bps = static_cast<uint32_t>(capped);
} }
} }

View File

@@ -141,7 +141,7 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
if (props->control_bar_expand_) { if (props->control_bar_expand_) {
ImGui::SetCursorPosX(props->is_control_bar_in_left_ ImGui::SetCursorPosX(props->is_control_bar_in_left_
? props->control_window_width_ * 1.03f ? props->control_window_width_ * 0.03f
: props->control_window_width_ * 0.17f); : props->control_window_width_ * 0.17f);
ImDrawList* draw_list = ImGui::GetWindowDrawList(); ImDrawList* draw_list = ImGui::GetWindowDrawList();
@@ -359,13 +359,11 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
ImGui::SameLine(); ImGui::SameLine();
} }
float expand_button_pos_x = float expand_button_pos_x = props->control_bar_expand_
props->control_bar_expand_ ? (props->is_control_bar_in_left_ ? (props->is_control_bar_in_left_
? props->control_window_width_ * 1.917f ? props->control_window_width_ * 0.917f
: props->control_window_width_ * 0.03f) : props->control_window_width_ * 0.03f)
: (props->is_control_bar_in_left_ : props->control_window_width_ * 0.11f;
? props->control_window_width_ * 1.02f
: props->control_window_width_ * 0.23f);
ImGui::SetCursorPosX(expand_button_pos_x); ImGui::SetCursorPosX(expand_button_pos_x);
@@ -397,9 +395,7 @@ int Render::ControlBar(std::shared_ptr<SubStreamWindowProperties>& props) {
} }
int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) { int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) {
ImGui::SetCursorPos(ImVec2(props->is_control_bar_in_left_ ImGui::SetCursorPos(ImVec2(props->control_window_width_ * 0.048f,
? props->control_window_width_ * 1.02f
: props->control_window_width_ * 0.02f,
props->control_window_min_height_)); props->control_window_min_height_));
ImGui::SetWindowFontScale(0.5f); ImGui::SetWindowFontScale(0.5f);
if (ImGui::BeginTable("NetTrafficStats", 4, ImGuiTableFlags_BordersH, if (ImGui::BeginTable("NetTrafficStats", 4, ImGuiTableFlags_BordersH,
@@ -460,12 +456,33 @@ int Render::NetTrafficStats(std::shared_ptr<SubStreamWindowProperties>& props) {
LossRateDisplay(props->net_traffic_stats_.total_inbound_stats.loss_rate); LossRateDisplay(props->net_traffic_stats_.total_inbound_stats.loss_rate);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("FPS"); ImGui::Text("FPS:");
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("%d", props->fps_); ImGui::Text("%d", props->fps_);
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::TableNextColumn();
ImGui::Text("%s:",
localization::resolution[localization_language_index_].c_str());
ImGui::TableNextColumn();
ImGui::Text("%dx%d", props->video_width_, props->video_height_);
ImGui::TableNextColumn();
ImGui::TableNextColumn();
ImGui::TableNextColumn();
ImGui::Text(
"%s:",
localization::connection_mode[localization_language_index_].c_str());
ImGui::TableNextColumn();
ImGui::Text(
"%s",
props->traversal_mode_ == 0
? localization::connection_mode_direct[localization_language_index_]
.c_str()
: localization::connection_mode_relay[localization_language_index_]
.c_str());
ImGui::EndTable(); ImGui::EndTable();
} }
ImGui::SetWindowFontScale(1.0f); ImGui::SetWindowFontScale(1.0f);

View File

@@ -9,15 +9,17 @@ int Render::StatusBar() {
float status_bar_width = io.DisplaySize.x; float status_bar_width = io.DisplaySize.x;
float status_bar_height = io.DisplaySize.y * STATUS_BAR_HEIGHT; float status_bar_height = io.DisplaySize.y * STATUS_BAR_HEIGHT;
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
static bool a, b, c, d, e; static bool a, b, c, d, e;
ImGui::SetNextWindowPos(ImVec2(0, io.DisplaySize.y * (1 - STATUS_BAR_HEIGHT)), ImGui::SetNextWindowPos(ImVec2(0, io.DisplaySize.y * (1 - STATUS_BAR_HEIGHT)),
ImGuiCond_Always); ImGuiCond_Always);
ImGui::BeginChild( ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
"StatusBar", ImVec2(status_bar_width, status_bar_height), ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
ImGuiChildFlags_Border, ImGui::BeginChild("StatusBar", ImVec2(status_bar_width, status_bar_height),
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBringToFrontOnFocus); ImGuiChildFlags_Border,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoBringToFrontOnFocus);
ImGui::PopStyleColor(2);
ImVec2 dot_pos = ImVec2(status_bar_width * 0.025f, ImVec2 dot_pos = ImVec2(status_bar_width * 0.025f,
io.DisplaySize.y * (1 - STATUS_BAR_HEIGHT * 0.5f)); io.DisplaySize.y * (1 - STATUS_BAR_HEIGHT * 0.5f));
@@ -40,7 +42,6 @@ int Render::StatusBar() {
.c_str()); .c_str());
ImGui::SetWindowFontScale(1.0f); ImGui::SetWindowFontScale(1.0f);
ImGui::PopStyleColor();
ImGui::EndChild(); ImGui::EndChild();
return 0; return 0;
} }

View File

@@ -2,6 +2,7 @@
#include "localization.h" #include "localization.h"
#include "rd_log.h" #include "rd_log.h"
#include "render.h" #include "render.h"
#include "rounded_corner_button.h"
constexpr double kNewVersionIconBlinkIntervalSec = 2.0; constexpr double kNewVersionIconBlinkIntervalSec = 2.0;
constexpr double kNewVersionIconBlinkOnTimeSec = 1.0; constexpr double kNewVersionIconBlinkOnTimeSec = 1.0;
@@ -23,7 +24,7 @@ int Render::TitleBar(bool main_window) {
if (io.DisplaySize.x > 0.0f && io.DisplaySize.y > 0.0f) { if (io.DisplaySize.x > 0.0f && io.DisplaySize.y > 0.0f) {
title_bar_width = io.DisplaySize.x; title_bar_width = io.DisplaySize.x;
title_bar_height = io.DisplaySize.y * TITLE_BAR_HEIGHT; title_bar_height = io.DisplaySize.y * TITLE_BAR_HEIGHT;
title_bar_height_padding = io.DisplaySize.y * (TITLE_BAR_HEIGHT + 0.01f); title_bar_height_padding = io.DisplaySize.y * TITLE_BAR_HEIGHT;
title_bar_button_width = io.DisplaySize.x * TITLE_BAR_BUTTON_WIDTH; title_bar_button_width = io.DisplaySize.x * TITLE_BAR_BUTTON_WIDTH;
title_bar_button_height = io.DisplaySize.y * TITLE_BAR_BUTTON_HEIGHT; title_bar_button_height = io.DisplaySize.y * TITLE_BAR_BUTTON_HEIGHT;
@@ -45,7 +46,7 @@ int Render::TitleBar(bool main_window) {
title_bar_button_height = title_bar_button_height_; title_bar_button_height = title_bar_button_height_;
} }
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
ImGui::BeginChild(main_window ? "MainTitleBar" : "StreamTitleBar", ImGui::BeginChild(main_window ? "MainTitleBar" : "StreamTitleBar",
@@ -285,8 +286,20 @@ int Render::TitleBar(bool main_window) {
float xmark_pos_y = title_bar_button_height * 0.5f; float xmark_pos_y = title_bar_button_height * 0.5f;
float xmark_size = title_bar_button_width * 0.33f; float xmark_size = title_bar_button_width * 0.33f;
std::string close_button = "##xmark"; // ICON_FA_XMARK; std::string close_button = "##xmark"; // ICON_FA_XMARK;
if (ImGui::Button(close_button.c_str(), bool close_button_clicked = false;
ImVec2(title_bar_button_width, title_bar_button_height))) { if (main_window) {
close_button_clicked = RoundedCornerButton(
close_button.c_str(),
ImVec2(title_bar_button_width, title_bar_button_height), 8.5f,
ImDrawFlags_RoundCornersTopRight, true, IM_COL32(0, 0, 0, 0),
IM_COL32(250, 0, 0, 255), IM_COL32(255, 0, 0, 128));
} else {
close_button_clicked =
ImGui::Button(close_button.c_str(),
ImVec2(title_bar_button_width, title_bar_button_height));
}
if (close_button_clicked) {
#if _WIN32 #if _WIN32
if (enable_minimize_to_tray_) { if (enable_minimize_to_tray_) {
tray_->MinimizeToTray(); tray_->MinimizeToTray();
@@ -299,6 +312,7 @@ int Render::TitleBar(bool main_window) {
} }
#endif #endif
} }
draw_list->AddLine(ImVec2(xmark_pos_x - xmark_size / 2 - 0.25f, draw_list->AddLine(ImVec2(xmark_pos_x - xmark_size / 2 - 0.25f,
xmark_pos_y - xmark_size / 2 + 0.75f), xmark_pos_y - xmark_size / 2 + 0.75f),
ImVec2(xmark_pos_x + xmark_size / 2 - 1.5f, ImVec2(xmark_pos_x + xmark_size / 2 - 1.5f,

View File

@@ -77,7 +77,7 @@ int Render::AboutWindow() {
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::SetWindowFontScale(0.5f); ImGui::SetWindowFontScale(0.5f);
ImGui::Begin( ImGui::Begin(

View File

@@ -18,7 +18,7 @@ bool Render::ConnectionStatusWindow(
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::Begin("ConnectionStatusWindow", nullptr, ImGui::Begin("ConnectionStatusWindow", nullptr,
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |

View File

@@ -42,50 +42,74 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
} }
} }
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1, 1, 1, 1)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 10.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 10.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.0f); ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 10.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::SetNextWindowSize( float y_boundary = fullscreen_button_pressed_ ? 0.0f : title_bar_height_;
ImVec2(props->control_window_width_, props->control_window_height_), float container_x = 0.0f;
ImGuiCond_Always); float container_y = y_boundary;
float container_w = stream_window_width_;
float container_h = stream_window_height_ - y_boundary;
ImGui::SetNextWindowPos(ImVec2(0, title_bar_height_), ImGuiCond_Once); ImGui::SetNextWindowSize(ImVec2(container_w, container_h), ImGuiCond_Always);
ImGui::SetNextWindowPos(ImVec2(container_x, container_y), ImGuiCond_Always);
float pos_x = 0; float pos_x = 0;
float pos_y = 0; float pos_y = 0;
float y_boundary = fullscreen_button_pressed_ ? 0 : title_bar_height_;
if (props->reset_control_bar_pos_) { std::string container_window_title =
float new_cursor_pos_x = 0; props->remote_id_ + "ControlContainerWindow";
float new_cursor_pos_y = 0; ImGui::Begin(container_window_title.c_str(), nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoDocking |
ImGuiWindowFlags_NoBackground);
ImGui::PopStyleVar();
ImVec2 container_pos = ImGui::GetWindowPos();
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) &&
props->control_bar_hovered_) {
float current_x_rel = props->control_window_pos_.x - container_pos.x;
float current_y_rel = props->control_window_pos_.y - container_pos.y;
ImVec2 delta = ImGui::GetIO().MouseDelta;
pos_x = current_x_rel + delta.x;
pos_y = current_y_rel + delta.y;
if (pos_x < 0.0f) pos_x = 0.0f;
if (pos_y < 0.0f) pos_y = 0.0f;
if (pos_x + props->control_window_width_ > container_w)
pos_x = container_w - props->control_window_width_;
if (pos_y + props->control_window_height_ > container_h)
pos_y = container_h - props->control_window_height_;
} else if (props->reset_control_bar_pos_) {
float new_cursor_pos_x = 0.0f;
float new_cursor_pos_y = 0.0f;
// set control window pos // set control window pos
if (props->control_window_pos_.y + props->control_window_height_ > float current_y_rel = props->control_window_pos_.y - container_pos.y;
stream_window_height_) { if (current_y_rel + props->control_window_height_ > container_h) {
pos_y = stream_window_height_ - props->control_window_height_; pos_y = container_h - props->control_window_height_;
} else if (props->control_window_pos_.y < y_boundary) { } else if (current_y_rel < 0.0f) {
pos_y = y_boundary; pos_y = 0.0f;
} else { } else {
pos_y = props->control_window_pos_.y; pos_y = current_y_rel;
} }
if (props->is_control_bar_in_left_) { if (props->is_control_bar_in_left_) {
pos_x = 0; pos_x = 0.0f;
} else { } else {
pos_x = stream_window_width_ - props->control_window_width_; pos_x = container_w - props->control_window_width_;
} }
ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y), ImGuiCond_Always);
if (0 != props->mouse_diff_control_bar_pos_x_ && if (0 != props->mouse_diff_control_bar_pos_x_ &&
0 != props->mouse_diff_control_bar_pos_y_) { 0 != props->mouse_diff_control_bar_pos_y_) {
// set cursor pos // set cursor pos
new_cursor_pos_x = pos_x + props->mouse_diff_control_bar_pos_x_; new_cursor_pos_x =
new_cursor_pos_y = pos_y + props->mouse_diff_control_bar_pos_y_; container_pos.x + pos_x + props->mouse_diff_control_bar_pos_x_;
new_cursor_pos_y =
container_pos.y + pos_y + props->mouse_diff_control_bar_pos_y_;
SDL_WarpMouseInWindow(stream_window_, (int)new_cursor_pos_x, SDL_WarpMouseInWindow(stream_window_, (int)new_cursor_pos_x,
(int)new_cursor_pos_y); (int)new_cursor_pos_y);
@@ -94,12 +118,14 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
} else if (!props->reset_control_bar_pos_ && } else if (!props->reset_control_bar_pos_ &&
ImGui::IsMouseReleased(ImGuiMouseButton_Left) || ImGui::IsMouseReleased(ImGuiMouseButton_Left) ||
props->control_window_width_is_changing_) { props->control_window_width_is_changing_) {
if (props->control_window_pos_.x <= stream_window_width_ * 0.5f) { float current_x_rel = props->control_window_pos_.x - container_pos.x;
if (props->control_window_pos_.y + props->control_window_height_ > float current_y_rel = props->control_window_pos_.y - container_pos.y;
stream_window_height_) { if (current_x_rel <= container_w * 0.5f) {
pos_y = stream_window_height_ - props->control_window_height_; pos_x = 0.0f;
if (current_y_rel + props->control_window_height_ > container_h) {
pos_y = container_h - props->control_window_height_;
} else { } else {
pos_y = props->control_window_pos_.y; pos_y = current_y_rel;
} }
if (props->control_bar_expand_) { if (props->control_bar_expand_) {
@@ -118,47 +144,53 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
} }
} }
props->is_control_bar_in_left_ = true; props->is_control_bar_in_left_ = true;
} else if (props->control_window_pos_.x > stream_window_width_ * 0.5f) { } else if (current_x_rel > container_w * 0.5f) {
pos_x = 0; pos_x = container_w - props->control_window_width_;
pos_y = pos_y = (current_y_rel >= 0.0f &&
(props->control_window_pos_.y >= y_boundary && current_y_rel <= container_h - props->control_window_height_)
props->control_window_pos_.y <= ? current_y_rel
stream_window_height_ - props->control_window_height_) : (current_y_rel < 0.0f
? props->control_window_pos_.y ? 0.0f
: (props->control_window_pos_.y < : (container_h - props->control_window_height_));
(fullscreen_button_pressed_ ? 0 : title_bar_height_)
? (fullscreen_button_pressed_ ? 0 : title_bar_height_)
: (stream_window_height_ - props->control_window_height_));
if (props->control_bar_expand_) { if (props->control_bar_expand_) {
if (props->control_window_width_ >= props->control_window_max_width_) { if (props->control_window_width_ >= props->control_window_max_width_) {
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; props->control_window_width_is_changing_ = false;
pos_x = stream_window_width_ - props->control_window_max_width_; pos_x = container_w - props->control_window_max_width_;
} else { } else {
props->control_window_width_is_changing_ = true; props->control_window_width_is_changing_ = true;
pos_x = stream_window_width_ - props->control_window_width_; pos_x = container_w - props->control_window_width_;
} }
} else { } else {
if (props->control_window_width_ <= props->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_ = props->control_window_min_width_;
props->control_window_width_is_changing_ = false; props->control_window_width_is_changing_ = false;
pos_x = stream_window_width_ - props->control_window_min_width_; pos_x = container_w - props->control_window_min_width_;
} else { } else {
props->control_window_width_is_changing_ = true; props->control_window_width_is_changing_ = true;
pos_x = stream_window_width_ - props->control_window_width_; pos_x = container_w - props->control_window_width_;
} }
} }
props->is_control_bar_in_left_ = false; props->is_control_bar_in_left_ = false;
} }
if (props->control_window_pos_.y + props->control_window_height_ > if (current_y_rel + props->control_window_height_ > container_h) {
stream_window_height_) { pos_y = container_h - props->control_window_height_;
pos_y = stream_window_height_ - props->control_window_height_; } else if (current_y_rel < 0.0f) {
} else if (props->control_window_pos_.y < y_boundary) { pos_y = 0.0f;
pos_y = y_boundary;
} }
ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y), ImGuiCond_Always); } else {
float current_x_rel = props->control_window_pos_.x - container_pos.x;
float current_y_rel = props->control_window_pos_.y - container_pos.y;
pos_x = current_x_rel;
pos_y = current_y_rel;
if (pos_x < 0.0f) pos_x = 0.0f;
if (pos_y < 0.0f) pos_y = 0.0f;
if (pos_x + props->control_window_width_ > container_w)
pos_x = container_w - props->control_window_width_;
if (pos_y + props->control_window_height_ > container_h)
pos_y = container_h - props->control_window_height_;
} }
if (props->control_bar_expand_ && props->control_window_height_is_changing_) { if (props->control_bar_expand_ && props->control_window_height_is_changing_) {
@@ -180,10 +212,20 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
} }
std::string control_window_title = props->remote_id_ + "ControlWindow"; std::string control_window_title = props->remote_id_ + "ControlWindow";
ImGui::Begin(control_window_title.c_str(), nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoDocking); static bool a, b, c, d, e;
ImGui::PopStyleVar(); float child_cursor_x = pos_x;
float child_cursor_y = pos_y;
ImGui::SetCursorPos(ImVec2(child_cursor_x, child_cursor_y));
std::string control_child_window_title =
props->remote_id_ + "ControlChildWindow";
ImGui::BeginChild(
control_child_window_title.c_str(),
ImVec2(props->control_window_width_, props->control_window_height_),
ImGuiChildFlags_Border, ImGuiWindowFlags_NoDecoration);
ImGui::PopStyleColor();
props->control_window_pos_ = ImGui::GetWindowPos(); props->control_window_pos_ = ImGui::GetWindowPos();
SDL_GetMouseState(&props->mouse_pos_x_, &props->mouse_pos_y_); SDL_GetMouseState(&props->mouse_pos_x_, &props->mouse_pos_y_);
@@ -192,31 +234,26 @@ int Render::ControlWindow(std::shared_ptr<SubStreamWindowProperties>& props) {
props->mouse_diff_control_bar_pos_y_ = props->mouse_diff_control_bar_pos_y_ =
props->mouse_pos_y_ - props->control_window_pos_.y; props->mouse_pos_y_ - props->control_window_pos_.y;
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); if (props->control_window_pos_.y < container_pos.y ||
static bool a, b, c, d, e; props->control_window_pos_.y + props->control_window_height_ >
ImGui::SetNextWindowPos( (container_pos.y + container_h) ||
ImVec2(props->is_control_bar_in_left_ props->control_window_pos_.x < container_pos.x ||
? props->control_window_pos_.x - props->control_window_width_ props->control_window_pos_.x + props->control_window_width_ >
: props->control_window_pos_.x, (container_pos.x + container_w)) {
props->control_window_pos_.y), ImGui::ClearActiveID();
ImGuiCond_Always); props->reset_control_bar_pos_ = true;
props->mouse_diff_control_bar_pos_x_ = 0;
std::string control_child_window_title = props->mouse_diff_control_bar_pos_y_ = 0;
props->remote_id_ + "ControlChildWindow"; }
ImGui::BeginChild(control_child_window_title.c_str(),
ImVec2(props->control_window_width_ * 2.0f,
props->control_window_height_),
ImGuiChildFlags_Border, ImGuiWindowFlags_NoDecoration);
ImGui::PopStyleColor();
ControlBar(props); ControlBar(props);
props->control_bar_hovered_ = ImGui::IsWindowHovered(); props->control_bar_hovered_ = ImGui::IsWindowHovered();
ImGui::EndChild(); ImGui::EndChild();
ImGui::End(); ImGui::End();
ImGui::PopStyleVar(4); ImGui::PopStyleVar(3);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
return 0; return 0;
} }
} // namespace crossdesk } // namespace crossdesk

View File

@@ -50,7 +50,7 @@ int Render::SettingWindow() {
int settings_items_offset = 0; int settings_items_offset = 0;
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::Begin(localization::settings[localization_language_index_].c_str(), ImGui::Begin(localization::settings[localization_language_index_].c_str(),
@@ -331,10 +331,14 @@ int Render::SettingWindow() {
ImGui::EndTooltip(); ImGui::EndTooltip();
} }
} }
#if _WIN32
ImGui::Separator(); ImGui::Separator();
{ {
#ifndef _WIN32
ImGui::BeginDisabled();
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.5f, 0.5f, 0.5f, 1.0f));
#endif
settings_items_offset += settings_items_padding; settings_items_offset += settings_items_padding;
ImGui::SetCursorPosY(settings_items_offset); ImGui::SetCursorPosY(settings_items_offset);
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
@@ -350,8 +354,11 @@ int Render::SettingWindow() {
ImGui::Checkbox("##enable_minimize_to_tray_", ImGui::Checkbox("##enable_minimize_to_tray_",
&enable_minimize_to_tray_); &enable_minimize_to_tray_);
} #ifndef _WIN32
ImGui::PopStyleColor();
ImGui::EndDisabled();
#endif #endif
}
ImGui::Separator(); ImGui::Separator();
@@ -365,7 +372,7 @@ int Render::SettingWindow() {
.c_str()); .c_str());
ImGui::SameLine(); ImGui::SameLine();
if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) { if (ConfigCenter::LANGUAGE::CHINESE == localization_language_) {
ImGui::SetCursorPosX(title_bar_button_width_ * 2.8f); ImGui::SetCursorPosX(title_bar_button_width_ * 2.82f);
} else { } else {
ImGui::SetCursorPosX(title_bar_button_width_ * 4.3f); ImGui::SetCursorPosX(title_bar_button_width_ * 4.3f);
} }

View File

@@ -14,7 +14,8 @@ int Render::MainWindow() {
ImGui::SetNextWindowPos(ImVec2(0.0f, io.DisplaySize.y * (TITLE_BAR_HEIGHT)), ImGui::SetNextWindowPos(ImVec2(0.0f, io.DisplaySize.y * (TITLE_BAR_HEIGHT)),
ImGuiCond_Always); ImGuiCond_Always);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
ImGui::BeginChild( ImGui::BeginChild(
"DeskWindow", "DeskWindow",
ImVec2(local_remote_window_width, local_remote_window_height), ImVec2(local_remote_window_width, local_remote_window_height),
@@ -22,7 +23,7 @@ int Render::MainWindow() {
ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoBringToFrontOnFocus); ImGuiWindowFlags_NoBringToFrontOnFocus);
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::PopStyleColor(); ImGui::PopStyleColor(2);
LocalWindow(); LocalWindow();

View File

@@ -127,7 +127,7 @@ int Render::RequestPermissionWindow() {
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));

View File

@@ -51,7 +51,7 @@ int Render::SelfHostedServerWindow() {
{ {
ImGui::SetWindowFontScale(0.5f); ImGui::SetWindowFontScale(0.5f);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::Begin(localization::self_hosted_server_settings ImGui::Begin(localization::self_hosted_server_settings

View File

@@ -8,6 +8,7 @@
#include "localization.h" #include "localization.h"
#include "rd_log.h" #include "rd_log.h"
#include "render.h" #include "render.h"
#include "rounded_corner_button.h"
namespace crossdesk { namespace crossdesk {
@@ -48,17 +49,19 @@ int Render::ServerWindow() {
ImGui::SetNextWindowSize(ImVec2(server_window_width_, server_window_height_), ImGui::SetNextWindowSize(ImVec2(server_window_width_, server_window_height_),
ImGuiCond_Always); ImGuiCond_Always);
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::Begin("##server_window", nullptr, ImGui::Begin("##server_window", nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollbar |
ImGuiWindowFlags_NoScrollWithMouse); ImGuiWindowFlags_NoScrollWithMouse);
ImGui::PopStyleVar();
server_window_title_bar_height_ = title_bar_height_; server_window_title_bar_height_ = title_bar_height_;
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 1.0f, 1.0f, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
ImGui::BeginChild( ImGui::BeginChild(
"ServerTitleBar", "ServerTitleBar",
@@ -83,9 +86,13 @@ int Render::ServerWindow() {
const char* icon = const char* icon =
server_window_collapsed_ ? ICON_FA_ANGLE_DOWN : ICON_FA_ANGLE_UP; server_window_collapsed_ ? ICON_FA_ANGLE_DOWN : ICON_FA_ANGLE_UP;
std::string toggle_label = std::string(icon) + "##server_toggle"; std::string toggle_label = std::string(icon) + "##server_toggle";
if (ImGui::Button(toggle_label.c_str(),
ImVec2(server_title_bar_button_width, bool toggle_clicked = RoundedCornerButton(
server_title_bar_button_height))) { toggle_label.c_str(),
ImVec2(server_title_bar_button_width, server_title_bar_button_height),
8.5f, ImDrawFlags_RoundCornersTopLeft, true, IM_COL32(0, 0, 0, 0),
IM_COL32(0, 0, 0, 25), IM_COL32(255, 255, 255, 255));
if (toggle_clicked) {
if (server_window_) { if (server_window_) {
int w = 0; int w = 0;
int h = 0; int h = 0;
@@ -114,7 +121,7 @@ int Render::ServerWindow() {
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::PopStyleVar(); ImGui::PopStyleVar(2);
ImGui::PopStyleColor(); ImGui::PopStyleColor();
RemoteClientInfoWindow(); RemoteClientInfoWindow();

View File

@@ -117,7 +117,9 @@ int Render::StreamWindow() {
ImGui::SetWindowFontScale(0.6f); ImGui::SetWindowFontScale(0.6f);
ImGui::SetNextWindowSize( ImGui::SetNextWindowSize(
ImVec2(stream_window_width_, stream_window_height_), ImVec2(stream_window_width_,
stream_window_height_ -
(fullscreen_button_pressed_ ? 0 : title_bar_height_)),
ImGuiCond_Always); ImGuiCond_Always);
ImGui::SetNextWindowPos( ImGui::SetNextWindowPos(
ImVec2(0, fullscreen_button_pressed_ ? 0 : title_bar_height_), ImVec2(0, fullscreen_button_pressed_ ? 0 : title_bar_height_),
@@ -138,7 +140,7 @@ int Render::StreamWindow() {
UpdateRenderRect(); UpdateRenderRect();
ControlWindow(props); ControlWindow(props);
// Show file transfer window if needed // Show file transfer window if needed
FileTransferWindow(props); FileTransferWindow(props);
@@ -151,12 +153,12 @@ int Render::StreamWindow() {
// std::unique_lock unique_lock(client_properties_mutex_); // std::unique_lock unique_lock(client_properties_mutex_);
auto erase_it = client_properties_.find(remote_id_to_erase); auto erase_it = client_properties_.find(remote_id_to_erase);
if (erase_it != client_properties_.end()) { if (erase_it != client_properties_.end()) {
erase_it = client_properties_.erase(erase_it); // Ensure we flush pending STREAM_REFRESH_EVENT events and
if (client_properties_.empty()) { // clean up peer resources before erasing the entry, otherwise
SDL_Event event; // SDL events may still hold raw pointers to freed
event.type = SDL_EVENT_QUIT; // SubStreamWindowProperties (including video_frame_mutex_),
SDL_PushEvent(&event); // leading to std::system_error when locking.
} CloseTab(erase_it);
} }
} }
// lock.lock(); // lock.lock();
@@ -217,7 +219,9 @@ int Render::StreamWindow() {
if (props->tab_selected_) { if (props->tab_selected_) {
ImGui::SetNextWindowSize( ImGui::SetNextWindowSize(
ImVec2(stream_window_width_, stream_window_height_), ImVec2(stream_window_width_,
stream_window_height_ -
(fullscreen_button_pressed_ ? 0 : title_bar_height_)),
ImGuiCond_Always); ImGuiCond_Always);
ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always); ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_Always);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
@@ -236,10 +240,10 @@ int Render::StreamWindow() {
UpdateRenderRect(); UpdateRenderRect();
ControlWindow(props); ControlWindow(props);
// Show file transfer window if needed // Show file transfer window if needed
FileTransferWindow(props); FileTransferWindow(props);
ImGui::End(); ImGui::End();
if (!props->peer_) { if (!props->peer_) {
@@ -251,12 +255,7 @@ int Render::StreamWindow() {
// std::unique_lock unique_lock(client_properties_mutex_); // std::unique_lock unique_lock(client_properties_mutex_);
auto erase_it = client_properties_.find(remote_id_to_erase); auto erase_it = client_properties_.find(remote_id_to_erase);
if (erase_it != client_properties_.end()) { if (erase_it != client_properties_.end()) {
client_properties_.erase(erase_it); CloseTab(erase_it);
if (client_properties_.empty()) {
SDL_Event event;
event.type = SDL_EVENT_QUIT;
SDL_PushEvent(&event);
}
} }
} }
// lock.lock(); // lock.lock();

View File

@@ -77,7 +77,7 @@ int Render::UpdateNotificationWindow() {
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f)); ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 5.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::Begin( ImGui::Begin(
localization::notification[localization_language_index_].c_str(), localization::notification[localization_language_index_].c_str(),