GUACAMOLE-1196: Add VNC protocol support for updating display size.
This commit is contained in:
parent
1f52c48a04
commit
ddc2e22a4f
@ -106,11 +106,16 @@ int guac_client_init(guac_client* client) {
|
||||
guac_vnc_client* vnc_client = guac_mem_zalloc(sizeof(guac_vnc_client));
|
||||
client->data = vnc_client;
|
||||
|
||||
vnc_client->vnc_display = guac_vnc_display_update_alloc(client);
|
||||
|
||||
#ifdef ENABLE_VNC_TLS_LOCKING
|
||||
/* Initialize the TLS write lock */
|
||||
pthread_mutex_init(&vnc_client->tls_lock, NULL);
|
||||
#endif
|
||||
|
||||
/* Initialize the message lock. */
|
||||
pthread_mutex_init(&(vnc_client->message_lock), NULL);
|
||||
|
||||
/* Init clipboard */
|
||||
vnc_client->clipboard = guac_common_clipboard_alloc();
|
||||
|
||||
@ -209,6 +214,11 @@ int guac_vnc_client_free_handler(guac_client* client) {
|
||||
pthread_mutex_destroy(&(vnc_client->tls_lock));
|
||||
#endif
|
||||
|
||||
/* Clean up the message lock. */
|
||||
pthread_mutex_destroy(&(vnc_client->message_lock));
|
||||
|
||||
guac_vnc_display_update_free(vnc_client->vnc_display);
|
||||
|
||||
/* Free generic data struct */
|
||||
guac_mem_free(client->data);
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "client.h"
|
||||
#include "display.h"
|
||||
#include "common/iconv.h"
|
||||
#include "common/surface.h"
|
||||
#include "vnc.h"
|
||||
@ -30,6 +31,7 @@
|
||||
#include <guacamole/mem.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
#include <guacamole/timestamp.h>
|
||||
#include <rfb/rfbclient.h>
|
||||
#include <rfb/rfbproto.h>
|
||||
|
||||
@ -153,6 +155,88 @@ void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h, in
|
||||
|
||||
}
|
||||
|
||||
guac_vnc_display* guac_vnc_display_update_alloc(guac_client* client) {
|
||||
|
||||
guac_vnc_display* display = guac_mem_alloc(sizeof(guac_vnc_display));
|
||||
display->client = client;
|
||||
|
||||
/* No requests have been made */
|
||||
display->last_request = guac_timestamp_current();
|
||||
display->requested_width = 0;
|
||||
display->requested_height = 0;
|
||||
|
||||
return display;
|
||||
|
||||
}
|
||||
|
||||
void guac_vnc_display_update_free(guac_vnc_display* display) {
|
||||
guac_mem_free(display);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function does the actual work of updating the display size if adequate
|
||||
* time has passed since the last update and the size is actually different.
|
||||
*
|
||||
* @param display
|
||||
* The data structure that contains information used for determing if and
|
||||
* when display updates should be allowed.
|
||||
*
|
||||
* @param rfb_client
|
||||
* A pointer to the VNC (RFB) client.
|
||||
*/
|
||||
static void guac_vnc_display_update_size(guac_vnc_display* display,
|
||||
rfbClient* rfb_client) {
|
||||
|
||||
int width = display->requested_width;
|
||||
int height = display->requested_height;
|
||||
|
||||
/* Do not update size if no requests have been received */
|
||||
if (width == 0 || height == 0)
|
||||
return;
|
||||
|
||||
guac_timestamp now = guac_timestamp_current();
|
||||
|
||||
/* Limit display update frequency */
|
||||
if (now - display->last_request <= GUAC_COMMON_DISPLAY_UPDATE_INTERVAL)
|
||||
return;
|
||||
|
||||
/* Do NOT send requests unless the size will change */
|
||||
if (rfb_client != NULL
|
||||
&& width == rfb_client->screen.width
|
||||
&& height == rfb_client->screen.height)
|
||||
return;
|
||||
|
||||
/* Send the display size update. */
|
||||
guac_vnc_client* vnc_client = (guac_vnc_client*) display->client->data;
|
||||
pthread_mutex_lock(&(vnc_client->message_lock));
|
||||
SendExtDesktopSize(rfb_client, width, height);
|
||||
display->last_request = now;
|
||||
pthread_mutex_unlock(&(vnc_client->message_lock));
|
||||
|
||||
}
|
||||
|
||||
void guac_vnc_display_set_size(guac_vnc_display* display,
|
||||
rfbClient* rfb_client, int width, int height) {
|
||||
|
||||
/* Fit width within bounds, adjusting height to maintain aspect ratio */
|
||||
guac_common_display_fit(&width, &height);
|
||||
|
||||
/* Fit height within bounds, adjusting width to maintain aspect ratio */
|
||||
guac_common_display_fit(&height, &width);
|
||||
|
||||
/* Width must be even */
|
||||
if (width % 2 == 1)
|
||||
width -= 1;
|
||||
|
||||
/* Store deferred size */
|
||||
display->requested_width = width;
|
||||
display->requested_height = height;
|
||||
|
||||
/* Send display update notification if possible */
|
||||
guac_vnc_display_update_size(display, rfb_client);
|
||||
|
||||
}
|
||||
|
||||
void guac_vnc_set_pixel_format(rfbClient* client, int color_depth) {
|
||||
client->format.trueColour = 1;
|
||||
switch(color_depth) {
|
||||
@ -205,4 +289,3 @@ rfbBool guac_vnc_malloc_framebuffer(rfbClient* rfb_client) {
|
||||
/* Use original, wrapped proc */
|
||||
return vnc_client->rfb_MallocFrameBuffer(rfb_client);
|
||||
}
|
||||
|
||||
|
||||
@ -26,8 +26,36 @@
|
||||
#include <rfb/rfbproto.h>
|
||||
|
||||
/**
|
||||
* Callback invoked by libVNCServer when it receives a new binary image data.
|
||||
* the VNC server. The image itself will be stored in the designated sub-
|
||||
* Display size update module for VNC.
|
||||
*/
|
||||
typedef struct guac_vnc_display {
|
||||
|
||||
/**
|
||||
* The guac_client instance handling the relevant VNC connection.
|
||||
*/
|
||||
guac_client* client;
|
||||
|
||||
/**
|
||||
* The timestamp of the last display update request, or 0 if no request
|
||||
* has been sent yet.
|
||||
*/
|
||||
guac_timestamp last_request;
|
||||
|
||||
/**
|
||||
* The last requested screen width, in pixels.
|
||||
*/
|
||||
int requested_width;
|
||||
|
||||
/**
|
||||
* The last requested screen height, in pixels.
|
||||
*/
|
||||
int requested_height;
|
||||
|
||||
} guac_vnc_display;
|
||||
|
||||
/**
|
||||
* Callback invoked by libVNCServer when it receives a new binary image data
|
||||
* from the VNC server. The image itself will be stored in the designated sub-
|
||||
* rectangle of client->framebuffer.
|
||||
*
|
||||
* @param client
|
||||
@ -84,6 +112,52 @@ void guac_vnc_update(rfbClient* client, int x, int y, int w, int h);
|
||||
void guac_vnc_copyrect(rfbClient* client, int src_x, int src_y, int w, int h,
|
||||
int dest_x, int dest_y);
|
||||
|
||||
/**
|
||||
* Allocates a new VNC display update module, which will keep track of the data
|
||||
* needed to handle display updates.
|
||||
*
|
||||
* @param client
|
||||
* The guac_client instance handling the relevant VNC connection.
|
||||
*
|
||||
* @return
|
||||
* A newly-allocated VNC display update module.
|
||||
*/
|
||||
guac_vnc_display* guac_vnc_display_update_alloc(guac_client* client);
|
||||
|
||||
/**
|
||||
* Frees the resources associated with the data structure that keeps track of
|
||||
* items related to VNC display updates. Only resources specific to Guacamole
|
||||
* are freed. Resources that are part of the rfbClient will be freed separately.
|
||||
* If no resources are currently allocated for Display Update support, this
|
||||
* function has no effect.
|
||||
*
|
||||
* @param display
|
||||
* The display update module to free.
|
||||
*/
|
||||
void guac_vnc_display_update_free(guac_vnc_display* display);
|
||||
|
||||
/**
|
||||
* Attempts to set the display size of the remote server to the size requested
|
||||
* by the client, usually as part of a client (browser) resize, if supported by
|
||||
* both the VNC client and the remote server.
|
||||
*
|
||||
* @param display
|
||||
* The VNC display update object that tracks information related to display
|
||||
* update requests.
|
||||
*
|
||||
* @param rfb_client
|
||||
* The data structure containing the VNC client that is used by this
|
||||
* connection.
|
||||
*
|
||||
* @param width
|
||||
* The width that is being requested, in pixels.
|
||||
*
|
||||
* @param height
|
||||
* The height that is being requested, in pixels.
|
||||
*/
|
||||
void guac_vnc_display_set_size(guac_vnc_display* display, rfbClient* rfb_client,
|
||||
int width, int height);
|
||||
|
||||
/**
|
||||
* Sets the pixel format to request of the VNC server. The request will be made
|
||||
* during the connection handshake with the VNC server using the values
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
|
||||
#include "common/cursor.h"
|
||||
#include "common/display.h"
|
||||
#include "display.h"
|
||||
#include "vnc.h"
|
||||
|
||||
#include <guacamole/recording.h>
|
||||
@ -64,3 +65,14 @@ int guac_vnc_user_key_handler(guac_user* user, int keysym, int pressed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int guac_vnc_user_size_handler(guac_user* user, int width, int height) {
|
||||
|
||||
guac_vnc_client* vnc_client = (guac_vnc_client*) user->client->data;
|
||||
rfbClient* rfb_client = vnc_client->rfb_client;
|
||||
|
||||
/* Send display update */
|
||||
guac_vnc_display_set_size(vnc_client->vnc_display, rfb_client, width, height);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@ -34,5 +34,9 @@ guac_user_mouse_handler guac_vnc_user_mouse_handler;
|
||||
*/
|
||||
guac_user_key_handler guac_vnc_user_key_handler;
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Handler for Guacamole user resize events.
|
||||
*/
|
||||
guac_user_size_handler guac_vnc_user_size_handler;
|
||||
|
||||
#endif // GUAC_VNC_INPUT_H
|
||||
|
||||
@ -91,6 +91,9 @@ int guac_vnc_user_join_handler(guac_user* user, int argc, char** argv) {
|
||||
user->file_handler = guac_vnc_sftp_file_handler;
|
||||
#endif
|
||||
|
||||
/* Handle display size changes. */
|
||||
user->size_handler = guac_vnc_user_size_handler;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
#include "common/display.h"
|
||||
#include "common/iconv.h"
|
||||
#include "common/surface.h"
|
||||
#include "display.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <guacamole/client.h>
|
||||
@ -63,6 +64,11 @@ typedef struct guac_vnc_client {
|
||||
pthread_mutex_t tls_lock;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Lock which synchronizes messages sent to VNC server.
|
||||
*/
|
||||
pthread_mutex_t message_lock;
|
||||
|
||||
/**
|
||||
* The underlying VNC client.
|
||||
*/
|
||||
@ -135,6 +141,11 @@ typedef struct guac_vnc_client {
|
||||
*/
|
||||
guac_iconv_write* clipboard_writer;
|
||||
|
||||
/**
|
||||
* VNC display update module.
|
||||
*/
|
||||
guac_vnc_display* vnc_display;
|
||||
|
||||
} guac_vnc_client;
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user