GUACAMOLE-1196: Correct VNC resize support to conform to the RFB standard.
This commit is contained in:
parent
af7ed38d8e
commit
32067616c9
51
configure.ac
51
configure.ac
@ -653,59 +653,40 @@ then
|
||||
fi
|
||||
|
||||
#
|
||||
# libVNCserver support for the rfbSetDesktopSizeMsg message, which allows the
|
||||
# VNC client to send its dimensions to the server, requesting that the server
|
||||
# resize itself to match. If libvnc lacks this message, remote resize will
|
||||
# be completely disabled.
|
||||
# libVNCserver support for the rfbSetDesktopSizeMsg message and the screen
|
||||
# data structure, both of which are required in order to properly request that
|
||||
# a remote server resize its screen to match the dimensions that the client
|
||||
# sends. If libvnc lacks either this message or the screen data structure
|
||||
# remote resize will be completely disabled.
|
||||
#
|
||||
|
||||
if test "x${have_libvncserver}" = "xyes"
|
||||
then
|
||||
|
||||
have_vnc_size_msg=yes
|
||||
have_vnc_resize_support=yes
|
||||
AC_CHECK_TYPE([rfbSetDesktopSizeMsg],
|
||||
[], [have_vnc_size_msg=no],
|
||||
[], [have_vnc_resize_support=no],
|
||||
[[#include <rfb/rfbproto.h>]])
|
||||
|
||||
if test "x${have_vnc_size_msg}" = "xno"
|
||||
AC_CHECK_MEMBERS([rfbClient.screen],
|
||||
[], [have_vnc_resize_support=no],
|
||||
[[#include <rfb/rfbclient.h>]])
|
||||
|
||||
if test "x${have_vnc_resize_support}" = "xno"
|
||||
then
|
||||
AC_MSG_WARN([
|
||||
--------------------------------------------------------
|
||||
No support for rfbSetDesktopSizeMsg in libvncclient.
|
||||
VNC support for remote display resize will be disabled.
|
||||
The libvncclient library lacks support for either the
|
||||
rfbSetDesktopSizeMsg message or for extended screen
|
||||
support. Resizing of remote displays will be disabled.
|
||||
--------------------------------------------------------])
|
||||
else
|
||||
AC_DEFINE([LIBVNC_HAS_SIZE_MSG],,
|
||||
AC_DEFINE([LIBVNC_HAS_RESIZE_SUPPORT],,
|
||||
[Whether VNC client will support sending desktop size messages.])
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
#
|
||||
# libVNCserver support for the screen structure, which allows for tracking
|
||||
# multiple screens that are part of a larger frame buffer display. If this
|
||||
# feature is missing, the VNC client may still attempt to send the display
|
||||
# resize messages, but will assume that there is a one-to-one relationship
|
||||
# between the screen size and the frame buffer size (which is currently safe
|
||||
# for Guacamole, as it lacks multi-monitor/screen support).
|
||||
#
|
||||
|
||||
if test "x${have_libvncserver}" = "xyes"
|
||||
then
|
||||
|
||||
have_vnc_screen=yes
|
||||
AC_CHECK_MEMBERS([rfbClient.screen],
|
||||
[], [have_vnc_screen=no],
|
||||
[[#include <rfb/rfbclient.h>]])
|
||||
|
||||
if test "x${have_vnc_screen}" = "xyes"
|
||||
then
|
||||
AC_DEFINE([LIBVNC_CLIENT_HAS_SCREEN],,
|
||||
[Whether rfbClient contains the screen data structure.])
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
#
|
||||
# libVNCserver support for the requestedResize member, which enables the
|
||||
# client to pause frame buffer updates during a resize operation. If support
|
||||
|
||||
@ -146,7 +146,7 @@ void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, in
|
||||
|
||||
}
|
||||
|
||||
#ifdef LIBVNC_HAS_SIZE_MSG
|
||||
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
|
||||
/**
|
||||
* This function does the actual work of sending the message to the RFB/VNC
|
||||
* server to request the resize, and then makes sure that the client frame
|
||||
@ -173,7 +173,11 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
|
||||
/* Get the Guacamole client data */
|
||||
guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY);
|
||||
|
||||
#ifdef LIBVNC_CLIENT_HAS_SCREEN
|
||||
if (client->screen.width == 0 || client->screen.height == 0) {
|
||||
guac_client_log(gc, GUAC_LOG_WARNING, "Screen data has not been initialized, yet.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
guac_client_log(gc, GUAC_LOG_TRACE,
|
||||
"Current screen size is %ix%i; setting new size %ix%i\n",
|
||||
rfbClientSwap16IfLE(client->screen.width),
|
||||
@ -185,19 +189,6 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
|
||||
guac_client_log(gc, GUAC_LOG_WARNING, "Screen size has not changed, not sending update.");
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
/* Don't send an update if the screen appears to be uninitialized. */
|
||||
if (client->width == 0 || client->height == 0) {
|
||||
guac_client_log(gc, GUAC_LOG_WARNING, "Framebuffer has not been initialized, cannot send resize.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Don't send an update if the requested dimensions are identical to current dimensions. */
|
||||
if (client->width == rfbClientSwap16IfLE(width) && client->height == rfbClientSwap16IfLE(height)) {
|
||||
guac_client_log(gc, GUAC_LOG_WARNING, "Screen size has not changed, not sending update.");
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Note: The RFB protocol requires two message types to be sent during a
|
||||
@ -219,19 +210,11 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
|
||||
size_msg.height = rfbClientSwap16IfLE(height);
|
||||
size_msg.numberOfScreens = 1;
|
||||
|
||||
#ifdef LIBVNC_CLIENT_HAS_SCREEN
|
||||
/* Configure the screen update message. */
|
||||
new_screen.id = GUAC_VNC_SCREEN_ID;
|
||||
new_screen.x = client->screen.x;
|
||||
new_screen.y = client->screen.y;
|
||||
new_screen.flags = client->screen.flags;
|
||||
#else
|
||||
/* Assume screen starts at the origin. */
|
||||
new_screen.id = GUAC_VNC_SCREEN_ID;
|
||||
new_screen.x = 0;
|
||||
new_screen.y = 0;
|
||||
new_screen.flags = 0;
|
||||
#endif // LIBVNC_CLIENT_HAS_SCREEN
|
||||
|
||||
new_screen.width = rfbClientSwap16IfLE(width);
|
||||
new_screen.height = rfbClientSwap16IfLE(height);
|
||||
@ -246,11 +229,9 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
|
||||
|
||||
}
|
||||
|
||||
#ifdef LIBVNC_CLIENT_HAS_SCREEN
|
||||
/* Update the client frame buffer with the requested size. */
|
||||
client->screen.width = rfbClientSwap16IfLE(width);
|
||||
client->screen.height = rfbClientSwap16IfLE(height);
|
||||
#endif // LIBVNC_CLIENT_HAS_SCREEN
|
||||
|
||||
#ifdef LIBVNC_CLIENT_HAS_REQUESTED_RESIZE
|
||||
client->requestedResize = FALSE;
|
||||
@ -266,6 +247,7 @@ static rfbBool guac_vnc_send_desktop_size(rfbClient* client, int width, int heig
|
||||
|
||||
/* Update should be successful. */
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
void* guac_vnc_display_set_owner_size(guac_user* owner, void* data) {
|
||||
@ -323,7 +305,7 @@ void guac_vnc_display_set_size(rfbClient* client, int requested_width, int reque
|
||||
pthread_mutex_unlock(&(vnc_client->message_lock));
|
||||
|
||||
}
|
||||
#endif // LIBVNC_HAS_SIZE_MSG
|
||||
#endif // LIBVNC_HAS_RESIZE_SUPPORT
|
||||
|
||||
void guac_vnc_set_pixel_format(rfbClient* client, int color_depth) {
|
||||
client->format.trueColour = 1;
|
||||
|
||||
@ -64,7 +64,7 @@ int guac_vnc_user_key_handler(guac_user* user, int keysym, int pressed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef LIBVNC_HAS_SIZE_MSG
|
||||
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
|
||||
int guac_vnc_user_size_handler(guac_user* user, int width, int height) {
|
||||
|
||||
guac_user_log(user, GUAC_LOG_TRACE, "Running user size handler.");
|
||||
@ -78,4 +78,4 @@ int guac_vnc_user_size_handler(guac_user* user, int width, int height) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif //LIBVNC_HAS_SIZE_MSG
|
||||
#endif // LIBVNC_HAS_RESIZE_SUPPORT
|
||||
|
||||
@ -89,11 +89,14 @@ int guac_vnc_user_join_handler(guac_user* user, int argc, char** argv) {
|
||||
user->file_handler = guac_vnc_sftp_file_handler;
|
||||
#endif
|
||||
|
||||
#ifdef LIBVNC_HAS_SIZE_MSG
|
||||
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
|
||||
/* If user is owner, set size handler. */
|
||||
if (user->owner && !settings->disable_display_resize)
|
||||
user->size_handler = guac_vnc_user_size_handler;
|
||||
#endif // LIBVNC_HAS_SIZE_MSG
|
||||
#else
|
||||
guac_user_log(user, GUAC_LOG_WARNING,
|
||||
"The libvncclient library does not support remote resize.");
|
||||
#endif // LIBVNC_HAS_RESIZE_SUPPORT
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -281,8 +281,9 @@ static int guac_vnc_wait_for_messages(rfbClient* rfb_client, int msec_timeout) {
|
||||
* True (non-zero) if messages were handled successfully, false (zero)
|
||||
* otherwise.
|
||||
*/
|
||||
static rfbBool guac_vnc_handle_messages(guac_vnc_client* vnc_client) {
|
||||
static rfbBool guac_vnc_handle_messages(guac_client* client) {
|
||||
|
||||
guac_vnc_client* vnc_client = (guac_vnc_client*) client->data;
|
||||
rfbClient* rfb_client = vnc_client->rfb_client;
|
||||
guac_display_layer* default_layer = guac_display_default_layer(vnc_client->display);
|
||||
|
||||
@ -311,6 +312,31 @@ static rfbBool guac_vnc_handle_messages(guac_vnc_client* vnc_client) {
|
||||
guac_display_layer_close_raw(default_layer, context);
|
||||
vnc_client->current_context = NULL;
|
||||
|
||||
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
|
||||
// If screen was not previously initialized, check for it and set it.
|
||||
if (!vnc_client->rfb_screen_initialized
|
||||
&& rfb_client->screen.width > 0
|
||||
&& rfb_client->screen.height > 0) {
|
||||
vnc_client->rfb_screen_initialized = true;
|
||||
guac_client_log(client, GUAC_LOG_DEBUG, "Screen is now initialized.");
|
||||
}
|
||||
|
||||
/*
|
||||
* If the screen is now or has been initialized, check to see if the initial
|
||||
* dimensions have already been sent. If not, and resize is not disabled,
|
||||
* send the initial size.
|
||||
*/
|
||||
if (vnc_client->rfb_screen_initialized) {
|
||||
guac_vnc_settings* settings = vnc_client->settings;
|
||||
if (!vnc_client->rfb_initial_resize && !settings->disable_display_resize) {
|
||||
guac_client_log(client, GUAC_LOG_DEBUG,
|
||||
"Sending initial screen size to VNC server.");
|
||||
guac_client_for_owner(client, guac_vnc_display_set_owner_size, rfb_client);
|
||||
vnc_client->rfb_initial_resize = true;
|
||||
}
|
||||
}
|
||||
#endif // LIBVNC_HAS_RESIZE_SUPPORT
|
||||
|
||||
/* Resize the surface if VNC screen size has changed (this call
|
||||
* automatically deals with invalid dimensions and is a no-op
|
||||
* if the size has not changed) */
|
||||
@ -588,11 +614,11 @@ void* guac_vnc_client_thread(void* data) {
|
||||
guac_display_set_cursor(vnc_client->display, GUAC_DISPLAY_CURSOR_POINTER);
|
||||
}
|
||||
|
||||
#ifdef LIBVNC_HAS_SIZE_MSG
|
||||
/* Update the display with the owner's screen size. */
|
||||
if (!settings->disable_display_resize)
|
||||
guac_client_for_owner(client, guac_vnc_display_set_owner_size, rfb_client);
|
||||
#endif // LIBVNC_HAS_SIZE_MSG
|
||||
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
|
||||
/* Set initial state of the screen and resize flags. */
|
||||
vnc_client->rfb_screen_initialized = false;
|
||||
vnc_client->rfb_initial_resize = false;
|
||||
#endif // LIBVNC_HAS_RESIZE_SUPPORT
|
||||
|
||||
guac_display_end_frame(vnc_client->display);
|
||||
|
||||
@ -606,7 +632,7 @@ void* guac_vnc_client_thread(void* data) {
|
||||
if (wait_result > 0) {
|
||||
|
||||
/* Handle any message received */
|
||||
if (!guac_vnc_handle_messages(vnc_client)) {
|
||||
if (!guac_vnc_handle_messages(client)) {
|
||||
guac_client_abort(client,
|
||||
GUAC_PROTOCOL_STATUS_UPSTREAM_ERROR,
|
||||
"Error handling message from VNC server.");
|
||||
|
||||
@ -164,6 +164,19 @@ typedef struct guac_vnc_client {
|
||||
*/
|
||||
guac_iconv_write* clipboard_writer;
|
||||
|
||||
#ifdef LIBVNC_HAS_RESIZE_SUPPORT
|
||||
/**
|
||||
* Whether or not the server has sent the required message to initialize
|
||||
* the screen data in the client.
|
||||
*/
|
||||
bool rfb_screen_initialized;
|
||||
|
||||
/**
|
||||
* Whether or not the client has sent it's starting size to the server.
|
||||
*/
|
||||
bool rfb_initial_resize;
|
||||
#endif
|
||||
|
||||
} guac_vnc_client;
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user