> Done. It would be rather nice if the fixes from the ubuntu gtk-vnc
> package would find it's way into debian eventually.
> Cheers,
>  -- Guido

Sure. The attached patch is almost all the delta between the Debian and the
Ubuntu packages (that and an updated shlibs in debian/rules due to a new symbol
added in 0.3.3).

The patch description, quoting Soren Hansen:
11:28 <     soren> pochu: The patch enables an extension to the VNC protocol
that sends key codes rather than keysyms over the wire. This alleviates
practially all problems you might encounter if you're not using US keymapping
everywhere.

The patch comes from upstream, but isn't in upstream's tree yet.

If you need help with gtk-vnc maintenance I could lend you a hand with it.

Regards,
Emilio
diff -Nur -x '*.orig' -x '*~' gtk-vnc-0.3.3/src/gvnc.c gtk-vnc-0.3.3.new/src/gvnc.c
--- gtk-vnc-0.3.3/src/gvnc.c	2008-02-13 11:57:00.649165000 +0100
+++ gtk-vnc-0.3.3.new/src/gvnc.c	2008-02-13 11:58:27.612665381 +0100
@@ -31,6 +31,8 @@
 #include "coroutine.h"
 #include "d3des.h"
 
+#include "x_keymap.h"
+
 #include "utils.h"
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
@@ -158,6 +160,8 @@
 
 	uint8_t zrle_pi;
 	int zrle_pi_bits;
+
+	gboolean has_ext_key_event;
 };
 
 #define nibhi(a) (((a) >> 4) & 0x0F)
@@ -815,6 +819,7 @@
 	uint8_t pad[1] = {0};
 	int i;
 
+	gvnc->has_ext_key_event = FALSE;
 	gvnc_write_u8(gvnc, 2);
 	gvnc_write(gvnc, pad, 1);
 	gvnc_write_u16(gvnc, n_encoding);
@@ -879,14 +884,33 @@
 	g_io_wakeup(&gvnc->wait);
 }
 
-gboolean gvnc_key_event(struct gvnc *gvnc, uint8_t down_flag, uint32_t key)
+gboolean gvnc_key_event(struct gvnc *gvnc, uint8_t down_flag,
+			uint32_t key, uint16_t scancode)
 {
 	uint8_t pad[2] = {0};
 
-	gvnc_buffered_write_u8(gvnc, 4);
-	gvnc_buffered_write_u8(gvnc, down_flag);
-	gvnc_buffered_write(gvnc, pad, 2);
-	gvnc_buffered_write_u32(gvnc, key);
+	if (gvnc->has_ext_key_event) {
+		scancode = x_keycode_to_pc_keycode(scancode);
+
+		gvnc_buffered_write_u8(gvnc, 255);
+		gvnc_buffered_write_u8(gvnc, 0);
+		gvnc_buffered_write_u16(gvnc, down_flag);
+		gvnc_buffered_write_u32(gvnc, key);
+		gvnc_buffered_write_u32(gvnc, scancode);
+	} else {
+		gvnc_buffered_write_u8(gvnc, 4);
+		gvnc_buffered_write_u8(gvnc, down_flag);
+		gvnc_buffered_write(gvnc, pad, 2);
+		gvnc_buffered_write_u32(gvnc, key);
+	}
+
+	gvnc_buffered_flush(gvnc);
+	return !gvnc_has_error(gvnc);
+}
+
+gboolean gvnc_key_event_scancode(struct gvnc *gvnc, uint8_t down_flag,
+				 uint16_t scancode)
+{
 	gvnc_buffered_flush(gvnc);
 	return !gvnc_has_error(gvnc);
 }
@@ -1884,6 +1908,9 @@
 	case GVNC_ENCODING_XCURSOR:
 		gvnc_xcursor(gvnc, x, y, width, height);
 		break;
+	case GVNC_ENCODING_EXT_KEY_EVENT:
+		gvnc->has_ext_key_event = TRUE;
+		break;
 	default:
 		GVNC_DEBUG("Received an unknown encoding type: %d\n", etype);
 		gvnc->has_error = TRUE;
