[gtk-vnc-devel] Mouse pointer patch, take 2



Sorry about tarring and gzipping a set of patches... first time submitting patches as such. I usually don't make changes to libraries. Here's the combined patch. I really don't consider it a complete fix for everybody's needs, it's a good start to getting the pointer motion in Tight. OpenGL works, wasn't able to get the Gdk image to draw... I don't know Gdk well enough and don't have the time to figure out what's going on in there. I hope somebody can make the Gdk portion work.

What I've implemented is a software cursor. The reason for this is because I intend to use more than one VNC per computer, so the mouse pointer will bounce around between the VNC displays. I also think that scaling wouldn't look very good with a "hardware" cursor... The cursor wouldn't scale with the rest of the display. I also fixed up the OpenGL code a little; the vertecies and projection was based upon the texture size, not the framebuffer size... that caused some rather interesting issues with the mouse pointer position.

Have fun,

Rob Stoddard
diff -uNr gtk-vnc-0.3.5/src/gvnc.c gtk-vnc-mine/src/gvnc.c
--- gtk-vnc-0.3.5/src/gvnc.c	2008-04-06 15:35:22.000000000 -0700
+++ gtk-vnc-mine/src/gvnc.c	2008-04-08 15:59:54.000000000 -0700
@@ -1858,6 +1858,18 @@
 	}
 }
 
+
+static void gvnc_pointer_pos_change(struct gvnc *gvnc, int x, int y)
+{
+	if(gvnc->has_error || !gvnc->ops.pointer_pos_change)
+                return;
+	if (!gvnc->ops.pointer_pos_change(gvnc->ops_data, x, y)) 
+	{
+                GVNC_DEBUG("Closing the connection: gvnc_pointer_pos_change\n");
+                gvnc->has_error = TRUE;
+        }
+}
+
 static void gvnc_rich_cursor_blt(struct gvnc *gvnc, uint8_t *pixbuf,
 				 uint8_t *image, uint8_t *mask,
 				 int pitch, uint16_t width, uint16_t height)
@@ -1865,6 +1877,8 @@
 	gvnc->rich_cursor_blt(gvnc, pixbuf, image, mask, pitch, width, height);
 }
 
+
+
 static void gvnc_rich_cursor(struct gvnc *gvnc, int x, int y, int width, int height)
 {
 	uint8_t *pixbuf = NULL;
@@ -2021,6 +2035,9 @@
 	case GVNC_ENCODING_EXT_KEY_EVENT:
 		gvnc->has_ext_key_event = TRUE;
 		break;
+	case GVNC_ENCODING_CURSOR_POS:
+		gvnc_pointer_pos_change(gvnc, x, y);
+		break;
 	default:
 		GVNC_DEBUG("Received an unknown encoding type: %d\n", etype);
 		gvnc->has_error = TRUE;
@@ -2046,6 +2063,8 @@
 		}
 	} while ((ret = gvnc_read_u8_interruptable(gvnc, &msg)) == -EAGAIN);
 
+	GVNC_DEBUG("Got char %d for message type.\n", msg);
+
 	if (ret < 0) {
 		GVNC_DEBUG("Aborting message processing on error\n");
 		return !gvnc_has_error(gvnc);
@@ -2056,7 +2075,7 @@
 		uint8_t pad[1];
 		uint16_t n_rects;
 		int i;
-
+GVNC_DEBUG("Framebuffer update.");
 		gvnc_read(gvnc, pad, 1);
 		n_rects = gvnc_read_u16(gvnc);
 		for (i = 0; i < n_rects; i++) {
@@ -2077,7 +2096,7 @@
 		uint16_t n_colors;
 		uint8_t pad[1];
 		int i;
-
+GVNC_DEBUG("Colormap entries");
 		gvnc_read(gvnc, pad, 1);
 		first_color = gvnc_read_u16(gvnc);
 		n_colors = gvnc_read_u16(gvnc);
@@ -2095,13 +2114,14 @@
 		}
 	}	break;
 	case 2: /* Bell */
