Merge 1.6.0 changes back to patch.

This commit is contained in:
Virtually Nick 2024-09-10 08:23:45 -04:00
commit 9c841a6d94
3 changed files with 124 additions and 30 deletions

View File

@ -1141,6 +1141,30 @@ then
[AC_MSG_RESULT([no])])
fi
if test "x${have_freerdp}" = "xyes"
then
AC_MSG_CHECKING([whether freerdp instance supports LoadChannels])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
#include <freerdp/freerdp.h>
/* Mock LoadChannels function with the expected signature */
BOOL load_channels(freerdp* instance) {
return TRUE;
}
int main() {
freerdp* instance = freerdp_new();
instance->LoadChannels = load_channels;
freerdp_free(instance);
return 0;
}
]])],
[AC_MSG_RESULT([yes])]
[AC_DEFINE([RDP_INST_HAS_LOAD_CHANNELS],,
[Defined if freerdp instance supports LoadChannels])],
[AC_MSG_RESULT([no])])
fi
# Restore CPPFLAGS, removing FreeRDP-specific options needed for testing
CPPFLAGS="$OLDCPPFLAGS"

View File

@ -79,21 +79,29 @@
#include <stdlib.h>
#include <time.h>
BOOL rdp_freerdp_pre_connect(freerdp* instance) {
/**
* Initializes and loads the necessary FreeRDP plugins based on the current
* RDP session settings. This function is designed to work in environments
* where the FreeRDP instance expects a LoadChannels callback to be set
* otherwise it can becalled directly from our pre_connect callback. It
* configures various features such as display resizing, multi-touch support,
* audio input, clipboard synchronization, device redirection, and graphics
* pipeline, by loading their corresponding plugins if they are enabled in the
* session settings.
*
* @param instance
* The FreeRDP instance to be prepared, containing all context and
* settings for the session.
*
* @return
* Always TRUE.
*/
static BOOL rdp_freerdp_load_channels(freerdp* instance) {
rdpContext* context = GUAC_RDP_CONTEXT(instance);
rdpGraphics* graphics = context->graphics;
guac_client* client = ((rdp_freerdp_context*) context)->client;
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
guac_rdp_settings* settings = rdp_client->settings;
/* Push desired settings to FreeRDP */
guac_rdp_push_settings(client, settings, instance);
/* Init FreeRDP add-in provider */
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
/* Load "disp" plugin for display update */
if (settings->resize_method == GUAC_RESIZE_DISPLAY_UPDATE)
guac_rdp_disp_load_plugin(context);
@ -125,6 +133,53 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
guac_rdpsnd_load_plugin(context);
}
/* Load "rdpgfx" plugin for Graphics Pipeline Extension */
if (settings->enable_gfx)
guac_rdp_rdpgfx_load_plugin(context);
/* Load plugin providing Dynamic Virtual Channel support, if required */
if (freerdp_settings_get_bool(GUAC_RDP_CONTEXT(instance)->settings, FreeRDP_SupportDynamicChannels) &&
guac_freerdp_channels_load_plugin(context, "drdynvc",
GUAC_RDP_CONTEXT(instance)->settings)) {
guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load drdynvc plugin. Display update and audio "
"input support will be disabled.");
}
return TRUE;
}
/**
* Prepares the FreeRDP instance for connection by setting up session-specific
* configurations like graphics, plugins, and RDP settings. This involves
* integrating Guacamole's custom rendering handlers (for bitmaps, glyphs,
* and pointers). If using a freerdp instance that does not expect a
* LoadChannels callback then this function manually loads RDP channels.
*
* @param instance
* The FreeRDP instance to be prepared, containing all context and
* settings for the session.
*
* @return
* Returns TRUE if the pre-connection process completes successfully.
* Returns FALSE if an error occurs during the initialization of the
* FreeRDP GDI system.
*/
static BOOL rdp_freerdp_pre_connect(freerdp* instance) {
rdpContext* context = GUAC_RDP_CONTEXT(instance);
rdpGraphics* graphics = context->graphics;
guac_client* client = ((rdp_freerdp_context*) context)->client;
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
guac_rdp_settings* settings = rdp_client->settings;
/* Push desired settings to FreeRDP */
guac_rdp_push_settings(client, settings, instance);
/* Init FreeRDP add-in provider */
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
/* Load RAIL plugin if RemoteApp in use */
if (settings->remote_app != NULL)
guac_rdp_rail_load_plugin(context);
@ -194,21 +249,15 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
primary->MemBlt = guac_rdp_gdi_memblt;
primary->OpaqueRect = guac_rdp_gdi_opaquerect;
/* Load "rdpgfx" plugin for Graphics Pipeline Extension */
if (settings->enable_gfx)
guac_rdp_rdpgfx_load_plugin(context);
/* Load plugin providing Dynamic Virtual Channel support, if required */
if (freerdp_settings_get_bool(GUAC_RDP_CONTEXT(instance)->settings, FreeRDP_SupportDynamicChannels) &&
guac_freerdp_channels_load_plugin(context, "drdynvc",
GUAC_RDP_CONTEXT(instance)->settings)) {
guac_client_log(client, GUAC_LOG_WARNING,
"Failed to load drdynvc plugin. Display update and audio "
"input support will be disabled.");
}
/*
* If the freerdp instance does not have a LoadChannels callback for
* loading plugins we use the PreConnect callback to load plugins instead.
*/
#ifndef RDP_INST_HAS_LOAD_CHANNELS
rdp_freerdp_load_channels(instance);
#endif
return TRUE;
}
/**
@ -489,6 +538,14 @@ static int guac_rdp_handle_connection(guac_client* client) {
/* Init client */
freerdp* rdp_inst = freerdp_new();
/*
* If the freerdp instance has a LoadChannels callback for loading plugins
* we use that instead of the PreConnect callback to load plugins.
*/
#ifdef RDP_INST_HAS_LOAD_CHANNELS
rdp_inst->LoadChannels = rdp_freerdp_load_channels;
#endif
rdp_inst->PreConnect = rdp_freerdp_pre_connect;
rdp_inst->Authenticate = rdp_freerdp_authenticate;