diff -Nur -x '*.orig' -x '*~' gtk-vnc-0.3.3/src/gvnc.h gtk-vnc-0.3.3.new/src/gvnc.h
--- gtk-vnc-0.3.3/src/gvnc.h	2008-02-13 11:57:00.653174000 +0100
+++ gtk-vnc-0.3.3.new/src/gvnc.h	2008-02-13 11:58:27.612665381 +0100
@@ -89,6 +89,7 @@
 	GVNC_ENCODING_XCURSOR = -240,
 
 	GVNC_ENCODING_POINTER_CHANGE = -257,
+	GVNC_ENCODING_EXT_KEY_EVENT = -258,
 } gvnc_encoding;
 
 typedef enum {
@@ -149,7 +150,8 @@
 gboolean gvnc_pointer_event(struct gvnc *gvnc, uint8_t button_mask,
 			    uint16_t x, uint16_t y);
 
-gboolean gvnc_key_event(struct gvnc *gvnc, uint8_t down_flag, uint32_t key);
+gboolean gvnc_key_event(struct gvnc *gvnc, uint8_t down_flag,
+			uint32_t key, uint16_t scancode);
 
 gboolean gvnc_framebuffer_update_request(struct gvnc *gvnc,
 					 uint8_t incremental,
diff -Nur -x '*.orig' -x '*~' gtk-vnc-0.3.3/src/Makefile.am gtk-vnc-0.3.3.new/src/Makefile.am
--- gtk-vnc-0.3.3/src/Makefile.am	2008-02-13 11:57:00.649165000 +0100
+++ gtk-vnc-0.3.3.new/src/Makefile.am	2008-02-13 11:58:27.612665381 +0100
@@ -12,7 +12,7 @@
                             -version-info 0:1:0
 
 gtk_vnc_includedir = $(includedir)/gtk-vnc-1.0/
-gtk_vnc_include_HEADERS = vncdisplay.h gvnc.h
+gtk_vnc_include_HEADERS = vncdisplay.h
 
 libgtk_vnc_1_0_la_SOURCES = blt.h blt1.h \
 	coroutine.h \
@@ -20,6 +20,7 @@
 	gvnc.h gvnc.c \
 	vncdisplay.h vncdisplay.c \
         vncmarshal.h vncmarshal.c \
+	x_keymap.h x_keymap.c \
 	utils.h
 
 if WITH_UCONTEXT
diff -Nur -x '*.orig' -x '*~' gtk-vnc-0.3.3/src/vncdisplay.c gtk-vnc-0.3.3.new/src/vncdisplay.c
--- gtk-vnc-0.3.3/src/vncdisplay.c	2008-02-13 11:57:00.653174000 +0100
+++ gtk-vnc-0.3.3.new/src/vncdisplay.c	2008-02-13 11:58:27.612665381 +0100
@@ -47,6 +47,7 @@
 	gboolean in_keyboard_grab;
 
 	guint down_keyval[16];
+	guint down_scancode[16];
 
 	int button_mask;
 	int last_x;
@@ -418,8 +419,9 @@
 		for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
 			if (priv->down_keyval[i] == 0) {
 				priv->down_keyval[i] = keyval;
+				priv->down_scancode[i] = key->hardware_keycode;
 				/* Send the actual key event we're dealing with */
-				gvnc_key_event(priv->gvnc, 1, keyval);
+				gvnc_key_event(priv->gvnc, 1, keyval, key->hardware_keycode);
 				break;
 			} else if (priv->down_keyval[i] == keyval) {
 				/* Got an press when we're already pressed ! Why ... ?
@@ -431,9 +433,9 @@
 				 * them into a sensible stream of press+release pairs
 				 */
 				/* Fake an up event for the previous down event */
-				gvnc_key_event(priv->gvnc, 0, keyval);
+				gvnc_key_event(priv->gvnc, 0, keyval, key->hardware_keycode);
 				/* Now send our actual ldown event */
-				gvnc_key_event(priv->gvnc, 1, keyval);
+				gvnc_key_event(priv->gvnc, 1, keyval, key->hardware_keycode);
 			}
 		}
 	} else {
@@ -442,8 +444,9 @@
 			/* We were pressed, and now we're released, so... */
 			if (priv->down_keyval[i] == keyval) {
 				priv->down_keyval[i] = 0;
+				priv->down_scancode[i] = 0;
 				/* ..send the key releae event we're dealing with */
-				gvnc_key_event(priv->gvnc, 0, keyval);
+				gvnc_key_event(priv->gvnc, 0, keyval, key->hardware_keycode);
 				break;
 			}
 		}
