diff --git a/gnome-connections-41.2-rdp-graphics-pipeline.patch b/gnome-connections-41.2-rdp-graphics-pipeline.patch new file mode 100644 index 0000000..7aade1e --- /dev/null +++ b/gnome-connections-41.2-rdp-graphics-pipeline.patch @@ -0,0 +1,779 @@ +--- gnome-connections-41.2/src/display-view.vala ++++ gnome-connections-41.2/src/display-view.vala +@@ -104,23 +104,8 @@ namespace Connections { + if (event.type == EventType.GRAB_BROKEN) + return false; + +- if (event_box.get_child () != null) { +- var child = event_box.get_child (); +- var offset_x = (get_allocated_width () - child.get_allocated_width ()) / 2.0; +- var offset_y = (get_allocated_height () - child.get_allocated_height ()) / 2.0; +- +- switch (event.get_event_type ()) { +- case Gdk.EventType.MOTION_NOTIFY: +- event.motion.x -= offset_x; +- event.motion.y -= offset_y; +- break; +- +- default: +- break; +- } +- +- child.event (event); +- } ++ if (event_box.get_child () != null) ++ event_box.get_child ().event (event); + + return false; + } +--- gnome-connections-41.2/src/rdp-connection.vala ++++ gnome-connections-41.2/src/rdp-connection.vala +@@ -66,10 +66,10 @@ namespace Connections { + display.bind_property ("username", this, "username", BindingFlags.BIDIRECTIONAL); + display.bind_property ("password", this, "password", BindingFlags.BIDIRECTIONAL); + +- display.rdp_connected.connect (() => { show (); }); ++ display.rdp_connected.connect (on_rdp_connection_connected_cb); + //display.rdp_needs_authentication.connect (on_rdp_auth_credential_cb); + display.rdp_auth_failure.connect (auth_failed); +- //display.size_allocate.connect (scale); ++ display.size_allocate.connect (scale); + + need_username = need_password = true; + } +@@ -101,6 +101,10 @@ namespace Connections { + + return; + } ++ else { ++ display.username = username; ++ display.password = password; ++ } + + display.open_host (host, port); + connected = true; +@@ -123,6 +127,23 @@ namespace Connections { + + handle_auth (); + } ++ ++ private void on_rdp_connection_connected_cb () { ++ connected = true; ++ scaling = true; ++ ++ display.grab_focus (); ++ scale (); ++ show (); ++ } ++ ++ public void scale () { ++ if (!display.is_open ()) ++ return; ++ ++ display.scaling = display.hexpand = true; ++ display.width_request = display.height_request = 0; ++ } + } + + private class FrdpDisplay : Frdp.Display { +--- gnome-connections-41.2/subprojects/gtk-frdp/src/frdp-session.c ++++ gnome-connections-41.2/subprojects/gtk-frdp/src/frdp-session.c +@@ -19,6 +19,10 @@ + #include + #include + #include ++#include ++#include ++#include ++#include + #include + #include + #include +@@ -26,7 +30,7 @@ + + #include "frdp-session.h" + +-#define SELECT_TIMEOUT 50 ++#define SELECT_TIMEOUT 10 + #define FRDP_CONNECTION_THREAD_MAX_ERRORS 10 + + struct frdp_pointer +@@ -41,6 +45,7 @@ struct _FrdpSessionPrivate + freerdp *freerdp_session; + + GtkWidget *display; ++ cairo_format_t cairo_format; + cairo_surface_t *surface; + gboolean scaling; + double scale; +@@ -59,6 +64,8 @@ struct _FrdpSessionPrivate + gboolean show_cursor; + gboolean cursor_null; + frdpPointer *cursor; ++ GQueue *area_draw_queue; /* elem: GdkRectangle */ ++ GMutex area_draw_mutex; + }; + + G_DEFINE_TYPE_WITH_PRIVATE (FrdpSession, frdp_session, G_TYPE_OBJECT) +@@ -91,6 +98,16 @@ struct frdp_context + }; + typedef struct frdp_context frdpContext; + ++static void queue_draw_area (FrdpSession *self, ++ gint x, ++ gint y, ++ gint width, ++ gint height); ++ ++static void frdp_session_configure_event (GtkWidget *widget, ++ GdkEvent *event, ++ gpointer user_data); ++ + static void + frdp_session_update_mouse_pointer (FrdpSession *self) + { +@@ -153,143 +170,58 @@ frdp_session_update_mouse_pointer (FrdpS + gdk_window_set_cursor (window, cursor); + } + +-static BOOL +-frdp_Pointer_New(rdpContext* context, rdpPointer* pointer) ++static guint32 ++frdp_session_get_best_color_depth (FrdpSession *self) + { +- frdpContext *fcontext = (frdpContext*) context; +- frdpPointer *fpointer = (frdpPointer*) pointer; +- int stride; +- unsigned char *data; +- cairo_surface_t *surface; +- +- if (!fcontext || !fpointer) +- return FALSE; +- +- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, pointer->width, +- pointer->height); +- if (!surface) { +- return FALSE; +- } +- +- { /* FreeRDP BUG https://github.com/FreeRDP/FreeRDP/issues/5061 +- * the function freerdp_image_copy_from_pointer_data +- * does not initialize the buffer which results in broken alpha data. */ +- cairo_t* cairo = cairo_create (surface); +- +- cairo_set_source_rgba (cairo, 0.0, 0.0, 0.0, 1.0); +- cairo_fill (cairo); +- cairo_paint (cairo); +- cairo_destroy (cairo); +- } ++ GdkScreen *display; ++ GdkVisual *visual; + +- data = cairo_image_surface_get_data (surface); +- if (!data) { +- goto fail; +- } +- +- stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, pointer->width); +- if (!freerdp_image_copy_from_pointer_data (data, PIXEL_FORMAT_BGRA32, +- stride, 0, 0, pointer->width, +- pointer->height, +- pointer->xorMaskData, +- pointer->lengthXorMask, +- pointer->andMaskData, +- pointer->lengthAndMask, +- pointer->xorBpp, +- &context->gdi->palette)) +- goto fail; ++ display = gdk_screen_get_default (); ++ visual = gdk_screen_get_rgba_visual (display); + +- fpointer->data = surface; +- return TRUE; +-fail: +- if (surface) +- cairo_surface_destroy (surface); +- return FALSE; ++ return gdk_visual_get_depth (visual); + } + + static void +-frdp_Pointer_Free (rdpContext* context, rdpPointer* pointer) ++create_cairo_surface (FrdpSession *self) + { +- frdpPointer *fpointer = (frdpPointer*) pointer; ++ FrdpSessionPrivate *priv = self->priv; ++ rdpGdi *gdi; ++ gint stride; + +- if (fpointer && fpointer->data) { +- cairo_surface_destroy (fpointer->data); +- fpointer->data = NULL; ++ if (priv->surface != NULL) { ++ cairo_surface_mark_dirty (priv->surface); ++ cairo_surface_destroy (priv->surface); ++ self->priv->surface = NULL; + } +-} +- +-static BOOL +-frdp_Pointer_Set (rdpContext* context, +- const rdpPointer* pointer) +-{ +- frdpContext *fcontext = (frdpContext*) context; +- frdpPointer *fpointer = (frdpPointer*) pointer; +- FrdpSessionPrivate *priv = fcontext->self->priv; +- +- priv->cursor = fpointer; +- priv->cursor_null = FALSE; +- +- frdp_session_update_mouse_pointer (fcontext->self); +- return TRUE; +-} +- +-static BOOL +-frdp_Pointer_SetNull (rdpContext* context) +-{ +- frdpContext *fcontext = (frdpContext*) context; +- FrdpSessionPrivate *priv = fcontext->self->priv; + +- priv->cursor = NULL; +- priv->cursor_null = TRUE; ++ gdi = priv->freerdp_session->context->gdi; + +- frdp_session_update_mouse_pointer (fcontext->self); +- +- return TRUE; +-} +- +-static BOOL +-frdp_Pointer_SetDefault (rdpContext* context) +-{ +- frdpContext *fcontext = (frdpContext*) context; +- FrdpSessionPrivate *priv = fcontext->self->priv; +- +- priv->cursor = NULL; +- priv->cursor_null = FALSE; +- frdp_session_update_mouse_pointer (fcontext->self); +- return TRUE; +-} +- +-static BOOL +-frdp_Pointer_SetPosition (rdpContext* context, UINT32 x, UINT32 y) +-{ +- return TRUE; +-} +- +-static void +-frdp_register_pointer (rdpGraphics* graphics) +-{ +- rdpPointer pointer; ++ stride = cairo_format_stride_for_width (priv->cairo_format, gdi->width); ++ self->priv->surface = ++ cairo_image_surface_create_for_data ((unsigned char*) gdi->primary_buffer, ++ priv->cairo_format, ++ gdi->width, ++ gdi->height, ++ stride); ++ cairo_surface_flush (priv->surface); + +- pointer.size = sizeof(frdpPointer); +- pointer.New = frdp_Pointer_New; +- pointer.Free = frdp_Pointer_Free; +- pointer.Set = frdp_Pointer_Set; +- pointer.SetNull = frdp_Pointer_SetNull; +- pointer.SetDefault = frdp_Pointer_SetDefault; +- pointer.SetPosition = frdp_Pointer_SetPosition; +- graphics_register_pointer(graphics, &pointer); ++ frdp_session_configure_event (priv->display, NULL, self); + } + +-static guint32 +-frdp_session_get_best_color_depth (FrdpSession *self) ++static gboolean ++frdp_desktop_resize (rdpContext *context) + { +- GdkScreen *display; +- GdkVisual *visual; +- +- display = gdk_screen_get_default (); +- visual = gdk_screen_get_rgba_visual (display); ++ FrdpSession *self = ((frdpContext *) context)->self; ++ rdpGdi *gdi = context->gdi; + +- return gdk_visual_get_depth (visual); ++ if (gdi_resize (gdi, ++ context->settings->DesktopWidth, ++ context->settings->DesktopHeight)) { ++ return TRUE; ++ } else { ++ return FALSE; ++ } + } + + static void +@@ -298,22 +230,37 @@ frdp_session_configure_event (GtkWidget + gpointer user_data) + { + FrdpSession *self = (FrdpSession*) user_data; ++ FrdpSessionPrivate *priv = self->priv; ++ GtkWidget *scrolled; + rdpSettings *settings = self->priv->freerdp_session->settings; +- double width, height; ++ double width, height, widget_ratio, server_ratio; ++ rdpGdi *gdi; + +- if (self->priv->scaling) { +- width = (double)gtk_widget_get_allocated_width (widget); +- height = (double)gtk_widget_get_allocated_height (widget); ++ if (priv->freerdp_session == NULL) ++ return; ++ ++ gdi = priv->freerdp_session->context->gdi; ++ ++ if (priv->surface == NULL) ++ create_cairo_surface (self); + +- if (width < height) +- self->priv->scale = width / settings->DesktopWidth; +- else +- self->priv->scale = height / settings->DesktopHeight; ++ scrolled = gtk_widget_get_ancestor (widget, GTK_TYPE_SCROLLED_WINDOW); ++ width = (double)gtk_widget_get_allocated_width (scrolled); ++ height = (double)gtk_widget_get_allocated_height (scrolled); + +- settings->DesktopScaleFactor = self->priv->scale; ++ if (priv->scaling) { ++ widget_ratio = height > 0 ? width / height : 1.0; ++ server_ratio = settings->DesktopHeight > 0 ? (double) settings->DesktopWidth / settings->DesktopHeight : 1.0; ++ ++ if (widget_ratio > server_ratio) ++ self->priv->scale = height / settings->DesktopHeight; ++ else ++ self->priv->scale = width / settings->DesktopWidth; + +- self->priv->offset_x = (width - settings->DesktopWidth * self->priv->scale) / 2.0; +- self->priv->offset_y = (height - settings->DesktopHeight * self->priv->scale) / 2.0; ++ self->priv->offset_x = (width - settings->DesktopWidth * self->priv->scale) / 2.0; ++ self->priv->offset_y = (height - settings->DesktopHeight * self->priv->scale) / 2.0; ++ } else { ++ gtk_widget_set_size_request (priv->display, gdi->width, gdi->height); + } + + frdp_session_update_mouse_pointer (self); +@@ -335,6 +282,23 @@ frdp_session_draw (GtkWidget *widget, + { + FrdpSession *self = (FrdpSession*) user_data; + ++ if (!self->priv->is_connected) ++ return FALSE; ++ ++ if (self->priv->surface == NULL || ++ (self->priv->freerdp_session->context->gdi->width != cairo_image_surface_get_width (self->priv->surface) || ++ self->priv->freerdp_session->context->gdi->height != cairo_image_surface_get_height (self->priv->surface))) { ++ create_cairo_surface (self); ++ } ++ ++ cairo_rectangle (cr, ++ self->priv->offset_x, ++ self->priv->offset_y, ++ cairo_image_surface_get_width (self->priv->surface) * self->priv->scale, ++ cairo_image_surface_get_height (self->priv->surface) * self->priv->scale); ++ cairo_set_source_rgba (cr, 0, 0, 0, 1); ++ cairo_fill (cr); ++ + if (self->priv->scaling) { + cairo_translate (cr, self->priv->offset_x, self->priv->offset_y); + cairo_scale (cr, self->priv->scale, self->priv->scale); +@@ -385,9 +350,61 @@ frdp_authenticate (freerdp *freerdp_ses + domain); + } + ++static void ++frdp_on_channel_connected_event_handler (void *context, ++ ChannelConnectedEventArgs *e) ++{ ++ frdpContext *ctx = (frdpContext *) context; ++ ++ if (strcmp (e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { ++ gdi_graphics_pipeline_init (ctx->context.gdi, (RdpgfxClientContext *) e->pInterface); ++ } else if (strcmp (e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0) { ++ gdi_video_geometry_init (ctx->context.gdi, (GeometryClientContext *) e->pInterface); ++ } else if (strcmp (e->name, VIDEO_CONTROL_DVC_CHANNEL_NAME) == 0) { ++ gdi_video_control_init (ctx->context.gdi, (VideoClientContext *) e->pInterface); ++ } else if (strcmp (e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0) { ++ gdi_video_data_init (ctx->context.gdi, (VideoClientContext *) e->pInterface); ++ } ++} ++ ++static void ++frdp_on_channel_disconnected_event_handler (void *context, ++ ChannelDisconnectedEventArgs *e) ++{ ++ frdpContext *ctx = (frdpContext *) context; ++ ++ if (strcmp (e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { ++ gdi_graphics_pipeline_uninit (ctx->context.gdi, (RdpgfxClientContext *) e->pInterface); ++ } else if (strcmp (e->name, GEOMETRY_DVC_CHANNEL_NAME) == 0) { ++ gdi_video_geometry_uninit (ctx->context.gdi, (GeometryClientContext *) e->pInterface); ++ } else if (strcmp (e->name, VIDEO_CONTROL_DVC_CHANNEL_NAME) == 0) { ++ gdi_video_control_uninit (ctx->context.gdi, (VideoClientContext *) e->pInterface); ++ } else if (strcmp (e->name, VIDEO_DATA_DVC_CHANNEL_NAME) == 0) { ++ gdi_video_data_uninit (ctx->context.gdi, (VideoClientContext *) e->pInterface); ++ } ++} ++ ++static gboolean ++frdp_load_channels (freerdp *instance) ++{ ++ instance->context->settings->DeviceRedirection = FALSE; ++ if (!freerdp_client_load_addins (instance->context->channels, instance->context->settings)) ++ return FALSE; ++ ++ return TRUE; ++} ++ + static gboolean + frdp_pre_connect (freerdp *freerdp_session) + { ++ rdpContext *context = freerdp_session->context; ++ ++ PubSub_SubscribeChannelConnected (context->pubSub, ++ frdp_on_channel_connected_event_handler); ++ PubSub_SubscribeChannelDisconnected (context->pubSub, ++ frdp_on_channel_disconnected_event_handler); ++ ++ frdp_load_channels (freerdp_session); + return TRUE; + } + +@@ -402,6 +419,30 @@ frdp_begin_paint (rdpContext *context) + return TRUE; + } + ++static void ++queue_draw_area (FrdpSession *self, ++ gint x, ++ gint y, ++ gint width, ++ gint height) ++{ ++ FrdpSessionPrivate *priv = self->priv; ++ GdkRectangle *rectangle; ++ ++ rectangle = g_new (GdkRectangle, 1); ++ rectangle->x = x; ++ rectangle->y = y; ++ rectangle->width = width; ++ rectangle->height = height; ++ ++ g_mutex_lock (&priv->area_draw_mutex); ++ ++ if (priv->area_draw_queue != NULL) ++ g_queue_push_tail (priv->area_draw_queue, rectangle); ++ ++ g_mutex_unlock (&priv->area_draw_mutex); ++} ++ + static gboolean + frdp_end_paint (rdpContext *context) + { +@@ -422,70 +463,75 @@ frdp_end_paint (rdpContext *context) + priv = self->priv; + + if (priv->scaling) { +- pos_x = self->priv->offset_x + x * priv->scale; +- pos_y = self->priv->offset_y + y * priv->scale; +- gtk_widget_queue_draw_area (priv->display, +- floor (pos_x), +- floor (pos_y), +- ceil (pos_x + w * priv->scale) - floor (pos_x), +- ceil (pos_y + h * priv->scale) - floor (pos_y)); ++ pos_x = self->priv->offset_x + x * priv->scale; ++ pos_y = self->priv->offset_y + y * priv->scale; ++ queue_draw_area (self, ++ floor (pos_x), ++ floor (pos_y), ++ ceil (pos_x + w * priv->scale) - floor (pos_x), ++ ceil (pos_y + h * priv->scale) - floor (pos_y)); + } else { +- gtk_widget_queue_draw_area (priv->display, x, y, w, h); ++ queue_draw_area (self, x, y, w, h); + } + + return TRUE; + } + ++static void ++frdp_post_disconnect (freerdp *instance) ++{ ++ FrdpSession *self; ++ rdpContext *context; ++ ++ if (!instance || !instance->context) ++ return; ++ ++ self = ((frdpContext *) instance->context)->self; ++ ++ g_signal_handlers_disconnect_by_func (self->priv->display, G_CALLBACK (frdp_session_draw), self); ++ g_signal_handlers_disconnect_by_func (self->priv->display, G_CALLBACK (frdp_session_configure_event), self); ++ ++ context = instance->context; ++ PubSub_UnsubscribeChannelConnected (context->pubSub, ++ frdp_on_channel_connected_event_handler); ++ PubSub_UnsubscribeChannelDisconnected (context->pubSub, ++ frdp_on_channel_disconnected_event_handler); ++ gdi_free (instance); ++} ++ + static gboolean + frdp_post_connect (freerdp *freerdp_session) + { + FrdpSession *self = ((frdpContext *) freerdp_session->context)->self; +- cairo_format_t cairo_format; +- rdpGdi *gdi; + guint32 color_format; +- gint stride; + + switch (frdp_session_get_best_color_depth (self)) { + case 32: +- color_format = PIXEL_FORMAT_BGRA32; +- cairo_format = CAIRO_FORMAT_ARGB32; ++ color_format = PIXEL_FORMAT_BGRX32; ++ self->priv->cairo_format = CAIRO_FORMAT_ARGB32; + break; + case 24: + color_format = PIXEL_FORMAT_BGRX32; +- cairo_format = CAIRO_FORMAT_RGB24; ++ self->priv->cairo_format = CAIRO_FORMAT_RGB24; + break; + case 16: + case 15: + color_format = PIXEL_FORMAT_BGR16; +- cairo_format = CAIRO_FORMAT_RGB16_565; ++ self->priv->cairo_format = CAIRO_FORMAT_RGB16_565; + break; + default: + color_format = PIXEL_FORMAT_BGRX32; +- cairo_format = CAIRO_FORMAT_RGB16_565; ++ self->priv->cairo_format = CAIRO_FORMAT_RGB16_565; + break; + } + + gdi_init (freerdp_session, color_format); +- gdi = freerdp_session->context->gdi; + +- frdp_register_pointer (freerdp_session->context->graphics); +- pointer_cache_register_callbacks(freerdp_session->context->update); + freerdp_session->update->BeginPaint = frdp_begin_paint; + freerdp_session->update->EndPaint = frdp_end_paint; ++ freerdp_session->update->DesktopResize = frdp_desktop_resize; + +- stride = cairo_format_stride_for_width (cairo_format, gdi->width); +- self->priv->surface = +- cairo_image_surface_create_for_data ((unsigned char*) gdi->primary_buffer, +- cairo_format, +- gdi->width, +- gdi->height, +- stride); +- +- gtk_widget_queue_draw_area (self->priv->display, +- 0, +- 0, +- gdi->width, +- gdi->height); ++ create_cairo_surface (self); + + return TRUE; + } +@@ -502,9 +548,13 @@ idle_close (gpointer user_data) + self->priv->update_id = 0; + } + ++ g_mutex_lock (&self->priv->area_draw_mutex); ++ g_queue_clear_full (self->priv->area_draw_queue, g_free); ++ g_mutex_unlock (&self->priv->area_draw_mutex); ++ g_mutex_clear (&self->priv->area_draw_mutex); ++ + if (self->priv->freerdp_session != NULL) { + freerdp_disconnect (self->priv->freerdp_session); +- freerdp_context_free (self->priv->freerdp_session); + g_clear_pointer (&self->priv->freerdp_session, freerdp_free); + } + +@@ -526,31 +576,49 @@ update (gpointer user_data) + DWORD usedHandles; + FrdpSessionPrivate *priv; + FrdpSession *self = (FrdpSession*) user_data; ++ GdkRectangle *rectangle; + + priv = self->priv; + ++ g_mutex_lock (&priv->area_draw_mutex); ++ ++ while (priv->area_draw_queue != NULL && !g_queue_is_empty (priv->area_draw_queue)) { ++ rectangle = g_queue_pop_head (priv->area_draw_queue); ++ gtk_widget_queue_draw_area (priv->display, rectangle->x, rectangle->y, rectangle->width, rectangle->height); ++ g_free (rectangle); ++ } ++ ++ g_mutex_unlock (&priv->area_draw_mutex); ++ ++ if (freerdp_shall_disconnect (priv->freerdp_session)) { ++ priv->update_id = 0; ++ g_idle_add ((GSourceFunc) idle_close, self); ++ ++ return FALSE; ++ } ++ + usedHandles = freerdp_get_event_handles (priv->freerdp_session->context, + handles, ARRAYSIZE(handles)); + if (usedHandles == 0) { + g_warning ("Failed to get FreeRDP event handle"); ++ priv->update_id = 0; + return FALSE; + } + + status = WaitForMultipleObjects (usedHandles, handles, FALSE, SELECT_TIMEOUT); + if (status == WAIT_TIMEOUT) +- return TRUE; +- if (status == WAIT_FAILED) +- return FALSE; +- +- if (!freerdp_check_event_handles (priv->freerdp_session->context)) { +- g_warning ("Failed to check FreeRDP file descriptor"); ++ return TRUE; ++ if (status == WAIT_FAILED) { ++ priv->update_id = 0; + return FALSE; + } + +- if (freerdp_shall_disconnect (priv->freerdp_session)) { +- g_idle_add ((GSourceFunc) idle_close, self); ++ if (!freerdp_check_event_handles (priv->freerdp_session->context)) { ++ if (freerdp_get_last_error(priv->freerdp_session->context) == FREERDP_ERROR_SUCCESS) { ++ g_warning ("Failed to check FreeRDP file descriptor"); ++ } + +- return FALSE; ++ return TRUE; + } + + return TRUE; +@@ -560,12 +628,14 @@ static void + frdp_session_init_freerdp (FrdpSession *self) + { + FrdpSessionPrivate *priv = self->priv; +- rdpSettings *settings; ++ rdpSettings *settings; ++ gchar *build_options; + + /* Setup FreeRDP session */ + priv->freerdp_session = freerdp_new (); + priv->freerdp_session->PreConnect = frdp_pre_connect; + priv->freerdp_session->PostConnect = frdp_post_connect; ++ priv->freerdp_session->PostDisconnect = frdp_post_disconnect; + priv->freerdp_session->Authenticate = frdp_authenticate; + priv->freerdp_session->VerifyCertificate = frdp_certificate_verify; + priv->freerdp_session->VerifyChangedCertificate = frdp_changed_certificate_verify; +@@ -594,6 +664,23 @@ frdp_session_init_freerdp (FrdpSession * + settings->UseRdpSecurityLayer = FALSE; + + settings->NegotiateSecurityLayer = TRUE; ++ ++ settings->RemoteFxCodec = TRUE; ++ settings->RedirectClipboard = FALSE; ++ settings->ColorDepth = 32; ++ settings->SupportGraphicsPipeline = TRUE; ++ ++ build_options = g_ascii_strup (freerdp_get_build_config (), -1); ++ if (g_strrstr (build_options, "WITH_GFX_H264=ON") != NULL) { ++ settings->GfxH264 = TRUE; ++ settings->GfxAVC444 = TRUE; ++ } else { ++ settings->GfxH264 = FALSE; ++ settings->GfxAVC444 = FALSE; ++ } ++ g_free (build_options); ++ ++ freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0); + } + + static void +@@ -643,6 +730,9 @@ frdp_session_connect_thread (GTask + return; + } + ++ gtk_widget_realize (self->priv->display); ++ create_cairo_surface (self); ++ + g_signal_connect (self->priv->display, "draw", + G_CALLBACK (frdp_session_draw), self); + g_signal_connect (self->priv->display, "configure-event", +@@ -661,21 +751,20 @@ frdp_session_get_property (GObject *o + GParamSpec *pspec) + { + FrdpSession *self = (FrdpSession*) object; +- rdpSettings *settings = self->priv->freerdp_session->settings; + + switch (property_id) + { + case PROP_HOSTNAME: +- g_value_set_string (value, settings->ServerHostname); ++ g_value_set_string (value, self->priv->hostname); + break; + case PROP_PORT: +- g_value_set_uint (value, settings->ServerPort); ++ g_value_set_uint (value, self->priv->port); + break; + case PROP_USERNAME: +- g_value_set_string (value, settings->Username); ++ g_value_set_string (value, self->priv->username); + break; + case PROP_PASSWORD: +- g_value_set_string (value, settings->Password); ++ g_value_set_string (value, self->priv->password); + break; + case PROP_DISPLAY: + g_value_set_object (value, self->priv->display); +@@ -817,6 +906,9 @@ frdp_session_init (FrdpSession *self) + { + self->priv = frdp_session_get_instance_private (self); + ++ g_mutex_init (&self->priv->area_draw_mutex); ++ self->priv->area_draw_queue = g_queue_new (); ++ + self->priv->is_connected = FALSE; + } + +@@ -844,7 +936,19 @@ frdp_session_connect (FrdpSession + self->priv->port = port; + + task = g_task_new (self, cancellable, callback, user_data); +- g_task_run_in_thread (task, frdp_session_connect_thread); ++ /* Turn off the asynchronous connection via GTask thread as the FreeRDP ++ * process then runs in the new thread which makes it hard to cooperate ++ * with the original thread running UI leading to random race conditions. ++ * Turn it on again if there will be an async support for connection ++ * added to FreeRDP. ++ * The disadvantage is that the application freezes during connection ++ * for some time. ++ ++ g_task_run_in_thread (task, frdp_session_connect_thread); ++ ++ */ ++ ++ frdp_session_connect_thread (task, self, user_data, cancellable); + + g_object_unref (task); + } +--- gnome-connections-41.2/subprojects/gtk-frdp/src/meson.build ++++ gnome-connections-41.2/subprojects/gtk-frdp/src/meson.build +@@ -40,6 +40,7 @@ gtk_frdp_deps = [ + # The 2.0.0-rc4 version is needed at least, but there is no easy way to detect this. + dependency('winpr2', version: '>= 2.0.0'), + dependency('freerdp2', version: '>= 2.0.0'), ++ dependency('freerdp-client2', version: '>= 2.0.0'), + + dependency('gio-2.0', version: '>= 2.50'), + dependency('gtk+-3.0'), diff --git a/gnome-connections.spec b/gnome-connections.spec index 1e66024..dc48144 100644 --- a/gnome-connections.spec +++ b/gnome-connections.spec @@ -7,13 +7,16 @@ Name: gnome-connections Version: 41.2 -Release: 1%{?dist} +Release: 2%{?dist} Summary: A remote desktop client for the GNOME desktop environment License: GPLv3+ URL: https://gitlab.gnome.org/gnome/connections/-/wikis/home Source0: https://download.gnome.org/sources/gnome-connections/%{url_ver}/gnome-connections-%{tarball_version}.tar.xz +# https://issues.redhat.com/browse/RHEL-57692 +Patch0: gnome-connections-41.2-rdp-graphics-pipeline.patch + BuildRequires: desktop-file-utils BuildRequires: gcc BuildRequires: gettext @@ -74,6 +77,10 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/org.gnome.Connections %{_datadir}/mime/packages/org.gnome.Connections.xml %changelog +* Fri Nov 22 2024 Marek Kasik - 41.2-2 +- Enable Graphics Pipeline for RDP connections +- Resolves: RHEL-57692 + * Wed Jan 05 2022 Felipe Borges - 41.2-1 - Update to 41.2 Related: rhbz#2031651