+GVNC_DEBUG("Bell.");
 		gvnc_bell(gvnc);
 		break;
 	case 3: { /* ServerCutText */
 		uint8_t pad[3];
 		uint32_t n_text;
 		char *data;
-
+GVNC_DEBUG("Server cut text.");
 		gvnc_read(gvnc, pad, 3);
 		n_text = gvnc_read_u32(gvnc);
 		if (n_text > (32 << 20)) {
diff -uNr gtk-vnc-0.3.5/src/gvnc.h gtk-vnc-mine/src/gvnc.h
--- gtk-vnc-0.3.5/src/gvnc.h	2008-03-11 09:26:04.000000000 -0700
+++ gtk-vnc-mine/src/gvnc.h	2008-04-08 15:41:03.000000000 -0700
@@ -23,6 +23,7 @@
 	gboolean (*resize)(void *, int, int);
         gboolean (*pixel_format)(void *, struct gvnc_pixel_format *);
 	gboolean (*pointer_type_change)(void *, int);
+	gboolean (*pointer_pos_change)(void*, int, int);
 	gboolean (*local_cursor)(void *, int, int, int, int, uint8_t *);
 	gboolean (*auth_unsupported)(void *, unsigned int);
 	gboolean (*render_jpeg)(void *, rgb24_render_func *render, void *,
@@ -90,6 +91,7 @@
 	GVNC_ENCODING_DESKTOP_RESIZE = -223,
         GVNC_ENCODING_WMVi = 0x574D5669,
 
+	
 	GVNC_ENCODING_CURSOR_POS = -232,
 	GVNC_ENCODING_RICH_CURSOR = -239,
 	GVNC_ENCODING_XCURSOR = -240,
diff -uNr gtk-vnc-0.3.5/src/vncdisplay.c gtk-vnc-mine/src/vncdisplay.c
--- gtk-vnc-0.3.5/src/vncdisplay.c	2008-04-06 15:35:22.000000000 -0700
+++ gtk-vnc-mine/src/vncdisplay.c	2008-04-09 09:51:57.000000000 -0700
@@ -41,6 +41,7 @@
 	char *port;
 	GdkGC *gc;
 	GdkImage *image;
+	GdkPixbuf *ptr_image;
 	GdkCursor *null_cursor;
 	GdkCursor *remote_cursor;
 
@@ -55,6 +56,11 @@
 	int gl_width;
 	int gl_height;
 	GLuint gl_tex;
+	GLuint gl_ptr_tex;
+	int ptr_width;
+	int ptr_height;
+	int ptr_x;
+	int ptr_y;
 #endif
 
 	struct gvnc_framebuffer fb;
@@ -292,7 +298,15 @@
 	if (priv->gl_enabled) {
 		float rx, ry;
 		int wx = 0, wy = 0;
-		int ww = priv->gl_width, wh = priv->gl_height;
+		int ww = priv->fb.width;
+		int wh = priv->fb.height;
+
+		int px = priv->last_x - priv->ptr_x;
+		int py = priv->fb.height - priv->last_y + priv->ptr_y - priv->ptr_height;
+
+		int pw = priv->ptr_width;
+		int ph = priv->ptr_height;
+
 		double scale_x, scale_y;
 
 		scale_x = (double)priv->gl_width / priv->fb.width;
@@ -320,7 +334,10 @@
 		w -= x;
 		h -= y;
 
+
 		gdk_gl_drawable_gl_begin(priv->gl_drawable, priv->gl_context);
+		glEnable(GL_TEXTURE_2D);
+		glDisable(GL_DEPTH_TEST);
 		glBindTexture(GL_TEXTURE_2D, priv->gl_tex);
 		glPixelStorei(GL_UNPACK_ROW_LENGTH, priv->fb.width);
 		glTexSubImage2D(GL_TEXTURE_2D, 0,
@@ -332,16 +349,30 @@
 				x * 4);
 		rx = (float)priv->fb.width  / priv->gl_texture_width;
 		ry = (float)priv->fb.height / priv->gl_texture_height;
-		
-		glEnable(GL_TEXTURE_2D);
-		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
+		glEnable(GL_BLEND);	
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+		/*  Draw the screen  */
 		glBegin(GL_QUADS);
 		glTexCoord2f(0,ry);  glVertex3f(wx, wy, 0);
 		glTexCoord2f(0,0);  glVertex3f(wx, wy+wh, 0);
 		glTexCoord2f(rx,0);  glVertex3f(wx+ww, wy+wh, 0);
 		glTexCoord2f(rx,ry);  glVertex3f(wx+ww, wy, 0);
-		glEnd();		
+		glEnd();
+
+		glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+
+		/*  Draw the pointer  */
+		glBindTexture(GL_TEXTURE_2D, priv->gl_ptr_tex);
+
+		glBegin(GL_QUADS);
+                glTexCoord2f(0.0f, 1.0f);  glVertex3f(px, py, 0.0f);
+                glTexCoord2f(0.0f, 0.0f);  glVertex3f(px, py+ph, 0.0f);
+                glTexCoord2f(1.0f, 0.0f);  glVertex3f(px+pw, py+ph, 0.0f);
+                glTexCoord2f(1.0f, 1.0f);  glVertex3f(px+pw, py, 0.0f);
+                glEnd();
+		glEnable(GL_DEPTH_TEST);
 		glDisable(GL_TEXTURE_2D);
+		glDisable(GL_BLEND);
 		glFlush();
 		gdk_gl_drawable_gl_end(priv->gl_drawable);
 	} else
@@ -378,9 +409,16 @@
 		gdk_region_subtract(clear, copy);
 
 		gdk_gc_set_clip_region(priv->gc, copy);
+
+		/*  Draw the screen  */
 		gdk_draw_image(widget->window, priv->gc, priv->image,
 			       x, y, x + mx, y + my, w, h);
 
+		/* draw the pointer image */
+		if(priv->ptr_image)
+			gdk_draw_pixbuf(widget->window, priv->gc, priv->ptr_image,
+				0, 0, priv->last_x, priv->fb.height - priv->last_y, priv->ptr_width, priv->ptr_height, GDK_RGB_DITHER_NONE, 0, 0);
+
 		gdk_gc_set_clip_region(priv->gc, clear);
 		gdk_draw_rectangle(widget->window, priv->gc, TRUE, expose->area.x, expose->area.y,
 				   expose->area.width, expose->area.height);
@@ -900,6 +938,10 @@
 	gdk_gl_drawable_gl_begin(priv->gl_drawable, priv->gl_context);
 
 	glGenTextures(1, &priv->gl_tex);
+	glGenTextures(1, &priv->gl_ptr_tex);
+	glBindTexture(GL_TEXTURE_2D, priv->gl_ptr_tex);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 	glBindTexture(GL_TEXTURE_2D, priv->gl_tex);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -1160,7 +1202,7 @@
 	glViewport(0, 0, priv->gl_width, priv->gl_height);
 	glMatrixMode(GL_PROJECTION);
 	glLoadIdentity();
-	glOrtho(0.0, priv->gl_width, 0.0, priv->gl_height, -1, 1);
+	glOrtho(0.0, priv->fb.width, 0.0, priv->fb.height, -1, 1);
 	glMatrixMode(GL_MODELVIEW);
 	glLoadIdentity();
 	gdk_gl_drawable_gl_end(priv->gl_drawable);
@@ -1224,6 +1266,20 @@
 	return TRUE;
 }
 
+
+static gboolean on_pointer_pos_change(void *opaque, int x, int y)
+{
+	GtkWidget *widget = GTK_WIDGET(opaque);
+	VncDisplay *obj = VNC_DISPLAY(opaque);
+        VncDisplayPrivate *priv = obj->priv;
+
+	priv->last_x = x;
+	priv->last_y = y;
+
+	gtk_widget_queue_draw_area(widget, x, priv->fb.height - y, 32, 32);
+}
+
+
 static gboolean on_auth_cred(void *opaque)
 {
 	VncDisplay *obj = VNC_DISPLAY(opaque);
@@ -1345,17 +1401,28 @@
 		priv->remote_cursor = NULL;
 	}
 
-	if (width && height) {
+	if (width && height) 
+	{
 		GdkDisplay *display = gdk_drawable_get_display(GDK_DRAWABLE(GTK_WIDGET(obj)->window));
-		GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(image, GDK_COLORSPACE_RGB,
+		priv->ptr_image = gdk_pixbuf_new_from_data(image, GDK_COLORSPACE_RGB,
 							     TRUE, 8, width, height,
 							     width * 4, NULL, NULL);
-		priv->remote_cursor = gdk_cursor_new_from_pixbuf(display,
-								 pixbuf,
-								 x, y);
-		gdk_pixbuf_unref(pixbuf);
 	}
-
+#if WITH_GTKGLEXT
+        if (priv->gl_enabled) 
+	{
+		priv->ptr_width = width;
+		priv->ptr_height = height;
+		priv->ptr_x = x;
+		priv->ptr_y = y;
+		gdk_gl_drawable_gl_begin(priv->gl_drawable, priv->gl_context);
+		glEnable(GL_TEXTURE_2D);
+		glBindTexture(GL_TEXTURE_2D, priv->gl_ptr_tex);
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
+		glDisable(GL_TEXTURE_2D);
+		gdk_gl_drawable_gl_end(priv->gl_drawable);
+	}
+#endif
 	if (priv->in_pointer_grab) {
 		do_pointer_ungrab(obj, TRUE);
 		do_pointer_grab(obj, TRUE);
@@ -1420,6 +1487,7 @@
 	.resize = on_resize,
         .pixel_format = on_pixel_format,
 	.pointer_type_change = on_pointer_type_change,
+	.pointer_pos_change = on_pointer_pos_change,
 	.local_cursor = on_local_cursor,
 	.auth_unsupported = on_auth_unsupported,
 	.server_cut_text = on_server_cut_text,
@@ -1456,7 +1524,8 @@
 				GVNC_ENCODING_HEXTILE,
 				GVNC_ENCODING_RRE,
 				GVNC_ENCODING_COPY_RECT,
-				GVNC_ENCODING_RAW };
+				GVNC_ENCODING_RAW,
+				GVNC_ENCODING_CURSOR_POS };
 	int32_t *encodingsp;
 	int n_encodings;
 	int ret;
@@ -2063,6 +2132,7 @@
 	priv->grab_pointer = FALSE;
 	priv->grab_keyboard = FALSE;
 	priv->local_pointer = FALSE;
+	priv->ptr_image = NULL;
 
 #if WITH_GTKGLEXT
 	if (gtk_gl_init_check(NULL, NULL)) {


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