@@ -509,8 +512,10 @@
 		/* We are currently pressed so... */
 		if (priv->down_keyval[i] != 0) {
 			/* ..send the fake key releae event to match */
-			gvnc_key_event(priv->gvnc, 0, priv->down_keyval[i]);
+			gvnc_key_event(priv->gvnc, 0,
+				       priv->down_keyval[i], priv->down_scancode[i]);
 			priv->down_keyval[i] = 0;
+			priv->down_scancode[i] = 0;
 		}
 	}
 
@@ -814,6 +819,7 @@
 	/* this order is extremely important! */
 	int32_t encodings[] = {	GVNC_ENCODING_TIGHT_JPEG5,
 				GVNC_ENCODING_TIGHT,
+				GVNC_ENCODING_EXT_KEY_EVENT,
 				GVNC_ENCODING_DESKTOP_RESIZE,
 				GVNC_ENCODING_RICH_CURSOR,
 				GVNC_ENCODING_XCURSOR,
@@ -982,21 +988,40 @@
 				 nkeyvals, VNC_DISPLAY_KEY_EVENT_CLICK);
 }
 
+static guint get_keycode_from_keyval(guint keyval)
+{
+	guint keycode = 0;
+	GdkKeymapKey *keys = NULL;
+	gint n_keys = 0;
+
+	if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(),
+					      keyval, &keys, &n_keys)) {
+		/* FIXME what about levels? */
+		keycode = keys[0].keycode;
+		g_free(keys);
+	}
+
+	return keycode;
+}
+
 void vnc_display_send_keys_ex(VncDisplay *obj, const guint *keyvals,
 			      int nkeyvals, VncDisplayKeyEvent kind)
 {
 	int i;
+
 	if (obj->priv->gvnc == NULL || !gvnc_is_open(obj->priv->gvnc))
 		return;
 
 	if (kind & VNC_DISPLAY_KEY_EVENT_PRESS) {
 		for (i = 0 ; i < nkeyvals ; i++)
-			gvnc_key_event(obj->priv->gvnc, 1, keyvals[i]);
+			gvnc_key_event(obj->priv->gvnc, 1, keyvals[i],
+				       get_keycode_from_keyval(keyvals[i]));
 	}
 
 	if (kind & VNC_DISPLAY_KEY_EVENT_RELEASE) {
 		for (i = (nkeyvals-1) ; i >= 0 ; i--)
-			gvnc_key_event(obj->priv->gvnc, 0, keyvals[i]);
+			gvnc_key_event(obj->priv->gvnc, 0, keyvals[i],
+				       get_keycode_from_keyval(keyvals[i]));
 	}
 }
 
