From 5f8c0a86d90ee045f47c76adacc795be65b712b3 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 22 Jan 2026 16:44:00 +0100 Subject: [PATCH] [client,sdl] encapsulate window class --- client/SDL/SDL3/sdl_disp.cpp | 4 +- client/SDL/SDL3/sdl_freerdp.cpp | 65 +--------------- client/SDL/SDL3/sdl_window.cpp | 126 +++++++++++++++++++++++++++----- client/SDL/SDL3/sdl_window.hpp | 37 +++++++--- 4 files changed, 142 insertions(+), 90 deletions(-) diff --git a/client/SDL/SDL3/sdl_disp.cpp b/client/SDL/SDL3/sdl_disp.cpp index cc13365c7..fe4619e28 100644 --- a/client/SDL/SDL3/sdl_disp.cpp +++ b/client/SDL/SDL3/sdl_disp.cpp @@ -294,7 +294,7 @@ bool sdlDispContext::updateMonitor(SDL_WindowID id) return true; const auto& window = _sdl->windows.at(id); - auto monitor = window.monitor(); + auto monitor = window.monitor(true); monitor.is_primary = TRUE; if (!freerdp_settings_set_monitor_def_array_sorted(settings, &monitor, 1)) @@ -328,7 +328,7 @@ bool sdlDispContext::updateMonitors(SDL_EventType type) monitors.reserve(_sdl->windows.size()); for (auto& smon : _sdl->windows) { - monitors.emplace_back(smon.second.monitor()); + monitors.emplace_back(smon.second.monitor(false)); } if (!freerdp_settings_set_monitor_def_array_sorted(settings, monitors.data(), monitors.size())) diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 0a2f3bf5c..e1f8a4040 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -110,55 +110,6 @@ static BOOL sdl_begin_paint(rdpContext* context) return TRUE; } -static bool sdl_draw_to_window_rect([[maybe_unused]] SdlContext* sdl, SdlWindow& window, - SDL_Surface* surface, SDL_Point offset, const SDL_Rect& srcRect) -{ - WINPR_ASSERT(surface); - SDL_Rect dstRect = { offset.x + srcRect.x, offset.y + srcRect.y, srcRect.w, srcRect.h }; - return window.blit(surface, srcRect, dstRect); -} - -static bool sdl_draw_to_window_rect(SdlContext* sdl, SdlWindow& window, SDL_Surface* surface, - SDL_Point offset, const std::vector& rects = {}) -{ - if (rects.empty()) - { - return sdl_draw_to_window_rect(sdl, window, surface, offset, - { 0, 0, surface->w, surface->h }); - } - for (auto& srcRect : rects) - { - if (!sdl_draw_to_window_rect(sdl, window, surface, offset, srcRect)) - return false; - } - return true; -} - -static bool sdl_draw_to_window_scaled_rect(SdlContext* sdl, SdlWindow& window, SDL_Surface* surface, - const SDL_Rect& srcRect) -{ - SDL_Rect dstRect = srcRect; - sdl_scale_coordinates(sdl, window.id(), &dstRect.x, &dstRect.y, FALSE, TRUE); - sdl_scale_coordinates(sdl, window.id(), &dstRect.w, &dstRect.h, FALSE, TRUE); - return window.blit(surface, srcRect, dstRect); -} - -static BOOL sdl_draw_to_window_scaled_rect(SdlContext* sdl, SdlWindow& window, SDL_Surface* surface, - const std::vector& rects = {}) -{ - if (rects.empty()) - { - return sdl_draw_to_window_scaled_rect(sdl, window, surface, - { 0, 0, surface->w, surface->h }); - } - for (const auto& srcRect : rects) - { - if (!sdl_draw_to_window_scaled_rect(sdl, window, surface, srcRect)) - return FALSE; - } - return TRUE; -} - static BOOL sdl_draw_to_window(SdlContext* sdl, SdlWindow& window, const std::vector& rects = {}) { @@ -187,14 +138,12 @@ static BOOL sdl_draw_to_window(SdlContext* sdl, SdlWindow& window, { window.setOffsetY((size.h - gdi->height) / 2); } - if (!sdl_draw_to_window_scaled_rect(sdl, window, surface, rects)) + if (!window.drawScaledRects(surface, rects)) return FALSE; } else { - - if (!sdl_draw_to_window_rect(sdl, window, surface, { window.offsetX(), window.offsetY() }, - rects)) + if (!window.drawRects(surface, { window.offsetX(), window.offsetY() }, rects)) return FALSE; } @@ -474,8 +423,6 @@ static BOOL sdl_create_windows(SdlContext* sdl) } Uint32 flags = SDL_WINDOW_HIGH_PIXEL_DENSITY; - auto startupX = SDL_WINDOWPOS_CENTERED_DISPLAY(id); - auto startupY = SDL_WINDOWPOS_CENTERED_DISPLAY(id); if (freerdp_settings_get_bool(settings, FreeRDP_Fullscreen) && !freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) @@ -493,12 +440,8 @@ static BOOL sdl_create_windows(SdlContext* sdl) char buffer[MAX_PATH + 64] = {}; (void)sprintf_s(buffer, sizeof(buffer), "%s:%" PRIu32, title, x); - SdlWindow window{ buffer, - static_cast(startupX), - static_cast(startupY), - static_cast(w), - static_cast(h), - flags }; + auto window = + SdlWindow::create(id, buffer, flags, static_cast(w), static_cast(h)); if (!window.window()) return FALSE; diff --git a/client/SDL/SDL3/sdl_window.cpp b/client/SDL/SDL3/sdl_window.cpp index 7b8bd9001..94037a51d 100644 --- a/client/SDL/SDL3/sdl_window.cpp +++ b/client/SDL/SDL3/sdl_window.cpp @@ -17,6 +17,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include +#include + #include "sdl_window.hpp" #include "sdl_utils.hpp" @@ -42,11 +45,11 @@ SdlWindow::SdlWindow(const std::string& title, Sint32 startupX, Sint32 startupY, _window = SDL_CreateWindowWithProperties(props); SDL_DestroyProperties(props); - auto scale = SDL_GetWindowPixelDensity(_window); - const int iscale = static_cast(scale * 100.0f); + auto sc = scale(); + const int iscale = static_cast(sc * 100.0f); auto w = 100 * width / iscale; auto h = 100 * height / iscale; - (void)SDL_SetWindowSize(_window, w, h); + resize({ w, h }); SDL_SetHint(SDL_HINT_APP_NAME, ""); (void)SDL_SyncWindow(_window); } @@ -112,27 +115,21 @@ Sint32 SdlWindow::offsetY() const return _offset_y; } -rdpMonitor SdlWindow::monitor() const +rdpMonitor SdlWindow::monitor(bool isPrimary) const { rdpMonitor mon{}; - const auto factor = SDL_GetWindowDisplayScale(_window); + const auto factor = scale(); const auto dsf = static_cast(100 * factor); mon.attributes.desktopScaleFactor = dsf; mon.attributes.deviceScaleFactor = 100; - int pixelWidth = 0; - int pixelHeight = 0; - auto prc = SDL_GetWindowSizeInPixels(_window, &pixelWidth, &pixelHeight); + const auto r = rect(); + mon.width = r.w; + mon.height = r.h; - if (prc) - { - mon.width = pixelWidth; - mon.height = pixelHeight; - - mon.attributes.physicalWidth = WINPR_ASSERTING_INT_CAST(uint32_t, pixelWidth); - mon.attributes.physicalHeight = WINPR_ASSERTING_INT_CAST(uint32_t, pixelHeight); - } + mon.attributes.physicalWidth = WINPR_ASSERTING_INT_CAST(uint32_t, r.w); + mon.attributes.physicalHeight = WINPR_ASSERTING_INT_CAST(uint32_t, r.h); SDL_Rect rect = {}; auto did = SDL_GetDisplayForWindow(_window); @@ -148,11 +145,21 @@ rdpMonitor SdlWindow::monitor() const mon.attributes.orientation = sdl::utils::orientaion_to_rdp(orientation); auto primary = SDL_GetPrimaryDisplay(); - mon.is_primary = SDL_GetWindowID(_window) == primary; + mon.is_primary = isPrimary || (SDL_GetWindowID(_window) == primary); mon.orig_screen = did; + if (mon.is_primary) + { + mon.x = 0; + mon.y = 0; + } return mon; } +float SdlWindow::scale() const +{ + return SDL_GetWindowDisplayScale(_window); +} + bool SdlWindow::grabKeyboard(bool enable) { if (!_window) @@ -200,6 +207,56 @@ void SdlWindow::minimize() (void)SDL_SyncWindow(_window); } +bool SdlWindow::resize(const SDL_Point& size) +{ + return SDL_SetWindowSize(_window, size.x, size.y); +} + +bool SdlWindow::drawRect(SDL_Surface* surface, SDL_Point offset, const SDL_Rect& srcRect) +{ + WINPR_ASSERT(surface); + SDL_Rect dstRect = { offset.x + srcRect.x, offset.y + srcRect.y, srcRect.w, srcRect.h }; + return blit(surface, srcRect, dstRect); +} + +bool SdlWindow::drawRects(SDL_Surface* surface, SDL_Point offset, + const std::vector& rects) +{ + if (rects.empty()) + { + return drawRect(surface, offset, { 0, 0, surface->w, surface->h }); + } + for (auto& srcRect : rects) + { + if (!drawRect(surface, offset, srcRect)) + return false; + } + return true; +} + +bool SdlWindow::drawScaledRect(SDL_Surface* surface, const SDL_Rect& srcRect) +{ + SDL_Rect dstRect = srcRect; + // TODO: Scale + // sdl_scale_coordinates(sdl, id(), &dstRect.x, &dstRect.y, FALSE, TRUE); + // sdl_scale_coordinates(sdl, id(), &dstRect.w, &dstRect.h, FALSE, TRUE); + return blit(surface, srcRect, dstRect); +} + +bool SdlWindow::drawScaledRects(SDL_Surface* surface, const std::vector& rects) +{ + if (rects.empty()) + { + return drawScaledRect(surface, { 0, 0, surface->w, surface->h }); + } + for (const auto& srcRect : rects) + { + if (!drawScaledRect(surface, srcRect)) + return false; + } + return true; +} + bool SdlWindow::fill(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { auto surface = SDL_GetWindowSurface(_window); @@ -233,3 +290,38 @@ void SdlWindow::updateSurface() { SDL_UpdateWindowSurface(_window); } + +SdlWindow SdlWindow::create(SDL_DisplayID id, const std::string& title, Uint32 flags, Uint32 width, + Uint32 height) +{ + flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY; + auto startupX = static_cast(SDL_WINDOWPOS_CENTERED_DISPLAY(id)); + auto startupY = static_cast(SDL_WINDOWPOS_CENTERED_DISPLAY(id)); + + if ((flags & SDL_WINDOW_FULLSCREEN) != 0) + { + SDL_Rect rect = {}; + SDL_GetDisplayBounds(id, &rect); + startupX = rect.x; + startupY = rect.y; + width = static_cast(rect.w); + height = static_cast(rect.h); + } + + std::stringstream ss; + ss << title << ":" << id; + SdlWindow window{ + ss.str(), startupX, startupY, static_cast(width), static_cast(height), flags + }; + (void)window.window(); + + if ((flags & (SDL_WINDOW_FULLSCREEN)) != 0) + { + SDL_Rect rect = {}; + SDL_GetDisplayBounds(id, &rect); + window.setOffsetX(rect.x); + window.setOffsetY(rect.y); + } + + return window; +} diff --git a/client/SDL/SDL3/sdl_window.hpp b/client/SDL/SDL3/sdl_window.hpp index d53255f43..629d1ee01 100644 --- a/client/SDL/SDL3/sdl_window.hpp +++ b/client/SDL/SDL3/sdl_window.hpp @@ -20,6 +20,8 @@ #pragma once #include +#include + #include #include @@ -27,11 +29,12 @@ class SdlWindow { public: - SdlWindow(const std::string& title, Sint32 startupX, Sint32 startupY, Sint32 width, - Sint32 height, Uint32 flags); + [[nodiscard]] static SdlWindow create(SDL_DisplayID id, const std::string& title, Uint32 flags, + Uint32 width = 0, Uint32 height = 0); + SdlWindow(SdlWindow&& other) noexcept; SdlWindow(const SdlWindow& other) = delete; - ~SdlWindow(); + virtual ~SdlWindow(); SdlWindow& operator=(const SdlWindow& other) = delete; SdlWindow& operator=(SdlWindow&& other) = delete; @@ -47,23 +50,37 @@ class SdlWindow void setOffsetY(Sint32 y); [[nodiscard]] Sint32 offsetY() const; - [[nodiscard]] rdpMonitor monitor() const; + [[nodiscard]] rdpMonitor monitor(bool isPrimary) const; - bool grabKeyboard(bool enable); - bool grabMouse(bool enable); + [[nodiscard]] float scale() const; + + [[nodiscard]] bool grabKeyboard(bool enable); + [[nodiscard]] bool grabMouse(bool enable); void setBordered(bool bordered); void raise(); void resizeable(bool use); void fullscreen(bool enter); void minimize(); - bool fill(Uint8 r = 0x00, Uint8 g = 0x00, Uint8 b = 0x00, Uint8 a = 0xff); - bool blit(SDL_Surface* surface, const SDL_Rect& src, SDL_Rect& dst); + [[nodiscard]] bool resize(const SDL_Point& size); + + [[nodiscard]] bool drawRect(SDL_Surface* surface, SDL_Point offset, const SDL_Rect& srcRect); + [[nodiscard]] bool drawRects(SDL_Surface* surface, SDL_Point offset, + const std::vector& rects = {}); + [[nodiscard]] bool drawScaledRect(SDL_Surface* surface, const SDL_Rect& srcRect); + + [[nodiscard]] bool drawScaledRects(SDL_Surface* surface, + const std::vector& rects = {}); + + [[nodiscard]] bool fill(Uint8 r = 0x00, Uint8 g = 0x00, Uint8 b = 0x00, Uint8 a = 0xff); + [[nodiscard]] bool blit(SDL_Surface* surface, const SDL_Rect& src, SDL_Rect& dst); void updateSurface(); - private: - static UINT32 orientaion_to_rdp(SDL_DisplayOrientation orientation); + protected: + SdlWindow(const std::string& title, Sint32 startupX, Sint32 startupY, Sint32 width, + Sint32 height, Uint32 flags); + private: SDL_Window* _window = nullptr; Sint32 _offset_x = 0; Sint32 _offset_y = 0;