Merge pull request #5 from glyptodon/resize-with-dpi

GUAC-936: Use initial resolution for all future resizing of display.
This commit is contained in:
James Muehlner 2014-12-01 11:23:43 -08:00
commit 7ef33e5901
6 changed files with 144 additions and 61 deletions

View File

@ -43,6 +43,7 @@ libguac_client_rdp_la_SOURCES = \
rdp_settings.c \ rdp_settings.c \
rdp_stream.c \ rdp_stream.c \
rdp_svc.c \ rdp_svc.c \
resolution.c \
unicode.c unicode.c
guacsvc_sources = \ guacsvc_sources = \
@ -95,6 +96,7 @@ noinst_HEADERS = \
rdp_status.h \ rdp_status.h \
rdp_stream.h \ rdp_stream.h \
rdp_svc.h \ rdp_svc.h \
resolution.h \
unicode.h unicode.h
# Add compatibility layer for WinPR if not available # Add compatibility layer for WinPR if not available

View File

@ -33,6 +33,7 @@
#include "rdp_pointer.h" #include "rdp_pointer.h"
#include "rdp_stream.h" #include "rdp_stream.h"
#include "rdp_svc.h" #include "rdp_svc.h"
#include "resolution.h"
#ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT #ifdef HAVE_FREERDP_DISPLAY_UPDATE_SUPPORT
#include "rdp_disp.h" #include "rdp_disp.h"
@ -509,56 +510,6 @@ 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(client, GUAC_LOG_INFO,
"Reducing resolution to %i DPI (%ix%i)", resolution, width, height);
return 1;
}
/* No reduction performed */
return 0;
}
/**
* Forces the client resolution to the given value, without checking whether
* the resulting width and height are reasonable.
*/
static void __guac_rdp_force_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;
/* Do not force DPI to zero */
if (resolution == 0) {
guac_client_log(client, GUAC_LOG_WARNING,
"Cowardly refusing to force resolution to %i DPI", resolution);
return;
}
/* Reduced resolution if result is reasonably sized */
client->info.optimal_width = width;
client->info.optimal_height = height;
client->info.optimal_resolution = resolution;
guac_client_log(client, GUAC_LOG_INFO,
"Resolution forced to %i DPI (%ix%i)", resolution, width, height);
}
int guac_client_init(guac_client* client, int argc, char** argv) { int guac_client_init(guac_client* client, int argc, char** argv) {
rdp_guac_client_data* guac_client_data; rdp_guac_client_data* guac_client_data;
@ -648,23 +599,22 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
if (argv[IDX_PORT][0] != '\0') if (argv[IDX_PORT][0] != '\0')
settings->port = atoi(argv[IDX_PORT]); settings->port = atoi(argv[IDX_PORT]);
guac_client_log(client, GUAC_LOG_INFO, "Client resolution is %ix%i at %i DPI", guac_client_log(client, GUAC_LOG_DEBUG,
"Client resolution is %ix%i at %i DPI",
client->info.optimal_width, client->info.optimal_width,
client->info.optimal_height, client->info.optimal_height,
client->info.optimal_resolution); client->info.optimal_resolution);
/* Use optimal resolution unless overridden */ /* Use suggested resolution unless overridden */
settings->resolution = guac_rdp_suggest_resolution(client);
if (argv[IDX_DPI][0] != '\0') if (argv[IDX_DPI][0] != '\0')
__guac_rdp_force_resolution(client, atoi(argv[IDX_DPI])); settings->resolution = atoi(argv[IDX_DPI]);
/* If resolution not forced, attempt to reduce resolution for high DPI */
else 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(client, GUAC_LOG_INFO, "No reasonable lower resolution");
/* Use optimal width unless overridden */ /* Use optimal width unless overridden */
settings->width = client->info.optimal_width; settings->width = client->info.optimal_width
* settings->resolution
/ client->info.optimal_resolution;
if (argv[IDX_WIDTH][0] != '\0') if (argv[IDX_WIDTH][0] != '\0')
settings->width = atoi(argv[IDX_WIDTH]); settings->width = atoi(argv[IDX_WIDTH]);
@ -680,7 +630,10 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
settings->width = settings->width & ~0x3; settings->width = settings->width & ~0x3;
/* Use optimal height unless overridden */ /* Use optimal height unless overridden */
settings->height = client->info.optimal_height; settings->height = client->info.optimal_height
* settings->resolution
/ client->info.optimal_resolution;
if (argv[IDX_HEIGHT][0] != '\0') if (argv[IDX_HEIGHT][0] != '\0')
settings->height = atoi(argv[IDX_HEIGHT]); settings->height = atoi(argv[IDX_HEIGHT]);
@ -692,6 +645,12 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
argv[IDX_WIDTH], settings->height); argv[IDX_WIDTH], settings->height);
} }
guac_client_log(client, GUAC_LOG_DEBUG,
"Using resolution of %ix%i at %i DPI",
settings->width,
settings->height,
settings->resolution);
/* Domain */ /* Domain */
settings->domain = NULL; settings->domain = NULL;
if (argv[IDX_DOMAIN][0] != '\0') if (argv[IDX_DOMAIN][0] != '\0')

