[PATCH 13/25] Replace 'local_cursor' operation callback with a signal
- From: "Daniel P. Berrange" <berrange redhat com>
- To: gtk-vnc-list gnome org
- Cc: "Daniel P. Berrange" <berrange redhat com>
- Subject: [PATCH 13/25] Replace 'local_cursor' operation callback with a signal
- Date: Sat, 21 Nov 2009 13:28:02 +0000
Remove the 'local_cursor' operation callback from VncConnection.
Introduce a signal 'vnc-cursor-changed' and pass it as a
VncCursor object
---
src/vncconnection.c | 124 ++++++++++++++++++++++++++++++++++++++++++++------
src/vncconnection.h | 7 +++-
src/vncdisplay.c | 33 ++++++++++----
3 files changed, 139 insertions(+), 25 deletions(-)
diff --git a/src/vncconnection.c b/src/vncconnection.c
index bbe862e..88579ec 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -150,6 +150,8 @@ struct _VncConnectionPrivate
VncFramebuffer *fb;
gboolean fbSwapRemote;
+ VncCursor *cursor;
+
vnc_connection_rich_cursor_blt_func *rich_cursor_blt;
vnc_connection_tight_compute_predicted_func *tight_compute_predicted;
vnc_connection_tight_sum_pixel_func *tight_sum_pixel;
@@ -184,6 +186,15 @@ struct _VncConnectionPrivate
G_DEFINE_TYPE(VncConnection, vnc_connection, G_TYPE_OBJECT);
+
+enum {
+ VNC_CURSOR_CHANGED,
+
+ VNC_LAST_SIGNAL,
+};
+
+static guint signals[VNC_LAST_SIGNAL] = { 0, };
+
#define nibhi(a) (((a) >> 4) & 0x0F)
#define niblo(a) ((a) & 0x0F)
@@ -344,6 +355,55 @@ static void vnc_connection_set_property(GObject *object,
}
}
+struct signal_data
+{
+ VncConnection *conn;
+ struct coroutine *caller;
+
+ int signum;
+
+ union {
+ VncCursor *cursor;
+ } params;
+};
+
+static gboolean do_vnc_connection_emit_main_context(gpointer opaque)
+{
+ struct signal_data *data = opaque;
+
+ switch (data->signum) {
+ case VNC_CURSOR_CHANGED:
+ g_signal_emit(G_OBJECT(data->conn),
+ signals[data->signum],
+ 0,
+ data->params.cursor);
+ break;
+ }
+
+ coroutine_yieldto(data->caller, NULL);
+
+ return FALSE;
+}
+
+static void vnc_connection_emit_main_context(VncConnection *conn,
+ int signum,
+ struct signal_data *data)
+{
+ data->conn = conn;
+ data->caller = coroutine_self();
+ data->signum = signum;
+
+ g_idle_add(do_vnc_connection_emit_main_context, data);
+
+ /* This switches to the system coroutine context, lets
+ * the idle function run to dispatch the signal, and
+ * finally returns once complete. ie this is synchronous
+ * from the POV of the VNC coroutine despite there being
+ * an idle function involved
+ */
+ coroutine_yield(NULL);
+}
+
static gboolean vnc_connection_use_compression(VncConnection *conn)
{
@@ -2154,10 +2214,16 @@ static void vnc_connection_rich_cursor_blt(VncConnection *conn, guint8 *pixbuf,
static void vnc_connection_rich_cursor(VncConnection *conn, int x, int y, int width, int height)
{
VncConnectionPrivate *priv = conn->priv;
- guint8 *pixbuf = NULL;
+ struct signal_data sigdata;
+
+ if (priv->cursor) {
+ g_object_unref(priv->cursor);
+ priv->cursor = NULL;
+ }
if (width && height) {
- guint8 *image, *mask;
+ guint8 *pixbuf = NULL;
+ guint8 *image = NULL, *mask = NULL;
int imagelen, masklen;
imagelen = width * height * (priv->fmt.bits_per_pixel / 8);
@@ -2176,24 +2242,30 @@ static void vnc_connection_rich_cursor(VncConnection *conn, int x, int y, int wi
g_free(image);
g_free(mask);
+
+ priv->cursor = vnc_cursor_new(pixbuf, x, y, width, height);
}
- if (priv->has_error || !priv->ops.local_cursor)
+ if (priv->has_error)
return;
- if (!priv->ops.local_cursor(priv->ops_data, x, y, width, height, pixbuf)) {
- GVNC_DEBUG("Closing the connection: vnc_connection_rich_cursor() - !ops.local_cursor()");
- priv->has_error = TRUE;
- }
- g_free(pixbuf);
+ sigdata.params.cursor = priv->cursor;
+
+ vnc_connection_emit_main_context(conn, VNC_CURSOR_CHANGED, &sigdata);
}
static void vnc_connection_xcursor(VncConnection *conn, int x, int y, int width, int height)
{
VncConnectionPrivate *priv = conn->priv;
- guint8 *pixbuf = NULL;
+ struct signal_data sigdata;
+
+ if (priv->cursor) {
+ g_object_unref(priv->cursor);
+ priv->cursor = NULL;
+ }
if (width && height) {
+ guint8 *pixbuf = NULL;
guint8 *data, *mask, *datap, *maskp;
guint32 *pixp;
int rowlen;
@@ -2225,16 +2297,16 @@ static void vnc_connection_xcursor(VncConnection *conn, int x, int y, int width,
}
g_free(data);
g_free(mask);
+
+ priv->cursor = vnc_cursor_new(pixbuf, x, y, width, height);
}
- if (priv->has_error || !priv->ops.local_cursor)
+ if (priv->has_error)
return;
- if (!priv->ops.local_cursor(priv->ops_data, x, y, width, height, pixbuf)) {
- GVNC_DEBUG("Closing the connection: vnc_connection_xcursor() - !ops.local_cursor()");
- priv->has_error = TRUE;
- }
- g_free(pixbuf);
+ sigdata.params.cursor = priv->cursor;
+
+ vnc_connection_emit_main_context(conn, VNC_CURSOR_CHANGED, &sigdata);
}
static void vnc_connection_ext_key_event(VncConnection *conn)
@@ -3510,6 +3582,9 @@ static void vnc_connection_finalize (GObject *object)
if (vnc_connection_is_open(conn))
vnc_connection_close(conn);
+ if (priv->cursor)
+ g_object_unref(G_OBJECT(priv->cursor));
+
if (priv->fb)
g_object_unref(G_OBJECT(priv->fb));
@@ -3536,6 +3611,17 @@ static void vnc_connection_class_init(VncConnectionClass *klass)
G_PARAM_STATIC_NICK |
G_PARAM_STATIC_BLURB));
+ signals[VNC_CURSOR_CHANGED] =
+ g_signal_new ("vnc-cursor-changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (VncConnectionClass, vnc_cursor_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE,
+ 1,
+ VNC_TYPE_CURSOR);
+
g_type_class_add_private(klass, sizeof(VncConnectionPrivate));
}
@@ -4106,6 +4192,14 @@ gboolean vnc_connection_using_raw_keycodes(VncConnection *conn)
return priv->has_ext_key_event;
}
+VncCursor *vnc_connection_get_cursor(VncConnection *conn)
+{
+ VncConnectionPrivate *priv = conn->priv;
+
+ return priv->cursor;
+}
+
+
/*
* Local variables:
* c-indent-level: 8
diff --git a/src/vncconnection.h b/src/vncconnection.h
index 68a348e..42a6e05 100644
--- a/src/vncconnection.h
+++ b/src/vncconnection.h
@@ -24,6 +24,7 @@
#include <glib.h>
#include "vncframebuffer.h"
+#include "vnccursor.h"
G_BEGIN_DECLS
@@ -49,6 +50,9 @@ struct _VncConnection
struct _VncConnectionClass
{
GObjectClass parent_class;
+
+ /* Signals */
+ void (*vnc_cursor_changed)(VncConnection *conn, VncCursor *cursor);
};
typedef void (rgb24_render_func)(void *, int, int, int, int, guint8 *, int);
@@ -66,7 +70,6 @@ struct vnc_connection_ops
gboolean (*resize)(void *, int, int);
gboolean (*pixel_format)(void *, VncPixelFormat *);
gboolean (*pointer_type_change)(void *, int);
- gboolean (*local_cursor)(void *, int, int, int, int, guint8 *);
gboolean (*auth_unsupported)(void *, unsigned int);
gboolean (*render_jpeg)(void *, rgb24_render_func *render, void *,
int, int, int, int, guint8 *, int);
@@ -193,6 +196,8 @@ const char *vnc_connection_get_name(VncConnection *conn);
int vnc_connection_get_width(VncConnection *conn);
int vnc_connection_get_height(VncConnection *conn);
+VncCursor *vnc_connection_get_cursor(VncConnection *conn);
+
/* HACK this is temporary */
gboolean vnc_connection_using_raw_keycodes(VncConnection *conn);
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 165f67a..d796da0 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -939,6 +939,7 @@ static void emit_signal_delayed(VncDisplay *obj, int signum,
data->obj = obj;
data->caller = coroutine_self();
data->signum = signum;
+
g_idle_add(emit_signal_auth_cred, data);
coroutine_yield(NULL);
}
@@ -1238,24 +1239,38 @@ static gboolean on_bell(void *opaque)
return TRUE;
}
-static gboolean on_local_cursor(void *opaque, int x, int y, int width, int height, guint8 *image)
+static void on_cursor_changed(VncConnection *conn G_GNUC_UNUSED,
+ VncCursor *cursor,
+ gpointer opaque)
{
VncDisplay *obj = VNC_DISPLAY(opaque);
VncDisplayPrivate *priv = obj->priv;
+ GVNC_DEBUG("Cursor changed %p x=%d y=%d w=%d h=%d",
+ cursor,
+ cursor ? vnc_cursor_get_hotx(cursor) : -1,
+ cursor ? vnc_cursor_get_hoty(cursor) : -1,
+ cursor ? vnc_cursor_get_width(cursor) : -1,
+ cursor ? vnc_cursor_get_height(cursor) : -1);
+
if (priv->remote_cursor) {
gdk_cursor_unref(priv->remote_cursor);
priv->remote_cursor = NULL;
}
- if (width && height) {
+ if (cursor) {
GdkDisplay *display = gdk_drawable_get_display(GDK_DRAWABLE(GTK_WIDGET(obj)->window));
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(image, GDK_COLORSPACE_RGB,
- TRUE, 8, width, height,
- width * 4, NULL, NULL);
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(vnc_cursor_get_data(cursor),
+ GDK_COLORSPACE_RGB,
+ TRUE, 8,
+ vnc_cursor_get_width(cursor),
+ vnc_cursor_get_height(cursor),
+ vnc_cursor_get_width(cursor) * 4,
+ NULL, NULL);
priv->remote_cursor = gdk_cursor_new_from_pixbuf(display,
pixbuf,
- x, y);
+ vnc_cursor_get_hotx(cursor),
+ vnc_cursor_get_hoty(cursor));
g_object_unref(pixbuf);
}
@@ -1265,8 +1280,6 @@ static gboolean on_local_cursor(void *opaque, int x, int y, int width, int heigh
} else if (priv->absolute) {
do_pointer_hide(obj);
}
-
- return TRUE;
}
static gboolean check_pixbuf_support(const char *name)
@@ -1329,7 +1342,6 @@ static const struct vnc_connection_ops vnc_display_ops = {
.resize = on_resize,
.pixel_format = on_pixel_format,
.pointer_type_change = on_pointer_type_change,
- .local_cursor = on_local_cursor,
.auth_unsupported = on_auth_unsupported,
.server_cut_text = on_server_cut_text,
.bell = on_bell,
@@ -2013,6 +2025,9 @@ static void vnc_display_init(VncDisplay *display)
priv->preferable_auths = g_slist_append (priv->preferable_auths, GUINT_TO_POINTER (GVNC_AUTH_NONE));
priv->conn = vnc_connection_new(&vnc_display_ops, obj);
+
+ g_signal_connect(G_OBJECT(priv->conn), "vnc-cursor-changed",
+ G_CALLBACK(on_cursor_changed), display);
}
static int vnc_display_best_path(char *buf,
--
1.6.5.2
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]