Re: [gtk-vnc-devel] [PATCH] Fix little to big endian conversion



Hi, Daniel

The my patch was commited with revision 147.
But, the change of the patch was reverted with revision 148.
If it is an accident, could you commit the patch?

Thanks
Hiroyuki Kaguchi

diff -r 28eab97c0d35 -r 01b34fbc6e99 AUTHORS
--- a/AUTHORS	Mon Feb 18 10:31:58 2008 -0300
+++ b/AUTHORS	Mon Feb 18 13:46:54 2008 -0500
@@ -10,6 +10,7 @@ Patches received from:
 Patches received from:
 
    Halton Huo <Halton-dot-Huo-at-Sun-dotCOM>
+   Hiroyuki Kaguchi <fj7025cf-at-aa-dot-jp-dot-fujitsu-dot-com>
 
     ...send patches to get your name here...
 
diff -r 28eab97c0d35 -r 01b34fbc6e99 configure.ac
--- a/configure.ac	Mon Feb 18 10:31:58 2008 -0300
+++ b/configure.ac	Mon Feb 18 13:46:54 2008 -0500
@@ -102,11 +102,6 @@ AC_DEFINE_UNQUOTED(WITH_GTKGLEXT,[$WITH_
 AC_DEFINE_UNQUOTED(WITH_GTKGLEXT,[$WITH_GTKGLEXT], [Whether to use gtkglext])
 AC_SUBST(GTKGLEXT_CFLAGS)
 AC_SUBST(GTKGLEXT_LIBS)
-if test $WITH_GTKGLEXT -eq 0; then
-  with_scaling="no"
-else
-  with_scaling="yes"
-fi
 
 AC_ARG_WITH(libview,
 [  --with-libview          enable libview support in gvncviewer],
@@ -244,5 +239,4 @@ Configure summary:
 	Install example programs ...:  ${WITH_EXAMPLES}
 	Browser plugin .............:  ${enable_plugin}
 	DEBUG messages..............:  ${enable_debug}
-	Scaling support.............:  ${with_scaling}
 "
diff -r 28eab97c0d35 -r 01b34fbc6e99 examples/gvncviewer.c
--- a/examples/gvncviewer.c	Mon Feb 18 10:31:58 2008 -0300
+++ b/examples/gvncviewer.c	Mon Feb 18 13:46:54 2008 -0500
@@ -18,8 +18,6 @@
 #if WITH_GTKGLEXT
 #include <gtk/gtkgl.h>
 #endif
-
-static GtkWidget *vnc;
 
 static void set_title(VncDisplay *vnc, GtkWidget *window, gboolean grabbed)
 {
@@ -244,13 +242,10 @@ static gboolean window_state_event(GtkWi
 	ViewAutoDrawer *drawer = VIEW_AUTODRAWER(data);
 
 	if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
-		if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
-			vnc_display_force_grab(VNC_DISPLAY(vnc), TRUE);
-			ViewAutoDrawer_SetActive(drawer, TRUE);
-		} else {
-			vnc_display_force_grab(VNC_DISPLAY(vnc), FALSE);
-			ViewAutoDrawer_SetActive(drawer, FALSE);
-		}
+		if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)
+			ViewAutoDrawer_SetPinned(drawer, FALSE);
+		else
+			ViewAutoDrawer_SetPinned(drawer, TRUE);
 	}
 
 	return FALSE;
@@ -262,6 +257,7 @@ int main(int argc, char **argv)
 	char port[1024], hostname[1024];
 	char *display;
 	GtkWidget *window;
+	GtkWidget *vnc;
 	GtkWidget *layout;
 	GtkWidget *menubar;
 	GtkWidget *sendkey, *view;
@@ -326,7 +322,7 @@ int main(int argc, char **argv)
 	gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), submenu);
 
 #if WITH_LIBVIEW
-	ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(layout), FALSE);
+	ViewAutoDrawer_SetPinned(VIEW_AUTODRAWER(layout), TRUE);
 	ViewOvBox_SetOver(VIEW_OV_BOX(layout), menubar);
 	ViewOvBox_SetUnder(VIEW_OV_BOX(layout), vnc);
 #else
diff -r 28eab97c0d35 -r 01b34fbc6e99 src/blt.h
--- a/src/blt.h	Mon Feb 18 10:31:58 2008 -0300
+++ b/src/blt.h	Mon Feb 18 13:46:54 2008 -0500
@@ -16,7 +16,7 @@
 #define RGB24_BLIT SPLICE(gvnc_rgb24_blt_, SUFFIX())
 #define TIGHT_COMPUTE_PREDICTED SPLICE(gvnc_tight_compute_predicted_, SUFFIX())
 #define TIGHT_SUM_PIXEL SPLICE(gvnc_tight_sum_pixel_, SUFFIX())
