[gtk-frdp] Fixed #7: Added RDP mouse cursor support
- From: Felipe Borges <felipeborges src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk-frdp] Fixed #7: Added RDP mouse cursor support
- Date: Mon, 8 Jul 2019 11:07:27 +0000 (UTC)
commit 3a5f1356864339a5a9af27ce6e9464b8f0c5c5f5
Author: akallabeth <armin novak thincast com>
Date: Mon Jul 8 11:07:16 2019 +0000
Fixed #7: Added RDP mouse cursor support
src/frdp-display.c | 26 ++++++-
src/frdp-session.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/frdp-session.h | 3 +
3 files changed, 244 insertions(+), 1 deletion(-)
---
diff --git a/src/frdp-display.c b/src/frdp-display.c
index c7307d2..a04b879 100644
--- a/src/frdp-display.c
+++ b/src/frdp-display.c
@@ -199,6 +199,26 @@ frdp_display_scroll_event (GtkWidget *widget,
return TRUE;
}
+static gboolean
+frdp_enter_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ FrdpDisplay *self = FRDP_DISPLAY (widget);
+ FrdpDisplayPrivate *priv = frdp_display_get_instance_private (self);
+ frdp_session_mouse_pointer(priv->session, TRUE);
+ return TRUE;
+}
+
+static gboolean
+frdp_leave_notify_event (GtkWidget *widget,
+ GdkEventCrossing *event)
+{
+ FrdpDisplay *self = FRDP_DISPLAY (widget);
+ FrdpDisplayPrivate *priv = frdp_display_get_instance_private (self);
+ frdp_session_mouse_pointer(priv->session, FALSE);
+ return TRUE;
+}
+
static void
frdp_display_disconnected (GObject *source_object,
gpointer user_data)
@@ -310,6 +330,8 @@ frdp_display_class_init (FrdpDisplayClass *klass)
widget_class->button_press_event = frdp_display_button_press_event;
widget_class->button_release_event = frdp_display_button_press_event;
widget_class->scroll_event = frdp_display_scroll_event;
+ widget_class->enter_notify_event = frdp_enter_notify_event;
+ widget_class->leave_notify_event = frdp_leave_notify_event;
g_object_class_install_property (gobject_class,
PROP_USERNAME,
@@ -365,7 +387,9 @@ frdp_display_init (FrdpDisplay *self)
GDK_BUTTON_RELEASE_MASK |
GDK_SCROLL_MASK |
GDK_SMOOTH_SCROLL_MASK |
- GDK_KEY_PRESS_MASK);
+ GDK_KEY_PRESS_MASK |
+ GDK_ENTER_NOTIFY_MASK |
+ GDK_LEAVE_NOTIFY_MASK);
gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE);
diff --git a/src/frdp-session.c b/src/frdp-session.c
index 5ce5f86..45643be 100644
--- a/src/frdp-session.c
+++ b/src/frdp-session.c
@@ -28,6 +28,13 @@
#define SELECT_TIMEOUT 50
+struct frdp_pointer
+{
+ rdpPointer pointer;
+ cairo_surface_t *data;
+};
+typedef struct frdp_pointer frdpPointer;
+
struct _FrdpSessionPrivate
{
freerdp *freerdp_session;
@@ -47,6 +54,10 @@ struct _FrdpSessionPrivate
gchar *username;
gchar *password;
guint port;
+
+ gboolean show_cursor;
+ gboolean cursor_null;
+ frdpPointer *cursor;
};
G_DEFINE_TYPE_WITH_PRIVATE (FrdpSession, frdp_session, G_TYPE_OBJECT)
@@ -78,6 +89,197 @@ struct frdp_context
};
typedef struct frdp_context frdpContext;
+static void
+frdp_session_update_mouse_pointer (FrdpSession *self)
+{
+ FrdpSessionPrivate *priv = self->priv;
+ GdkCursor *cursor;
+ GdkDisplay *display;
+ GdkWindow *window;
+
+ window = gtk_widget_get_parent_window(priv->display);
+ display = gtk_widget_get_display(priv->display);
+ if (priv->show_cursor && priv->cursor_null) {
+ cairo_surface_t *surface;
+ cairo_t *cairo;
+
+ /* Create a 1x1 image with transparent color */
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
+ cairo = cairo_create (surface);
+ cairo_set_source_rgba (cairo, 0.0, 0.0, 0.0, 0.0);
+ cairo_set_line_width(cairo, 1);
+ cairo_rectangle(cairo, 0, 0, 1, 1);
+ cairo_fill (cairo);
+
+ cursor = gdk_cursor_new_from_surface (display, surface, 0, 0);
+ cairo_surface_destroy (surface);
+ cairo_destroy (cairo);
+ cairo_surface_destroy (surface);
+ } else if (!priv->show_cursor || !priv->cursor)
+ /* No cursor set or none to show */
+ cursor = gdk_cursor_new_from_name (display, "default");
+ else {
+ rdpPointer *pointer = &priv->cursor->pointer;
+ double scale = self->priv->scale;
+ double x = priv->cursor->pointer.xPos * scale;
+ double y = priv->cursor->pointer.yPos * scale;
+ double w = pointer->width * scale;
+ double h = pointer->height * scale;
+ cairo_surface_t *surface;
+ cairo_t *cairo;
+
+ if (!self->priv->scaling) {
+ scale = 1.0;
+ }
+
+ /* Scale the source image according to current settings. */
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, w, h);
+ cairo = cairo_create (surface);
+
+ cairo_scale(cairo, scale, scale);
+ cairo_set_source_surface (cairo, priv->cursor->data, 0, 0);
+ cairo_paint (cairo);
+
+ cairo_fill (cairo);
+ cursor = gdk_cursor_new_from_surface (display, surface, x, y);
+ cairo_surface_destroy (surface);
+ cairo_destroy (cairo);
+ }
+
+ gdk_window_set_cursor (window, cursor);
+}
+
+static BOOL
+frdp_Pointer_New(rdpContext* context, rdpPointer* pointer)
+{
+ 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);
+ }
+
+ 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;
+
+ fpointer->data = surface;
+ return TRUE;
+fail:
+ if (surface)
+ cairo_surface_destroy (surface);
+ return FALSE;
+}
+
+static void
+frdp_Pointer_Free (rdpContext* context, rdpPointer* pointer)
+{
+ frdpContext *fcontext = (frdpContext*) context;
+ frdpPointer *fpointer = (frdpPointer*) pointer;
+
+ if (fpointer && fpointer->data) {
+ cairo_surface_destroy (fpointer->data);
+ fpointer->data = 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;
+ unsigned char *data;
+ cairo_surface_t *surface;
+
+ priv->cursor = NULL;
+ priv->cursor_null = TRUE;
+
+ 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)
+{
+ frdpContext *fcontext = (frdpContext*) context;
+ /* TODO */
+ return TRUE;
+}
+
+static void
+frdp_register_pointer (rdpGraphics* graphics)
+{
+ rdpPointer pointer;
+
+ 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);
+}
+
static guint32
frdp_session_get_best_color_depth (FrdpSession *self)
{
@@ -113,6 +315,8 @@ frdp_session_configure_event (GtkWidget *widget,
self->priv->offset_x = (width - settings->DesktopWidth * self->priv->scale) / 2.0;
self->priv->offset_y = (height - settings->DesktopHeight * self->priv->scale) / 2.0;
}
+
+ frdp_session_update_mouse_pointer (self);
}
static void
@@ -277,6 +481,8 @@ frdp_post_connect (freerdp *freerdp_session)
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;
@@ -701,6 +907,16 @@ frdp_session_mouse_event (FrdpSession *self,
}
}
+void
+frdp_session_mouse_pointer (FrdpSession *self,
+ gboolean enter)
+{
+ FrdpSessionPrivate *priv = self->priv;
+
+ priv->show_cursor = enter;
+ frdp_session_update_mouse_pointer (self);
+}
+
static unsigned char keycode_scancodes[] = {
0, 0, 0, 0, 0, 0, 0, 28,
29, 53, 55, 56, 0, 71, 72, 73,
diff --git a/src/frdp-session.h b/src/frdp-session.h
index a9a146d..b88b217 100644
--- a/src/frdp-session.h
+++ b/src/frdp-session.h
@@ -80,6 +80,9 @@ void frdp_session_mouse_event (FrdpSession *self,
guint16 x,
guint16 y);
+void frdp_session_mouse_pointer (FrdpSession *self,
+ gboolean enter);
+
void frdp_session_send_key (FrdpSession *self,
FrdpKeyEvent event,
guint16 keycode);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]