View File

@ -51,6 +51,25 @@ void guac_vnc_update(rfbClient* client, int x, int y, int w, int h) {
guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY);
guac_vnc_client* vnc_client = (guac_vnc_client*) gc->data;
#ifdef LIBVNC_CLIENT_HAS_SCREEN
int new_height = rfbClientSwap16IfLE(client->screen.height);
int new_width = rfbClientSwap16IfLE(client->screen.width);
#else
int new_height = rfbClientSwap16IfLE(client->height);
int new_width = rfbClientSwap16IfLE(client->width);
#endif
/* Resize the surface if VNC screen size has changed */
int old_height = vnc_client->display->default_surface->height;
int old_width = vnc_client->display->default_surface->width;
if (
new_height > 0 && new_width > 0
&& (new_height != old_height || new_width != old_width)
) {
guac_common_surface_resize(vnc_client->display->default_surface,
new_width, new_height);
}
int dx, dy;
/* Cairo image buffer */
@ -309,15 +328,9 @@ void guac_vnc_display_set_size(rfbClient* client, int width, int height) {
/* Send the display size update. */
guac_client_log(gc, GUAC_LOG_TRACE, "Setting VNC display size.");
if (guac_vnc_send_desktop_size(client, width, height)) {
if (guac_vnc_send_desktop_size(client, width, height))
guac_client_log(gc, GUAC_LOG_TRACE, "Successfully sent desktop size message.");
/* Resize the surface now that the VNC size update has completed */
if (vnc_client->display != NULL)
guac_common_surface_resize(vnc_client->display->default_surface,
width, height);
}
else
guac_client_log(gc, GUAC_LOG_TRACE, "Failed to send desktop size message.");