[gtk-vnc] Move X keycode -> PC scancode conversion into VncDisplay



commit dee099d33ee070df318086659960245d54bce571
Author: Daniel P. Berrange <berrange redhat com>
Date:   Sat Nov 21 11:48:56 2009 +0000

    Move X keycode -> PC scancode conversion into VncDisplay
    
    The VncConnection class should not depend on anything from GDK.
    The X keycode to PC scancode conversion uses GDK. Therefore it
    had to be moved into the VncDisplay class

 src/Makefile.am                        |    2 +-
 src/vnc_keycodes.h                     |   34 --------------------------------
 src/vncconnection.c                    |    6 -----
 src/vncdisplay.c                       |   34 +++++++++++++++++++++----------
 src/{x_keymap.c => vncdisplaykeymap.c} |   24 ++++++++++++++++------
 src/{x_keymap.h => vncdisplaykeymap.h} |   18 ++++++++--------
 6 files changed, 50 insertions(+), 68 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index cfc5e3f..de75886 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,8 +34,8 @@ libgtk_vnc_1_0_la_SOURCES = blt.h blt1.h \
         vncconnectionenums.h vncconnectionenums.c \
 	vncdisplay.h vncdisplay.c \
         vncdisplayenums.h vncdisplayenums.c \
+	vncdisplaykeymap.h vncdisplaykeymap.c \
         vncmarshal.h vncmarshal.c \
-	x_keymap.h x_keymap.c vnc_keycodes.h \
 	utils.h
 
 if WITH_UCONTEXT
diff --git a/src/vncconnection.c b/src/vncconnection.c
index 8fad4d4..94fb170 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -42,8 +42,6 @@
 #include "coroutine.h"
 #include "d3des.h"
 
-#include "x_keymap.h"
-
 #include "utils.h"
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
@@ -186,7 +184,6 @@ struct _VncConnectionPrivate
 	int zrle_pi_bits;
 
 	gboolean has_ext_key_event;
-	const guint8 const *keycode_map;
 };
 
 G_DEFINE_TYPE(VncConnection, vnc_connection, G_TYPE_OBJECT);
@@ -1417,8 +1414,6 @@ gboolean vnc_connection_key_event(VncConnection *conn, guint8 down_flag,
 
 	GVNC_DEBUG("Key event %d %d %d %d", key, scancode, down_flag, priv->has_ext_key_event);
 	if (priv->has_ext_key_event) {
-		scancode = x_keycode_to_pc_keycode(priv->keycode_map, scancode);
-
 		vnc_connection_buffered_write_u8(conn, 255);
 		vnc_connection_buffered_write_u8(conn, 0);
 		vnc_connection_buffered_write_u16(conn, down_flag);
@@ -2494,7 +2489,6 @@ static void vnc_connection_ext_key_event(VncConnection *conn)
 	VncConnectionPrivate *priv = conn->priv;
 
 	priv->has_ext_key_event = TRUE;
-	priv->keycode_map = x_keycode_to_pc_keycode_map();
 }
 
 static void vnc_connection_framebuffer_update(VncConnection *conn, gint32 etype,
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index 8736948..afd59c2 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -28,7 +28,7 @@
 #include "utils.h"
 #include "vncmarshal.h"
 #include "config.h"
-#include "x_keymap.h"
+#include "vncdisplaykeymap.h"
 #include "vncdisplayenums.h"
 
 #include <gtk/gtk.h>
@@ -90,6 +90,7 @@ struct _VncDisplayPrivate
 	gboolean force_size;
 
 	GSList *preferable_auths;
+	const guint8 const *keycode_map;
 };
 
 /* Delayed signal emission.
@@ -700,7 +701,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
 		   key->type == GDK_KEY_PRESS ? "press" : "release",
 		   key->hardware_keycode, key->state, key->group, keyval);
 
-	keyval = x_keymap_get_keyval_from_keycode(key->hardware_keycode, keyval);
+	keyval = vnc_display_keyval_from_keycode(key->hardware_keycode, keyval);
 
 	/*
 	 * Some VNC suckiness with key state & modifiers in particular
@@ -730,6 +731,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);
 			/*
 			 * ..send the key release event we're dealing with
 			 *
@@ -740,7 +743,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
 			 * true, with "Tab" generating Tab on press, and
 			 * ISO_Prev_Group on release.
 			 */
-			vnc_connection_key_event(priv->conn, 0, priv->down_keyval[i], key->hardware_keycode);
+			vnc_connection_key_event(priv->conn, 0, priv->down_keyval[i], scancode);
 			priv->down_keyval[i] = 0;
 			priv->down_scancode[i] = 0;
 			break;
@@ -750,10 +753,12 @@ 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);
 				priv->down_keyval[i] = keyval;
 				priv->down_scancode[i] = key->hardware_keycode;
 				/* Send the actual key event we're dealing with */
