diff --git a/client/SDL/SDL2/dialogs/sdl_dialogs.cpp b/client/SDL/SDL2/dialogs/sdl_dialogs.cpp index 32f845763..6db8ff2b6 100644 --- a/client/SDL/SDL2/dialogs/sdl_dialogs.cpp +++ b/client/SDL/SDL2/dialogs/sdl_dialogs.cpp @@ -214,8 +214,11 @@ SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, vo WINPR_ASSERT(what); auto sdl = get_context(instance->context); + auto settings = instance->context->settings; + const size_t delay = freerdp_settings_get_uint32(settings, FreeRDP_TcpConnectTimeout); std::lock_guard lock(sdl->critical); - WINPR_ASSERT(sdl->connection_dialog); + if (!sdl->connection_dialog) + return delay; sdl->connection_dialog->setTitle("Retry connection to %s", freerdp_settings_get_server_name(instance->context->settings)); @@ -233,7 +236,6 @@ SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, vo what); } - auto settings = instance->context->settings; const BOOL enabled = freerdp_settings_get_bool(settings, FreeRDP_AutoReconnectionEnabled); if (!enabled) @@ -244,7 +246,7 @@ SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, vo } const size_t max = freerdp_settings_get_uint32(settings, FreeRDP_AutoReconnectMaxRetries); - const size_t delay = freerdp_settings_get_uint32(settings, FreeRDP_TcpConnectTimeout); + if (current >= max) { sdl->connection_dialog->showError( diff --git a/client/SDL/SDL2/sdl_disp.cpp b/client/SDL/SDL2/sdl_disp.cpp index 34863baec..491d8af9f 100644 --- a/client/SDL/SDL2/sdl_disp.cpp +++ b/client/SDL/SDL2/sdl_disp.cpp @@ -337,7 +337,10 @@ BOOL sdlDispContext::handle_display_event(const SDL_DisplayEvent* ev) BOOL sdlDispContext::handle_window_event(const SDL_WindowEvent* ev) { WINPR_ASSERT(ev); - +#if defined(WITH_DEBUG_SDL_EVENTS) + SDL_Log("got windowEvent %s [0x%08" PRIx32 "]", sdl_window_event_str(ev->event).c_str(), + ev->event); +#endif auto bordered = freerdp_settings_get_bool(_sdl->context()->settings, FreeRDP_Decorations) ? SDL_TRUE : SDL_FALSE; @@ -351,7 +354,6 @@ BOOL sdlDispContext::handle_window_event(const SDL_WindowEvent* ev) case SDL_WINDOWEVENT_HIDDEN: case SDL_WINDOWEVENT_MINIMIZED: gdi_send_suppress_output(_sdl->context()->gdi, TRUE); - return TRUE; case SDL_WINDOWEVENT_EXPOSED: diff --git a/client/SDL/SDL2/sdl_freerdp.cpp b/client/SDL/SDL2/sdl_freerdp.cpp index 8306c7cc5..10b00e0d7 100644 --- a/client/SDL/SDL2/sdl_freerdp.cpp +++ b/client/SDL/SDL2/sdl_freerdp.cpp @@ -220,6 +220,14 @@ static const struct sdl_exit_code_map_t* sdl_map_entry_by_code(int exit_code) return nullptr; } +static void sdl_hide_connection_dialog(SdlContext* sdl) +{ + WINPR_ASSERT(sdl); + std::lock_guard lock(sdl->critical); + if (sdl->connection_dialog) + sdl->connection_dialog->hide(); +} + static const struct sdl_exit_code_map_t* sdl_map_entry_by_error(DWORD error) { for (size_t x = 0; x < ARRAYSIZE(sdl_exit_code_map); x++) @@ -781,6 +789,8 @@ static bool shall_abort(SdlContext* sdl) std::lock_guard lock(sdl->critical); if (freerdp_shall_disconnect_context(sdl->context())) { + if (sdl->rdp_thread_running) + return false; if (!sdl->connection_dialog) return true; return !sdl->connection_dialog->running(); @@ -914,14 +924,14 @@ static int sdl_run(SdlContext* sdl) case SDL_WINDOWEVENT: { const SDL_WindowEvent* ev = &windowEvent.window; - sdl->disp.handle_window_event(ev); - + auto window = sdl->windows.find(ev->windowID); + if (window != sdl->windows.end()) + sdl->disp.handle_window_event(ev); switch (ev->event) { case SDL_WINDOWEVENT_RESIZED: case SDL_WINDOWEVENT_SIZE_CHANGED: { - auto window = sdl->windows.find(ev->windowID); if (window != sdl->windows.end()) { window->second.fill(); @@ -931,7 +941,6 @@ static int sdl_run(SdlContext* sdl) break; case SDL_WINDOWEVENT_MOVED: { - auto window = sdl->windows.find(ev->windowID); if (window != sdl->windows.end()) { auto r = window->second.rect(); @@ -1071,11 +1080,7 @@ static BOOL sdl_post_connect(freerdp* instance) auto sdl = get_context(context); // Retry was successful, discard dialog - { - std::lock_guard lock(sdl->critical); - if (sdl->connection_dialog) - sdl->connection_dialog->hide(); - } + sdl_hide_connection_dialog(sdl); if (freerdp_settings_get_bool(context->settings, FreeRDP_AuthenticationOnly)) { @@ -1165,6 +1170,7 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) auto instance = sdl->context()->instance; WINPR_ASSERT(instance); + sdl->rdp_thread_running = true; BOOL rc = freerdp_connect(instance); rdpContext* context = sdl->context(); @@ -1200,11 +1206,15 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) freerdp_get_last_error_string(last)); } - if (last == FREERDP_ERROR_AUTHENTICATION_FAILED) - exit_code = SDL_EXIT_AUTH_FAILURE; - else if (code == ERRINFO_SUCCESS) - exit_code = SDL_EXIT_CONN_FAILED; + if (exit_code == SDL_EXIT_SUCCESS) + { + if (last == FREERDP_ERROR_AUTHENTICATION_FAILED) + exit_code = SDL_EXIT_AUTH_FAILURE; + else if (code == ERRINFO_SUCCESS) + exit_code = SDL_EXIT_CONN_FAILED; + } + sdl_hide_connection_dialog(sdl); goto terminate; } @@ -1233,12 +1243,19 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) break; } - status = WaitForMultipleObjects(nCount, handles, FALSE, 100); + 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_hide_connection_dialog(sdl); continue; + } else { /* @@ -1252,14 +1269,8 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) WLog_Print(sdl->log, WLOG_ERROR, "WaitForMultipleObjects failed with %" PRIu32 "", status); - break; - } - - if (!freerdp_check_event_handles(context)) - { if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) WLog_Print(sdl->log, WLOG_ERROR, "Failed to check FreeRDP event handles"); - break; } } @@ -1288,6 +1299,8 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) freerdp_disconnect(instance); terminate: + 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_map_to_code_tag(exit_code), exit_code); @@ -1299,17 +1312,24 @@ terminate: case SDL_EXIT_DISCONNECT: case SDL_EXIT_LOGOFF: case SDL_EXIT_DISCONNECT_BY_USER: + case SDL_EXIT_CONNECT_CANCELLED: break; default: { std::lock_guard lock(sdl->critical); if (sdl->connection_dialog && error_msg) + { sdl->connection_dialog->showError(error_msg); + showError = true; + } } break; } } free(error_msg); + if (!showError) + sdl_hide_connection_dialog(sdl); + sdl->exit_code = exit_code; sdl_push_user_event(SDL_USEREVENT_QUIT); #if SDL_VERSION_ATLEAST(2, 0, 16) @@ -1691,7 +1711,8 @@ BOOL SdlContext::update_resizeable(BOOL enable) SdlContext::SdlContext(rdpContext* context) : _context(context), log(WLog_Get(SDL_TAG)), update_complete(true), disp(this), input(this), - primary(nullptr, SDL_FreeSurface), primary_format(nullptr, SDL_FreeFormat) + primary(nullptr, SDL_FreeSurface), primary_format(nullptr, SDL_FreeFormat), + rdp_thread_running(false) { WINPR_ASSERT(context); grab_kbd_enabled = freerdp_settings_get_bool(context->settings, FreeRDP_GrabKeyboard); diff --git a/client/SDL/SDL2/sdl_freerdp.hpp b/client/SDL/SDL2/sdl_freerdp.hpp index 086ec1f17..976584a59 100644 --- a/client/SDL/SDL2/sdl_freerdp.hpp +++ b/client/SDL/SDL2/sdl_freerdp.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -80,6 +81,8 @@ class SdlContext std::unique_ptr connection_dialog; + std::atomic rdp_thread_running; + public: BOOL update_resizeable(BOOL enable); BOOL update_fullscreen(BOOL enter); diff --git a/client/SDL/SDL3/dialogs/sdl_dialogs.cpp b/client/SDL/SDL3/dialogs/sdl_dialogs.cpp index 50864dade..b1c5a224e 100644 --- a/client/SDL/SDL3/dialogs/sdl_dialogs.cpp +++ b/client/SDL/SDL3/dialogs/sdl_dialogs.cpp @@ -214,8 +214,12 @@ SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, vo WINPR_ASSERT(what); auto sdl = get_context(instance->context); + auto settings = instance->context->settings; + const BOOL enabled = freerdp_settings_get_bool(settings, FreeRDP_AutoReconnectionEnabled); + const size_t delay = freerdp_settings_get_uint32(settings, FreeRDP_TcpConnectTimeout); std::lock_guard lock(sdl->critical); - WINPR_ASSERT(sdl->connection_dialog); + if (!sdl->connection_dialog) + return delay; sdl->connection_dialog->setTitle("Retry connection to %s", freerdp_settings_get_server_name(instance->context->settings)); @@ -233,9 +237,6 @@ SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, vo what); } - auto settings = instance->context->settings; - const BOOL enabled = freerdp_settings_get_bool(settings, FreeRDP_AutoReconnectionEnabled); - if (!enabled) { sdl->connection_dialog->showError( @@ -244,7 +245,6 @@ SSIZE_T sdl_retry_dialog(freerdp* instance, const char* what, size_t current, vo } const size_t max = freerdp_settings_get_uint32(settings, FreeRDP_AutoReconnectMaxRetries); - const size_t delay = freerdp_settings_get_uint32(settings, FreeRDP_TcpConnectTimeout); if (current >= max) { sdl->connection_dialog->showError( diff --git a/client/SDL/SDL3/sdl_freerdp.cpp b/client/SDL/SDL3/sdl_freerdp.cpp index 103306890..05ba30c32 100644 --- a/client/SDL/SDL3/sdl_freerdp.cpp +++ b/client/SDL/SDL3/sdl_freerdp.cpp @@ -220,6 +220,14 @@ static const struct sdl_exit_code_map_t* sdl_map_entry_by_code(int exit_code) return nullptr; } +static void sdl_hide_connection_dialog(SdlContext* sdl) +{ + WINPR_ASSERT(sdl); + std::lock_guard lock(sdl->critical); + if (sdl->connection_dialog) + sdl->connection_dialog->hide(); +} + static const struct sdl_exit_code_map_t* sdl_map_entry_by_error(DWORD error) { for (size_t x = 0; x < ARRAYSIZE(sdl_exit_code_map); x++) @@ -779,6 +787,8 @@ static bool shall_abort(SdlContext* sdl) std::lock_guard lock(sdl->critical); if (freerdp_shall_disconnect_context(sdl->context())) { + if (sdl->rdp_thread_running) + return false; if (!sdl->connection_dialog) return true; return !sdl->connection_dialog->running(); @@ -1007,35 +1017,29 @@ static int sdl_run(SdlContext* sdl) (windowEvent.type <= SDL_EVENT_WINDOW_LAST)) { const SDL_WindowEvent* ev = &windowEvent.window; - sdl->disp.handle_window_event(ev); - - switch (ev->type) + auto window = sdl->windows.find(ev->windowID); + if (window != sdl->windows.end()) { - case SDL_EVENT_WINDOW_RESIZED: - case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: + sdl->disp.handle_window_event(ev); + + switch (ev->type) { - auto window = sdl->windows.find(ev->windowID); - if (window != sdl->windows.end()) - { + case SDL_EVENT_WINDOW_RESIZED: + case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: window->second.fill(); window->second.updateSurface(); - } - } - break; + break; case SDL_EVENT_WINDOW_MOVED: { - auto window = sdl->windows.find(ev->windowID); - if (window != sdl->windows.end()) - { - auto r = window->second.rect(); - auto id = window->second.id(); - WLog_DBG(SDL_TAG, "%lu: %dx%d-%dx%d", id, r.x, r.y, r.w, r.h); - } + auto r = window->second.rect(); + auto id = window->second.id(); + WLog_DBG(SDL_TAG, "%lu: %dx%d-%dx%d", id, r.x, r.y, r.w, r.h); } break; default: break; } + } } break; } @@ -1066,11 +1070,7 @@ static BOOL sdl_post_connect(freerdp* instance) auto sdl = get_context(context); // Retry was successful, discard dialog - { - std::lock_guard lock(sdl->critical); - if (sdl->connection_dialog) - sdl->connection_dialog->hide(); - } + sdl_hide_connection_dialog(sdl); if (freerdp_settings_get_bool(context->settings, FreeRDP_AuthenticationOnly)) { @@ -1160,6 +1160,7 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) auto instance = sdl->context()->instance; WINPR_ASSERT(instance); + sdl->rdp_thread_running = true; BOOL rc = freerdp_connect(instance); rdpContext* context = sdl->context(); @@ -1195,11 +1196,15 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) freerdp_get_last_error_string(last)); } - if (last == FREERDP_ERROR_AUTHENTICATION_FAILED) - exit_code = SDL_EXIT_AUTH_FAILURE; - else if (code == ERRINFO_SUCCESS) - exit_code = SDL_EXIT_CONN_FAILED; + if (exit_code == SDL_EXIT_SUCCESS) + { + if (last == FREERDP_ERROR_AUTHENTICATION_FAILED) + exit_code = SDL_EXIT_AUTH_FAILURE; + else if (code == ERRINFO_SUCCESS) + exit_code = SDL_EXIT_CONN_FAILED; + } + sdl_hide_connection_dialog(sdl); goto terminate; } @@ -1228,12 +1233,19 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) break; } - status = WaitForMultipleObjects(nCount, handles, FALSE, 100); + 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_hide_connection_dialog(sdl); continue; + } else { /* @@ -1247,14 +1259,8 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) WLog_Print(sdl->log, WLOG_ERROR, "WaitForMultipleObjects failed with %" PRIu32 "", status); - break; - } - - if (!freerdp_check_event_handles(context)) - { if (freerdp_get_last_error(context) == FREERDP_ERROR_SUCCESS) WLog_Print(sdl->log, WLOG_ERROR, "Failed to check FreeRDP event handles"); - break; } } @@ -1283,6 +1289,8 @@ static DWORD WINAPI sdl_client_thread_proc(SdlContext* sdl) freerdp_disconnect(instance); terminate: + 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_map_to_code_tag(exit_code), exit_code); @@ -1294,17 +1302,24 @@ terminate: case SDL_EXIT_DISCONNECT: case SDL_EXIT_LOGOFF: case SDL_EXIT_DISCONNECT_BY_USER: + case SDL_EXIT_CONNECT_CANCELLED: break; default: { std::lock_guard lock(sdl->critical); if (sdl->connection_dialog && error_msg) + { sdl->connection_dialog->showError(error_msg); + showError = true; + } } break; } } free(error_msg); + if (!showError) + sdl_hide_connection_dialog(sdl); + sdl->exit_code = exit_code; sdl_push_user_event(SDL_EVENT_USER_QUIT); SDL_CleanupTLS(); @@ -1685,7 +1700,7 @@ BOOL SdlContext::update_resizeable(BOOL enable) SdlContext::SdlContext(rdpContext* context) : _context(context), log(WLog_Get(SDL_TAG)), update_complete(true), disp(this), clip(this), input(this), primary(nullptr, SDL_DestroySurface), - primary_format(nullptr, SDL_DestroyPixelFormat) + primary_format(nullptr, SDL_DestroyPixelFormat), rdp_thread_running(false) { WINPR_ASSERT(context); grab_kbd_enabled = freerdp_settings_get_bool(context->settings, FreeRDP_GrabKeyboard); diff --git a/client/SDL/SDL3/sdl_freerdp.hpp b/client/SDL/SDL3/sdl_freerdp.hpp index 5f968e898..933300c34 100644 --- a/client/SDL/SDL3/sdl_freerdp.hpp +++ b/client/SDL/SDL3/sdl_freerdp.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -82,6 +83,8 @@ class SdlContext std::unique_ptr connection_dialog; + std::atomic rdp_thread_running; + public: BOOL update_resizeable(BOOL enable); BOOL update_fullscreen(BOOL enter);