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:
commit
7ef33e5901
@ -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
|
||||||
|
@ -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')
|
||||||
|
@ -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,
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
60
src/protocols/rdp/resolution.c
Normal file
60
src/protocols/rdp/resolution.c
Normal 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
49
src/protocols/rdp/resolution.h
Normal file
49
src/protocols/rdp/resolution.h
Normal 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user