-				vnc_connection_key_event(priv->conn, 1, keyval, key->hardware_keycode);
+				vnc_connection_key_event(priv->conn, 1, keyval, scancode);
 				break;
 			}
 		}
@@ -815,9 +820,11 @@ 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]);
 			/* ..send the fake key release event to match */
 			vnc_connection_key_event(priv->conn, 0,
-				       priv->down_keyval[i], priv->down_scancode[i]);
+						 priv->down_keyval[i], scancode);
 			priv->down_keyval[i] = 0;
 			priv->down_scancode[i] = 0;
 		}
@@ -1310,7 +1317,6 @@ static void *vnc_coroutine(void *opaque)
 	}
 
 	GVNC_DEBUG("Started background coroutine");
-	x_keymap_set_keymap_entries();
 
 	if (priv->fd != -1) {
 		if (!vnc_connection_open_fd(priv->conn, priv->fd))
@@ -1371,7 +1377,6 @@ static void *vnc_coroutine(void *opaque)
 	vnc_connection_close(priv->conn);
 	emit_signal_delayed(obj, VNC_DISCONNECTED, &s);
 	g_idle_add(delayed_unref_object, obj);
-	x_keymap_free_keymap_entries();
 	/* Co-routine exits now - the VncDisplay object may no longer exist,
 	   so don't do anything else now unless you like SEGVs */
 	return NULL;
@@ -1477,8 +1482,9 @@ void vnc_display_send_keys(VncDisplay *obj, const guint *keyvals, int nkeyvals)
 				 nkeyvals, VNC_DISPLAY_KEY_EVENT_CLICK);
 }
 
-static guint get_keycode_from_keyval(guint keyval)
+static guint get_scancode_from_keyval(VncDisplay *obj, guint keyval)
 {
+	VncDisplayPrivate *priv = obj->priv;
 	guint keycode = 0;
 	GdkKeymapKey *keys = NULL;
 	gint n_keys = 0;
@@ -1490,7 +1496,7 @@ static guint get_keycode_from_keyval(guint keyval)
 		g_free(keys);
 	}
 
-	return keycode;
+	return vnc_display_keymap_x2pc(priv->keycode_map, keycode);
 }
 
 void vnc_display_send_keys_ex(VncDisplay *obj, const guint *keyvals,
@@ -1504,13 +1510,13 @@ void vnc_display_send_keys_ex(VncDisplay *obj, const guint *keyvals,
 	if (kind & VNC_DISPLAY_KEY_EVENT_PRESS) {
 		for (i = 0 ; i < nkeyvals ; i++)
 			vnc_connection_key_event(obj->priv->conn, 1, keyvals[i],
-				       get_keycode_from_keyval(keyvals[i]));
+						 get_scancode_from_keyval(obj, keyvals[i]));
 	}
 
 	if (kind & VNC_DISPLAY_KEY_EVENT_RELEASE) {
 		for (i = (nkeyvals-1) ; i >= 0 ; i--)
 			vnc_connection_key_event(obj->priv->conn, 0, keyvals[i],
-				       get_keycode_from_keyval(keyvals[i]));
+						 get_scancode_from_keyval(obj, keyvals[i]));
 	}
 }
 
@@ -1575,6 +1581,8 @@ static void vnc_display_finalize (GObject *obj)
 
 	g_slist_free (priv->preferable_auths);
 
+	vnc_display_keyval_free_entries();
+
 	G_OBJECT_CLASS (vnc_display_parent_class)->finalize (obj);
 }
 
@@ -1894,6 +1902,8 @@ static void vnc_display_init(VncDisplay *display)
 
 	GTK_WIDGET_SET_FLAGS(obj, GTK_CAN_FOCUS);
 
+	vnc_display_keyval_set_entries();
+
 	gtk_widget_add_events(widget,
 			      GDK_POINTER_MOTION_MASK |
 			      GDK_BUTTON_PRESS_MASK |
@@ -1966,6 +1976,8 @@ static void vnc_display_init(VncDisplay *display)
 			 G_CALLBACK(on_auth_choose_type), display);
 	g_signal_connect(G_OBJECT(priv->conn), "vnc-auth-choose-subtype",
 			 G_CALLBACK(on_auth_choose_subtype), display);
