[gtk-vnc-devel] PATCH: Fix gtk-vnc keymap translation for evdev
- From: "Daniel P. Berrange" <berrange redhat com>
- To: gtk-vnc-devel <gtk-vnc-devel lists sourceforge net>
- Subject: [gtk-vnc-devel] PATCH: Fix gtk-vnc keymap translation for evdev
- Date: Thu, 27 Nov 2008 11:42:26 +0000
This is an update of my previous patch to support evdev in gtk-vnc. The
patch takes the evdev keycode translation tables from the Ubuntu gtk-vnc
patch, but changes the logic so it caches the current keymap, rather than
requerying for evdev on each key event
Daniel
diff --git a/src/gvnc.c b/src/gvnc.c
--- a/src/gvnc.c
+++ b/src/gvnc.c
@@ -50,7 +50,6 @@
#include <gdk/gdkkeysyms.h>
-#include "vnc_keycodes.h"
#include "getaddrinfo.h"
/* AI_ADDRCONFIG is missing on some systems and gnulib won't provide it
@@ -183,6 +182,7 @@ struct gvnc
int zrle_pi_bits;
gboolean has_ext_key_event;
+ const uint8_t const *keycode_map;
};
#define nibhi(a) (((a) >> 4) & 0x0F)
@@ -936,11 +936,9 @@ gboolean gvnc_key_event(struct gvnc *gvn
{
uint8_t pad[2] = {0};
+ GVNC_DEBUG("Key event %d %d %d %d", key, scancode, down_flag, gvnc->has_ext_key_event);
if (gvnc->has_ext_key_event) {
- if (key == GDK_Pause)
- scancode = VKC_PAUSE;
- else
- scancode = x_keycode_to_pc_keycode(scancode);
+ scancode = x_keycode_to_pc_keycode(gvnc->keycode_map, scancode);
gvnc_buffered_write_u8(gvnc, 255);
gvnc_buffered_write_u8(gvnc, 0);
@@ -1956,6 +1954,11 @@ static void gvnc_xcursor(struct gvnc *gv
g_free(pixbuf);
}
+static void gvnc_ext_key_event(struct gvnc *gvnc)
+{
+ gvnc->has_ext_key_event = TRUE;
+ gvnc->keycode_map = x_keycode_to_pc_keycode_map();
+}
static void gvnc_framebuffer_update(struct gvnc *gvnc, int32_t etype,
uint16_t x, uint16_t y,
@@ -2006,7 +2009,7 @@ static void gvnc_framebuffer_update(stru
gvnc_xcursor(gvnc, x, y, width, height);
break;
case GVNC_ENCODING_EXT_KEY_EVENT:
- gvnc->has_ext_key_event = TRUE;
+ gvnc_ext_key_event(gvnc);
break;
default:
GVNC_DEBUG("Received an unknown encoding type: %d\n", etype);
diff --git a/src/x_keymap.c b/src/x_keymap.c
--- a/src/x_keymap.c
+++ b/src/x_keymap.c
@@ -1,5 +1,19 @@
/*
- * QEMU SDL display driver
+ * Copyright (C) 2008 Anthony Liguori <anthony codemonkey ws>
+ *
+ * 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 <gdk/gdkkeysyms.h>
+#include "x_keymap.h"
+#include "utils.h"
+#include "vnc_keycodes.h"
+
+/*
+ * This table is taken from QEMU x_keymap.c, under the terms:
*
* Copyright (c) 2003 Fabrice Bellard
*
@@ -22,110 +36,139 @@
* THE SOFTWARE.
*/
-/*
- * Adapted for gtk-vnc from QEMU x_keymap.c revision 1.3 (on 20080113)
- *
- * Copyright (C) 2008 Anthony Liguori <anthony codemonkey ws>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.0 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+static const uint8_t x_keycode_to_pc_keycode_table[61] = {
+ 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 */
+ 0, /* 110 Pause */
+ 0xb7, /* 111 Print */
+ 0xb5, /* 112 Divide */
+ 0xb8, /* 113 Alt-R */
+ 0xc6, /* 114 Break */
+ 0, /* 115 */
+ 0, /* 116 */
+ 0, /* 117 */
+ 0, /* 118 */
+ 0, /* 119 */
+ 0, /* 120 */
+ 0, /* 121 */
+ 0, /* 122 */
+ 0, /* 123 */
+ 0, /* 124 */
+ 0, /* 125 */
+ 0, /* 126 */
+ 0, /* 127 */
+ 0, /* 128 */
+ 0x79, /* 129 Henkan */
+ 0, /* 130 */
+ 0x7b, /* 131 Muhenkan */
+ 0, /* 132 */
+ 0x7d, /* 133 Yen */
+ 0, /* 134 */
+ 0, /* 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 */
+};
+
+/* This table is generated based off the xfree86 -> scancode mapping above
+ * and the keycode mappings in /usr/share/X11/xkb/keycodes/evdev
+ * and /usr/share/X11/xkb/keycodes/xfree86
*/
-#include "x_keymap.h"
-#include <gdk/gdkkeysyms.h>
+static const uint8_t evdev_keycode_to_pc_keycode[61] = {
+ 0, /* 97 EVDEV - RO ("Internet" Keyboards) */
+ 0, /* 98 EVDEV - KATA (Katakana) */
+ 0, /* 99 EVDEV - HIRA (Hiragana) */
+ 0x79, /* 100 EVDEV - HENK (Henkan) */
+ 0x70, /* 101 EVDEV - HKTG (Hiragana/Katakana toggle) */
+ 0x7b, /* 102 EVDEV - MUHE (Muhenkan) */
+ 0, /* 103 EVDEV - JPCM (KPJPComma) */
+ 0x9c, /* 104 KPEN */
+ 0x9d, /* 105 RCTL */
+ 0xb5, /* 106 KPDV */
+ 0xb7, /* 107 PRSC */
+ 0xb8, /* 108 RALT */
+ 0, /* 109 EVDEV - LNFD ("Internet" Keyboards) */
+ 0xc7, /* 110 HOME */
+ 0xc8, /* 111 UP */
+ 0xc9, /* 112 PGUP */
+ 0xcb, /* 113 LEFT */
+ 0xcd, /* 114 RGHT */
+ 0xcf, /* 115 END */
+ 0xd0, /* 116 DOWN */
+ 0xd1, /* 117 PGDN */
+ 0xd2, /* 118 INS */
+ 0xd3, /* 119 DELE */
+ 0, /* 120 EVDEV - I120 ("Internet" Keyboards) */
+ 0, /* 121 EVDEV - MUTE */
+ 0, /* 122 EVDEV - VOL- */
+ 0, /* 123 EVDEV - VOL+ */
+ 0, /* 124 EVDEV - POWR */
+ 0, /* 125 EVDEV - KPEQ */
+ 0, /* 126 EVDEV - I126 ("Internet" Keyboards) */
+ 0, /* 127 EVDEV - PAUS */
+ 0, /* 128 EVDEV - ???? */
+ 0, /* 129 EVDEV - I129 ("Internet" Keyboards) */
+ 0xf1, /* 130 EVDEV - HNGL (Korean Hangul Latin toggle) */
+ 0xf2, /* 131 EVDEV - HJCV (Korean Hangul Hanja toggle) */
+ 0x7d, /* 132 AE13 (Yen)*/
+ 0xdb, /* 133 EVDEV - LWIN */
+ 0xdc, /* 134 EVDEV - RWIN */
+ 0xdd, /* 135 EVDEV - MENU */
+ 0, /* 136 EVDEV - STOP */
+ 0, /* 137 EVDEV - AGAI */
+ 0, /* 138 EVDEV - PROP */
+ 0, /* 139 EVDEV - UNDO */
+ 0, /* 140 EVDEV - FRNT */
+ 0, /* 141 EVDEV - COPY */
+ 0, /* 142 EVDEV - OPEN */
+ 0, /* 143 EVDEV - PAST */
+ 0, /* 144 EVDEV - FIND */
+ 0, /* 145 EVDEV - CUT */
+ 0, /* 146 EVDEV - HELP */
+ 0, /* 147 EVDEV - I147 */
+ 0, /* 148 EVDEV - I148 */
+ 0, /* 149 EVDEV - I149 */
+ 0, /* 150 EVDEV - I150 */
+ 0, /* 151 EVDEV - I151 */
+ 0, /* 152 EVDEV - I152 */
+ 0, /* 153 EVDEV - I153 */
+ 0, /* 154 EVDEV - I154 */
+ 0, /* 155 EVDEV - I156 */
+ 0, /* 156 EVDEV - I157 */
+ 0, /* 157 EVDEV - I158 */
+};
-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 */
-};
/* keycode translation for sending ISO_Left_Send
* to vncserver
@@ -138,20 +181,81 @@ static struct {
static unsigned int ref_count_for_untranslated_keys = 0;
-/* FIXME N.B. on Windows, gtk probably returns PC scan codes */
+/* 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 */
-uint8_t x_keycode_to_pc_keycode(int keycode)
+#ifndef WIN32
+#include <gdk/gdkx.h>
+#include <X11/XKBlib.h>
+#include <stdbool.h>
+#include <string.h>
+
+#define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
+
+static gboolean check_for_evdev(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;
+
+ 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;
+}
+#else
+static gboolean check_for_evdev(void)
+{
+ return FALSE;
+}
+#endif
+
+const uint8_t const *x_keycode_to_pc_keycode_map(void)
+{
+ if (check_for_evdev()) {
+ GVNC_DEBUG("Using evdev keycode mapping");
+ return evdev_keycode_to_pc_keycode;
+ } else {
+ GVNC_DEBUG("Using xfree86 keycode mapping");
+ return x_keycode_to_pc_keycode_table;
+ }
+}
+
+uint16_t x_keycode_to_pc_keycode(const uint8_t const *keycode_map,
+ uint16_t keycode)
+{
+ if (keycode == GDK_Pause)
+ return VKC_PAUSE;
+
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 0;
- return keycode;
+ if (keycode < 97)
+ return keycode - 8; /* just an offset */
+
+ if (keycode < 158)
+ return keycode_map[keycode - 97];
+
+ if (keycode == 208) /* Hiragana_Katakana */
+ return 0x70;
+
+ if (keycode == 211) /* backslash */
+ return 0x73;
+
+ return 0;
}
/* Set the keymap entries */
@@ -194,3 +298,10 @@ guint x_keymap_get_keyval_from_keycode(g
return keyval;
}
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff --git a/src/x_keymap.h b/src/x_keymap.h
--- a/src/x_keymap.h
+++ b/src/x_keymap.h
@@ -24,7 +24,9 @@
#include <stdint.h>
#include <gdk/gdk.h>
-uint8_t x_keycode_to_pc_keycode(int keycode);
+const uint8_t const *x_keycode_to_pc_keycode_map(void);
+uint16_t x_keycode_to_pc_keycode(const uint8_t *keycode_map,
+ uint16_t 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);
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
[
Date Prev][
Date Next] [
Thread Prev][Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]