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



Rob Stoddard wrote:
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;
+        }
+}
+

The formatting here is bad.

 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);
 }
+
+

Please don't introduce extraneous whitespace like this.

 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.");

There's no indentation here? Please separate functionality from additional debugging in the future.


In general, I'm not a big fan of this approach. You're achieving a couple notable things. I do think we should scale the cursor image but I think we should do it by pre-scaling an image and setting that as the cursor. GTK will handle drawing the cursor for us if necessary. I'm not really concerned about having hardware accelerated cursor.

In terms of supporting the warping encoding, I think we need to make it optional and disabled by default. The problem is that a malicious (or broken) server can trap your cursor by constantly warping. You can disable the richcursor encoding without disabling tight which should address your use-case FWIW.

Regards,

Anthony LIguori

 		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)) {

------------------------------------------------------------------------

-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
------------------------------------------------------------------------

_______________________________________________
Gtk-vnc-devel mailing list
Gtk-vnc-devel lists sourceforge net
https://lists.sourceforge.net/lists/listinfo/gtk-vnc-devel





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