+
+	priv->keycode_map = vnc_display_keymap_x2pc_table();
 }
 
 gboolean vnc_display_set_credential(VncDisplay *obj, int type, const gchar *data)
diff --git a/src/x_keymap.c b/src/vncdisplaykeymap.c
similarity index 93%
rename from src/x_keymap.c
rename to src/vncdisplaykeymap.c
index 00e9e45..1c5ecc8 100644
--- a/src/x_keymap.c
+++ b/src/vncdisplaykeymap.c
@@ -7,10 +7,10 @@
  *
  */
 
+#include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
-#include "x_keymap.h"
+#include "vncdisplaykeymap.h"
 #include "utils.h"
-#include "vnc_keycodes.h"
 
 /*
  * This table is taken from QEMU x_keymap.c, under the terms:
@@ -223,7 +223,7 @@ static gboolean check_for_evdev(void)
 }
 #endif
 
-const guint8 const *x_keycode_to_pc_keycode_map(void)
+const guint8 const *vnc_display_keymap_x2pc_table(void)
 {
 	if (check_for_evdev()) {
 		GVNC_DEBUG("Using evdev keycode mapping");
@@ -234,7 +234,17 @@ const guint8 const *x_keycode_to_pc_keycode_map(void)
 	}
 }
 
-guint16 x_keycode_to_pc_keycode(const guint8 const *keycode_map,
+/* All keycodes from 0 to 0xFF correspond to the hardware keycodes generated
+ * by a US101 PC keyboard with the following encoding:
+ *
+ * 0) Sequences of XX are replaced with XX
+ * 1) Sequences of 0xe0 XX are replaces with XX | 0x80
+ * 2) All other keys are defined below
+ */
+
+#define VKC_PAUSE	0x100
+
+guint16 vnc_display_keymap_x2pc(const guint8 const *keycode_map,
 				guint16 keycode)
 {
 	if (keycode == GDK_Pause)
@@ -259,7 +269,7 @@ guint16 x_keycode_to_pc_keycode(const guint8 const *keycode_map,
 }
 
 /* Set the keymap entries */
-void x_keymap_set_keymap_entries()
+void vnc_display_keyval_set_entries(void)
 {
 	size_t i;
 	if (ref_count_for_untranslated_keys == 0)
@@ -272,7 +282,7 @@ void x_keymap_set_keymap_entries()
 }
 
 /* Free the keymap entries */
-void x_keymap_free_keymap_entries()
+void vnc_display_keyval_free_entries(void)
 {
 	size_t i;
 
@@ -287,7 +297,7 @@ void x_keymap_free_keymap_entries()
 }
 
 /* Get the keyval from the keycode without the level. */
-guint x_keymap_get_keyval_from_keycode(guint keycode, guint keyval)
+guint vnc_display_keyval_from_keycode(guint keycode, guint keyval)
 {
 	size_t i;
 	for (i = 0; i < sizeof(untranslated_keys) / sizeof(untranslated_keys[0]); i++) {
diff --git a/src/x_keymap.h b/src/vncdisplaykeymap.h
similarity index 69%
rename from src/x_keymap.h
rename to src/vncdisplaykeymap.h
index b67fe27..4b31e5f 100644
--- a/src/x_keymap.h
+++ b/src/vncdisplaykeymap.h
@@ -18,16 +18,16 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
-#ifndef _GTK_VNC_X_KEYMAP_H
-#define _GTK_VNC_X_KEYMAP_H
+#ifndef VNC_DISPLAY_KEYMAP_H
+#define VNC_DISPLAY_KEYMAP_H
 
-#include <gdk/gdk.h>
+#include <glib.h>
 
-const guint8 const *x_keycode_to_pc_keycode_map(void);
-guint16 x_keycode_to_pc_keycode(const guint8 *keycode_map,
+const guint8 const *vnc_display_keymap_x2pc_table(void);
+guint16 vnc_display_keymap_x2pc(const guint8 *keycode_map,
 				guint16 keycode);
-void x_keymap_set_keymap_entries(void);
-void x_keymap_free_keymap_entries(void);
-guint x_keymap_get_keyval_from_keycode(guint keycode, guint keyval);
+void vnc_display_keyval_set_entries(void);
+void vnc_display_keyval_free_entries(void);
+guint vnc_display_keyval_from_keycode(guint keycode, guint keyval);
 
-#endif
+#endif /* VNC_DISPLAY_KEYMAP_H */



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