From af48763b9aa1f2315e8a63178e9b2a47c2cfb228 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 22 Jan 2026 16:20:43 +0100 Subject: [PATCH 01/30] [client,sdl] simplify sdl thread startup --- client/SDL/SDL3/sdl_freerdp.cpp | 135 +++++++++++++------------------- client/SDL/SDL3/sdl_freerdp.hpp | 4 +- 2 files changed, 57 insertions(+), 82 deletions(-) diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index e853bf517..b4e764b3f 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -513,23 +513,6 @@ static BOOL sdl_play_sound(rdpContext* context, const PLAY_SOUND_UPDATE* play_so return TRUE; } -static BOOL sdl_wait_for_init(SdlContext* sdl) -{ - WINPR_ASSERT(sdl); - sdl->initialize.set(); - - HANDLE handles[] = { sdl->initialized.handle(), freerdp_abort_event(sdl->context()) }; - - const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, INFINITE); - switch (rc) - { - case WAIT_OBJECT_0: - return TRUE; - default: - return FALSE; - } -} - /* Called before a connection is established. * Set all configuration options to support and load channels here. */ static BOOL sdl_pre_connect(freerdp* instance) @@ -564,9 +547,6 @@ static BOOL sdl_pre_connect(freerdp* instance) UINT32 maxWidth = 0; UINT32 maxHeight = 0; - if (!sdl_wait_for_init(sdl)) - return FALSE; - if (!sdl_detect_monitors(sdl, &maxWidth, &maxHeight)) return FALSE; @@ -640,22 +620,6 @@ static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const sdl_push_quit(); } -static void sdl_cleanup_sdl(SdlContext* sdl) -{ - if (!sdl) - return; - - std::unique_lock lock(sdl->critical); - sdl->windows.clear(); - sdl->dialog.destroy(); - - sdl_destroy_primary(sdl); - - freerdp_del_signal_cleanup_handler(sdl->context(), sdl_term_handler); - sdl_dialogs_uninit(); - SDL_Quit(); -} - static BOOL sdl_create_windows(SdlContext* sdl) { WINPR_ASSERT(sdl); @@ -779,44 +743,10 @@ static int sdl_run(SdlContext* sdl) int rc = -1; WINPR_ASSERT(sdl); - HANDLE handles[] = { sdl->initialize.handle(), freerdp_abort_event(sdl->context()) }; - const DWORD status = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, INFINITE); - switch (status) - { - case WAIT_OBJECT_0: - break; - default: - return 0; - } - - SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS); - auto backend = SDL_GetCurrentVideoDriver(); - WLog_Print(sdl->log, WLOG_DEBUG, "client is using backend '%s'", backend); - sdl_dialogs_init(); - - SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0"); - SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); - SDL_SetHint(SDL_HINT_PEN_MOUSE_EVENTS, "0"); - SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); - SDL_SetHint(SDL_HINT_PEN_TOUCH_EVENTS, "1"); - SDL_SetHint(SDL_HINT_TRACKPAD_IS_TOUCH_ONLY, "1"); - - freerdp_add_signal_cleanup_handler(sdl->context(), sdl_term_handler); - sdl->dialog.create(sdl->context()); - sdl->dialog.setTitle("Connecting to '%s'", - freerdp_settings_get_server_name(sdl->context()->settings)); - sdl->dialog.showInfo("The connection is being established\n\nPlease wait..."); - if (!freerdp_settings_get_bool(sdl->context()->settings, FreeRDP_UseCommonStdioCallbacks)) - { - sdl->dialog.show(true); - } - - sdl->initialized.set(); - - while (!shall_abort(sdl)) + while (!sdl->shallAbort()) { SDL_Event windowEvent = {}; - while (!shall_abort(sdl) && SDL_WaitEventTimeout(nullptr, 1000)) + while (!sdl->shallAbort() && SDL_WaitEventTimeout(nullptr, 1000)) { /* Only poll standard SDL events and SDL_EVENT_USERS meant to create * dialogs. do not process the dialog return value events here. @@ -833,12 +763,12 @@ static int sdl_run(SdlContext* sdl) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "got event %s [0x%08" PRIx32 "]", sdl_event_type_str(windowEvent.type), windowEvent.type); #endif + if (sdl->shallAbort(true)) + continue; + + if (sdl->dialog.handleEvent(windowEvent)) { - std::unique_lock lock(sdl->critical); - /* The session might have been disconnected while we were waiting for a - * new SDL event. In that case ignore the SDL event and terminate. */ - if (freerdp_shall_disconnect_context(sdl->context())) - continue; + continue; } if (sdl->dialog.handleEvent(windowEvent)) @@ -1136,7 +1066,6 @@ static int sdl_run(SdlContext* sdl) rc = 1; - sdl_cleanup_sdl(sdl); return rc; } @@ -1777,9 +1706,9 @@ static std::string getRdpFile() int main(int argc, char* argv[]) { int rc = -1; - int status = 0; RDP_CLIENT_ENTRY_POINTS clientEntryPoints = {}; + /* Allocate the RDP context first, we need to pass it to SDL */ RdpClientEntry(&clientEntryPoints); std::unique_ptr sdl_rdp( reinterpret_cast(freerdp_client_context_new(&clientEntryPoints)), @@ -1807,7 +1736,7 @@ int main(int argc, char* argv[]) } } - status = freerdp_client_settings_parse_command_line( + auto status = freerdp_client_settings_parse_command_line( settings, WINPR_ASSERTING_INT_CAST(int, args.size()), args.data(), FALSE); sdl_rdp->sdl->setMetadata(); if (status) @@ -1832,10 +1761,42 @@ int main(int argc, char* argv[]) return rc; } + /* Basic SDL initialization */ + if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) + return -1; + + /* Redirect SDL log messages to wLog */ SDL_SetLogOutputFunction(winpr_LogOutputFunction, sdl); auto level = WLog_GetLogLevel(sdl->log); SDL_SetLogPriorities(wloglevel2dl(level)); + auto backend = SDL_GetCurrentVideoDriver(); + WLog_Print(sdl->log, WLOG_DEBUG, "client is using backend '%s'", backend); + sdl_dialogs_init(); + + SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0"); + SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); + SDL_SetHint(SDL_HINT_PEN_MOUSE_EVENTS, "0"); + SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0"); + SDL_SetHint(SDL_HINT_PEN_TOUCH_EVENTS, "1"); + SDL_SetHint(SDL_HINT_TRACKPAD_IS_TOUCH_ONLY, "1"); + + /* SDL cleanup code if the client exits */ + ScopeGuard guard( + [&]() + { + std::unique_lock lock(sdl->critical); + sdl->windows.clear(); + sdl->dialog.destroy(); + + sdl_destroy_primary(sdl); + + freerdp_del_signal_cleanup_handler(sdl->context(), sdl_term_handler); + sdl_dialogs_uninit(); + SDL_Quit(); + }); + + /* Initialize RDP */ auto context = sdl->context(); WINPR_ASSERT(context); @@ -1922,6 +1883,20 @@ void SdlContext::setMetadata() SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_TYPE_STRING, SDL_CLIENT_TYPE); } +bool SdlContext::shallAbort(bool ignoreDialogs) +{ + std::unique_lock lock(critical); + if (freerdp_shall_disconnect_context(context())) + { + if (ignoreDialogs) + return true; + if (rdp_thread_running) + return false; + return !dialog.isRunning(); + } + return false; +} + bool SdlContext::redraw(bool suppress) const { if (!_connected) diff --git a/client/SDL/SDL3/sdl_freerdp.hpp b/client/SDL/SDL3/sdl_freerdp.hpp index 0c2e14544..45f4d84f9 100644 --- a/client/SDL/SDL3/sdl_freerdp.hpp +++ b/client/SDL/SDL3/sdl_freerdp.hpp @@ -83,6 +83,8 @@ class SdlContext void setMetadata(); + [[nodiscard]] bool shallAbort(bool ignoreDialogs = false); + private: rdpContext* _context; std::atomic _connected = false; @@ -105,8 +107,6 @@ class SdlContext CriticalSection critical; std::thread thread; - WinPREvent initialize; - WinPREvent initialized; WinPREvent windows_created; int exit_code = -1; From f183b1d258df95471e025305adc13d690c96bb15 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 22 Jan 2026 16:28:36 +0100 Subject: [PATCH 02/30] [client,sdl] add utils functions * Add HighDpiScaleMode platformScaleMode(): get the platform specific high dpi hangling type * Move and rename sdl exit codes to separate namespace * mark all functions [[nodiscard]] --- client/SDL/SDL3/sdl_freerdp.cpp | 229 +++----------------------------- client/SDL/SDL3/sdl_utils.cpp | 166 +++++++++++++++++++++++ client/SDL/SDL3/sdl_utils.hpp | 113 ++++++++++++++-- 3 files changed, 287 insertions(+), 221 deletions(-) diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index b4e764b3f..0a2f3bf5c 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -74,206 +74,15 @@ #define SDL_TAG CLIENT_TAG("SDL") -enum SDL_EXIT_CODE -{ - /* section 0-15: protocol-independent codes */ - SDL_EXIT_SUCCESS = 0, - SDL_EXIT_DISCONNECT = 1, - SDL_EXIT_LOGOFF = 2, - SDL_EXIT_IDLE_TIMEOUT = 3, - SDL_EXIT_LOGON_TIMEOUT = 4, - SDL_EXIT_CONN_REPLACED = 5, - SDL_EXIT_OUT_OF_MEMORY = 6, - SDL_EXIT_CONN_DENIED = 7, - SDL_EXIT_CONN_DENIED_FIPS = 8, - SDL_EXIT_USER_PRIVILEGES = 9, - SDL_EXIT_FRESH_CREDENTIALS_REQUIRED = 10, - SDL_EXIT_DISCONNECT_BY_USER = 11, - - /* section 16-31: license error set */ - SDL_EXIT_LICENSE_INTERNAL = 16, - SDL_EXIT_LICENSE_NO_LICENSE_SERVER = 17, - SDL_EXIT_LICENSE_NO_LICENSE = 18, - SDL_EXIT_LICENSE_BAD_CLIENT_MSG = 19, - SDL_EXIT_LICENSE_HWID_DOESNT_MATCH = 20, - SDL_EXIT_LICENSE_BAD_CLIENT = 21, - SDL_EXIT_LICENSE_CANT_FINISH_PROTOCOL = 22, - SDL_EXIT_LICENSE_CLIENT_ENDED_PROTOCOL = 23, - SDL_EXIT_LICENSE_BAD_CLIENT_ENCRYPTION = 24, - SDL_EXIT_LICENSE_CANT_UPGRADE = 25, - SDL_EXIT_LICENSE_NO_REMOTE_CONNECTIONS = 26, - - /* section 32-127: RDP protocol error set */ - SDL_EXIT_RDP = 32, - - /* section 128-254: xfreerdp specific exit codes */ - SDL_EXIT_PARSE_ARGUMENTS = 128, - SDL_EXIT_MEMORY = 129, - SDL_EXIT_PROTOCOL = 130, - SDL_EXIT_CONN_FAILED = 131, - SDL_EXIT_AUTH_FAILURE = 132, - SDL_EXIT_NEGO_FAILURE = 133, - SDL_EXIT_LOGON_FAILURE = 134, - SDL_EXIT_ACCOUNT_LOCKED_OUT = 135, - SDL_EXIT_PRE_CONNECT_FAILED = 136, - SDL_EXIT_CONNECT_UNDEFINED = 137, - SDL_EXIT_POST_CONNECT_FAILED = 138, - SDL_EXIT_DNS_ERROR = 139, - SDL_EXIT_DNS_NAME_NOT_FOUND = 140, - SDL_EXIT_CONNECT_FAILED = 141, - SDL_EXIT_MCS_CONNECT_INITIAL_ERROR = 142, - SDL_EXIT_TLS_CONNECT_FAILED = 143, - SDL_EXIT_INSUFFICIENT_PRIVILEGES = 144, - SDL_EXIT_CONNECT_CANCELLED = 145, - - SDL_EXIT_CONNECT_TRANSPORT_FAILED = 147, - SDL_EXIT_CONNECT_PASSWORD_EXPIRED = 148, - SDL_EXIT_CONNECT_PASSWORD_MUST_CHANGE = 149, - SDL_EXIT_CONNECT_KDC_UNREACHABLE = 150, - SDL_EXIT_CONNECT_ACCOUNT_DISABLED = 151, - SDL_EXIT_CONNECT_PASSWORD_CERTAINLY_EXPIRED = 152, - SDL_EXIT_CONNECT_CLIENT_REVOKED = 153, - SDL_EXIT_CONNECT_WRONG_PASSWORD = 154, - SDL_EXIT_CONNECT_ACCESS_DENIED = 155, - SDL_EXIT_CONNECT_ACCOUNT_RESTRICTION = 156, - SDL_EXIT_CONNECT_ACCOUNT_EXPIRED = 157, - SDL_EXIT_CONNECT_LOGON_TYPE_NOT_GRANTED = 158, - SDL_EXIT_CONNECT_NO_OR_MISSING_CREDENTIALS = 159, - SDL_EXIT_CONNECT_TARGET_BOOTING = 160, - - SDL_EXIT_UNKNOWN = 255, -}; - -struct sdl_exit_code_map_t -{ - DWORD error; - int code; - const char* code_tag; -}; - -#define ENTRY(x, y) { x, y, #y } -static const struct sdl_exit_code_map_t sdl_exit_code_map[] = { - ENTRY(FREERDP_ERROR_SUCCESS, SDL_EXIT_SUCCESS), ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_DISCONNECT), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LOGOFF), ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_IDLE_TIMEOUT), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LOGON_TIMEOUT), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_CONN_REPLACED), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_OUT_OF_MEMORY), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_CONN_DENIED), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_CONN_DENIED_FIPS), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_USER_PRIVILEGES), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_FRESH_CREDENTIALS_REQUIRED), - ENTRY(ERRINFO_LOGOFF_BY_USER, SDL_EXIT_DISCONNECT_BY_USER), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_UNKNOWN), - - /* section 16-31: license error set */ - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_INTERNAL), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_NO_LICENSE_SERVER), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_NO_LICENSE), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_BAD_CLIENT_MSG), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_HWID_DOESNT_MATCH), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_BAD_CLIENT), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_CANT_FINISH_PROTOCOL), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_CLIENT_ENDED_PROTOCOL), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_BAD_CLIENT_ENCRYPTION), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_CANT_UPGRADE), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_NO_REMOTE_CONNECTIONS), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_LICENSE_CANT_UPGRADE), - - /* section 32-127: RDP protocol error set */ - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_RDP), - - /* section 128-254: xfreerdp specific exit codes */ - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_PARSE_ARGUMENTS), ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_MEMORY), - ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_PROTOCOL), ENTRY(FREERDP_ERROR_NONE, SDL_EXIT_CONN_FAILED), - - ENTRY(FREERDP_ERROR_AUTHENTICATION_FAILED, SDL_EXIT_AUTH_FAILURE), - ENTRY(FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED, SDL_EXIT_NEGO_FAILURE), - ENTRY(FREERDP_ERROR_CONNECT_LOGON_FAILURE, SDL_EXIT_LOGON_FAILURE), - ENTRY(FREERDP_ERROR_CONNECT_TARGET_BOOTING, SDL_EXIT_CONNECT_TARGET_BOOTING), - ENTRY(FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT, SDL_EXIT_ACCOUNT_LOCKED_OUT), - ENTRY(FREERDP_ERROR_PRE_CONNECT_FAILED, SDL_EXIT_PRE_CONNECT_FAILED), - ENTRY(FREERDP_ERROR_CONNECT_UNDEFINED, SDL_EXIT_CONNECT_UNDEFINED), - ENTRY(FREERDP_ERROR_POST_CONNECT_FAILED, SDL_EXIT_POST_CONNECT_FAILED), - ENTRY(FREERDP_ERROR_DNS_ERROR, SDL_EXIT_DNS_ERROR), - ENTRY(FREERDP_ERROR_DNS_NAME_NOT_FOUND, SDL_EXIT_DNS_NAME_NOT_FOUND), - ENTRY(FREERDP_ERROR_CONNECT_FAILED, SDL_EXIT_CONNECT_FAILED), - ENTRY(FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR, SDL_EXIT_MCS_CONNECT_INITIAL_ERROR), - ENTRY(FREERDP_ERROR_TLS_CONNECT_FAILED, SDL_EXIT_TLS_CONNECT_FAILED), - ENTRY(FREERDP_ERROR_INSUFFICIENT_PRIVILEGES, SDL_EXIT_INSUFFICIENT_PRIVILEGES), - ENTRY(FREERDP_ERROR_CONNECT_CANCELLED, SDL_EXIT_CONNECT_CANCELLED), - ENTRY(FREERDP_ERROR_CONNECT_TRANSPORT_FAILED, SDL_EXIT_CONNECT_TRANSPORT_FAILED), - ENTRY(FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED, SDL_EXIT_CONNECT_PASSWORD_EXPIRED), - ENTRY(FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE, SDL_EXIT_CONNECT_PASSWORD_MUST_CHANGE), - ENTRY(FREERDP_ERROR_CONNECT_KDC_UNREACHABLE, SDL_EXIT_CONNECT_KDC_UNREACHABLE), - ENTRY(FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED, SDL_EXIT_CONNECT_ACCOUNT_DISABLED), - ENTRY(FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED, - SDL_EXIT_CONNECT_PASSWORD_CERTAINLY_EXPIRED), - ENTRY(FREERDP_ERROR_CONNECT_CLIENT_REVOKED, SDL_EXIT_CONNECT_CLIENT_REVOKED), - ENTRY(FREERDP_ERROR_CONNECT_WRONG_PASSWORD, SDL_EXIT_CONNECT_WRONG_PASSWORD), - ENTRY(FREERDP_ERROR_CONNECT_ACCESS_DENIED, SDL_EXIT_CONNECT_ACCESS_DENIED), - ENTRY(FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION, SDL_EXIT_CONNECT_ACCOUNT_RESTRICTION), - ENTRY(FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED, SDL_EXIT_CONNECT_ACCOUNT_EXPIRED), - ENTRY(FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED, SDL_EXIT_CONNECT_LOGON_TYPE_NOT_GRANTED), - ENTRY(FREERDP_ERROR_CONNECT_NO_OR_MISSING_CREDENTIALS, - SDL_EXIT_CONNECT_NO_OR_MISSING_CREDENTIALS) -}; - -static const struct sdl_exit_code_map_t* sdl_map_entry_by_code(int exit_code) -{ - for (const auto& x : sdl_exit_code_map) - { - const struct sdl_exit_code_map_t* cur = &x; - if (cur->code == exit_code) - return cur; - } - return nullptr; -} - -static const struct sdl_exit_code_map_t* sdl_map_entry_by_error(UINT32 error) -{ - for (const auto& x : sdl_exit_code_map) - { - const struct sdl_exit_code_map_t* cur = &x; - if (cur->error == error) - return cur; - } - return nullptr; -} - -static int sdl_map_error_to_exit_code(DWORD error) -{ - const struct sdl_exit_code_map_t* entry = sdl_map_entry_by_error(error); - if (entry) - return entry->code; - - return SDL_EXIT_CONN_FAILED; -} - -static const char* sdl_map_error_to_code_tag(UINT32 error) -{ - const struct sdl_exit_code_map_t* entry = sdl_map_entry_by_error(error); - if (entry) - return entry->code_tag; - return nullptr; -} - -static const char* sdl_map_to_code_tag(int code) -{ - const struct sdl_exit_code_map_t* entry = sdl_map_entry_by_code(code); - if (entry) - return entry->code_tag; - return nullptr; -} - static int error_info_to_error(freerdp* instance, DWORD* pcode, char** msg, size_t* len) { const DWORD code = freerdp_error_info(instance); const char* name = freerdp_get_error_info_name(code); const char* str = freerdp_get_error_info_string(code); - const int exit_code = sdl_map_error_to_exit_code(code); + const int exit_code = sdl::error::errorToExitCode(code); winpr_asprintf(msg, len, "Terminate with %s due to ERROR_INFO %s [0x%08" PRIx32 "]: %s", - sdl_map_error_to_code_tag(code), name, code, str); + sdl::error::errorToExitCodeTag(code), name, code, str); SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%s", *msg); if (pcode) *pcode = code; @@ -1177,16 +986,16 @@ static void sdl_client_cleanup(SdlContext* sdl, int exit_code, const std::string bool showError = false; if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly)) WLog_Print(sdl->log, WLOG_INFO, "Authentication only, exit status %s [%" PRId32 "]", - sdl_map_to_code_tag(exit_code), exit_code); + sdl::error::exitCodeToTag(exit_code), exit_code); else { switch (exit_code) { - case SDL_EXIT_SUCCESS: - case SDL_EXIT_DISCONNECT: - case SDL_EXIT_LOGOFF: - case SDL_EXIT_DISCONNECT_BY_USER: - case SDL_EXIT_CONNECT_CANCELLED: + case sdl::error::SUCCESS: + case sdl::error::DISCONNECT: + case sdl::error::LOGOFF: + case sdl::error::DISCONNECT_BY_USER: + case sdl::error::CONNECT_CANCELLED: break; default: { @@ -1218,11 +1027,11 @@ static int sdl_client_thread_connect(SdlContext* sdl, std::string& error_msg) rdpSettings* settings = context->settings; WINPR_ASSERT(settings); - int exit_code = SDL_EXIT_SUCCESS; + int exit_code = sdl::error::SUCCESS; if (!rc) { UINT32 error = freerdp_get_last_error(context); - exit_code = sdl_map_error_to_exit_code(error); + exit_code = sdl::error::errorToExitCode(error); } if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly)) @@ -1237,7 +1046,7 @@ static int sdl_client_thread_connect(SdlContext* sdl, std::string& error_msg) if (!rc) { DWORD code = freerdp_error_info(instance); - if (exit_code == SDL_EXIT_SUCCESS) + if (exit_code == sdl::error::SUCCESS) { char* msg = nullptr; size_t len = 0; @@ -1260,12 +1069,12 @@ static int sdl_client_thread_connect(SdlContext* sdl, std::string& error_msg) free(msg); } - if (exit_code == SDL_EXIT_SUCCESS) + if (exit_code == sdl::error::SUCCESS) { if (last == FREERDP_ERROR_AUTHENTICATION_FAILED) - exit_code = SDL_EXIT_AUTH_FAILURE; + exit_code = sdl::error::AUTH_FAILURE; else if (code == ERRINFO_SUCCESS) - exit_code = SDL_EXIT_CONN_FAILED; + exit_code = sdl::error::CONN_FAILED; } sdl->dialog.show(false); @@ -1284,7 +1093,7 @@ static int sdl_client_thread_run(SdlContext* sdl, std::string& error_msg) auto instance = context->instance; WINPR_ASSERT(instance); - int exit_code = SDL_EXIT_SUCCESS; + int exit_code = sdl::error::SUCCESS; while (!freerdp_shall_disconnect_context(context)) { HANDLE handles[MAXIMUM_WAIT_OBJECTS] = {}; @@ -1331,7 +1140,7 @@ static int sdl_client_thread_run(SdlContext* sdl, std::string& error_msg) * did not succeed and no other error was specified. */ if (freerdp_error_info(instance) == 0) - exit_code = SDL_EXIT_CONN_FAILED; + exit_code = sdl::error::CONN_FAILED; } if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) @@ -1343,7 +1152,7 @@ static int sdl_client_thread_run(SdlContext* sdl, std::string& error_msg) } } - if (exit_code == SDL_EXIT_SUCCESS) + if (exit_code == sdl::error::SUCCESS) { DWORD code = 0; { @@ -1370,7 +1179,7 @@ static int sdl_client_thread_run(SdlContext* sdl, std::string& error_msg) /* This situation might be limited to Windows XP. */ WLog_Print(sdl->log, WLOG_INFO, "%s", msg); - exit_code = SDL_EXIT_LOGOFF; + exit_code = sdl::error::LOGOFF; } } @@ -1388,7 +1197,7 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) std::string error_msg; int exit_code = sdl_client_thread_connect(sdl, error_msg); - if (exit_code == SDL_EXIT_SUCCESS) + if (exit_code == sdl::error::SUCCESS) exit_code = sdl_client_thread_run(sdl, error_msg); sdl_client_cleanup(sdl, exit_code, error_msg); diff --git a/client/SDL/SDL3/sdl_utils.cpp b/client/SDL/SDL3/sdl_utils.cpp index 58768c104..e827fe4a9 100644 --- a/client/SDL/SDL3/sdl_utils.cpp +++ b/client/SDL/SDL3/sdl_utils.cpp @@ -390,3 +390,169 @@ std::string sdl::utils::generate_uuid_v4() } return ss.str(); } + +sdl::utils::HighDpiScaleMode sdl::utils::platformScaleMode() +{ + const auto platform = SDL_GetPlatform(); + if (!platform) + return SCALE_MODE_INVALID; + if (strcmp("Windows", platform) == 0) + return SCALE_MODE_X11; + if (strcmp("macOS", platform) == 0) + return SCALE_MODE_WAYLAND; + if (strcmp("Linux", platform) == 0) + { + const auto driver = SDL_GetCurrentVideoDriver(); + if (!driver) + return SCALE_MODE_WAYLAND; + if (strcmp("x11", driver) == 0) + return SCALE_MODE_X11; + if (strcmp("wayland", driver) == 0) + return SCALE_MODE_WAYLAND; + } + return SCALE_MODE_INVALID; +} + +std::string sdl::utils::windowTitle(const rdpSettings* settings) +{ + const char* prefix = "FreeRDP:"; + + if (!settings) + return {}; + + const auto windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle); + if (windowTitle) + return {}; + + const auto name = freerdp_settings_get_server_name(settings); + const auto port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort); + + const auto addPort = (port != 3389); + + std::stringstream ss; + ss << prefix << " "; + if (!addPort) + ss << name; + else + ss << name << ":" << port; + + return ss.str(); +} + +namespace sdl::error +{ + struct sdl_exitCode_map_t + { + DWORD error; + int code; + const char* code_tag; + }; + +#define ENTRY(x, y) { x, y, #y } + static const struct sdl_exitCode_map_t sdl_exitCode_map[] = { + ENTRY(FREERDP_ERROR_SUCCESS, SUCCESS), ENTRY(FREERDP_ERROR_NONE, DISCONNECT), + ENTRY(FREERDP_ERROR_NONE, LOGOFF), ENTRY(FREERDP_ERROR_NONE, IDLE_TIMEOUT), + ENTRY(FREERDP_ERROR_NONE, LOGON_TIMEOUT), ENTRY(FREERDP_ERROR_NONE, CONN_REPLACED), + ENTRY(FREERDP_ERROR_NONE, OUT_OF_MEMORY), ENTRY(FREERDP_ERROR_NONE, CONN_DENIED), + ENTRY(FREERDP_ERROR_NONE, CONN_DENIED_FIPS), ENTRY(FREERDP_ERROR_NONE, USER_PRIVILEGES), + ENTRY(FREERDP_ERROR_NONE, FRESH_CREDENTIALS_REQUIRED), + ENTRY(ERRINFO_LOGOFF_BY_USER, DISCONNECT_BY_USER), ENTRY(FREERDP_ERROR_NONE, UNKNOWN), + + /* section 16-31: license error set */ + ENTRY(FREERDP_ERROR_NONE, LICENSE_INTERNAL), + ENTRY(FREERDP_ERROR_NONE, LICENSE_NO_LICENSE_SERVER), + ENTRY(FREERDP_ERROR_NONE, LICENSE_NO_LICENSE), + ENTRY(FREERDP_ERROR_NONE, LICENSE_BAD_CLIENT_MSG), + ENTRY(FREERDP_ERROR_NONE, LICENSE_HWID_DOESNT_MATCH), + ENTRY(FREERDP_ERROR_NONE, LICENSE_BAD_CLIENT), + ENTRY(FREERDP_ERROR_NONE, LICENSE_CANT_FINISH_PROTOCOL), + ENTRY(FREERDP_ERROR_NONE, LICENSE_CLIENT_ENDED_PROTOCOL), + ENTRY(FREERDP_ERROR_NONE, LICENSE_BAD_CLIENT_ENCRYPTION), + ENTRY(FREERDP_ERROR_NONE, LICENSE_CANT_UPGRADE), + ENTRY(FREERDP_ERROR_NONE, LICENSE_NO_REMOTE_CONNECTIONS), + ENTRY(FREERDP_ERROR_NONE, LICENSE_CANT_UPGRADE), + + /* section 32-127: RDP protocol error set */ + ENTRY(FREERDP_ERROR_NONE, RDP), + + /* section 128-254: xfreerdp specific exit codes */ + ENTRY(FREERDP_ERROR_NONE, PARSE_ARGUMENTS), ENTRY(FREERDP_ERROR_NONE, MEMORY), + ENTRY(FREERDP_ERROR_NONE, PROTOCOL), ENTRY(FREERDP_ERROR_NONE, CONN_FAILED), + + ENTRY(FREERDP_ERROR_AUTHENTICATION_FAILED, AUTH_FAILURE), + ENTRY(FREERDP_ERROR_SECURITY_NEGO_CONNECT_FAILED, NEGO_FAILURE), + ENTRY(FREERDP_ERROR_CONNECT_LOGON_FAILURE, LOGON_FAILURE), + ENTRY(FREERDP_ERROR_CONNECT_TARGET_BOOTING, CONNECT_TARGET_BOOTING), + ENTRY(FREERDP_ERROR_CONNECT_ACCOUNT_LOCKED_OUT, ACCOUNT_LOCKED_OUT), + ENTRY(FREERDP_ERROR_PRE_CONNECT_FAILED, PRE_CONNECT_FAILED), + ENTRY(FREERDP_ERROR_CONNECT_UNDEFINED, CONNECT_UNDEFINED), + ENTRY(FREERDP_ERROR_POST_CONNECT_FAILED, POST_CONNECT_FAILED), + ENTRY(FREERDP_ERROR_DNS_ERROR, DNS_ERROR), + ENTRY(FREERDP_ERROR_DNS_NAME_NOT_FOUND, DNS_NAME_NOT_FOUND), + ENTRY(FREERDP_ERROR_CONNECT_FAILED, CONNECT_FAILED), + ENTRY(FREERDP_ERROR_MCS_CONNECT_INITIAL_ERROR, MCS_CONNECT_INITIAL_ERROR), + ENTRY(FREERDP_ERROR_TLS_CONNECT_FAILED, TLS_CONNECT_FAILED), + ENTRY(FREERDP_ERROR_INSUFFICIENT_PRIVILEGES, INSUFFICIENT_PRIVILEGES), + ENTRY(FREERDP_ERROR_CONNECT_CANCELLED, CONNECT_CANCELLED), + ENTRY(FREERDP_ERROR_CONNECT_TRANSPORT_FAILED, CONNECT_TRANSPORT_FAILED), + ENTRY(FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED, CONNECT_PASSWORD_EXPIRED), + ENTRY(FREERDP_ERROR_CONNECT_PASSWORD_MUST_CHANGE, CONNECT_PASSWORD_MUST_CHANGE), + ENTRY(FREERDP_ERROR_CONNECT_KDC_UNREACHABLE, CONNECT_KDC_UNREACHABLE), + ENTRY(FREERDP_ERROR_CONNECT_ACCOUNT_DISABLED, CONNECT_ACCOUNT_DISABLED), + ENTRY(FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED, CONNECT_PASSWORD_CERTAINLY_EXPIRED), + ENTRY(FREERDP_ERROR_CONNECT_CLIENT_REVOKED, CONNECT_CLIENT_REVOKED), + ENTRY(FREERDP_ERROR_CONNECT_WRONG_PASSWORD, CONNECT_WRONG_PASSWORD), + ENTRY(FREERDP_ERROR_CONNECT_ACCESS_DENIED, CONNECT_ACCESS_DENIED), + ENTRY(FREERDP_ERROR_CONNECT_ACCOUNT_RESTRICTION, CONNECT_ACCOUNT_RESTRICTION), + ENTRY(FREERDP_ERROR_CONNECT_ACCOUNT_EXPIRED, CONNECT_ACCOUNT_EXPIRED), + ENTRY(FREERDP_ERROR_CONNECT_LOGON_TYPE_NOT_GRANTED, CONNECT_LOGON_TYPE_NOT_GRANTED), + ENTRY(FREERDP_ERROR_CONNECT_NO_OR_MISSING_CREDENTIALS, CONNECT_NO_OR_MISSING_CREDENTIALS) + }; + + static const sdl_exitCode_map_t* mapEntryByCode(int exit_code) + { + for (const auto& x : sdl_exitCode_map) + { + auto cur = &x; + if (cur->code == exit_code) + return cur; + } + return nullptr; + } + + static const sdl_exitCode_map_t* mapEntryByError(UINT32 error) + { + for (const auto& x : sdl_exitCode_map) + { + auto cur = &x; + if (cur->error == error) + return cur; + } + return nullptr; + } +} + +int sdl::error::errorToExitCode(DWORD error) +{ + auto entry = mapEntryByError(error); + if (entry) + return entry->code; + + return CONN_FAILED; +} + +const char* sdl::error::errorToExitCodeTag(UINT32 error) +{ + auto entry = mapEntryByError(error); + if (entry) + return entry->code_tag; + return nullptr; +} + +const char* sdl::error::exitCodeToTag(int code) +{ + auto entry = mapEntryByCode(code); + if (entry) + return entry->code_tag; + return nullptr; +} diff --git a/client/SDL/SDL3/sdl_utils.hpp b/client/SDL/SDL3/sdl_utils.hpp index 1157b1467..bd13dd6e2 100644 --- a/client/SDL/SDL3/sdl_utils.hpp +++ b/client/SDL/SDL3/sdl_utils.hpp @@ -22,6 +22,8 @@ #include #include +#include + #include #include #include @@ -67,23 +69,112 @@ typedef struct Sint32 result; } SDL_UserAuthArg; -bool sdl_push_user_event(Uint32 type, ...); +[[nodiscard]] bool sdl_push_user_event(Uint32 type, ...); -bool sdl_push_quit(); +[[nodiscard]] bool sdl_push_quit(); -std::string sdl_window_event_str(Uint32 ev); -const char* sdl_event_type_str(Uint32 type); -const char* sdl_error_string(Sint32 res); +[[nodiscard]] std::string sdl_window_event_str(Uint32 ev); +[[nodiscard]] const char* sdl_event_type_str(Uint32 type); +[[nodiscard]] const char* sdl_error_string(Sint32 res); #define sdl_log_error(res, log, what) sdl_log_error_ex(res, log, what, __FILE__, __LINE__, __func__) -BOOL sdl_log_error_ex(Sint32 res, wLog* log, const char* what, const char* file, size_t line, - const char* fkt); +[[nodiscard]] BOOL sdl_log_error_ex(Sint32 res, wLog* log, const char* what, const char* file, + size_t line, const char* fkt); namespace sdl::utils { - std::string rdp_orientation_to_str(uint32_t orientation); - std::string sdl_orientation_to_str(SDL_DisplayOrientation orientation); - UINT32 orientaion_to_rdp(SDL_DisplayOrientation orientation); + [[nodiscard]] std::string rdp_orientation_to_str(uint32_t orientation); + [[nodiscard]] std::string sdl_orientation_to_str(SDL_DisplayOrientation orientation); + [[nodiscard]] UINT32 orientaion_to_rdp(SDL_DisplayOrientation orientation); + + [[nodiscard]] std::string generate_uuid_v4(); + + enum HighDpiScaleMode + { + SCALE_MODE_INVALID, + SCALE_MODE_X11, + SCALE_MODE_WAYLAND + }; + + HighDpiScaleMode platformScaleMode(); + + [[nodiscard]] std::string windowTitle(const rdpSettings* settings); - std::string generate_uuid_v4(); } // namespace sdl::utils + +namespace sdl::error +{ + enum EXIT_CODE + { + /* section 0-15: protocol-independent codes */ + SUCCESS = 0, + DISCONNECT = 1, + LOGOFF = 2, + IDLE_TIMEOUT = 3, + LOGON_TIMEOUT = 4, + CONN_REPLACED = 5, + OUT_OF_MEMORY = 6, + CONN_DENIED = 7, + CONN_DENIED_FIPS = 8, + USER_PRIVILEGES = 9, + FRESH_CREDENTIALS_REQUIRED = 10, + DISCONNECT_BY_USER = 11, + + /* section 16-31: license error set */ + LICENSE_INTERNAL = 16, + LICENSE_NO_LICENSE_SERVER = 17, + LICENSE_NO_LICENSE = 18, + LICENSE_BAD_CLIENT_MSG = 19, + LICENSE_HWID_DOESNT_MATCH = 20, + LICENSE_BAD_CLIENT = 21, + LICENSE_CANT_FINISH_PROTOCOL = 22, + LICENSE_CLIENT_ENDED_PROTOCOL = 23, + LICENSE_BAD_CLIENT_ENCRYPTION = 24, + LICENSE_CANT_UPGRADE = 25, + LICENSE_NO_REMOTE_CONNECTIONS = 26, + + /* section 32-127: RDP protocol error set */ + RDP = 32, + + /* section 128-254: xfreerdp specific exit codes */ + PARSE_ARGUMENTS = 128, + MEMORY = 129, + PROTOCOL = 130, + CONN_FAILED = 131, + AUTH_FAILURE = 132, + NEGO_FAILURE = 133, + LOGON_FAILURE = 134, + ACCOUNT_LOCKED_OUT = 135, + PRE_CONNECT_FAILED = 136, + CONNECT_UNDEFINED = 137, + POST_CONNECT_FAILED = 138, + DNS_ERROR = 139, + DNS_NAME_NOT_FOUND = 140, + CONNECT_FAILED = 141, + MCS_CONNECT_INITIAL_ERROR = 142, + TLS_CONNECT_FAILED = 143, + INSUFFICIENT_PRIVILEGES = 144, + CONNECT_CANCELLED = 145, + + CONNECT_TRANSPORT_FAILED = 147, + CONNECT_PASSWORD_EXPIRED = 148, + CONNECT_PASSWORD_MUST_CHANGE = 149, + CONNECT_KDC_UNREACHABLE = 150, + CONNECT_ACCOUNT_DISABLED = 151, + CONNECT_PASSWORD_CERTAINLY_EXPIRED = 152, + CONNECT_CLIENT_REVOKED = 153, + CONNECT_WRONG_PASSWORD = 154, + CONNECT_ACCESS_DENIED = 155, + CONNECT_ACCOUNT_RESTRICTION = 156, + CONNECT_ACCOUNT_EXPIRED = 157, + CONNECT_LOGON_TYPE_NOT_GRANTED = 158, + CONNECT_NO_OR_MISSING_CREDENTIALS = 159, + CONNECT_TARGET_BOOTING = 160, + + UNKNOWN = 255, + }; + + [[nodiscard]] int errorToExitCode(DWORD error); + [[nodiscard]] const char* errorToExitCodeTag(UINT32 error); + [[nodiscard]] const char* exitCodeToTag(int code); +} From 5f8c0a86d90ee045f47c76adacc795be65b712b3 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 22 Jan 2026 16:44:00 +0100 Subject: [PATCH 03/30] [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; From 2fe15703b317d9a139babffcc1729ebebe9f64c7 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Thu, 22 Jan 2026 17:00:10 +0100 Subject: [PATCH 04/30] [client,sdl] split SdlContext to separate files --- client/SDL/SDL3/CMakeLists.txt | 2 + .../SDL3/dialogs/sdl_connection_dialog.cpp | 8 +- .../dialogs/sdl_connection_dialog_hider.cpp | 8 +- client/SDL/SDL3/dialogs/sdl_dialogs.cpp | 20 +- client/SDL/SDL3/sdl_channels.cpp | 19 +- client/SDL/SDL3/sdl_clip.cpp | 10 +- client/SDL/SDL3/sdl_clip.hpp | 6 +- client/SDL/SDL3/sdl_context.cpp | 1052 +++++++++++++++++ client/SDL/SDL3/sdl_context.hpp | 175 +++ client/SDL/SDL3/sdl_disp.cpp | 52 +- client/SDL/SDL3/sdl_freerdp.cpp | 997 +--------------- client/SDL/SDL3/sdl_freerdp.hpp | 103 +- client/SDL/SDL3/sdl_kbd.cpp | 56 +- client/SDL/SDL3/sdl_monitor.cpp | 2 +- client/SDL/SDL3/sdl_pointer.cpp | 10 +- client/SDL/SDL3/sdl_touch.cpp | 21 +- 16 files changed, 1364 insertions(+), 1177 deletions(-) create mode 100644 client/SDL/SDL3/sdl_context.cpp create mode 100644 client/SDL/SDL3/sdl_context.hpp diff --git a/client/SDL/SDL3/CMakeLists.txt b/client/SDL/SDL3/CMakeLists.txt index 0774f0076..f0a6eaff3 100644 --- a/client/SDL/SDL3/CMakeLists.txt +++ b/client/SDL/SDL3/CMakeLists.txt @@ -45,6 +45,8 @@ set(SRCS sdl_window.cpp sdl_clip.hpp sdl_clip.cpp + sdl_context.hpp + sdl_context.cpp ) list( diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp index a580b463f..503d7bc50 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp @@ -21,7 +21,7 @@ #include "sdl_connection_dialog.hpp" #include "../sdl_utils.hpp" -#include "../sdl_freerdp.hpp" +#include "../sdl_context.hpp" #include "res/sdl3_resource_manager.hpp" static const SDL_Color textcolor = { 0xd1, 0xcf, 0xcd, 0xff }; @@ -130,11 +130,11 @@ bool SDLConnectionDialog::setModal() if (_window) { auto sdl = get_context(_context); - if (sdl->windows.empty()) + auto parent = sdl->getFirstWindow(); + if (!parent) return true; - auto parent = sdl->windows.begin()->second.window(); - SDL_SetWindowParent(_window.get(), parent); + SDL_SetWindowParent(_window.get(), parent->window()); SDL_SetWindowModal(_window.get(), true); SDL_RaiseWindow(_window.get()); } diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog_hider.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog_hider.cpp index 15d88b5e0..e745527d3 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog_hider.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog_hider.cpp @@ -1,13 +1,13 @@ #include "sdl_connection_dialog_hider.hpp" -#include "../sdl_freerdp.hpp" +#include "../sdl_context.hpp" SDLConnectionDialogHider::SDLConnectionDialogHider(SdlContext* sdl) - : _sdl(sdl), _visible(_sdl->dialog.isVisible()) + : _sdl(sdl), _visible(_sdl->getDialog().isVisible()) { - _sdl->dialog.show(false); + _sdl->getDialog().show(false); } SDLConnectionDialogHider::~SDLConnectionDialogHider() { - _sdl->dialog.show(_visible); + _sdl->getDialog().show(_visible); } diff --git a/client/SDL/SDL3/dialogs/sdl_dialogs.cpp b/client/SDL/SDL3/dialogs/sdl_dialogs.cpp index 207f48780..56db550c1 100644 --- a/client/SDL/SDL3/dialogs/sdl_dialogs.cpp +++ b/client/SDL/SDL3/dialogs/sdl_dialogs.cpp @@ -26,7 +26,7 @@ #include -#include "../sdl_freerdp.hpp" +#include "../sdl_context.hpp" #include "sdl_dialogs.hpp" #include "sdl_input_widget_pair.hpp" #include "sdl_input_widget_pair_list.hpp" @@ -212,24 +212,24 @@ SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, const BOOL enabled = freerdp_settings_get_bool(settings, FreeRDP_AutoReconnectionEnabled); const size_t delay = freerdp_settings_get_uint32(settings, FreeRDP_TcpConnectTimeout); - sdl->dialog.setTitle("Retry connection to %s", - freerdp_settings_get_server_name(instance->context->settings)); + sdl->getDialog().setTitle("Retry connection to %s", + freerdp_settings_get_server_name(instance->context->settings)); if ((strcmp(what, "arm-transport") != 0) && (strcmp(what, "connection") != 0)) { - sdl->dialog.showError("Unknown module %s, aborting", what); + sdl->getDialog().showError("Unknown module %s, aborting", what); return -1; } if (current == 0) { if (strcmp(what, "arm-transport") == 0) - sdl->dialog.showWarn("[%s] Starting your VM. It may take up to 5 minutes", what); + sdl->getDialog().showWarn("[%s] Starting your VM. It may take up to 5 minutes", what); } if (!enabled) { - sdl->dialog.showError( + sdl->getDialog().showError( "Automatic reconnection disabled, terminating. Try to connect again later"); return -1; } @@ -237,16 +237,16 @@ SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, const size_t max = freerdp_settings_get_uint32(settings, FreeRDP_AutoReconnectMaxRetries); if (current >= max) { - sdl->dialog.showError( + sdl->getDialog().showError( "[%s] retries exceeded. Your VM failed to start. Try again later or contact your " "tech support for help if this keeps happening.", what); return -1; } - sdl->dialog.showInfo("[%s] retry %" PRIuz "/%" PRIuz ", delaying %" PRIuz - "ms before next attempt", - what, current + 1, max, delay); + sdl->getDialog().showInfo("[%s] retry %" PRIuz "/%" PRIuz ", delaying %" PRIuz + "ms before next attempt", + what, current + 1, max, delay); return WINPR_ASSERTING_INT_CAST(ssize_t, delay); } diff --git a/client/SDL/SDL3/sdl_channels.cpp b/client/SDL/SDL3/sdl_channels.cpp index c6b482c07..210d3b15d 100644 --- a/client/SDL/SDL3/sdl_channels.cpp +++ b/client/SDL/SDL3/sdl_channels.cpp @@ -26,7 +26,7 @@ #include #include "sdl_channels.hpp" -#include "sdl_freerdp.hpp" +#include "sdl_context.hpp" #include "sdl_disp.hpp" void sdl_OnChannelConnectedEventHandler(void* context, const ChannelConnectedEventArgs* e) @@ -43,13 +43,17 @@ void sdl_OnChannelConnectedEventHandler(void* context, const ChannelConnectedEve { auto clip = reinterpret_cast(e->pInterface); WINPR_ASSERT(clip); - sdl->clip.init(clip); + + if (!sdl->getClipboardChannelContext().init(clip)) + WLog_Print(sdl->getWLog(), WLOG_WARN, "Failed to initialize clipboard channel"); } else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { auto disp = reinterpret_cast(e->pInterface); WINPR_ASSERT(disp); - (void)sdl->disp.init(disp); + + if (!sdl->getDisplayChannelContext().init(disp)) + WLog_Print(sdl->getWLog(), WLOG_WARN, "Failed to initialize display channel"); } else freerdp_client_OnChannelConnectedEventHandler(context, e); @@ -70,14 +74,19 @@ void sdl_OnChannelDisconnectedEventHandler(void* context, const ChannelDisconnec { auto clip = reinterpret_cast(e->pInterface); WINPR_ASSERT(clip); - (void)sdl->clip.uninit(clip); + + if (!sdl->getClipboardChannelContext().uninit(clip)) + WLog_Print(sdl->getWLog(), WLOG_WARN, "Failed to uninitialize clipboard channel"); clip->custom = nullptr; } else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { auto disp = reinterpret_cast(e->pInterface); WINPR_ASSERT(disp); - (void)sdl->disp.uninit(disp); + + if (!sdl->getDisplayChannelContext().uninit(disp)) + WLog_Print(sdl->getWLog(), WLOG_WARN, "Failed to uninitialize display channel"); + disp->custom = nullptr; } else freerdp_client_OnChannelDisconnectedEventHandler(context, e); diff --git a/client/SDL/SDL3/sdl_clip.cpp b/client/SDL/SDL3/sdl_clip.cpp index 59e7afdef..bf2659d01 100644 --- a/client/SDL/SDL3/sdl_clip.cpp +++ b/client/SDL/SDL3/sdl_clip.cpp @@ -29,7 +29,7 @@ #include #include "sdl_clip.hpp" -#include "sdl_freerdp.hpp" +#include "sdl_context.hpp" #define TAG CLIENT_TAG("sdl.cliprdr") @@ -147,7 +147,7 @@ sdlClip::~sdlClip() (void)CloseHandle(_event); } -BOOL sdlClip::init(CliprdrClientContext* clip) +bool sdlClip::init(CliprdrClientContext* clip) { WINPR_ASSERT(clip); _ctx = clip; @@ -162,14 +162,14 @@ BOOL sdlClip::init(CliprdrClientContext* clip) return cliprdr_file_context_init(_file, _ctx); } -BOOL sdlClip::uninit(CliprdrClientContext* clip) +bool sdlClip::uninit(CliprdrClientContext* clip) { WINPR_ASSERT(clip); if (!cliprdr_file_context_uninit(_file, _ctx)) - return FALSE; + return false; _ctx = nullptr; clip->custom = nullptr; - return TRUE; + return true; } bool sdlClip::contains(const char** mime_types, Sint32 count) diff --git a/client/SDL/SDL3/sdl_clip.hpp b/client/SDL/SDL3/sdl_clip.hpp index c8df04d9f..84b513642 100644 --- a/client/SDL/SDL3/sdl_clip.hpp +++ b/client/SDL/SDL3/sdl_clip.hpp @@ -97,10 +97,10 @@ class sdlClip sdlClip& operator=(const sdlClip&) = delete; sdlClip& operator=(sdlClip&&) = delete; - BOOL init(CliprdrClientContext* clip); - BOOL uninit(CliprdrClientContext* clip); + [[nodiscard]] bool init(CliprdrClientContext* clip); + [[nodiscard]] bool uninit(CliprdrClientContext* clip); - bool handle_update(const SDL_ClipboardEvent& ev); + [[nodiscard]] bool handle_update(const SDL_ClipboardEvent& ev); private: UINT SendClientCapabilities(); diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp new file mode 100644 index 000000000..63e49a83b --- /dev/null +++ b/client/SDL/SDL3/sdl_context.cpp @@ -0,0 +1,1052 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * SDL Client + * + * Copyright 2022 Armin Novak + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "sdl_context.hpp" +#include "sdl_config.hpp" +#include "sdl_channels.hpp" +#include "sdl_monitor.hpp" +#include "sdl_pointer.hpp" + +#include +#include + +#include "dialogs/sdl_dialogs.hpp" + +#if defined(WITH_WEBVIEW) +#include +#endif + +SdlContext::SdlContext(rdpContext* context) + : _context(context), _log(WLog_Get(CLIENT_TAG("SDL"))), _rdpThreadRunning(false), + _primary(nullptr, SDL_DestroySurface), _disp(this), _input(this), _clip(this), _dialog(_log) +{ + WINPR_ASSERT(context); + setMetadata(); + + auto instance = _context->instance; + WINPR_ASSERT(instance); + + instance->PreConnect = preConnect; + instance->PostConnect = postConnect; + instance->PostDisconnect = postDisconnect; + instance->PostFinalDisconnect = postFinalDisconnect; + instance->AuthenticateEx = sdl_authenticate_ex; + instance->VerifyCertificateEx = sdl_verify_certificate_ex; + instance->VerifyChangedCertificateEx = sdl_verify_changed_certificate_ex; + instance->LogonErrorInfo = sdl_logon_error_info; + instance->PresentGatewayMessage = sdl_present_gateway_message; + instance->ChooseSmartcard = sdl_choose_smartcard; + instance->RetryDialog = sdl_retry_dialog; + +#ifdef WITH_WEBVIEW + instance->GetAccessToken = sdl_webview_get_access_token; +#else + instance->GetAccessToken = client_cli_get_access_token; +#endif + /* TODO: Client display set up */ +} + +SdlContext::~SdlContext() +{ +} + +void SdlContext::setHasCursor(bool val) +{ + this->_cursor_visible = val; +} + +bool SdlContext::hasCursor() const +{ + return _cursor_visible; +} + +void SdlContext::setMetadata() +{ + auto wmclass = freerdp_settings_get_string(_context->settings, FreeRDP_WmClass); + if (!wmclass || (strlen(wmclass) == 0)) + wmclass = SDL_CLIENT_UUID; + + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, wmclass); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, SDL_CLIENT_NAME); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, SDL_CLIENT_VERSION); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_CREATOR_STRING, SDL_CLIENT_VENDOR); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_COPYRIGHT_STRING, SDL_CLIENT_COPYRIGHT); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_URL_STRING, SDL_CLIENT_URL); + SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_TYPE_STRING, SDL_CLIENT_TYPE); +} + +int SdlContext::start() +{ + _thread = std::thread(rdpThreadRun, this); + return 0; +} + +int SdlContext::join() +{ + /* We do not want to use freerdp_abort_connect_context here. + * It would change the exit code and we do not want that. */ + HANDLE event = freerdp_abort_event(context()); + if (!SetEvent(event)) + return -1; + + _thread.join(); + return 0; +} + +void SdlContext::cleanup() +{ + std::unique_lock lock(_critical); + _windows.clear(); + _dialog.destroy(); + _primary.reset(); +} + +bool SdlContext::shallAbort(bool ignoreDialogs) +{ + std::unique_lock lock(_critical); + if (freerdp_shall_disconnect_context(context())) + { + if (ignoreDialogs) + return true; + if (_rdpThreadRunning) + return false; + return !getDialog().isRunning(); + } + return false; +} + +/* Called before a connection is established. + * Set all configuration options to support and load channels here. */ +BOOL SdlContext::preConnect(freerdp* instance) +{ + WINPR_ASSERT(instance); + WINPR_ASSERT(instance->context); + + auto sdl = get_context(instance->context); + + auto settings = instance->context->settings; + WINPR_ASSERT(settings); + + if (!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, TRUE)) + return FALSE; + + /* Optional OS identifier sent to server */ + if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX)) + return FALSE; + if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_SDL)) + return FALSE; + /* OrderSupport is initialized at this point. + * Only override it if you plan to implement custom order + * callbacks or deactivate certain features. */ + /* Register the channel listeners. + * They are required to set up / tear down channels if they are loaded. */ + PubSub_SubscribeChannelConnected(instance->context->pubSub, sdl_OnChannelConnectedEventHandler); + PubSub_SubscribeChannelDisconnected(instance->context->pubSub, + sdl_OnChannelDisconnectedEventHandler); + + if (!freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly)) + { + UINT32 maxWidth = 0; + UINT32 maxHeight = 0; + + if (!sdl_detect_monitors(sdl, &maxWidth, &maxHeight)) + return FALSE; + + if ((maxWidth != 0) && (maxHeight != 0) && + !freerdp_settings_get_bool(settings, FreeRDP_SmartSizing)) + { + WLog_Print(sdl->getWLog(), WLOG_INFO, "Update size to %ux%u", maxWidth, maxHeight); + if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, maxWidth)) + return FALSE; + if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, maxHeight)) + return FALSE; + } + } + else + { + /* Check +auth-only has a username and password. */ + if (!freerdp_settings_get_string(settings, FreeRDP_Password)) + { + WLog_Print(sdl->getWLog(), WLOG_INFO, + "auth-only, but no password set. Please provide one."); + return FALSE; + } + + if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE)) + return FALSE; + + WLog_Print(sdl->getWLog(), WLOG_INFO, "Authentication only. Don't connect SDL."); + } + + if (!sdl->getInputChannelContext().initialize()) + return FALSE; + + /* TODO: Any code your client requires */ + return TRUE; +} + +/* Called after a RDP connection was successfully established. + * Settings might have changed during negotiation of client / server feature + * support. + * + * Set up local framebuffers and paing callbacks. + * If required, register pointer callbacks to change the local mouse cursor + * when hovering over the RDP window + */ +BOOL SdlContext::postConnect(freerdp* instance) +{ + WINPR_ASSERT(instance); + + auto context = instance->context; + WINPR_ASSERT(context); + + auto sdl = get_context(context); + + // Retry was successful, discard dialog + sdl->getDialog().show(false); + + if (freerdp_settings_get_bool(context->settings, FreeRDP_AuthenticationOnly)) + { + /* Check +auth-only has a username and password. */ + if (!freerdp_settings_get_string(context->settings, FreeRDP_Password)) + { + WLog_Print(sdl->getWLog(), WLOG_INFO, + "auth-only, but no password set. Please provide one."); + return FALSE; + } + + WLog_Print(sdl->getWLog(), WLOG_INFO, "Authentication only. Don't connect to X."); + return TRUE; + } + + if (!sdl->waitForWindowsCreated()) + return FALSE; + + sdl->_sdlPixelFormat = SDL_PIXELFORMAT_BGRA32; + if (!gdi_init(instance, PIXEL_FORMAT_BGRA32)) + return FALSE; + + if (!sdl->createPrimary()) + return FALSE; + + if (!sdl_register_pointer(instance->context->graphics)) + return FALSE; + + WINPR_ASSERT(context->update); + + context->update->BeginPaint = beginPaint; + context->update->EndPaint = endPaint; + context->update->PlaySound = playSound; + context->update->DesktopResize = desktopResize; + context->update->SetKeyboardIndicators = sdlInput::keyboard_set_indicators; + context->update->SetKeyboardImeStatus = sdlInput::keyboard_set_ime_status; + + if (!sdl->setResizeable(false)) + return FALSE; + if (!sdl->setFullscreen(freerdp_settings_get_bool(context->settings, FreeRDP_Fullscreen) || + freerdp_settings_get_bool(context->settings, FreeRDP_UseMultimon))) + return FALSE; + sdl->setConnected(true); + return TRUE; +} + +/* This function is called whether a session ends by failure or success. + * Clean up everything allocated by pre_connect and post_connect. + */ +void SdlContext::postDisconnect(freerdp* instance) +{ + if (!instance) + return; + + if (!instance->context) + return; + + auto sdl = get_context(instance->context); + sdl->setConnected(false); + + gdi_free(instance); +} + +void SdlContext::postFinalDisconnect(freerdp* instance) +{ + if (!instance) + return; + + if (!instance->context) + return; + + PubSub_UnsubscribeChannelConnected(instance->context->pubSub, + sdl_OnChannelConnectedEventHandler); + PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub, + sdl_OnChannelDisconnectedEventHandler); +} + +/* Create a SDL surface from the GDI buffer */ +bool SdlContext::createPrimary() +{ + auto gdi = context()->gdi; + WINPR_ASSERT(gdi); + + _primary = SDLSurfacePtr( + SDL_CreateSurfaceFrom(static_cast(gdi->width), static_cast(gdi->height), + pixelFormat(), gdi->primary_buffer, static_cast(gdi->stride)), + SDL_DestroySurface); + if (!_primary) + return false; + + SDL_SetSurfaceBlendMode(_primary.get(), SDL_BLENDMODE_NONE); + SDL_Rect surfaceRect = { 0, 0, gdi->width, gdi->height }; + SDL_FillSurfaceRect(_primary.get(), &surfaceRect, + SDL_MapSurfaceRGBA(_primary.get(), 0, 0, 0, 0xff)); + + return true; +} + +bool SdlContext::createWindows() +{ + auto settings = context()->settings; + const auto& title = windowTitle(); + + ScopeGuard guard1([&]() { _windowsCreatedEvent.set(); }); + + UINT32 windowCount = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); + + Sint32 originX = 0; + Sint32 originY = 0; + for (UINT32 x = 0; x < windowCount; x++) + { + auto id = monitorId(x); + if (id < 0) + return false; + + auto monitor = static_cast( + freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x)); + + originX = std::min(monitor->x, originX); + originY = std::min(monitor->y, originY); + } + + for (UINT32 x = 0; x < windowCount; x++) + { + auto id = monitorId(x); + if (id < 0) + return false; + + auto monitor = static_cast( + freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x)); + + auto w = WINPR_ASSERTING_INT_CAST(Uint32, monitor->width); + auto h = WINPR_ASSERTING_INT_CAST(Uint32, monitor->height); + if (!(freerdp_settings_get_bool(settings, FreeRDP_UseMultimon) || + freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))) + { + w = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth); + h = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight); + } + + Uint32 flags = SDL_WINDOW_HIGH_PIXEL_DENSITY; + + if (freerdp_settings_get_bool(settings, FreeRDP_Fullscreen) && + !freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) + { + flags |= SDL_WINDOW_FULLSCREEN; + } + + if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) + { + flags |= SDL_WINDOW_BORDERLESS; + } + + if (!freerdp_settings_get_bool(settings, FreeRDP_Decorations)) + flags |= SDL_WINDOW_BORDERLESS; + + std::stringstream ss; + ss << title << ":" << x; + + auto did = WINPR_ASSERTING_INT_CAST(SDL_DisplayID, id); + auto window = SdlWindow::create(did, title, flags, w, h); + if (!window.window()) + return false; + + if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) + { + window.setOffsetX(originX - monitor->x); + window.setOffsetY(originY - monitor->y); + } + + _windows.insert({ window.id(), std::move(window) }); + } + + return true; +} + +bool SdlContext::updateWindowList() +{ + std::vector list; + list.reserve(_windows.size()); + for (const auto& win : _windows) + list.push_back(win.second.monitor(_windows.size() == 1)); + + return freerdp_settings_set_monitor_def_array_sorted(context()->settings, list.data(), + list.size()); +} + +std::string SdlContext::windowTitle() const +{ + const char* prefix = "FreeRDP:"; + + const auto windowTitle = freerdp_settings_get_string(context()->settings, FreeRDP_WindowTitle); + if (windowTitle) + return windowTitle; + + const auto name = freerdp_settings_get_server_name(context()->settings); + const auto port = freerdp_settings_get_uint32(context()->settings, FreeRDP_ServerPort); + const auto addPort = (port != 3389); + + std::stringstream ss; + ss << prefix << " " << name; + + if (addPort) + ss << ":" << port; + + return ss.str(); +} + +bool SdlContext::waitForWindowsCreated() +{ + { + std::unique_lock lock(_critical); + _windowsCreatedEvent.clear(); + if (!sdl_push_user_event(SDL_EVENT_USER_CREATE_WINDOWS, this)) + return false; + } + + HANDLE handles[] = { _windowsCreatedEvent.handle(), freerdp_abort_event(context()) }; + + const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, INFINITE); + switch (rc) + { + case WAIT_OBJECT_0: + return true; + default: + return false; + } +} + +/* This function is called when the library completed composing a new + * frame. Read out the changed areas and blit them to your output device. + * The image buffer will have the format specified by gdi_init + */ +BOOL SdlContext::endPaint(rdpContext* context) +{ + auto sdl = get_context(context); + WINPR_ASSERT(sdl); + + auto gdi = context->gdi; + WINPR_ASSERT(gdi); + WINPR_ASSERT(gdi->primary); + + HGDI_DC hdc = gdi->primary->hdc; + WINPR_ASSERT(hdc); + if (!hdc->hwnd) + return TRUE; + + HGDI_WND hwnd = hdc->hwnd; + WINPR_ASSERT(hwnd->invalid || (hwnd->ninvalid == 0)); + + if (hwnd->invalid->null) + return TRUE; + + WINPR_ASSERT(hwnd->invalid); + if (gdi->suppressOutput || hwnd->invalid->null) + return TRUE; + + const INT32 ninvalid = hwnd->ninvalid; + const GDI_RGN* cinvalid = hwnd->cinvalid; + + if (ninvalid < 1) + return TRUE; + + std::vector rects; + for (INT32 x = 0; x < ninvalid; x++) + { + auto& rgn = cinvalid[x]; + rects.push_back({ rgn.x, rgn.y, rgn.w, rgn.h }); + } + + sdl->push(std::move(rects)); + return sdl_push_user_event(SDL_EVENT_USER_UPDATE); +} + +void SdlContext::sdl_client_cleanup(int exit_code, const std::string& error_msg) +{ + rdpSettings* settings = context()->settings; + WINPR_ASSERT(settings); + + _rdpThreadRunning = false; + bool showError = false; + if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly)) + WLog_Print(getWLog(), WLOG_INFO, "Authentication only, exit status %s [%" PRId32 "]", + sdl::error::exitCodeToTag(exit_code), exit_code); + else + { + switch (exit_code) + { + case sdl::error::SUCCESS: + case sdl::error::DISCONNECT: + case sdl::error::LOGOFF: + case sdl::error::DISCONNECT_BY_USER: + case sdl::error::CONNECT_CANCELLED: + break; + default: + { + getDialog().showError(error_msg); + } + break; + } + } + + if (!showError) + getDialog().show(false); + + _exitCode = exit_code; + sdl_push_user_event(SDL_EVENT_USER_QUIT); + SDL_CleanupTLS(); +} + +int SdlContext::sdl_client_thread_connect(std::string& error_msg) +{ + auto instance = context()->instance; + WINPR_ASSERT(instance); + + _rdpThreadRunning = true; + BOOL rc = freerdp_connect(instance); + + rdpSettings* settings = context()->settings; + WINPR_ASSERT(settings); + + int exit_code = sdl::error::SUCCESS; + if (!rc) + { + UINT32 error = freerdp_get_last_error(context()); + exit_code = sdl::error::errorToExitCode(error); + } + + if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly)) + { + DWORD code = freerdp_get_last_error(context()); + freerdp_abort_connect_context(context()); + WLog_Print(getWLog(), WLOG_ERROR, "Authentication only, %s [0x%08" PRIx32 "] %s", + freerdp_get_last_error_name(code), code, freerdp_get_last_error_string(code)); + return exit_code; + } + + if (!rc) + { + DWORD code = freerdp_error_info(instance); + if (exit_code == sdl::error::SUCCESS) + { + char* msg = nullptr; + size_t len = 0; + exit_code = error_info_to_error(&code, &msg, &len); + if (msg) + error_msg = msg; + free(msg); + } + + auto last = freerdp_get_last_error(context()); + if (error_msg.empty()) + { + char* msg = nullptr; + size_t len = 0; + winpr_asprintf(&msg, &len, "%s [0x%08" PRIx32 "]\n%s", + freerdp_get_last_error_name(last), last, + freerdp_get_last_error_string(last)); + if (msg) + error_msg = msg; + free(msg); + } + + if (exit_code == sdl::error::SUCCESS) + { + if (last == FREERDP_ERROR_AUTHENTICATION_FAILED) + exit_code = sdl::error::AUTH_FAILURE; + else if (code == ERRINFO_SUCCESS) + exit_code = sdl::error::CONN_FAILED; + } + + getDialog().show(false); + } + + return exit_code; +} + +int SdlContext::sdl_client_thread_run(std::string& error_msg) +{ + auto instance = context()->instance; + WINPR_ASSERT(instance); + + int exit_code = sdl::error::SUCCESS; + while (!freerdp_shall_disconnect_context(context())) + { + HANDLE handles[MAXIMUM_WAIT_OBJECTS] = {}; + /* + * win8 and server 2k12 seem to have some timing issue/race condition + * when a initial sync request is send to sync the keyboard indicators + * sending the sync event twice fixed this problem + */ + if (freerdp_focus_required(instance)) + { + auto ctx = get_context(context()); + WINPR_ASSERT(ctx); + + auto& input = ctx->getInputChannelContext(); + if (!input.keyboard_focus_in()) + break; + if (!input.keyboard_focus_in()) + break; + } + + const DWORD nCount = freerdp_get_event_handles(context(), handles, ARRAYSIZE(handles)); + + if (nCount == 0) + { + WLog_Print(getWLog(), WLOG_ERROR, "freerdp_get_event_handles failed"); + break; + } + + const DWORD status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); + + if (status == WAIT_FAILED) + break; + + if (!freerdp_check_event_handles(context())) + { + if (client_auto_reconnect(instance)) + { + // Retry was successful, discard dialog + getDialog().show(false); + continue; + } + else + { + /* + * Indicate an unsuccessful connection attempt if reconnect + * did not succeed and no other error was specified. + */ + if (freerdp_error_info(instance) == 0) + exit_code = sdl::error::CONN_FAILED; + } + + if (freerdp_get_last_error(context()) == FREERDP_ERROR_SUCCESS) + WLog_Print(getWLog(), WLOG_ERROR, "WaitForMultipleObjects failed with %" PRIu32 "", + status); + if (freerdp_get_last_error(context()) == FREERDP_ERROR_SUCCESS) + WLog_Print(getWLog(), WLOG_ERROR, "Failed to check FreeRDP event handles"); + break; + } + } + + if (exit_code == sdl::error::SUCCESS) + { + DWORD code = 0; + { + char* emsg = nullptr; + size_t elen = 0; + exit_code = error_info_to_error(&code, &emsg, &elen); + if (emsg) + error_msg = emsg; + free(emsg); + } + + if ((code == ERRINFO_LOGOFF_BY_USER) && + (freerdp_get_disconnect_ultimatum(context()) == Disconnect_Ultimatum_user_requested)) + { + const char* msg = "Error info says user did not initiate but disconnect ultimatum says " + "they did; treat this as a user logoff"; + + char* emsg = nullptr; + size_t elen = 0; + winpr_asprintf(&emsg, &elen, "%s", msg); + if (emsg) + error_msg = emsg; + free(emsg); + + /* This situation might be limited to Windows XP. */ + WLog_Print(getWLog(), WLOG_INFO, "%s", msg); + exit_code = sdl::error::LOGOFF; + } + } + + freerdp_disconnect(instance); + + return exit_code; +} + +/* RDP main loop. + * Connects RDP, loops while running and handles event and dispatch, cleans up + * after the connection ends. */ +DWORD SdlContext::rdpThreadRun(SdlContext* sdl) +{ + WINPR_ASSERT(sdl); + + std::string error_msg; + int exit_code = sdl->sdl_client_thread_connect(error_msg); + if (exit_code == sdl::error::SUCCESS) + exit_code = sdl->sdl_client_thread_run(error_msg); + sdl->sdl_client_cleanup(exit_code, error_msg); + + return static_cast(exit_code); +} + +int SdlContext::error_info_to_error(DWORD* pcode, char** msg, size_t* len) const +{ + const DWORD code = freerdp_error_info(context()->instance); + const char* name = freerdp_get_error_info_name(code); + const char* str = freerdp_get_error_info_string(code); + const int exit_code = sdl::error::errorToExitCode(code); + + winpr_asprintf(msg, len, "Terminate with %s due to ERROR_INFO %s [0x%08" PRIx32 "]: %s", + sdl::error::errorToExitCodeTag(code), name, code, str); + SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%s", *msg); + if (pcode) + *pcode = code; + return exit_code; +} + +bool SdlContext::drawToWindow(SdlWindow& window, const std::vector& rects) +{ + if (!isConnected()) + return true; + + auto gdi = context()->gdi; + WINPR_ASSERT(gdi); + + auto size = window.rect(); + + std::unique_lock lock(_critical); + auto surface = _primary.get(); + if (freerdp_settings_get_bool(context()->settings, FreeRDP_SmartSizing)) + { + window.setOffsetX(0); + window.setOffsetY(0); + if (gdi->width < size.w) + { + window.setOffsetX((size.w - gdi->width) / 2); + } + if (gdi->height < size.h) + { + window.setOffsetY((size.h - gdi->height) / 2); + } + if (!window.drawScaledRects(surface, rects)) + return false; + } + else + { + if (!window.drawRects(surface, { window.offsetX(), window.offsetY() }, rects)) + return false; + } + + window.updateSurface(); + return true; +} + +bool SdlContext::minimizeAllWindows() +{ + for (auto& w : _windows) + w.second.minimize(); + return true; +} + +int SdlContext::exitCode() const +{ + return _exitCode; +} + +SDL_PixelFormat SdlContext::pixelFormat() const +{ + return _sdlPixelFormat; +} + +SdlWindow* SdlContext::getWindowForId(SDL_WindowID id) +{ + auto it = _windows.find(id); + if (it == _windows.end()) + return nullptr; + return &it->second; +} + +SdlWindow* SdlContext::getFirstWindow() +{ + if (_windows.empty()) + return nullptr; + return &_windows.begin()->second; +} + +sdlDispContext& SdlContext::getDisplayChannelContext() +{ + return _disp; +} + +sdlInput& SdlContext::getInputChannelContext() +{ + return _input; +} + +sdlClip& SdlContext::getClipboardChannelContext() +{ + return _clip; +} + +SdlConnectionDialogWrapper& SdlContext::getDialog() +{ + return _dialog; +} + +wLog* SdlContext::getWLog() +{ + return _log; +} + +bool SdlContext::drawToWindows(const std::vector& rects) +{ + for (auto& window : _windows) + { + if (!drawToWindow(window.second, rects)) + return FALSE; + } + + return TRUE; +} + +BOOL SdlContext::desktopResize(rdpContext* context) +{ + rdpGdi* gdi = nullptr; + rdpSettings* settings = nullptr; + auto sdl = get_context(context); + + WINPR_ASSERT(sdl); + WINPR_ASSERT(context); + + settings = context->settings; + WINPR_ASSERT(settings); + + std::unique_lock lock(sdl->_critical); + gdi = context->gdi; + if (!gdi_resize(gdi, freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth), + freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight))) + return FALSE; + return sdl->createPrimary(); +} + +/* This function is called to output a System BEEP */ +BOOL SdlContext::playSound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound) +{ + /* TODO: Implement */ + WINPR_UNUSED(context); + WINPR_UNUSED(play_sound); + return TRUE; +} + +/* This function is called whenever a new frame starts. + * It can be used to reset invalidated areas. */ +BOOL SdlContext::beginPaint(rdpContext* context) +{ + auto gdi = context->gdi; + WINPR_ASSERT(gdi); + WINPR_ASSERT(gdi->primary); + + HGDI_DC hdc = gdi->primary->hdc; + WINPR_ASSERT(hdc); + if (!hdc->hwnd) + return TRUE; + + HGDI_WND hwnd = hdc->hwnd; + WINPR_ASSERT(hwnd->invalid); + hwnd->invalid->null = TRUE; + hwnd->ninvalid = 0; + + return TRUE; +} + +bool SdlContext::redraw(bool suppress) const +{ + if (!_connected) + return true; + + auto gdi = context()->gdi; + WINPR_ASSERT(gdi); + return gdi_send_suppress_output(gdi, suppress); +} + +void SdlContext::setConnected(bool val) +{ + _connected = val; +} + +bool SdlContext::isConnected() const +{ + return _connected; +} + +rdpContext* SdlContext::context() const +{ + WINPR_ASSERT(_context); + return _context; +} + +rdpClientContext* SdlContext::common() const +{ + return reinterpret_cast(context()); +} + +void SdlContext::setCursor(rdpPointer* cursor) +{ + _cursor = cursor; +} + +rdpPointer* SdlContext::cursor() const +{ + return _cursor; +} + +void SdlContext::setMonitorIds(const std::vector& ids) +{ + _monitorIds.clear(); + for (auto id : ids) + { + _monitorIds.push_back(id); + } +} + +const std::vector& SdlContext::monitorIds() const +{ + return _monitorIds; +} + +int64_t SdlContext::monitorId(uint32_t index) const +{ + if (index >= _monitorIds.size()) + { + return -1; + } + return _monitorIds[index]; +} + +void SdlContext::push(std::vector&& rects) +{ + std::unique_lock lock(_queue_mux); + _queue.emplace(std::move(rects)); +} + +std::vector SdlContext::pop() +{ + std::unique_lock lock(_queue_mux); + if (_queue.empty()) + { + return {}; + } + auto val = std::move(_queue.front()); + _queue.pop(); + return val; +} + +bool SdlContext::setFullscreen(bool enter) +{ + for (const auto& window : _windows) + { + if (!sdl_push_user_event(SDL_EVENT_USER_WINDOW_FULLSCREEN, &window.second, enter)) + return false; + } + _fullscreen = enter; + return true; +} + +bool SdlContext::setMinimized() +{ + return sdl_push_user_event(SDL_EVENT_USER_WINDOW_MINIMIZE); +} + +bool SdlContext::grabMouse() const +{ + return _grabMouse; +} + +bool SdlContext::toggleGrabMouse() +{ + return setGrabMouse(!grabMouse()); +} + +bool SdlContext::setGrabMouse(bool enter) +{ + _grabMouse = enter; + return true; +} + +bool SdlContext::grabKeyboard() const +{ + return _grabKeyboard; +} + +bool SdlContext::toggleGrabKeyboard() +{ + return setGrabKeyboard(!grabKeyboard()); +} + +bool SdlContext::setGrabKeyboard(bool enter) +{ + _grabKeyboard = enter; + return true; +} + +bool SdlContext::setResizeable(bool enable) +{ + const auto settings = context()->settings; + const bool dyn = freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate); + const bool smart = freerdp_settings_get_bool(settings, FreeRDP_SmartSizing); + bool use = (dyn && enable) || smart; + + for (const auto& window : _windows) + { + if (!sdl_push_user_event(SDL_EVENT_USER_WINDOW_RESIZEABLE, &window.second, use)) + return false; + } + _resizeable = use; + + return true; +} + +bool SdlContext::resizeable() const +{ + return _resizeable; +} + +bool SdlContext::toggleResizeable() +{ + return setResizeable(!resizeable()); +} + +bool SdlContext::fullscreen() const +{ + return _fullscreen; +} + +bool SdlContext::toggleFullscreen() +{ + return setFullscreen(!fullscreen()); +} diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp new file mode 100644 index 000000000..3dd981fe8 --- /dev/null +++ b/client/SDL/SDL3/sdl_context.hpp @@ -0,0 +1,175 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * SDL Client + * + * Copyright 2022 Armin Novak + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include "sdl_window.hpp" +#include "sdl_disp.hpp" +#include "sdl_clip.hpp" +#include "sdl_kbd.hpp" + +#include "dialogs/sdl_connection_dialog_wrapper.hpp" + +class SdlContext +{ + public: + explicit SdlContext(rdpContext* context); + SdlContext(const SdlContext& other) = delete; + SdlContext(SdlContext&& other) = delete; + virtual ~SdlContext(); + + SdlContext& operator=(const SdlContext& other) = delete; + SdlContext& operator=(SdlContext&& other) = delete; + + [[nodiscard]] bool redraw(bool suppress = false) const; + + void setConnected(bool val); + [[nodiscard]] bool isConnected() const; + void cleanup(); + + [[nodiscard]] bool resizeable() const; + [[nodiscard]] bool toggleResizeable(); + [[nodiscard]] bool setResizeable(bool enable); + + [[nodiscard]] bool fullscreen() const; + [[nodiscard]] bool toggleFullscreen(); + [[nodiscard]] bool setFullscreen(bool enter); + + [[nodiscard]] bool setMinimized(); + + [[nodiscard]] bool grabMouse() const; + [[nodiscard]] bool toggleGrabMouse(); + [[nodiscard]] bool setGrabMouse(bool enter); + + [[nodiscard]] bool grabKeyboard() const; + [[nodiscard]] bool toggleGrabKeyboard(); + [[nodiscard]] bool setGrabKeyboard(bool enter); + + [[nodiscard]] rdpContext* context() const; + [[nodiscard]] rdpClientContext* common() const; + + void setCursor(rdpPointer* cursor); + [[nodiscard]] rdpPointer* cursor() const; + + void setMonitorIds(const std::vector& ids); + const std::vector& monitorIds() const; + int64_t monitorId(uint32_t index) const; + + void push(std::vector&& rects); + std::vector pop(); + + void setHasCursor(bool val); + [[nodiscard]] bool hasCursor() const; + + void setMetadata(); + + [[nodiscard]] int start(); + [[nodiscard]] int join(); + [[nodiscard]] bool shallAbort(bool ignoreDialogs = false); + + [[nodiscard]] bool createWindows(); + [[nodiscard]] bool updateWindowList(); + + [[nodiscard]] bool drawToWindows(const std::vector& rects = {}); + [[nodiscard]] bool drawToWindow(SdlWindow& window, const std::vector& rects = {}); + [[nodiscard]] bool minimizeAllWindows(); + [[nodiscard]] int exitCode() const; + [[nodiscard]] SDL_PixelFormat pixelFormat() const; + + [[nodiscard]] SdlWindow* getWindowForId(SDL_WindowID id); + [[nodiscard]] SdlWindow* getFirstWindow(); + + [[nodiscard]] sdlDispContext& getDisplayChannelContext(); + [[nodiscard]] sdlInput& getInputChannelContext(); + [[nodiscard]] sdlClip& getClipboardChannelContext(); + + [[nodiscard]] SdlConnectionDialogWrapper& getDialog(); + + [[nodiscard]] wLog* getWLog(); + + private: + [[nodiscard]] static BOOL preConnect(freerdp* instance); + [[nodiscard]] static BOOL postConnect(freerdp* instance); + static void postDisconnect(freerdp* instance); + static void postFinalDisconnect(freerdp* instance); + [[nodiscard]] static BOOL desktopResize(rdpContext* context); + [[nodiscard]] static BOOL playSound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound); + [[nodiscard]] static BOOL beginPaint(rdpContext* context); + [[nodiscard]] static BOOL endPaint(rdpContext* context); + [[nodiscard]] static DWORD WINAPI rdpThreadRun(SdlContext* sdl); + + [[nodiscard]] bool createPrimary(); + [[nodiscard]] std::string windowTitle() const; + [[nodiscard]] bool waitForWindowsCreated(); + + void sdl_client_cleanup(int exit_code, const std::string& error_msg); + [[nodiscard]] int sdl_client_thread_connect(std::string& error_msg); + [[nodiscard]] int sdl_client_thread_run(std::string& error_msg); + + [[nodiscard]] int error_info_to_error(DWORD* pcode, char** msg, size_t* len) const; + + rdpContext* _context = nullptr; + wLog* _log = nullptr; + + std::atomic _connected = false; + bool _cursor_visible = true; + rdpPointer* _cursor = nullptr; + std::vector _monitorIds{}; + std::mutex _queue_mux{}; + std::queue> _queue{}; + /* SDL */ + bool _fullscreen = false; + bool _resizeable = false; + bool _grabMouse = false; + bool _grabKeyboard = false; + int _exitCode = -1; + std::atomic _rdpThreadRunning = false; + SDL_PixelFormat _sdlPixelFormat = SDL_PIXELFORMAT_UNKNOWN; + + CriticalSection _critical{}; + + using SDLSurfacePtr = std::unique_ptr; + + SDLSurfacePtr _primary; + + sdlDispContext _disp; + sdlInput _input; + sdlClip _clip; + + SdlConnectionDialogWrapper _dialog; + + std::map _windows{}; + + WinPREvent _windowsCreatedEvent{}; + std::thread _thread{}; +}; diff --git a/client/SDL/SDL3/sdl_disp.cpp b/client/SDL/SDL3/sdl_disp.cpp index fe4619e28..9e0dc34b6 100644 --- a/client/SDL/SDL3/sdl_disp.cpp +++ b/client/SDL/SDL3/sdl_disp.cpp @@ -28,7 +28,7 @@ #include "sdl_disp.hpp" #include "sdl_kbd.hpp" #include "sdl_utils.hpp" -#include "sdl_freerdp.hpp" +#include "sdl_context.hpp" #include #define TAG CLIENT_TAG("sdl.disp") @@ -90,7 +90,7 @@ bool sdlDispContext::sendResize() bool sdlDispContext::set_window_resizable() { - return _sdl->update_resizeable(true); + return _sdl->setResizeable(true); } static bool sdl_disp_check_context(void* context, SdlContext** ppsdl, sdlDispContext** ppsdlDisp, @@ -107,7 +107,7 @@ static bool sdl_disp_check_context(void* context, SdlContext** ppsdl, sdlDispCon return false; *ppsdl = sdl; - *ppsdlDisp = &sdl->disp; + *ppsdlDisp = &sdl->getDisplayChannelContext(); *ppSettings = sdl->context()->settings; return true; } @@ -169,21 +169,21 @@ Uint32 sdlDispContext::OnTimer(void* param, [[maybe_unused]] SDL_TimerID timerID if (!sdl_disp_check_context(sdl->context(), &sdl, &sdlDisp, &settings)) return 0; - WLog_Print(sdl->log, WLOG_TRACE, "checking for display changes..."); + WLog_Print(sdl->getWLog(), WLOG_TRACE, "checking for display changes..."); if (!sdlDisp->_activated || freerdp_settings_get_bool(settings, FreeRDP_Fullscreen)) return 0; auto rc = sdlDisp->sendResize(); if (!rc) - WLog_Print(sdl->log, WLOG_TRACE, "sent new display layout, result %d", rc); + WLog_Print(sdl->getWLog(), WLOG_TRACE, "sent new display layout, result %d", rc); if (sdlDisp->_timer_retries++ >= MAX_RETRIES) { - WLog_Print(sdl->log, WLOG_TRACE, "deactivate timer, retries exceeded"); + WLog_Print(sdl->getWLog(), WLOG_TRACE, "deactivate timer, retries exceeded"); return 0; } - WLog_Print(sdl->log, WLOG_TRACE, "fire timer one more time"); + WLog_Print(sdl->getWLog(), WLOG_TRACE, "fire timer one more time"); return interval; } @@ -276,7 +276,7 @@ bool sdlDispContext::addTimer() return false; SDL_RemoveTimer(_timer); - WLog_Print(_sdl->log, WLOG_TRACE, "adding new display check timer"); + WLog_Print(_sdl->getWLog(), WLOG_TRACE, "adding new display check timer"); _timer_retries = 0; sendResize(); @@ -293,10 +293,11 @@ bool sdlDispContext::updateMonitor(SDL_WindowID id) if (!freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_DynamicResolutionUpdate)) return true; - const auto& window = _sdl->windows.at(id); - auto monitor = window.monitor(true); + const auto window = _sdl->getWindowForId(id); + if (!window) + return false; - monitor.is_primary = TRUE; + const auto& monitor = window->monitor(true); if (!freerdp_settings_set_monitor_def_array_sorted(settings, &monitor, 1)) return false; @@ -324,14 +325,7 @@ bool sdlDispContext::updateMonitors(SDL_EventType type) if (!freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate)) return true; - std::vector monitors; - monitors.reserve(_sdl->windows.size()); - for (auto& smon : _sdl->windows) - { - monitors.emplace_back(smon.second.monitor(false)); - } - - if (!freerdp_settings_set_monitor_def_array_sorted(settings, monitors.data(), monitors.size())) + if (!_sdl->updateWindowList()) return false; return addTimer(); } @@ -374,9 +368,9 @@ bool sdlDispContext::handle_window_event(const SDL_WindowEvent* ev) auto bordered = freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_Decorations); - auto it = _sdl->windows.find(ev->windowID); - if (it != _sdl->windows.end()) - it->second.setBordered(bordered); + auto window = _sdl->getWindowForId(ev->windowID); + if (window) + window->setBordered(bordered); switch (ev->type) { @@ -403,14 +397,14 @@ bool sdlDispContext::handle_window_event(const SDL_WindowEvent* ev) return updateMonitor(ev->windowID); case SDL_EVENT_WINDOW_MOUSE_LEAVE: WINPR_ASSERT(_sdl); - _sdl->input.keyboard_grab(ev->windowID, false); - return true; + return _sdl->getInputChannelContext().keyboard_grab(ev->windowID, false); case SDL_EVENT_WINDOW_MOUSE_ENTER: WINPR_ASSERT(_sdl); - _sdl->input.keyboard_grab(ev->windowID, true); - return _sdl->input.keyboard_focus_in(); + if (!_sdl->getInputChannelContext().keyboard_grab(ev->windowID, true)) + return false; + return _sdl->getInputChannelContext().keyboard_focus_in(); case SDL_EVENT_WINDOW_FOCUS_GAINED: - return _sdl->input.keyboard_focus_in(); + return _sdl->getInputChannelContext().keyboard_focus_in(); default: return true; @@ -465,7 +459,7 @@ bool sdlDispContext::init(DispClientContext* disp) disp->DisplayControlCaps = sdlDispContext::DisplayControlCaps; } - return _sdl->update_resizeable(true); + return _sdl->setResizeable(true); } bool sdlDispContext::uninit(DispClientContext* disp) @@ -474,7 +468,7 @@ bool sdlDispContext::uninit(DispClientContext* disp) return false; _disp = nullptr; - return _sdl->update_resizeable(false); + return _sdl->setResizeable(false); } sdlDispContext::sdlDispContext(SdlContext* sdl) : _sdl(sdl) diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index e1f8a4040..9390db6f6 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -61,6 +61,7 @@ #include "sdl_channels.hpp" #include "sdl_disp.hpp" #include "sdl_freerdp.hpp" +#include "sdl_context.hpp" #include "sdl_kbd.hpp" #include "sdl_monitor.hpp" #include "sdl_pointer.hpp" @@ -68,309 +69,9 @@ #include "sdl_touch.hpp" #include "sdl_utils.hpp" -#if defined(WITH_WEBVIEW) -#include -#endif - +#if defined(_WIN32) #define SDL_TAG CLIENT_TAG("SDL") - -static int error_info_to_error(freerdp* instance, DWORD* pcode, char** msg, size_t* len) -{ - const DWORD code = freerdp_error_info(instance); - const char* name = freerdp_get_error_info_name(code); - const char* str = freerdp_get_error_info_string(code); - const int exit_code = sdl::error::errorToExitCode(code); - - winpr_asprintf(msg, len, "Terminate with %s due to ERROR_INFO %s [0x%08" PRIx32 "]: %s", - sdl::error::errorToExitCodeTag(code), name, code, str); - SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%s", *msg); - if (pcode) - *pcode = code; - return exit_code; -} - -/* This function is called whenever a new frame starts. - * It can be used to reset invalidated areas. */ -static BOOL sdl_begin_paint(rdpContext* context) -{ - auto gdi = context->gdi; - WINPR_ASSERT(gdi); - WINPR_ASSERT(gdi->primary); - - HGDI_DC hdc = gdi->primary->hdc; - WINPR_ASSERT(hdc); - if (!hdc->hwnd) - return TRUE; - - HGDI_WND hwnd = hdc->hwnd; - WINPR_ASSERT(hwnd->invalid); - hwnd->invalid->null = TRUE; - hwnd->ninvalid = 0; - - return TRUE; -} - -static BOOL sdl_draw_to_window(SdlContext* sdl, SdlWindow& window, - const std::vector& rects = {}) -{ - WINPR_ASSERT(sdl); - - if (!sdl->isConnected()) - return TRUE; - - auto context = sdl->context(); - auto gdi = context->gdi; - WINPR_ASSERT(gdi); - - auto size = window.rect(); - - std::unique_lock lock(sdl->critical); - auto surface = sdl->primary.get(); - if (freerdp_settings_get_bool(context->settings, FreeRDP_SmartSizing)) - { - window.setOffsetX(0); - window.setOffsetY(0); - if (gdi->width < size.w) - { - window.setOffsetX((size.w - gdi->width) / 2); - } - if (gdi->height < size.h) - { - window.setOffsetY((size.h - gdi->height) / 2); - } - if (!window.drawScaledRects(surface, rects)) - return FALSE; - } - else - { - if (!window.drawRects(surface, { window.offsetX(), window.offsetY() }, rects)) - return FALSE; - } - - window.updateSurface(); - return TRUE; -} - -static BOOL sdl_draw_to_window(SdlContext* sdl, std::map& windows, - const std::vector& rects = {}) -{ - for (auto& window : windows) - { - if (!sdl_draw_to_window(sdl, window.second, rects)) - return FALSE; - } - - return TRUE; -} - -/* This function is called when the library completed composing a new - * frame. Read out the changed areas and blit them to your output device. - * The image buffer will have the format specified by gdi_init - */ -static BOOL sdl_end_paint(rdpContext* context) -{ - auto sdl = get_context(context); - WINPR_ASSERT(sdl); - - auto gdi = context->gdi; - WINPR_ASSERT(gdi); - WINPR_ASSERT(gdi->primary); - - HGDI_DC hdc = gdi->primary->hdc; - WINPR_ASSERT(hdc); - if (!hdc->hwnd) - return TRUE; - - HGDI_WND hwnd = hdc->hwnd; - WINPR_ASSERT(hwnd->invalid || (hwnd->ninvalid == 0)); - - if (hwnd->invalid->null) - return TRUE; - - WINPR_ASSERT(hwnd->invalid); - if (gdi->suppressOutput || hwnd->invalid->null) - return TRUE; - - const INT32 ninvalid = hwnd->ninvalid; - const GDI_RGN* cinvalid = hwnd->cinvalid; - - if (ninvalid < 1) - return TRUE; - - std::vector rects; - for (INT32 x = 0; x < ninvalid; x++) - { - auto& rgn = cinvalid[x]; - rects.push_back({ rgn.x, rgn.y, rgn.w, rgn.h }); - } - - sdl->push(std::move(rects)); - return sdl_push_user_event(SDL_EVENT_USER_UPDATE); -} - -static void sdl_destroy_primary(SdlContext* sdl) -{ - if (!sdl) - return; - sdl->primary.reset(); -} - -/* Create a SDL surface from the GDI buffer */ -static BOOL sdl_create_primary(SdlContext* sdl) -{ - rdpGdi* gdi = nullptr; - - WINPR_ASSERT(sdl); - - gdi = sdl->context()->gdi; - WINPR_ASSERT(gdi); - - sdl_destroy_primary(sdl); - sdl->primary = - SDLSurfacePtr(SDL_CreateSurfaceFrom(static_cast(gdi->width), - static_cast(gdi->height), sdl->sdl_pixel_format, - gdi->primary_buffer, static_cast(gdi->stride)), - SDL_DestroySurface); - if (!sdl->primary) - return FALSE; - - SDL_SetSurfaceBlendMode(sdl->primary.get(), SDL_BLENDMODE_NONE); - SDL_Rect surfaceRect = { 0, 0, gdi->width, gdi->height }; - SDL_FillSurfaceRect(sdl->primary.get(), &surfaceRect, - SDL_MapSurfaceRGBA(sdl->primary.get(), 0, 0, 0, 0xff)); - - return TRUE; -} - -static BOOL sdl_desktop_resize(rdpContext* context) -{ - rdpGdi* gdi = nullptr; - rdpSettings* settings = nullptr; - auto sdl = get_context(context); - - WINPR_ASSERT(sdl); - WINPR_ASSERT(context); - - settings = context->settings; - WINPR_ASSERT(settings); - - std::unique_lock lock(sdl->critical); - gdi = context->gdi; - if (!gdi_resize(gdi, freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth), - freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight))) - return FALSE; - return sdl_create_primary(sdl); -} - -/* This function is called to output a System BEEP */ -static BOOL sdl_play_sound(rdpContext* context, const PLAY_SOUND_UPDATE* play_sound) -{ - /* TODO: Implement */ - WINPR_UNUSED(context); - WINPR_UNUSED(play_sound); - return TRUE; -} - -/* Called before a connection is established. - * Set all configuration options to support and load channels here. */ -static BOOL sdl_pre_connect(freerdp* instance) -{ - WINPR_ASSERT(instance); - WINPR_ASSERT(instance->context); - - auto sdl = get_context(instance->context); - - auto settings = instance->context->settings; - WINPR_ASSERT(settings); - - if (!freerdp_settings_set_bool(settings, FreeRDP_CertificateCallbackPreferPEM, TRUE)) - return FALSE; - - /* Optional OS identifier sent to server */ - if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMajorType, OSMAJORTYPE_UNIX)) - return FALSE; - if (!freerdp_settings_set_uint32(settings, FreeRDP_OsMinorType, OSMINORTYPE_NATIVE_SDL)) - return FALSE; - /* OrderSupport is initialized at this point. - * Only override it if you plan to implement custom order - * callbacks or deactivate certain features. */ - /* Register the channel listeners. - * They are required to set up / tear down channels if they are loaded. */ - PubSub_SubscribeChannelConnected(instance->context->pubSub, sdl_OnChannelConnectedEventHandler); - PubSub_SubscribeChannelDisconnected(instance->context->pubSub, - sdl_OnChannelDisconnectedEventHandler); - - if (!freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly)) - { - UINT32 maxWidth = 0; - UINT32 maxHeight = 0; - - if (!sdl_detect_monitors(sdl, &maxWidth, &maxHeight)) - return FALSE; - - if ((maxWidth != 0) && (maxHeight != 0) && - !freerdp_settings_get_bool(settings, FreeRDP_SmartSizing)) - { - WLog_Print(sdl->log, WLOG_INFO, "Update size to %ux%u", maxWidth, maxHeight); - if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, maxWidth)) - return FALSE; - if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, maxHeight)) - return FALSE; - } - } - else - { - /* Check +auth-only has a username and password. */ - if (!freerdp_settings_get_string(settings, FreeRDP_Password)) - { - WLog_Print(sdl->log, WLOG_INFO, "auth-only, but no password set. Please provide one."); - return FALSE; - } - - if (!freerdp_settings_set_bool(settings, FreeRDP_DeactivateClientDecoding, TRUE)) - return FALSE; - - WLog_Print(sdl->log, WLOG_INFO, "Authentication only. Don't connect SDL."); - } - - if (!sdl->input.initialize()) - return FALSE; - - /* TODO: Any code your client requires */ - return TRUE; -} - -static const char* sdl_window_get_title(rdpSettings* settings) -{ - const char* windowTitle = nullptr; - UINT32 port = 0; - BOOL addPort = 0; - const char* name = nullptr; - const char* prefix = "FreeRDP:"; - - if (!settings) - return nullptr; - - windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle); - if (windowTitle) - return windowTitle; - - name = freerdp_settings_get_server_name(settings); - port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort); - - addPort = (port != 3389); - - char buffer[MAX_PATH + 64] = {}; - - if (!addPort) - (void)sprintf_s(buffer, sizeof(buffer), "%s %s", prefix, name); - else - (void)sprintf_s(buffer, sizeof(buffer), "%s %s:%" PRIu32, prefix, name, port); - - if (!freerdp_settings_set_string(settings, FreeRDP_WindowTitle, buffer)) - return nullptr; - return freerdp_settings_get_string(settings, FreeRDP_WindowTitle); -} +#endif static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const char* signame, [[maybe_unused]] void* context) @@ -378,118 +79,6 @@ static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const sdl_push_quit(); } -static BOOL sdl_create_windows(SdlContext* sdl) -{ - WINPR_ASSERT(sdl); - - auto settings = sdl->context()->settings; - auto title = sdl_window_get_title(settings); - - ScopeGuard guard1([&]() { sdl->windows_created.set(); }); - - UINT32 windowCount = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); - - Sint32 originX = 0; - Sint32 originY = 0; - for (UINT32 x = 0; x < windowCount; x++) - { - auto id = sdl->monitorId(x); - if (id < 0) - return FALSE; - - auto monitor = static_cast( - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x)); - - originX = std::min(monitor->x, originX); - originY = std::min(monitor->y, originY); - } - - for (UINT32 x = 0; x < windowCount; x++) - { - auto id = sdl->monitorId(x); - if (id < 0) - return FALSE; - - auto monitor = static_cast( - freerdp_settings_get_pointer_array_writable(settings, FreeRDP_MonitorDefArray, x)); - - auto w = WINPR_ASSERTING_INT_CAST(Uint32, monitor->width); - auto h = WINPR_ASSERTING_INT_CAST(Uint32, monitor->height); - if (!(freerdp_settings_get_bool(settings, FreeRDP_UseMultimon) || - freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))) - { - w = freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth); - h = freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight); - } - - Uint32 flags = SDL_WINDOW_HIGH_PIXEL_DENSITY; - - if (freerdp_settings_get_bool(settings, FreeRDP_Fullscreen) && - !freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) - { - flags |= SDL_WINDOW_FULLSCREEN; - } - - if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) - { - flags |= SDL_WINDOW_BORDERLESS; - } - - if (!freerdp_settings_get_bool(settings, FreeRDP_Decorations)) - flags |= SDL_WINDOW_BORDERLESS; - - char buffer[MAX_PATH + 64] = {}; - (void)sprintf_s(buffer, sizeof(buffer), "%s:%" PRIu32, title, x); - auto window = - SdlWindow::create(id, buffer, flags, static_cast(w), static_cast(h)); - if (!window.window()) - return FALSE; - - if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) - { - window.setOffsetX(originX - monitor->x); - window.setOffsetY(originY - monitor->y); - } - - sdl->windows.insert({ window.id(), std::move(window) }); - } - - return TRUE; -} - -static BOOL sdl_wait_create_windows(SdlContext* sdl) -{ - { - std::unique_lock lock(sdl->critical); - sdl->windows_created.clear(); - if (!sdl_push_user_event(SDL_EVENT_USER_CREATE_WINDOWS, sdl)) - return FALSE; - } - - HANDLE handles[] = { sdl->windows_created.handle(), freerdp_abort_event(sdl->context()) }; - - const DWORD rc = WaitForMultipleObjects(ARRAYSIZE(handles), handles, FALSE, INFINITE); - switch (rc) - { - case WAIT_OBJECT_0: - return TRUE; - default: - return FALSE; - } -} - -static bool shall_abort(SdlContext* sdl) -{ - std::unique_lock lock(sdl->critical); - if (freerdp_shall_disconnect_context(sdl->context())) - { - if (sdl->rdp_thread_running) - return false; - return !sdl->dialog.isRunning(); - } - return false; -} - static int sdl_run(SdlContext* sdl) { int rc = -1; @@ -507,7 +96,7 @@ static int sdl_run(SdlContext* sdl) SDL_EVENT_USER_RETRY_DIALOG); if (prc < 0) { - if (sdl_log_error(prc, sdl->log, "SDL_PeepEvents")) + if (sdl_log_error(prc, sdl->getWLog(), "SDL_PeepEvents")) continue; } @@ -518,12 +107,12 @@ static int sdl_run(SdlContext* sdl) if (sdl->shallAbort(true)) continue; - if (sdl->dialog.handleEvent(windowEvent)) + if (sdl->getDialog().handleEvent(windowEvent)) { continue; } - if (sdl->dialog.handleEvent(windowEvent)) + if (sdl->getDialog().handleEvent(windowEvent)) { continue; } @@ -549,7 +138,7 @@ static int sdl_run(SdlContext* sdl) case SDL_EVENT_KEY_UP: { const SDL_KeyboardEvent* ev = &windowEvent.key; - sdl->input.keyboard_handle_event(ev); + sdl->getInputChannelContext().keyboard_handle_event(ev); } break; case SDL_EVENT_KEYMAP_CHANGED: @@ -643,14 +232,14 @@ static int sdl_run(SdlContext* sdl) do { rectangles = sdl->pop(); - sdl_draw_to_window(sdl, sdl->windows, rectangles); + sdl->drawToWindows(rectangles); } while (!rectangles.empty()); } break; case SDL_EVENT_USER_CREATE_WINDOWS: { auto ctx = static_cast(windowEvent.user.data1); - sdl_create_windows(ctx); + ctx->createWindows(); } break; case SDL_EVENT_USER_WINDOW_RESIZEABLE: @@ -670,10 +259,7 @@ static int sdl_run(SdlContext* sdl) } break; case SDL_EVENT_USER_WINDOW_MINIMIZE: - for (auto& window : sdl->windows) - { - window.second.minimize(); - } + sdl->minimizeAllWindows(); break; case SDL_EVENT_USER_POINTER_NULL: SDL_HideCursor(); @@ -714,7 +300,7 @@ static int sdl_run(SdlContext* sdl) sdl_Pointer_Set_Process(sdl); break; case SDL_EVENT_CLIPBOARD_UPDATE: - sdl->clip.handle_update(windowEvent.clipboard); + sdl->getClipboardChannelContext().handle_update(windowEvent.clipboard); break; case SDL_EVENT_USER_QUIT: default: @@ -722,16 +308,16 @@ static int sdl_run(SdlContext* sdl) (windowEvent.type <= SDL_EVENT_DISPLAY_LAST)) { const SDL_DisplayEvent* ev = &windowEvent.display; - (void)sdl->disp.handle_display_event(ev); + (void)sdl->getDisplayChannelContext().handle_display_event(ev); } else if ((windowEvent.type >= SDL_EVENT_WINDOW_FIRST) && (windowEvent.type <= SDL_EVENT_WINDOW_LAST)) { const SDL_WindowEvent* ev = &windowEvent.window; - auto window = sdl->windows.find(ev->windowID); - if (window != sdl->windows.end()) + auto window = sdl->getWindowForId(ev->windowID); + if (window) { - (void)sdl->disp.handle_window_event(ev); + (void)sdl->getDisplayChannelContext().handle_window_event(ev); switch (ev->type) { @@ -745,7 +331,7 @@ static int sdl_run(SdlContext* sdl) { break; } - auto win = window->second.window(); + auto win = window->window(); int w_pix{}; int h_pix{}; [[maybe_unused]] auto rcpix = @@ -787,14 +373,14 @@ static int sdl_run(SdlContext* sdl) } break; case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: - window->second.fill(); - sdl_draw_to_window(sdl, window->second); + window->fill(); + sdl->drawToWindow(*window); sdl_Pointer_Set_Process(sdl); break; case SDL_EVENT_WINDOW_MOVED: { - auto r = window->second.rect(); - auto id = window->second.id(); + auto r = window->rect(); + auto id = window->id(); SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%u: %dx%d-%dx%d", id, r.x, r.y, r.w, r.h); } @@ -821,332 +407,6 @@ static int sdl_run(SdlContext* sdl) return rc; } -/* Called after a RDP connection was successfully established. - * Settings might have changed during negotiation of client / server feature - * support. - * - * Set up local framebuffers and paing callbacks. - * If required, register pointer callbacks to change the local mouse cursor - * when hovering over the RDP window - */ -static BOOL sdl_post_connect(freerdp* instance) -{ - WINPR_ASSERT(instance); - - auto context = instance->context; - WINPR_ASSERT(context); - - auto sdl = get_context(context); - - // Retry was successful, discard dialog - sdl->dialog.show(false); - - if (freerdp_settings_get_bool(context->settings, FreeRDP_AuthenticationOnly)) - { - /* Check +auth-only has a username and password. */ - if (!freerdp_settings_get_string(context->settings, FreeRDP_Password)) - { - WLog_Print(sdl->log, WLOG_INFO, "auth-only, but no password set. Please provide one."); - return FALSE; - } - - WLog_Print(sdl->log, WLOG_INFO, "Authentication only. Don't connect to X."); - return TRUE; - } - - if (!sdl_wait_create_windows(sdl)) - return FALSE; - - sdl->sdl_pixel_format = SDL_PIXELFORMAT_BGRA32; - if (!gdi_init(instance, PIXEL_FORMAT_BGRA32)) - return FALSE; - - if (!sdl_create_primary(sdl)) - return FALSE; - - if (!sdl_register_pointer(instance->context->graphics)) - return FALSE; - - WINPR_ASSERT(context->update); - - context->update->BeginPaint = sdl_begin_paint; - context->update->EndPaint = sdl_end_paint; - context->update->PlaySound = sdl_play_sound; - context->update->DesktopResize = sdl_desktop_resize; - context->update->SetKeyboardIndicators = sdlInput::keyboard_set_indicators; - context->update->SetKeyboardImeStatus = sdlInput::keyboard_set_ime_status; - - if (!sdl->update_resizeable(false)) - return FALSE; - if (!sdl->update_fullscreen(freerdp_settings_get_bool(context->settings, FreeRDP_Fullscreen) || - freerdp_settings_get_bool(context->settings, FreeRDP_UseMultimon))) - return FALSE; - sdl->setConnected(true); - return TRUE; -} - -/* This function is called whether a session ends by failure or success. - * Clean up everything allocated by pre_connect and post_connect. - */ -static void sdl_post_disconnect(freerdp* instance) -{ - if (!instance) - return; - - if (!instance->context) - return; - - auto sdl = get_context(instance->context); - sdl->setConnected(false); - - gdi_free(instance); -} - -static void sdl_post_final_disconnect(freerdp* instance) -{ - if (!instance) - return; - - if (!instance->context) - return; - - PubSub_UnsubscribeChannelConnected(instance->context->pubSub, - sdl_OnChannelConnectedEventHandler); - PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub, - sdl_OnChannelDisconnectedEventHandler); -} - -static void sdl_client_cleanup(SdlContext* sdl, int exit_code, const std::string& error_msg) -{ - WINPR_ASSERT(sdl); - - rdpContext* context = sdl->context(); - WINPR_ASSERT(context); - rdpSettings* settings = context->settings; - WINPR_ASSERT(settings); - - sdl->rdp_thread_running = false; - bool showError = false; - if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly)) - WLog_Print(sdl->log, WLOG_INFO, "Authentication only, exit status %s [%" PRId32 "]", - sdl::error::exitCodeToTag(exit_code), exit_code); - else - { - switch (exit_code) - { - case sdl::error::SUCCESS: - case sdl::error::DISCONNECT: - case sdl::error::LOGOFF: - case sdl::error::DISCONNECT_BY_USER: - case sdl::error::CONNECT_CANCELLED: - break; - default: - { - sdl->dialog.showError(error_msg); - } - break; - } - } - - if (!showError) - sdl->dialog.show(false); - - sdl->exit_code = exit_code; - sdl_push_user_event(SDL_EVENT_USER_QUIT); - SDL_CleanupTLS(); -} - -static int sdl_client_thread_connect(SdlContext* sdl, std::string& error_msg) -{ - WINPR_ASSERT(sdl); - - auto instance = sdl->context()->instance; - WINPR_ASSERT(instance); - - sdl->rdp_thread_running = true; - BOOL rc = freerdp_connect(instance); - - rdpContext* context = sdl->context(); - rdpSettings* settings = context->settings; - WINPR_ASSERT(settings); - - int exit_code = sdl::error::SUCCESS; - if (!rc) - { - UINT32 error = freerdp_get_last_error(context); - exit_code = sdl::error::errorToExitCode(error); - } - - if (freerdp_settings_get_bool(settings, FreeRDP_AuthenticationOnly)) - { - DWORD code = freerdp_get_last_error(context); - freerdp_abort_connect_context(context); - WLog_Print(sdl->log, WLOG_ERROR, "Authentication only, %s [0x%08" PRIx32 "] %s", - freerdp_get_last_error_name(code), code, freerdp_get_last_error_string(code)); - return exit_code; - } - - if (!rc) - { - DWORD code = freerdp_error_info(instance); - if (exit_code == sdl::error::SUCCESS) - { - char* msg = nullptr; - size_t len = 0; - exit_code = error_info_to_error(instance, &code, &msg, &len); - if (msg) - error_msg = msg; - free(msg); - } - - auto last = freerdp_get_last_error(context); - if (error_msg.empty()) - { - char* msg = nullptr; - size_t len = 0; - winpr_asprintf(&msg, &len, "%s [0x%08" PRIx32 "]\n%s", - freerdp_get_last_error_name(last), last, - freerdp_get_last_error_string(last)); - if (msg) - error_msg = msg; - free(msg); - } - - if (exit_code == sdl::error::SUCCESS) - { - if (last == FREERDP_ERROR_AUTHENTICATION_FAILED) - exit_code = sdl::error::AUTH_FAILURE; - else if (code == ERRINFO_SUCCESS) - exit_code = sdl::error::CONN_FAILED; - } - - sdl->dialog.show(false); - } - - return exit_code; -} - -static int sdl_client_thread_run(SdlContext* sdl, std::string& error_msg) -{ - WINPR_ASSERT(sdl); - - auto context = sdl->context(); - WINPR_ASSERT(context); - - auto instance = context->instance; - WINPR_ASSERT(instance); - - int exit_code = sdl::error::SUCCESS; - while (!freerdp_shall_disconnect_context(context)) - { - HANDLE handles[MAXIMUM_WAIT_OBJECTS] = {}; - /* - * win8 and server 2k12 seem to have some timing issue/race condition - * when a initial sync request is send to sync the keyboard indicators - * sending the sync event twice fixed this problem - */ - if (freerdp_focus_required(instance)) - { - auto ctx = get_context(context); - WINPR_ASSERT(ctx); - if (!ctx->input.keyboard_focus_in()) - break; - if (!ctx->input.keyboard_focus_in()) - break; - } - - const DWORD nCount = freerdp_get_event_handles(context, handles, ARRAYSIZE(handles)); - - if (nCount == 0) - { - WLog_Print(sdl->log, WLOG_ERROR, "freerdp_get_event_handles failed"); - break; - } - - const DWORD status = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE); - - if (status == WAIT_FAILED) - break; - - if (!freerdp_check_event_handles(context)) - { - if (client_auto_reconnect(instance)) - { - // Retry was successful, discard dialog - sdl->dialog.show(false); - continue; - } - else - { - /* - * Indicate an unsuccessful connection attempt if reconnect - * did not succeed and no other error was specified. - */ - if (freerdp_error_info(instance) == 0) - exit_code = sdl::error::CONN_FAILED; - } - - if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) - WLog_Print(sdl->log, WLOG_ERROR, "WaitForMultipleObjects failed with %" PRIu32 "", - status); - if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) - WLog_Print(sdl->log, WLOG_ERROR, "Failed to check FreeRDP event handles"); - break; - } - } - - if (exit_code == sdl::error::SUCCESS) - { - DWORD code = 0; - { - char* emsg = nullptr; - size_t elen = 0; - exit_code = error_info_to_error(instance, &code, &emsg, &elen); - if (emsg) - error_msg = emsg; - free(emsg); - } - - if ((code == ERRINFO_LOGOFF_BY_USER) && - (freerdp_get_disconnect_ultimatum(context) == Disconnect_Ultimatum_user_requested)) - { - const char* msg = "Error info says user did not initiate but disconnect ultimatum says " - "they did; treat this as a user logoff"; - - char* emsg = nullptr; - size_t elen = 0; - winpr_asprintf(&emsg, &elen, "%s", msg); - if (emsg) - error_msg = emsg; - free(emsg); - - /* This situation might be limited to Windows XP. */ - WLog_Print(sdl->log, WLOG_INFO, "%s", msg); - exit_code = sdl::error::LOGOFF; - } - } - - freerdp_disconnect(instance); - - return exit_code; -} - -/* RDP main loop. - * Connects RDP, loops while running and handles event and dispatch, cleans up - * after the connection ends. */ -static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) -{ - WINPR_ASSERT(sdl); - - std::string error_msg; - int exit_code = sdl_client_thread_connect(sdl, error_msg); - if (exit_code == sdl::error::SUCCESS) - exit_code = sdl_client_thread_run(sdl, error_msg); - sdl_client_cleanup(sdl, exit_code, error_msg); - - return static_cast(exit_code); -} - /* Optional global initializer. * Here we just register a signal handler to print out stack traces * if available. */ @@ -1182,29 +442,7 @@ static BOOL sdl_client_new(freerdp* instance, rdpContext* context) return FALSE; sdl->sdl = new SdlContext(context); - if (!sdl->sdl) - return FALSE; - - instance->PreConnect = sdl_pre_connect; - instance->PostConnect = sdl_post_connect; - instance->PostDisconnect = sdl_post_disconnect; - instance->PostFinalDisconnect = sdl_post_final_disconnect; - instance->AuthenticateEx = sdl_authenticate_ex; - instance->VerifyCertificateEx = sdl_verify_certificate_ex; - instance->VerifyChangedCertificateEx = sdl_verify_changed_certificate_ex; - instance->LogonErrorInfo = sdl_logon_error_info; - instance->PresentGatewayMessage = sdl_present_gateway_message; - instance->ChooseSmartcard = sdl_choose_smartcard; - instance->RetryDialog = sdl_retry_dialog; - -#ifdef WITH_WEBVIEW - instance->GetAccessToken = sdl_webview_get_access_token; -#else - instance->GetAccessToken = client_cli_get_access_token; -#endif - /* TODO: Client display set up */ - - return TRUE; + return sdl->sdl != nullptr; } static void sdl_client_free([[maybe_unused]] freerdp* instance, rdpContext* context) @@ -1221,24 +459,14 @@ static int sdl_client_start(rdpContext* context) { auto sdl = get_context(context); WINPR_ASSERT(sdl); - - sdl->thread = std::thread(sdl_client_thread_proc, sdl); - return 0; + return sdl->start(); } static int sdl_client_stop(rdpContext* context) { auto sdl = get_context(context); WINPR_ASSERT(sdl); - - /* We do not want to use freerdp_abort_connect_context here. - * It would change the exit code and we do not want that. */ - HANDLE event = freerdp_abort_event(context); - if (!SetEvent(event)) - return -1; - - sdl->thread.join(); - return 0; + return sdl->join(); } static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) @@ -1371,7 +599,7 @@ static void SDLCALL winpr_LogOutputFunction(void* userdata, int category, SDL_Lo WINPR_ASSERT(sdl); const DWORD level = sdlpriority2wlog(priority); - auto log = sdl->log; + auto log = sdl->getWLog(); if (!WLog_IsLevelActive(log, level)) return; @@ -1519,11 +747,11 @@ int main(int argc, char* argv[]) /* Redirect SDL log messages to wLog */ SDL_SetLogOutputFunction(winpr_LogOutputFunction, sdl); - auto level = WLog_GetLogLevel(sdl->log); + auto level = WLog_GetLogLevel(sdl->getWLog()); SDL_SetLogPriorities(wloglevel2dl(level)); auto backend = SDL_GetCurrentVideoDriver(); - WLog_Print(sdl->log, WLOG_DEBUG, "client is using backend '%s'", backend); + WLog_Print(sdl->getWLog(), WLOG_DEBUG, "client is using backend '%s'", backend); sdl_dialogs_init(); SDL_SetHint(SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED, "0"); @@ -1537,12 +765,7 @@ int main(int argc, char* argv[]) ScopeGuard guard( [&]() { - std::unique_lock lock(sdl->critical); - sdl->windows.clear(); - sdl->dialog.destroy(); - - sdl_destroy_primary(sdl); - + sdl->cleanup(); freerdp_del_signal_cleanup_handler(sdl->context(), sdl_term_handler); sdl_dialogs_uninit(); SDL_Quit(); @@ -1563,170 +786,8 @@ int main(int argc, char* argv[]) if (freerdp_client_stop(context) != 0) return -1; - if (sdl->exit_code != 0) - rc = sdl->exit_code; + if (sdl->exitCode() != 0) + rc = sdl->exitCode(); return rc; } - -bool SdlContext::update_fullscreen(bool enter) -{ - for (const auto& window : windows) - { - if (!sdl_push_user_event(SDL_EVENT_USER_WINDOW_FULLSCREEN, &window.second, enter)) - return false; - } - fullscreen = enter; - return true; -} - -bool SdlContext::update_minimize() -{ - return sdl_push_user_event(SDL_EVENT_USER_WINDOW_MINIMIZE); -} - -bool SdlContext::update_resizeable(bool enable) -{ - const auto settings = context()->settings; - const bool dyn = freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate); - const bool smart = freerdp_settings_get_bool(settings, FreeRDP_SmartSizing); - bool use = (dyn && enable) || smart; - - for (const auto& window : windows) - { - if (!sdl_push_user_event(SDL_EVENT_USER_WINDOW_RESIZEABLE, &window.second, use)) - return false; - } - resizeable = use; - - return true; -} - -SdlContext::SdlContext(rdpContext* context) - : _context(context), log(WLog_Get(SDL_TAG)), disp(this), input(this), clip(this), - primary(nullptr, SDL_DestroySurface), rdp_thread_running(false), dialog(log) -{ - WINPR_ASSERT(context); - setMetadata(); -} - -void SdlContext::setHasCursor(bool val) -{ - this->_cursor_visible = val; -} - -bool SdlContext::hasCursor() const -{ - return _cursor_visible; -} - -void SdlContext::setMetadata() -{ - auto wmclass = freerdp_settings_get_string(_context->settings, FreeRDP_WmClass); - if (!wmclass || (strlen(wmclass) == 0)) - wmclass = SDL_CLIENT_UUID; - - SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_IDENTIFIER_STRING, wmclass); - SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING, SDL_CLIENT_NAME); - SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_VERSION_STRING, SDL_CLIENT_VERSION); - SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_CREATOR_STRING, SDL_CLIENT_VENDOR); - SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_COPYRIGHT_STRING, SDL_CLIENT_COPYRIGHT); - SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_URL_STRING, SDL_CLIENT_URL); - SDL_SetAppMetadataProperty(SDL_PROP_APP_METADATA_TYPE_STRING, SDL_CLIENT_TYPE); -} - -bool SdlContext::shallAbort(bool ignoreDialogs) -{ - std::unique_lock lock(critical); - if (freerdp_shall_disconnect_context(context())) - { - if (ignoreDialogs) - return true; - if (rdp_thread_running) - return false; - return !dialog.isRunning(); - } - return false; -} - -bool SdlContext::redraw(bool suppress) const -{ - if (!_connected) - return true; - - auto gdi = context()->gdi; - WINPR_ASSERT(gdi); - return gdi_send_suppress_output(gdi, suppress); -} - -void SdlContext::setConnected(bool val) -{ - _connected = val; -} - -bool SdlContext::isConnected() const -{ - return _connected; -} - -rdpContext* SdlContext::context() const -{ - WINPR_ASSERT(_context); - return _context; -} - -rdpClientContext* SdlContext::common() const -{ - return reinterpret_cast(context()); -} - -void SdlContext::setCursor(rdpPointer* cursor) -{ - _cursor = cursor; -} - -rdpPointer* SdlContext::cursor() const -{ - return _cursor; -} - -void SdlContext::setMonitorIds(const std::vector& ids) -{ - _monitorIds.clear(); - for (auto id : ids) - { - _monitorIds.push_back(id); - } -} - -const std::vector& SdlContext::monitorIds() const -{ - return _monitorIds; -} - -int64_t SdlContext::monitorId(uint32_t index) const -{ - if (index >= _monitorIds.size()) - { - return -1; - } - return _monitorIds[index]; -} - -void SdlContext::push(std::vector&& rects) -{ - std::unique_lock lock(_queue_mux); - _queue.emplace(std::move(rects)); -} - -std::vector SdlContext::pop() -{ - std::unique_lock lock(_queue_mux); - if (_queue.empty()) - { - return {}; - } - auto val = std::move(_queue.front()); - _queue.pop(); - return val; -} diff --git a/client/SDL/SDL3/sdl_freerdp.hpp b/client/SDL/SDL3/sdl_freerdp.hpp index 45f4d84f9..35af3388b 100644 --- a/client/SDL/SDL3/sdl_freerdp.hpp +++ b/client/SDL/SDL3/sdl_freerdp.hpp @@ -19,105 +19,4 @@ #pragma once -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "sdl_types.hpp" -#include "sdl_disp.hpp" -#include "sdl_kbd.hpp" -#include "sdl_clip.hpp" -#include "sdl_utils.hpp" -#include "sdl_window.hpp" -#include "dialogs/sdl_connection_dialog_wrapper.hpp" - -using SDLSurfacePtr = std::unique_ptr; - -class SdlContext -{ - public: - explicit SdlContext(rdpContext* context); - SdlContext(const SdlContext& other) = delete; - SdlContext(SdlContext&& other) = delete; - ~SdlContext() = default; - - SdlContext& operator=(const SdlContext& other) = delete; - SdlContext& operator=(SdlContext&& other) = delete; - - [[nodiscard]] bool redraw(bool suppress = false) const; - - void setConnected(bool val); - [[nodiscard]] bool isConnected() const; - - [[nodiscard]] bool update_resizeable(bool enable); - [[nodiscard]] bool update_fullscreen(bool enter); - [[nodiscard]] bool update_minimize(); - - [[nodiscard]] rdpContext* context() const; - [[nodiscard]] rdpClientContext* common() const; - - void setCursor(rdpPointer* cursor); - [[nodiscard]] rdpPointer* cursor() const; - - void setMonitorIds(const std::vector& ids); - const std::vector& monitorIds() const; - int64_t monitorId(uint32_t index) const; - - void push(std::vector&& rects); - std::vector pop(); - - void setHasCursor(bool val); - [[nodiscard]] bool hasCursor() const; - - void setMetadata(); - - [[nodiscard]] bool shallAbort(bool ignoreDialogs = false); - - private: - rdpContext* _context; - std::atomic _connected = false; - bool _cursor_visible = true; - rdpPointer* _cursor = nullptr; - std::vector _monitorIds; - std::mutex _queue_mux; - std::queue> _queue; - - public: - wLog* log; - - /* SDL */ - bool fullscreen = false; - bool resizeable = false; - bool grab_mouse = false; - bool grab_kbd = false; - - std::map windows; - - CriticalSection critical; - std::thread thread; - WinPREvent windows_created; - int exit_code = -1; - - sdlDispContext disp; - sdlInput input; - sdlClip clip; - - SDLSurfacePtr primary; - - SDL_PixelFormat sdl_pixel_format = SDL_PIXELFORMAT_UNKNOWN; - - std::atomic rdp_thread_running; - SdlConnectionDialogWrapper dialog; -}; +#include "sdl_context.hpp" diff --git a/client/SDL/SDL3/sdl_kbd.cpp b/client/SDL/SDL3/sdl_kbd.cpp index 4330b53aa..8702164ca 100644 --- a/client/SDL/SDL3/sdl_kbd.cpp +++ b/client/SDL/SDL3/sdl_kbd.cpp @@ -19,7 +19,7 @@ #include "sdl_kbd.hpp" #include "sdl_disp.hpp" -#include "sdl_freerdp.hpp" +#include "sdl_context.hpp" #include "sdl_utils.hpp" #include "sdl_prefs.hpp" #include "sdl_touch.hpp" @@ -318,7 +318,7 @@ BOOL sdlInput::keyboard_focus_in() // TODO: fullscreen/remote app float fx = 0.0f; float fy = 0.0f; - if (_sdl->fullscreen) + if (_sdl->fullscreen()) { SDL_GetGlobalMouseState(&fx, &fy); } @@ -366,7 +366,7 @@ BOOL sdlInput::keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 if (!context) return FALSE; - WLog_Print(sdl->log, WLOG_WARN, + WLog_Print(sdl->getWLog(), WLOG_WARN, "KeyboardSetImeStatus(unitId=%04" PRIx16 ", imeState=%08" PRIx32 ", imeConvMode=%08" PRIx32 ") ignored", imeId, imeState, imeConvMode); @@ -447,7 +447,7 @@ bool sdlInput::prefToEnabled() } else { - WLog_Print(_sdl->log, WLOG_WARN, + WLog_Print(_sdl->getWLog(), WLOG_WARN, "Invalid config::SDL_KeyModMask entry value '%s', disabling hotkeys", val.c_str()); enabled = false; @@ -530,7 +530,7 @@ UINT32 sdlInput::scancode_to_rdp(Uint32 scancode) #if defined(WITH_DEBUG_SDL_KBD_EVENTS) auto code = static_cast(scancode); - WLog_Print(_sdl->log, WLOG_DEBUG, "got %s [%s] -> [%s]", SDL_GetScancodeName(code), + WLog_Print(_sdl->getWLog(), WLOG_DEBUG, "got %s [%s] -> [%s]", SDL_GetScancodeName(code), sdl_scancode_name(scancode), sdl_rdp_scancode_name(rdp)); #endif return rdp; @@ -580,30 +580,30 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) { if (ev->scancode == _hotkeyFullscreen) { - WLog_Print(_sdl->log, WLOG_INFO, "%s+<%s> pressed, toggling fullscreen state", + WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling fullscreen state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyFullscreen)); keyboard_sync_state(); - return _sdl->update_fullscreen(!_sdl->fullscreen); + return _sdl->toggleFullscreen(); } if (ev->scancode == _hotkeyResizable) { - WLog_Print(_sdl->log, WLOG_INFO, "%s+<%s> pressed, toggling resizeable state", + WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling resizeable state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyResizable)); keyboard_sync_state(); - return _sdl->update_resizeable(!_sdl->resizeable); + return _sdl->toggleResizeable(); } if (ev->scancode == _hotkeyGrab) { - WLog_Print(_sdl->log, WLOG_INFO, "%s+<%s> pressed, toggling grab state", + WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling grab state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyGrab)); keyboard_sync_state(); - keyboard_grab(ev->windowID, !_sdl->grab_kbd); + keyboard_grab(ev->windowID, !_sdl->grabKeyboard()); return TRUE; } if (ev->scancode == _hotkeyDisconnect) { - WLog_Print(_sdl->log, WLOG_INFO, "%s+<%s> pressed, disconnecting RDP session", + WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, disconnecting RDP session", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyDisconnect)); keyboard_sync_state(); freerdp_abort_connect_context(_sdl->context()); @@ -611,10 +611,10 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) } if (ev->scancode == _hotkeyMinimize) { - WLog_Print(_sdl->log, WLOG_INFO, "%s+<%s> pressed, minimizing client", + WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, minimizing client", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyMinimize)); keyboard_sync_state(); - return _sdl->update_minimize(); + return _sdl->setMinimized(); } } } @@ -623,7 +623,7 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) { const BOOL ex = RDP_SCANCODE_EXTENDED(rdp_scancode); const DWORD sc = RDP_SCANCODE_CODE(rdp_scancode); - WLog_Print(_sdl->log, WLOG_DEBUG, + WLog_Print(_sdl->getWLog(), WLOG_DEBUG, "SDL keycode: %02" PRIX32 " -> rdp code: [%04" PRIx16 "] %02" PRIX8 "%s", ev->scancode, rdp_scancode, sc, ex ? " extended" : ""); } @@ -634,7 +634,7 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) { const BOOL ex = RDP_SCANCODE_EXTENDED(scancode); const DWORD sc = RDP_SCANCODE_CODE(scancode); - WLog_Print(_sdl->log, WLOG_DEBUG, + WLog_Print(_sdl->getWLog(), WLOG_DEBUG, "SDL keycode: %02" PRIX32 " -> remapped rdp code: [%04" PRIx16 "] %02" PRIX8 "%s", ev->scancode, scancode, sc, ex ? " extended" : ""); @@ -646,15 +646,16 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) BOOL sdlInput::keyboard_grab(Uint32 windowID, bool enable) { - auto it = _sdl->windows.find(windowID); - if (it == _sdl->windows.end()) + const auto window = _sdl->getWindowForId(windowID); + if (!window) return FALSE; auto settings = _sdl->context()->settings; auto kbd_enabled = freerdp_settings_get_bool(settings, FreeRDP_GrabKeyboard); auto status = enable && kbd_enabled; - _sdl->grab_kbd = status; - return it->second.grabKeyboard(status); + if (!_sdl->setGrabKeyboard(status)) + WLog_Print(_sdl->getWLog(), WLOG_WARN, "Failed to ungrab keyboard"); + return window->grabKeyboard(status); } BOOL sdlInput::mouse_focus(Uint32 windowID) @@ -662,22 +663,23 @@ BOOL sdlInput::mouse_focus(Uint32 windowID) if (_lastWindowID != windowID) { _lastWindowID = windowID; - auto it = _sdl->windows.find(windowID); - if (it == _sdl->windows.end()) + auto window = _sdl->getWindowForId(windowID); + if (!window) return FALSE; - it->second.raise(); + window->raise(); } return TRUE; } BOOL sdlInput::mouse_grab(Uint32 windowID, bool enable) { - auto it = _sdl->windows.find(windowID); - if (it == _sdl->windows.end()) + auto window = _sdl->getWindowForId(windowID); + if (!window) return FALSE; - _sdl->grab_mouse = enable; - return it->second.grabMouse(enable); + if (!_sdl->setGrabMouse(enable)) + WLog_Print(_sdl->getWLog(), WLOG_WARN, "Failed to ungrab mouse"); + return window->grabMouse(enable); } sdlInput::sdlInput(SdlContext* sdl) diff --git a/client/SDL/SDL3/sdl_monitor.cpp b/client/SDL/SDL3/sdl_monitor.cpp index 5e1bb3a4d..2f8840692 100644 --- a/client/SDL/SDL3/sdl_monitor.cpp +++ b/client/SDL/SDL3/sdl_monitor.cpp @@ -36,7 +36,7 @@ #define TAG CLIENT_TAG("sdl") #include "sdl_monitor.hpp" -#include "sdl_freerdp.hpp" +#include "sdl_context.hpp" typedef struct { diff --git a/client/SDL/SDL3/sdl_pointer.cpp b/client/SDL/SDL3/sdl_pointer.cpp index 472e46066..3fdd73d61 100644 --- a/client/SDL/SDL3/sdl_pointer.cpp +++ b/client/SDL/SDL3/sdl_pointer.cpp @@ -22,7 +22,7 @@ #include #include "sdl_pointer.hpp" -#include "sdl_freerdp.hpp" +#include "sdl_context.hpp" #include "sdl_touch.hpp" #include "sdl_utils.hpp" @@ -136,7 +136,7 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) sdl_Pointer_Clear(ptr); - ptr->image = SDL_CreateSurface(sw, sh, sdl->sdl_pixel_format); + ptr->image = SDL_CreateSurface(sw, sh, sdl->pixelFormat()); if (!ptr->image) return FALSE; @@ -153,11 +153,11 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) // create a cursor image in 100% display scale to trick SDL into creating the cursor with the // correct size - auto it = sdl->windows.begin(); - if (it == sdl->windows.end()) + auto fw = sdl->getFirstWindow(); + if (!fw) return FALSE; - const auto hidpi_scale = SDL_GetWindowDisplayScale(it->second.window()); + const auto hidpi_scale = SDL_GetWindowDisplayScale(fw->window()); auto normal = SDL_CreateSurface( static_cast(static_cast(ptr->image->w) / hidpi_scale), static_cast(static_cast(ptr->image->h) / hidpi_scale), ptr->image->format); diff --git a/client/SDL/SDL3/sdl_touch.cpp b/client/SDL/SDL3/sdl_touch.cpp index 7e1924ab3..c29544ea7 100644 --- a/client/SDL/SDL3/sdl_touch.cpp +++ b/client/SDL/SDL3/sdl_touch.cpp @@ -20,7 +20,7 @@ #include #include "sdl_touch.hpp" -#include "sdl_freerdp.hpp" +#include "sdl_context.hpp" #include #include @@ -52,22 +52,15 @@ BOOL sdl_scale_coordinates(SdlContext* sdl, Uint32 windowId, INT32* px, INT32* p int offset_x = 0; int offset_y = 0; - for (const auto& it : sdl->windows) + auto window = sdl->getWindowForId(windowId); + if (window) { - auto& window = it.second; - const auto id = window.id(); - if (id != windowId) - { - continue; - } - - auto size = window.rect(); + auto size = window->rect(); sx = size.w / static_cast(gdi->width); sy = size.h / static_cast(gdi->height); - offset_x = window.offsetX(); - offset_y = window.offsetY(); - break; + offset_x = window->offsetX(); + offset_y = window->offsetY(); } if (freerdp_settings_get_bool(sdl->context()->settings, FreeRDP_SmartSizing)) @@ -199,7 +192,7 @@ BOOL sdl_handle_mouse_motion(SdlContext* sdl, const SDL_MouseMotionEvent* ev) WINPR_ASSERT(sdl); WINPR_ASSERT(ev); - sdl->input.mouse_focus(ev->windowID); + sdl->getInputChannelContext().mouse_focus(ev->windowID); const BOOL relative = freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor(); auto x = static_cast(relative ? ev->xrel : ev->x); From 636590374abbe66c89ce593135fb6976b1ed89b0 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 23 Jan 2026 10:08:08 +0100 Subject: [PATCH 05/30] [client,sdl] mark functions nodiscard * mark all SDL client functions nodiscard to emit warnings if the return is not properly checked * refactor some member functions, move implementation from header to source --- client/SDL/SDL3/sdl_channels.hpp | 5 +- client/SDL/SDL3/sdl_clip.cpp | 22 +++++++++ client/SDL/SDL3/sdl_clip.hpp | 78 ++++++++++++++------------------ client/SDL/SDL3/sdl_disp.hpp | 23 +++++----- client/SDL/SDL3/sdl_kbd.hpp | 55 +++++++++++----------- client/SDL/SDL3/sdl_monitor.hpp | 4 +- client/SDL/SDL3/sdl_pointer.hpp | 4 +- client/SDL/SDL3/sdl_touch.hpp | 16 +++---- client/SDL/SDL3/sdl_types.hpp | 4 +- 9 files changed, 114 insertions(+), 97 deletions(-) diff --git a/client/SDL/SDL3/sdl_channels.hpp b/client/SDL/SDL3/sdl_channels.hpp index a5c9f7d34..5c0e243df 100644 --- a/client/SDL/SDL3/sdl_channels.hpp +++ b/client/SDL/SDL3/sdl_channels.hpp @@ -22,8 +22,9 @@ #include #include -int sdl_on_channel_connected(freerdp* instance, const char* name, void* pInterface); -int sdl_on_channel_disconnected(freerdp* instance, const char* name, void* pInterface); +[[nodiscard]] int sdl_on_channel_connected(freerdp* instance, const char* name, void* pInterface); +[[nodiscard]] int sdl_on_channel_disconnected(freerdp* instance, const char* name, + void* pInterface); void sdl_OnChannelConnectedEventHandler(void* context, const ChannelConnectedEventArgs* e); void sdl_OnChannelDisconnectedEventHandler(void* context, const ChannelDisconnectedEventArgs* e); diff --git a/client/SDL/SDL3/sdl_clip.cpp b/client/SDL/SDL3/sdl_clip.cpp index bf2659d01..d7eb1aab5 100644 --- a/client/SDL/SDL3/sdl_clip.cpp +++ b/client/SDL/SDL3/sdl_clip.cpp @@ -964,6 +964,10 @@ ClipRequest::ClipRequest(UINT32 format, const std::string& mime) { } +ClipRequest::~ClipRequest() +{ +} + uint32_t ClipRequest::format() const { return _format; @@ -988,3 +992,21 @@ void ClipRequest::setSuccess(bool status) { _success = status; } + +CliprdrFormat::CliprdrFormat(uint32_t formatID, const char* formatName) : _formatID(formatID) +{ + if (formatName) + _formatName = formatName; +} + +uint32_t CliprdrFormat::formatId() const +{ + return _formatID; +} + +const char* CliprdrFormat::formatName() const +{ + if (_formatName.empty()) + return nullptr; + return _formatName.c_str(); +} diff --git a/client/SDL/SDL3/sdl_clip.hpp b/client/SDL/SDL3/sdl_clip.hpp index 84b513642..d5531e4fa 100644 --- a/client/SDL/SDL3/sdl_clip.hpp +++ b/client/SDL/SDL3/sdl_clip.hpp @@ -41,7 +41,7 @@ class ClipRequest ClipRequest(UINT32 format, const std::string& mime); ClipRequest(const ClipRequest& other) = default; ClipRequest(ClipRequest&& other) = default; - ~ClipRequest() = default; + virtual ~ClipRequest(); ClipRequest& operator=(const ClipRequest& other) = delete; ClipRequest& operator=(ClipRequest&& other) = delete; @@ -61,23 +61,10 @@ class ClipRequest class CliprdrFormat { public: - CliprdrFormat(uint32_t formatID, const char* formatName) : _formatID(formatID) - { - if (formatName) - _formatName = formatName; - } + CliprdrFormat(uint32_t formatID, const char* formatName); - [[nodiscard]] uint32_t formatId() const - { - return _formatID; - } - - [[nodiscard]] const char* formatName() const - { - if (_formatName.empty()) - return nullptr; - return _formatName.c_str(); - } + [[nodiscard]] uint32_t formatId() const; + [[nodiscard]] const char* formatName() const; private: uint32_t _formatID; @@ -103,42 +90,47 @@ class sdlClip [[nodiscard]] bool handle_update(const SDL_ClipboardEvent& ev); private: - UINT SendClientCapabilities(); + [[nodiscard]] UINT SendClientCapabilities(); void clearServerFormats(); - UINT SendFormatListResponse(BOOL status); - UINT SendDataResponse(const BYTE* data, size_t size); - UINT SendDataRequest(uint32_t formatID, const std::string& mime); + [[nodiscard]] UINT SendFormatListResponse(BOOL status); + [[nodiscard]] UINT SendDataResponse(const BYTE* data, size_t size); + [[nodiscard]] UINT SendDataRequest(uint32_t formatID, const std::string& mime); - std::string getServerFormat(uint32_t id); - uint32_t serverIdForMime(const std::string& mime); + [[nodiscard]] std::string getServerFormat(uint32_t id); + [[nodiscard]] uint32_t serverIdForMime(const std::string& mime); - bool contains(const char** mime_types, Sint32 count); + [[nodiscard]] bool contains(const char** mime_types, Sint32 count); - static UINT MonitorReady(CliprdrClientContext* context, - const CLIPRDR_MONITOR_READY* monitorReady); + [[nodiscard]] static UINT MonitorReady(CliprdrClientContext* context, + const CLIPRDR_MONITOR_READY* monitorReady); - static UINT ReceiveServerCapabilities(CliprdrClientContext* context, - const CLIPRDR_CAPABILITIES* capabilities); - static UINT ReceiveServerFormatList(CliprdrClientContext* context, - const CLIPRDR_FORMAT_LIST* formatList); - static UINT ReceiveFormatListResponse(CliprdrClientContext* context, - const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse); - static std::shared_ptr ReceiveFormatDataRequestHandle( + [[nodiscard]] static UINT ReceiveServerCapabilities(CliprdrClientContext* context, + const CLIPRDR_CAPABILITIES* capabilities); + [[nodiscard]] static UINT ReceiveServerFormatList(CliprdrClientContext* context, + const CLIPRDR_FORMAT_LIST* formatList); + [[nodiscard]] static UINT + ReceiveFormatListResponse(CliprdrClientContext* context, + const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse); + [[nodiscard]] static std::shared_ptr ReceiveFormatDataRequestHandle( sdlClip* clipboard, const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest, uint32_t& len); - static UINT ReceiveFormatDataRequest(CliprdrClientContext* context, - const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest); - static UINT ReceiveFormatDataResponse(CliprdrClientContext* context, - const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse); + [[nodiscard]] static UINT + ReceiveFormatDataRequest(CliprdrClientContext* context, + const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest); + [[nodiscard]] static UINT + ReceiveFormatDataResponse(CliprdrClientContext* context, + const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse); - static const void* SDLCALL ClipDataCb(void* userdata, const char* mime_type, size_t* size); + [[nodiscard]] static const void* SDLCALL ClipDataCb(void* userdata, const char* mime_type, + size_t* size); static void SDLCALL ClipCleanCb(void* userdata); - static bool mime_is_file(const std::string& mime); - static bool mime_is_text(const std::string& mime); - static bool mime_is_image(const std::string& mime); - static bool mime_is_bmp(const std::string& mime); - static bool mime_is_html(const std::string& mime); + [[nodiscard]] static bool mime_is_file(const std::string& mime); + [[nodiscard]] static bool mime_is_text(const std::string& mime); + [[nodiscard]] static bool mime_is_image(const std::string& mime); + [[nodiscard]] static bool mime_is_bmp(const std::string& mime); + [[nodiscard]] static bool mime_is_html(const std::string& mime); + private: SdlContext* _sdl = nullptr; CliprdrFileContext* _file = nullptr; CliprdrClientContext* _ctx = nullptr; diff --git a/client/SDL/SDL3/sdl_disp.hpp b/client/SDL/SDL3/sdl_disp.hpp index 9acbc8561..881b8c2e9 100644 --- a/client/SDL/SDL3/sdl_disp.hpp +++ b/client/SDL/SDL3/sdl_disp.hpp @@ -35,7 +35,7 @@ class sdlDispContext explicit sdlDispContext(SdlContext* sdl); sdlDispContext(const sdlDispContext& other) = delete; sdlDispContext(sdlDispContext&& other) = delete; - ~sdlDispContext(); + virtual ~sdlDispContext(); sdlDispContext& operator=(const sdlDispContext& other) = delete; sdlDispContext& operator=(sdlDispContext&& other) = delete; @@ -47,24 +47,25 @@ class sdlDispContext [[nodiscard]] bool handle_window_event(const SDL_WindowEvent* ev); private: - UINT DisplayControlCaps(UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, - UINT32 maxMonitorAreaFactorB); - bool set_window_resizable(); + [[nodiscard]] UINT DisplayControlCaps(UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, + UINT32 maxMonitorAreaFactorB); + [[nodiscard]] bool set_window_resizable(); - bool sendResize(); - bool settings_changed(const std::vector& layout); - UINT sendLayout(const rdpMonitor* monitors, size_t nmonitors); + [[nodiscard]] bool sendResize(); + [[nodiscard]] bool settings_changed(const std::vector& layout); + [[nodiscard]] UINT sendLayout(const rdpMonitor* monitors, size_t nmonitors); - bool addTimer(); + [[nodiscard]] bool addTimer(); bool updateMonitor(SDL_WindowID id); bool updateMonitors(SDL_EventType type); - static UINT DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors, - UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB); + [[nodiscard]] static UINT DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors, + UINT32 maxMonitorAreaFactorA, + UINT32 maxMonitorAreaFactorB); static void OnActivated(void* context, const ActivatedEventArgs* e); static void OnGraphicsReset(void* context, const GraphicsResetEventArgs* e); - static Uint32 SDLCALL OnTimer(void* param, SDL_TimerID timerID, Uint32 interval); + [[nodiscard]] static Uint32 SDLCALL OnTimer(void* param, SDL_TimerID timerID, Uint32 interval); SdlContext* _sdl = nullptr; DispClientContext* _disp = nullptr; diff --git a/client/SDL/SDL3/sdl_kbd.hpp b/client/SDL/SDL3/sdl_kbd.hpp index 901f79a0f..522def3b6 100644 --- a/client/SDL/SDL3/sdl_kbd.hpp +++ b/client/SDL/SDL3/sdl_kbd.hpp @@ -37,47 +37,48 @@ class sdlInput explicit sdlInput(SdlContext* sdl); sdlInput(const sdlInput& other) = delete; sdlInput(sdlInput&& other) = delete; - ~sdlInput(); + virtual ~sdlInput(); sdlInput& operator=(const sdlInput& other) = delete; sdlInput& operator=(sdlInput&& other) = delete; - BOOL initialize(); + [[nodiscard]] BOOL initialize(); - BOOL keyboard_sync_state(); - BOOL keyboard_focus_in(); + [[nodiscard]] BOOL keyboard_sync_state(); + [[nodiscard]] BOOL keyboard_focus_in(); - BOOL keyboard_handle_event(const SDL_KeyboardEvent* ev); + [[nodiscard]] BOOL keyboard_handle_event(const SDL_KeyboardEvent* ev); - BOOL keyboard_grab(Uint32 windowID, bool enable); - BOOL mouse_focus(Uint32 windowID); - BOOL mouse_grab(Uint32 windowID, bool enable); + [[nodiscard]] BOOL keyboard_grab(Uint32 windowID, bool enable); + [[nodiscard]] BOOL mouse_focus(Uint32 windowID); + [[nodiscard]] BOOL mouse_grab(Uint32 windowID, bool enable); - static BOOL keyboard_set_indicators(rdpContext* context, UINT16 led_flags); - static BOOL keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState, - UINT32 imeConvMode); + [[nodiscard]] static BOOL keyboard_set_indicators(rdpContext* context, UINT16 led_flags); + [[nodiscard]] static BOOL keyboard_set_ime_status(rdpContext* context, UINT16 imeId, + UINT32 imeState, UINT32 imeConvMode); - bool prefToEnabled(); - uint32_t prefToMask(); - static uint32_t prefKeyValue(const std::string& key, uint32_t fallback = SDL_SCANCODE_UNKNOWN); + [[nodiscard]] bool prefToEnabled(); + [[nodiscard]] uint32_t prefToMask(); + [[nodiscard]] static uint32_t prefKeyValue(const std::string& key, + uint32_t fallback = SDL_SCANCODE_UNKNOWN); private: - static std::list tokenize(const std::string& data, - const std::string& delimiter = ","); - static bool extract(const std::string& token, uint32_t& key, uint32_t& value); + [[nodiscard]] static std::list tokenize(const std::string& data, + const std::string& delimiter = ","); + [[nodiscard]] static bool extract(const std::string& token, uint32_t& key, uint32_t& value); - UINT32 scancode_to_rdp(Uint32 scancode); + [[nodiscard]] UINT32 scancode_to_rdp(Uint32 scancode); - SdlContext* _sdl; - Uint32 _lastWindowID; + SdlContext* _sdl = nullptr; + Uint32 _lastWindowID = 0; // hotkey handling - bool _hotkeysEnabled; - uint32_t _hotkeyModmask; // modifier keys mask - uint32_t _hotkeyFullscreen; - uint32_t _hotkeyResizable; - uint32_t _hotkeyGrab; - uint32_t _hotkeyDisconnect; - uint32_t _hotkeyMinimize; + bool _hotkeysEnabled = false; + uint32_t _hotkeyModmask = 0; // modifier keys mask + uint32_t _hotkeyFullscreen = 0; + uint32_t _hotkeyResizable = 0; + uint32_t _hotkeyGrab = 0; + uint32_t _hotkeyDisconnect = 0; + uint32_t _hotkeyMinimize = 0; FREERDP_REMAP_TABLE* _remapTable = nullptr; }; diff --git a/client/SDL/SDL3/sdl_monitor.hpp b/client/SDL/SDL3/sdl_monitor.hpp index 2d9e2c27f..a993c9f1a 100644 --- a/client/SDL/SDL3/sdl_monitor.hpp +++ b/client/SDL/SDL3/sdl_monitor.hpp @@ -24,5 +24,5 @@ #include "sdl_types.hpp" -int sdl_list_monitors(SdlContext* sdl); -BOOL sdl_detect_monitors(SdlContext* sdl, UINT32* pMaxWidth, UINT32* ppMaxHeight); +[[nodiscard]] int sdl_list_monitors(SdlContext* sdl); +[[nodiscard]] BOOL sdl_detect_monitors(SdlContext* sdl, UINT32* pMaxWidth, UINT32* ppMaxHeight); diff --git a/client/SDL/SDL3/sdl_pointer.hpp b/client/SDL/SDL3/sdl_pointer.hpp index f65171d69..830bee7c2 100644 --- a/client/SDL/SDL3/sdl_pointer.hpp +++ b/client/SDL/SDL3/sdl_pointer.hpp @@ -25,6 +25,6 @@ #include -BOOL sdl_register_pointer(rdpGraphics* graphics); +[[nodiscard]] BOOL sdl_register_pointer(rdpGraphics* graphics); -BOOL sdl_Pointer_Set_Process(SdlContext* sdl); +[[nodiscard]] BOOL sdl_Pointer_Set_Process(SdlContext* sdl); diff --git a/client/SDL/SDL3/sdl_touch.hpp b/client/SDL/SDL3/sdl_touch.hpp index 7eebba030..35082a688 100644 --- a/client/SDL/SDL3/sdl_touch.hpp +++ b/client/SDL/SDL3/sdl_touch.hpp @@ -24,13 +24,13 @@ #include #include "sdl_types.hpp" -BOOL sdl_scale_coordinates(SdlContext* sdl, Uint32 windowId, INT32* px, INT32* py, - BOOL fromLocalToRDP, BOOL applyOffset); +[[nodiscard]] BOOL sdl_scale_coordinates(SdlContext* sdl, Uint32 windowId, INT32* px, INT32* py, + BOOL fromLocalToRDP, BOOL applyOffset); -BOOL sdl_handle_mouse_motion(SdlContext* sdl, const SDL_MouseMotionEvent* ev); -BOOL sdl_handle_mouse_wheel(SdlContext* sdl, const SDL_MouseWheelEvent* ev); -BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev); +[[nodiscard]] BOOL sdl_handle_mouse_motion(SdlContext* sdl, const SDL_MouseMotionEvent* ev); +[[nodiscard]] BOOL sdl_handle_mouse_wheel(SdlContext* sdl, const SDL_MouseWheelEvent* ev); +[[nodiscard]] BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev); -BOOL sdl_handle_touch_down(SdlContext* sdl, const SDL_TouchFingerEvent* ev); -BOOL sdl_handle_touch_up(SdlContext* sdl, const SDL_TouchFingerEvent* ev); -BOOL sdl_handle_touch_motion(SdlContext* sdl, const SDL_TouchFingerEvent* ev); +[[nodiscard]] BOOL sdl_handle_touch_down(SdlContext* sdl, const SDL_TouchFingerEvent* ev); +[[nodiscard]] BOOL sdl_handle_touch_up(SdlContext* sdl, const SDL_TouchFingerEvent* ev); +[[nodiscard]] BOOL sdl_handle_touch_motion(SdlContext* sdl, const SDL_TouchFingerEvent* ev); diff --git a/client/SDL/SDL3/sdl_types.hpp b/client/SDL/SDL3/sdl_types.hpp index 831472c35..b41c55a7e 100644 --- a/client/SDL/SDL3/sdl_types.hpp +++ b/client/SDL/SDL3/sdl_types.hpp @@ -29,7 +29,7 @@ typedef struct SdlContext* sdl; } sdl_rdp_context; -static inline SdlContext* get_context(void* ctx) +[[nodiscard]] static inline SdlContext* get_context(void* ctx) { if (!ctx) return nullptr; @@ -37,7 +37,7 @@ static inline SdlContext* get_context(void* ctx) return sdl->sdl; } -static inline SdlContext* get_context(rdpContext* ctx) +[[nodiscard]] static inline SdlContext* get_context(rdpContext* ctx) { if (!ctx) return nullptr; From caffbab7d40c77709739fb85e5c84632a5fca16b Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 23 Jan 2026 10:33:49 +0100 Subject: [PATCH 06/30] [client,sdl] fix display channel updates * always send updates if enabled and a monitor setting changed * properly handle window and display updates --- client/SDL/SDL3/sdl_context.cpp | 20 ++++++++++ client/SDL/SDL3/sdl_context.hpp | 3 ++ client/SDL/SDL3/sdl_disp.cpp | 65 ++++++++++++++++----------------- client/SDL/SDL3/sdl_disp.hpp | 4 +- 4 files changed, 56 insertions(+), 36 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index 63e49a83b..7e4879f7d 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -783,6 +783,26 @@ SDL_PixelFormat SdlContext::pixelFormat() const return _sdlPixelFormat; } +bool SdlContext::addDisplayWindow(SDL_DisplayID id) +{ + const auto flags = + SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS; + auto title = sdl::utils::windowTitle(context()->settings); + auto w = SdlWindow::create(id, title, flags); + _windows.emplace(w.id(), std::move(w)); + return true; +} + +bool SdlContext::removeDisplay(SDL_DisplayID id) +{ + for (auto& w : _windows) + { + if (w.second.displayIndex() == id) + _windows.erase(w.first); + } + return true; +} + SdlWindow* SdlContext::getWindowForId(SDL_WindowID id) { auto it = _windows.find(id); diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index 3dd981fe8..a19dc8ab6 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -109,6 +109,9 @@ class SdlContext [[nodiscard]] SdlWindow* getWindowForId(SDL_WindowID id); [[nodiscard]] SdlWindow* getFirstWindow(); + [[nodiscard]] bool addDisplayWindow(SDL_DisplayID id); + [[nodiscard]] bool removeDisplay(SDL_DisplayID id); + [[nodiscard]] sdlDispContext& getDisplayChannelContext(); [[nodiscard]] sdlInput& getInputChannelContext(); [[nodiscard]] sdlClip& getClipboardChannelContext(); diff --git a/client/SDL/SDL3/sdl_disp.cpp b/client/SDL/SDL3/sdl_disp.cpp index 9e0dc34b6..7f9b1b09b 100644 --- a/client/SDL/SDL3/sdl_disp.cpp +++ b/client/SDL/SDL3/sdl_disp.cpp @@ -88,7 +88,7 @@ bool sdlDispContext::sendResize() return sendLayout(monitors, mcount) != CHANNEL_RC_OK; } -bool sdlDispContext::set_window_resizable() +bool sdlDispContext::setWindowResizeable() { return _sdl->setResizeable(true); } @@ -125,7 +125,8 @@ void sdlDispContext::OnActivated(void* context, const ActivatedEventArgs* e) if (sdlDisp->_activated && !freerdp_settings_get_bool(settings, FreeRDP_Fullscreen)) { - sdlDisp->set_window_resizable(); + if (!sdlDisp->setWindowResizeable()) + return; if (e->firstActivation) return; @@ -148,7 +149,7 @@ void sdlDispContext::OnGraphicsReset(void* context, const GraphicsResetEventArgs if (sdlDisp->_activated && !freerdp_settings_get_bool(settings, FreeRDP_Fullscreen)) { - sdlDisp->set_window_resizable(); + sdlDisp->setWindowResizeable(); sdlDisp->addTimer(); } } @@ -170,8 +171,6 @@ Uint32 sdlDispContext::OnTimer(void* param, [[maybe_unused]] SDL_TimerID timerID return 0; WLog_Print(sdl->getWLog(), WLOG_TRACE, "checking for display changes..."); - if (!sdlDisp->_activated || freerdp_settings_get_bool(settings, FreeRDP_Fullscreen)) - return 0; auto rc = sdlDisp->sendResize(); if (!rc) @@ -279,7 +278,8 @@ bool sdlDispContext::addTimer() WLog_Print(_sdl->getWLog(), WLOG_TRACE, "adding new display check timer"); _timer_retries = 0; - sendResize(); + if (!sendResize()) + return false; _timer = SDL_AddTimer(1000, sdlDispContext::OnTimer, this); return true; } @@ -288,36 +288,19 @@ bool sdlDispContext::updateMonitor(SDL_WindowID id) { auto settings = _sdl->context()->settings; if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) - return updateMonitors(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED); + return updateMonitors(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, id); if (!freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_DynamicResolutionUpdate)) return true; - const auto window = _sdl->getWindowForId(id); - if (!window) - return false; - - const auto& monitor = window->monitor(true); - if (!freerdp_settings_set_monitor_def_array_sorted(settings, &monitor, 1)) + if (!_sdl->updateWindowList()) return false; return addTimer(); } -bool sdlDispContext::updateMonitors(SDL_EventType type) +bool sdlDispContext::updateMonitors(SDL_EventType type, SDL_DisplayID displayID) { - switch (type) - { - case SDL_EVENT_DISPLAY_ADDED: - case SDL_EVENT_DISPLAY_REMOVED: - case SDL_EVENT_DISPLAY_MOVED: - SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "TODO [%s] Not fully supported yet", - sdl_event_type_str(type)); - break; - default: - break; - } - auto settings = _sdl->context()->settings; if (!freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) return true; @@ -325,6 +308,20 @@ bool sdlDispContext::updateMonitors(SDL_EventType type) if (!freerdp_settings_get_bool(settings, FreeRDP_DynamicResolutionUpdate)) return true; + switch (type) + { + case SDL_EVENT_DISPLAY_ADDED: + if (!_sdl->addDisplayWindow(displayID)) + return false; + break; + case SDL_EVENT_DISPLAY_REMOVED: + if (!_sdl->removeDisplay(displayID)) + return false; + break; + default: + break; + } + if (!_sdl->updateWindowList()) return false; return addTimer(); @@ -338,25 +335,25 @@ bool sdlDispContext::handle_display_event(const SDL_DisplayEvent* ev) { case SDL_EVENT_DISPLAY_ADDED: SDL_Log("A new display with id %u was connected", ev->displayID); - return updateMonitors(ev->type); + return updateMonitors(ev->type, ev->displayID); case SDL_EVENT_DISPLAY_REMOVED: SDL_Log("The display with id %u was disconnected", ev->displayID); - return updateMonitors(ev->type); + return updateMonitors(ev->type, ev->displayID); case SDL_EVENT_DISPLAY_ORIENTATION: SDL_Log("The orientation of display with id %u was changed", ev->displayID); - return updateMonitors(ev->type); + return updateMonitors(ev->type, ev->displayID); case SDL_EVENT_DISPLAY_MOVED: SDL_Log("The display with id %u was moved", ev->displayID); - return updateMonitors(ev->type); + return updateMonitors(ev->type, ev->displayID); case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED: SDL_Log("The display with id %u changed scale", ev->displayID); - return updateMonitors(ev->type); + return updateMonitors(ev->type, ev->displayID); case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED: SDL_Log("The display with id %u changed mode", ev->displayID); - return updateMonitors(ev->type); + return updateMonitors(ev->type, ev->displayID); case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED: SDL_Log("The display with id %u changed desktop mode", ev->displayID); - return updateMonitors(ev->type); + return updateMonitors(ev->type, ev->displayID); default: return true; } @@ -438,7 +435,7 @@ UINT sdlDispContext::DisplayControlCaps(UINT32 maxNumMonitors, UINT32 maxMonitor return CHANNEL_RC_OK; WLog_DBG(TAG, "DisplayControlCapsPdu: setting the window as resizable"); - return set_window_resizable() ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY; + return setWindowResizeable() ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY; } bool sdlDispContext::init(DispClientContext* disp) diff --git a/client/SDL/SDL3/sdl_disp.hpp b/client/SDL/SDL3/sdl_disp.hpp index 881b8c2e9..b62b1b8e9 100644 --- a/client/SDL/SDL3/sdl_disp.hpp +++ b/client/SDL/SDL3/sdl_disp.hpp @@ -49,7 +49,7 @@ class sdlDispContext private: [[nodiscard]] UINT DisplayControlCaps(UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB); - [[nodiscard]] bool set_window_resizable(); + [[nodiscard]] bool setWindowResizeable(); [[nodiscard]] bool sendResize(); [[nodiscard]] bool settings_changed(const std::vector& layout); @@ -58,7 +58,7 @@ class sdlDispContext [[nodiscard]] bool addTimer(); bool updateMonitor(SDL_WindowID id); - bool updateMonitors(SDL_EventType type); + bool updateMonitors(SDL_EventType type, SDL_DisplayID displayID); [[nodiscard]] static UINT DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, From 845ef25997f3708336a7c12cd6d36f4ee073f015 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 23 Jan 2026 12:57:44 +0100 Subject: [PATCH 07/30] [client,sdl] fix unused return warnings --- .../SDL3/dialogs/sdl_connection_dialog.cpp | 6 +- client/SDL/SDL3/sdl_context.cpp | 2 +- client/SDL/SDL3/sdl_disp.cpp | 8 +-- client/SDL/SDL3/sdl_freerdp.cpp | 55 +++++++++++++------ client/SDL/SDL3/sdl_kbd.cpp | 21 ++++--- client/SDL/SDL3/sdl_touch.cpp | 11 +++- client/SDL/SDL3/sdl_window.cpp | 2 +- 7 files changed, 67 insertions(+), 38 deletions(-) diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp index 503d7bc50..a2c935093 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp @@ -202,7 +202,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (event.type == SDL_EVENT_KEY_UP) { freerdp_abort_event(_context); - sdl_push_quit(); + (void)sdl_push_quit(); } break; case SDLK_TAB: @@ -238,7 +238,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (event.type == SDL_EVENT_MOUSE_BUTTON_UP) { freerdp_abort_event(_context); - sdl_push_quit(); + (void)sdl_push_quit(); } } @@ -272,7 +272,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (windowID == ev.windowID) { freerdp_abort_event(_context); - sdl_push_quit(); + (void)sdl_push_quit(); } break; default: diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index 7e4879f7d..16f3a4fbe 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -525,7 +525,7 @@ void SdlContext::sdl_client_cleanup(int exit_code, const std::string& error_msg) getDialog().show(false); _exitCode = exit_code; - sdl_push_user_event(SDL_EVENT_USER_QUIT); + (void)sdl_push_user_event(SDL_EVENT_USER_QUIT); SDL_CleanupTLS(); } diff --git a/client/SDL/SDL3/sdl_disp.cpp b/client/SDL/SDL3/sdl_disp.cpp index 7f9b1b09b..0372f9e20 100644 --- a/client/SDL/SDL3/sdl_disp.cpp +++ b/client/SDL/SDL3/sdl_disp.cpp @@ -131,7 +131,7 @@ void sdlDispContext::OnActivated(void* context, const ActivatedEventArgs* e) if (e->firstActivation) return; - sdlDisp->addTimer(); + (void)sdlDisp->addTimer(); } } @@ -149,8 +149,8 @@ void sdlDispContext::OnGraphicsReset(void* context, const GraphicsResetEventArgs if (sdlDisp->_activated && !freerdp_settings_get_bool(settings, FreeRDP_Fullscreen)) { - sdlDisp->setWindowResizeable(); - sdlDisp->addTimer(); + if (sdlDisp->setWindowResizeable()) + (void)sdlDisp->addTimer(); } } @@ -478,7 +478,7 @@ sdlDispContext::sdlDispContext(SdlContext* sdl) : _sdl(sdl) PubSub_SubscribeActivated(pubSub, sdlDispContext::OnActivated); PubSub_SubscribeGraphicsReset(pubSub, sdlDispContext::OnGraphicsReset); - addTimer(); + (void)addTimer(); } sdlDispContext::~sdlDispContext() diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 9390db6f6..281fce4c9 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -76,7 +76,7 @@ static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const char* signame, [[maybe_unused]] void* context) { - sdl_push_quit(); + (void)sdl_push_quit(); } static int sdl_run(SdlContext* sdl) @@ -138,7 +138,8 @@ static int sdl_run(SdlContext* sdl) case SDL_EVENT_KEY_UP: { const SDL_KeyboardEvent* ev = &windowEvent.key; - sdl->getInputChannelContext().keyboard_handle_event(ev); + if (!sdl->getInputChannelContext().keyboard_handle_event(ev)) + return -1; } break; case SDL_EVENT_KEYMAP_CHANGED: @@ -150,7 +151,8 @@ static int sdl_run(SdlContext* sdl) SDL_MouseMotionEvent& ev = windowEvent.motion; point2pix(ev.windowID, ev.x, ev.y); point2pix(ev.windowID, ev.xrel, ev.yrel); - sdl_handle_mouse_motion(sdl, &ev); + if (!sdl_handle_mouse_motion(sdl, &ev)) + return -1; } break; case SDL_EVENT_MOUSE_BUTTON_DOWN: @@ -158,31 +160,36 @@ static int sdl_run(SdlContext* sdl) { SDL_MouseButtonEvent& ev = windowEvent.button; point2pix(ev.windowID, ev.x, ev.y); - sdl_handle_mouse_button(sdl, &ev); + if (!sdl_handle_mouse_button(sdl, &ev)) + return -1; } break; case SDL_EVENT_MOUSE_WHEEL: { const SDL_MouseWheelEvent* ev = &windowEvent.wheel; - sdl_handle_mouse_wheel(sdl, ev); + if (!sdl_handle_mouse_wheel(sdl, ev)) + return -1; } break; case SDL_EVENT_FINGER_DOWN: { const SDL_TouchFingerEvent* ev = &windowEvent.tfinger; - sdl_handle_touch_down(sdl, ev); + if (!sdl_handle_touch_down(sdl, ev)) + return -1; } break; case SDL_EVENT_FINGER_UP: { const SDL_TouchFingerEvent* ev = &windowEvent.tfinger; - sdl_handle_touch_up(sdl, ev); + if (!sdl_handle_touch_up(sdl, ev)) + return -1; } break; case SDL_EVENT_FINGER_MOTION: { const SDL_TouchFingerEvent* ev = &windowEvent.tfinger; - sdl_handle_touch_motion(sdl, ev); + if (!sdl_handle_touch_motion(sdl, ev)) + return -1; } break; @@ -232,14 +239,16 @@ static int sdl_run(SdlContext* sdl) do { rectangles = sdl->pop(); - sdl->drawToWindows(rectangles); + if (!sdl->drawToWindows(rectangles)) + return -1; } while (!rectangles.empty()); } break; case SDL_EVENT_USER_CREATE_WINDOWS: { auto ctx = static_cast(windowEvent.user.data1); - ctx->createWindows(); + if (!ctx->createWindows()) + return -1; } break; case SDL_EVENT_USER_WINDOW_RESIZEABLE: @@ -259,7 +268,8 @@ static int sdl_run(SdlContext* sdl) } break; case SDL_EVENT_USER_WINDOW_MINIMIZE: - sdl->minimizeAllWindows(); + if (!sdl->minimizeAllWindows()) + return -1; break; case SDL_EVENT_USER_POINTER_NULL: SDL_HideCursor(); @@ -297,10 +307,12 @@ static int sdl_run(SdlContext* sdl) break; case SDL_EVENT_USER_POINTER_SET: sdl->setCursor(static_cast(windowEvent.user.data1)); - sdl_Pointer_Set_Process(sdl); + if (!sdl_Pointer_Set_Process(sdl)) + return -1; break; case SDL_EVENT_CLIPBOARD_UPDATE: - sdl->getClipboardChannelContext().handle_update(windowEvent.clipboard); + if (!sdl->getClipboardChannelContext().handle_update(windowEvent.clipboard)) + return -1; break; case SDL_EVENT_USER_QUIT: default: @@ -324,7 +336,8 @@ static int sdl_run(SdlContext* sdl) case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: if (sdl->isConnected()) { - sdl_Pointer_Set_Process(sdl); + if (!sdl_Pointer_Set_Process(sdl)) + return -1; if (freerdp_settings_get_bool( sdl->context()->settings, FreeRDP_DynamicResolutionUpdate)) @@ -373,9 +386,12 @@ static int sdl_run(SdlContext* sdl) } break; case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: - window->fill(); - sdl->drawToWindow(*window); - sdl_Pointer_Set_Process(sdl); + if (!window->fill()) + return -1; + if (!sdl->drawToWindow(*window)) + return -1; + if (!sdl_Pointer_Set_Process(sdl)) + return -1; break; case SDL_EVENT_WINDOW_MOVED: { @@ -723,7 +739,10 @@ int main(int argc, char* argv[]) { rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv); if (freerdp_settings_get_bool(settings, FreeRDP_ListMonitors)) - sdl_list_monitors(sdl); + { + if (!sdl_list_monitors(sdl)) + return -1; + } else { switch (status) diff --git a/client/SDL/SDL3/sdl_kbd.cpp b/client/SDL/SDL3/sdl_kbd.cpp index 8702164ca..c5c7bdfba 100644 --- a/client/SDL/SDL3/sdl_kbd.cpp +++ b/client/SDL/SDL3/sdl_kbd.cpp @@ -332,7 +332,8 @@ BOOL sdlInput::keyboard_focus_in() if (w) { auto id = SDL_GetWindowID(w); - sdl_scale_coordinates(_sdl, id, &x, &y, TRUE, TRUE); + if (!sdl_scale_coordinates(_sdl, id, &x, &y, TRUE, TRUE)) + return FALSE; } return freerdp_client_send_button_event(_sdl->common(), FALSE, PTR_FLAGS_MOVE, x, y); } @@ -582,14 +583,16 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling fullscreen state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyFullscreen)); - keyboard_sync_state(); + if (!keyboard_sync_state()) + return FALSE; return _sdl->toggleFullscreen(); } if (ev->scancode == _hotkeyResizable) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling resizeable state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyResizable)); - keyboard_sync_state(); + if (!keyboard_sync_state()) + return FALSE; return _sdl->toggleResizeable(); } @@ -597,15 +600,16 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling grab state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyGrab)); - keyboard_sync_state(); - keyboard_grab(ev->windowID, !_sdl->grabKeyboard()); - return TRUE; + if (!keyboard_sync_state()) + return FALSE; + return keyboard_grab(ev->windowID, !_sdl->grabKeyboard()); } if (ev->scancode == _hotkeyDisconnect) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, disconnecting RDP session", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyDisconnect)); - keyboard_sync_state(); + if (!keyboard_sync_state()) + return FALSE; freerdp_abort_connect_context(_sdl->context()); return TRUE; } @@ -613,7 +617,8 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, minimizing client", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyMinimize)); - keyboard_sync_state(); + if (!keyboard_sync_state()) + return FALSE; return _sdl->setMinimized(); } } diff --git a/client/SDL/SDL3/sdl_touch.cpp b/client/SDL/SDL3/sdl_touch.cpp index c29544ea7..e8aba9eac 100644 --- a/client/SDL/SDL3/sdl_touch.cpp +++ b/client/SDL/SDL3/sdl_touch.cpp @@ -192,12 +192,15 @@ BOOL sdl_handle_mouse_motion(SdlContext* sdl, const SDL_MouseMotionEvent* ev) WINPR_ASSERT(sdl); WINPR_ASSERT(ev); - sdl->getInputChannelContext().mouse_focus(ev->windowID); + if (!sdl->getInputChannelContext().mouse_focus(ev->windowID)) + return FALSE; + const BOOL relative = freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor(); auto x = static_cast(relative ? ev->xrel : ev->x); auto y = static_cast(relative ? ev->yrel : ev->y); - sdl_scale_coordinates(sdl, ev->windowID, &x, &y, TRUE, TRUE); + if (!sdl_scale_coordinates(sdl, ev->windowID, &x, &y, TRUE, TRUE)) + return FALSE; return freerdp_client_send_button_event(sdl->common(), relative, PTR_FLAGS_MOVE, x, y); } @@ -264,7 +267,9 @@ BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev) freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor(); auto x = static_cast(relative ? 0 : ev->x); auto y = static_cast(relative ? 0 : ev->y); - sdl_scale_coordinates(sdl, ev->windowID, &x, &y, TRUE, TRUE); + if (!sdl_scale_coordinates(sdl, ev->windowID, &x, &y, TRUE, TRUE)) + return FALSE; + if ((flags & (~PTR_FLAGS_DOWN)) != 0) return freerdp_client_send_button_event(sdl->common(), relative, flags, x, y); else if ((xflags & (~PTR_XFLAGS_DOWN)) != 0) diff --git a/client/SDL/SDL3/sdl_window.cpp b/client/SDL/SDL3/sdl_window.cpp index 94037a51d..70a244145 100644 --- a/client/SDL/SDL3/sdl_window.cpp +++ b/client/SDL/SDL3/sdl_window.cpp @@ -49,7 +49,7 @@ SdlWindow::SdlWindow(const std::string& title, Sint32 startupX, Sint32 startupY, const int iscale = static_cast(sc * 100.0f); auto w = 100 * width / iscale; auto h = 100 * height / iscale; - resize({ w, h }); + (void)resize({ w, h }); SDL_SetHint(SDL_HINT_APP_NAME, ""); (void)SDL_SyncWindow(_window); } From 4c15ec1b99cc560709ebb22c62ca9630ceaee47f Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 23 Jan 2026 19:45:10 +0100 Subject: [PATCH 08/30] [client,sdl] add nodiscard to functions --- .../dialogs/res/sdl3_resource_manager.hpp | 2 +- .../SDL/SDL3/dialogs/sdl_blend_mode_guard.hpp | 2 +- client/SDL/SDL3/dialogs/sdl_button.cpp | 4 +- client/SDL/SDL3/dialogs/sdl_buttons.cpp | 6 +- client/SDL/SDL3/dialogs/sdl_buttons.hpp | 18 +++--- .../SDL3/dialogs/sdl_connection_dialog.cpp | 57 ++++++++++++------- .../SDL3/dialogs/sdl_connection_dialog.hpp | 38 ++++++------- .../dialogs/sdl_connection_dialog_wrapper.cpp | 12 ++-- .../dialogs/sdl_connection_dialog_wrapper.hpp | 6 +- client/SDL/SDL3/dialogs/sdl_dialogs.hpp | 43 +++++++------- client/SDL/SDL3/dialogs/sdl_input_widget.hpp | 2 +- .../SDL3/dialogs/sdl_input_widget_pair.cpp | 4 +- .../SDL3/dialogs/sdl_input_widget_pair.hpp | 14 ++--- .../dialogs/sdl_input_widget_pair_list.cpp | 14 +++-- .../dialogs/sdl_input_widget_pair_list.hpp | 10 ++-- client/SDL/SDL3/dialogs/sdl_select.cpp | 2 +- client/SDL/SDL3/dialogs/sdl_select_list.cpp | 18 +++--- client/SDL/SDL3/dialogs/sdl_select_list.hpp | 4 +- .../SDL3/dialogs/sdl_selectable_widget.hpp | 6 +- client/SDL/SDL3/dialogs/sdl_widget.cpp | 25 ++++---- client/SDL/SDL3/dialogs/sdl_widget.hpp | 26 +++++---- client/SDL/SDL3/dialogs/sdl_widget_list.cpp | 8 ++- client/SDL/SDL3/dialogs/sdl_widget_list.hpp | 8 +-- client/SDL/SDL3/sdl_clip.cpp | 10 ++-- client/SDL/SDL3/sdl_disp.hpp | 4 +- client/SDL/SDL3/sdl_freerdp.cpp | 14 +++-- client/SDL/SDL3/sdl_kbd.cpp | 16 +++--- client/SDL/SDL3/sdl_monitor.cpp | 15 +++-- client/SDL/SDL3/sdl_pointer.cpp | 10 ++-- client/SDL/SDL3/sdl_utils.hpp | 2 +- client/SDL/common/aad/sdl_webview.hpp | 4 +- client/SDL/common/aad/webview_impl.hpp | 3 +- .../SDL/common/res/sdl_resource_manager.hpp | 13 +++-- client/SDL/common/sdl_prefs.hpp | 7 ++- 34 files changed, 235 insertions(+), 192 deletions(-) diff --git a/client/SDL/SDL3/dialogs/res/sdl3_resource_manager.hpp b/client/SDL/SDL3/dialogs/res/sdl3_resource_manager.hpp index 638435708..93970ae63 100644 --- a/client/SDL/SDL3/dialogs/res/sdl3_resource_manager.hpp +++ b/client/SDL/SDL3/dialogs/res/sdl3_resource_manager.hpp @@ -34,5 +34,5 @@ class SDL3ResourceManager : public SDLResourceManager SDL3ResourceManager& operator=(const SDL3ResourceManager& other) = delete; SDL3ResourceManager& operator=(SDL3ResourceManager&& other) = delete; - static SDL_IOStream* get(const std::string& type, const std::string& id); + [[nodiscard]] static SDL_IOStream* get(const std::string& type, const std::string& id); }; diff --git a/client/SDL/SDL3/dialogs/sdl_blend_mode_guard.hpp b/client/SDL/SDL3/dialogs/sdl_blend_mode_guard.hpp index 1262133f2..2057e7e6b 100644 --- a/client/SDL/SDL3/dialogs/sdl_blend_mode_guard.hpp +++ b/client/SDL/SDL3/dialogs/sdl_blend_mode_guard.hpp @@ -37,7 +37,7 @@ class SdlBlendModeGuard SdlBlendModeGuard& operator=(const SdlBlendModeGuard& other) = delete; SdlBlendModeGuard& operator=(SdlBlendModeGuard&& other) = delete; - bool update(SDL_BlendMode mode); + [[nodiscard]] bool update(SDL_BlendMode mode); private: SDL_BlendMode _restore_mode = SDL_BLENDMODE_INVALID; diff --git a/client/SDL/SDL3/dialogs/sdl_button.cpp b/client/SDL/SDL3/dialogs/sdl_button.cpp index 28704dec8..ef625e1cd 100644 --- a/client/SDL/SDL3/dialogs/sdl_button.cpp +++ b/client/SDL/SDL3/dialogs/sdl_button.cpp @@ -31,8 +31,8 @@ SdlButton::SdlButton(std::shared_ptr& renderer, const std::string& _highlightcolor = { 0xcd, 0xca, 0x35, 0x60 }; _mouseovercolor = { 0x66, 0xff, 0x66, 0x60 }; _fontcolor = { 0xd1, 0xcf, 0xcd, 0xff }; - update_text(label); - update(); + (void)update_text(label); + (void)update(); } SdlButton::SdlButton(SdlButton&& other) noexcept = default; diff --git a/client/SDL/SDL3/dialogs/sdl_buttons.cpp b/client/SDL/SDL3/dialogs/sdl_buttons.cpp index aadb32ab2..f7d54fd37 100644 --- a/client/SDL/SDL3/dialogs/sdl_buttons.cpp +++ b/client/SDL/SDL3/dialogs/sdl_buttons.cpp @@ -95,8 +95,10 @@ bool SdlButtonList::update() { for (auto& btn : _list) { - btn->highlight(btn == _highlighted); - btn->mouseover(btn == _mouseover); + if (!btn->highlight(btn == _highlighted)) + return false; + if (!btn->mouseover(btn == _mouseover)) + return false; if (!btn->update()) return false; diff --git a/client/SDL/SDL3/dialogs/sdl_buttons.hpp b/client/SDL/SDL3/dialogs/sdl_buttons.hpp index 281cf2b63..733380894 100644 --- a/client/SDL/SDL3/dialogs/sdl_buttons.hpp +++ b/client/SDL/SDL3/dialogs/sdl_buttons.hpp @@ -17,17 +17,17 @@ class SdlButtonList SdlButtonList& operator=(const SdlButtonList& other) = delete; SdlButtonList& operator=(SdlButtonList&& other) = delete; - bool populate(std::shared_ptr& renderer, const std::vector& labels, - const std::vector& ids, Sint32 total_width, Sint32 offsetY, Sint32 width, - Sint32 height); + [[nodiscard]] bool populate(std::shared_ptr& renderer, + const std::vector& labels, const std::vector& ids, + Sint32 total_width, Sint32 offsetY, Sint32 width, Sint32 height); - bool update(); - std::shared_ptr get_selected(const SDL_MouseButtonEvent& button); - std::shared_ptr get_selected(float x, float y); + [[nodiscard]] bool update(); + [[nodiscard]] std::shared_ptr get_selected(const SDL_MouseButtonEvent& button); + [[nodiscard]] std::shared_ptr get_selected(float x, float y); - bool set_highlight_next(bool reset = false); - bool set_highlight(size_t index); - bool set_mouseover(float x, float y); + [[nodiscard]] bool set_highlight_next(bool reset = false); + [[nodiscard]] bool set_highlight(size_t index); + [[nodiscard]] bool set_mouseover(float x, float y); void clear(); diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp index a2c935093..904a735a8 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp @@ -34,7 +34,7 @@ static const Uint32 hpadding = 5; SDLConnectionDialog::SDLConnectionDialog(rdpContext* context) : _context(context) { - hide(); + (void)hide(); } SDLConnectionDialog::~SDLConnectionDialog() @@ -109,7 +109,8 @@ bool SDLConnectionDialog::updateMsg(SdlConnectionDialogWrapper::MsgType type) case SdlConnectionDialogWrapper::MSG_WARN: case SdlConnectionDialogWrapper::MSG_ERROR: _type_active = type; - createWindow(); + if (!createWindow()) + return false; break; case SdlConnectionDialogWrapper::MSG_DISCARD: resetTimer(); @@ -192,7 +193,8 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (visible()) { auto& ev = reinterpret_cast(event); - update(); + if (!update()) + return false; switch (event.key.key) { case SDLK_RETURN: @@ -206,7 +208,8 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) } break; case SDLK_TAB: - _buttons.set_highlight_next(); + if (!_buttons.set_highlight_next()) + return false; break; default: break; @@ -220,8 +223,10 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) { auto& ev = reinterpret_cast(event); - _buttons.set_mouseover(event.button.x, event.button.y); - update(); + if (!_buttons.set_mouseover(event.button.x, event.button.y)) + return false; + if (!update()) + return false; return windowID == ev.windowID; } return false; @@ -230,7 +235,8 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (visible()) { auto& ev = reinterpret_cast(event); - update(); + if (!update()) + return false; auto button = _buttons.get_selected(event.button); if (button) @@ -249,7 +255,8 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (visible()) { auto& ev = reinterpret_cast(event); - update(); + if (!update()) + return false; return windowID == ev.windowID; } return false; @@ -258,7 +265,8 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (visible()) { auto& ev = reinterpret_cast(event); - update(); + if (!update()) + return false; return windowID == ev.windowID; } return false; @@ -276,8 +284,10 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) } break; default: - update(); - setModal(); + if (!update()) + return false; + if (!setModal()) + return false; break; } @@ -304,7 +314,8 @@ bool SDLConnectionDialog::createWindow() if (!reset(_title, widget_width, total_height)) return false; - setModal(); + if (!setModal()) + return false; SDL_Color res_bgcolor; switch (_type_active) @@ -369,19 +380,25 @@ bool SDLConnectionDialog::createWindow() #endif widget_cfg_t w{ textcolor, _backgroundcolor, { _renderer, rect } }; - w.widget.set_wrap(true, widget_width); + if (!w.widget.set_wrap(true, widget_width)) + return false; _list.emplace_back(std::move(w)); rect.y += widget_height + vpadding; const std::vector buttonids = { 1 }; const std::vector buttonlabels = { "cancel" }; - _buttons.populate(_renderer, buttonlabels, buttonids, widget_width, - total_height - widget_height - vpadding, - static_cast(widget_width / 2), static_cast(widget_height)); - _buttons.set_highlight(0); + if (!_buttons.populate(_renderer, buttonlabels, buttonids, widget_width, + total_height - widget_height - vpadding, + static_cast(widget_width / 2), + static_cast(widget_height))) + return false; + if (!_buttons.set_highlight(0)) + return false; - SDL_ShowWindow(_window.get()); - SDL_RaiseWindow(_window.get()); + if (!SDL_ShowWindow(_window.get())) + return false; + if (!SDL_RaiseWindow(_window.get())) + return false; return true; } @@ -455,7 +472,7 @@ Uint32 SDLConnectionDialog::timeout(void* pvthis, [[maybe_unused]] SDL_TimerID t [[maybe_unused]] Uint32 intervalMS) { auto self = static_cast(pvthis); - self->hide(); + (void)self->hide(); self->_running = false; return 0; } diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog.hpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog.hpp index 6021af251..051da4843 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog.hpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog.hpp @@ -42,40 +42,40 @@ class SDLConnectionDialog : public SdlWidgetList SDLConnectionDialog& operator=(const SDLConnectionDialog& other) = delete; SDLConnectionDialog& operator=(SDLConnectionDialog&& other) = delete; - bool setTitle(const char* fmt, ...); - bool showInfo(const char* fmt, ...); - bool showWarn(const char* fmt, ...); - bool showError(const char* fmt, ...); + [[nodiscard]] bool setTitle(const char* fmt, ...); + [[nodiscard]] bool showInfo(const char* fmt, ...); + [[nodiscard]] bool showWarn(const char* fmt, ...); + [[nodiscard]] bool showError(const char* fmt, ...); - bool show(); - bool hide(); + [[nodiscard]] bool show(); + [[nodiscard]] bool hide(); - bool running() const; - bool wait(bool ignoreRdpContextQuit = false); + [[nodiscard]] bool running() const; + [[nodiscard]] bool wait(bool ignoreRdpContextQuit = false); - bool handle(const SDL_Event& event); + [[nodiscard]] bool handle(const SDL_Event& event); - bool visible() const override; + [[nodiscard]] bool visible() const override; protected: - bool updateInternal() override; + [[nodiscard]] bool updateInternal() override; private: - bool createWindow(); + [[nodiscard]] bool createWindow(); void destroyWindow(); - bool updateMsg(SdlConnectionDialogWrapper::MsgType type); + [[nodiscard]] bool updateMsg(SdlConnectionDialogWrapper::MsgType type); - bool setModal(); + [[nodiscard]] bool setModal(); - bool show(SdlConnectionDialogWrapper::MsgType type, const char* fmt, va_list ap); - bool show(SdlConnectionDialogWrapper::MsgType type); + [[nodiscard]] bool show(SdlConnectionDialogWrapper::MsgType type, const char* fmt, va_list ap); + [[nodiscard]] bool show(SdlConnectionDialogWrapper::MsgType type); - static std::string print(const char* fmt, va_list ap); - bool setTimer(Uint32 timeoutMS = 15000); + [[nodiscard]] static std::string print(const char* fmt, va_list ap); + [[nodiscard]] bool setTimer(Uint32 timeoutMS = 15000); void resetTimer(); - static Uint32 timeout(void* pvthis, SDL_TimerID timerID, Uint32 intervalMS); + [[nodiscard]] static Uint32 timeout(void* pvthis, SDL_TimerID timerID, Uint32 intervalMS); struct widget_cfg_t { diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.cpp index 57e7e8523..45e775c6a 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.cpp @@ -166,7 +166,7 @@ void SdlConnectionDialogWrapper::handleShow() if (arg.hasTitle() && _connection_dialog) { - _connection_dialog->setTitle(arg.title().c_str()); + (void)_connection_dialog->setTitle(arg.title().c_str()); } if (arg.hasType() && arg.hasMessage()) @@ -175,19 +175,19 @@ void SdlConnectionDialogWrapper::handleShow() { case SdlConnectionDialogWrapper::MSG_INFO: if (_connection_dialog) - _connection_dialog->showInfo(arg.message().c_str()); + (void)_connection_dialog->showInfo(arg.message().c_str()); else WLog_Print(_log, WLOG_INFO, "%s", arg.message().c_str()); break; case SdlConnectionDialogWrapper::MSG_WARN: if (_connection_dialog) - _connection_dialog->showWarn(arg.message().c_str()); + (void)_connection_dialog->showWarn(arg.message().c_str()); else WLog_Print(_log, WLOG_WARN, "%s", arg.message().c_str()); break; case SdlConnectionDialogWrapper::MSG_ERROR: if (_connection_dialog) - _connection_dialog->showError(arg.message().c_str()); + (void)_connection_dialog->showError(arg.message().c_str()); else WLog_Print(_log, WLOG_ERROR, "%s", arg.message().c_str()); break; @@ -199,9 +199,9 @@ void SdlConnectionDialogWrapper::handleShow() if (arg.hasVisibility() && _connection_dialog) { if (arg.visible()) - _connection_dialog->show(); + (void)_connection_dialog->show(); else - _connection_dialog->hide(); + (void)_connection_dialog->hide(); } } } diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.hpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.hpp index db96b689c..ed4665ea2 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.hpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.hpp @@ -57,10 +57,10 @@ class SdlConnectionDialogWrapper void create(rdpContext* context); void destroy(); - bool isRunning() const; - bool isVisible() const; + [[nodiscard]] bool isRunning() const; + [[nodiscard]] bool isVisible() const; - bool handleEvent(const SDL_Event& event); + [[nodiscard]] bool handleEvent(const SDL_Event& event); WINPR_ATTR_FORMAT_ARG(2, 3) void setTitle(WINPR_FORMAT_ARG const char* fmt, ...); diff --git a/client/SDL/SDL3/dialogs/sdl_dialogs.hpp b/client/SDL/SDL3/dialogs/sdl_dialogs.hpp index db15de5c7..627b36934 100644 --- a/client/SDL/SDL3/dialogs/sdl_dialogs.hpp +++ b/client/SDL/SDL3/dialogs/sdl_dialogs.hpp @@ -25,32 +25,35 @@ #include "../sdl_types.hpp" #include "../sdl_utils.hpp" -BOOL sdl_authenticate_ex(freerdp* instance, char** username, char** password, char** domain, - rdp_auth_reason reason); -BOOL sdl_choose_smartcard(freerdp* instance, SmartcardCertInfo** cert_list, DWORD count, - DWORD* choice, BOOL gateway); +[[nodiscard]] BOOL sdl_authenticate_ex(freerdp* instance, char** username, char** password, + char** domain, rdp_auth_reason reason); +[[nodiscard]] BOOL sdl_choose_smartcard(freerdp* instance, SmartcardCertInfo** cert_list, + DWORD count, DWORD* choice, BOOL gateway); -SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, void* userarg); +[[nodiscard]] SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, + void* userarg); -DWORD sdl_verify_certificate_ex(freerdp* instance, const char* host, UINT16 port, - const char* common_name, const char* subject, const char* issuer, - const char* fingerprint, DWORD flags); +[[nodiscard]] DWORD sdl_verify_certificate_ex(freerdp* instance, const char* host, UINT16 port, + const char* common_name, const char* subject, + const char* issuer, const char* fingerprint, + DWORD flags); -DWORD sdl_verify_changed_certificate_ex(freerdp* instance, const char* host, UINT16 port, - const char* common_name, const char* subject, - const char* issuer, const char* new_fingerprint, - const char* old_subject, const char* old_issuer, - const char* old_fingerprint, DWORD flags); +[[nodiscard]] DWORD +sdl_verify_changed_certificate_ex(freerdp* instance, const char* host, UINT16 port, + const char* common_name, const char* subject, const char* issuer, + const char* new_fingerprint, const char* old_subject, + const char* old_issuer, const char* old_fingerprint, DWORD flags); -int sdl_logon_error_info(freerdp* instance, UINT32 data, UINT32 type); +[[nodiscard]] int sdl_logon_error_info(freerdp* instance, UINT32 data, UINT32 type); -BOOL sdl_present_gateway_message(freerdp* instance, UINT32 type, BOOL isDisplayMandatory, - BOOL isConsentMandatory, size_t length, const WCHAR* message); +[[nodiscard]] BOOL sdl_present_gateway_message(freerdp* instance, UINT32 type, + BOOL isDisplayMandatory, BOOL isConsentMandatory, + size_t length, const WCHAR* message); -BOOL sdl_message_dialog_show(const char* title, const char* message, Sint32 flags); -BOOL sdl_cert_dialog_show(const char* title, const char* message); -BOOL sdl_scard_dialog_show(const char* title, Sint32 count, const char** list); -BOOL sdl_auth_dialog_show(const SDL_UserAuthArg* args); +[[nodiscard]] BOOL sdl_message_dialog_show(const char* title, const char* message, Sint32 flags); +[[nodiscard]] BOOL sdl_cert_dialog_show(const char* title, const char* message); +[[nodiscard]] BOOL sdl_scard_dialog_show(const char* title, Sint32 count, const char** list); +[[nodiscard]] BOOL sdl_auth_dialog_show(const SDL_UserAuthArg* args); void sdl_dialogs_init(); void sdl_dialogs_uninit(); diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget.hpp b/client/SDL/SDL3/dialogs/sdl_input_widget.hpp index 92c35279f..26235e79f 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget.hpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget.hpp @@ -36,7 +36,7 @@ class SdlInputWidget : public SdlSelectableWidget ~SdlInputWidget() override; - std::string text() const; + [[nodiscard]] std::string text() const; private: void init(); diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget_pair.cpp b/client/SDL/SDL3/dialogs/sdl_input_widget_pair.cpp index 5b014f6fa..319f6eb88 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget_pair.cpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget_pair.cpp @@ -40,8 +40,8 @@ SdlInputWidgetPair::SdlInputWidgetPair(std::shared_ptr& renderer, static_cast(offset * (height + _vpadding)), static_cast(width), static_cast(height) }) { - _label.update_text(label); - update_input_text(initial); + (void)_label.update_text(label); + (void)update_input_text(initial); } SdlInputWidgetPair::SdlInputWidgetPair(SdlInputWidgetPair&& other) noexcept = default; diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget_pair.hpp b/client/SDL/SDL3/dialogs/sdl_input_widget_pair.hpp index f872c10da..ebbcec0f5 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget_pair.hpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget_pair.hpp @@ -45,22 +45,22 @@ class SdlInputWidgetPair SdlInputWidgetPair& operator=(const SdlInputWidgetPair& other) = delete; SdlInputWidgetPair& operator=(SdlInputWidgetPair&& other) = delete; - bool set_mouseover(bool mouseOver); - bool set_highlight(bool highlight); + [[nodiscard]] bool set_mouseover(bool mouseOver); + [[nodiscard]] bool set_highlight(bool highlight); - bool set_str(const std::string& text); - bool remove_str(size_t count); - bool append_str(const std::string& text); + [[nodiscard]] bool set_str(const std::string& text); + [[nodiscard]] bool remove_str(size_t count); + [[nodiscard]] bool append_str(const std::string& text); [[nodiscard]] const SDL_FRect& input_rect() const; [[nodiscard]] std::string value() const; [[nodiscard]] bool readonly() const; - bool update(); + [[nodiscard]] bool update(); protected: - bool update_input_text(const std::string& txt); + [[nodiscard]] bool update_input_text(const std::string& txt); Uint32 _vpadding = 5; Uint32 _hpadding = 10; diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp b/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp index 261024c57..08b4cfd77 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp @@ -55,10 +55,10 @@ SdlInputWidgetPairList::SdlInputWidgetPairList(const std::string& title, m_list.emplace_back(widget); } - _buttons.populate(_renderer, buttonlabels, buttonids, total_width, - static_cast(input_height), static_cast(widget_width), - static_cast(widget_heigth)); - _buttons.set_highlight(0); + (void)_buttons.populate( + _renderer, buttonlabels, buttonids, total_width, static_cast(input_height), + static_cast(widget_width), static_cast(widget_heigth)); + (void)_buttons.set_highlight(0); m_currentActiveTextInput = selected; } } @@ -211,7 +211,8 @@ int SdlInputWidgetPairList::run(std::vector& result) if (cur) { auto text = SDL_GetClipboardText(); - cur->set_str(text); + if (!cur->set_str(text)) + throw; } } break; @@ -245,7 +246,8 @@ int SdlInputWidgetPairList::run(std::vector& result) throw; } - _buttons.set_mouseover(event.button.x, event.button.y); + if (!_buttons.set_mouseover(event.button.x, event.button.y)) + throw; } break; case SDL_EVENT_MOUSE_BUTTON_DOWN: diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.hpp b/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.hpp index 0b42cca16..5de4762cd 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.hpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.hpp @@ -41,11 +41,11 @@ class SdlInputWidgetPairList : public SdlWidgetList SdlInputWidgetPairList& operator=(const SdlInputWidgetPairList& other) = delete; SdlInputWidgetPairList& operator=(SdlInputWidgetPairList&& other) = delete; - int run(std::vector& result); + [[nodiscard]] int run(std::vector& result); protected: - bool updateInternal() override; - ssize_t get_index(const SDL_MouseButtonEvent& button); + [[nodiscard]] bool updateInternal() override; + [[nodiscard]] ssize_t get_index(const SDL_MouseButtonEvent& button); private: enum @@ -54,9 +54,9 @@ class SdlInputWidgetPairList : public SdlWidgetList INPUT_BUTTON_CANCEL = -2 }; - ssize_t next(ssize_t current); + [[nodiscard]] ssize_t next(ssize_t current); [[nodiscard]] bool valid(ssize_t current) const; - std::shared_ptr get(ssize_t index); + [[nodiscard]] std::shared_ptr get(ssize_t index); std::vector> m_list; ssize_t m_currentActiveTextInput = -1; diff --git a/client/SDL/SDL3/dialogs/sdl_select.cpp b/client/SDL/SDL3/dialogs/sdl_select.cpp index 9de01ae70..ac2490664 100644 --- a/client/SDL/SDL3/dialogs/sdl_select.cpp +++ b/client/SDL/SDL3/dialogs/sdl_select.cpp @@ -37,7 +37,7 @@ SdlSelectWidget::SdlSelectWidget(std::shared_ptr& renderer, const { _backgroundcolor = { 0x69, 0x66, 0x63, 0xff }; _fontcolor = { 0xd1, 0xcf, 0xcd, 0xff }; - update_text(label); + (void)update_text(label); } SdlSelectWidget::~SdlSelectWidget() = default; diff --git a/client/SDL/SDL3/dialogs/sdl_select_list.cpp b/client/SDL/SDL3/dialogs/sdl_select_list.cpp index a5a91b741..a4cebfe15 100644 --- a/client/SDL/SDL3/dialogs/sdl_select_list.cpp +++ b/client/SDL/SDL3/dialogs/sdl_select_list.cpp @@ -23,10 +23,10 @@ SdlSelectList::SdlSelectList(const std::string& title, const std::vector buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL }; const std::vector buttonlabels = { "accept", "cancel" }; - _buttons.populate(_renderer, buttonlabels, buttonids, widget_width, - static_cast(total_height), static_cast(widget_width / 2), - static_cast(widget_height)); - _buttons.set_highlight(0); + (void)_buttons.populate( + _renderer, buttonlabels, buttonids, widget_width, static_cast(total_height), + static_cast(widget_width / 2), static_cast(widget_height)); + (void)_buttons.set_highlight(0); } } @@ -111,7 +111,8 @@ int SdlSelectList::run() throw; } - _buttons.set_mouseover(event.button.x, event.button.y); + if (!_buttons.set_mouseover(event.button.x, event.button.y)) + throw; } break; case SDL_EVENT_MOUSE_BUTTON_DOWN: @@ -147,7 +148,8 @@ int SdlSelectList::run() throw; } - update(); + if (!update()) + throw; } } catch (...) @@ -186,7 +188,7 @@ void SdlSelectList::reset_mouseover() { for (auto& cur : _list) { - cur.mouseover(false); + (void)cur.mouseover(false); } } @@ -194,6 +196,6 @@ void SdlSelectList::reset_highlight() { for (auto& cur : _list) { - cur.highlight(false); + (void)cur.highlight(false); } } diff --git a/client/SDL/SDL3/dialogs/sdl_select_list.hpp b/client/SDL/SDL3/dialogs/sdl_select_list.hpp index d611fd029..53d406ff8 100644 --- a/client/SDL/SDL3/dialogs/sdl_select_list.hpp +++ b/client/SDL/SDL3/dialogs/sdl_select_list.hpp @@ -21,10 +21,10 @@ class SdlSelectList : public SdlWidgetList SdlSelectList& operator=(const SdlSelectList& other) = delete; SdlSelectList& operator=(SdlSelectList&& other) = delete; - int run(); + [[nodiscard]] int run(); protected: - bool updateInternal() override; + [[nodiscard]] bool updateInternal() override; private: enum diff --git a/client/SDL/SDL3/dialogs/sdl_selectable_widget.hpp b/client/SDL/SDL3/dialogs/sdl_selectable_widget.hpp index 53e6ed8a8..06e2c8e63 100644 --- a/client/SDL/SDL3/dialogs/sdl_selectable_widget.hpp +++ b/client/SDL/SDL3/dialogs/sdl_selectable_widget.hpp @@ -36,11 +36,11 @@ class SdlSelectableWidget : public SdlWidget SdlSelectableWidget& operator=(const SdlSelectableWidget& other) = delete; SdlSelectableWidget& operator=(SdlSelectableWidget&& other) = delete; - bool highlight(bool enable); - bool mouseover(bool enable); + [[nodiscard]] bool highlight(bool enable); + [[nodiscard]] bool mouseover(bool enable); protected: - bool updateInternal() override; + [[nodiscard]] bool updateInternal() override; SDL_Color _highlightcolor = { 0xcd, 0xca, 0x35, 0x60 }; SDL_Color _mouseovercolor = { 0x66, 0xff, 0x66, 0x60 }; diff --git a/client/SDL/SDL3/dialogs/sdl_widget.cpp b/client/SDL/SDL3/dialogs/sdl_widget.cpp index 494427868..50630d4d5 100644 --- a/client/SDL/SDL3/dialogs/sdl_widget.cpp +++ b/client/SDL/SDL3/dialogs/sdl_widget.cpp @@ -51,12 +51,12 @@ SdlWidget::SdlWidget(std::shared_ptr& renderer, const SDL_FRect& r auto ops = SDL3ResourceManager::get(SDLResourceManager::typeFonts(), "OpenSans-VariableFont_wdth,wght.ttf"); if (!ops) - widget_log_error(false, "SDLResourceManager::get"); + (void)widget_log_error(false, "SDLResourceManager::get"); else { _font = std::shared_ptr(TTF_OpenFontIO(ops, true, 64), TTF_CloseFont); if (!_font) - widget_log_error(false, "TTF_OpenFontRW"); + (void)widget_log_error(false, "TTF_OpenFontRW"); } } @@ -72,7 +72,7 @@ SdlWidget::SdlWidget(std::shared_ptr& renderer, const SDL_FRect& r _image = std::shared_ptr(IMG_LoadTexture_IO(renderer.get(), ops, 1), SDL_DestroyTexture); if (!_image) - widget_log_error(false, "IMG_LoadTexture_IO"); + (void)widget_log_error(false, "IMG_LoadTexture_IO"); } } #endif @@ -95,7 +95,7 @@ std::shared_ptr SdlWidget::render_text(const std::string& text, SDL TTF_RenderText_Blended(_font.get(), text.c_str(), 0, fgcolor), SDL_DestroySurface); if (!surface) { - widget_log_error(false, "TTF_RenderText_Blended"); + (void)widget_log_error(false, "TTF_RenderText_Blended"); return nullptr; } @@ -103,13 +103,13 @@ std::shared_ptr SdlWidget::render_text(const std::string& text, SDL SDL_CreateTextureFromSurface(_renderer.get(), surface.get()), SDL_DestroyTexture); if (!texture) { - widget_log_error(false, "SDL_CreateTextureFromSurface"); + (void)widget_log_error(false, "SDL_CreateTextureFromSurface"); return nullptr; } if (!_engine) { - widget_log_error(false, "TTF_CreateRendererTextEngine"); + (void)widget_log_error(false, "TTF_CreateRendererTextEngine"); return nullptr; } @@ -118,14 +118,14 @@ std::shared_ptr SdlWidget::render_text(const std::string& text, SDL if (!txt) { - widget_log_error(false, "TTF_CreateText"); + (void)widget_log_error(false, "TTF_CreateText"); return nullptr; } int w = 0; int h = 0; if (!TTF_GetTextSize(txt.get(), &w, &h)) { - widget_log_error(false, "TTF_GetTextSize"); + (void)widget_log_error(false, "TTF_GetTextSize"); return nullptr; } @@ -170,7 +170,7 @@ std::shared_ptr SdlWidget::render_text_wrapped(const std::string& t SDL_DestroySurface); if (!surface) { - widget_log_error(false, "TTF_RenderText_Blended"); + (void)widget_log_error(false, "TTF_RenderText_Blended"); return nullptr; } @@ -181,7 +181,7 @@ std::shared_ptr SdlWidget::render_text_wrapped(const std::string& t SDL_CreateTextureFromSurface(_renderer.get(), surface.get()), SDL_DestroyTexture); if (!texture) { - widget_log_error(false, "SDL_CreateTextureFromSurface"); + (void)widget_log_error(false, "SDL_CreateTextureFromSurface"); return nullptr; } @@ -313,7 +313,10 @@ bool SdlWidget::update_text(const std::string& text) auto w = SDL_GetNumberProperty(propId, SDL_PROP_TEXTURE_WIDTH_NUMBER, -1); auto h = SDL_GetNumberProperty(propId, SDL_PROP_TEXTURE_HEIGHT_NUMBER, -1); if (w < 0 || h < 0) - widget_log_error(false, "SDL_GetTextureProperties"); + { + if (!widget_log_error(false, "SDL_GetTextureProperties")) + return false; + } src.w = static_cast(w); src.h = static_cast(h); } diff --git a/client/SDL/SDL3/dialogs/sdl_widget.hpp b/client/SDL/SDL3/dialogs/sdl_widget.hpp index 38305d44f..7f3f44759 100644 --- a/client/SDL/SDL3/dialogs/sdl_widget.hpp +++ b/client/SDL/SDL3/dialogs/sdl_widget.hpp @@ -59,19 +59,19 @@ class SdlWidget SdlWidget& operator=(const SdlWidget& other) = delete; SdlWidget& operator=(SdlWidget&& other) = delete; - bool fill(SDL_Color color) const; - bool fill(const std::vector& colors) const; - bool update_text(const std::string& text); + [[nodiscard]] bool fill(SDL_Color color) const; + [[nodiscard]] bool fill(const std::vector& colors) const; + [[nodiscard]] bool update_text(const std::string& text); [[nodiscard]] bool wrap() const; - bool set_wrap(bool wrap = true, size_t width = 0); + [[nodiscard]] bool set_wrap(bool wrap = true, size_t width = 0); [[nodiscard]] const SDL_FRect& rect() const; - bool update(); + [[nodiscard]] bool update(); #define widget_log_error(res, what) SdlWidget::error_ex(res, what, __FILE__, __LINE__, __func__) - static bool error_ex(bool success, const char* what, const char* file, size_t line, - const char* fkt); + [[nodiscard]] static bool error_ex(bool success, const char* what, const char* file, + size_t line, const char* fkt); protected: std::shared_ptr _renderer; @@ -83,11 +83,13 @@ class SdlWidget virtual bool updateInternal(); private: - bool draw_rect(const SDL_FRect& rect, SDL_Color color) const; - std::shared_ptr render_text(const std::string& text, SDL_Color fgcolor, - SDL_FRect& src, SDL_FRect& dst) const; - std::shared_ptr render_text_wrapped(const std::string& text, SDL_Color fgcolor, - SDL_FRect& src, SDL_FRect& dst) const; + [[nodiscard]] bool draw_rect(const SDL_FRect& rect, SDL_Color color) const; + [[nodiscard]] std::shared_ptr + render_text(const std::string& text, SDL_Color fgcolor, SDL_FRect& src, SDL_FRect& dst) const; + [[nodiscard]] std::shared_ptr render_text_wrapped(const std::string& text, + SDL_Color fgcolor, + SDL_FRect& src, + SDL_FRect& dst) const; std::shared_ptr _font = nullptr; std::shared_ptr _image = nullptr; diff --git a/client/SDL/SDL3/dialogs/sdl_widget_list.cpp b/client/SDL/SDL3/dialogs/sdl_widget_list.cpp index 15fd15fd2..ff2a8ce65 100644 --- a/client/SDL/SDL3/dialogs/sdl_widget_list.cpp +++ b/client/SDL/SDL3/dialogs/sdl_widget_list.cpp @@ -14,7 +14,7 @@ bool SdlWidgetList::reset(const std::string& title, size_t width, size_t height) _renderer = std::shared_ptr(renderer, SDL_DestroyRenderer); _window = std::shared_ptr(window, SDL_DestroyWindow); if (!rc) - widget_log_error(rc, "SDL_CreateWindowAndRenderer"); + (void)widget_log_error(rc, "SDL_CreateWindowAndRenderer"); return rc; } @@ -47,8 +47,10 @@ bool SdlWidgetList::update() if (!visible()) return true; - clearWindow(); - updateInternal(); + if (!clearWindow()) + return false; + if (!updateInternal()) + return false; if (!_buttons.update()) return false; auto rc = SDL_RenderPresent(_renderer.get()); diff --git a/client/SDL/SDL3/dialogs/sdl_widget_list.hpp b/client/SDL/SDL3/dialogs/sdl_widget_list.hpp index 768f331c7..ab3a582f6 100644 --- a/client/SDL/SDL3/dialogs/sdl_widget_list.hpp +++ b/client/SDL/SDL3/dialogs/sdl_widget_list.hpp @@ -18,14 +18,14 @@ class SdlWidgetList SdlWidgetList& operator=(SdlWidgetList&& other) = delete; virtual ~SdlWidgetList(); - virtual bool reset(const std::string& title, size_t width, size_t height); + [[nodiscard]] virtual bool reset(const std::string& title, size_t width, size_t height); [[nodiscard]] virtual bool visible() const; protected: - bool update(); - virtual bool clearWindow(); - virtual bool updateInternal() = 0; + [[nodiscard]] bool update(); + [[nodiscard]] virtual bool clearWindow(); + [[nodiscard]] virtual bool updateInternal() = 0; std::shared_ptr _window; std::shared_ptr _renderer; diff --git a/client/SDL/SDL3/sdl_clip.cpp b/client/SDL/SDL3/sdl_clip.cpp index d7eb1aab5..b3768ccc5 100644 --- a/client/SDL/SDL3/sdl_clip.cpp +++ b/client/SDL/SDL3/sdl_clip.cpp @@ -37,7 +37,7 @@ // NOLINTNEXTLINE(bugprone-suspicious-missing-comma) const char mime_text_utf8[] = mime_text_plain ";charset=utf-8"; -static const std::vector& s_mime_text() +[[nodiscard]] static const std::vector& s_mime_text() { static std::vector values; if (values.empty()) @@ -58,7 +58,7 @@ static const char s_mime_html[] = "text/html"; #define BMP_MIME_LIST "image/bmp", "image/x-bmp", "image/x-MS-bmp", "image/x-win-bitmap" -static const std::vector& s_mime_bitmap() +[[nodiscard]] static const std::vector& s_mime_bitmap() { static std::vector values; if (values.empty()) @@ -68,7 +68,7 @@ static const std::vector& s_mime_bitmap() return values; } -static const std::vector& s_mime_image() +[[nodiscard]] static const std::vector& s_mime_image() { static std::vector values; if (values.empty()) @@ -144,7 +144,7 @@ sdlClip::~sdlClip() { cliprdr_file_context_free(_file); ClipboardDestroy(_system); - (void)CloseHandle(_event); + std::ignore = CloseHandle(_event); } bool sdlClip::init(CliprdrClientContext* clip) @@ -876,7 +876,7 @@ const void* sdlClip::ClipDataCb(void* userdata, const char* mime_type, size_t* s clip->_request_queue.pop(); if (clip->_request_queue.empty()) - (void)ResetEvent(clip->_event); + std::ignore = ResetEvent(clip->_event); if (request.success()) { diff --git a/client/SDL/SDL3/sdl_disp.hpp b/client/SDL/SDL3/sdl_disp.hpp index b62b1b8e9..b48f10e79 100644 --- a/client/SDL/SDL3/sdl_disp.hpp +++ b/client/SDL/SDL3/sdl_disp.hpp @@ -57,8 +57,8 @@ class sdlDispContext [[nodiscard]] bool addTimer(); - bool updateMonitor(SDL_WindowID id); - bool updateMonitors(SDL_EventType type, SDL_DisplayID displayID); + [[nodiscard]] bool updateMonitor(SDL_WindowID id); + [[nodiscard]] bool updateMonitors(SDL_EventType type, SDL_DisplayID displayID); [[nodiscard]] static UINT DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 281fce4c9..8b6e015ef 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -207,7 +207,8 @@ static int sdl_run(SdlContext* sdl) SDLConnectionDialogHider hider(sdl); auto title = static_cast(windowEvent.user.data1); auto msg = static_cast(windowEvent.user.data2); - sdl_cert_dialog_show(title, msg); + if (!sdl_cert_dialog_show(title, msg)) + return -1; } break; case SDL_EVENT_USER_SHOW_DIALOG: @@ -215,7 +216,8 @@ static int sdl_run(SdlContext* sdl) SDLConnectionDialogHider hider(sdl); auto title = static_cast(windowEvent.user.data1); auto msg = static_cast(windowEvent.user.data2); - sdl_message_dialog_show(title, msg, windowEvent.user.code); + if (!sdl_message_dialog_show(title, msg, windowEvent.user.code)) + return -1; } break; case SDL_EVENT_USER_SCARD_DIALOG: @@ -223,14 +225,16 @@ static int sdl_run(SdlContext* sdl) SDLConnectionDialogHider hider(sdl); auto title = static_cast(windowEvent.user.data1); auto msg = static_cast(windowEvent.user.data2); - sdl_scard_dialog_show(title, windowEvent.user.code, msg); + if (!sdl_scard_dialog_show(title, windowEvent.user.code, msg)) + return -1; } break; case SDL_EVENT_USER_AUTH_DIALOG: { SDLConnectionDialogHider hider(sdl); - sdl_auth_dialog_show( - reinterpret_cast(windowEvent.padding)); + if (!sdl_auth_dialog_show( + reinterpret_cast(windowEvent.padding))) + return -1; } break; case SDL_EVENT_USER_UPDATE: diff --git a/client/SDL/SDL3/sdl_kbd.cpp b/client/SDL/SDL3/sdl_kbd.cpp index c5c7bdfba..a0c171d1b 100644 --- a/client/SDL/SDL3/sdl_kbd.cpp +++ b/client/SDL/SDL3/sdl_kbd.cpp @@ -283,7 +283,7 @@ static const scancode_entry_t map[] = { ENTRY(SDL_SCANCODE_MEDIA_FAST_FORWARD, RDP_SCANCODE_UNKNOWN) }; -static UINT32 sdl_get_kbd_flags() +[[nodiscard]] static UINT32 sdl_get_kbd_flags() { UINT32 flags = 0; @@ -374,7 +374,7 @@ BOOL sdlInput::keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 return TRUE; } -static const std::map& getSdlMap() +[[nodiscard]] static const std::map& getSdlMap() { static std::map s_map = { { "KMOD_LSHIFT", SDL_KMOD_LSHIFT }, { "KMOD_RSHIFT", SDL_KMOD_RSHIFT }, @@ -399,7 +399,7 @@ static const std::map& getSdlMap() return s_map; } -static std::string modbyvalue(uint32_t val) +[[nodiscard]] static std::string modbyvalue(uint32_t val) { for (const auto& v : getSdlMap()) { @@ -411,7 +411,7 @@ static std::string modbyvalue(uint32_t val) return "KMOD_UNKNONW"; } -static std::string masktostr(uint32_t mask) +[[nodiscard]] static std::string masktostr(uint32_t mask) { if (mask == 0) return ""; @@ -470,7 +470,7 @@ uint32_t sdlInput::prefToMask() return mod; } -static const char* sdl_scancode_name(Uint32 scancode) +[[nodiscard]] static const char* sdl_scancode_name(Uint32 scancode) { for (const auto& cur : map) { @@ -481,7 +481,7 @@ static const char* sdl_scancode_name(Uint32 scancode) return "SDL_SCANCODE_UNKNOWN"; } -static Uint32 sdl_scancode_val(const char* scancodeName) +[[nodiscard]] static Uint32 sdl_scancode_val(const char* scancodeName) { for (const auto& cur : map) { @@ -493,7 +493,7 @@ static Uint32 sdl_scancode_val(const char* scancodeName) } #if defined(WITH_DEBUG_SDL_KBD_EVENTS) -static const char* sdl_rdp_scancode_name(UINT32 scancode) +[[nodiscard]] static const char* sdl_rdp_scancode_name(UINT32 scancode) { for (const auto& cur : map) { @@ -504,7 +504,7 @@ static const char* sdl_rdp_scancode_name(UINT32 scancode) return "RDP_SCANCODE_UNKNOWN"; } -static UINT32 sdl_rdp_scancode_val(const char* scancodeName) +[[nodiscard]] static UINT32 sdl_rdp_scancode_val(const char* scancodeName) { for (const auto& cur : map) { diff --git a/client/SDL/SDL3/sdl_monitor.cpp b/client/SDL/SDL3/sdl_monitor.cpp index 2f8840692..9b8b78031 100644 --- a/client/SDL/SDL3/sdl_monitor.cpp +++ b/client/SDL/SDL3/sdl_monitor.cpp @@ -81,7 +81,8 @@ int sdl_list_monitors([[maybe_unused]] SdlContext* sdl) return 0; } -static BOOL sdl_apply_mon_max_size(SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight) +[[nodiscard]] static BOOL sdl_apply_mon_max_size(SdlContext* sdl, UINT32* pMaxWidth, + UINT32* pMaxHeight) { int32_t left = 0; int32_t right = 0; @@ -113,7 +114,7 @@ static BOOL sdl_apply_mon_max_size(SdlContext* sdl, UINT32* pMaxWidth, UINT32* p return TRUE; } -static BOOL sdl_apply_max_size(SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight) +[[nodiscard]] static BOOL sdl_apply_max_size(SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight) { WINPR_ASSERT(sdl); WINPR_ASSERT(pMaxWidth); @@ -170,14 +171,15 @@ static BOOL sdl_apply_max_size(SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxH return TRUE; } -static Uint32 scale(Uint32 val, float scale) +[[nodiscard]] static Uint32 scale(Uint32 val, float scale) { const auto dval = static_cast(val); const auto sval = dval / scale; return static_cast(sval); } -static BOOL sdl_apply_monitor_properties(rdpMonitor& monitor, SDL_DisplayID id, bool isPrimary) +[[nodiscard]] static BOOL sdl_apply_monitor_properties(rdpMonitor& monitor, SDL_DisplayID id, + bool isPrimary) { float dpi = SDL_GetDisplayContentScale(id); @@ -248,7 +250,7 @@ static BOOL sdl_apply_monitor_properties(rdpMonitor& monitor, SDL_DisplayID id, return TRUE; } -static BOOL sdl_apply_display_properties(SdlContext* sdl) +[[nodiscard]] static BOOL sdl_apply_display_properties(SdlContext* sdl) { WINPR_ASSERT(sdl); @@ -285,7 +287,8 @@ static BOOL sdl_apply_display_properties(SdlContext* sdl) monitors.size()); } -static BOOL sdl_detect_single_window(SdlContext* sdl, UINT32* pMaxWidth, UINT32* pMaxHeight) +[[nodiscard]] static BOOL sdl_detect_single_window(SdlContext* sdl, UINT32* pMaxWidth, + UINT32* pMaxHeight) { WINPR_ASSERT(sdl); WINPR_ASSERT(pMaxWidth); diff --git a/client/SDL/SDL3/sdl_pointer.cpp b/client/SDL/SDL3/sdl_pointer.cpp index 3fdd73d61..c8793bd13 100644 --- a/client/SDL/SDL3/sdl_pointer.cpp +++ b/client/SDL/SDL3/sdl_pointer.cpp @@ -37,7 +37,7 @@ typedef struct void* data; } sdlPointer; -static BOOL sdl_Pointer_New(rdpContext* context, rdpPointer* pointer) +[[nodiscard]] static BOOL sdl_Pointer_New(rdpContext* context, rdpPointer* pointer) { auto ptr = reinterpret_cast(pointer); @@ -90,14 +90,14 @@ static void sdl_Pointer_Free(rdpContext* context, rdpPointer* pointer) } } -static BOOL sdl_Pointer_SetDefault(rdpContext* context) +[[nodiscard]] static BOOL sdl_Pointer_SetDefault(rdpContext* context) { WINPR_UNUSED(context); return sdl_push_user_event(SDL_EVENT_USER_POINTER_DEFAULT); } -static BOOL sdl_Pointer_Set(rdpContext* context, rdpPointer* pointer) +[[nodiscard]] static BOOL sdl_Pointer_Set(rdpContext* context, rdpPointer* pointer) { WINPR_UNUSED(context); return sdl_push_user_event(SDL_EVENT_USER_POINTER_SET, pointer); @@ -178,14 +178,14 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) return TRUE; } -static BOOL sdl_Pointer_SetNull(rdpContext* context) +[[nodiscard]] static BOOL sdl_Pointer_SetNull(rdpContext* context) { WINPR_UNUSED(context); return sdl_push_user_event(SDL_EVENT_USER_POINTER_NULL); } -static BOOL sdl_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y) +[[nodiscard]] static BOOL sdl_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y) { WINPR_UNUSED(context); WINPR_ASSERT(context); diff --git a/client/SDL/SDL3/sdl_utils.hpp b/client/SDL/SDL3/sdl_utils.hpp index bd13dd6e2..be00920f6 100644 --- a/client/SDL/SDL3/sdl_utils.hpp +++ b/client/SDL/SDL3/sdl_utils.hpp @@ -96,7 +96,7 @@ namespace sdl::utils SCALE_MODE_WAYLAND }; - HighDpiScaleMode platformScaleMode(); + [[nodiscard]] HighDpiScaleMode platformScaleMode(); [[nodiscard]] std::string windowTitle(const rdpSettings* settings); diff --git a/client/SDL/common/aad/sdl_webview.hpp b/client/SDL/common/aad/sdl_webview.hpp index 8ece62d25..80a7e8221 100644 --- a/client/SDL/common/aad/sdl_webview.hpp +++ b/client/SDL/common/aad/sdl_webview.hpp @@ -26,8 +26,8 @@ extern "C" { #endif - BOOL sdl_webview_get_access_token(freerdp* instance, AccessTokenType tokenType, char** token, - size_t count, ...); + [[nodiscard]] BOOL sdl_webview_get_access_token(freerdp* instance, AccessTokenType tokenType, + char** token, size_t count, ...); #ifdef __cplusplus } diff --git a/client/SDL/common/aad/webview_impl.hpp b/client/SDL/common/aad/webview_impl.hpp index 25bca3c0a..9e48de21c 100644 --- a/client/SDL/common/aad/webview_impl.hpp +++ b/client/SDL/common/aad/webview_impl.hpp @@ -21,4 +21,5 @@ #include -bool webview_impl_run(const std::string& title, const std::string& url, std::string& code); +[[nodiscard]] bool webview_impl_run(const std::string& title, const std::string& url, + std::string& code); diff --git a/client/SDL/common/res/sdl_resource_manager.hpp b/client/SDL/common/res/sdl_resource_manager.hpp index 54cca16bf..a85b68bbc 100644 --- a/client/SDL/common/res/sdl_resource_manager.hpp +++ b/client/SDL/common/res/sdl_resource_manager.hpp @@ -33,20 +33,21 @@ class SDLResourceManager SDLResourceManager operator=(const SDLResourceManager& other) = delete; SDLResourceManager& operator=(SDLResourceManager&& other) = delete; - static std::string typeFonts(); - static std::string typeImages(); + [[nodiscard]] static std::string typeFonts(); + [[nodiscard]] static std::string typeImages(); protected: static void insert(const std::string& type, const std::string& id, const std::vector& data); - static const std::vector* data(const std::string& type, const std::string& id); - static std::string filename(const std::string& type, const std::string& id); + [[nodiscard]] static const std::vector* data(const std::string& type, + const std::string& id); + [[nodiscard]] static std::string filename(const std::string& type, const std::string& id); - static bool useCompiledResources(); + [[nodiscard]] static bool useCompiledResources(); private: - static std::map>& resources(); + [[nodiscard]] static std::map>& resources(); #if defined(SDL_USE_COMPILED_RESOURCES) static void init(); // implemented in generated file #endif diff --git a/client/SDL/common/sdl_prefs.hpp b/client/SDL/common/sdl_prefs.hpp index 63ea0bdd6..aba0b4294 100644 --- a/client/SDL/common/sdl_prefs.hpp +++ b/client/SDL/common/sdl_prefs.hpp @@ -27,7 +27,7 @@ class SdlPref { public: - static std::shared_ptr + [[nodiscard]] static std::shared_ptr instance(const std::string& name = SdlPref::get_default_file(false)); [[nodiscard]] std::string get_pref_file(bool systemConfigOnly = false) const; @@ -63,6 +63,7 @@ class SdlPref [[nodiscard]] bool is_user_config_enabled() const; - static std::string get_default_file(bool systemConfigOnly); - static std::string item_to_str(WINPR_JSON* item, const std::string& fallback = ""); + [[nodiscard]] static std::string get_default_file(bool systemConfigOnly); + [[nodiscard]] static std::string item_to_str(WINPR_JSON* item, + const std::string& fallback = ""); }; From 2bbe3310ba6dd3ef4772404d7d7cdc359c940de8 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Fri, 23 Jan 2026 20:42:32 +0100 Subject: [PATCH 09/30] [warnings] fix compiler and clang-tidy issues --- .../SDL3/dialogs/sdl_connection_dialog.cpp | 9 ++-- client/SDL/SDL3/dialogs/sdl_widget.cpp | 2 +- client/SDL/SDL3/sdl_clip.cpp | 4 -- client/SDL/SDL3/sdl_clip.hpp | 5 +-- client/SDL/SDL3/sdl_context.cpp | 4 -- client/SDL/SDL3/sdl_context.hpp | 16 +++---- client/SDL/SDL3/sdl_utils.cpp | 45 ++++++++++--------- client/SDL/SDL3/sdl_utils.hpp | 2 +- 8 files changed, 39 insertions(+), 48 deletions(-) diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp index 904a735a8..e97ce62f4 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp @@ -354,16 +354,15 @@ bool SDLConnectionDialog::createWindow() break; } - const auto height = (total_height - 3ul * vpadding) / 2ul; - SDL_FRect iconRect{ hpadding, vpadding, widget_width / 4ul - 2ul * hpadding, - static_cast(height) }; + const auto height = (total_height - 3.0f * vpadding) / 2.0f; + SDL_FRect iconRect{ hpadding, vpadding, widget_width / 4.0f - 2.0f * hpadding, height }; widget_cfg_t icon{ textcolor, res_bgcolor, { _renderer, iconRect, SDL3ResourceManager::get(SDLResourceManager::typeImages(), res_name) } }; _list.emplace_back(std::move(icon)); - iconRect.y += static_cast(height); + iconRect.y += height; widget_cfg_t logo{ textcolor, _backgroundcolor, @@ -372,7 +371,7 @@ bool SDLConnectionDialog::createWindow() "FreeRDP_Icon.svg") } }; _list.emplace_back(std::move(logo)); - SDL_FRect rect = { widget_width / 4ul, vpadding, widget_width * 3ul / 4ul, + SDL_FRect rect = { widget_width / 4.0f, vpadding, widget_width * 3.0f / 4.0f, total_height - 3ul * vpadding - widget_height }; #else SDL_FRect rect = { hpadding, vpadding, widget_width - 2ul * hpadding, diff --git a/client/SDL/SDL3/dialogs/sdl_widget.cpp b/client/SDL/SDL3/dialogs/sdl_widget.cpp index 50630d4d5..d0cbaefc8 100644 --- a/client/SDL/SDL3/dialogs/sdl_widget.cpp +++ b/client/SDL/SDL3/dialogs/sdl_widget.cpp @@ -69,7 +69,7 @@ SdlWidget::SdlWidget(std::shared_ptr& renderer, const SDL_FRect& r { if (ops) { - _image = std::shared_ptr(IMG_LoadTexture_IO(renderer.get(), ops, 1), + _image = std::shared_ptr(IMG_LoadTexture_IO(renderer.get(), ops, true), SDL_DestroyTexture); if (!_image) (void)widget_log_error(false, "IMG_LoadTexture_IO"); diff --git a/client/SDL/SDL3/sdl_clip.cpp b/client/SDL/SDL3/sdl_clip.cpp index b3768ccc5..172576a3b 100644 --- a/client/SDL/SDL3/sdl_clip.cpp +++ b/client/SDL/SDL3/sdl_clip.cpp @@ -964,10 +964,6 @@ ClipRequest::ClipRequest(UINT32 format, const std::string& mime) { } -ClipRequest::~ClipRequest() -{ -} - uint32_t ClipRequest::format() const { return _format; diff --git a/client/SDL/SDL3/sdl_clip.hpp b/client/SDL/SDL3/sdl_clip.hpp index d5531e4fa..e4497e111 100644 --- a/client/SDL/SDL3/sdl_clip.hpp +++ b/client/SDL/SDL3/sdl_clip.hpp @@ -41,7 +41,7 @@ class ClipRequest ClipRequest(UINT32 format, const std::string& mime); ClipRequest(const ClipRequest& other) = default; ClipRequest(ClipRequest&& other) = default; - virtual ~ClipRequest(); + ~ClipRequest() = default; ClipRequest& operator=(const ClipRequest& other) = delete; ClipRequest& operator=(ClipRequest&& other) = delete; @@ -130,14 +130,13 @@ class sdlClip [[nodiscard]] static bool mime_is_bmp(const std::string& mime); [[nodiscard]] static bool mime_is_html(const std::string& mime); - private: SdlContext* _sdl = nullptr; CliprdrFileContext* _file = nullptr; CliprdrClientContext* _ctx = nullptr; wLog* _log = nullptr; wClipboard* _system = nullptr; std::atomic _sync = false; - HANDLE _event; + HANDLE _event = nullptr; Uint64 _last_timestamp = 0; std::vector _serverFormats; diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index 16f3a4fbe..962dbb8e7 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -61,10 +61,6 @@ SdlContext::SdlContext(rdpContext* context) /* TODO: Client display set up */ } -SdlContext::~SdlContext() -{ -} - void SdlContext::setHasCursor(bool val) { this->_cursor_visible = val; diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index a19dc8ab6..0c25e3377 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -46,7 +46,7 @@ class SdlContext explicit SdlContext(rdpContext* context); SdlContext(const SdlContext& other) = delete; SdlContext(SdlContext&& other) = delete; - virtual ~SdlContext(); + ~SdlContext() = default; SdlContext& operator=(const SdlContext& other) = delete; SdlContext& operator=(SdlContext&& other) = delete; @@ -147,9 +147,9 @@ class SdlContext std::atomic _connected = false; bool _cursor_visible = true; rdpPointer* _cursor = nullptr; - std::vector _monitorIds{}; - std::mutex _queue_mux{}; - std::queue> _queue{}; + std::vector _monitorIds; + std::mutex _queue_mux; + std::queue> _queue; /* SDL */ bool _fullscreen = false; bool _resizeable = false; @@ -159,7 +159,7 @@ class SdlContext std::atomic _rdpThreadRunning = false; SDL_PixelFormat _sdlPixelFormat = SDL_PIXELFORMAT_UNKNOWN; - CriticalSection _critical{}; + CriticalSection _critical; using SDLSurfacePtr = std::unique_ptr; @@ -171,8 +171,8 @@ class SdlContext SdlConnectionDialogWrapper _dialog; - std::map _windows{}; + std::map _windows; - WinPREvent _windowsCreatedEvent{}; - std::thread _thread{}; + WinPREvent _windowsCreatedEvent; + std::thread _thread; }; diff --git a/client/SDL/SDL3/sdl_utils.cpp b/client/SDL/SDL3/sdl_utils.cpp index e827fe4a9..83129eeae 100644 --- a/client/SDL/SDL3/sdl_utils.cpp +++ b/client/SDL/SDL3/sdl_utils.cpp @@ -530,29 +530,30 @@ namespace sdl::error } return nullptr; } -} -int sdl::error::errorToExitCode(DWORD error) -{ - auto entry = mapEntryByError(error); - if (entry) - return entry->code; + int errorToExitCode(DWORD error) + { + auto entry = mapEntryByError(error); + if (entry) + return entry->code; - return CONN_FAILED; -} + return CONN_FAILED; + } -const char* sdl::error::errorToExitCodeTag(UINT32 error) -{ - auto entry = mapEntryByError(error); - if (entry) - return entry->code_tag; - return nullptr; -} + const char* errorToExitCodeTag(UINT32 error) + { + auto entry = mapEntryByError(error); + if (entry) + return entry->code_tag; + return nullptr; + } -const char* sdl::error::exitCodeToTag(int code) -{ - auto entry = mapEntryByCode(code); - if (entry) - return entry->code_tag; - return nullptr; -} + const char* exitCodeToTag(int code) + { + auto entry = mapEntryByCode(code); + if (entry) + return entry->code_tag; + return nullptr; + } + +} // namespace sdl::error diff --git a/client/SDL/SDL3/sdl_utils.hpp b/client/SDL/SDL3/sdl_utils.hpp index be00920f6..8fa10f30f 100644 --- a/client/SDL/SDL3/sdl_utils.hpp +++ b/client/SDL/SDL3/sdl_utils.hpp @@ -177,4 +177,4 @@ namespace sdl::error [[nodiscard]] int errorToExitCode(DWORD error); [[nodiscard]] const char* errorToExitCodeTag(UINT32 error); [[nodiscard]] const char* exitCodeToTag(int code); -} +} // namespace sdl::error From 743e1a6799cfb71a936f98f7ddafd0b3db0eb353 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sat, 24 Jan 2026 08:08:35 +0100 Subject: [PATCH 10/30] [client,sdl] add new SdlWindow members * get orientation of window on display * get window size (in logical size) --- client/SDL/SDL3/sdl_window.cpp | 40 ++++++++++++++++++++++++---------- client/SDL/SDL3/sdl_window.hpp | 4 +++- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/client/SDL/SDL3/sdl_window.cpp b/client/SDL/SDL3/sdl_window.cpp index 70a244145..54f95f82b 100644 --- a/client/SDL/SDL3/sdl_window.cpp +++ b/client/SDL/SDL3/sdl_window.cpp @@ -49,9 +49,9 @@ SdlWindow::SdlWindow(const std::string& title, Sint32 startupX, Sint32 startupY, const int iscale = static_cast(sc * 100.0f); auto w = 100 * width / iscale; auto h = 100 * height / iscale; - (void)resize({ w, h }); + std::ignore = resize({ w, h }); SDL_SetHint(SDL_HINT_APP_NAME, ""); - (void)SDL_SyncWindow(_window); + std::ignore = SDL_SyncWindow(_window); } SdlWindow::SdlWindow(SdlWindow&& other) noexcept @@ -65,7 +65,7 @@ SdlWindow::~SdlWindow() SDL_DestroyWindow(_window); } -Uint32 SdlWindow::id() const +SDL_WindowID SdlWindow::id() const { if (!_window) return 0; @@ -90,6 +90,17 @@ SDL_Rect SdlWindow::rect() const return rect; } +SDL_Rect SdlWindow::bounds() const +{ + SDL_Rect rect = {}; + if (_window) + { + SDL_GetWindowPosition(_window, &rect.x, &rect.y); + SDL_GetWindowSize(_window, &rect.w, &rect.h); + } + return rect; +} + SDL_Window* SdlWindow::window() const { return _window; @@ -141,8 +152,8 @@ rdpMonitor SdlWindow::monitor(bool isPrimary) const mon.y = rect.y; } - auto orientation = SDL_GetCurrentDisplayOrientation(did); - mon.attributes.orientation = sdl::utils::orientaion_to_rdp(orientation); + const auto orient = orientation(); + mon.attributes.orientation = sdl::utils::orientaion_to_rdp(orient); auto primary = SDL_GetPrimaryDisplay(); mon.is_primary = isPrimary || (SDL_GetWindowID(_window) == primary); @@ -160,6 +171,12 @@ float SdlWindow::scale() const return SDL_GetWindowDisplayScale(_window); } +SDL_DisplayOrientation SdlWindow::orientation() const +{ + const auto did = displayIndex(); + return SDL_GetCurrentDisplayOrientation(did); +} + bool SdlWindow::grabKeyboard(bool enable) { if (!_window) @@ -180,31 +197,31 @@ void SdlWindow::setBordered(bool bordered) { if (_window) SDL_SetWindowBordered(_window, bordered); - (void)SDL_SyncWindow(_window); + std::ignore = SDL_SyncWindow(_window); } void SdlWindow::raise() { SDL_RaiseWindow(_window); - (void)SDL_SyncWindow(_window); + std::ignore = SDL_SyncWindow(_window); } void SdlWindow::resizeable(bool use) { SDL_SetWindowResizable(_window, use); - (void)SDL_SyncWindow(_window); + std::ignore = SDL_SyncWindow(_window); } void SdlWindow::fullscreen(bool enter) { - (void)SDL_SetWindowFullscreen(_window, enter); - (void)SDL_SyncWindow(_window); + std::ignore = SDL_SetWindowFullscreen(_window, enter); + std::ignore = SDL_SyncWindow(_window); } void SdlWindow::minimize() { SDL_MinimizeWindow(_window); - (void)SDL_SyncWindow(_window); + std::ignore = SDL_SyncWindow(_window); } bool SdlWindow::resize(const SDL_Point& size) @@ -313,7 +330,6 @@ SdlWindow SdlWindow::create(SDL_DisplayID id, const std::string& title, Uint32 f SdlWindow window{ ss.str(), startupX, startupY, static_cast(width), static_cast(height), flags }; - (void)window.window(); if ((flags & (SDL_WINDOW_FULLSCREEN)) != 0) { diff --git a/client/SDL/SDL3/sdl_window.hpp b/client/SDL/SDL3/sdl_window.hpp index 629d1ee01..7d40dafc6 100644 --- a/client/SDL/SDL3/sdl_window.hpp +++ b/client/SDL/SDL3/sdl_window.hpp @@ -39,9 +39,10 @@ class SdlWindow SdlWindow& operator=(const SdlWindow& other) = delete; SdlWindow& operator=(SdlWindow&& other) = delete; - [[nodiscard]] Uint32 id() const; + [[nodiscard]] SDL_WindowID id() const; [[nodiscard]] SDL_DisplayID displayIndex() const; [[nodiscard]] SDL_Rect rect() const; + [[nodiscard]] SDL_Rect bounds() const; [[nodiscard]] SDL_Window* window() const; [[nodiscard]] Sint32 offsetX() const; @@ -53,6 +54,7 @@ class SdlWindow [[nodiscard]] rdpMonitor monitor(bool isPrimary) const; [[nodiscard]] float scale() const; + [[nodiscard]] SDL_DisplayOrientation orientation() const; [[nodiscard]] bool grabKeyboard(bool enable); [[nodiscard]] bool grabMouse(bool enable); From 49ddfe65f9b7ad69f84fb342ca7cc507035e62f2 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sat, 24 Jan 2026 08:07:24 +0100 Subject: [PATCH 11/30] [client,sdl] add toString methods for various types * unify and add toString methods for types * add missing event types --- client/SDL/SDL3/sdl_utils.cpp | 26 +++++++++++++++++++++++--- client/SDL/SDL3/sdl_utils.hpp | 6 ++++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/client/SDL/SDL3/sdl_utils.cpp b/client/SDL/SDL3/sdl_utils.cpp index 83129eeae..c27690940 100644 --- a/client/SDL/SDL3/sdl_utils.cpp +++ b/client/SDL/SDL3/sdl_utils.cpp @@ -71,6 +71,7 @@ const char* sdl_event_type_str(Uint32 type) EV_CASE_STR(SDL_EVENT_WINDOW_HIT_TEST); EV_CASE_STR(SDL_EVENT_WINDOW_ICCPROF_CHANGED); EV_CASE_STR(SDL_EVENT_WINDOW_DISPLAY_CHANGED); + EV_CASE_STR(SDL_EVENT_WINDOW_SAFE_AREA_CHANGED); EV_CASE_STR(SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED); EV_CASE_STR(SDL_EVENT_WINDOW_OCCLUDED); EV_CASE_STR(SDL_EVENT_WINDOW_ENTER_FULLSCREEN); @@ -318,7 +319,7 @@ UINT32 sdl::utils::orientaion_to_rdp(SDL_DisplayOrientation orientation) } } -std::string sdl::utils::sdl_orientation_to_str(SDL_DisplayOrientation orientation) +std::string sdl::utils::toString(SDL_DisplayOrientation orientation) { switch (orientation) { @@ -335,7 +336,7 @@ std::string sdl::utils::sdl_orientation_to_str(SDL_DisplayOrientation orientatio } } -std::string sdl::utils::rdp_orientation_to_str(uint32_t orientation) +std::string sdl::utils::toString(uint32_t orientation) { switch (orientation) { @@ -357,6 +358,26 @@ std::string sdl::utils::rdp_orientation_to_str(uint32_t orientation) } } +std::string sdl::utils::toString(const SDL_DisplayMode* mode) +{ + if (!mode) + return "SDL_DisplayMode=null"; + + std::stringstream ss; + + ss << "[" + << "id=" << mode->displayID << "," + << "fmt=" << mode->format << "," + << "w=" << mode->w << "," + << "h=" << mode->h << "," + << "dpi=" << mode->pixel_density << "," + << "refresh=" << mode->refresh_rate << "," + << "num=" << mode->refresh_rate_numerator << "," + << "denom=" << mode->refresh_rate_denominator << "]"; + + return ss.str(); +} + std::string sdl::utils::generate_uuid_v4() { static std::random_device rd; @@ -555,5 +576,4 @@ namespace sdl::error return entry->code_tag; return nullptr; } - } // namespace sdl::error diff --git a/client/SDL/SDL3/sdl_utils.hpp b/client/SDL/SDL3/sdl_utils.hpp index 8fa10f30f..8332ff277 100644 --- a/client/SDL/SDL3/sdl_utils.hpp +++ b/client/SDL/SDL3/sdl_utils.hpp @@ -83,8 +83,10 @@ typedef struct namespace sdl::utils { - [[nodiscard]] std::string rdp_orientation_to_str(uint32_t orientation); - [[nodiscard]] std::string sdl_orientation_to_str(SDL_DisplayOrientation orientation); + [[nodiscard]] std::string toString(uint32_t orientation); + [[nodiscard]] std::string toString(SDL_DisplayOrientation orientation); + [[nodiscard]] std::string toString(const SDL_DisplayMode* mode); + [[nodiscard]] UINT32 orientaion_to_rdp(SDL_DisplayOrientation orientation); [[nodiscard]] std::string generate_uuid_v4(); From abdedab33cd021131a22509af676f93dcba13fdb Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sat, 24 Jan 2026 08:09:55 +0100 Subject: [PATCH 12/30] [client,sdl] encapsulate and unify event handling * move event handling to SdlContext * name functions similar --- client/SDL/SDL3/sdl_context.cpp | 89 +++++++++++++++++++++++++++++- client/SDL/SDL3/sdl_context.hpp | 3 + client/SDL/SDL3/sdl_disp.cpp | 13 +++-- client/SDL/SDL3/sdl_disp.hpp | 4 +- client/SDL/SDL3/sdl_freerdp.cpp | 98 ++------------------------------- 5 files changed, 103 insertions(+), 104 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index 962dbb8e7..24bc11eaf 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -376,8 +376,6 @@ bool SdlContext::createWindows() auto did = WINPR_ASSERTING_INT_CAST(SDL_DisplayID, id); auto window = SdlWindow::create(did, title, flags, w, h); - if (!window.window()) - return false; if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) { @@ -839,6 +837,93 @@ wLog* SdlContext::getWLog() return _log; } +bool SdlContext::handleEvent(const SDL_WindowEvent* ev) +{ + + if (!getDisplayChannelContext().handleEvent(ev)) + return false; + + auto window = getWindowForId(ev->windowID); + if (!window) + return true; + + { + const auto& r = window->rect(); + const auto& b = window->bounds(); + const auto& scale = window->scale(); + const auto& orientiaion = window->orientation(); + SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, + "%s: [%u] %dx%d-%dx%d {%dx%d-%dx%d}{scale=%f,orientation=%s}", + sdl_event_type_str(ev->type), ev->windowID, r.x, r.y, r.w, r.h, b.x, b.y, b.w, + b.h, scale, sdl::utils::toString(orientation).c_str()); + } + + switch (ev->type) + { + case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: + if (isConnected()) + { + if (!window->fill()) + return -1; + if (!drawToWindow(*window)) + return -1; + if (!sdl_Pointer_Set_Process(this)) + return -1; + } + break; + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + if (!window->fill()) + return -1; + if (!drawToWindow(*window)) + return -1; + if (!sdl_Pointer_Set_Process(this)) + return -1; + break; + case SDL_EVENT_WINDOW_MOVED: + { + auto r = window->rect(); + auto id = window->id(); + SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%u: %dx%d-%dx%d", id, r.x, r.y, r.w, r.h); + } + break; + case SDL_EVENT_WINDOW_CLOSE_REQUESTED: + { + SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Window closed, terminating RDP session..."); + freerdp_abort_connect_context(context()); + } + break; + default: + break; + } + return true; +} + +bool SdlContext::handleEvent(const SDL_DisplayEvent* ev) +{ + + if (!getDisplayChannelContext().handleEvent(ev)) + return false; + { + SDL_Rect r = {}; + if (!SDL_GetDisplayBounds(ev->displayID, &r)) + return false; + const auto name = SDL_GetDisplayName(ev->displayID); + if (!name) + return false; + const auto orientation = SDL_GetCurrentDisplayOrientation(ev->displayID); + const auto scale = SDL_GetDisplayContentScale(ev->displayID); + const auto mode = SDL_GetCurrentDisplayMode(ev->displayID); + if (!mode) + return false; + + SDL_LogDebug( + SDL_LOG_CATEGORY_APPLICATION, "%s: [%u, %s] %dx%d-%dx%d {orientation=%s, scale=%f}%s", + sdl_event_type_str(ev->type), ev->displayID, name, r.x, r.y, r.w, r.h, + sdl::utils::toString(orientation).c_str(), scale, sdl::utils::toString(mode).c_str()); + } + return true; +} + bool SdlContext::drawToWindows(const std::vector& rects) { for (auto& window : _windows) diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index 0c25e3377..6fc7c59f7 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -120,6 +120,9 @@ class SdlContext [[nodiscard]] wLog* getWLog(); + [[nodiscard]] bool handleEvent(const SDL_WindowEvent* ev); + [[nodiscard]] bool handleEvent(const SDL_DisplayEvent* ev); + private: [[nodiscard]] static BOOL preConnect(freerdp* instance); [[nodiscard]] static BOOL postConnect(freerdp* instance); diff --git a/client/SDL/SDL3/sdl_disp.cpp b/client/SDL/SDL3/sdl_disp.cpp index 0372f9e20..a23034e7a 100644 --- a/client/SDL/SDL3/sdl_disp.cpp +++ b/client/SDL/SDL3/sdl_disp.cpp @@ -327,7 +327,7 @@ bool sdlDispContext::updateMonitors(SDL_EventType type, SDL_DisplayID displayID) return addTimer(); } -bool sdlDispContext::handle_display_event(const SDL_DisplayEvent* ev) +bool sdlDispContext::handleEvent(const SDL_DisplayEvent* ev) { WINPR_ASSERT(ev); @@ -359,15 +359,16 @@ bool sdlDispContext::handle_display_event(const SDL_DisplayEvent* ev) } } -bool sdlDispContext::handle_window_event(const SDL_WindowEvent* ev) +bool sdlDispContext::handleEvent(const SDL_WindowEvent* ev) { WINPR_ASSERT(ev); - auto bordered = freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_Decorations); - auto window = _sdl->getWindowForId(ev->windowID); - if (window) - window->setBordered(bordered); + if (!window) + return true; + + auto bordered = freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_Decorations); + window->setBordered(bordered); switch (ev->type) { diff --git a/client/SDL/SDL3/sdl_disp.hpp b/client/SDL/SDL3/sdl_disp.hpp index b48f10e79..8d30f4881 100644 --- a/client/SDL/SDL3/sdl_disp.hpp +++ b/client/SDL/SDL3/sdl_disp.hpp @@ -43,8 +43,8 @@ class sdlDispContext [[nodiscard]] bool init(DispClientContext* disp); [[nodiscard]] bool uninit(DispClientContext* disp); - [[nodiscard]] bool handle_display_event(const SDL_DisplayEvent* ev); - [[nodiscard]] bool handle_window_event(const SDL_WindowEvent* ev); + [[nodiscard]] bool handleEvent(const SDL_DisplayEvent* ev); + [[nodiscard]] bool handleEvent(const SDL_WindowEvent* ev); private: [[nodiscard]] UINT DisplayControlCaps(UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 8b6e015ef..559dfe64c 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -108,14 +108,7 @@ static int sdl_run(SdlContext* sdl) continue; if (sdl->getDialog().handleEvent(windowEvent)) - { continue; - } - - if (sdl->getDialog().handleEvent(windowEvent)) - { - continue; - } auto point2pix = [](Uint32 win_id, float& x, float& y) { @@ -324,98 +317,15 @@ static int sdl_run(SdlContext* sdl) (windowEvent.type <= SDL_EVENT_DISPLAY_LAST)) { const SDL_DisplayEvent* ev = &windowEvent.display; - (void)sdl->getDisplayChannelContext().handle_display_event(ev); + if (!sdl->handleEvent(ev)) + return -1; } else if ((windowEvent.type >= SDL_EVENT_WINDOW_FIRST) && (windowEvent.type <= SDL_EVENT_WINDOW_LAST)) { const SDL_WindowEvent* ev = &windowEvent.window; - auto window = sdl->getWindowForId(ev->windowID); - if (window) - { - (void)sdl->getDisplayChannelContext().handle_window_event(ev); - - switch (ev->type) - { - case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: - if (sdl->isConnected()) - { - if (!sdl_Pointer_Set_Process(sdl)) - return -1; - if (freerdp_settings_get_bool( - sdl->context()->settings, - FreeRDP_DynamicResolutionUpdate)) - { - break; - } - auto win = window->window(); - int w_pix{}; - int h_pix{}; - [[maybe_unused]] auto rcpix = - SDL_GetWindowSizeInPixels(win, &w_pix, &h_pix); - assert(rcpix); - auto scale = SDL_GetWindowDisplayScale(win); - if (scale <= SDL_FLT_EPSILON) - { - auto err = SDL_GetError(); - SDL_LogWarn( - SDL_LOG_CATEGORY_APPLICATION, - "SDL_GetWindowDisplayScale() failed with %s", err); - } - else - { - assert(SDL_isnanf(scale) == 0); - assert(SDL_isinff(scale) == 0); - assert(scale > SDL_FLT_EPSILON); - auto w_gdi = sdl->context()->gdi->width; - auto h_gdi = sdl->context()->gdi->height; - auto pix2point = [=](int pix) - { - return static_cast(static_cast(pix) / - scale); - }; - if (w_pix != w_gdi || h_pix != h_gdi) - { - const auto ssws = SDL_SetWindowSize( - win, pix2point(w_gdi), pix2point(h_gdi)); - if (!ssws) - { - auto err = SDL_GetError(); - SDL_LogWarn( - SDL_LOG_CATEGORY_APPLICATION, - "SDL_SetWindowSize() failed with %s", err); - } - } - } - } - break; - case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: - if (!window->fill()) - return -1; - if (!sdl->drawToWindow(*window)) - return -1; - if (!sdl_Pointer_Set_Process(sdl)) - return -1; - break; - case SDL_EVENT_WINDOW_MOVED: - { - auto r = window->rect(); - auto id = window->id(); - SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%u: %dx%d-%dx%d", - id, r.x, r.y, r.w, r.h); - } - break; - case SDL_EVENT_WINDOW_CLOSE_REQUESTED: - { - SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, - "Window closed, terminating RDP session..."); - freerdp_abort_connect_context(sdl->context()); - } - break; - default: - break; - } - } + if (!sdl->handleEvent(ev)) + return -1; } break; } From 1ce038c12bd824ffb9488f3dd58a4947d8013638 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sat, 24 Jan 2026 13:19:39 +0100 Subject: [PATCH 13/30] [client,sdl] unify stringification functions --- client/SDL/SDL3/sdl_context.cpp | 8 +- client/SDL/SDL3/sdl_freerdp.cpp | 2 +- client/SDL/SDL3/sdl_utils.cpp | 565 ++++++++++++++++---------------- client/SDL/SDL3/sdl_utils.hpp | 5 +- 4 files changed, 287 insertions(+), 293 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index 24bc11eaf..0a39ace56 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -851,11 +851,11 @@ bool SdlContext::handleEvent(const SDL_WindowEvent* ev) const auto& r = window->rect(); const auto& b = window->bounds(); const auto& scale = window->scale(); - const auto& orientiaion = window->orientation(); + const auto& orientation = window->orientation(); SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%s: [%u] %dx%d-%dx%d {%dx%d-%dx%d}{scale=%f,orientation=%s}", - sdl_event_type_str(ev->type), ev->windowID, r.x, r.y, r.w, r.h, b.x, b.y, b.w, - b.h, scale, sdl::utils::toString(orientation).c_str()); + sdl::utils::toString(ev->type).c_str(), ev->windowID, r.x, r.y, r.w, r.h, b.x, + b.y, b.w, b.h, scale, sdl::utils::toString(orientation).c_str()); } switch (ev->type) @@ -918,7 +918,7 @@ bool SdlContext::handleEvent(const SDL_DisplayEvent* ev) SDL_LogDebug( SDL_LOG_CATEGORY_APPLICATION, "%s: [%u, %s] %dx%d-%dx%d {orientation=%s, scale=%f}%s", - sdl_event_type_str(ev->type), ev->displayID, name, r.x, r.y, r.w, r.h, + sdl::utils::toString(ev->type).c_str(), ev->displayID, name, r.x, r.y, r.w, r.h, sdl::utils::toString(orientation).c_str(), scale, sdl::utils::toString(mode).c_str()); } return true; diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 559dfe64c..613674bd2 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -102,7 +102,7 @@ static int sdl_run(SdlContext* sdl) #if defined(WITH_DEBUG_SDL_EVENTS) SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "got event %s [0x%08" PRIx32 "]", - sdl_event_type_str(windowEvent.type), windowEvent.type); + sdl::utils::toString(windowEvent.type).c_str(), windowEvent.type); #endif if (sdl->shallAbort(true)) continue; diff --git a/client/SDL/SDL3/sdl_utils.cpp b/client/SDL/SDL3/sdl_utils.cpp index c27690940..30ffa37d7 100644 --- a/client/SDL/SDL3/sdl_utils.cpp +++ b/client/SDL/SDL3/sdl_utils.cpp @@ -35,147 +35,6 @@ case x: \ return STR(x) -const char* sdl_event_type_str(Uint32 type) -{ - switch (type) - { - EV_CASE_STR(SDL_EVENT_FIRST); - EV_CASE_STR(SDL_EVENT_QUIT); - EV_CASE_STR(SDL_EVENT_TERMINATING); - EV_CASE_STR(SDL_EVENT_LOW_MEMORY); - EV_CASE_STR(SDL_EVENT_WILL_ENTER_BACKGROUND); - EV_CASE_STR(SDL_EVENT_DID_ENTER_BACKGROUND); - EV_CASE_STR(SDL_EVENT_WILL_ENTER_FOREGROUND); - EV_CASE_STR(SDL_EVENT_DID_ENTER_FOREGROUND); - EV_CASE_STR(SDL_EVENT_LOCALE_CHANGED); - EV_CASE_STR(SDL_EVENT_SYSTEM_THEME_CHANGED); - EV_CASE_STR(SDL_EVENT_DISPLAY_ORIENTATION); - EV_CASE_STR(SDL_EVENT_DISPLAY_ADDED); - EV_CASE_STR(SDL_EVENT_DISPLAY_REMOVED); - EV_CASE_STR(SDL_EVENT_DISPLAY_MOVED); - EV_CASE_STR(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED); - EV_CASE_STR(SDL_EVENT_WINDOW_SHOWN); - EV_CASE_STR(SDL_EVENT_WINDOW_HIDDEN); - EV_CASE_STR(SDL_EVENT_WINDOW_EXPOSED); - EV_CASE_STR(SDL_EVENT_WINDOW_MOVED); - EV_CASE_STR(SDL_EVENT_WINDOW_RESIZED); - EV_CASE_STR(SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED); - EV_CASE_STR(SDL_EVENT_WINDOW_MINIMIZED); - EV_CASE_STR(SDL_EVENT_WINDOW_MAXIMIZED); - EV_CASE_STR(SDL_EVENT_WINDOW_RESTORED); - EV_CASE_STR(SDL_EVENT_WINDOW_MOUSE_ENTER); - EV_CASE_STR(SDL_EVENT_WINDOW_MOUSE_LEAVE); - EV_CASE_STR(SDL_EVENT_WINDOW_FOCUS_GAINED); - EV_CASE_STR(SDL_EVENT_WINDOW_FOCUS_LOST); - EV_CASE_STR(SDL_EVENT_WINDOW_CLOSE_REQUESTED); - EV_CASE_STR(SDL_EVENT_WINDOW_HIT_TEST); - EV_CASE_STR(SDL_EVENT_WINDOW_ICCPROF_CHANGED); - EV_CASE_STR(SDL_EVENT_WINDOW_DISPLAY_CHANGED); - EV_CASE_STR(SDL_EVENT_WINDOW_SAFE_AREA_CHANGED); - EV_CASE_STR(SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED); - EV_CASE_STR(SDL_EVENT_WINDOW_OCCLUDED); - EV_CASE_STR(SDL_EVENT_WINDOW_ENTER_FULLSCREEN); - EV_CASE_STR(SDL_EVENT_WINDOW_LEAVE_FULLSCREEN); - EV_CASE_STR(SDL_EVENT_WINDOW_DESTROYED); - - EV_CASE_STR(SDL_EVENT_KEY_DOWN); - EV_CASE_STR(SDL_EVENT_KEY_UP); - EV_CASE_STR(SDL_EVENT_TEXT_EDITING); - EV_CASE_STR(SDL_EVENT_TEXT_INPUT); - EV_CASE_STR(SDL_EVENT_KEYMAP_CHANGED); - EV_CASE_STR(SDL_EVENT_KEYBOARD_ADDED); - EV_CASE_STR(SDL_EVENT_KEYBOARD_REMOVED); - - EV_CASE_STR(SDL_EVENT_MOUSE_MOTION); - EV_CASE_STR(SDL_EVENT_MOUSE_BUTTON_DOWN); - EV_CASE_STR(SDL_EVENT_MOUSE_BUTTON_UP); - EV_CASE_STR(SDL_EVENT_MOUSE_WHEEL); - EV_CASE_STR(SDL_EVENT_MOUSE_ADDED); - EV_CASE_STR(SDL_EVENT_MOUSE_REMOVED); - - EV_CASE_STR(SDL_EVENT_JOYSTICK_AXIS_MOTION); - EV_CASE_STR(SDL_EVENT_JOYSTICK_BALL_MOTION); - EV_CASE_STR(SDL_EVENT_JOYSTICK_HAT_MOTION); - EV_CASE_STR(SDL_EVENT_JOYSTICK_BUTTON_DOWN); - EV_CASE_STR(SDL_EVENT_JOYSTICK_BUTTON_UP); - EV_CASE_STR(SDL_EVENT_JOYSTICK_ADDED); - EV_CASE_STR(SDL_EVENT_JOYSTICK_REMOVED); - EV_CASE_STR(SDL_EVENT_JOYSTICK_BATTERY_UPDATED); - EV_CASE_STR(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE); - - EV_CASE_STR(SDL_EVENT_GAMEPAD_AXIS_MOTION); - EV_CASE_STR(SDL_EVENT_GAMEPAD_BUTTON_DOWN); - EV_CASE_STR(SDL_EVENT_GAMEPAD_BUTTON_UP); - EV_CASE_STR(SDL_EVENT_GAMEPAD_ADDED); - EV_CASE_STR(SDL_EVENT_GAMEPAD_REMOVED); - EV_CASE_STR(SDL_EVENT_GAMEPAD_REMAPPED); - EV_CASE_STR(SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN); - EV_CASE_STR(SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION); - EV_CASE_STR(SDL_EVENT_GAMEPAD_TOUCHPAD_UP); - EV_CASE_STR(SDL_EVENT_GAMEPAD_SENSOR_UPDATE); - EV_CASE_STR(SDL_EVENT_GAMEPAD_UPDATE_COMPLETE); - EV_CASE_STR(SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED); - - EV_CASE_STR(SDL_EVENT_FINGER_DOWN); - EV_CASE_STR(SDL_EVENT_FINGER_UP); - EV_CASE_STR(SDL_EVENT_FINGER_MOTION); - - EV_CASE_STR(SDL_EVENT_CLIPBOARD_UPDATE); - - EV_CASE_STR(SDL_EVENT_DROP_FILE); - EV_CASE_STR(SDL_EVENT_DROP_TEXT); - EV_CASE_STR(SDL_EVENT_DROP_BEGIN); - EV_CASE_STR(SDL_EVENT_DROP_COMPLETE); - EV_CASE_STR(SDL_EVENT_DROP_POSITION); - - EV_CASE_STR(SDL_EVENT_AUDIO_DEVICE_ADDED); - EV_CASE_STR(SDL_EVENT_AUDIO_DEVICE_REMOVED); - EV_CASE_STR(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED); - - EV_CASE_STR(SDL_EVENT_SENSOR_UPDATE); - - EV_CASE_STR(SDL_EVENT_PEN_DOWN); - EV_CASE_STR(SDL_EVENT_PEN_UP); - EV_CASE_STR(SDL_EVENT_PEN_MOTION); - EV_CASE_STR(SDL_EVENT_PEN_BUTTON_DOWN); - EV_CASE_STR(SDL_EVENT_PEN_BUTTON_UP); - EV_CASE_STR(SDL_EVENT_CAMERA_DEVICE_ADDED); - EV_CASE_STR(SDL_EVENT_CAMERA_DEVICE_REMOVED); - EV_CASE_STR(SDL_EVENT_CAMERA_DEVICE_APPROVED); - EV_CASE_STR(SDL_EVENT_CAMERA_DEVICE_DENIED); - - EV_CASE_STR(SDL_EVENT_RENDER_TARGETS_RESET); - EV_CASE_STR(SDL_EVENT_RENDER_DEVICE_RESET); - EV_CASE_STR(SDL_EVENT_POLL_SENTINEL); - - EV_CASE_STR(SDL_EVENT_USER); - - EV_CASE_STR(SDL_EVENT_USER_CERT_DIALOG); - EV_CASE_STR(SDL_EVENT_USER_CERT_RESULT); - EV_CASE_STR(SDL_EVENT_USER_SHOW_DIALOG); - EV_CASE_STR(SDL_EVENT_USER_SHOW_RESULT); - EV_CASE_STR(SDL_EVENT_USER_AUTH_DIALOG); - EV_CASE_STR(SDL_EVENT_USER_AUTH_RESULT); - EV_CASE_STR(SDL_EVENT_USER_SCARD_DIALOG); - EV_CASE_STR(SDL_EVENT_USER_RETRY_DIALOG); - EV_CASE_STR(SDL_EVENT_USER_SCARD_RESULT); - EV_CASE_STR(SDL_EVENT_USER_UPDATE); - EV_CASE_STR(SDL_EVENT_USER_CREATE_WINDOWS); - EV_CASE_STR(SDL_EVENT_USER_WINDOW_RESIZEABLE); - EV_CASE_STR(SDL_EVENT_USER_WINDOW_FULLSCREEN); - EV_CASE_STR(SDL_EVENT_USER_WINDOW_MINIMIZE); - EV_CASE_STR(SDL_EVENT_USER_POINTER_NULL); - EV_CASE_STR(SDL_EVENT_USER_POINTER_DEFAULT); - EV_CASE_STR(SDL_EVENT_USER_POINTER_POSITION); - EV_CASE_STR(SDL_EVENT_USER_POINTER_SET); - EV_CASE_STR(SDL_EVENT_USER_QUIT); - - EV_CASE_STR(SDL_EVENT_LAST); - default: - return "SDL_UNKNOWNEVENT"; - } -} - const char* sdl_error_string(Sint32 res) { if (res == 0) @@ -295,170 +154,306 @@ bool sdl_push_quit() return true; } -std::string sdl_window_event_str(Uint32 ev) +namespace sdl::utils { - if ((ev >= SDL_EVENT_WINDOW_FIRST) && (ev <= SDL_EVENT_WINDOW_LAST)) - return sdl_event_type_str(ev); - - return "SDL_EVENT_WINDOW_UNKNOWN"; -} - -UINT32 sdl::utils::orientaion_to_rdp(SDL_DisplayOrientation orientation) -{ - switch (orientation) + UINT32 orientaion_to_rdp(SDL_DisplayOrientation orientation) { - case SDL_ORIENTATION_LANDSCAPE: - return ORIENTATION_LANDSCAPE; - case SDL_ORIENTATION_LANDSCAPE_FLIPPED: - return ORIENTATION_LANDSCAPE_FLIPPED; - case SDL_ORIENTATION_PORTRAIT_FLIPPED: - return ORIENTATION_PORTRAIT_FLIPPED; - case SDL_ORIENTATION_PORTRAIT: - default: - return ORIENTATION_PORTRAIT; - } -} - -std::string sdl::utils::toString(SDL_DisplayOrientation orientation) -{ - switch (orientation) - { - case SDL_ORIENTATION_LANDSCAPE: - return "SDL_ORIENTATION_LANDSCAPE"; - case SDL_ORIENTATION_LANDSCAPE_FLIPPED: - return "SDL_ORIENTATION_LANDSCAPE_FLIPPED"; - case SDL_ORIENTATION_PORTRAIT_FLIPPED: - return "SDL_ORIENTATION_PORTRAIT_FLIPPED"; - case SDL_ORIENTATION_PORTRAIT: - return "SDL_ORIENTATION_PORTRAIT"; - default: - return "SDL_ORIENTATION_UNKNOWN"; - } -} - -std::string sdl::utils::toString(uint32_t orientation) -{ - switch (orientation) - { - case ORIENTATION_LANDSCAPE: - return "ORIENTATION_LANDSCAPE"; - case ORIENTATION_LANDSCAPE_FLIPPED: - return "ORIENTATION_LANDSCAPE_FLIPPED"; - case ORIENTATION_PORTRAIT_FLIPPED: - return "ORIENTATION_PORTRAIT_FLIPPED"; - case ORIENTATION_PORTRAIT: - return "ORIENTATION_PORTRAIT"; - default: + switch (orientation) { - std::stringstream ss; - ss << "ORIENTATION_UNKNOWN_" << std::hex << std::setfill('0') << std::setw(8) - << orientation; - return ss.str(); + case SDL_ORIENTATION_LANDSCAPE: + return ORIENTATION_LANDSCAPE; + case SDL_ORIENTATION_LANDSCAPE_FLIPPED: + return ORIENTATION_LANDSCAPE_FLIPPED; + case SDL_ORIENTATION_PORTRAIT_FLIPPED: + return ORIENTATION_PORTRAIT_FLIPPED; + case SDL_ORIENTATION_PORTRAIT: + default: + return ORIENTATION_PORTRAIT; } } -} -std::string sdl::utils::toString(const SDL_DisplayMode* mode) -{ - if (!mode) - return "SDL_DisplayMode=null"; - - std::stringstream ss; - - ss << "[" - << "id=" << mode->displayID << "," - << "fmt=" << mode->format << "," - << "w=" << mode->w << "," - << "h=" << mode->h << "," - << "dpi=" << mode->pixel_density << "," - << "refresh=" << mode->refresh_rate << "," - << "num=" << mode->refresh_rate_numerator << "," - << "denom=" << mode->refresh_rate_denominator << "]"; - - return ss.str(); -} - -std::string sdl::utils::generate_uuid_v4() -{ - static std::random_device rd; - static std::mt19937 gen(rd()); - static std::uniform_int_distribution<> dis(0, 255); - std::stringstream ss; - ss << std::hex << std::setfill('0') << std::setw(2); - for (int i = 0; i < 4; i++) + std::string toString(SDL_DisplayOrientation orientation) { - ss << dis(gen); + switch (orientation) + { + case SDL_ORIENTATION_LANDSCAPE: + return "SDL_ORIENTATION_LANDSCAPE"; + case SDL_ORIENTATION_LANDSCAPE_FLIPPED: + return "SDL_ORIENTATION_LANDSCAPE_FLIPPED"; + case SDL_ORIENTATION_PORTRAIT_FLIPPED: + return "SDL_ORIENTATION_PORTRAIT_FLIPPED"; + case SDL_ORIENTATION_PORTRAIT: + return "SDL_ORIENTATION_PORTRAIT"; + default: + return "SDL_ORIENTATION_UNKNOWN"; + } } - ss << "-"; - for (int i = 0; i < 2; i++) - { - ss << dis(gen); - } - ss << "-"; - for (int i = 0; i < 2; i++) - { - ss << dis(gen); - } - ss << "-"; - for (int i = 0; i < 2; i++) - { - ss << dis(gen); - } - ss << "-"; - for (int i = 0; i < 6; i++) - { - ss << dis(gen); - } - return ss.str(); -} -sdl::utils::HighDpiScaleMode sdl::utils::platformScaleMode() -{ - const auto platform = SDL_GetPlatform(); - if (!platform) - return SCALE_MODE_INVALID; - if (strcmp("Windows", platform) == 0) - return SCALE_MODE_X11; - if (strcmp("macOS", platform) == 0) - return SCALE_MODE_WAYLAND; - if (strcmp("Linux", platform) == 0) + std::string toString(FreeRDP_DesktopRotationFlags orientation) { - const auto driver = SDL_GetCurrentVideoDriver(); - if (!driver) - return SCALE_MODE_WAYLAND; - if (strcmp("x11", driver) == 0) + switch (orientation) + { + case ORIENTATION_LANDSCAPE: + return "ORIENTATION_LANDSCAPE"; + case ORIENTATION_LANDSCAPE_FLIPPED: + return "ORIENTATION_LANDSCAPE_FLIPPED"; + case ORIENTATION_PORTRAIT_FLIPPED: + return "ORIENTATION_PORTRAIT_FLIPPED"; + case ORIENTATION_PORTRAIT: + return "ORIENTATION_PORTRAIT"; + default: + { + std::stringstream ss; + ss << "ORIENTATION_UNKNOWN_" << std::hex << std::setfill('0') << std::setw(8) + << orientation; + return ss.str(); + } + } + } + + std::string toString(const SDL_DisplayMode* mode) + { + if (!mode) + return "SDL_DisplayMode=null"; + + std::stringstream ss; + + ss << "[" + << "id=" << mode->displayID << "," + << "fmt=" << mode->format << "," + << "w=" << mode->w << "," + << "h=" << mode->h << "," + << "dpi=" << mode->pixel_density << "," + << "refresh=" << mode->refresh_rate << "," + << "num=" << mode->refresh_rate_numerator << "," + << "denom=" << mode->refresh_rate_denominator << "]"; + + return ss.str(); + } + + std::string toString(Uint32 type) + { + switch (type) + { + EV_CASE_STR(SDL_EVENT_FIRST); + EV_CASE_STR(SDL_EVENT_QUIT); + EV_CASE_STR(SDL_EVENT_TERMINATING); + EV_CASE_STR(SDL_EVENT_LOW_MEMORY); + EV_CASE_STR(SDL_EVENT_WILL_ENTER_BACKGROUND); + EV_CASE_STR(SDL_EVENT_DID_ENTER_BACKGROUND); + EV_CASE_STR(SDL_EVENT_WILL_ENTER_FOREGROUND); + EV_CASE_STR(SDL_EVENT_DID_ENTER_FOREGROUND); + EV_CASE_STR(SDL_EVENT_LOCALE_CHANGED); + EV_CASE_STR(SDL_EVENT_SYSTEM_THEME_CHANGED); + EV_CASE_STR(SDL_EVENT_DISPLAY_ORIENTATION); + EV_CASE_STR(SDL_EVENT_DISPLAY_ADDED); + EV_CASE_STR(SDL_EVENT_DISPLAY_REMOVED); + EV_CASE_STR(SDL_EVENT_DISPLAY_MOVED); + EV_CASE_STR(SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED); + EV_CASE_STR(SDL_EVENT_WINDOW_SHOWN); + EV_CASE_STR(SDL_EVENT_WINDOW_HIDDEN); + EV_CASE_STR(SDL_EVENT_WINDOW_EXPOSED); + EV_CASE_STR(SDL_EVENT_WINDOW_MOVED); + EV_CASE_STR(SDL_EVENT_WINDOW_RESIZED); + EV_CASE_STR(SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED); + EV_CASE_STR(SDL_EVENT_WINDOW_MINIMIZED); + EV_CASE_STR(SDL_EVENT_WINDOW_MAXIMIZED); + EV_CASE_STR(SDL_EVENT_WINDOW_RESTORED); + EV_CASE_STR(SDL_EVENT_WINDOW_MOUSE_ENTER); + EV_CASE_STR(SDL_EVENT_WINDOW_MOUSE_LEAVE); + EV_CASE_STR(SDL_EVENT_WINDOW_FOCUS_GAINED); + EV_CASE_STR(SDL_EVENT_WINDOW_FOCUS_LOST); + EV_CASE_STR(SDL_EVENT_WINDOW_CLOSE_REQUESTED); + EV_CASE_STR(SDL_EVENT_WINDOW_HIT_TEST); + EV_CASE_STR(SDL_EVENT_WINDOW_ICCPROF_CHANGED); + EV_CASE_STR(SDL_EVENT_WINDOW_DISPLAY_CHANGED); + EV_CASE_STR(SDL_EVENT_WINDOW_SAFE_AREA_CHANGED); + EV_CASE_STR(SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED); + EV_CASE_STR(SDL_EVENT_WINDOW_OCCLUDED); + EV_CASE_STR(SDL_EVENT_WINDOW_ENTER_FULLSCREEN); + EV_CASE_STR(SDL_EVENT_WINDOW_LEAVE_FULLSCREEN); + EV_CASE_STR(SDL_EVENT_WINDOW_DESTROYED); + + EV_CASE_STR(SDL_EVENT_KEY_DOWN); + EV_CASE_STR(SDL_EVENT_KEY_UP); + EV_CASE_STR(SDL_EVENT_TEXT_EDITING); + EV_CASE_STR(SDL_EVENT_TEXT_INPUT); + EV_CASE_STR(SDL_EVENT_KEYMAP_CHANGED); + EV_CASE_STR(SDL_EVENT_KEYBOARD_ADDED); + EV_CASE_STR(SDL_EVENT_KEYBOARD_REMOVED); + + EV_CASE_STR(SDL_EVENT_MOUSE_MOTION); + EV_CASE_STR(SDL_EVENT_MOUSE_BUTTON_DOWN); + EV_CASE_STR(SDL_EVENT_MOUSE_BUTTON_UP); + EV_CASE_STR(SDL_EVENT_MOUSE_WHEEL); + EV_CASE_STR(SDL_EVENT_MOUSE_ADDED); + EV_CASE_STR(SDL_EVENT_MOUSE_REMOVED); + + EV_CASE_STR(SDL_EVENT_JOYSTICK_AXIS_MOTION); + EV_CASE_STR(SDL_EVENT_JOYSTICK_BALL_MOTION); + EV_CASE_STR(SDL_EVENT_JOYSTICK_HAT_MOTION); + EV_CASE_STR(SDL_EVENT_JOYSTICK_BUTTON_DOWN); + EV_CASE_STR(SDL_EVENT_JOYSTICK_BUTTON_UP); + EV_CASE_STR(SDL_EVENT_JOYSTICK_ADDED); + EV_CASE_STR(SDL_EVENT_JOYSTICK_REMOVED); + EV_CASE_STR(SDL_EVENT_JOYSTICK_BATTERY_UPDATED); + EV_CASE_STR(SDL_EVENT_JOYSTICK_UPDATE_COMPLETE); + + EV_CASE_STR(SDL_EVENT_GAMEPAD_AXIS_MOTION); + EV_CASE_STR(SDL_EVENT_GAMEPAD_BUTTON_DOWN); + EV_CASE_STR(SDL_EVENT_GAMEPAD_BUTTON_UP); + EV_CASE_STR(SDL_EVENT_GAMEPAD_ADDED); + EV_CASE_STR(SDL_EVENT_GAMEPAD_REMOVED); + EV_CASE_STR(SDL_EVENT_GAMEPAD_REMAPPED); + EV_CASE_STR(SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN); + EV_CASE_STR(SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION); + EV_CASE_STR(SDL_EVENT_GAMEPAD_TOUCHPAD_UP); + EV_CASE_STR(SDL_EVENT_GAMEPAD_SENSOR_UPDATE); + EV_CASE_STR(SDL_EVENT_GAMEPAD_UPDATE_COMPLETE); + EV_CASE_STR(SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED); + + EV_CASE_STR(SDL_EVENT_FINGER_DOWN); + EV_CASE_STR(SDL_EVENT_FINGER_UP); + EV_CASE_STR(SDL_EVENT_FINGER_MOTION); + + EV_CASE_STR(SDL_EVENT_CLIPBOARD_UPDATE); + + EV_CASE_STR(SDL_EVENT_DROP_FILE); + EV_CASE_STR(SDL_EVENT_DROP_TEXT); + EV_CASE_STR(SDL_EVENT_DROP_BEGIN); + EV_CASE_STR(SDL_EVENT_DROP_COMPLETE); + EV_CASE_STR(SDL_EVENT_DROP_POSITION); + + EV_CASE_STR(SDL_EVENT_AUDIO_DEVICE_ADDED); + EV_CASE_STR(SDL_EVENT_AUDIO_DEVICE_REMOVED); + EV_CASE_STR(SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED); + + EV_CASE_STR(SDL_EVENT_SENSOR_UPDATE); + + EV_CASE_STR(SDL_EVENT_PEN_DOWN); + EV_CASE_STR(SDL_EVENT_PEN_UP); + EV_CASE_STR(SDL_EVENT_PEN_MOTION); + EV_CASE_STR(SDL_EVENT_PEN_BUTTON_DOWN); + EV_CASE_STR(SDL_EVENT_PEN_BUTTON_UP); + EV_CASE_STR(SDL_EVENT_CAMERA_DEVICE_ADDED); + EV_CASE_STR(SDL_EVENT_CAMERA_DEVICE_REMOVED); + EV_CASE_STR(SDL_EVENT_CAMERA_DEVICE_APPROVED); + EV_CASE_STR(SDL_EVENT_CAMERA_DEVICE_DENIED); + + EV_CASE_STR(SDL_EVENT_RENDER_TARGETS_RESET); + EV_CASE_STR(SDL_EVENT_RENDER_DEVICE_RESET); + EV_CASE_STR(SDL_EVENT_POLL_SENTINEL); + + EV_CASE_STR(SDL_EVENT_USER); + + EV_CASE_STR(SDL_EVENT_USER_CERT_DIALOG); + EV_CASE_STR(SDL_EVENT_USER_CERT_RESULT); + EV_CASE_STR(SDL_EVENT_USER_SHOW_DIALOG); + EV_CASE_STR(SDL_EVENT_USER_SHOW_RESULT); + EV_CASE_STR(SDL_EVENT_USER_AUTH_DIALOG); + EV_CASE_STR(SDL_EVENT_USER_AUTH_RESULT); + EV_CASE_STR(SDL_EVENT_USER_SCARD_DIALOG); + EV_CASE_STR(SDL_EVENT_USER_RETRY_DIALOG); + EV_CASE_STR(SDL_EVENT_USER_SCARD_RESULT); + EV_CASE_STR(SDL_EVENT_USER_UPDATE); + EV_CASE_STR(SDL_EVENT_USER_CREATE_WINDOWS); + EV_CASE_STR(SDL_EVENT_USER_WINDOW_RESIZEABLE); + EV_CASE_STR(SDL_EVENT_USER_WINDOW_FULLSCREEN); + EV_CASE_STR(SDL_EVENT_USER_WINDOW_MINIMIZE); + EV_CASE_STR(SDL_EVENT_USER_POINTER_NULL); + EV_CASE_STR(SDL_EVENT_USER_POINTER_DEFAULT); + EV_CASE_STR(SDL_EVENT_USER_POINTER_POSITION); + EV_CASE_STR(SDL_EVENT_USER_POINTER_SET); + EV_CASE_STR(SDL_EVENT_USER_QUIT); + + EV_CASE_STR(SDL_EVENT_LAST); + default: + return "SDL_UNKNOWNEVENT"; + } + } + + std::string generate_uuid_v4() + { + static std::random_device rd; + static std::mt19937 gen(rd()); + static std::uniform_int_distribution<> dis(0, 255); + std::stringstream ss; + ss << std::hex << std::setfill('0') << std::setw(2); + for (int i = 0; i < 4; i++) + { + ss << dis(gen); + } + ss << "-"; + for (int i = 0; i < 2; i++) + { + ss << dis(gen); + } + ss << "-"; + for (int i = 0; i < 2; i++) + { + ss << dis(gen); + } + ss << "-"; + for (int i = 0; i < 2; i++) + { + ss << dis(gen); + } + ss << "-"; + for (int i = 0; i < 6; i++) + { + ss << dis(gen); + } + return ss.str(); + } + + HighDpiScaleMode platformScaleMode() + { + const auto platform = SDL_GetPlatform(); + if (!platform) + return SCALE_MODE_INVALID; + if (strcmp("Windows", platform) == 0) return SCALE_MODE_X11; - if (strcmp("wayland", driver) == 0) + if (strcmp("macOS", platform) == 0) return SCALE_MODE_WAYLAND; + if (strcmp("Linux", platform) == 0) + { + const auto driver = SDL_GetCurrentVideoDriver(); + if (!driver) + return SCALE_MODE_WAYLAND; + if (strcmp("x11", driver) == 0) + return SCALE_MODE_X11; + if (strcmp("wayland", driver) == 0) + return SCALE_MODE_WAYLAND; + } + return SCALE_MODE_INVALID; } - return SCALE_MODE_INVALID; -} -std::string sdl::utils::windowTitle(const rdpSettings* settings) -{ - const char* prefix = "FreeRDP:"; + std::string windowTitle(const rdpSettings* settings) + { + const char* prefix = "FreeRDP:"; - if (!settings) - return {}; + if (!settings) + return {}; - const auto windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle); - if (windowTitle) - return {}; + const auto windowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle); + if (windowTitle) + return {}; - const auto name = freerdp_settings_get_server_name(settings); - const auto port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort); + const auto name = freerdp_settings_get_server_name(settings); + const auto port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort); - const auto addPort = (port != 3389); + const auto addPort = (port != 3389); - std::stringstream ss; - ss << prefix << " "; - if (!addPort) - ss << name; - else - ss << name << ":" << port; + std::stringstream ss; + ss << prefix << " "; + if (!addPort) + ss << name; + else + ss << name << ":" << port; - return ss.str(); -} + return ss.str(); + } +} // namespace sdl::utils namespace sdl::error { diff --git a/client/SDL/SDL3/sdl_utils.hpp b/client/SDL/SDL3/sdl_utils.hpp index 8332ff277..280cbf9f1 100644 --- a/client/SDL/SDL3/sdl_utils.hpp +++ b/client/SDL/SDL3/sdl_utils.hpp @@ -73,8 +73,6 @@ typedef struct [[nodiscard]] bool sdl_push_quit(); -[[nodiscard]] std::string sdl_window_event_str(Uint32 ev); -[[nodiscard]] const char* sdl_event_type_str(Uint32 type); [[nodiscard]] const char* sdl_error_string(Sint32 res); #define sdl_log_error(res, log, what) sdl_log_error_ex(res, log, what, __FILE__, __LINE__, __func__) @@ -83,9 +81,10 @@ typedef struct namespace sdl::utils { - [[nodiscard]] std::string toString(uint32_t orientation); + [[nodiscard]] std::string toString(enum FreeRDP_DesktopRotationFlags orientation); [[nodiscard]] std::string toString(SDL_DisplayOrientation orientation); [[nodiscard]] std::string toString(const SDL_DisplayMode* mode); + [[nodiscard]] std::string toString(Uint32 type); [[nodiscard]] UINT32 orientaion_to_rdp(SDL_DisplayOrientation orientation); From 842624f25a06dccdd3f86ccaf6f7a4f44aae6b7b Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 11:59:03 +0100 Subject: [PATCH 14/30] [client,sdl] check function return in dialogs --- client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp index e97ce62f4..a4d9773d8 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp @@ -135,9 +135,12 @@ bool SDLConnectionDialog::setModal() if (!parent) return true; - SDL_SetWindowParent(_window.get(), parent->window()); - SDL_SetWindowModal(_window.get(), true); - SDL_RaiseWindow(_window.get()); + if (!SDL_SetWindowParent(_window.get(), parent->window())) + return false; + if (!SDL_SetWindowModal(_window.get(), true)) + return false; + if (!SDL_RaiseWindow(_window.get())) + return false; } return true; } From 7258c778388117f7a6dd8058ea1fea23d33ad855 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 12:01:59 +0100 Subject: [PATCH 15/30] [client,sdl] fix local scaled drawing * Add scaling factor to drawing routines * Update local scaling on each draw --- client/SDL/SDL3/sdl_context.cpp | 24 +++++++++++++++++++++++- client/SDL/SDL3/sdl_context.hpp | 4 ++++ client/SDL/SDL3/sdl_window.cpp | 17 ++++++++++------- client/SDL/SDL3/sdl_window.hpp | 5 +++-- 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index 0a39ace56..e3c0e6878 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -747,7 +747,10 @@ bool SdlContext::drawToWindow(SdlWindow& window, const std::vector& re { window.setOffsetY((size.h - gdi->height) / 2); } - if (!window.drawScaledRects(surface, rects)) + + _localScale = { static_cast(size.w) / static_cast(gdi->width), + static_cast(size.h) / static_cast(gdi->height) }; + if (!window.drawScaledRects(surface, _localScale, rects)) return false; } else @@ -924,6 +927,25 @@ bool SdlContext::handleEvent(const SDL_DisplayEvent* ev) return true; } +SDL_FPoint SdlContext::applyLocalScaling(const SDL_FPoint& val) const +{ + if (!freerdp_settings_get_bool(context()->settings, FreeRDP_SmartSizing)) + return val; + + auto rval = val; + rval.x *= _localScale.x; + rval.y *= _localScale.y; + return rval; +} + +void SdlContext::removeLocalScaling(float& x, float& y) +{ + if (!freerdp_settings_get_bool(context()->settings, FreeRDP_SmartSizing)) + return; + x /= _localScale.x; + y /= _localScale.y; +} + bool SdlContext::drawToWindows(const std::vector& rects) { for (auto& window : _windows) diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index 6fc7c59f7..9b945f107 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -134,6 +134,9 @@ class SdlContext [[nodiscard]] static BOOL endPaint(rdpContext* context); [[nodiscard]] static DWORD WINAPI rdpThreadRun(SdlContext* sdl); + [[nodiscard]] SDL_FPoint applyLocalScaling(const SDL_FPoint& val) const; + void removeLocalScaling(float& x, float& y); + [[nodiscard]] bool createPrimary(); [[nodiscard]] std::string windowTitle() const; [[nodiscard]] bool waitForWindowsCreated(); @@ -167,6 +170,7 @@ class SdlContext using SDLSurfacePtr = std::unique_ptr; SDLSurfacePtr _primary; + SDL_FPoint _localScale{ 1.0f, 1.0f }; sdlDispContext _disp; sdlInput _input; diff --git a/client/SDL/SDL3/sdl_window.cpp b/client/SDL/SDL3/sdl_window.cpp index 54f95f82b..be1241d3e 100644 --- a/client/SDL/SDL3/sdl_window.cpp +++ b/client/SDL/SDL3/sdl_window.cpp @@ -251,24 +251,27 @@ bool SdlWindow::drawRects(SDL_Surface* surface, SDL_Point offset, return true; } -bool SdlWindow::drawScaledRect(SDL_Surface* surface, const SDL_Rect& srcRect) +bool SdlWindow::drawScaledRect(SDL_Surface* surface, const SDL_FPoint& scale, + 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); + dstRect.x = static_cast(static_cast(dstRect.x) * scale.x); + dstRect.w = static_cast(static_cast(dstRect.w) * scale.x); + dstRect.y = static_cast(static_cast(dstRect.y) * scale.y); + dstRect.h = static_cast(static_cast(dstRect.h) * scale.y); return blit(surface, srcRect, dstRect); } -bool SdlWindow::drawScaledRects(SDL_Surface* surface, const std::vector& rects) +bool SdlWindow::drawScaledRects(SDL_Surface* surface, const SDL_FPoint& scale, + const std::vector& rects) { if (rects.empty()) { - return drawScaledRect(surface, { 0, 0, surface->w, surface->h }); + return drawScaledRect(surface, scale, { 0, 0, surface->w, surface->h }); } for (const auto& srcRect : rects) { - if (!drawScaledRect(surface, srcRect)) + if (!drawScaledRect(surface, scale, srcRect)) return false; } return true; diff --git a/client/SDL/SDL3/sdl_window.hpp b/client/SDL/SDL3/sdl_window.hpp index 7d40dafc6..c2a8e5973 100644 --- a/client/SDL/SDL3/sdl_window.hpp +++ b/client/SDL/SDL3/sdl_window.hpp @@ -69,9 +69,10 @@ class SdlWindow [[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 drawScaledRect(SDL_Surface* surface, const SDL_FPoint& scale, + const SDL_Rect& srcRect); - [[nodiscard]] bool drawScaledRects(SDL_Surface* surface, + [[nodiscard]] bool drawScaledRects(SDL_Surface* surface, const SDL_FPoint& scale, const std::vector& rects = {}); [[nodiscard]] bool fill(Uint8 r = 0x00, Uint8 g = 0x00, Uint8 b = 0x00, Uint8 a = 0xff); From e3d3bc363cbcc2dad74430f1083130778ffa64d2 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 12:02:53 +0100 Subject: [PATCH 16/30] [client,sdl] add util stringify functions --- client/SDL/SDL3/sdl_utils.cpp | 55 ++++++++++++++++++++++------------- client/SDL/SDL3/sdl_utils.hpp | 1 + 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/client/SDL/SDL3/sdl_utils.cpp b/client/SDL/SDL3/sdl_utils.cpp index 30ffa37d7..c1890ddcd 100644 --- a/client/SDL/SDL3/sdl_utils.cpp +++ b/client/SDL/SDL3/sdl_utils.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "sdl_utils.hpp" @@ -29,6 +30,7 @@ #include #include +#include #define STR(x) #x #define EV_CASE_STR(x) \ @@ -172,6 +174,26 @@ namespace sdl::utils } } + std::string touchFlagsToString(Uint32 flags) + { + std::stringstream ss; + ss << "{"; + bool first = true; + for (size_t x = 0; x < 32; x++) + { + const Uint32 mask = 1u << x; + if (flags & mask) + { + if (!first) + ss << "|"; + first = false; + ss << freerdp_input_touch_state_string(mask); + } + } + ss << "}"; + return ss.str(); + } + std::string toString(SDL_DisplayOrientation orientation) { switch (orientation) @@ -185,30 +207,18 @@ namespace sdl::utils case SDL_ORIENTATION_PORTRAIT: return "SDL_ORIENTATION_PORTRAIT"; default: - return "SDL_ORIENTATION_UNKNOWN"; + { + std::stringstream ss; + ss << "SDL_ORIENTATION_UNKNOWN[0x" << std::hex << std::setw(8) << std::setfill('0') + << orientation << "]"; + return ss.str(); + } } } std::string toString(FreeRDP_DesktopRotationFlags orientation) { - switch (orientation) - { - case ORIENTATION_LANDSCAPE: - return "ORIENTATION_LANDSCAPE"; - case ORIENTATION_LANDSCAPE_FLIPPED: - return "ORIENTATION_LANDSCAPE_FLIPPED"; - case ORIENTATION_PORTRAIT_FLIPPED: - return "ORIENTATION_PORTRAIT_FLIPPED"; - case ORIENTATION_PORTRAIT: - return "ORIENTATION_PORTRAIT"; - default: - { - std::stringstream ss; - ss << "ORIENTATION_UNKNOWN_" << std::hex << std::setfill('0') << std::setw(8) - << orientation; - return ss.str(); - } - } + return freerdp_desktop_rotation_flags_to_string(orientation); } std::string toString(const SDL_DisplayMode* mode) @@ -368,7 +378,12 @@ namespace sdl::utils EV_CASE_STR(SDL_EVENT_LAST); default: - return "SDL_UNKNOWNEVENT"; + { + std::stringstream ss; + ss << "SDL_UNKNOWNEVENT[0x" << std::hex << std::setw(8) << std::setfill('0') << type + << "]"; + return ss.str(); + } } } diff --git a/client/SDL/SDL3/sdl_utils.hpp b/client/SDL/SDL3/sdl_utils.hpp index 280cbf9f1..b4b449406 100644 --- a/client/SDL/SDL3/sdl_utils.hpp +++ b/client/SDL/SDL3/sdl_utils.hpp @@ -81,6 +81,7 @@ typedef struct namespace sdl::utils { + [[nodiscard]] std::string touchFlagsToString(Uint32 flags); [[nodiscard]] std::string toString(enum FreeRDP_DesktopRotationFlags orientation); [[nodiscard]] std::string toString(SDL_DisplayOrientation orientation); [[nodiscard]] std::string toString(const SDL_DisplayMode* mode); From 02a9d611828dd1ced36610db1e9815c909e868f4 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 12:03:29 +0100 Subject: [PATCH 17/30] [client,sdl] remove unused channel function definitions --- client/SDL/SDL3/sdl_channels.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/SDL/SDL3/sdl_channels.hpp b/client/SDL/SDL3/sdl_channels.hpp index 5c0e243df..19800cac4 100644 --- a/client/SDL/SDL3/sdl_channels.hpp +++ b/client/SDL/SDL3/sdl_channels.hpp @@ -22,9 +22,5 @@ #include #include -[[nodiscard]] int sdl_on_channel_connected(freerdp* instance, const char* name, void* pInterface); -[[nodiscard]] int sdl_on_channel_disconnected(freerdp* instance, const char* name, - void* pInterface); - void sdl_OnChannelConnectedEventHandler(void* context, const ChannelConnectedEventArgs* e); void sdl_OnChannelDisconnectedEventHandler(void* context, const ChannelDisconnectedEventArgs* e); From 2e7639d903a69bb30f51f2cbfa1739332d5e77f0 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 12:14:36 +0100 Subject: [PATCH 18/30] [client,sdl] add coordinat conversion functions * pixel to screen mapper * screen to pixel mapper * local scaling add/remove for smart-sizing --- client/SDL/SDL3/sdl_context.cpp | 49 +++++++++++++++++++++++++++++++++ client/SDL/SDL3/sdl_context.hpp | 7 +++++ 2 files changed, 56 insertions(+) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index e3c0e6878..0942de432 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -927,6 +927,17 @@ bool SdlContext::handleEvent(const SDL_DisplayEvent* ev) return true; } +bool SdlContext::eventToPixelCoordinates(SDL_WindowID id, SDL_Event& ev) +{ + auto w = getWindowForId(id); + if (!w) + return false; + auto renderer = SDL_GetRenderer(w->window()); + if (!renderer) + return false; + return SDL_ConvertEventToRenderCoordinates(renderer, &ev); +} + SDL_FPoint SdlContext::applyLocalScaling(const SDL_FPoint& val) const { if (!freerdp_settings_get_bool(context()->settings, FreeRDP_SmartSizing)) @@ -946,6 +957,44 @@ void SdlContext::removeLocalScaling(float& x, float& y) y /= _localScale.y; } +SDL_FPoint SdlContext::screenToPixel(SDL_WindowID id, const SDL_FPoint& pos) +{ + auto w = getWindowForId(id); + if (!w) + return {}; + auto renderer = SDL_GetRenderer(w->window()); + if (!renderer) + return {}; + + SDL_FPoint rpos{}; + if (!SDL_RenderCoordinatesFromWindow(renderer, pos.x, pos.y, &rpos.x, &rpos.y)) + return {}; + removeLocalScaling(rpos.x, rpos.y); + return rpos; +} + +SDL_FPoint SdlContext::pixelToScreen(SDL_WindowID id, const SDL_FPoint& pos) +{ + auto w = getWindowForId(id); + if (!w) + return {}; + auto renderer = SDL_GetRenderer(w->window()); + if (!renderer) + return {}; + + SDL_FPoint rpos{}; + if (!SDL_RenderCoordinatesToWindow(renderer, pos.x, pos.y, &rpos.x, &rpos.y)) + return {}; + return applyLocalScaling(rpos); +} + +SDL_FRect SdlContext::pixelToScreen(SDL_WindowID id, const SDL_FRect& pos) +{ + const auto fpos = pixelToScreen(id, SDL_FPoint{ pos.x, pos.y }); + const auto size = pixelToScreen(id, SDL_FPoint{ pos.w, pos.h }); + return { fpos.x, fpos.y, size.x, size.y }; +} + bool SdlContext::drawToWindows(const std::vector& rects) { for (auto& window : _windows) diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index 9b945f107..4b98a8807 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -120,6 +120,11 @@ class SdlContext [[nodiscard]] wLog* getWLog(); + [[nodiscard]] SDL_FPoint screenToPixel(SDL_WindowID id, const SDL_FPoint& pos); + + [[nodiscard]] SDL_FPoint pixelToScreen(SDL_WindowID id, const SDL_FPoint& pos); + [[nodiscard]] SDL_FRect pixelToScreen(SDL_WindowID id, const SDL_FRect& pos); + [[nodiscard]] bool handleEvent(const SDL_WindowEvent* ev); [[nodiscard]] bool handleEvent(const SDL_DisplayEvent* ev); @@ -134,6 +139,8 @@ class SdlContext [[nodiscard]] static BOOL endPaint(rdpContext* context); [[nodiscard]] static DWORD WINAPI rdpThreadRun(SdlContext* sdl); + [[nodiscard]] bool eventToPixelCoordinates(SDL_WindowID id, SDL_Event& ev); + [[nodiscard]] SDL_FPoint applyLocalScaling(const SDL_FPoint& val) const; void removeLocalScaling(float& x, float& y); From c6b104cce03a583fd55ea50de25459cb3324d8a7 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 12:16:16 +0100 Subject: [PATCH 19/30] [client,sdl] wrap mouse cursor move in SdlContext --- client/SDL/SDL3/sdl_context.cpp | 12 ++++++++++++ client/SDL/SDL3/sdl_context.hpp | 2 ++ client/SDL/SDL3/sdl_freerdp.cpp | 15 +++------------ 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index 0942de432..016fd1831 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -840,6 +840,18 @@ wLog* SdlContext::getWLog() return _log; } +bool SdlContext::moveMouseTo(const SDL_FPoint& pos) +{ + auto window = SDL_GetMouseFocus(); + if (!window) + return true; + + const auto id = SDL_GetWindowID(window); + const auto spos = pixelToScreen(id, pos); + SDL_WarpMouseInWindow(window, spos.x, spos.y); + return true; +} + bool SdlContext::handleEvent(const SDL_WindowEvent* ev) { diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index 4b98a8807..0cbee1c64 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -120,6 +120,8 @@ class SdlContext [[nodiscard]] wLog* getWLog(); + [[nodiscard]] bool moveMouseTo(const SDL_FPoint& pos); + [[nodiscard]] SDL_FPoint screenToPixel(SDL_WindowID id, const SDL_FPoint& pos); [[nodiscard]] SDL_FPoint pixelToScreen(SDL_WindowID id, const SDL_FPoint& pos); diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 613674bd2..0af737663 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -288,18 +288,9 @@ static int sdl_run(SdlContext* sdl) static_cast(reinterpret_cast(windowEvent.user.data1)); const auto y = static_cast(reinterpret_cast(windowEvent.user.data2)); - - SDL_Window* window = SDL_GetMouseFocus(); - if (window) - { - const Uint32 id = SDL_GetWindowID(window); - - INT32 sx = x; - INT32 sy = y; - if (sdl_scale_coordinates(sdl, id, &sx, &sy, FALSE, FALSE)) - SDL_WarpMouseInWindow(window, static_cast(sx), - static_cast(sy)); - } + if (!sdl->moveMouseTo( + { static_cast(x) * 1.0f, static_cast(y) * 1.0f })) + return -1; } break; case SDL_EVENT_USER_POINTER_SET: From 7f434db04a0def15906c078aff253cf2bdf02e33 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 12:21:15 +0100 Subject: [PATCH 20/30] [client,sdl] use SdlContext scaling functions --- client/SDL/SDL3/sdl_kbd.cpp | 18 +++++------------- client/SDL/SDL3/sdl_pointer.cpp | 26 +++++++++++++------------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/client/SDL/SDL3/sdl_kbd.cpp b/client/SDL/SDL3/sdl_kbd.cpp index a0c171d1b..bd9ad14d9 100644 --- a/client/SDL/SDL3/sdl_kbd.cpp +++ b/client/SDL/SDL3/sdl_kbd.cpp @@ -319,23 +319,15 @@ BOOL sdlInput::keyboard_focus_in() float fx = 0.0f; float fy = 0.0f; if (_sdl->fullscreen()) - { SDL_GetGlobalMouseState(&fx, &fy); - } else - { SDL_GetMouseState(&fx, &fy); - } - auto x = static_cast(fx); - auto y = static_cast(fy); + auto w = SDL_GetMouseFocus(); - if (w) - { - auto id = SDL_GetWindowID(w); - if (!sdl_scale_coordinates(_sdl, id, &x, &y, TRUE, TRUE)) - return FALSE; - } - return freerdp_client_send_button_event(_sdl->common(), FALSE, PTR_FLAGS_MOVE, x, y); + const auto& pos = _sdl->screenToPixel(SDL_GetWindowID(w), SDL_FPoint{ fx, fy }); + + return freerdp_client_send_button_event(_sdl->common(), FALSE, PTR_FLAGS_MOVE, + static_cast(pos.x), static_cast(pos.y)); } /* This function is called to update the keyboard indicator LED */ diff --git a/client/SDL/SDL3/sdl_pointer.cpp b/client/SDL/SDL3/sdl_pointer.cpp index c8793bd13..55b90275e 100644 --- a/client/SDL/SDL3/sdl_pointer.cpp +++ b/client/SDL/SDL3/sdl_pointer.cpp @@ -119,10 +119,10 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) rdpGdi* gdi = context->gdi; WINPR_ASSERT(gdi); - auto x = static_cast(pointer->xPos); - auto y = static_cast(pointer->yPos); - auto sw = w = static_cast(pointer->width); - auto sh = h = static_cast(pointer->height); + auto ix = static_cast(pointer->xPos); + auto iy = static_cast(pointer->yPos); + auto isw = w = static_cast(pointer->width); + auto ish = h = static_cast(pointer->height); SDL_Window* window = SDL_GetMouseFocus(); if (!window) @@ -130,13 +130,12 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) const Uint32 id = SDL_GetWindowID(window); - if (!sdl_scale_coordinates(sdl, id, &x, &y, FALSE, FALSE) || - !sdl_scale_coordinates(sdl, id, &sw, &sh, FALSE, FALSE)) - return FALSE; + auto pos = sdl->pixelToScreen(id, SDL_FRect{ ix * 1.0f, iy * 1.0f, isw * 1.0f, ish * 1.0f }); sdl_Pointer_Clear(ptr); - ptr->image = SDL_CreateSurface(sw, sh, sdl->pixelFormat()); + ptr->image = + SDL_CreateSurface(static_cast(pos.w), static_cast(pos.h), sdl->pixelFormat()); if (!ptr->image) return FALSE; @@ -157,16 +156,17 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) if (!fw) return FALSE; - const auto hidpi_scale = SDL_GetWindowDisplayScale(fw->window()); - auto normal = SDL_CreateSurface( - static_cast(static_cast(ptr->image->w) / hidpi_scale), - static_cast(static_cast(ptr->image->h) / hidpi_scale), ptr->image->format); + const auto hidpi_scale = + sdl->pixelToScreen(fw->id(), SDL_FPoint{ static_cast(ptr->image->w), + static_cast(ptr->image->h) }); + auto normal = SDL_CreateSurface(static_cast(hidpi_scale.x), + static_cast(hidpi_scale.y), ptr->image->format); assert(normal); SDL_BlitSurfaceScaled(ptr->image, nullptr, normal, nullptr, SDL_ScaleMode::SDL_SCALEMODE_LINEAR); SDL_AddSurfaceAlternateImage(normal, ptr->image); - ptr->cursor = SDL_CreateColorCursor(normal, x, y); + ptr->cursor = SDL_CreateColorCursor(normal, static_cast(pos.x), static_cast(pos.y)); if (!ptr->cursor) return FALSE; From 9468720d93528788e471dbc77db84c24650f7ed5 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 12:22:18 +0100 Subject: [PATCH 21/30] [client,sdl] refactor sdlInput * fix return types, use standard types instead of WinPR ones * rename files, match class names --- client/SDL/SDL3/CMakeLists.txt | 4 +- client/SDL/SDL3/sdl_context.hpp | 2 +- client/SDL/SDL3/sdl_disp.cpp | 2 +- client/SDL/SDL3/sdl_freerdp.cpp | 2 +- .../SDL/SDL3/{sdl_kbd.cpp => sdl_input.cpp} | 47 +++++++++---------- .../SDL/SDL3/{sdl_kbd.hpp => sdl_input.hpp} | 14 +++--- 6 files changed, 34 insertions(+), 37 deletions(-) rename client/SDL/SDL3/{sdl_kbd.cpp => sdl_input.cpp} (97%) rename client/SDL/SDL3/{sdl_kbd.hpp => sdl_input.hpp} (87%) diff --git a/client/SDL/SDL3/CMakeLists.txt b/client/SDL/SDL3/CMakeLists.txt index f0a6eaff3..3ccff8794 100644 --- a/client/SDL/SDL3/CMakeLists.txt +++ b/client/SDL/SDL3/CMakeLists.txt @@ -27,8 +27,8 @@ set(SRCS sdl_types.hpp sdl_utils.cpp sdl_utils.hpp - sdl_kbd.cpp - sdl_kbd.hpp + sdl_input.cpp + sdl_input.hpp sdl_touch.cpp sdl_touch.hpp sdl_pointer.cpp diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index 0cbee1c64..f5afffd41 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -36,7 +36,7 @@ #include "sdl_window.hpp" #include "sdl_disp.hpp" #include "sdl_clip.hpp" -#include "sdl_kbd.hpp" +#include "sdl_input.hpp" #include "dialogs/sdl_connection_dialog_wrapper.hpp" diff --git a/client/SDL/SDL3/sdl_disp.cpp b/client/SDL/SDL3/sdl_disp.cpp index a23034e7a..0bc8d486c 100644 --- a/client/SDL/SDL3/sdl_disp.cpp +++ b/client/SDL/SDL3/sdl_disp.cpp @@ -26,7 +26,7 @@ #include #include "sdl_disp.hpp" -#include "sdl_kbd.hpp" +#include "sdl_input.hpp" #include "sdl_utils.hpp" #include "sdl_context.hpp" diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 0af737663..466e34e93 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -62,7 +62,7 @@ #include "sdl_disp.hpp" #include "sdl_freerdp.hpp" #include "sdl_context.hpp" -#include "sdl_kbd.hpp" +#include "sdl_input.hpp" #include "sdl_monitor.hpp" #include "sdl_pointer.hpp" #include "sdl_prefs.hpp" diff --git a/client/SDL/SDL3/sdl_kbd.cpp b/client/SDL/SDL3/sdl_input.cpp similarity index 97% rename from client/SDL/SDL3/sdl_kbd.cpp rename to client/SDL/SDL3/sdl_input.cpp index bd9ad14d9..7866f7798 100644 --- a/client/SDL/SDL3/sdl_kbd.cpp +++ b/client/SDL/SDL3/sdl_input.cpp @@ -17,7 +17,7 @@ * limitations under the License. */ -#include "sdl_kbd.hpp" +#include "sdl_input.hpp" #include "sdl_disp.hpp" #include "sdl_context.hpp" #include "sdl_utils.hpp" @@ -44,10 +44,7 @@ typedef struct } scancode_entry_t; #define STR(x) #x -#define ENTRY(x, y) \ - { \ - x, STR(x), y, #y \ - } +#define ENTRY(x, y) { x, STR(x), y, #y } static const scancode_entry_t map[] = { ENTRY(SDL_SCANCODE_UNKNOWN, RDP_SCANCODE_UNKNOWN), ENTRY(SDL_SCANCODE_A, RDP_SCANCODE_KEY_A), @@ -300,13 +297,13 @@ static const scancode_entry_t map[] = { return flags; } -BOOL sdlInput::keyboard_sync_state() +bool sdlInput::keyboard_sync_state() { const UINT32 syncFlags = sdl_get_kbd_flags(); return freerdp_input_send_synchronize_event(_sdl->context()->input, syncFlags); } -BOOL sdlInput::keyboard_focus_in() +bool sdlInput::keyboard_focus_in() { auto input = _sdl->context()->input; WINPR_ASSERT(input); @@ -561,7 +558,7 @@ bool sdlInput::extract(const std::string& token, uint32_t& key, uint32_t& value) return freerdp_extract_key_value(token.c_str(), &key, &value); } -BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) +bool sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) { WINPR_ASSERT(ev); const UINT32 rdp_scancode = scancode_to_rdp(ev->scancode); @@ -576,7 +573,7 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling fullscreen state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyFullscreen)); if (!keyboard_sync_state()) - return FALSE; + return false; return _sdl->toggleFullscreen(); } if (ev->scancode == _hotkeyResizable) @@ -584,7 +581,7 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling resizeable state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyResizable)); if (!keyboard_sync_state()) - return FALSE; + return false; return _sdl->toggleResizeable(); } @@ -593,7 +590,7 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling grab state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyGrab)); if (!keyboard_sync_state()) - return FALSE; + return false; return keyboard_grab(ev->windowID, !_sdl->grabKeyboard()); } if (ev->scancode == _hotkeyDisconnect) @@ -601,16 +598,16 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, disconnecting RDP session", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyDisconnect)); if (!keyboard_sync_state()) - return FALSE; + return false; freerdp_abort_connect_context(_sdl->context()); - return TRUE; + return true; } if (ev->scancode == _hotkeyMinimize) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, minimizing client", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyMinimize)); if (!keyboard_sync_state()) - return FALSE; + return false; return _sdl->setMinimized(); } } @@ -641,11 +638,11 @@ BOOL sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) _sdl->context()->input, ev->type == SDL_EVENT_KEY_DOWN, ev->repeat, scancode); } -BOOL sdlInput::keyboard_grab(Uint32 windowID, bool enable) +bool sdlInput::keyboard_grab(Uint32 windowID, bool enable) { const auto window = _sdl->getWindowForId(windowID); if (!window) - return FALSE; + return false; auto settings = _sdl->context()->settings; auto kbd_enabled = freerdp_settings_get_bool(settings, FreeRDP_GrabKeyboard); @@ -655,25 +652,25 @@ BOOL sdlInput::keyboard_grab(Uint32 windowID, bool enable) return window->grabKeyboard(status); } -BOOL sdlInput::mouse_focus(Uint32 windowID) +bool sdlInput::mouse_focus(Uint32 windowID) { if (_lastWindowID != windowID) { _lastWindowID = windowID; auto window = _sdl->getWindowForId(windowID); if (!window) - return FALSE; + return false; window->raise(); } - return TRUE; + return true; } -BOOL sdlInput::mouse_grab(Uint32 windowID, bool enable) +bool sdlInput::mouse_grab(Uint32 windowID, bool enable) { auto window = _sdl->getWindowForId(windowID); if (!window) - return FALSE; + return false; if (!_sdl->setGrabMouse(enable)) WLog_Print(_sdl->getWLog(), WLOG_WARN, "Failed to ungrab mouse"); return window->grabMouse(enable); @@ -695,7 +692,7 @@ sdlInput::~sdlInput() freerdp_keyboard_remap_free(_remapTable); } -BOOL sdlInput::initialize() +bool sdlInput::initialize() { auto settings = _sdl->context()->settings; WINPR_ASSERT(settings); @@ -705,7 +702,7 @@ BOOL sdlInput::initialize() auto list = freerdp_settings_get_string(settings, FreeRDP_KeyboardRemappingList); _remapTable = freerdp_keyboard_remap_string_to_list(list); if (!_remapTable) - return FALSE; + return false; } if (freerdp_settings_get_uint32(settings, FreeRDP_KeyboardLayout) == 0) @@ -717,7 +714,7 @@ BOOL sdlInput::initialize() KeyboardLayout = ENGLISH_UNITED_STATES; if (!freerdp_settings_set_uint32(settings, FreeRDP_KeyboardLayout, KeyboardLayout)) - return FALSE; + return false; } - return TRUE; + return true; } diff --git a/client/SDL/SDL3/sdl_kbd.hpp b/client/SDL/SDL3/sdl_input.hpp similarity index 87% rename from client/SDL/SDL3/sdl_kbd.hpp rename to client/SDL/SDL3/sdl_input.hpp index 522def3b6..2e392c4e6 100644 --- a/client/SDL/SDL3/sdl_kbd.hpp +++ b/client/SDL/SDL3/sdl_input.hpp @@ -42,16 +42,16 @@ class sdlInput sdlInput& operator=(const sdlInput& other) = delete; sdlInput& operator=(sdlInput&& other) = delete; - [[nodiscard]] BOOL initialize(); + [[nodiscard]] bool initialize(); - [[nodiscard]] BOOL keyboard_sync_state(); - [[nodiscard]] BOOL keyboard_focus_in(); + [[nodiscard]] bool keyboard_sync_state(); + [[nodiscard]] bool keyboard_focus_in(); - [[nodiscard]] BOOL keyboard_handle_event(const SDL_KeyboardEvent* ev); + [[nodiscard]] bool keyboard_handle_event(const SDL_KeyboardEvent* ev); - [[nodiscard]] BOOL keyboard_grab(Uint32 windowID, bool enable); - [[nodiscard]] BOOL mouse_focus(Uint32 windowID); - [[nodiscard]] BOOL mouse_grab(Uint32 windowID, bool enable); + [[nodiscard]] bool keyboard_grab(Uint32 windowID, bool enable); + [[nodiscard]] bool mouse_focus(Uint32 windowID); + [[nodiscard]] bool mouse_grab(Uint32 windowID, bool enable); [[nodiscard]] static BOOL keyboard_set_indicators(rdpContext* context, UINT16 led_flags); [[nodiscard]] static BOOL keyboard_set_ime_status(rdpContext* context, UINT16 imeId, From 947427a9118c770c517bd91170bf905a68a7d3a3 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 12:28:38 +0100 Subject: [PATCH 22/30] [client,sdl] simplify event handling pass on events to SdlContext and let the class handle it internally --- client/SDL/SDL3/sdl_context.cpp | 155 ++++++++++++++++++++++------ client/SDL/SDL3/sdl_context.hpp | 10 +- client/SDL/SDL3/sdl_disp.cpp | 79 +++++++------- client/SDL/SDL3/sdl_disp.hpp | 6 +- client/SDL/SDL3/sdl_freerdp.cpp | 112 ++++---------------- client/SDL/SDL3/sdl_touch.cpp | 175 ++++++++++---------------------- client/SDL/SDL3/sdl_touch.hpp | 21 ++-- 7 files changed, 251 insertions(+), 307 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index 016fd1831..d99021e16 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -21,6 +21,7 @@ #include "sdl_channels.hpp" #include "sdl_monitor.hpp" #include "sdl_pointer.hpp" +#include "sdl_touch.hpp" #include #include @@ -519,7 +520,7 @@ void SdlContext::sdl_client_cleanup(int exit_code, const std::string& error_msg) getDialog().show(false); _exitCode = exit_code; - (void)sdl_push_user_event(SDL_EVENT_USER_QUIT); + std::ignore = sdl_push_user_event(SDL_EVENT_USER_QUIT); SDL_CleanupTLS(); } @@ -852,13 +853,34 @@ bool SdlContext::moveMouseTo(const SDL_FPoint& pos) return true; } -bool SdlContext::handleEvent(const SDL_WindowEvent* ev) +bool SdlContext::handleEvent(const SDL_MouseMotionEvent& ev) { + SDL_Event copy{}; + copy.motion = ev; + if (!eventToPixelCoordinates(ev.windowID, copy)) + return false; + removeLocalScaling(copy.motion.x, copy.motion.y); + removeLocalScaling(copy.motion.xrel, copy.motion.yrel); + return SdlTouch::handleEvent(this, copy.motion); +} + +bool SdlContext::handleEvent(const SDL_MouseWheelEvent& ev) +{ + SDL_Event copy{}; + copy.wheel = ev; + if (!eventToPixelCoordinates(ev.windowID, copy)) + return false; + removeLocalScaling(copy.wheel.mouse_x, copy.wheel.mouse_y); + return SdlTouch::handleEvent(this, copy.wheel); +} + +bool SdlContext::handleEvent(const SDL_WindowEvent& ev) +{ if (!getDisplayChannelContext().handleEvent(ev)) return false; - auto window = getWindowForId(ev->windowID); + auto window = getWindowForId(ev.windowID); if (!window) return true; @@ -869,30 +891,31 @@ bool SdlContext::handleEvent(const SDL_WindowEvent* ev) const auto& orientation = window->orientation(); SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "%s: [%u] %dx%d-%dx%d {%dx%d-%dx%d}{scale=%f,orientation=%s}", - sdl::utils::toString(ev->type).c_str(), ev->windowID, r.x, r.y, r.w, r.h, b.x, - b.y, b.w, b.h, scale, sdl::utils::toString(orientation).c_str()); + sdl::utils::toString(ev.type).c_str(), ev.windowID, r.x, r.y, r.w, r.h, b.x, + b.y, b.w, b.h, static_cast(scale), + sdl::utils::toString(orientation).c_str()); } - switch (ev->type) + switch (ev.type) { case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: if (isConnected()) { if (!window->fill()) - return -1; + return false; if (!drawToWindow(*window)) - return -1; + return false; if (!sdl_Pointer_Set_Process(this)) - return -1; + return false; } break; case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: if (!window->fill()) - return -1; + return false; if (!drawToWindow(*window)) - return -1; + return false; if (!sdl_Pointer_Set_Process(this)) - return -1; + return false; break; case SDL_EVENT_WINDOW_MOVED: { @@ -913,32 +936,61 @@ bool SdlContext::handleEvent(const SDL_WindowEvent* ev) return true; } -bool SdlContext::handleEvent(const SDL_DisplayEvent* ev) +bool SdlContext::handleEvent(const SDL_DisplayEvent& ev) { - if (!getDisplayChannelContext().handleEvent(ev)) return false; - { - SDL_Rect r = {}; - if (!SDL_GetDisplayBounds(ev->displayID, &r)) - return false; - const auto name = SDL_GetDisplayName(ev->displayID); - if (!name) - return false; - const auto orientation = SDL_GetCurrentDisplayOrientation(ev->displayID); - const auto scale = SDL_GetDisplayContentScale(ev->displayID); - const auto mode = SDL_GetCurrentDisplayMode(ev->displayID); - if (!mode) - return false; - SDL_LogDebug( - SDL_LOG_CATEGORY_APPLICATION, "%s: [%u, %s] %dx%d-%dx%d {orientation=%s, scale=%f}%s", - sdl::utils::toString(ev->type).c_str(), ev->displayID, name, r.x, r.y, r.w, r.h, - sdl::utils::toString(orientation).c_str(), scale, sdl::utils::toString(mode).c_str()); + switch (ev.type) + { + case SDL_EVENT_DISPLAY_REMOVED: // Can't show details for this one... + break; + default: + { + SDL_Rect r = {}; + if (!SDL_GetDisplayBounds(ev.displayID, &r)) + return false; + const auto name = SDL_GetDisplayName(ev.displayID); + if (!name) + return false; + const auto orientation = SDL_GetCurrentDisplayOrientation(ev.displayID); + const auto scale = SDL_GetDisplayContentScale(ev.displayID); + const auto mode = SDL_GetCurrentDisplayMode(ev.displayID); + if (!mode) + return false; + + SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, + "%s: [%u, %s] %dx%d-%dx%d {orientation=%s, scale=%f}%s", + sdl::utils::toString(ev.type).c_str(), ev.displayID, name, r.x, r.y, r.w, + r.h, sdl::utils::toString(orientation).c_str(), static_cast(scale), + sdl::utils::toString(mode).c_str()); + } + break; } return true; } +bool SdlContext::handleEvent(const SDL_MouseButtonEvent& ev) +{ + SDL_Event copy = {}; + copy.button = ev; + if (!eventToPixelCoordinates(ev.windowID, copy)) + return false; + removeLocalScaling(copy.button.x, copy.button.y); + return SdlTouch::handleEvent(this, copy.button); +} + +bool SdlContext::handleEvent(const SDL_TouchFingerEvent& ev) +{ + SDL_Event copy{}; + copy.tfinger = ev; + if (!eventToPixelCoordinates(ev.windowID, copy)) + return false; + removeLocalScaling(copy.tfinger.dx, copy.tfinger.dy); + removeLocalScaling(copy.tfinger.x, copy.tfinger.y); + return SdlTouch::handleEvent(this, copy.tfinger); +} + bool SdlContext::eventToPixelCoordinates(SDL_WindowID id, SDL_Event& ev) { auto w = getWindowForId(id); @@ -1007,6 +1059,49 @@ SDL_FRect SdlContext::pixelToScreen(SDL_WindowID id, const SDL_FRect& pos) return { fpos.x, fpos.y, size.x, size.y }; } +bool SdlContext::handleEvent(const SDL_Event& windowEvent) +{ + if ((windowEvent.type >= SDL_EVENT_DISPLAY_FIRST) && + (windowEvent.type <= SDL_EVENT_DISPLAY_LAST)) + { + const auto& ev = windowEvent.display; + return handleEvent(ev); + } + if ((windowEvent.type >= SDL_EVENT_WINDOW_FIRST) && (windowEvent.type <= SDL_EVENT_WINDOW_LAST)) + { + const auto& ev = windowEvent.window; + return handleEvent(ev); + } + switch (windowEvent.type) + { + case SDL_EVENT_FINGER_DOWN: + case SDL_EVENT_FINGER_UP: + case SDL_EVENT_FINGER_MOTION: + { + const auto& ev = windowEvent.tfinger; + return handleEvent(ev); + } + case SDL_EVENT_MOUSE_MOTION: + { + const auto& ev = windowEvent.motion; + return handleEvent(ev); + } + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: + { + const auto& ev = windowEvent.button; + return handleEvent(ev); + } + case SDL_EVENT_MOUSE_WHEEL: + { + const auto& ev = windowEvent.wheel; + return handleEvent(ev); + } + default: + return true; + } +} + bool SdlContext::drawToWindows(const std::vector& rects) { for (auto& window : _windows) diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index f5afffd41..ddab25f87 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -127,8 +127,7 @@ class SdlContext [[nodiscard]] SDL_FPoint pixelToScreen(SDL_WindowID id, const SDL_FPoint& pos); [[nodiscard]] SDL_FRect pixelToScreen(SDL_WindowID id, const SDL_FRect& pos); - [[nodiscard]] bool handleEvent(const SDL_WindowEvent* ev); - [[nodiscard]] bool handleEvent(const SDL_DisplayEvent* ev); + [[nodiscard]] bool handleEvent(const SDL_Event& ev); private: [[nodiscard]] static BOOL preConnect(freerdp* instance); @@ -146,6 +145,13 @@ class SdlContext [[nodiscard]] SDL_FPoint applyLocalScaling(const SDL_FPoint& val) const; void removeLocalScaling(float& x, float& y); + [[nodiscard]] bool handleEvent(const SDL_WindowEvent& ev); + [[nodiscard]] bool handleEvent(const SDL_DisplayEvent& ev); + [[nodiscard]] bool handleEvent(const SDL_MouseButtonEvent& ev); + [[nodiscard]] bool handleEvent(const SDL_MouseMotionEvent& ev); + [[nodiscard]] bool handleEvent(const SDL_MouseWheelEvent& ev); + [[nodiscard]] bool handleEvent(const SDL_TouchFingerEvent& ev); + [[nodiscard]] bool createPrimary(); [[nodiscard]] std::string windowTitle() const; [[nodiscard]] bool waitForWindowsCreated(); diff --git a/client/SDL/SDL3/sdl_disp.cpp b/client/SDL/SDL3/sdl_disp.cpp index 0bc8d486c..4478f070d 100644 --- a/client/SDL/SDL3/sdl_disp.cpp +++ b/client/SDL/SDL3/sdl_disp.cpp @@ -27,7 +27,6 @@ #include "sdl_disp.hpp" #include "sdl_input.hpp" -#include "sdl_utils.hpp" #include "sdl_context.hpp" #include @@ -85,7 +84,7 @@ bool sdlDispContext::sendResize() const UINT32 mcount = freerdp_settings_get_uint32(settings, FreeRDP_MonitorCount); auto monitors = static_cast( freerdp_settings_get_pointer(settings, FreeRDP_MonitorDefArray)); - return sendLayout(monitors, mcount) != CHANNEL_RC_OK; + return sendLayout(monitors, mcount); } bool sdlDispContext::setWindowResizeable() @@ -131,7 +130,7 @@ void sdlDispContext::OnActivated(void* context, const ActivatedEventArgs* e) if (e->firstActivation) return; - (void)sdlDisp->addTimer(); + std::ignore = sdlDisp->addTimer(); } } @@ -150,7 +149,7 @@ void sdlDispContext::OnGraphicsReset(void* context, const GraphicsResetEventArgs if (sdlDisp->_activated && !freerdp_settings_get_bool(settings, FreeRDP_Fullscreen)) { if (sdlDisp->setWindowResizeable()) - (void)sdlDisp->addTimer(); + std::ignore = sdlDisp->addTimer(); } } @@ -186,10 +185,8 @@ Uint32 sdlDispContext::OnTimer(void* param, [[maybe_unused]] SDL_TimerID timerID return interval; } -UINT sdlDispContext::sendLayout(const rdpMonitor* monitors, size_t nmonitors) +bool sdlDispContext::sendLayout(const rdpMonitor* monitors, size_t nmonitors) { - UINT ret = CHANNEL_RC_OK; - WINPR_ASSERT(monitors); WINPR_ASSERT(nmonitors > 0); @@ -261,12 +258,12 @@ UINT sdlDispContext::sendLayout(const rdpMonitor* monitors, size_t nmonitors) WINPR_ASSERT(_disp); const size_t len = layouts.size(); WINPR_ASSERT(len <= UINT32_MAX); - ret = IFCALLRESULT(CHANNEL_RC_OK, _disp->SendMonitorLayout, _disp, static_cast(len), - layouts.data()); + const auto ret = IFCALLRESULT(CHANNEL_RC_OK, _disp->SendMonitorLayout, _disp, + static_cast(len), layouts.data()); if (ret != CHANNEL_RC_OK) - return ret; + return false; _last_sent_layout = layouts; - return ret; + return true; } bool sdlDispContext::addTimer() @@ -284,12 +281,8 @@ bool sdlDispContext::addTimer() return true; } -bool sdlDispContext::updateMonitor(SDL_WindowID id) +bool sdlDispContext::updateMonitor([[maybe_unused]] SDL_WindowID id) { - auto settings = _sdl->context()->settings; - if (freerdp_settings_get_bool(settings, FreeRDP_UseMultimon)) - return updateMonitors(SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, id); - if (!freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_DynamicResolutionUpdate)) return true; @@ -327,58 +320,54 @@ bool sdlDispContext::updateMonitors(SDL_EventType type, SDL_DisplayID displayID) return addTimer(); } -bool sdlDispContext::handleEvent(const SDL_DisplayEvent* ev) +bool sdlDispContext::handleEvent(const SDL_DisplayEvent& ev) { - WINPR_ASSERT(ev); - - switch (ev->type) + switch (ev.type) { case SDL_EVENT_DISPLAY_ADDED: - SDL_Log("A new display with id %u was connected", ev->displayID); - return updateMonitors(ev->type, ev->displayID); + SDL_Log("A new display with id %u was connected", ev.displayID); + return updateMonitors(ev.type, ev.displayID); case SDL_EVENT_DISPLAY_REMOVED: - SDL_Log("The display with id %u was disconnected", ev->displayID); - return updateMonitors(ev->type, ev->displayID); + SDL_Log("The display with id %u was disconnected", ev.displayID); + return updateMonitors(ev.type, ev.displayID); case SDL_EVENT_DISPLAY_ORIENTATION: - SDL_Log("The orientation of display with id %u was changed", ev->displayID); - return updateMonitors(ev->type, ev->displayID); + SDL_Log("The orientation of display with id %u was changed", ev.displayID); + return updateMonitors(ev.type, ev.displayID); case SDL_EVENT_DISPLAY_MOVED: - SDL_Log("The display with id %u was moved", ev->displayID); - return updateMonitors(ev->type, ev->displayID); + SDL_Log("The display with id %u was moved", ev.displayID); + return updateMonitors(ev.type, ev.displayID); case SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED: - SDL_Log("The display with id %u changed scale", ev->displayID); - return updateMonitors(ev->type, ev->displayID); + SDL_Log("The display with id %u changed scale", ev.displayID); + return updateMonitors(ev.type, ev.displayID); case SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED: - SDL_Log("The display with id %u changed mode", ev->displayID); - return updateMonitors(ev->type, ev->displayID); + SDL_Log("The display with id %u changed mode", ev.displayID); + return updateMonitors(ev.type, ev.displayID); case SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED: - SDL_Log("The display with id %u changed desktop mode", ev->displayID); - return updateMonitors(ev->type, ev->displayID); + SDL_Log("The display with id %u changed desktop mode", ev.displayID); + return updateMonitors(ev.type, ev.displayID); default: return true; } } -bool sdlDispContext::handleEvent(const SDL_WindowEvent* ev) +bool sdlDispContext::handleEvent(const SDL_WindowEvent& ev) { - WINPR_ASSERT(ev); - - auto window = _sdl->getWindowForId(ev->windowID); + auto window = _sdl->getWindowForId(ev.windowID); if (!window) return true; auto bordered = freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_Decorations); window->setBordered(bordered); - switch (ev->type) + switch (ev.type) { case SDL_EVENT_WINDOW_HIDDEN: case SDL_EVENT_WINDOW_MINIMIZED: return _sdl->redraw(true); case SDL_EVENT_WINDOW_ENTER_FULLSCREEN: - return updateMonitor(ev->windowID); + return updateMonitor(ev.windowID); case SDL_EVENT_WINDOW_LEAVE_FULLSCREEN: - return updateMonitor(ev->windowID); + return updateMonitor(ev.windowID); case SDL_EVENT_WINDOW_EXPOSED: case SDL_EVENT_WINDOW_SHOWN: @@ -392,13 +381,13 @@ bool sdlDispContext::handleEvent(const SDL_WindowEvent* ev) case SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED: case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: case SDL_EVENT_WINDOW_RESIZED: - return updateMonitor(ev->windowID); + return updateMonitor(ev.windowID); case SDL_EVENT_WINDOW_MOUSE_LEAVE: WINPR_ASSERT(_sdl); - return _sdl->getInputChannelContext().keyboard_grab(ev->windowID, false); + return _sdl->getInputChannelContext().keyboard_grab(ev.windowID, false); case SDL_EVENT_WINDOW_MOUSE_ENTER: WINPR_ASSERT(_sdl); - if (!_sdl->getInputChannelContext().keyboard_grab(ev->windowID, true)) + if (!_sdl->getInputChannelContext().keyboard_grab(ev.windowID, true)) return false; return _sdl->getInputChannelContext().keyboard_focus_in(); case SDL_EVENT_WINDOW_FOCUS_GAINED: @@ -479,7 +468,7 @@ sdlDispContext::sdlDispContext(SdlContext* sdl) : _sdl(sdl) PubSub_SubscribeActivated(pubSub, sdlDispContext::OnActivated); PubSub_SubscribeGraphicsReset(pubSub, sdlDispContext::OnGraphicsReset); - (void)addTimer(); + std::ignore = addTimer(); } sdlDispContext::~sdlDispContext() diff --git a/client/SDL/SDL3/sdl_disp.hpp b/client/SDL/SDL3/sdl_disp.hpp index 8d30f4881..8dd12f64c 100644 --- a/client/SDL/SDL3/sdl_disp.hpp +++ b/client/SDL/SDL3/sdl_disp.hpp @@ -43,8 +43,8 @@ class sdlDispContext [[nodiscard]] bool init(DispClientContext* disp); [[nodiscard]] bool uninit(DispClientContext* disp); - [[nodiscard]] bool handleEvent(const SDL_DisplayEvent* ev); - [[nodiscard]] bool handleEvent(const SDL_WindowEvent* ev); + [[nodiscard]] bool handleEvent(const SDL_DisplayEvent& ev); + [[nodiscard]] bool handleEvent(const SDL_WindowEvent& ev); private: [[nodiscard]] UINT DisplayControlCaps(UINT32 maxNumMonitors, UINT32 maxMonitorAreaFactorA, @@ -53,7 +53,7 @@ class sdlDispContext [[nodiscard]] bool sendResize(); [[nodiscard]] bool settings_changed(const std::vector& layout); - [[nodiscard]] UINT sendLayout(const rdpMonitor* monitors, size_t nmonitors); + [[nodiscard]] bool sendLayout(const rdpMonitor* monitors, size_t nmonitors); [[nodiscard]] bool addTimer(); diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 466e34e93..4299bd7ac 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -59,14 +59,11 @@ #include "dialogs/sdl_dialogs.hpp" #include "scoped_guard.hpp" #include "sdl_channels.hpp" -#include "sdl_disp.hpp" #include "sdl_freerdp.hpp" #include "sdl_context.hpp" -#include "sdl_input.hpp" #include "sdl_monitor.hpp" #include "sdl_pointer.hpp" #include "sdl_prefs.hpp" -#include "sdl_touch.hpp" #include "sdl_utils.hpp" #if defined(_WIN32) @@ -76,10 +73,10 @@ static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const char* signame, [[maybe_unused]] void* context) { - (void)sdl_push_quit(); + std::ignore = sdl_push_quit(); } -static int sdl_run(SdlContext* sdl) +[[nodiscard]] static int sdl_run(SdlContext* sdl) { int rc = -1; WINPR_ASSERT(sdl); @@ -110,17 +107,8 @@ static int sdl_run(SdlContext* sdl) if (sdl->getDialog().handleEvent(windowEvent)) continue; - auto point2pix = [](Uint32 win_id, float& x, float& y) - { - auto win = SDL_GetWindowFromID(win_id); - if (win) - { - auto scale = SDL_GetWindowDisplayScale(win); - assert(scale); - x *= scale; - y *= scale; - } - }; + if (!sdl->handleEvent(windowEvent)) + return -1; switch (windowEvent.type) { @@ -135,65 +123,14 @@ static int sdl_run(SdlContext* sdl) return -1; } break; - case SDL_EVENT_KEYMAP_CHANGED: - { - } - break; // TODO: Switch keyboard layout - case SDL_EVENT_MOUSE_MOTION: - { - SDL_MouseMotionEvent& ev = windowEvent.motion; - point2pix(ev.windowID, ev.x, ev.y); - point2pix(ev.windowID, ev.xrel, ev.yrel); - if (!sdl_handle_mouse_motion(sdl, &ev)) - return -1; - } - break; - case SDL_EVENT_MOUSE_BUTTON_DOWN: - case SDL_EVENT_MOUSE_BUTTON_UP: - { - SDL_MouseButtonEvent& ev = windowEvent.button; - point2pix(ev.windowID, ev.x, ev.y); - if (!sdl_handle_mouse_button(sdl, &ev)) - return -1; - } - break; - case SDL_EVENT_MOUSE_WHEEL: - { - const SDL_MouseWheelEvent* ev = &windowEvent.wheel; - if (!sdl_handle_mouse_wheel(sdl, ev)) - return -1; - } - break; - case SDL_EVENT_FINGER_DOWN: - { - const SDL_TouchFingerEvent* ev = &windowEvent.tfinger; - if (!sdl_handle_touch_down(sdl, ev)) - return -1; - } - break; - case SDL_EVENT_FINGER_UP: - { - const SDL_TouchFingerEvent* ev = &windowEvent.tfinger; - if (!sdl_handle_touch_up(sdl, ev)) - return -1; - } - break; - case SDL_EVENT_FINGER_MOTION: - { - const SDL_TouchFingerEvent* ev = &windowEvent.tfinger; - if (!sdl_handle_touch_motion(sdl, ev)) - return -1; - } - break; - case SDL_EVENT_RENDER_TARGETS_RESET: - (void)sdl->redraw(); + std::ignore = sdl->redraw(); break; case SDL_EVENT_RENDER_DEVICE_RESET: - (void)sdl->redraw(); + std::ignore = sdl->redraw(); break; case SDL_EVENT_WILL_ENTER_FOREGROUND: - (void)sdl->redraw(); + std::ignore = sdl->redraw(); break; case SDL_EVENT_USER_CERT_DIALOG: { @@ -304,20 +241,6 @@ static int sdl_run(SdlContext* sdl) break; case SDL_EVENT_USER_QUIT: default: - if ((windowEvent.type >= SDL_EVENT_DISPLAY_FIRST) && - (windowEvent.type <= SDL_EVENT_DISPLAY_LAST)) - { - const SDL_DisplayEvent* ev = &windowEvent.display; - if (!sdl->handleEvent(ev)) - return -1; - } - else if ((windowEvent.type >= SDL_EVENT_WINDOW_FIRST) && - (windowEvent.type <= SDL_EVENT_WINDOW_LAST)) - { - const SDL_WindowEvent* ev = &windowEvent.window; - if (!sdl->handleEvent(ev)) - return -1; - } break; } } @@ -331,7 +254,7 @@ static int sdl_run(SdlContext* sdl) /* Optional global initializer. * Here we just register a signal handler to print out stack traces * if available. */ -static BOOL sdl_client_global_init() +[[nodiscard]] static BOOL sdl_client_global_init() { #if defined(_WIN32) WSADATA wsaData = {}; @@ -355,7 +278,7 @@ static void sdl_client_global_uninit() #endif } -static BOOL sdl_client_new(freerdp* instance, rdpContext* context) +[[nodiscard]] static BOOL sdl_client_new(freerdp* instance, rdpContext* context) { auto sdl = reinterpret_cast(context); @@ -376,21 +299,21 @@ static void sdl_client_free([[maybe_unused]] freerdp* instance, rdpContext* cont delete sdl->sdl; } -static int sdl_client_start(rdpContext* context) +[[nodiscard]] static int sdl_client_start(rdpContext* context) { auto sdl = get_context(context); WINPR_ASSERT(sdl); return sdl->start(); } -static int sdl_client_stop(rdpContext* context) +[[nodiscard]] static int sdl_client_stop(rdpContext* context) { auto sdl = get_context(context); WINPR_ASSERT(sdl); return sdl->join(); } -static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) +static void RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) { WINPR_ASSERT(pEntryPoints); @@ -404,7 +327,6 @@ static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints) pEntryPoints->ClientFree = sdl_client_free; pEntryPoints->ClientStart = sdl_client_start; pEntryPoints->ClientStop = sdl_client_stop; - return 0; } static void context_free(sdl_rdp_context* sdl) @@ -413,7 +335,7 @@ static void context_free(sdl_rdp_context* sdl) freerdp_client_context_free(&sdl->common.context); } -static const char* category2str(int category) +[[nodiscard]] static const char* category2str(int category) { switch (category) { @@ -461,7 +383,7 @@ static const char* category2str(int category) } } -static SDL_LogPriority wloglevel2dl(DWORD level) +[[nodiscard]] static SDL_LogPriority wloglevel2dl(DWORD level) { switch (level) { @@ -483,7 +405,7 @@ static SDL_LogPriority wloglevel2dl(DWORD level) } } -static DWORD sdlpriority2wlog(SDL_LogPriority priority) +[[nodiscard]] static DWORD sdlpriority2wlog(SDL_LogPriority priority) { DWORD level = WLOG_OFF; switch (priority) @@ -567,7 +489,7 @@ static void SDLCALL rdp_file_cb(void* userdata, const char* const* filelist, sdl_quit(); } -static std::string getRdpFile() +[[nodiscard]] static std::string getRdpFile() { const auto flags = SDL_INIT_VIDEO | SDL_INIT_EVENTS; SDL_DialogFileFilter filters[] = { { "RDP files", "rdp;rdpw" } }; @@ -589,7 +511,7 @@ static std::string getRdpFile() do { SDL_Event event = {}; - (void)SDL_PollEvent(&event); + std::ignore = SDL_PollEvent(&event); switch (event.type) { diff --git a/client/SDL/SDL3/sdl_touch.cpp b/client/SDL/SDL3/sdl_touch.cpp index e8aba9eac..34fcaf388 100644 --- a/client/SDL/SDL3/sdl_touch.cpp +++ b/client/SDL/SDL3/sdl_touch.cpp @@ -30,88 +30,7 @@ #include -BOOL sdl_scale_coordinates(SdlContext* sdl, Uint32 windowId, INT32* px, INT32* py, - BOOL fromLocalToRDP, BOOL applyOffset) -{ - rdpGdi* gdi = nullptr; - double sx = 1.0; - double sy = 1.0; - - if (!sdl || !px || !py || !sdl->context()->gdi) - return FALSE; - - WINPR_ASSERT(sdl->context()->gdi); - WINPR_ASSERT(sdl->context()->settings); - - gdi = sdl->context()->gdi; - - // TODO: Make this multimonitor ready! - // TODO: Need to find the primary monitor, get the scale - // TODO: Need to find the destination monitor, get the scale - // TODO: All intermediate monitors, get the scale - - int offset_x = 0; - int offset_y = 0; - auto window = sdl->getWindowForId(windowId); - if (window) - { - auto size = window->rect(); - - sx = size.w / static_cast(gdi->width); - sy = size.h / static_cast(gdi->height); - offset_x = window->offsetX(); - offset_y = window->offsetY(); - } - - if (freerdp_settings_get_bool(sdl->context()->settings, FreeRDP_SmartSizing)) - { - if (!fromLocalToRDP) - { - *px = static_cast(*px * sx); - *py = static_cast(*py * sy); - } - else - { - *px = static_cast(*px / sx); - *py = static_cast(*py / sy); - } - } - else if (applyOffset) - { - *px -= offset_x; - *py -= offset_y; - } - - return TRUE; -} - -static BOOL sdl_get_touch_scaled(SdlContext* sdl, const SDL_TouchFingerEvent* ev, INT32* px, - INT32* py, BOOL local) -{ - Uint32 windowID = 0; - - WINPR_ASSERT(sdl); - WINPR_ASSERT(ev); - WINPR_ASSERT(px); - WINPR_ASSERT(py); - - SDL_Window* window = SDL_GetWindowFromID(ev->windowID); - - if (!window) - return FALSE; - - windowID = SDL_GetWindowID(window); - SDL_Surface* surface = SDL_GetWindowSurface(window); - if (!surface) - return FALSE; - - // TODO: Add the offset of the surface in the global coordinates - *px = static_cast(ev->x * static_cast(surface->w)); - *py = static_cast(ev->y * static_cast(surface->h)); - return sdl_scale_coordinates(sdl, windowID, px, py, local, TRUE); -} - -static BOOL send_mouse_wheel(SdlContext* sdl, UINT16 flags, INT32 avalue) +static bool send_mouse_wheel(SdlContext* sdl, UINT16 flags, INT32 avalue) { WINPR_ASSERT(sdl); if (avalue < 0) @@ -145,73 +64,67 @@ static UINT32 sdl_scale_pressure(const float pressure) return static_cast(val); } -BOOL sdl_handle_touch_up(SdlContext* sdl, const SDL_TouchFingerEvent* ev) +bool SdlTouch::touchUp(SdlContext* sdl, const SDL_TouchFingerEvent& ev) { WINPR_ASSERT(sdl); - WINPR_ASSERT(ev); - INT32 x = 0; - INT32 y = 0; - if (!sdl_get_touch_scaled(sdl, ev, &x, &y, TRUE)) - return FALSE; return freerdp_client_handle_touch(sdl->common(), FREERDP_TOUCH_UP | FREERDP_TOUCH_HAS_PRESSURE, - static_cast(ev->fingerID), - sdl_scale_pressure(ev->pressure), x, y); + static_cast(ev.fingerID), + sdl_scale_pressure(ev.pressure), static_cast(ev.x), + static_cast(ev.y)); } -BOOL sdl_handle_touch_down(SdlContext* sdl, const SDL_TouchFingerEvent* ev) +bool SdlTouch::touchCancel(SdlContext* sdl, const SDL_TouchFingerEvent& ev) +{ + WINPR_ASSERT(sdl); + + return freerdp_client_handle_touch( + sdl->common(), FREERDP_TOUCH_CANCEL | FREERDP_TOUCH_HAS_PRESSURE, + static_cast(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast(ev.x), + static_cast(ev.y)); +} + +bool SdlTouch::touchDown(SdlContext* sdl, const SDL_TouchFingerEvent& ev) { WINPR_ASSERT(sdl); - WINPR_ASSERT(ev); - INT32 x = 0; - INT32 y = 0; - if (!sdl_get_touch_scaled(sdl, ev, &x, &y, TRUE)) - return FALSE; return freerdp_client_handle_touch( sdl->common(), FREERDP_TOUCH_DOWN | FREERDP_TOUCH_HAS_PRESSURE, - static_cast(ev->fingerID), sdl_scale_pressure(ev->pressure), x, y); + static_cast(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast(ev.x), + static_cast(ev.y)); } -BOOL sdl_handle_touch_motion(SdlContext* sdl, const SDL_TouchFingerEvent* ev) +bool SdlTouch::touchMotion(SdlContext* sdl, const SDL_TouchFingerEvent& ev) { WINPR_ASSERT(sdl); - WINPR_ASSERT(ev); - INT32 x = 0; - INT32 y = 0; - if (!sdl_get_touch_scaled(sdl, ev, &x, &y, TRUE)) - return FALSE; return freerdp_client_handle_touch( sdl->common(), FREERDP_TOUCH_MOTION | FREERDP_TOUCH_HAS_PRESSURE, - static_cast(ev->fingerID), sdl_scale_pressure(ev->pressure), x, y); + static_cast(ev.fingerID), sdl_scale_pressure(ev.pressure), static_cast(ev.x), + static_cast(ev.y)); } -BOOL sdl_handle_mouse_motion(SdlContext* sdl, const SDL_MouseMotionEvent* ev) +bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseMotionEvent& ev) { WINPR_ASSERT(sdl); - WINPR_ASSERT(ev); - if (!sdl->getInputChannelContext().mouse_focus(ev->windowID)) + if (!sdl->getInputChannelContext().mouse_focus(ev.windowID)) return FALSE; const BOOL relative = freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor(); - auto x = static_cast(relative ? ev->xrel : ev->x); - auto y = static_cast(relative ? ev->yrel : ev->y); - if (!sdl_scale_coordinates(sdl, ev->windowID, &x, &y, TRUE, TRUE)) - return FALSE; + auto x = static_cast(relative ? ev.xrel : ev.x); + auto y = static_cast(relative ? ev.yrel : ev.y); return freerdp_client_send_button_event(sdl->common(), relative, PTR_FLAGS_MOVE, x, y); } -BOOL sdl_handle_mouse_wheel(SdlContext* sdl, const SDL_MouseWheelEvent* ev) +bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseWheelEvent& ev) { WINPR_ASSERT(sdl); - WINPR_ASSERT(ev); - const BOOL flipped = (ev->direction == SDL_MOUSEWHEEL_FLIPPED); - const auto x = static_cast(ev->x * (flipped ? -1.0f : 1.0f) * 120.0f); - const auto y = static_cast(ev->y * (flipped ? -1.0f : 1.0f) * 120.0f); + const BOOL flipped = (ev.direction == SDL_MOUSEWHEEL_FLIPPED); + const auto x = static_cast(ev.x * (flipped ? -1.0f : 1.0f) * 120.0f); + const auto y = static_cast(ev.y * (flipped ? -1.0f : 1.0f) * 120.0f); UINT16 flags = 0; if (y != 0) @@ -228,21 +141,20 @@ BOOL sdl_handle_mouse_wheel(SdlContext* sdl, const SDL_MouseWheelEvent* ev) return TRUE; } -BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev) +bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseButtonEvent& ev) { UINT16 flags = 0; UINT16 xflags = 0; WINPR_ASSERT(sdl); - WINPR_ASSERT(ev); - if (ev->type == SDL_EVENT_MOUSE_BUTTON_DOWN) + if (ev.type == SDL_EVENT_MOUSE_BUTTON_DOWN) { flags |= PTR_FLAGS_DOWN; xflags |= PTR_XFLAGS_DOWN; } - switch (ev->button) + switch (ev.button) { case 1: flags |= PTR_FLAGS_BUTTON1; @@ -265,10 +177,8 @@ BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev) const BOOL relative = freerdp_client_use_relative_mouse_events(sdl->common()) && !sdl->hasCursor(); - auto x = static_cast(relative ? 0 : ev->x); - auto y = static_cast(relative ? 0 : ev->y); - if (!sdl_scale_coordinates(sdl, ev->windowID, &x, &y, TRUE, TRUE)) - return FALSE; + auto x = static_cast(relative ? 0 : ev.x); + auto y = static_cast(relative ? 0 : ev.y); if ((flags & (~PTR_FLAGS_DOWN)) != 0) return freerdp_client_send_button_event(sdl->common(), relative, flags, x, y); @@ -277,3 +187,20 @@ BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev) else return FALSE; } + +bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_TouchFingerEvent& ev) +{ + switch (ev.type) + { + case SDL_EVENT_FINGER_CANCELED: + return SdlTouch::touchCancel(sdl, ev); + case SDL_EVENT_FINGER_UP: + return SdlTouch::touchUp(sdl, ev); + case SDL_EVENT_FINGER_DOWN: + return SdlTouch::touchDown(sdl, ev); + case SDL_EVENT_FINGER_MOTION: + return SdlTouch::touchMotion(sdl, ev); + default: + return false; + } +} diff --git a/client/SDL/SDL3/sdl_touch.hpp b/client/SDL/SDL3/sdl_touch.hpp index 35082a688..951a98e17 100644 --- a/client/SDL/SDL3/sdl_touch.hpp +++ b/client/SDL/SDL3/sdl_touch.hpp @@ -24,13 +24,18 @@ #include #include "sdl_types.hpp" -[[nodiscard]] BOOL sdl_scale_coordinates(SdlContext* sdl, Uint32 windowId, INT32* px, INT32* py, - BOOL fromLocalToRDP, BOOL applyOffset); +class SdlTouch +{ + public: + [[nodiscard]] static bool handleEvent(SdlContext* sdl, const SDL_MouseMotionEvent& ev); + [[nodiscard]] static bool handleEvent(SdlContext* sdl, const SDL_MouseWheelEvent& ev); + [[nodiscard]] static bool handleEvent(SdlContext* sdl, const SDL_MouseButtonEvent& ev); -[[nodiscard]] BOOL sdl_handle_mouse_motion(SdlContext* sdl, const SDL_MouseMotionEvent* ev); -[[nodiscard]] BOOL sdl_handle_mouse_wheel(SdlContext* sdl, const SDL_MouseWheelEvent* ev); -[[nodiscard]] BOOL sdl_handle_mouse_button(SdlContext* sdl, const SDL_MouseButtonEvent* ev); + [[nodiscard]] static bool handleEvent(SdlContext* sdl, const SDL_TouchFingerEvent& ev); -[[nodiscard]] BOOL sdl_handle_touch_down(SdlContext* sdl, const SDL_TouchFingerEvent* ev); -[[nodiscard]] BOOL sdl_handle_touch_up(SdlContext* sdl, const SDL_TouchFingerEvent* ev); -[[nodiscard]] BOOL sdl_handle_touch_motion(SdlContext* sdl, const SDL_TouchFingerEvent* ev); + private: + [[nodiscard]] static bool touchDown(SdlContext* sdl, const SDL_TouchFingerEvent& ev); + [[nodiscard]] static bool touchUp(SdlContext* sdl, const SDL_TouchFingerEvent& ev); + [[nodiscard]] static bool touchCancel(SdlContext* sdl, const SDL_TouchFingerEvent& ev); + [[nodiscard]] static bool touchMotion(SdlContext* sdl, const SDL_TouchFingerEvent& ev); +}; From 57034f2294d1722f21926d9f361d2e58bc9a3c75 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 13:18:04 +0100 Subject: [PATCH 23/30] [client,sdl] fix compiler warnings --- client/SDL/SDL3/sdl_context.cpp | 35 ++++++++++++++++----------------- client/SDL/SDL3/sdl_context.hpp | 2 +- client/SDL/SDL3/sdl_pointer.cpp | 15 ++++++-------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index d99021e16..e311340ff 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -1013,7 +1013,7 @@ SDL_FPoint SdlContext::applyLocalScaling(const SDL_FPoint& val) const return rval; } -void SdlContext::removeLocalScaling(float& x, float& y) +void SdlContext::removeLocalScaling(float& x, float& y) const { if (!freerdp_settings_get_bool(context()->settings, FreeRDP_SmartSizing)) return; @@ -1059,43 +1059,42 @@ SDL_FRect SdlContext::pixelToScreen(SDL_WindowID id, const SDL_FRect& pos) return { fpos.x, fpos.y, size.x, size.y }; } -bool SdlContext::handleEvent(const SDL_Event& windowEvent) +bool SdlContext::handleEvent(const SDL_Event& ev) { - if ((windowEvent.type >= SDL_EVENT_DISPLAY_FIRST) && - (windowEvent.type <= SDL_EVENT_DISPLAY_LAST)) + if ((ev.type >= SDL_EVENT_DISPLAY_FIRST) && (ev.type <= SDL_EVENT_DISPLAY_LAST)) { - const auto& ev = windowEvent.display; - return handleEvent(ev); + const auto& dev = ev.display; + return handleEvent(dev); } - if ((windowEvent.type >= SDL_EVENT_WINDOW_FIRST) && (windowEvent.type <= SDL_EVENT_WINDOW_LAST)) + if ((ev.type >= SDL_EVENT_WINDOW_FIRST) && (ev.type <= SDL_EVENT_WINDOW_LAST)) { - const auto& ev = windowEvent.window; - return handleEvent(ev); + const auto& wev = ev.window; + return handleEvent(wev); } - switch (windowEvent.type) + switch (ev.type) { case SDL_EVENT_FINGER_DOWN: case SDL_EVENT_FINGER_UP: case SDL_EVENT_FINGER_MOTION: { - const auto& ev = windowEvent.tfinger; - return handleEvent(ev); + const auto& cev = ev.tfinger; + return handleEvent(cev); } case SDL_EVENT_MOUSE_MOTION: { - const auto& ev = windowEvent.motion; - return handleEvent(ev); + const auto& cev = ev.motion; + return handleEvent(cev); } case SDL_EVENT_MOUSE_BUTTON_DOWN: case SDL_EVENT_MOUSE_BUTTON_UP: { - const auto& ev = windowEvent.button; - return handleEvent(ev); + const auto& cev = ev.button; + return handleEvent(cev); } case SDL_EVENT_MOUSE_WHEEL: { - const auto& ev = windowEvent.wheel; - return handleEvent(ev); + const auto& cev = ev.wheel; + return handleEvent(cev); } default: return true; diff --git a/client/SDL/SDL3/sdl_context.hpp b/client/SDL/SDL3/sdl_context.hpp index ddab25f87..e83b1b0b2 100644 --- a/client/SDL/SDL3/sdl_context.hpp +++ b/client/SDL/SDL3/sdl_context.hpp @@ -143,7 +143,7 @@ class SdlContext [[nodiscard]] bool eventToPixelCoordinates(SDL_WindowID id, SDL_Event& ev); [[nodiscard]] SDL_FPoint applyLocalScaling(const SDL_FPoint& val) const; - void removeLocalScaling(float& x, float& y); + void removeLocalScaling(float& x, float& y) const; [[nodiscard]] bool handleEvent(const SDL_WindowEvent& ev); [[nodiscard]] bool handleEvent(const SDL_DisplayEvent& ev); diff --git a/client/SDL/SDL3/sdl_pointer.cpp b/client/SDL/SDL3/sdl_pointer.cpp index 55b90275e..292aec296 100644 --- a/client/SDL/SDL3/sdl_pointer.cpp +++ b/client/SDL/SDL3/sdl_pointer.cpp @@ -105,9 +105,6 @@ static void sdl_Pointer_Free(rdpContext* context, rdpPointer* pointer) BOOL sdl_Pointer_Set_Process(SdlContext* sdl) { - INT32 w = 0; - INT32 h = 0; - WINPR_ASSERT(sdl); auto context = sdl->context(); @@ -119,10 +116,10 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) rdpGdi* gdi = context->gdi; WINPR_ASSERT(gdi); - auto ix = static_cast(pointer->xPos); - auto iy = static_cast(pointer->yPos); - auto isw = w = static_cast(pointer->width); - auto ish = h = static_cast(pointer->height); + auto ix = static_cast(pointer->xPos); + auto iy = static_cast(pointer->yPos); + auto isw = static_cast(pointer->width); + auto ish = static_cast(pointer->height); SDL_Window* window = SDL_GetMouseFocus(); if (!window) @@ -130,7 +127,7 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) const Uint32 id = SDL_GetWindowID(window); - auto pos = sdl->pixelToScreen(id, SDL_FRect{ ix * 1.0f, iy * 1.0f, isw * 1.0f, ish * 1.0f }); + auto pos = sdl->pixelToScreen(id, SDL_FRect{ ix, iy, isw, ish }); sdl_Pointer_Clear(ptr); @@ -145,7 +142,7 @@ BOOL sdl_Pointer_Set_Process(SdlContext* sdl) const BOOL rc = freerdp_image_scale( pixels, gdi->dstFormat, static_cast(ptr->image->pitch), 0, 0, static_cast(ptr->image->w), static_cast(ptr->image->h), data, - gdi->dstFormat, 0, 0, 0, static_cast(w), static_cast(h)); + gdi->dstFormat, 0, 0, 0, static_cast(isw), static_cast(ish)); SDL_UnlockSurface(ptr->image); if (!rc) return FALSE; From d74eecff3bc4fc9371649cf57a4bad31a152e8b6 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Sun, 25 Jan 2026 20:27:50 +0100 Subject: [PATCH 24/30] [client,sdl] ignore set_mouseover result The function might return false if no item was selected. --- client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp | 3 +-- client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp | 9 +++------ client/SDL/SDL3/dialogs/sdl_select_list.cpp | 3 +-- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp index a4d9773d8..3286b24aa 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp @@ -226,8 +226,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) { auto& ev = reinterpret_cast(event); - if (!_buttons.set_mouseover(event.button.x, event.button.y)) - return false; + _buttons.set_mouseover(event.button.x, event.button.y); if (!update()) return false; return windowID == ev.windowID; diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp b/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp index 08b4cfd77..2bfb9c1c0 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp @@ -236,18 +236,15 @@ int SdlInputWidgetPairList::run(std::vector& result) auto TextInputIndex = get_index(event.button); for (auto& cur : m_list) { - if (!cur->set_mouseover(false)) - throw; + cur->set_mouseover(false); } if (TextInputIndex >= 0) { auto& cur = m_list[static_cast(TextInputIndex)]; - if (!cur->set_mouseover(true)) - throw; + cur->set_mouseover(true); } - if (!_buttons.set_mouseover(event.button.x, event.button.y)) - throw; + _buttons.set_mouseover(event.button.x, event.button.y); } break; case SDL_EVENT_MOUSE_BUTTON_DOWN: diff --git a/client/SDL/SDL3/dialogs/sdl_select_list.cpp b/client/SDL/SDL3/dialogs/sdl_select_list.cpp index a4cebfe15..751ae2d99 100644 --- a/client/SDL/SDL3/dialogs/sdl_select_list.cpp +++ b/client/SDL/SDL3/dialogs/sdl_select_list.cpp @@ -111,8 +111,7 @@ int SdlSelectList::run() throw; } - if (!_buttons.set_mouseover(event.button.x, event.button.y)) - throw; + _buttons.set_mouseover(event.button.x, event.button.y); } break; case SDL_EVENT_MOUSE_BUTTON_DOWN: From dcdde8122dc7ce6da420cfcb870a6e0497109a33 Mon Sep 17 00:00:00 2001 From: akallabeth Date: Tue, 27 Jan 2026 13:08:10 +0100 Subject: [PATCH 25/30] [client,sdl] adjust nodiscard use for dialogs --- client/SDL/SDL3/dialogs/sdl_button.cpp | 4 ++-- client/SDL/SDL3/dialogs/sdl_buttons.hpp | 6 +++--- .../SDL3/dialogs/sdl_connection_dialog.cpp | 10 +++++----- .../dialogs/sdl_connection_dialog_wrapper.cpp | 14 ++++++------- .../SDL3/dialogs/sdl_input_widget_pair.cpp | 4 ++-- .../SDL3/dialogs/sdl_input_widget_pair.hpp | 4 ++-- .../dialogs/sdl_input_widget_pair_list.cpp | 4 ++-- client/SDL/SDL3/dialogs/sdl_select.cpp | 2 +- client/SDL/SDL3/dialogs/sdl_select_list.cpp | 8 ++++---- .../SDL3/dialogs/sdl_selectable_widget.hpp | 4 ++-- client/SDL/SDL3/dialogs/sdl_widget.cpp | 20 +++++++++---------- client/SDL/SDL3/dialogs/sdl_widget.hpp | 4 ++-- client/SDL/SDL3/dialogs/sdl_widget_list.cpp | 2 +- .../SDL3/dialogs/test/TestSDLDialogInput.cpp | 11 ++-------- .../dialogs/test/TestSDLDialogSelectList.cpp | 11 ++-------- client/SDL/SDL3/sdl_touch.cpp | 10 ++++++---- 16 files changed, 53 insertions(+), 65 deletions(-) diff --git a/client/SDL/SDL3/dialogs/sdl_button.cpp b/client/SDL/SDL3/dialogs/sdl_button.cpp index ef625e1cd..da33c9452 100644 --- a/client/SDL/SDL3/dialogs/sdl_button.cpp +++ b/client/SDL/SDL3/dialogs/sdl_button.cpp @@ -31,8 +31,8 @@ SdlButton::SdlButton(std::shared_ptr& renderer, const std::string& _highlightcolor = { 0xcd, 0xca, 0x35, 0x60 }; _mouseovercolor = { 0x66, 0xff, 0x66, 0x60 }; _fontcolor = { 0xd1, 0xcf, 0xcd, 0xff }; - (void)update_text(label); - (void)update(); + std::ignore = update_text(label); + std::ignore = update(); } SdlButton::SdlButton(SdlButton&& other) noexcept = default; diff --git a/client/SDL/SDL3/dialogs/sdl_buttons.hpp b/client/SDL/SDL3/dialogs/sdl_buttons.hpp index 733380894..3d43c5492 100644 --- a/client/SDL/SDL3/dialogs/sdl_buttons.hpp +++ b/client/SDL/SDL3/dialogs/sdl_buttons.hpp @@ -25,9 +25,9 @@ class SdlButtonList [[nodiscard]] std::shared_ptr get_selected(const SDL_MouseButtonEvent& button); [[nodiscard]] std::shared_ptr get_selected(float x, float y); - [[nodiscard]] bool set_highlight_next(bool reset = false); - [[nodiscard]] bool set_highlight(size_t index); - [[nodiscard]] bool set_mouseover(float x, float y); + bool set_highlight_next(bool reset = false); + bool set_highlight(size_t index); + bool set_mouseover(float x, float y); void clear(); diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp index 3286b24aa..ffc2edd91 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog.cpp @@ -34,7 +34,7 @@ static const Uint32 hpadding = 5; SDLConnectionDialog::SDLConnectionDialog(rdpContext* context) : _context(context) { - (void)hide(); + std::ignore = hide(); } SDLConnectionDialog::~SDLConnectionDialog() @@ -207,7 +207,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (event.type == SDL_EVENT_KEY_UP) { freerdp_abort_event(_context); - (void)sdl_push_quit(); + std::ignore = sdl_push_quit(); } break; case SDLK_TAB: @@ -246,7 +246,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (event.type == SDL_EVENT_MOUSE_BUTTON_UP) { freerdp_abort_event(_context); - (void)sdl_push_quit(); + std::ignore = sdl_push_quit(); } } @@ -282,7 +282,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event) if (windowID == ev.windowID) { freerdp_abort_event(_context); - (void)sdl_push_quit(); + std::ignore = sdl_push_quit(); } break; default: @@ -473,7 +473,7 @@ Uint32 SDLConnectionDialog::timeout(void* pvthis, [[maybe_unused]] SDL_TimerID t [[maybe_unused]] Uint32 intervalMS) { auto self = static_cast(pvthis); - (void)self->hide(); + std::ignore = self->hide(); self->_running = false; return 0; } diff --git a/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.cpp b/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.cpp index 45e775c6a..b632833a6 100644 --- a/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.cpp +++ b/client/SDL/SDL3/dialogs/sdl_connection_dialog_wrapper.cpp @@ -88,7 +88,7 @@ static std::string format(WINPR_FORMAT_ARG const char* fmt, va_list ap) va_list ap2; va_copy(ap2, ap); - (void)vsnprintf(msg.data(), msg.size(), fmt, ap2); + std::ignore = vsnprintf(msg.data(), msg.size(), fmt, ap2); va_end(ap2); return msg; } @@ -166,7 +166,7 @@ void SdlConnectionDialogWrapper::handleShow() if (arg.hasTitle() && _connection_dialog) { - (void)_connection_dialog->setTitle(arg.title().c_str()); + std::ignore = _connection_dialog->setTitle(arg.title().c_str()); } if (arg.hasType() && arg.hasMessage()) @@ -175,19 +175,19 @@ void SdlConnectionDialogWrapper::handleShow() { case SdlConnectionDialogWrapper::MSG_INFO: if (_connection_dialog) - (void)_connection_dialog->showInfo(arg.message().c_str()); + std::ignore = _connection_dialog->showInfo(arg.message().c_str()); else WLog_Print(_log, WLOG_INFO, "%s", arg.message().c_str()); break; case SdlConnectionDialogWrapper::MSG_WARN: if (_connection_dialog) - (void)_connection_dialog->showWarn(arg.message().c_str()); + std::ignore = _connection_dialog->showWarn(arg.message().c_str()); else WLog_Print(_log, WLOG_WARN, "%s", arg.message().c_str()); break; case SdlConnectionDialogWrapper::MSG_ERROR: if (_connection_dialog) - (void)_connection_dialog->showError(arg.message().c_str()); + std::ignore = _connection_dialog->showError(arg.message().c_str()); else WLog_Print(_log, WLOG_ERROR, "%s", arg.message().c_str()); break; @@ -199,9 +199,9 @@ void SdlConnectionDialogWrapper::handleShow() if (arg.hasVisibility() && _connection_dialog) { if (arg.visible()) - (void)_connection_dialog->show(); + std::ignore = _connection_dialog->show(); else - (void)_connection_dialog->hide(); + std::ignore = _connection_dialog->hide(); } } } diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget_pair.cpp b/client/SDL/SDL3/dialogs/sdl_input_widget_pair.cpp index 319f6eb88..887564ba6 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget_pair.cpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget_pair.cpp @@ -40,8 +40,8 @@ SdlInputWidgetPair::SdlInputWidgetPair(std::shared_ptr& renderer, static_cast(offset * (height + _vpadding)), static_cast(width), static_cast(height) }) { - (void)_label.update_text(label); - (void)update_input_text(initial); + std::ignore = _label.update_text(label); + std::ignore = update_input_text(initial); } SdlInputWidgetPair::SdlInputWidgetPair(SdlInputWidgetPair&& other) noexcept = default; diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget_pair.hpp b/client/SDL/SDL3/dialogs/sdl_input_widget_pair.hpp index ebbcec0f5..2fedeb853 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget_pair.hpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget_pair.hpp @@ -45,8 +45,8 @@ class SdlInputWidgetPair SdlInputWidgetPair& operator=(const SdlInputWidgetPair& other) = delete; SdlInputWidgetPair& operator=(SdlInputWidgetPair&& other) = delete; - [[nodiscard]] bool set_mouseover(bool mouseOver); - [[nodiscard]] bool set_highlight(bool highlight); + bool set_mouseover(bool mouseOver); + bool set_highlight(bool highlight); [[nodiscard]] bool set_str(const std::string& text); [[nodiscard]] bool remove_str(size_t count); diff --git a/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp b/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp index 2bfb9c1c0..e07ea9657 100644 --- a/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp +++ b/client/SDL/SDL3/dialogs/sdl_input_widget_pair_list.cpp @@ -55,10 +55,10 @@ SdlInputWidgetPairList::SdlInputWidgetPairList(const std::string& title, m_list.emplace_back(widget); } - (void)_buttons.populate( + std::ignore = _buttons.populate( _renderer, buttonlabels, buttonids, total_width, static_cast(input_height), static_cast(widget_width), static_cast(widget_heigth)); - (void)_buttons.set_highlight(0); + _buttons.set_highlight(0); m_currentActiveTextInput = selected; } } diff --git a/client/SDL/SDL3/dialogs/sdl_select.cpp b/client/SDL/SDL3/dialogs/sdl_select.cpp index ac2490664..c295a8555 100644 --- a/client/SDL/SDL3/dialogs/sdl_select.cpp +++ b/client/SDL/SDL3/dialogs/sdl_select.cpp @@ -37,7 +37,7 @@ SdlSelectWidget::SdlSelectWidget(std::shared_ptr& renderer, const { _backgroundcolor = { 0x69, 0x66, 0x63, 0xff }; _fontcolor = { 0xd1, 0xcf, 0xcd, 0xff }; - (void)update_text(label); + std::ignore = update_text(label); } SdlSelectWidget::~SdlSelectWidget() = default; diff --git a/client/SDL/SDL3/dialogs/sdl_select_list.cpp b/client/SDL/SDL3/dialogs/sdl_select_list.cpp index 751ae2d99..f52a10dcc 100644 --- a/client/SDL/SDL3/dialogs/sdl_select_list.cpp +++ b/client/SDL/SDL3/dialogs/sdl_select_list.cpp @@ -23,10 +23,10 @@ SdlSelectList::SdlSelectList(const std::string& title, const std::vector buttonids = { INPUT_BUTTON_ACCEPT, INPUT_BUTTON_CANCEL }; const std::vector buttonlabels = { "accept", "cancel" }; - (void)_buttons.populate( + std::ignore = _buttons.populate( _renderer, buttonlabels, buttonids, widget_width, static_cast(total_height), static_cast(widget_width / 2), static_cast(widget_height)); - (void)_buttons.set_highlight(0); + _buttons.set_highlight(0); } } @@ -187,7 +187,7 @@ void SdlSelectList::reset_mouseover() { for (auto& cur : _list) { - (void)cur.mouseover(false); + cur.mouseover(false); } } @@ -195,6 +195,6 @@ void SdlSelectList::reset_highlight() { for (auto& cur : _list) { - (void)cur.highlight(false); + cur.highlight(false); } } diff --git a/client/SDL/SDL3/dialogs/sdl_selectable_widget.hpp b/client/SDL/SDL3/dialogs/sdl_selectable_widget.hpp index 06e2c8e63..f9706b4c9 100644 --- a/client/SDL/SDL3/dialogs/sdl_selectable_widget.hpp +++ b/client/SDL/SDL3/dialogs/sdl_selectable_widget.hpp @@ -36,8 +36,8 @@ class SdlSelectableWidget : public SdlWidget SdlSelectableWidget& operator=(const SdlSelectableWidget& other) = delete; SdlSelectableWidget& operator=(SdlSelectableWidget&& other) = delete; - [[nodiscard]] bool highlight(bool enable); - [[nodiscard]] bool mouseover(bool enable); + bool highlight(bool enable); + bool mouseover(bool enable); protected: [[nodiscard]] bool updateInternal() override; diff --git a/client/SDL/SDL3/dialogs/sdl_widget.cpp b/client/SDL/SDL3/dialogs/sdl_widget.cpp index d0cbaefc8..843f7a0f5 100644 --- a/client/SDL/SDL3/dialogs/sdl_widget.cpp +++ b/client/SDL/SDL3/dialogs/sdl_widget.cpp @@ -51,12 +51,12 @@ SdlWidget::SdlWidget(std::shared_ptr& renderer, const SDL_FRect& r auto ops = SDL3ResourceManager::get(SDLResourceManager::typeFonts(), "OpenSans-VariableFont_wdth,wght.ttf"); if (!ops) - (void)widget_log_error(false, "SDLResourceManager::get"); + widget_log_error(false, "SDLResourceManager::get"); else { _font = std::shared_ptr(TTF_OpenFontIO(ops, true, 64), TTF_CloseFont); if (!_font) - (void)widget_log_error(false, "TTF_OpenFontRW"); + widget_log_error(false, "TTF_OpenFontRW"); } } @@ -72,7 +72,7 @@ SdlWidget::SdlWidget(std::shared_ptr& renderer, const SDL_FRect& r _image = std::shared_ptr(IMG_LoadTexture_IO(renderer.get(), ops, true), SDL_DestroyTexture); if (!_image) - (void)widget_log_error(false, "IMG_LoadTexture_IO"); + widget_log_error(false, "IMG_LoadTexture_IO"); } } #endif @@ -95,7 +95,7 @@ std::shared_ptr SdlWidget::render_text(const std::string& text, SDL TTF_RenderText_Blended(_font.get(), text.c_str(), 0, fgcolor), SDL_DestroySurface); if (!surface) { - (void)widget_log_error(false, "TTF_RenderText_Blended"); + widget_log_error(false, "TTF_RenderText_Blended"); return nullptr; } @@ -103,13 +103,13 @@ std::shared_ptr SdlWidget::render_text(const std::string& text, SDL SDL_CreateTextureFromSurface(_renderer.get(), surface.get()), SDL_DestroyTexture); if (!texture) { - (void)widget_log_error(false, "SDL_CreateTextureFromSurface"); + widget_log_error(false, "SDL_CreateTextureFromSurface"); return nullptr; } if (!_engine) { - (void)widget_log_error(false, "TTF_CreateRendererTextEngine"); + widget_log_error(false, "TTF_CreateRendererTextEngine"); return nullptr; } @@ -118,14 +118,14 @@ std::shared_ptr SdlWidget::render_text(const std::string& text, SDL if (!txt) { - (void)widget_log_error(false, "TTF_CreateText"); + widget_log_error(false, "TTF_CreateText"); return nullptr; } int w = 0; int h = 0; if (!TTF_GetTextSize(txt.get(), &w, &h)) { - (void)widget_log_error(false, "TTF_GetTextSize"); + widget_log_error(false, "TTF_GetTextSize"); return nullptr; } @@ -170,7 +170,7 @@ std::shared_ptr SdlWidget::render_text_wrapped(const std::string& t SDL_DestroySurface); if (!surface) { - (void)widget_log_error(false, "TTF_RenderText_Blended"); + widget_log_error(false, "TTF_RenderText_Blended"); return nullptr; } @@ -181,7 +181,7 @@ std::shared_ptr SdlWidget::render_text_wrapped(const std::string& t SDL_CreateTextureFromSurface(_renderer.get(), surface.get()), SDL_DestroyTexture); if (!texture) { - (void)widget_log_error(false, "SDL_CreateTextureFromSurface"); + widget_log_error(false, "SDL_CreateTextureFromSurface"); return nullptr; } diff --git a/client/SDL/SDL3/dialogs/sdl_widget.hpp b/client/SDL/SDL3/dialogs/sdl_widget.hpp index 7f3f44759..1e13326bb 100644 --- a/client/SDL/SDL3/dialogs/sdl_widget.hpp +++ b/client/SDL/SDL3/dialogs/sdl_widget.hpp @@ -70,8 +70,8 @@ class SdlWidget [[nodiscard]] bool update(); #define widget_log_error(res, what) SdlWidget::error_ex(res, what, __FILE__, __LINE__, __func__) - [[nodiscard]] static bool error_ex(bool success, const char* what, const char* file, - size_t line, const char* fkt); + static bool error_ex(bool success, const char* what, const char* file, size_t line, + const char* fkt); protected: std::shared_ptr _renderer; diff --git a/client/SDL/SDL3/dialogs/sdl_widget_list.cpp b/client/SDL/SDL3/dialogs/sdl_widget_list.cpp index ff2a8ce65..e7be4b602 100644 --- a/client/SDL/SDL3/dialogs/sdl_widget_list.cpp +++ b/client/SDL/SDL3/dialogs/sdl_widget_list.cpp @@ -14,7 +14,7 @@ bool SdlWidgetList::reset(const std::string& title, size_t width, size_t height) _renderer = std::shared_ptr(renderer, SDL_DestroyRenderer); _window = std::shared_ptr(window, SDL_DestroyWindow); if (!rc) - (void)widget_log_error(rc, "SDL_CreateWindowAndRenderer"); + widget_log_error(rc, "SDL_CreateWindowAndRenderer"); return rc; } diff --git a/client/SDL/SDL3/dialogs/test/TestSDLDialogInput.cpp b/client/SDL/SDL3/dialogs/test/TestSDLDialogInput.cpp index 98e01864c..28ad4a159 100644 --- a/client/SDL/SDL3/dialogs/test/TestSDLDialogInput.cpp +++ b/client/SDL/SDL3/dialogs/test/TestSDLDialogInput.cpp @@ -53,14 +53,7 @@ static int runTest(fkt_t fkt) return rc; } -int main(int argc, char* argv[]) +int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { - int rc = 0; - - (void)argc; - (void)argv; - - rc = runTest(auth_dialogs); - - return rc; + return runTest(auth_dialogs); } diff --git a/client/SDL/SDL3/dialogs/test/TestSDLDialogSelectList.cpp b/client/SDL/SDL3/dialogs/test/TestSDLDialogSelectList.cpp index 5f20611c1..206c2da2d 100644 --- a/client/SDL/SDL3/dialogs/test/TestSDLDialogSelectList.cpp +++ b/client/SDL/SDL3/dialogs/test/TestSDLDialogSelectList.cpp @@ -41,14 +41,7 @@ static int runTest(fkt_t fkt) return rc; } -int main(int argc, char* argv[]) +int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[]) { - int rc = 0; - - (void)argc; - (void)argv; - - rc = runTest(select_dialogs); - - return rc; + return runTest(select_dialogs); } diff --git a/client/SDL/SDL3/sdl_touch.cpp b/client/SDL/SDL3/sdl_touch.cpp index 34fcaf388..28164269c 100644 --- a/client/SDL/SDL3/sdl_touch.cpp +++ b/client/SDL/SDL3/sdl_touch.cpp @@ -30,7 +30,7 @@ #include -static bool send_mouse_wheel(SdlContext* sdl, UINT16 flags, INT32 avalue) +[[nodiscard]] static bool send_mouse_wheel(SdlContext* sdl, UINT16 flags, INT32 avalue) { WINPR_ASSERT(sdl); if (avalue < 0) @@ -54,7 +54,7 @@ static bool send_mouse_wheel(SdlContext* sdl, UINT16 flags, INT32 avalue) return TRUE; } -static UINT32 sdl_scale_pressure(const float pressure) +[[nodiscard]] static UINT32 sdl_scale_pressure(const float pressure) { const float val = pressure * 0x400; /* [MS-RDPEI] 2.2.3.3.1.1 RDPINPUT_TOUCH_CONTACT */ if (val < 0.0f) @@ -130,13 +130,15 @@ bool SdlTouch::handleEvent(SdlContext* sdl, const SDL_MouseWheelEvent& ev) if (y != 0) { flags |= PTR_FLAGS_WHEEL; - send_mouse_wheel(sdl, flags, y); + if (!send_mouse_wheel(sdl, flags, y)) + return false; } if (x != 0) { flags |= PTR_FLAGS_HWHEEL; - send_mouse_wheel(sdl, flags, x); + if (!send_mouse_wheel(sdl, flags, x)) + return false; } return TRUE; } From ba07955689084ea7b86bc8d58e3adc34bcfe51a1 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 27 Jan 2026 14:00:28 +0100 Subject: [PATCH 26/30] [client,sdl] handle clipboard events in SdlContext --- client/SDL/SDL3/sdl_clip.cpp | 2 +- client/SDL/SDL3/sdl_clip.hpp | 2 +- client/SDL/SDL3/sdl_context.cpp | 5 +++++ client/SDL/SDL3/sdl_freerdp.cpp | 4 ---- winpr/include/winpr/platform.h | 4 +--- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/client/SDL/SDL3/sdl_clip.cpp b/client/SDL/SDL3/sdl_clip.cpp index 172576a3b..6b12faa19 100644 --- a/client/SDL/SDL3/sdl_clip.cpp +++ b/client/SDL/SDL3/sdl_clip.cpp @@ -183,7 +183,7 @@ bool sdlClip::contains(const char** mime_types, Sint32 count) return false; } -bool sdlClip::handle_update(const SDL_ClipboardEvent& ev) +bool sdlClip::handleEvent(const SDL_ClipboardEvent& ev) { if (!_ctx || !_sync || ev.owner) { diff --git a/client/SDL/SDL3/sdl_clip.hpp b/client/SDL/SDL3/sdl_clip.hpp index e4497e111..b753fe0f2 100644 --- a/client/SDL/SDL3/sdl_clip.hpp +++ b/client/SDL/SDL3/sdl_clip.hpp @@ -87,7 +87,7 @@ class sdlClip [[nodiscard]] bool init(CliprdrClientContext* clip); [[nodiscard]] bool uninit(CliprdrClientContext* clip); - [[nodiscard]] bool handle_update(const SDL_ClipboardEvent& ev); + [[nodiscard]] bool handleEvent(const SDL_ClipboardEvent& ev); private: [[nodiscard]] UINT SendClientCapabilities(); diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index e311340ff..acf47d7e4 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -1096,6 +1096,11 @@ bool SdlContext::handleEvent(const SDL_Event& ev) const auto& cev = ev.wheel; return handleEvent(cev); } + case SDL_EVENT_CLIPBOARD_UPDATE: + { + const auto& cev = ev.clipboard; + return getClipboardChannelContext().handleEvent(cev); + } default: return true; } diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 4299bd7ac..2f2c08579 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -235,10 +235,6 @@ static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const if (!sdl_Pointer_Set_Process(sdl)) return -1; break; - case SDL_EVENT_CLIPBOARD_UPDATE: - if (!sdl->getClipboardChannelContext().handle_update(windowEvent.clipboard)) - return -1; - break; case SDL_EVENT_USER_QUIT: default: break; diff --git a/winpr/include/winpr/platform.h b/winpr/include/winpr/platform.h index 702b82e8b..64fe8c068 100644 --- a/winpr/include/winpr/platform.h +++ b/winpr/include/winpr/platform.h @@ -533,9 +533,7 @@ WINPR_PRAGMA_DIAG_POP #define WINPR_DEPRECATED_VAR(text, obj) obj #endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 202202L) -#define WINPR_NORETURN(obj) [[noreturn]] obj -#elif defined(WIN32) && !defined(__CYGWIN__) +#if defined(WIN32) && !defined(__CYGWIN__) #define WINPR_NORETURN(obj) __declspec(noreturn) obj #elif defined(__GNUC__) #define WINPR_NORETURN(obj) __attribute__((__noreturn__)) obj From 03c350950a57c3028f9e52fc006ceeed6aa13da7 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 27 Jan 2026 14:03:06 +0100 Subject: [PATCH 27/30] [client,sdl] handle input events in SdlContext --- client/SDL/SDL3/sdl_context.cpp | 7 +++++++ client/SDL/SDL3/sdl_freerdp.cpp | 8 -------- client/SDL/SDL3/sdl_input.cpp | 27 +++++++++++++-------------- client/SDL/SDL3/sdl_input.hpp | 2 +- 4 files changed, 21 insertions(+), 23 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index acf47d7e4..fb7b9bc60 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -1101,6 +1101,13 @@ bool SdlContext::handleEvent(const SDL_Event& ev) const auto& cev = ev.clipboard; return getClipboardChannelContext().handleEvent(cev); } + case SDL_EVENT_KEY_DOWN: + case SDL_EVENT_KEY_UP: + { + const auto& cev = ev.key; + return getInputChannelContext().handleEvent(cev); + } + break; default: return true; } diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 2f2c08579..edd41bf75 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -115,14 +115,6 @@ static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const case SDL_EVENT_QUIT: freerdp_abort_connect_context(sdl->context()); break; - case SDL_EVENT_KEY_DOWN: - case SDL_EVENT_KEY_UP: - { - const SDL_KeyboardEvent* ev = &windowEvent.key; - if (!sdl->getInputChannelContext().keyboard_handle_event(ev)) - return -1; - } - break; case SDL_EVENT_RENDER_TARGETS_RESET: std::ignore = sdl->redraw(); break; diff --git a/client/SDL/SDL3/sdl_input.cpp b/client/SDL/SDL3/sdl_input.cpp index 7866f7798..1d9ef0f5b 100644 --- a/client/SDL/SDL3/sdl_input.cpp +++ b/client/SDL/SDL3/sdl_input.cpp @@ -558,17 +558,16 @@ bool sdlInput::extract(const std::string& token, uint32_t& key, uint32_t& value) return freerdp_extract_key_value(token.c_str(), &key, &value); } -bool sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) +bool sdlInput::handleEvent(const SDL_KeyboardEvent& ev) { - WINPR_ASSERT(ev); - const UINT32 rdp_scancode = scancode_to_rdp(ev->scancode); + const UINT32 rdp_scancode = scancode_to_rdp(ev.scancode); const SDL_Keymod mods = SDL_GetModState(); if (_hotkeysEnabled && (mods & _hotkeyModmask) == _hotkeyModmask) { - if (ev->type == SDL_EVENT_KEY_DOWN) + if (ev.type == SDL_EVENT_KEY_DOWN) { - if (ev->scancode == _hotkeyFullscreen) + if (ev.scancode == _hotkeyFullscreen) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling fullscreen state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyFullscreen)); @@ -576,7 +575,7 @@ bool sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) return false; return _sdl->toggleFullscreen(); } - if (ev->scancode == _hotkeyResizable) + if (ev.scancode == _hotkeyResizable) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling resizeable state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyResizable)); @@ -585,15 +584,15 @@ bool sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) return _sdl->toggleResizeable(); } - if (ev->scancode == _hotkeyGrab) + if (ev.scancode == _hotkeyGrab) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, toggling grab state", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyGrab)); if (!keyboard_sync_state()) return false; - return keyboard_grab(ev->windowID, !_sdl->grabKeyboard()); + return keyboard_grab(ev.windowID, !_sdl->grabKeyboard()); } - if (ev->scancode == _hotkeyDisconnect) + if (ev.scancode == _hotkeyDisconnect) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, disconnecting RDP session", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyDisconnect)); @@ -602,7 +601,7 @@ bool sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) freerdp_abort_connect_context(_sdl->context()); return true; } - if (ev->scancode == _hotkeyMinimize) + if (ev.scancode == _hotkeyMinimize) { WLog_Print(_sdl->getWLog(), WLOG_INFO, "%s+<%s> pressed, minimizing client", masktostr(_hotkeyModmask).c_str(), sdl_scancode_name(_hotkeyMinimize)); @@ -619,7 +618,7 @@ bool sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) const DWORD sc = RDP_SCANCODE_CODE(rdp_scancode); WLog_Print(_sdl->getWLog(), WLOG_DEBUG, "SDL keycode: %02" PRIX32 " -> rdp code: [%04" PRIx16 "] %02" PRIX8 "%s", - ev->scancode, rdp_scancode, sc, ex ? " extended" : ""); + ev.scancode, rdp_scancode, sc, ex ? " extended" : ""); } #endif @@ -631,11 +630,11 @@ bool sdlInput::keyboard_handle_event(const SDL_KeyboardEvent* ev) WLog_Print(_sdl->getWLog(), WLOG_DEBUG, "SDL keycode: %02" PRIX32 " -> remapped rdp code: [%04" PRIx16 "] %02" PRIX8 "%s", - ev->scancode, scancode, sc, ex ? " extended" : ""); + ev.scancode, scancode, sc, ex ? " extended" : ""); } #endif - return freerdp_input_send_keyboard_event_ex( - _sdl->context()->input, ev->type == SDL_EVENT_KEY_DOWN, ev->repeat, scancode); + return freerdp_input_send_keyboard_event_ex(_sdl->context()->input, + ev.type == SDL_EVENT_KEY_DOWN, ev.repeat, scancode); } bool sdlInput::keyboard_grab(Uint32 windowID, bool enable) diff --git a/client/SDL/SDL3/sdl_input.hpp b/client/SDL/SDL3/sdl_input.hpp index 2e392c4e6..d1fdadbfd 100644 --- a/client/SDL/SDL3/sdl_input.hpp +++ b/client/SDL/SDL3/sdl_input.hpp @@ -47,7 +47,7 @@ class sdlInput [[nodiscard]] bool keyboard_sync_state(); [[nodiscard]] bool keyboard_focus_in(); - [[nodiscard]] bool keyboard_handle_event(const SDL_KeyboardEvent* ev); + [[nodiscard]] bool handleEvent(const SDL_KeyboardEvent& ev); [[nodiscard]] bool keyboard_grab(Uint32 windowID, bool enable); [[nodiscard]] bool mouse_focus(Uint32 windowID); From 197ac808fd0d1424ae2c9111ff2e87754ecb3a0d Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 27 Jan 2026 14:05:34 +0100 Subject: [PATCH 28/30] [client,sdl] handle render events in SdlContext --- client/SDL/SDL3/sdl_context.cpp | 5 ++++- client/SDL/SDL3/sdl_freerdp.cpp | 9 --------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index fb7b9bc60..d3fe86dcc 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -1107,7 +1107,10 @@ bool SdlContext::handleEvent(const SDL_Event& ev) const auto& cev = ev.key; return getInputChannelContext().handleEvent(cev); } - break; + case SDL_EVENT_RENDER_TARGETS_RESET: + case SDL_EVENT_RENDER_DEVICE_RESET: + case SDL_EVENT_WILL_ENTER_FOREGROUND: + return redraw(); default: return true; } diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index edd41bf75..81d86a1c3 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -115,15 +115,6 @@ static void sdl_term_handler([[maybe_unused]] int signum, [[maybe_unused]] const case SDL_EVENT_QUIT: freerdp_abort_connect_context(sdl->context()); break; - case SDL_EVENT_RENDER_TARGETS_RESET: - std::ignore = sdl->redraw(); - break; - case SDL_EVENT_RENDER_DEVICE_RESET: - std::ignore = sdl->redraw(); - break; - case SDL_EVENT_WILL_ENTER_FOREGROUND: - std::ignore = sdl->redraw(); - break; case SDL_EVENT_USER_CERT_DIALOG: { SDLConnectionDialogHider hider(sdl); From 00cfc36987f3e836c681d436c9f91b3a35bd4019 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 27 Jan 2026 14:40:16 +0100 Subject: [PATCH 29/30] [client,sdl] warn about multimonitor issues --- client/SDL/SDL3/sdl_context.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index d3fe86dcc..b4e26731d 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -214,6 +214,28 @@ BOOL SdlContext::postConnect(freerdp* instance) auto sdl = get_context(context); + if (freerdp_settings_get_bool(context->settings, FreeRDP_UseMultimon)) + { + const auto driver = SDL_GetCurrentVideoDriver(); + if (driver && strcmp(driver, "wayland") == 0) + { + const auto name = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING); + + WLog_Print(sdl->getWLog(), WLOG_WARN, + "%s is affected by wayland bug " + "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/179", + name); + WLog_Print( + sdl->getWLog(), WLOG_WARN, + "you will not be able to properly use all monitors for FreeRDP unless this is " + "resolved and the SDL library you are using supports this."); + WLog_Print(sdl->getWLog(), WLOG_WARN, + "For the time being run %s from an X11 session or only use single monitor " + "fullscreen /f", + name); + } + } + // Retry was successful, discard dialog sdl->getDialog().show(false); From 501740404f5020121a0fee6361027417a2361e75 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 27 Jan 2026 15:35:12 +0100 Subject: [PATCH 30/30] [client,sdl] check for XWayland for warning Also check for a wayland environment if the SDL driver is x11. This is also affected by the multimonitor bug. --- client/SDL/SDL3/sdl_context.cpp | 19 ++++++++++++++++++- client/SDL/SDL3/sdl_utils.cpp | 1 - 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/client/SDL/SDL3/sdl_context.cpp b/client/SDL/SDL3/sdl_context.cpp index b4e26731d..75df27721 100644 --- a/client/SDL/SDL3/sdl_context.cpp +++ b/client/SDL/SDL3/sdl_context.cpp @@ -217,7 +217,24 @@ BOOL SdlContext::postConnect(freerdp* instance) if (freerdp_settings_get_bool(context->settings, FreeRDP_UseMultimon)) { const auto driver = SDL_GetCurrentVideoDriver(); - if (driver && strcmp(driver, "wayland") == 0) + bool buggy = false; + if (driver) + { + if (strcmp(driver, "wayland") == 0) + buggy = true; + else if (strcmp(driver, "x11") == 0) + { + auto env = SDL_GetEnvironment(); + auto xdg = SDL_GetEnvironmentVariable(env, "XDG_SESSION_TYPE"); + auto qpa = SDL_GetEnvironmentVariable(env, "QT_QPA_PLATFORM"); + if (xdg && (strcmp(xdg, "wayland") == 0)) + buggy = true; + else if (qpa && (strcmp(qpa, "wayland") == 0)) + buggy = true; + } + } + + if (buggy) { const auto name = SDL_GetAppMetadataProperty(SDL_PROP_APP_METADATA_NAME_STRING); diff --git a/client/SDL/SDL3/sdl_utils.cpp b/client/SDL/SDL3/sdl_utils.cpp index c1890ddcd..970d4e1e7 100644 --- a/client/SDL/SDL3/sdl_utils.cpp +++ b/client/SDL/SDL3/sdl_utils.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include "sdl_utils.hpp"