From fd800e6dd781eab245fec475b907fd2b3e39b3dd Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Mon, 21 Jul 2014 09:12:17 -0700 Subject: [PATCH] GUAC-771: Ensure display surface is available during initial connection. --- src/protocols/rdp/client.c | 26 ++++++++---------- src/protocols/rdp/rdp_bitmap.c | 6 +--- src/protocols/rdp/rdp_gdi.c | 14 ++++++++++ src/protocols/rdp/rdp_gdi.h | 47 ++++++++++++++++++++++++++++++-- src/protocols/rdp/rdp_glyph.c | 4 +-- src/protocols/rdp/rdp_settings.c | 30 +++++++++++++------- src/protocols/rdp/rdp_settings.h | 15 ++++++++-- 7 files changed, 106 insertions(+), 36 deletions(-) diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 921ebe81..95281e66 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -307,6 +307,7 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) { free(pointer); /* Set up GDI */ + instance->update->DesktopResize = guac_rdp_gdi_desktop_resize; instance->update->EndPaint = guac_rdp_gdi_end_paint; instance->update->Palette = guac_rdp_gdi_palette_update; instance->update->SetBounds = guac_rdp_gdi_set_bounds; @@ -696,6 +697,17 @@ int guac_client_init(guac_client* client, int argc, char** argv) { /* Load keymap into client */ __guac_rdp_client_load_keymap(client, settings->server_layout); + /* Create default surface */ + guac_client_data->default_surface = guac_common_surface_alloc(client->socket, GUAC_DEFAULT_LAYER, + settings->width, settings->height); + guac_client_data->current_surface = guac_client_data->default_surface; + + /* Send connection name */ + guac_protocol_send_name(client->socket, settings->hostname); + + /* Set default pointer */ + guac_common_set_pointer_cursor(client); + /* Push desired settings to FreeRDP */ guac_rdp_push_settings(settings, rdp_inst); @@ -705,20 +717,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) { return 1; } - /* Pull actual settings back from FreeRDP */ - guac_rdp_pull_settings(rdp_inst, settings); - - /* Send connection name */ - guac_protocol_send_name(client->socket, settings->hostname); - - /* Create default surface */ - guac_client_data->default_surface = guac_common_surface_alloc(client->socket, GUAC_DEFAULT_LAYER, - settings->width, settings->height); - guac_client_data->current_surface = guac_client_data->default_surface; - - /* Set default pointer */ - guac_common_set_pointer_cursor(client); - /* Success */ return 0; diff --git a/src/protocols/rdp/rdp_bitmap.c b/src/protocols/rdp/rdp_bitmap.c index 2b2502c2..43483a9d 100644 --- a/src/protocols/rdp/rdp_bitmap.c +++ b/src/protocols/rdp/rdp_bitmap.c @@ -79,14 +79,10 @@ void guac_rdp_bitmap_new(rdpContext* context, rdpBitmap* bitmap) { /* Convert image data if present */ if (bitmap->data != NULL) { - /* Get client data */ - guac_client* client = ((rdp_freerdp_context*) context)->client; - rdp_guac_client_data* client_data = (rdp_guac_client_data*) client->data; - /* Convert image data to 32-bit RGB */ unsigned char* image_buffer = freerdp_image_convert(bitmap->data, NULL, bitmap->width, bitmap->height, - client_data->settings.color_depth, + guac_rdp_get_depth(context->instance), 32, ((rdp_freerdp_context*) context)->clrconv); /* Free existing image, if any */ diff --git a/src/protocols/rdp/rdp_gdi.c b/src/protocols/rdp/rdp_gdi.c index 724f9fac..d6dc809e 100644 --- a/src/protocols/rdp/rdp_gdi.c +++ b/src/protocols/rdp/rdp_gdi.c @@ -372,3 +372,17 @@ void guac_rdp_gdi_end_paint(rdpContext* context) { /* IGNORE */ } +void guac_rdp_gdi_desktop_resize(rdpContext* context) { + + guac_client* client = ((rdp_freerdp_context*) context)->client; + rdp_guac_client_data* data = (rdp_guac_client_data*) client->data; + + guac_common_surface_resize(data->default_surface, + guac_rdp_get_width(context->instance), + guac_rdp_get_height(context->instance)); + + guac_common_surface_reset_clip(data->default_surface); + +} + + diff --git a/src/protocols/rdp/rdp_gdi.h b/src/protocols/rdp/rdp_gdi.h index 189f7b17..9520c0f1 100644 --- a/src/protocols/rdp/rdp_gdi.h +++ b/src/protocols/rdp/rdp_gdi.h @@ -29,16 +29,59 @@ #include #include -guac_composite_mode guac_rdp_rop3_transfer_function(guac_client* client, - int rop3); +/** + * Translates a standard RDP ROP3 value into a guac_composite_mode. + */ +guac_composite_mode guac_rdp_rop3_transfer_function(guac_client* client, int rop3); +/** + * Handler for RDP DSTBLT update. + */ void guac_rdp_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt); + +/** + * Handler for RDP PATBLT update. + */ void guac_rdp_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt); + +/** + * Handler for RDP SCRBLT update. + */ void guac_rdp_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt); + +/** + * Handler for RDP MEMBLT update. + */ void guac_rdp_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt); + +/** + * Handler for RDP OPAQUE_RECT update. + */ void guac_rdp_gdi_opaquerect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect); + +/** + * Handler called when the remote color palette is changing. + */ void guac_rdp_gdi_palette_update(rdpContext* context, PALETTE_UPDATE* palette); + +/** + * Handler called prior to calling the handlers for specific updates when + * those updatese are clipped by a bounding rectangle. + */ void guac_rdp_gdi_set_bounds(rdpContext* context, rdpBounds* bounds); + +/** + * Handler called when a paint operation is complete. We don't actually + * use this, but FreeRDP requires it. + */ void guac_rdp_gdi_end_paint(rdpContext* context); +/** + * Handler called when the desktop dimensions change, either from a + * true desktop resize event received by the RDP client, or due to + * a revised size given by the server during initial connection + * negotiation. + */ +void guac_rdp_gdi_desktop_resize(rdpContext* context); + #endif diff --git a/src/protocols/rdp/rdp_glyph.c b/src/protocols/rdp/rdp_glyph.c index 621251a5..403cc9e1 100644 --- a/src/protocols/rdp/rdp_glyph.c +++ b/src/protocols/rdp/rdp_glyph.c @@ -136,7 +136,7 @@ void guac_rdp_glyph_begindraw(rdpContext* context, /* Convert background color */ bgcolor = freerdp_color_convert_var(bgcolor, - guac_client_data->settings.color_depth, 32, + guac_rdp_get_depth(context->instance), 32, ((rdp_freerdp_context*) context)->clrconv); guac_common_surface_rect(guac_client_data->current_surface, x, y, width, height, @@ -148,7 +148,7 @@ void guac_rdp_glyph_begindraw(rdpContext* context, /* Convert foreground color */ guac_client_data->glyph_color = freerdp_color_convert_var(fgcolor, - guac_client_data->settings.color_depth, 32, ((rdp_freerdp_context*) context)->clrconv); + guac_rdp_get_depth(context->instance), 32, ((rdp_freerdp_context*) context)->clrconv); } diff --git a/src/protocols/rdp/rdp_settings.c b/src/protocols/rdp/rdp_settings.c index d00da5e2..b219a72b 100644 --- a/src/protocols/rdp/rdp_settings.c +++ b/src/protocols/rdp/rdp_settings.c @@ -34,20 +34,28 @@ #include -void guac_rdp_pull_settings(freerdp* rdp, guac_rdp_settings* guac_settings) { - - rdpSettings* rdp_settings = rdp->settings; - +int guac_rdp_get_width(freerdp* rdp) { #ifdef LEGACY_RDPSETTINGS - guac_settings->color_depth = rdp_settings->color_depth; - guac_settings->width = rdp_settings->width; - guac_settings->height = rdp_settings->height; + return rdp->settings->width; #else - guac_settings->color_depth = rdp_settings->ColorDepth; - guac_settings->width = rdp_settings->DesktopWidth; - guac_settings->height = rdp_settings->DesktopHeight; + return rdp->settings->DesktopWidth; #endif +} +int guac_rdp_get_height(freerdp* rdp) { +#ifdef LEGACY_RDPSETTINGS + return rdp->settings->height; +#else + return rdp->settings->DesktopHeight; +#endif +} + +int guac_rdp_get_depth(freerdp* rdp) { +#ifdef LEGACY_RDPSETTINGS + return rdp->settings->color_depth; +#else + return rdp->settings->ColorDepth; +#endif } void guac_rdp_push_settings(guac_rdp_settings* guac_settings, freerdp* rdp) { @@ -202,6 +210,7 @@ void guac_rdp_push_settings(guac_rdp_settings* guac_settings, freerdp* rdp) { rdp_settings->fast_path_input = FALSE; rdp_settings->fast_path_output = FALSE; #endif + rdp_settings->desktop_resize = TRUE; rdp_settings->order_support[NEG_DSTBLT_INDEX] = TRUE; rdp_settings->order_support[NEG_PATBLT_INDEX] = FALSE; /* PATBLT not yet supported */ rdp_settings->order_support[NEG_SCRBLT_INDEX] = TRUE; @@ -234,6 +243,7 @@ void guac_rdp_push_settings(guac_rdp_settings* guac_settings, freerdp* rdp) { rdp_settings->FastPathInput = FALSE; rdp_settings->FastPathOutput = FALSE; #endif + rdp_settings->DesktopResize = TRUE; rdp_settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; rdp_settings->OrderSupport[NEG_PATBLT_INDEX] = FALSE; /* PATBLT not yet supported */ rdp_settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; diff --git a/src/protocols/rdp/rdp_settings.h b/src/protocols/rdp/rdp_settings.h index f1fda0a2..e6e152d0 100644 --- a/src/protocols/rdp/rdp_settings.h +++ b/src/protocols/rdp/rdp_settings.h @@ -209,10 +209,19 @@ typedef struct guac_rdp_settings { void guac_rdp_push_settings(guac_rdp_settings* guac_settings, freerdp* rdp); /** - * Pull all settings from the given freerdp instance into the client - * stored settings. + * Returns the width of the RDP session display. */ -void guac_rdp_pull_settings(freerdp* rdp, guac_rdp_settings* guac_settings); +int guac_rdp_get_width(freerdp* rdp); + +/** + * Returns the height of the RDP session display. + */ +int guac_rdp_get_height(freerdp* rdp); + +/** + * Returns the depth of the RDP session display. + */ +int guac_rdp_get_depth(freerdp* rdp); #endif