975b3be6e7
Resolves: RHEL-57692
780 lines
26 KiB
Diff
780 lines
26 KiB
Diff
--- 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 <errno.h>
|
|
#include <freerdp/freerdp.h>
|
|
#include <freerdp/gdi/gdi.h>
|
|
+#include <freerdp/gdi/video.h>
|
|
+#include <freerdp/gdi/gfx.h>
|
|
+#include <freerdp/client/cmdline.h>
|
|
+#include <freerdp/client/channels.h>
|
|
#include <gdk/gdk.h>
|
|
#include <gio/gio.h>
|
|
#include <gtk/gtk.h>
|
|
@@ -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'),
|