diff --git a/src/protocols/rdp/rdp.c b/src/protocols/rdp/rdp.c index a19e55ba..ab5734f3 100644 --- a/src/protocols/rdp/rdp.c +++ b/src/protocols/rdp/rdp.c @@ -170,27 +170,30 @@ static int __guac_receive_channel_data(freerdp* rdp_inst, int channelId, static void guac_rdp_channel_connected(rdpContext* context, ChannelConnectedEventArgs* e) { + guac_client* client = ((rdp_freerdp_context*) context)->client; + guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + guac_rdp_settings* settings = rdp_client->settings; + + if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) { #ifdef HAVE_RDPSETTINGS_SUPPORTDISPLAYCONTROL - /* Store reference to the display update plugin once it's connected */ - if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { + /* Store reference to the display update plugin once it's connected */ + if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) { - DispClientContext* disp = (DispClientContext*) e->pInterface; + DispClientContext* disp = (DispClientContext*) e->pInterface; - guac_client* client = ((rdp_freerdp_context*) context)->client; - guac_rdp_client* rdp_client = (guac_rdp_client*) client->data; + /* Init module with current display size */ + guac_rdp_disp_set_size(rdp_client->disp, rdp_client->settings, + context->instance, guac_rdp_get_width(context->instance), + guac_rdp_get_height(context->instance)); - /* Init module with current display size */ - guac_rdp_disp_set_size(rdp_client->disp, rdp_client->settings, - context->instance, guac_rdp_get_width(context->instance), - guac_rdp_get_height(context->instance)); + /* Store connected channel */ + guac_rdp_disp_connect(rdp_client->disp, disp); + guac_client_log(client, GUAC_LOG_DEBUG, + "Display update channel connected."); - /* Store connected channel */ - guac_rdp_disp_connect(rdp_client->disp, disp); - guac_client_log(client, GUAC_LOG_DEBUG, - "Display update channel connected."); - - } + } #endif + } } #endif diff --git a/src/protocols/rdp/rdp_disp.c b/src/protocols/rdp/rdp_disp.c index c7ea64ab..973c3013 100644 --- a/src/protocols/rdp/rdp_disp.c +++ b/src/protocols/rdp/rdp_disp.c @@ -169,37 +169,37 @@ void guac_rdp_disp_update_size(guac_rdp_disp* disp, disp->last_request = now; - if (1) { + if (settings->resize_method == GUAC_RESIZE_RECONNECT) { + /* Update settings with new dimensions */ settings->width = width; settings->height = height; /* Signal reconnect */ disp->reconnect_needed = 1; -#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT - disp->disp = NULL; -#endif - return; + } + else if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE) { #ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT - DISPLAY_CONTROL_MONITOR_LAYOUT monitors[1] = {{ - .Flags = 0x1, /* DISPLAYCONTROL_MONITOR_PRIMARY */ - .Left = 0, - .Top = 0, - .Width = width, - .Height = height, - .PhysicalWidth = 0, - .PhysicalHeight = 0, - .Orientation = 0, - .DesktopScaleFactor = 0, - .DeviceScaleFactor = 0 - }}; + DISPLAY_CONTROL_MONITOR_LAYOUT monitors[1] = {{ + .Flags = 0x1, /* DISPLAYCONTROL_MONITOR_PRIMARY */ + .Left = 0, + .Top = 0, + .Width = width, + .Height = height, + .PhysicalWidth = 0, + .PhysicalHeight = 0, + .Orientation = 0, + .DesktopScaleFactor = 0, + .DeviceScaleFactor = 0 + }}; - /* Send display update notification if display channel is connected */ - if (disp->disp != NULL) - disp->disp->SendMonitorLayout(disp->disp, 1, monitors); + /* Send display update notification if display channel is connected */ + if (disp->disp != NULL) + disp->disp->SendMonitorLayout(disp->disp, 1, monitors); #endif + } } diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c index 0e90f4dc..7cedb7c4 100644 --- a/src/protocols/rdp/rdp_settings.c +++ b/src/protocols/rdp/rdp_settings.c @@ -92,6 +92,7 @@ const char* GUAC_RDP_CLIENT_ARGS[] = { "recording-path", "recording-name", "create-recording-path", + "resize-method", NULL }; @@ -360,6 +361,12 @@ enum RDP_ARGS_IDX { IDX_RECORDING_NAME, IDX_CREATE_RECORDING_PATH, + /** + * The method to use to apply screen size changes requested by the user. + * Valid values are blank, "display-update", and "reconnect". + */ + IDX_RESIZE_METHOD, + RDP_ARGS_COUNT }; @@ -696,6 +703,31 @@ guac_rdp_settings* guac_rdp_parse_args(guac_user* user, guac_user_parse_args_boolean(user, GUAC_RDP_CLIENT_ARGS, argv, IDX_CREATE_RECORDING_PATH, 0); + /* No resize method */ + if (strcmp(argv[IDX_RESIZE_METHOD], "") == 0) { + guac_user_log(user, GUAC_LOG_INFO, "Resize method: none"); + settings->resize_method = GUAC_RESIZE_NONE; + } + + /* Resize method: "reconnect" */ + else if (strcmp(argv[IDX_RESIZE_METHOD], "reconnect") == 0) { + guac_user_log(user, GUAC_LOG_INFO, "Resize method: reconnect"); + settings->resize_method = GUAC_RESIZE_RECONNECT; + } + + /* Resize method: "display-update" */ + else if (strcmp(argv[IDX_RESIZE_METHOD], "display-update") == 0) { + guac_user_log(user, GUAC_LOG_INFO, "Resize method: display-update"); + settings->resize_method = GUAC_RESIZE_DISPLAY_UPDATE; + } + + /* Default to no resize method if invalid */ + else { + guac_user_log(user, GUAC_LOG_INFO, "Resize method \"%s\" invalid. ", + "Defaulting to no resize method.", argv[IDX_RESIZE_METHOD]); + settings->resize_method = GUAC_RESIZE_NONE; + } + /* Success */ return settings; diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/rdp_settings.h index f4c979ab..80c15b90 100644 --- a/src/protocols/rdp/rdp_settings.h +++ b/src/protocols/rdp/rdp_settings.h @@ -88,6 +88,32 @@ typedef enum guac_rdp_security { } guac_rdp_security; +/** + * All supported combinations screen resize methods. + */ +typedef enum guac_rdp_resize_method { + + /** + * Dynamic resizing of the display will not be attempted. + */ + GUAC_RESIZE_NONE, + + /** + * Dynamic resizing will be attempted through sending requests along the + * Display Update channel. This will only work with recent versions of + * Windows and relatively-recent versions of FreeRDP. + */ + GUAC_RESIZE_DISPLAY_UPDATE, + + /** + * Guacamole will automatically disconnect and reconnect to the RDP server + * whenever the screen size changes, requesting the new size during + * reconnect. + */ + GUAC_RESIZE_RECONNECT + +} guac_rdp_resize_method; + /** * All settings supported by the Guacamole RDP client. */ @@ -350,6 +376,11 @@ typedef struct guac_rdp_settings { */ int create_recording_path; + /** + * The method to apply when the user's display changes size. + */ + guac_rdp_resize_method resize_method; + } guac_rdp_settings; /**