Skip to content

Commit

Permalink
Merge changes from patch branch back to main.
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-jumper committed Dec 22, 2024
2 parents 8e75eea + de07288 commit 15d5a27
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 76 deletions.
51 changes: 16 additions & 35 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -657,59 +657,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
Expand Down
34 changes: 8 additions & 26 deletions src/protocols/vnc/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/protocols/vnc/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.");
Expand All @@ -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
7 changes: 5 additions & 2 deletions src/protocols/vnc/user.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

}

Expand Down
40 changes: 33 additions & 7 deletions src/protocols/vnc/vnc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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) */
Expand Down Expand Up @@ -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);

Expand All @@ -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.");
Expand Down
13 changes: 13 additions & 0 deletions src/protocols/vnc/vnc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/**
Expand Down
5 changes: 5 additions & 0 deletions src/terminal/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,11 @@ void guac_terminal_display_set_columns(guac_terminal_display* display, int row,
/* For each column in range */
for (int col = start_column; col <= end_column; col += character->width) {

/* Flush pending copy operation before adding new SET operation. This
* avoid operation conflicts that cause inconsistent display. */
if (current->type == GUAC_CHAR_COPY)
guac_terminal_display_flush(display);

/* Set operation */
current->type = GUAC_CHAR_SET;
current->character = *character;
Expand Down
4 changes: 0 additions & 4 deletions src/terminal/terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -875,10 +875,6 @@ void guac_terminal_scroll_down(guac_terminal* term,
start_row, 0,
start_row + amount - 1, term->term_width - 1);

/* Flush display copy before the cursor commit override operation
* type for visible cursor row and breaks display. */
guac_terminal_display_flush(term->display);

}

int guac_terminal_clear_columns(guac_terminal* term,
Expand Down

0 comments on commit 15d5a27

Please sign in to comment.