diff --git a/rdesktop.c b/rdesktop.c index 085f9b5..e633c21 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -141,6 +141,8 @@ RD_BOOL g_has_reconnect_random = False; RD_BOOL g_reconnect_loop = False; uint8 g_client_random[SEC_RANDOM_SIZE]; RD_BOOL g_pending_resize = False; +RD_BOOL g_pending_resize_defer = True; +struct timeval g_pending_resize_defer_timer = {0}; #ifdef WITH_RDPSND RD_BOOL g_rdpsnd = False; @@ -487,6 +489,8 @@ handle_disconnect_reason(RD_BOOL deactivated, uint16 reason) static void rdesktop_reset_state(void) { + g_pending_resize_defer = True; + rdp_reset_state(); #ifdef WITH_SCARD scard_reset_state(); diff --git a/rdp.c b/rdp.c index e92f77f..ccb21bd 100644 --- a/rdp.c +++ b/rdp.c @@ -49,6 +49,8 @@ extern RD_BOOL g_bitmap_cache; extern RD_BOOL g_bitmap_cache_persist_enable; extern RD_BOOL g_numlock_sync; extern RD_BOOL g_pending_resize; +extern RD_BOOL g_pending_resize_defer; +extern struct timeval g_pending_resize_defer_timer; extern RD_BOOL g_network_error; extern time_t g_wait_for_deactivate_ts; @@ -1484,6 +1486,8 @@ process_ts_logon_info_extended(STREAM s) logger(Protocol, Debug, "process_ts_logon_info_extended(), saving Auto-Reconnect cookie, id=%u", g_reconnect_logonid); + + gettimeofday(&g_pending_resize_defer_timer, NULL); } } diff --git a/rdpedisp.c b/rdpedisp.c index 94c9050..43903ae 100644 --- a/rdpedisp.c +++ b/rdpedisp.c @@ -27,6 +27,7 @@ #define RDPEDISP_CHANNEL_NAME "Microsoft::Windows::RDS::DisplayControl" extern int g_dpi; +extern RD_BOOL g_pending_resize_defer; static void rdpedisp_send(STREAM s); static void rdpedisp_init_packet(STREAM s, uint32 type, uint32 length); @@ -43,6 +44,9 @@ rdpedisp_process_caps_pdu(STREAM s) logger(Protocol, Debug, "rdpedisp_process_caps_pdu(), Max supported monitor area (square pixels) is %d", tmp[0] * tmp[1] * tmp[2]); + + /* Start allowing session resizes */ + g_pending_resize_defer = False; } static void diff --git a/xwin.c b/xwin.c index c538ed9..776028f 100644 --- a/xwin.c +++ b/xwin.c @@ -58,6 +58,9 @@ extern RD_BOOL g_fullscreen; extern RD_BOOL g_grab_keyboard; extern RD_BOOL g_hide_decorations; extern RD_BOOL g_pending_resize; +extern RD_BOOL g_pending_resize_defer; +extern struct timeval g_pending_resize_defer_timer; + extern char g_title[]; extern char g_seamless_spawn_cmd[]; /* Color depth of the RDP session. @@ -2993,6 +2996,21 @@ process_ui() return False; } +static RD_BOOL +timeval_is_set(struct timeval *time) +{ + return (time->tv_sec == 0 && time->tv_usec == 0) ? False : True; +} + +/* Handle a pending resize. Resize is handled by either a disconnect/reconnect + sequence or online using RDPEDISP messages. Windows 2008 requires the use of + disconnect/reconnect and to do that without user login credentials the + auto-reconnect cookie is used. Windows 2008 seems sensitive to disconnects + to early in the login sequence so we defer to resize until we get the cookie. + + Windows 2016 on the other hand does not seem to send cookies but uses + RDPEDISP so in this case we defer until the RDPEDISP channel is established. + */ static RD_BOOL process_pending_resize () { @@ -3007,6 +3025,41 @@ process_pending_resize () if (time_difference_in_ms(g_resize_timer, now) <= 500) return False; + /* There is a race problem when using disconnect / reconnect + sequence were one sometimes would be presented with + unexpected login window. Waiting a little bit extra after + getting the reconnect cookie solves this problem. */ + if (timeval_is_set(&g_pending_resize_defer_timer) && + time_difference_in_ms(g_pending_resize_defer_timer, now) >= 100) + { + g_pending_resize_defer_timer.tv_sec = g_pending_resize_defer_timer.tv_usec = 0; + g_pending_resize_defer = False; + } + + if (g_pending_resize_defer == True) + return False; + + /* only for fullscreen or x%-of-screen-sized windows */ + if (g_window_size_type == PercentageOfScreen + || g_window_size_type == Fullscreen + || g_fullscreen) + { + /* follow root window size */ + width = WidthOfScreen(g_screen); + height = HeightOfScreen(g_screen); + if (g_window_size_type == PercentageOfScreen) + { + /* TODO: Implement percentage of screen */ + } + } + else + { + /* Follow window size */ + width = g_window_width; + height = g_window_height; + } + + /* carry out a resize to desired size */ if (rdpedisp_is_available() == False) { @@ -3015,8 +3068,8 @@ process_pending_resize () * server. */ - g_requested_session_width = g_window_width; - g_requested_session_height = g_window_height; + g_requested_session_width = width; + g_requested_session_height = height; logger(GUI, Verbose, "Window resize detected, reconnecting to new size %dx%d", g_requested_session_width,