-#define SWAP(gvnc, pixel) SPLICE(gvnc_swap_, SRC)(gvnc, pixel)
+#define SWAP(gvnc, pixel) SPLICE(gvnc_swap_, DST)(gvnc, pixel)
 #define COMPONENT(color, pixel) ((SWAP(gvnc, pixel) >> gvnc->fmt.SPLICE(color, _shift) & gvnc->fmt.SPLICE(color, _max)))
 
 static void FAST_FILL(struct gvnc *gvnc, src_pixel_t *sp,
@@ -43,9 +43,9 @@ static void FAST_FILL(struct gvnc *gvnc,
 
 static void SET_PIXEL(struct gvnc *gvnc, dst_pixel_t *dp, src_pixel_t *sp)
 {
-	*dp = ((*sp >> gvnc->rrs) & gvnc->rm) << gvnc->rls
+	*dp = SWAP(gvnc, ((*sp >> gvnc->rrs) & gvnc->rm) << gvnc->rls
 		| ((*sp >> gvnc->grs) & gvnc->gm) << gvnc->gls
-		| ((*sp >> gvnc->brs) & gvnc->bm) << gvnc->bls;
+		| ((*sp >> gvnc->brs) & gvnc->bm) << gvnc->bls);
 }
 
 static void SET_PIXEL_AT(struct gvnc *gvnc, int x, int y, src_pixel_t *sp)
diff -r 28eab97c0d35 -r 01b34fbc6e99 src/coroutine_gthread.c
--- a/src/coroutine_gthread.c	Mon Feb 18 10:31:58 2008 -0300
+++ b/src/coroutine_gthread.c	Mon Feb 18 13:46:54 2008 -0500
@@ -111,6 +111,7 @@ void *coroutine_yieldto(struct coroutine
 		fprintf(stderr, "Co-routine is re-entering itself\n");
 		abort();
 	}
+	to->caller = coroutine_self();
 	return coroutine_swap(coroutine_self(), to, arg);
 }
 
diff -r 28eab97c0d35 -r 01b34fbc6e99 src/gvnc.c
--- a/src/gvnc.c	Mon Feb 18 10:31:58 2008 -0300
+++ b/src/gvnc.c	Mon Feb 18 13:46:54 2008 -0500
@@ -354,7 +354,6 @@ static int gvnc_read(struct gvnc *gvnc, 
 		if (gvnc_use_compression(gvnc)) {
 			int ret = gvnc_zread(gvnc, data + offset, len);
 			if (ret == -1) {
-				GVNC_DEBUG("Closing the connection: gvnc_read() - gvnc_zread() failed\n");
 				gvnc->has_error = TRUE;
 				return -errno;
 			}
@@ -387,13 +386,11 @@ static int gvnc_read(struct gvnc *gvnc, 
 				case EINTR:
 					continue;
 				default:
-					GVNC_DEBUG("Closing the connection: gvnc_read() - ret=-1\n");
 					gvnc->has_error = TRUE;
 					return -errno;
 				}
 			}
 			if (ret == 0) {
-				GVNC_DEBUG("Closing the connection: gvnc_read() - ret=0\n");
 				gvnc->has_error = TRUE;
 				return -EPIPE;
 			}
@@ -442,13 +439,11 @@ static void gvnc_flush(struct gvnc *gvnc
 			case EINTR:
 				continue;
 			default:
-				GVNC_DEBUG("Closing the connection: gvnc_flush\n");
 				gvnc->has_error = TRUE;
 				return;
 			}
 		}
 		if (ret == 0) {
-			GVNC_DEBUG("Closing the connection: gvnc_flush\n");
 			gvnc->has_error = TRUE;
 			return;
 		}
@@ -958,7 +953,7 @@ static uint8_t gvnc_swap_8(struct gvnc *
 
 static uint16_t gvnc_swap_16(struct gvnc *gvnc, uint16_t pixel)
 {
-	if (gvnc->fmt.byte_order != __BYTE_ORDER)
+	if (gvnc->fmt.byte_order != gvnc->local.byte_order)
 		return  (((pixel >> 8) & 0xFF) << 0) |
 			(((pixel >> 0) & 0xFF) << 8);
 	else
@@ -967,7 +962,7 @@ static uint16_t gvnc_swap_16(struct gvnc
 
 static uint32_t gvnc_swap_32(struct gvnc *gvnc, uint32_t pixel)
 {
-	if (gvnc->fmt.byte_order != __BYTE_ORDER)
+	if (gvnc->fmt.byte_order != gvnc->local.byte_order)
 		return  (((pixel >> 24) & 0xFF) <<  0) |
 			(((pixel >> 16) & 0xFF) <<  8) |
 			(((pixel >>  8) & 0xFF) << 16) |
@@ -1099,7 +1094,6 @@ static void gvnc_raw_update(struct gvnc 
 
 	dst = malloc(width * (gvnc->fmt.bits_per_pixel / 8));
 	if (dst == NULL) {
-		GVNC_DEBUG("Closing the connection: gvnc_raw_update\n");
 		gvnc->has_error = TRUE;
 		return;
 	}
@@ -1381,7 +1375,6 @@ static void gvnc_zrle_update(struct gvnc
 	length = gvnc_read_u32(gvnc);
 	zlib_data = malloc(length);
 	if (zlib_data == NULL) {
-		GVNC_DEBUG("Closing the connection: gvnc_zrle_update\n");
 		gvnc->has_error = TRUE;
 		return;
 	}
@@ -1675,7 +1668,6 @@ static void gvnc_tight_update(struct gvn
 			gvnc_tight_update_gradient(gvnc, x, y, width, height);
 			break;
 		default: /* error */
-			GVNC_DEBUG("Closing the connection: gvnc_tight_update() - filter_id unknown\n");
 			gvnc->has_error = TRUE;
 			break;
 		}
@@ -1707,7 +1699,6 @@ static void gvnc_tight_update(struct gvn
 		g_free(jpeg_data);
 	} else {
 		/* error */
-		GVNC_DEBUG("Closing the connection: gvnc_tight_update() - ccontrol unknown\n");
 		gvnc->has_error = TRUE;
 	}
 }
@@ -1716,10 +1707,8 @@ static void gvnc_update(struct gvnc *gvn
 {
 	if (gvnc->has_error || !gvnc->ops.update)
 		return;
-	if (!gvnc->ops.update(gvnc->ops_data, x, y, width, height)) {
-		GVNC_DEBUG("Closing the connection: gvnc_update\n");
+	if (!gvnc->ops.update(gvnc->ops_data, x, y, width, height))
 		gvnc->has_error = TRUE;
-	}
 }
 
 static void gvnc_set_color_map_entry(struct gvnc *gvnc, uint16_t color,
@@ -1729,10 +1718,8 @@ static void gvnc_set_color_map_entry(str
 	if (gvnc->has_error || !gvnc->ops.set_color_map_entry)
 		return;
 	if (!gvnc->ops.set_color_map_entry(gvnc->ops_data, color,
-					    red, green, blue)) {
-		GVNC_DEBUG("Closing the connection: gvnc_set_color_map_entry\n");
+					    red, green, blue))
 		gvnc->has_error = TRUE;
-	}
 }
 
 static void gvnc_bell(struct gvnc *gvnc)
@@ -1742,10 +1729,8 @@ static void gvnc_bell(struct gvnc *gvnc)
 
 	GVNC_DEBUG("Server beep\n");
 
-	if (!gvnc->ops.bell(gvnc->ops_data)) {
-		GVNC_DEBUG("Closing the connection: gvnc_bell\n");
+	if (!gvnc->ops.bell(gvnc->ops_data))
 		gvnc->has_error = TRUE;
-	}
 }
 
 static void gvnc_server_cut_text(struct gvnc *gvnc, const void *data,
@@ -1754,30 +1739,26 @@ static void gvnc_server_cut_text(struct 
 	if (gvnc->has_error || !gvnc->ops.server_cut_text)
 		return;
 
-	if (!gvnc->ops.server_cut_text(gvnc->ops_data, data, len)) {
-		GVNC_DEBUG("Closing the connection: gvnc_server_cut_text\n");
+	GVNC_DEBUG("Server cut text\n");
+
+	if (!gvnc->ops.server_cut_text(gvnc->ops_data, data, len))
 		gvnc->has_error = TRUE;
-	}
 }
 
 static void gvnc_resize(struct gvnc *gvnc, int width, int height)
 {
 	if (gvnc->has_error || !gvnc->ops.resize)
 		return;
-	if (!gvnc->ops.resize(gvnc->ops_data, width, height)) {
-		GVNC_DEBUG("Closing the connection: gvnc_resize\n");
+	if (!gvnc->ops.resize(gvnc->ops_data, width, height))
 		gvnc->has_error = TRUE;
-	}
 }
 
 static void gvnc_pointer_type_change(struct gvnc *gvnc, int absolute)
 {
 	if (gvnc->has_error || !gvnc->ops.pointer_type_change)
 		return;
-	if (!gvnc->ops.pointer_type_change(gvnc->ops_data, absolute)) {
-		GVNC_DEBUG("Closing the connection: gvnc_pointer_type_change\n");
+	if (!gvnc->ops.pointer_type_change(gvnc->ops_data, absolute))
 		gvnc->has_error = TRUE;
-	}
 }
 
 static void gvnc_rich_cursor_blt(struct gvnc *gvnc, uint8_t *pixbuf,
@@ -1800,14 +1781,12 @@ static void gvnc_rich_cursor(struct gvnc
 
 		image = malloc(imagelen);
 		if (!image) {
-			GVNC_DEBUG("Closing the connection: gvnc_rich_cursor() - !image \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
 		mask = malloc(masklen);
 		if (!mask) {
 			free(image);
-			GVNC_DEBUG("Closing the connection: gvnc_rich_cursor() - !mask \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
@@ -1815,7 +1794,6 @@ static void gvnc_rich_cursor(struct gvnc
 		if (!pixbuf) {
 			free(mask);
 			free(image);
-			GVNC_DEBUG("Closing the connection: gvnc_rich_cursor() - !pixbuf \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
@@ -1832,10 +1810,8 @@ static void gvnc_rich_cursor(struct gvnc
 
 	if (gvnc->has_error || !gvnc->ops.local_cursor)
 		return;
-	if (!gvnc->ops.local_cursor(gvnc->ops_data, x, y, width, height, pixbuf)) {
-		GVNC_DEBUG("Closing the connection: gvnc_rich_cursor() - !ops.local_cursor() \n");
+	if (!gvnc->ops.local_cursor(gvnc->ops_data, x, y, width, height, pixbuf))
 		gvnc->has_error = TRUE;
-	}
 
 	free(pixbuf);
 }
@@ -1859,13 +1835,11 @@ static void gvnc_xcursor(struct gvnc *gv
 
 		rowlen = ((width + 7)/8);
 		if (!(data = malloc(rowlen*height))) {
-			GVNC_DEBUG("Closing the connection: gvnc_xcursor() - !data \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
 		if (!(mask = malloc(rowlen*height))) {
 			free(data);
-			GVNC_DEBUG("Closing the connection: gvnc_xcursor() - !mask \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
@@ -1889,10 +1863,8 @@ static void gvnc_xcursor(struct gvnc *gv
 
 	if (gvnc->has_error || !gvnc->ops.local_cursor)
 		return;
-	if (!gvnc->ops.local_cursor(gvnc->ops_data, x, y, width, height, pixbuf)) {
-		GVNC_DEBUG("Closing the connection: gvnc_xcursor() - !ops.local_cursor() \n");
+	if (!gvnc->ops.local_cursor(gvnc->ops_data, x, y, width, height, pixbuf))
 		gvnc->has_error = TRUE;
-	}
 
 	free(pixbuf);
 }
@@ -2023,14 +1995,12 @@ gboolean gvnc_server_message(struct gvnc
 		gvnc_read(gvnc, pad, 3);
 		n_text = gvnc_read_u32(gvnc);
 		if (n_text > (32 << 20)) {
-			GVNC_DEBUG("Closing the connection: gvnc_server_message() - cutText > allowed \n");
 			gvnc->has_error = TRUE;
 			break;
 		}
 
 		data = malloc(n_text + 1);
 		if (data == NULL) {
-			GVNC_DEBUG("Closing the connection: gvnc_server_message() - cutText - !data \n");
 			gvnc->has_error = TRUE;
 			break;
 		}
@@ -2983,7 +2953,7 @@ gboolean gvnc_set_local(struct gvnc *gvn
 	    fb->red_shift == gvnc->fmt.red_shift &&
 	    fb->green_shift == gvnc->fmt.green_shift &&
 	    fb->blue_shift == gvnc->fmt.blue_shift &&
-	    __BYTE_ORDER == gvnc->fmt.byte_order)
+	    fb->byte_order == gvnc->fmt.byte_order)
 		gvnc->perfect_match = TRUE;
 	else
 		gvnc->perfect_match = FALSE;
diff -r 28eab97c0d35 -r 01b34fbc6e99 src/gvnc.h
--- a/src/gvnc.h	Mon Feb 18 10:31:58 2008 -0300
+++ b/src/gvnc.h	Mon Feb 18 13:46:54 2008 -0500
@@ -49,6 +49,7 @@ struct gvnc_framebuffer
 
 	int linesize;
 
+	uint16_t byte_order;
 	int depth;
 	int bpp;
 
diff -r 28eab97c0d35 -r 01b34fbc6e99 src/libgtk-vnc_sym.version
--- a/src/libgtk-vnc_sym.version	Mon Feb 18 10:31:58 2008 -0300
+++ b/src/libgtk-vnc_sym.version	Mon Feb 18 13:46:54 2008 -0500
@@ -31,7 +31,6 @@
 
     vnc_display_set_lossy_encoding;
     vnc_display_set_scaling;
-    vnc_display_force_grab;
 
   local:
       *;
diff -r 28eab97c0d35 -r 01b34fbc6e99 src/vncdisplay.c
--- a/src/vncdisplay.c	Mon Feb 18 10:31:58 2008 -0300
+++ b/src/vncdisplay.c	Mon Feb 18 13:46:54 2008 -0500
@@ -81,28 +81,6 @@ struct _VncDisplayPrivate
 	gboolean read_only;
 	gboolean allow_lossy;
 	gboolean allow_scaling;
-};
-
-/* Delayed signal emmission.
- *
- * We want signals to be delivered in the system coroutine.  This helps avoid
- * confusing applications.  This is particularily important when using
- * GThread based coroutines since GTK gets very upset if a signal handler is
- * run in a different thread from the main loop if that signal handler isn't
- * written to use explicit locking.
- */
-struct signal_data
-{
-	VncDisplay *obj;
-	struct coroutine *caller;
-
-	int signum;
-	GValueArray *cred_list;
-	int width;
-	int height;
-	const char *msg;
-	unsigned int auth_type;
-	GString *str;
 };
 
 G_DEFINE_TYPE(VncDisplay, vnc_display, GTK_TYPE_DRAWING_AREA)
@@ -346,14 +324,6 @@ static void do_pointer_ungrab(VncDisplay
 		g_signal_emit(obj, signals[VNC_POINTER_UNGRAB], 0);
 }
 
-void vnc_display_force_grab(VncDisplay *obj, gboolean enable)
-{
-	if (enable)
-		do_pointer_grab(obj, FALSE);
-	else
-		do_pointer_ungrab(obj, FALSE);
-}
-
 static void do_pointer_hide(VncDisplay *obj)
 {
 	VncDisplayPrivate *priv = obj->priv;
@@ -381,9 +351,8 @@ static gboolean button_event(GtkWidget *
 	if (priv->read_only)
 		return FALSE;
 
-	gtk_widget_grab_focus (widget);
-
-	if (priv->grab_pointer && !priv->absolute && !priv->in_pointer_grab &&
+	if ((priv->grab_pointer || !priv->absolute) &&
+	    !priv->in_pointer_grab &&
 	    button->button == 1 && button->type == GDK_BUTTON_PRESS)
 		do_pointer_grab(VNC_DISPLAY(widget), FALSE);
 
@@ -536,15 +505,6 @@ static gboolean key_event(GtkWidget *wid
 		return FALSE;
 
 	if (gvnc_using_raw_keycodes(priv->gvnc)) {
-		if (key->type == GDK_KEY_PRESS &&
-		    ((key->keyval == GDK_Control_L && (key->state & GDK_MOD1_MASK)) ||
-		     (key->keyval == GDK_Alt_L && (key->state & GDK_CONTROL_MASK)))) {
-			if (priv->in_pointer_grab)
-				do_pointer_ungrab(VNC_DISPLAY(widget), FALSE);
-			else
-				do_pointer_grab(VNC_DISPLAY(widget), FALSE);
-		}
-
 		if (key->type == GDK_KEY_PRESS)
 			gvnc_key_event(priv->gvnc, 1,
 				       key->keyval, key->hardware_keycode);
@@ -775,6 +735,7 @@ static void setup_gdk_image(VncDisplay *
 	priv->fb.height = priv->image->height;
 	priv->fb.linesize = priv->image->bpl;
 	priv->fb.data = (uint8_t *)priv->image->mem;
+	priv->fb.byte_order = priv->image->byte_order == GDK_LSB_FIRST ? __LITTLE_ENDIAN : __BIG_ENDIAN;
 
 	gtk_widget_set_size_request(GTK_WIDGET(obj), width, height);
 }
@@ -829,72 +790,10 @@ static void setup_gl_image(VncDisplay *o
 }
 #endif
 
-static gboolean emit_signal_auth_cred(gpointer opaque)
-{
-	struct signal_data *s = opaque;
-
-	switch (s->signum) {
-	case VNC_AUTH_CREDENTIAL:
-		g_signal_emit(G_OBJECT(s->obj),
-			      signals[VNC_AUTH_CREDENTIAL],
-			      0,
-			      s->cred_list);
-		break;
-	case VNC_DESKTOP_RESIZE:
-		g_signal_emit(G_OBJECT(s->obj),
-			      signals[VNC_DESKTOP_RESIZE],
-			      0,
-			      s->width, s->height);
-		break;
-	case VNC_AUTH_FAILURE:
-		g_signal_emit(G_OBJECT(s->obj),
-			      signals[VNC_AUTH_FAILURE],
-			      0,
-			      s->msg);
-		break;
-	case VNC_AUTH_UNSUPPORTED:
-		g_signal_emit(G_OBJECT(s->obj),
-			      signals[VNC_AUTH_UNSUPPORTED],
-			      0,
-			      s->auth_type);
-		break;
-	case VNC_SERVER_CUT_TEXT:
-		g_signal_emit(G_OBJECT(s->obj),
-			      signals[VNC_SERVER_CUT_TEXT],
-			      0,
-			      s->str->str);
-		break;
-	case VNC_BELL:
-	case VNC_CONNECTED:
-	case VNC_INITIALIZED:
-	case VNC_DISCONNECTED:
-		g_signal_emit(G_OBJECT(s->obj),
-			      signals[s->signum],
-			      0);
-		break;
-	}
-
-	coroutine_yieldto(s->caller, NULL);
-	
-	return FALSE;
-}
-
-/* This function should be used to emit signals from gvnc callbacks */
-static void emit_signal_delayed(VncDisplay *obj, int signum,
-				struct signal_data *data)
-{
-	data->obj = obj;
-	data->caller = coroutine_self();
-	data->signum = signum;
-	g_idle_add(emit_signal_auth_cred, data);
-	coroutine_yield(NULL);
-}
-
-static gboolean do_resize(void *opaque, int width, int height, gboolean quiet)
+static gboolean on_resize(void *opaque, int width, int height)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
 	VncDisplayPrivate *priv = obj->priv;
-	struct signal_data s;
 
 	if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
 		return TRUE;
@@ -919,7 +818,7 @@ static gboolean do_resize(void *opaque, 
 		priv->null_cursor = create_null_cursor();
 		if (priv->local_pointer)
 			do_pointer_show(obj);
-		else if (!priv->absolute)
+		else
 			do_pointer_hide(obj);
 		priv->gc = gdk_gc_new(GTK_WIDGET(obj)->window);
 	}
@@ -933,18 +832,12 @@ static gboolean do_resize(void *opaque, 
 
 	gvnc_set_local(priv->gvnc, &priv->fb);
 
-	if (!quiet) {
-		s.width = width;
-		s.height = height;
-		emit_signal_delayed(obj, VNC_DESKTOP_RESIZE, &s);
-	}
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_DESKTOP_RESIZE],
+		       0,
+		       width, height);
 
 	return TRUE;
-}
-
-static gboolean on_resize(void *opaque, int width, int height)
-{
-	return do_resize(opaque, width, height, FALSE);
 }
 
 #if WITH_GTKGLEXT
@@ -1032,7 +925,7 @@ static void scale_display(VncDisplay *ob
 		image = priv->image;
 		priv->image = NULL;
 	
-		do_resize(obj, priv->fb.width, priv->fb.height, TRUE);
+		on_resize(obj, priv->fb.width, priv->fb.height);
 		build_gl_image_from_gdk((uint32_t *)priv->fb.data, image);
 
 		g_object_unref(image);
@@ -1075,7 +968,7 @@ static void rescale_display(VncDisplay *
 		data = priv->gl_tex_data;
 		priv->gl_tex_data = NULL;
 
-		do_resize(GTK_WIDGET(obj), priv->fb.width, priv->fb.height, TRUE);
+		on_resize(GTK_WIDGET(obj), priv->fb.width, priv->fb.height);
 
 		build_gdk_image_from_gl(priv->image, (uint32_t *)data);
 		gdk_gl_drawable_gl_begin(priv->gl_drawable,
@@ -1113,7 +1006,6 @@ static gboolean on_auth_cred(void *opaqu
 	VncDisplay *obj = VNC_DISPLAY(opaque);
 	GValueArray *cred_list;
 	GValue username, password, clientname;
-	struct signal_data s;
 
 	memset(&username, 0, sizeof(username));
 	memset(&password, 0, sizeof(password));
@@ -1136,8 +1028,10 @@ static gboolean on_auth_cred(void *opaqu
 		cred_list = g_value_array_append(cred_list, &clientname);
 	}
 
-	s.cred_list = cred_list;
-	emit_signal_delayed(obj, VNC_AUTH_CREDENTIAL, &s);
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_AUTH_CREDENTIAL],
+		       0,
+		       cred_list);
 
 	g_value_array_free(cred_list);
 
@@ -1177,10 +1071,11 @@ static gboolean on_auth_failure(void *op
 static gboolean on_auth_failure(void *opaque, const char *msg)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
-	struct signal_data s;
-
-	s.msg = msg;
-	emit_signal_delayed(obj, VNC_AUTH_FAILURE, &s);
+
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_AUTH_FAILURE],
+		       0,
+		       msg);
 
 	return TRUE;
 }
@@ -1188,10 +1083,11 @@ static gboolean on_auth_unsupported(void
 static gboolean on_auth_unsupported(void *opaque, unsigned int auth_type)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
-	struct signal_data s;
-
-	s.auth_type = auth_type;
-	emit_signal_delayed(obj, VNC_AUTH_UNSUPPORTED, &s);
+
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_AUTH_UNSUPPORTED],
+		       0,
+		       auth_type);
 
 	return TRUE;
 }
@@ -1200,10 +1096,11 @@ static gboolean on_server_cut_text(void 
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
 	GString *str = g_string_new_len ((const gchar *)text, len);
-	struct signal_data s;
-
-	s.str = str;
-	emit_signal_delayed(obj, VNC_SERVER_CUT_TEXT, &s);
+
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_SERVER_CUT_TEXT],
+		       0,
+		       str->str);
 
 	g_string_free (str, TRUE);
 	return TRUE;
@@ -1212,9 +1109,10 @@ static gboolean on_bell(void *opaque)
 static gboolean on_bell(void *opaque)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
-	struct signal_data s;
-
-	emit_signal_delayed(obj, VNC_BELL, &s);
+
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_BELL],
+		       0);
 
 	return TRUE;
 }
@@ -1341,8 +1239,8 @@ static void *vnc_coroutine(void *opaque)
 				GVNC_ENCODING_RAW };
 	int32_t *encodingsp;
 	int n_encodings;
+
 	int ret;
-	struct signal_data s;
 
 	if (priv->gvnc == NULL || gvnc_is_open(priv->gvnc)) {
 		g_idle_add(delayed_unref_object, obj);
@@ -1358,13 +1256,17 @@ static void *vnc_coroutine(void *opaque)
 			goto cleanup;
 	}
 
-	emit_signal_delayed(obj, VNC_CONNECTED, &s);
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_CONNECTED],
+		       0);
 
 	GVNC_DEBUG("Protocol initialization\n");
 	if (!gvnc_initialize(priv->gvnc, FALSE))
 		goto cleanup;
 
-	emit_signal_delayed(obj, VNC_INITIALIZED, &s);
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_INITIALIZED],
+		       0);
 
 	encodingsp = encodings;
 	n_encodings = ARRAY_SIZE(encodings);
@@ -1395,7 +1297,9 @@ static void *vnc_coroutine(void *opaque)
  cleanup:
 	GVNC_DEBUG("Doing final VNC cleanup\n");
 	gvnc_close(priv->gvnc);
-	emit_signal_delayed(obj, VNC_DISCONNECTED, &s);
+	g_signal_emit (G_OBJECT (obj),
+		       signals[VNC_DISCONNECTED],
+		       0);
 	g_idle_add(delayed_unref_object, obj);
 	/* Co-routine exits now - the VncDisplay object may no longer exist,
 	   so don't do anything else now unless you like SEGVs */
@@ -1906,7 +1810,7 @@ void vnc_display_set_pointer_local(VncDi
 	if (obj->priv->gc) {
 		if (enable)
 			do_pointer_show(obj);
-		else if (obj->priv->in_pointer_grab || obj->priv->absolute)
+		else
 			do_pointer_hide(obj);
 	}
 	obj->priv->local_pointer = enable;
@@ -1919,6 +1823,8 @@ void vnc_display_set_pointer_grab(VncDis
 	priv->grab_pointer = enable;
 	if (!enable && priv->absolute && priv->in_pointer_grab)
 		do_pointer_ungrab(obj, FALSE);
+	if (enable && priv->absolute && !priv->in_pointer_grab)
+		do_pointer_grab(obj, FALSE);
 }
 
 void vnc_display_set_keyboard_grab(VncDisplay *obj, gboolean enable)
@@ -1928,6 +1834,9 @@ void vnc_display_set_keyboard_grab(VncDi
 	priv->grab_keyboard = enable;
 	if (!enable && priv->in_keyboard_grab && !priv->in_pointer_grab)
 		do_keyboard_ungrab(obj, FALSE);
+	if (enable && !priv->in_keyboard_grab)
+		do_keyboard_grab(obj, FALSE);
+
 }
 
 void vnc_display_set_read_only(VncDisplay *obj, gboolean enable)
diff -r 28eab97c0d35 -r 01b34fbc6e99 src/vncdisplay.h
--- a/src/vncdisplay.h	Mon Feb 18 10:31:58 2008 -0300
+++ b/src/vncdisplay.h	Mon Feb 18 13:46:54 2008 -0500
@@ -107,8 +107,6 @@ void		vnc_display_set_lossy_encoding(Vnc
 
 gboolean	vnc_display_set_scaling(VncDisplay *obj, gboolean enable);
 
-void		vnc_display_force_grab(VncDisplay *obj, gboolean enable);
-
 G_END_DECLS
 
 #endif
diff -r 01b34fbc6e99 -r aaaaa7173d47 configure.ac
--- a/configure.ac	Mon Feb 18 13:46:54 2008 -0500
+++ b/configure.ac	Mon Feb 18 15:04:43 2008 -0500
@@ -102,6 +102,11 @@ AC_DEFINE_UNQUOTED(WITH_GTKGLEXT,[$WITH_
 AC_DEFINE_UNQUOTED(WITH_GTKGLEXT,[$WITH_GTKGLEXT], [Whether to use gtkglext])
 AC_SUBST(GTKGLEXT_CFLAGS)
 AC_SUBST(GTKGLEXT_LIBS)
+if test $WITH_GTKGLEXT -eq 0; then
+  with_scaling="no"
+else
+  with_scaling="yes"
+fi
 
 AC_ARG_WITH(libview,
 [  --with-libview          enable libview support in gvncviewer],
@@ -239,4 +244,5 @@ Configure summary:
 	Install example programs ...:  ${WITH_EXAMPLES}
 	Browser plugin .............:  ${enable_plugin}
 	DEBUG messages..............:  ${enable_debug}
+	Scaling support.............:  ${with_scaling}
 "
diff -r 01b34fbc6e99 -r aaaaa7173d47 examples/gvncviewer.c
--- a/examples/gvncviewer.c	Mon Feb 18 13:46:54 2008 -0500
+++ b/examples/gvncviewer.c	Mon Feb 18 15:04:43 2008 -0500
@@ -18,6 +18,8 @@
 #if WITH_GTKGLEXT
 #include <gtk/gtkgl.h>
 #endif
+
+static GtkWidget *vnc;
 
 static void set_title(VncDisplay *vnc, GtkWidget *window, gboolean grabbed)
 {
@@ -242,10 +244,13 @@ static gboolean window_state_event(GtkWi
 	ViewAutoDrawer *drawer = VIEW_AUTODRAWER(data);
 
 	if (event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
-		if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)
-			ViewAutoDrawer_SetPinned(drawer, FALSE);
-		else
-			ViewAutoDrawer_SetPinned(drawer, TRUE);
+		if (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) {
+			vnc_display_force_grab(VNC_DISPLAY(vnc), TRUE);
+			ViewAutoDrawer_SetActive(drawer, TRUE);
+		} else {
+			vnc_display_force_grab(VNC_DISPLAY(vnc), FALSE);
+			ViewAutoDrawer_SetActive(drawer, FALSE);
+		}
 	}
 
 	return FALSE;
@@ -257,7 +262,6 @@ int main(int argc, char **argv)
 	char port[1024], hostname[1024];
 	char *display;
 	GtkWidget *window;
-	GtkWidget *vnc;
 	GtkWidget *layout;
 	GtkWidget *menubar;
 	GtkWidget *sendkey, *view;
@@ -322,7 +326,7 @@ int main(int argc, char **argv)
 	gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), submenu);
 
 #if WITH_LIBVIEW
-	ViewAutoDrawer_SetPinned(VIEW_AUTODRAWER(layout), TRUE);
+	ViewAutoDrawer_SetActive(VIEW_AUTODRAWER(layout), FALSE);
 	ViewOvBox_SetOver(VIEW_OV_BOX(layout), menubar);
 	ViewOvBox_SetUnder(VIEW_OV_BOX(layout), vnc);
 #else
diff -r 01b34fbc6e99 -r aaaaa7173d47 src/blt.h
--- a/src/blt.h	Mon Feb 18 13:46:54 2008 -0500
+++ b/src/blt.h	Mon Feb 18 15:04:43 2008 -0500
@@ -16,7 +16,7 @@
 #define RGB24_BLIT SPLICE(gvnc_rgb24_blt_, SUFFIX())
 #define TIGHT_COMPUTE_PREDICTED SPLICE(gvnc_tight_compute_predicted_, SUFFIX())
 #define TIGHT_SUM_PIXEL SPLICE(gvnc_tight_sum_pixel_, SUFFIX())
-#define SWAP(gvnc, pixel) SPLICE(gvnc_swap_, DST)(gvnc, pixel)
+#define SWAP(gvnc, pixel) SPLICE(gvnc_swap_, SRC)(gvnc, pixel)
 #define COMPONENT(color, pixel) ((SWAP(gvnc, pixel) >> gvnc->fmt.SPLICE(color, _shift) & gvnc->fmt.SPLICE(color, _max)))
 
 static void FAST_FILL(struct gvnc *gvnc, src_pixel_t *sp,
@@ -43,9 +43,9 @@ static void FAST_FILL(struct gvnc *gvnc,
 
 static void SET_PIXEL(struct gvnc *gvnc, dst_pixel_t *dp, src_pixel_t *sp)
 {
-	*dp = SWAP(gvnc, ((*sp >> gvnc->rrs) & gvnc->rm) << gvnc->rls
+	*dp = ((*sp >> gvnc->rrs) & gvnc->rm) << gvnc->rls
 		| ((*sp >> gvnc->grs) & gvnc->gm) << gvnc->gls
-		| ((*sp >> gvnc->brs) & gvnc->bm) << gvnc->bls);
+		| ((*sp >> gvnc->brs) & gvnc->bm) << gvnc->bls;
 }
 
 static void SET_PIXEL_AT(struct gvnc *gvnc, int x, int y, src_pixel_t *sp)
diff -r 01b34fbc6e99 -r aaaaa7173d47 src/coroutine_gthread.c
--- a/src/coroutine_gthread.c	Mon Feb 18 13:46:54 2008 -0500
+++ b/src/coroutine_gthread.c	Mon Feb 18 15:04:43 2008 -0500
@@ -111,7 +111,6 @@ void *coroutine_yieldto(struct coroutine
 		fprintf(stderr, "Co-routine is re-entering itself\n");
 		abort();
 	}
-	to->caller = coroutine_self();
 	return coroutine_swap(coroutine_self(), to, arg);
 }
 
diff -r 01b34fbc6e99 -r aaaaa7173d47 src/gvnc.c
--- a/src/gvnc.c	Mon Feb 18 13:46:54 2008 -0500
+++ b/src/gvnc.c	Mon Feb 18 15:04:43 2008 -0500
@@ -354,6 +354,7 @@ static int gvnc_read(struct gvnc *gvnc, 
 		if (gvnc_use_compression(gvnc)) {
 			int ret = gvnc_zread(gvnc, data + offset, len);
 			if (ret == -1) {
+				GVNC_DEBUG("Closing the connection: gvnc_read() - gvnc_zread() failed\n");
 				gvnc->has_error = TRUE;
 				return -errno;
 			}
@@ -386,11 +387,13 @@ static int gvnc_read(struct gvnc *gvnc, 
 				case EINTR:
 					continue;
 				default:
+					GVNC_DEBUG("Closing the connection: gvnc_read() - ret=-1\n");
 					gvnc->has_error = TRUE;
 					return -errno;
 				}
 			}
 			if (ret == 0) {
+				GVNC_DEBUG("Closing the connection: gvnc_read() - ret=0\n");
 				gvnc->has_error = TRUE;
 				return -EPIPE;
 			}
@@ -439,11 +442,13 @@ static void gvnc_flush(struct gvnc *gvnc
 			case EINTR:
 				continue;
 			default:
+				GVNC_DEBUG("Closing the connection: gvnc_flush\n");
 				gvnc->has_error = TRUE;
 				return;
 			}
 		}
 		if (ret == 0) {
+			GVNC_DEBUG("Closing the connection: gvnc_flush\n");
 			gvnc->has_error = TRUE;
 			return;
 		}
@@ -1094,6 +1099,7 @@ static void gvnc_raw_update(struct gvnc 
 
 	dst = malloc(width * (gvnc->fmt.bits_per_pixel / 8));
 	if (dst == NULL) {
+		GVNC_DEBUG("Closing the connection: gvnc_raw_update\n");
 		gvnc->has_error = TRUE;
 		return;
 	}
@@ -1375,6 +1381,7 @@ static void gvnc_zrle_update(struct gvnc
 	length = gvnc_read_u32(gvnc);
 	zlib_data = malloc(length);
 	if (zlib_data == NULL) {
+		GVNC_DEBUG("Closing the connection: gvnc_zrle_update\n");
 		gvnc->has_error = TRUE;
 		return;
 	}
@@ -1668,6 +1675,7 @@ static void gvnc_tight_update(struct gvn
 			gvnc_tight_update_gradient(gvnc, x, y, width, height);
 			break;
 		default: /* error */
+			GVNC_DEBUG("Closing the connection: gvnc_tight_update() - filter_id unknown\n");
 			gvnc->has_error = TRUE;
 			break;
 		}
@@ -1699,6 +1707,7 @@ static void gvnc_tight_update(struct gvn
 		g_free(jpeg_data);
 	} else {
 		/* error */
+		GVNC_DEBUG("Closing the connection: gvnc_tight_update() - ccontrol unknown\n");
 		gvnc->has_error = TRUE;
 	}
 }
@@ -1707,8 +1716,10 @@ static void gvnc_update(struct gvnc *gvn
 {
 	if (gvnc->has_error || !gvnc->ops.update)
 		return;
-	if (!gvnc->ops.update(gvnc->ops_data, x, y, width, height))
+	if (!gvnc->ops.update(gvnc->ops_data, x, y, width, height)) {
+		GVNC_DEBUG("Closing the connection: gvnc_update\n");
 		gvnc->has_error = TRUE;
+	}
 }
 
 static void gvnc_set_color_map_entry(struct gvnc *gvnc, uint16_t color,
@@ -1718,8 +1729,10 @@ static void gvnc_set_color_map_entry(str
 	if (gvnc->has_error || !gvnc->ops.set_color_map_entry)
 		return;
 	if (!gvnc->ops.set_color_map_entry(gvnc->ops_data, color,
-					    red, green, blue))
+					    red, green, blue)) {
+		GVNC_DEBUG("Closing the connection: gvnc_set_color_map_entry\n");
 		gvnc->has_error = TRUE;
+	}
 }
 
 static void gvnc_bell(struct gvnc *gvnc)
@@ -1729,8 +1742,10 @@ static void gvnc_bell(struct gvnc *gvnc)
 
 	GVNC_DEBUG("Server beep\n");
 
-	if (!gvnc->ops.bell(gvnc->ops_data))
+	if (!gvnc->ops.bell(gvnc->ops_data)) {
+		GVNC_DEBUG("Closing the connection: gvnc_bell\n");
 		gvnc->has_error = TRUE;
+	}
 }
 
 static void gvnc_server_cut_text(struct gvnc *gvnc, const void *data,
@@ -1739,26 +1754,30 @@ static void gvnc_server_cut_text(struct 
 	if (gvnc->has_error || !gvnc->ops.server_cut_text)
 		return;
 
-	GVNC_DEBUG("Server cut text\n");
-
-	if (!gvnc->ops.server_cut_text(gvnc->ops_data, data, len))
+	if (!gvnc->ops.server_cut_text(gvnc->ops_data, data, len)) {
+		GVNC_DEBUG("Closing the connection: gvnc_server_cut_text\n");
 		gvnc->has_error = TRUE;
+	}
 }
 
 static void gvnc_resize(struct gvnc *gvnc, int width, int height)
 {
 	if (gvnc->has_error || !gvnc->ops.resize)
 		return;
-	if (!gvnc->ops.resize(gvnc->ops_data, width, height))
+	if (!gvnc->ops.resize(gvnc->ops_data, width, height)) {
+		GVNC_DEBUG("Closing the connection: gvnc_resize\n");
 		gvnc->has_error = TRUE;
+	}
 }
 
 static void gvnc_pointer_type_change(struct gvnc *gvnc, int absolute)
 {
 	if (gvnc->has_error || !gvnc->ops.pointer_type_change)
 		return;
-	if (!gvnc->ops.pointer_type_change(gvnc->ops_data, absolute))
+	if (!gvnc->ops.pointer_type_change(gvnc->ops_data, absolute)) {
+		GVNC_DEBUG("Closing the connection: gvnc_pointer_type_change\n");
 		gvnc->has_error = TRUE;
+	}
 }
 
 static void gvnc_rich_cursor_blt(struct gvnc *gvnc, uint8_t *pixbuf,
@@ -1781,12 +1800,14 @@ static void gvnc_rich_cursor(struct gvnc
 
 		image = malloc(imagelen);
 		if (!image) {
+			GVNC_DEBUG("Closing the connection: gvnc_rich_cursor() - !image \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
 		mask = malloc(masklen);
 		if (!mask) {
 			free(image);
+			GVNC_DEBUG("Closing the connection: gvnc_rich_cursor() - !mask \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
@@ -1794,6 +1815,7 @@ static void gvnc_rich_cursor(struct gvnc
 		if (!pixbuf) {
 			free(mask);
 			free(image);
+			GVNC_DEBUG("Closing the connection: gvnc_rich_cursor() - !pixbuf \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
@@ -1810,8 +1832,10 @@ static void gvnc_rich_cursor(struct gvnc
 
 	if (gvnc->has_error || !gvnc->ops.local_cursor)
 		return;
-	if (!gvnc->ops.local_cursor(gvnc->ops_data, x, y, width, height, pixbuf))
+	if (!gvnc->ops.local_cursor(gvnc->ops_data, x, y, width, height, pixbuf)) {
+		GVNC_DEBUG("Closing the connection: gvnc_rich_cursor() - !ops.local_cursor() \n");
 		gvnc->has_error = TRUE;
+	}
 
 	free(pixbuf);
 }
@@ -1835,11 +1859,13 @@ static void gvnc_xcursor(struct gvnc *gv
 
 		rowlen = ((width + 7)/8);
 		if (!(data = malloc(rowlen*height))) {
+			GVNC_DEBUG("Closing the connection: gvnc_xcursor() - !data \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
 		if (!(mask = malloc(rowlen*height))) {
 			free(data);
+			GVNC_DEBUG("Closing the connection: gvnc_xcursor() - !mask \n");
 			gvnc->has_error = TRUE;
 			return;
 		}
@@ -1863,8 +1889,10 @@ static void gvnc_xcursor(struct gvnc *gv
 
 	if (gvnc->has_error || !gvnc->ops.local_cursor)
 		return;
-	if (!gvnc->ops.local_cursor(gvnc->ops_data, x, y, width, height, pixbuf))
+	if (!gvnc->ops.local_cursor(gvnc->ops_data, x, y, width, height, pixbuf)) {
+		GVNC_DEBUG("Closing the connection: gvnc_xcursor() - !ops.local_cursor() \n");
 		gvnc->has_error = TRUE;
+	}
 
 	free(pixbuf);
 }
@@ -1995,12 +2023,14 @@ gboolean gvnc_server_message(struct gvnc
 		gvnc_read(gvnc, pad, 3);
 		n_text = gvnc_read_u32(gvnc);
 		if (n_text > (32 << 20)) {
+			GVNC_DEBUG("Closing the connection: gvnc_server_message() - cutText > allowed \n");
 			gvnc->has_error = TRUE;
 			break;
 		}
 
 		data = malloc(n_text + 1);
 		if (data == NULL) {
+			GVNC_DEBUG("Closing the connection: gvnc_server_message() - cutText - !data \n");
 			gvnc->has_error = TRUE;
 			break;
 		}
diff -r 01b34fbc6e99 -r aaaaa7173d47 src/gvnc.h
--- a/src/gvnc.h	Mon Feb 18 13:46:54 2008 -0500
+++ b/src/gvnc.h	Mon Feb 18 15:04:43 2008 -0500
@@ -49,7 +49,6 @@ struct gvnc_framebuffer
 
 	int linesize;
 
-	uint16_t byte_order;
 	int depth;
 	int bpp;
 
diff -r 01b34fbc6e99 -r aaaaa7173d47 src/libgtk-vnc_sym.version
--- a/src/libgtk-vnc_sym.version	Mon Feb 18 13:46:54 2008 -0500
+++ b/src/libgtk-vnc_sym.version	Mon Feb 18 15:04:43 2008 -0500
@@ -31,6 +31,7 @@
 
     vnc_display_set_lossy_encoding;
     vnc_display_set_scaling;
+    vnc_display_force_grab;
 
   local:
       *;
diff -r 01b34fbc6e99 -r aaaaa7173d47 src/vncdisplay.c
--- a/src/vncdisplay.c	Mon Feb 18 13:46:54 2008 -0500
+++ b/src/vncdisplay.c	Mon Feb 18 15:04:43 2008 -0500
@@ -81,6 +81,28 @@ struct _VncDisplayPrivate
 	gboolean read_only;
 	gboolean allow_lossy;
 	gboolean allow_scaling;
+};
+
+/* Delayed signal emmission.
+ *
+ * We want signals to be delivered in the system coroutine.  This helps avoid
+ * confusing applications.  This is particularily important when using
+ * GThread based coroutines since GTK gets very upset if a signal handler is
+ * run in a different thread from the main loop if that signal handler isn't
+ * written to use explicit locking.
+ */
+struct signal_data
+{
+	VncDisplay *obj;
+	struct coroutine *caller;
+
+	int signum;
+	GValueArray *cred_list;
+	int width;
+	int height;
+	const char *msg;
+	unsigned int auth_type;
+	GString *str;
 };
 
 G_DEFINE_TYPE(VncDisplay, vnc_display, GTK_TYPE_DRAWING_AREA)
@@ -324,6 +346,14 @@ static void do_pointer_ungrab(VncDisplay
 		g_signal_emit(obj, signals[VNC_POINTER_UNGRAB], 0);
 }
 
+void vnc_display_force_grab(VncDisplay *obj, gboolean enable)
+{
+	if (enable)
+		do_pointer_grab(obj, FALSE);
+	else
+		do_pointer_ungrab(obj, FALSE);
+}
+
 static void do_pointer_hide(VncDisplay *obj)
 {
 	VncDisplayPrivate *priv = obj->priv;
@@ -351,8 +381,9 @@ static gboolean button_event(GtkWidget *
 	if (priv->read_only)
 		return FALSE;
 
-	if ((priv->grab_pointer || !priv->absolute) &&
-	    !priv->in_pointer_grab &&
+	gtk_widget_grab_focus (widget);
+
+	if (priv->grab_pointer && !priv->absolute && !priv->in_pointer_grab &&
 	    button->button == 1 && button->type == GDK_BUTTON_PRESS)
 		do_pointer_grab(VNC_DISPLAY(widget), FALSE);
 
@@ -505,6 +536,15 @@ static gboolean key_event(GtkWidget *wid
 		return FALSE;
 
 	if (gvnc_using_raw_keycodes(priv->gvnc)) {
+		if (key->type == GDK_KEY_PRESS &&
+		    ((key->keyval == GDK_Control_L && (key->state & GDK_MOD1_MASK)) ||
+		     (key->keyval == GDK_Alt_L && (key->state & GDK_CONTROL_MASK)))) {
+			if (priv->in_pointer_grab)
+				do_pointer_ungrab(VNC_DISPLAY(widget), FALSE);
+			else
+				do_pointer_grab(VNC_DISPLAY(widget), FALSE);
+		}
+
 		if (key->type == GDK_KEY_PRESS)
 			gvnc_key_event(priv->gvnc, 1,
 				       key->keyval, key->hardware_keycode);
@@ -735,7 +775,6 @@ static void setup_gdk_image(VncDisplay *
 	priv->fb.height = priv->image->height;
 	priv->fb.linesize = priv->image->bpl;
 	priv->fb.data = (uint8_t *)priv->image->mem;
-	priv->fb.byte_order = priv->image->byte_order == GDK_LSB_FIRST ? __LITTLE_ENDIAN : __BIG_ENDIAN;
 
 	gtk_widget_set_size_request(GTK_WIDGET(obj), width, height);
 }
@@ -790,10 +829,72 @@ static void setup_gl_image(VncDisplay *o
 }
 #endif
 
-static gboolean on_resize(void *opaque, int width, int height)
+static gboolean emit_signal_auth_cred(gpointer opaque)
+{
+	struct signal_data *s = opaque;
+
+	switch (s->signum) {
+	case VNC_AUTH_CREDENTIAL:
+		g_signal_emit(G_OBJECT(s->obj),
+			      signals[VNC_AUTH_CREDENTIAL],
+			      0,
+			      s->cred_list);
+		break;
+	case VNC_DESKTOP_RESIZE:
+		g_signal_emit(G_OBJECT(s->obj),
+			      signals[VNC_DESKTOP_RESIZE],
+			      0,
+			      s->width, s->height);
+		break;
+	case VNC_AUTH_FAILURE:
+		g_signal_emit(G_OBJECT(s->obj),
+			      signals[VNC_AUTH_FAILURE],
+			      0,
+			      s->msg);
+		break;
+	case VNC_AUTH_UNSUPPORTED:
+		g_signal_emit(G_OBJECT(s->obj),
+			      signals[VNC_AUTH_UNSUPPORTED],
+			      0,
+			      s->auth_type);
+		break;
+	case VNC_SERVER_CUT_TEXT:
+		g_signal_emit(G_OBJECT(s->obj),
+			      signals[VNC_SERVER_CUT_TEXT],
+			      0,
+			      s->str->str);
+		break;
+	case VNC_BELL:
+	case VNC_CONNECTED:
+	case VNC_INITIALIZED:
+	case VNC_DISCONNECTED:
+		g_signal_emit(G_OBJECT(s->obj),
+			      signals[s->signum],
+			      0);
+		break;
+	}
+
+	coroutine_yieldto(s->caller, NULL);
+	
+	return FALSE;
+}
+
+/* This function should be used to emit signals from gvnc callbacks */
+static void emit_signal_delayed(VncDisplay *obj, int signum,
+				struct signal_data *data)
+{
+	data->obj = obj;
+	data->caller = coroutine_self();
+	data->signum = signum;
+	g_idle_add(emit_signal_auth_cred, data);
+	coroutine_yield(NULL);
+}
+
+static gboolean do_resize(void *opaque, int width, int height, gboolean quiet)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
 	VncDisplayPrivate *priv = obj->priv;
+	struct signal_data s;
 
 	if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc))
 		return TRUE;
@@ -818,7 +919,7 @@ static gboolean on_resize(void *opaque, 
 		priv->null_cursor = create_null_cursor();
 		if (priv->local_pointer)
 			do_pointer_show(obj);
-		else
+		else if (!priv->absolute)
 			do_pointer_hide(obj);
 		priv->gc = gdk_gc_new(GTK_WIDGET(obj)->window);
 	}
@@ -832,12 +933,18 @@ static gboolean on_resize(void *opaque, 
 
 	gvnc_set_local(priv->gvnc, &priv->fb);
 
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_DESKTOP_RESIZE],
-		       0,
-		       width, height);
+	if (!quiet) {
+		s.width = width;
+		s.height = height;
+		emit_signal_delayed(obj, VNC_DESKTOP_RESIZE, &s);
+	}
 
 	return TRUE;
+}
+
+static gboolean on_resize(void *opaque, int width, int height)
+{
+	return do_resize(opaque, width, height, FALSE);
 }
 
 #if WITH_GTKGLEXT
@@ -925,7 +1032,7 @@ static void scale_display(VncDisplay *ob
 		image = priv->image;
 		priv->image = NULL;
 	
-		on_resize(obj, priv->fb.width, priv->fb.height);
+		do_resize(obj, priv->fb.width, priv->fb.height, TRUE);
 		build_gl_image_from_gdk((uint32_t *)priv->fb.data, image);
 
 		g_object_unref(image);
@@ -968,7 +1075,7 @@ static void rescale_display(VncDisplay *
 		data = priv->gl_tex_data;
 		priv->gl_tex_data = NULL;
 
-		on_resize(GTK_WIDGET(obj), priv->fb.width, priv->fb.height);
+		do_resize(GTK_WIDGET(obj), priv->fb.width, priv->fb.height, TRUE);
 
 		build_gdk_image_from_gl(priv->image, (uint32_t *)data);
 		gdk_gl_drawable_gl_begin(priv->gl_drawable,
@@ -1006,6 +1113,7 @@ static gboolean on_auth_cred(void *opaqu
 	VncDisplay *obj = VNC_DISPLAY(opaque);
 	GValueArray *cred_list;
 	GValue username, password, clientname;
+	struct signal_data s;
 
 	memset(&username, 0, sizeof(username));
 	memset(&password, 0, sizeof(password));
@@ -1028,10 +1136,8 @@ static gboolean on_auth_cred(void *opaqu
 		cred_list = g_value_array_append(cred_list, &clientname);
 	}
 
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_AUTH_CREDENTIAL],
-		       0,
-		       cred_list);
+	s.cred_list = cred_list;
+	emit_signal_delayed(obj, VNC_AUTH_CREDENTIAL, &s);
 
 	g_value_array_free(cred_list);
 
@@ -1071,11 +1177,10 @@ static gboolean on_auth_failure(void *op
 static gboolean on_auth_failure(void *opaque, const char *msg)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
-
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_AUTH_FAILURE],
-		       0,
-		       msg);
+	struct signal_data s;
+
+	s.msg = msg;
+	emit_signal_delayed(obj, VNC_AUTH_FAILURE, &s);
 
 	return TRUE;
 }
@@ -1083,11 +1188,10 @@ static gboolean on_auth_unsupported(void
 static gboolean on_auth_unsupported(void *opaque, unsigned int auth_type)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
-
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_AUTH_UNSUPPORTED],
-		       0,
-		       auth_type);
+	struct signal_data s;
+
+	s.auth_type = auth_type;
+	emit_signal_delayed(obj, VNC_AUTH_UNSUPPORTED, &s);
 
 	return TRUE;
 }
@@ -1096,11 +1200,10 @@ static gboolean on_server_cut_text(void 
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
 	GString *str = g_string_new_len ((const gchar *)text, len);
-
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_SERVER_CUT_TEXT],
-		       0,
-		       str->str);
+	struct signal_data s;
+
+	s.str = str;
+	emit_signal_delayed(obj, VNC_SERVER_CUT_TEXT, &s);
 
 	g_string_free (str, TRUE);
 	return TRUE;
@@ -1109,10 +1212,9 @@ static gboolean on_bell(void *opaque)
 static gboolean on_bell(void *opaque)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
-
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_BELL],
-		       0);
+	struct signal_data s;
+
+	emit_signal_delayed(obj, VNC_BELL, &s);
 
 	return TRUE;
 }
@@ -1239,8 +1341,8 @@ static void *vnc_coroutine(void *opaque)
 				GVNC_ENCODING_RAW };
 	int32_t *encodingsp;
 	int n_encodings;
-
 	int ret;
+	struct signal_data s;
 
 	if (priv->gvnc == NULL || gvnc_is_open(priv->gvnc)) {
 		g_idle_add(delayed_unref_object, obj);
@@ -1256,17 +1358,13 @@ static void *vnc_coroutine(void *opaque)
 			goto cleanup;
 	}
 
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_CONNECTED],
-		       0);
+	emit_signal_delayed(obj, VNC_CONNECTED, &s);
 
 	GVNC_DEBUG("Protocol initialization\n");
 	if (!gvnc_initialize(priv->gvnc, FALSE))
 		goto cleanup;
 
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_INITIALIZED],
-		       0);
+	emit_signal_delayed(obj, VNC_INITIALIZED, &s);
 
 	encodingsp = encodings;
 	n_encodings = ARRAY_SIZE(encodings);
@@ -1297,9 +1395,7 @@ static void *vnc_coroutine(void *opaque)
  cleanup:
 	GVNC_DEBUG("Doing final VNC cleanup\n");
 	gvnc_close(priv->gvnc);
-	g_signal_emit (G_OBJECT (obj),
-		       signals[VNC_DISCONNECTED],
-		       0);
+	emit_signal_delayed(obj, VNC_DISCONNECTED, &s);
 	g_idle_add(delayed_unref_object, obj);
 	/* Co-routine exits now - the VncDisplay object may no longer exist,
 	   so don't do anything else now unless you like SEGVs */
@@ -1810,7 +1906,7 @@ void vnc_display_set_pointer_local(VncDi
 	if (obj->priv->gc) {
 		if (enable)
 			do_pointer_show(obj);
-		else
+		else if (obj->priv->in_pointer_grab || obj->priv->absolute)
 			do_pointer_hide(obj);
 	}
 	obj->priv->local_pointer = enable;
@@ -1823,8 +1919,6 @@ void vnc_display_set_pointer_grab(VncDis
 	priv->grab_pointer = enable;
 	if (!enable && priv->absolute && priv->in_pointer_grab)
 		do_pointer_ungrab(obj, FALSE);
-	if (enable && priv->absolute && !priv->in_pointer_grab)
-		do_pointer_grab(obj, FALSE);
 }
 
 void vnc_display_set_keyboard_grab(VncDisplay *obj, gboolean enable)
@@ -1834,9 +1928,6 @@ void vnc_display_set_keyboard_grab(VncDi
 	priv->grab_keyboard = enable;
 	if (!enable && priv->in_keyboard_grab && !priv->in_pointer_grab)
 		do_keyboard_ungrab(obj, FALSE);
-	if (enable && !priv->in_keyboard_grab)
-		do_keyboard_grab(obj, FALSE);
-
 }
 
 void vnc_display_set_read_only(VncDisplay *obj, gboolean enable)
diff -r 01b34fbc6e99 -r aaaaa7173d47 src/vncdisplay.h
--- a/src/vncdisplay.h	Mon Feb 18 13:46:54 2008 -0500
+++ b/src/vncdisplay.h	Mon Feb 18 15:04:43 2008 -0500
@@ -107,6 +107,8 @@ void		vnc_display_set_lossy_encoding(Vnc
 
 gboolean	vnc_display_set_scaling(VncDisplay *obj, gboolean enable);
 
+void		vnc_display_force_grab(VncDisplay *obj, gboolean enable);
+
 G_END_DECLS
 
 #endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]