View File

@ -480,6 +480,13 @@ int rdp_guac_client_size_handler(guac_client* client, int width, int height) {
freerdp* rdp_inst = guac_client_data->rdp_inst; freerdp* rdp_inst = guac_client_data->rdp_inst;
/* Convert client pixels to remote pixels */
width = width * guac_client_data->settings.resolution
/ client->info.optimal_resolution;
height = height * guac_client_data->settings.resolution
/ client->info.optimal_resolution;
/* Send display update */ /* Send display update */
pthread_mutex_lock(&(guac_client_data->rdp_lock)); pthread_mutex_lock(&(guac_client_data->rdp_lock));
guac_rdp_disp_set_size(guac_client_data->disp, rdp_inst->context, guac_rdp_disp_set_size(guac_client_data->disp, rdp_inst->context,

View File

@ -122,6 +122,12 @@ typedef struct guac_rdp_settings {
*/ */
int height; int height;
/**
* The DPI of the remote display to assume when converting between
* client pixels and remote pixels.
*/
int resolution;
/** /**
* Whether audio is enabled. * Whether audio is enabled.
*/ */

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2014 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "client.h"
#include "resolution.h"
#include <guacamole/client.h>
int guac_rdp_resolution_reasonable(guac_client* client, int resolution) {
int width = client->info.optimal_width;
int height = client->info.optimal_height;
/* Convert client pixels to remote pixels */
width = width * resolution / client->info.optimal_resolution;
height = height * resolution / client->info.optimal_resolution;
/*
* Resolution is reasonable if the same as the client optimal resolution
* OR if the resulting display area is reasonable
*/
return client->info.optimal_resolution == resolution
|| width*height >= GUAC_RDP_REASONABLE_AREA;
}
int guac_rdp_suggest_resolution(guac_client* client) {
/* Prefer RDP's native resolution */
if (guac_rdp_resolution_reasonable(client, GUAC_RDP_NATIVE_RESOLUTION))
return GUAC_RDP_NATIVE_RESOLUTION;
/* If native resolution is too tiny, try higher resolution */
if (guac_rdp_resolution_reasonable(client, GUAC_RDP_HIGH_RESOLUTION))
return GUAC_RDP_HIGH_RESOLUTION;
/* Fallback to client-suggested resolution */
return client->info.optimal_resolution;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2014 Glyptodon LLC
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef GUAC_RDP_RESOLUTION_H
#define GUAC_RDP_RESOLUTION_H
#include <guacamole/client.h>
/**
* Returns whether the given resolution is reasonable for the given client,
* based on arbitrary criteria for reasonability.
*
* @param client The guac_client to test the given resolution against.
* @param resolution The resolution to test, in DPI.
* @return Non-zero if the resolution is reasonable, zero otherwise.
*/
int guac_rdp_resolution_reasonable(guac_client* client, int resolution);
/**
* Returns a reasonable resolution for the remote display, given the size and
* resolution of a guac_client.
*
* @param client The guac_client whose size and resolution shall be used to
* determine an appropriate remote display resolution.
* @return A reasonable resolution for the remote display, in DPI.
*/
int guac_rdp_suggest_resolution(guac_client* client);
#endif