diff -Nur -x '*.orig' -x '*~' gtk-vnc-0.3.3/src/x_keymap.c gtk-vnc-0.3.3.new/src/x_keymap.c
--- gtk-vnc-0.3.3/src/x_keymap.c	1970-01-01 01:00:00.000000000 +0100
+++ gtk-vnc-0.3.3.new/src/x_keymap.c	2008-02-13 11:58:27.612665381 +0100
@@ -0,0 +1,133 @@
+/*
+ * QEMU SDL display driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/*
+ * Adapted for gtk-vnc from QEMU x_keymap.c revision 1.3 (on 20080113)
+ *
+ * Copyright (C) 2008  Anthony Liguori <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "x_keymap.h"
+
+static const uint8_t x_keycode_to_pc_keycode_table[115] = {
+   0xc7,      /*  97  Home   */
+   0xc8,      /*  98  Up     */
+   0xc9,      /*  99  PgUp   */
+   0xcb,      /* 100  Left   */
+   0x4c,        /* 101  KP-5   */
+   0xcd,      /* 102  Right  */
+   0xcf,      /* 103  End    */
+   0xd0,      /* 104  Down   */
+   0xd1,      /* 105  PgDn   */
+   0xd2,      /* 106  Ins    */
+   0xd3,      /* 107  Del    */
+   0x9c,      /* 108  Enter  */
+   0x9d,      /* 109  Ctrl-R */
+   0x0,       /* 110  Pause  */
+   0xb7,      /* 111  Print  */
+   0xb5,      /* 112  Divide */
+   0xb8,      /* 113  Alt-R  */
+   0xc6,      /* 114  Break  */
+   0x0,         /* 115 */
+   0x0,         /* 116 */
+   0x0,         /* 117 */
+   0x0,         /* 118 */
+   0x0,         /* 119 */
+   0x0,         /* 120 */
+   0x0,         /* 121 */
+   0x0,         /* 122 */
+   0x0,         /* 123 */
+   0x0,         /* 124 */
+   0x0,         /* 125 */
+   0x0,         /* 126 */
+   0x0,         /* 127 */
+   0x0,         /* 128 */
+   0x79,         /* 129 Henkan */
+   0x0,         /* 130 */
+   0x7b,         /* 131 Muhenkan */
+   0x0,         /* 132 */
+   0x7d,         /* 133 Yen */
+   0x0,         /* 134 */
+   0x0,         /* 135 */
+   0x47,         /* 136 KP_7 */
+   0x48,         /* 137 KP_8 */
+   0x49,         /* 138 KP_9 */
+   0x4b,         /* 139 KP_4 */
+   0x4c,         /* 140 KP_5 */
+   0x4d,         /* 141 KP_6 */
+   0x4f,         /* 142 KP_1 */
+   0x50,         /* 143 KP_2 */
+   0x51,         /* 144 KP_3 */
+   0x52,         /* 145 KP_0 */
+   0x53,         /* 146 KP_. */
+   0x47,         /* 147 KP_HOME */
+   0x48,         /* 148 KP_UP */
+   0x49,         /* 149 KP_PgUp */
+   0x4b,         /* 150 KP_Left */
+   0x4c,         /* 151 KP_ */
+   0x4d,         /* 152 KP_Right */
+   0x4f,         /* 153 KP_End */
+   0x50,         /* 154 KP_Down */
+   0x51,         /* 155 KP_PgDn */
+   0x52,         /* 156 KP_Ins */
+   0x53,         /* 157 KP_Del */
+   0x0,         /* 158 */
+   0x0,         /* 159 */
+   0x0,         /* 160 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 170 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 180 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 190 */
+   0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,         /* 200 */
+   0x0,         /* 201 */
+   0x0,         /* 202 */
+   0x0,         /* 203 */
+   0x0,         /* 204 */
+   0x0,         /* 205 */
+   0x0,         /* 206 */
+   0x0,         /* 207 */
+   0x70,         /* 208 Hiragana_Katakana */
+   0x0,         /* 209 */
+   0x0,         /* 210 */
+   0x73,         /* 211 backslash */
+};
+
+/* FIXME N.B. on Windows, gtk probably returns PC scan codes */
+
+uint8_t x_keycode_to_pc_keycode(int keycode)
+{
+	if (keycode < 9)
+		keycode = 0;
+	else if (keycode < 97)
+		keycode -= 8; /* just an offset */
+	else if (keycode < 212)
+		keycode = x_keycode_to_pc_keycode_table[keycode - 97];
+	else
+		keycode = 0;
+
+	return keycode;
+}
diff -Nur -x '*.orig' -x '*~' gtk-vnc-0.3.3/src/x_keymap.h gtk-vnc-0.3.3.new/src/x_keymap.h
--- gtk-vnc-0.3.3/src/x_keymap.h	1970-01-01 01:00:00.000000000 +0100
+++ gtk-vnc-0.3.3.new/src/x_keymap.h	2008-02-13 11:58:27.616665208 +0100
@@ -0,0 +1,8 @@
+#ifndef _GTK_VNC_X_KEYMAP_H
+#define _GTK_VNC_X_KEYMAP_H
+
+#include <stdint.h>
+
+uint8_t x_keycode_to_pc_keycode(int keycode);
+
+#endif

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to