[PATCH 2/3] Disable extended key events if keymap is unknown



Currently if we cannot determine the GDK keymap, we default to
the XT keymap. This is not a good choice because is causes
definite breakage on several platforms. If the keymap cannot
be determined, it is safer to disable the extended key event
support completely & rely on traditional VNC keysyms.

Also rename the x2pc methods to be gdk2rfb, since that's what
the conversion is actually doing.
---
 src/vncdisplay.c       |   19 ++++++++-----
 src/vncdisplaykeymap.c |   68 +++++++++++++++++++++++++++--------------------
 src/vncdisplaykeymap.h |    6 ++--
 3 files changed, 53 insertions(+), 40 deletions(-)

diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 9ebdd7b..e399b0d 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -752,8 +752,8 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
 	for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
 		/* We were pressed, and now we're released, so... */
 		if (priv->down_scancode[i] == key->hardware_keycode) {
-			guint16 scancode = vnc_display_keymap_x2pc(priv->keycode_map,
-								   key->hardware_keycode);
+			guint16 scancode = vnc_display_keymap_gdk2rfb(priv->keycode_map,
+								      key->hardware_keycode);
 			/*
 			 * ..send the key release event we're dealing with
 			 *
@@ -774,8 +774,8 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
 	if (key->type == GDK_KEY_PRESS) {
 		for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
 			if (priv->down_scancode[i] == 0) {
-				guint16 scancode = vnc_display_keymap_x2pc(priv->keycode_map,
-									   key->hardware_keycode);
+				guint16 scancode = vnc_display_keymap_gdk2rfb(priv->keycode_map,
+									      key->hardware_keycode);
 				priv->down_keyval[i] = keyval;
 				priv->down_scancode[i] = key->hardware_keycode;
 				/* Send the actual key event we're dealing with */
@@ -839,8 +839,8 @@ static gboolean focus_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSE
 	for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
 		/* We are currently pressed so... */
 		if (priv->down_scancode[i] != 0) {
-			guint16 scancode = vnc_display_keymap_x2pc(priv->keycode_map,
-								   priv->down_scancode[i]);
+			guint16 scancode = vnc_display_keymap_gdk2rfb(priv->keycode_map,
+								      priv->down_scancode[i]);
 			/* ..send the fake key release event to match */
 			vnc_connection_key_event(priv->conn, 0,
 						 priv->down_keyval[i], scancode);
@@ -1334,6 +1334,9 @@ static void on_initialized(VncConnection *conn G_GNUC_UNUSED,
 		REMOVE_ENCODING(VNC_CONNECTION_ENCODING_TIGHT);
 	}
 
+	if (priv->keycode_map == NULL)
+		REMOVE_ENCODING(VNC_CONNECTION_ENCODING_EXT_KEY_EVENT);
+
 	VNC_DEBUG("Sending %d encodings", n_encodings);
 	if (!vnc_connection_set_encodings(priv->conn, n_encodings, encodings))
 		goto error;
@@ -1441,7 +1444,7 @@ static guint get_scancode_from_keyval(VncDisplay *obj, guint keyval)
 		g_free(keys);
 	}
 
-	return vnc_display_keymap_x2pc(priv->keycode_map, keycode);
+	return vnc_display_keymap_gdk2rfb(priv->keycode_map, keycode);
 }
 
 void vnc_display_send_keys_ex(VncDisplay *obj, const guint *keyvals,
@@ -1940,7 +1943,7 @@ static void vnc_display_init(VncDisplay *display)
 	g_signal_connect(G_OBJECT(priv->conn), "vnc-disconnected",
 			 G_CALLBACK(on_disconnected), display);
 
-	priv->keycode_map = vnc_display_keymap_x2pc_table();
+	priv->keycode_map = vnc_display_keymap_gdk2rfb_table();
 }
 
 gboolean vnc_display_set_credential(VncDisplay *obj, int type, const gchar *data)
diff --git a/src/vncdisplaykeymap.c b/src/vncdisplaykeymap.c
index f6d87dd..a958737 100644
--- a/src/vncdisplaykeymap.c
+++ b/src/vncdisplaykeymap.c
@@ -37,7 +37,7 @@
  * THE SOFTWARE.
  */
 
