From d1a66f5616a549507f577abcc8a1ba1a4585a60b Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 25 Mar 2014 14:25:34 -0700 Subject: [PATCH] GUAC-552: If resolution is above 96 DPI, try to find a reasonable screen size at 96 DPI or 120 DPI, using native resolution as a last resort. --- src/protocols/rdp/client.c | 39 ++++++++++++++++++++++++++++++++++++-- src/protocols/rdp/client.h | 19 +++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/protocols/rdp/client.c b/src/protocols/rdp/client.c index 13c489eb..8bcd52ae 100644 --- a/src/protocols/rdp/client.c +++ b/src/protocols/rdp/client.c @@ -426,6 +426,30 @@ void __guac_rdp_client_load_keymap(guac_client* client, } +/** + * Reduces the resolution of the client to the given resolution in DPI if + * doing so is reasonable. This function returns non-zero if the resolution + * was successfully reduced to the given DPI, and zero if reduction failed. + */ +static int __guac_rdp_reduce_resolution(guac_client* client, int resolution) { + + int width = client->info.optimal_width * resolution / client->info.optimal_resolution; + int height = client->info.optimal_height * resolution / client->info.optimal_resolution; + + /* Reduced resolution if result is reasonably sized */ + if (width*height >= GUAC_RDP_REASONABLE_AREA) { + client->info.optimal_width = width; + client->info.optimal_height = height; + client->info.optimal_resolution = resolution; + guac_client_log_info(client, "Reducing resolution to %ix%i at %i DPI", width, height, resolution); + return 1; + } + + /* No reduction performed */ + return 0; + +} + int guac_client_init(guac_client* client, int argc, char** argv) { rdp_guac_client_data* guac_client_data; @@ -513,8 +537,19 @@ int guac_client_init(guac_client* client, int argc, char** argv) { if (argv[IDX_PORT][0] != '\0') settings->port = atoi(argv[IDX_PORT]); + guac_client_log_info(client, "Client resolution is %ix%i at %i DPI", + client->info.optimal_width, + client->info.optimal_height, + client->info.optimal_resolution); + + /* Attempt to reduce resolution for high DPI */ + if (client->info.optimal_resolution > GUAC_RDP_NATIVE_RESOLUTION + && !__guac_rdp_reduce_resolution(client, GUAC_RDP_NATIVE_RESOLUTION) + && !__guac_rdp_reduce_resolution(client, GUAC_RDP_HIGH_RESOLUTION)) + guac_client_log_info(client, "No reasonable lower resolution"); + /* Use optimal width unless overridden */ - settings->width = client->info.optimal_width * 96 / client->info.optimal_resolution; + settings->width = client->info.optimal_width; if (argv[IDX_WIDTH][0] != '\0') settings->width = atoi(argv[IDX_WIDTH]); @@ -530,7 +565,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { settings->width = settings->width & ~0x3; /* Use optimal height unless overridden */ - settings->height = client->info.optimal_height * 96 / client->info.optimal_resolution; + settings->height = client->info.optimal_height; if (argv[IDX_HEIGHT][0] != '\0') settings->height = atoi(argv[IDX_HEIGHT]); diff --git a/src/protocols/rdp/client.h b/src/protocols/rdp/client.h index 28b3902f..05c8e9f1 100644 --- a/src/protocols/rdp/client.h +++ b/src/protocols/rdp/client.h @@ -51,6 +51,25 @@ */ #define GUAC_RDP_FRAME_TIMEOUT 0 +/** + * The native resolution of most RDP connections. As Windows and other systems + * rely heavily on forced 96 DPI, we must assume 96 DPI. + */ +#define GUAC_RDP_NATIVE_RESOLUTION 96 + +/** + * The resolution of an RDP connection that would be considered high, but is + * tolerable in the case that the client display would be unreasonably small + * otherwise. + */ +#define GUAC_RDP_HIGH_RESOLUTION 120 + +/** + * The smallest area, in pixels^2, that would be considered reasonable large + * screen DPI needs to be adjusted. + */ +#define GUAC_RDP_REASONABLE_AREA (800*600) + /** * Client data that will remain accessible through the guac_client. * This should generally include data commonly used by Guacamole handlers.