qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH][RFC] Fix SDL on evdev hosts


From: Anthony Liguori
Subject: [Qemu-devel] [PATCH][RFC] Fix SDL on evdev hosts
Date: Fri, 27 Feb 2009 11:34:34 -0600

This patch corrects SDL support on X11 hosts using evdev.  It's losely based
on the previous patch by Dustin Kirkland and the evdev support code in gtk-vnc
written by Daniel Berrange.

I've tried to take into account all past feedback from previous patches posted
including a proper set of configure checks.  I've tested this on win32 but
I'd like some more eyes to look at it.

Signed-off-by: Anthony Liguori <address@hidden>

diff --git a/configure b/configure
index 62925d8..faacb8d 100755
--- a/configure
+++ b/configure
@@ -187,6 +187,7 @@ kerneldir=""
 aix="no"
 blobs="yes"
 fdt="yes"
+sdl_x11="no"
 
 # OS specific
 if check_define __linux__ ; then
@@ -805,6 +806,21 @@ else
     fi
 fi # -z $sdl
 
+if test "$sdl" = "yes" ; then
+cat > $TMPC <<EOF
+#include <SDL.h>
+#if defined(SDL_VIDEO_DRIVER_X11)
+#include <X11/XKBlib.h>
+#else
+#error No x11 support
+#endif
+int main(void) { return 0; }
+EOF
+    if $cc $ARCH_CFLAGS -o $TMPE ${OS_CFLAGS} `$sdl_config --cflags 2> 
/dev/null` $TMPC `$sdl_config --libs 2> /dev/null` > /dev/null 2>&1 ; then
+       sdl_x11="yes"
+    fi
+fi
+
 ##########################################
 # VNC TLS detection
 if test "$vnc_tls" = "yes" ; then
@@ -1393,6 +1409,8 @@ if test "$sdl1" = "yes" ; then
   echo "CONFIG_SDL=yes" >> $config_mak
   if test "$target_softmmu" = "no" -o "$static" = "yes"; then
     echo "SDL_LIBS=$sdl_static_libs" >> $config_mak
+  elif test "$sdl_x11" = "yes" ; then
+    echo "SDL_LIBS=`$sdl_config --libs` -lX11" >> $config_mak
   else
     echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak
   fi
diff --git a/console.h b/console.h
index 4a2f06f..8f438e9 100644
--- a/console.h
+++ b/console.h
@@ -292,9 +292,6 @@ void do_info_vnc(void);
 /* curses.c */
 void curses_display_init(DisplayState *ds, int full_screen);
 
-/* x_keymap.c */
-extern uint8_t _translate_keycode(const int key);
-
 /* FIXME: term_printf et al should probably go elsewhere so everything
    does not need to include console.h  */
 /* monitor.c */
diff --git a/sdl.c b/sdl.c
index 266fbcc..c685b81 100644
--- a/sdl.c
+++ b/sdl.c
@@ -24,8 +24,10 @@
 #include "qemu-common.h"
 #include "console.h"
 #include "sysemu.h"
+#include "x_keymap.h"
 
 #include <SDL.h>
+#include <SDL/SDL_syswm.h>
 
 #ifndef _WIN32
 #include <signal.h>
@@ -136,9 +138,54 @@ static uint8_t sdl_keyevent_to_keycode(const 
SDL_KeyboardEvent *ev)
 
 #else
 
+#if defined(SDL_VIDEO_DRIVER_X11)
+#include <X11/XKBlib.h>
+
+static int check_for_evdev(void)
+{
+    SDL_SysWMinfo info;
+    XkbDescPtr desc;
+    int has_evdev = 0;
+    const char *keycodes;
+
+    SDL_VERSION(&info.version);
+    if (!SDL_GetWMInfo(&info))
+        return 0;
+
+    desc = XkbGetKeyboard(info.info.x11.display,
+                          XkbGBN_AllComponentsMask,
+                          XkbUseCoreKbd);
+    if (desc == NULL || desc->names == NULL)
+        return 0;
+
+    keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
+    if (keycodes == NULL)
+        fprintf(stderr, "could not lookup keycode name\n");
+    else if (strstart(keycodes, "evdev_", NULL))
+        has_evdev = 1;
+    else if (!strstart(keycodes, "xfree86_", NULL))
+        fprintf(stderr,
+                "unknown keycodes `%s', please report to address@hidden",
+                keycodes);
+
+    XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
+
+    return has_evdev;
+}
+#else
+static int check_for_evdev(void)
+{
+       return 0;
+}
+#endif
+
 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
 {
     int keycode;
+    static int has_evdev = -1;
+
+    if (has_evdev == -1)
+        has_evdev = check_for_evdev();
 
     keycode = ev->keysym.scancode;
 
@@ -146,9 +193,16 @@ static uint8_t sdl_keyevent_to_keycode(const 
SDL_KeyboardEvent *ev)
         keycode = 0;
     } else if (keycode < 97) {
         keycode -= 8; /* just an offset */
-    } else if (keycode < 212) {
+    } else if (keycode < 158) {
         /* use conversion table */
-        keycode = _translate_keycode(keycode - 97);
+        if (has_evdev)
+            keycode = translate_evdev_keycode(keycode - 97);
+        else
+            keycode = translate_xfree86_keycode(keycode - 97);
+    } else if (keycode == 208) { /* Hiragana_Katakana */
+        keycode = 0x70;
+    } else if (keycode == 211) { /* backslash */
+        keycode = 0x73;
     } else {
         keycode = 0;
     }
diff --git a/x_keymap.c b/x_keymap.c
index f000475..b9b0944 100644
--- a/x_keymap.c
+++ b/x_keymap.c
@@ -22,7 +22,7 @@
  * THE SOFTWARE.
  */
 #include "qemu-common.h"
-#include "console.h"
+#include "x_keymap.h"
 
 static const uint8_t x_keycode_to_pc_keycode[115] = {
    0xc7,      /*  97  Home   */
@@ -86,27 +86,83 @@ static const uint8_t x_keycode_to_pc_keycode[115] = {
    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 */
 };
 
-uint8_t _translate_keycode(const int key)
+/* 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
+ */
+
+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 */
+};
+
+uint8_t translate_xfree86_keycode(const int key)
+{
+    return x_keycode_to_pc_keycode[key];
+}
+
+uint8_t translate_evdev_keycode(const int key)
 {
-       return x_keycode_to_pc_keycode[key];
+    return evdev_keycode_to_pc_keycode[key];
 }
diff --git a/x_keymap.h b/x_keymap.h
new file mode 100644
index 0000000..ecc59ab
--- /dev/null
+++ b/x_keymap.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+#ifndef _QEMU_X_KEYMAP_H
+#define _QEMU_X_KEYMAP_H
+
+extern uint8_t translate_xfree86_keycode(const int key);
+
+extern uint8_t translate_evdev_keycode(const int key);
+
+#endif
+




reply via email to

[Prev in Thread] Current Thread [Next in Thread]