-static const guint8 x_keycode_to_pc_keycode_table[61] = {
+static const guint8 xkbd_keycode_to_rfb_keycode_table[61] = {
 	0xc7,      /*  97  Home   */
 	0xc8,      /*  98  Up     */
 	0xc9,      /*  99  PgUp   */
@@ -106,7 +106,7 @@ static const guint8 x_keycode_to_pc_keycode_table[61] = {
  * and  /usr/share/X11/xkb/keycodes/xfree86
  */
 
-static const guint8 evdev_keycode_to_pc_keycode[61] = {
+static const guint8 xevdev_keycode_to_rfb_keycode[61] = {
 	0,         /*  97 EVDEV - RO   ("Internet" Keyboards) */
 	0,         /*  98 EVDEV - KATA (Katakana) */
 	0,         /*  99 EVDEV - HIRA (Hiragana) */
@@ -185,7 +185,7 @@ static unsigned int ref_count_for_untranslated_keys = 0;
 /* As best as I can tell, windows passes PC scan codes.  This code definitely
  * won't compile on windows so let's put in a guard anyway */
 
-#ifndef WIN32
+#if defined(GDK_WINDOWING_X11)
 #include <gdk/gdkx.h>
 #include <X11/XKBlib.h>
 #include <stdbool.h>
@@ -193,47 +193,54 @@ static unsigned int ref_count_for_untranslated_keys = 0;
 
 #define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
 
-static gboolean check_for_evdev(void)
+const guint8 const *vnc_display_keymap_gdk2rfb_table(void)
 {
 	XkbDescPtr desc;
-	gboolean has_evdev = FALSE;
 	const gchar *keycodes;
 
 	desc = XkbGetKeyboard(GDK_DISPLAY(), XkbGBN_AllComponentsMask,
 			      XkbUseCoreKbd);
 	if (desc == NULL || desc->names == NULL)
-		return FALSE;
+		return NULL;
 
 	keycodes = gdk_x11_get_xatom_name(desc->names->keycodes);
-	if (keycodes == NULL)
-		g_warning("could not lookup keycode name\n");
-	else if (STRPREFIX(keycodes, "evdev_"))
-		has_evdev = TRUE;
-	else if (!STRPREFIX(keycodes, "xfree86_"))
-		g_warning("unknown keycodes `%s', please report to gtk-vnc-devel\n",
-			  keycodes);
-
 	XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
 
-	return has_evdev;
+	if (keycodes == NULL) {
+		g_warning("could not lookup keycode name\n");
+		return NULL;
+	} else if (STRPREFIX(keycodes, "e2vdev_")) {
+		VNC_DEBUG("Using evdev keycode mapping");
+		return xevdev_keycode_to_rfb_keycode;
+	} else if (STRPREFIX(keycodes, "xfr2ee86_")) {
+		VNC_DEBUG("Using xfree86 keycode mapping");
+		return xkbd_keycode_to_rfb_keycode_table;
+       } else {
+               g_warning("Unknown keycode mapping.\n"
+                          "Please report to gtk-vnc-list gnome org\n"
+                         "including the following information:\n"
+                         "\n"
+                         "  - Operating system\n"
+                         "  - GTK build\n"
+                         "  - X11 Server\n"
+                         "  - xprop -root\n"
+                         "  - xdpyinfo\n");
+               return NULL;
+	}
 }
 #else
-static gboolean check_for_evdev(void)
+const guint8 const *vnc_display_keymap_gdk2rfb_table(void)
 {
-	return FALSE;
+	g_warning("Unsupported GDK Windowing platform.\n"
+                 "Please report to gtk-vnc-list gnome org\n"
+		  "including the following information:\n"
+		  "\n"
+		  "  - Operating system\n"
+		  "  - GTK Windowing system build\n");
+	return NULL;
 }
 #endif
 
-const guint8 const *vnc_display_keymap_x2pc_table(void)
-{
-	if (check_for_evdev()) {
-		VNC_DEBUG("Using evdev keycode mapping");
-		return evdev_keycode_to_pc_keycode;
-	} else {
-		VNC_DEBUG("Using xfree86 keycode mapping");
-		return x_keycode_to_pc_keycode_table;
-	}
-}
 
 /* All keycodes from 0 to 0xFF correspond to the hardware keycodes generated
  * by a US101 PC keyboard with the following encoding:
@@ -245,9 +252,12 @@ const guint8 const *vnc_display_keymap_x2pc_table(void)
 
 #define VKC_PAUSE	0x100
 
-guint16 vnc_display_keymap_x2pc(const guint8 const *keycode_map,
-				guint16 keycode)
+guint16 vnc_display_keymap_gdk2rfb(const guint8 const *keycode_map,
+				   guint16 keycode)
 {
+	if (keycode_map == NULL)
+		return 0;
+
 	if (keycode == GDK_Pause)
 		return VKC_PAUSE;
 
diff --git a/src/vncdisplaykeymap.h b/src/vncdisplaykeymap.h
index 885902b..ad5b47c 100644
--- a/src/vncdisplaykeymap.h
+++ b/src/vncdisplaykeymap.h
@@ -24,9 +24,9 @@
 
 #include <glib.h>
 
-const guint8 const *vnc_display_keymap_x2pc_table(void);
-guint16 vnc_display_keymap_x2pc(const guint8 *keycode_map,
-				guint16 keycode);
+const guint8 const *vnc_display_keymap_gdk2rfb_table(void);
+guint16 vnc_display_keymap_gdk2rfb(const guint8 *keycode_map,
+				   guint16 keycode);
 void vnc_display_keyval_set_entries(void);
 void vnc_display_keyval_free_entries(void);
 guint vnc_display_keyval_from_keycode(guint keycode, guint keyval);
-- 
1.7.1.1



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