qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

ui: convert GTK and SDL1 frontends to keycodemapdb

The x_keycode_to_pc_keycode and evdev_keycode_to_pc_keycode
tables are replaced with automatically generated tables.
In addition the X11 heuristics are improved to detect running
on XQuartz and XWin X11 servers, to activate the correct OS-X
and Win32 keycode maps.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Message-id: 20180117164717.15855-3-berrange@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

authored by

Daniel P. Berrange and committed by
Gerd Hoffmann
2ec78706 ed7b2624

+300 -317
+7
Makefile
··· 232 232 KEYCODEMAP_CSV = $(SRC_PATH)/ui/keycodemapdb/data/keymaps.csv 233 233 234 234 KEYCODEMAP_FILES = \ 235 + ui/input-keymap-atset1-to-qcode.c \ 235 236 ui/input-keymap-linux-to-qcode.c \ 236 237 ui/input-keymap-qcode-to-qnum.c \ 237 238 ui/input-keymap-qnum-to-qcode.c \ 238 239 ui/input-keymap-qcode-to-linux.c \ 239 240 ui/input-keymap-usb-to-qcode.c \ 241 + ui/input-keymap-win32-to-qcode.c \ 242 + ui/input-keymap-x11-to-qcode.c \ 243 + ui/input-keymap-xorgevdev-to-qcode.c \ 244 + ui/input-keymap-xorgkbd-to-qcode.c \ 245 + ui/input-keymap-xorgxquartz-to-qcode.c \ 246 + ui/input-keymap-xorgxwin-to-qcode.c \ 240 247 $(NULL) 241 248 242 249 GENERATED_FILES += $(KEYCODEMAP_FILES)
+21
include/ui/input.h
··· 68 68 void qemu_add_mouse_mode_change_notifier(Notifier *notify); 69 69 void qemu_remove_mouse_mode_change_notifier(Notifier *notify); 70 70 71 + extern const guint qemu_input_map_atset1_to_qcode_len; 72 + extern const guint16 qemu_input_map_atset1_to_qcode[]; 73 + 71 74 extern const guint qemu_input_map_linux_to_qcode_len; 72 75 extern const guint16 qemu_input_map_linux_to_qcode[]; 73 76 ··· 82 85 83 86 extern const guint qemu_input_map_usb_to_qcode_len; 84 87 extern const guint16 qemu_input_map_usb_to_qcode[]; 88 + 89 + extern const guint qemu_input_map_win32_to_qcode_len; 90 + extern const guint16 qemu_input_map_win32_to_qcode[]; 91 + 92 + extern const guint qemu_input_map_x11_to_qcode_len; 93 + extern const guint16 qemu_input_map_x11_to_qcode[]; 94 + 95 + extern const guint qemu_input_map_xorgevdev_to_qcode_len; 96 + extern const guint16 qemu_input_map_xorgevdev_to_qcode[]; 97 + 98 + extern const guint qemu_input_map_xorgkbd_to_qcode_len; 99 + extern const guint16 qemu_input_map_xorgkbd_to_qcode[]; 100 + 101 + extern const guint qemu_input_map_xorgxquartz_to_qcode_len; 102 + extern const guint16 qemu_input_map_xorgxquartz_to_qcode[]; 103 + 104 + extern const guint qemu_input_map_xorgxwin_to_qcode_len; 105 + extern const guint16 qemu_input_map_xorgxwin_to_qcode[]; 85 106 86 107 #endif /* INPUT_H */
+3 -2
ui/Makefile.objs
··· 11 11 common-obj-y += input.o input-keymap.o input-legacy.o 12 12 common-obj-$(CONFIG_LINUX) += input-linux.o 13 13 common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o 14 - common-obj-$(CONFIG_SDL) += sdl.mo x_keymap.o 14 + common-obj-$(CONFIG_SDL) += sdl.mo 15 15 common-obj-$(CONFIG_COCOA) += cocoa.o 16 16 common-obj-$(CONFIG_CURSES) += curses.o 17 17 common-obj-$(CONFIG_VNC) += $(vnc-obj-y) 18 - common-obj-$(CONFIG_GTK) += gtk.o x_keymap.o 18 + common-obj-$(CONFIG_GTK) += gtk.o 19 + common-obj-$(if $(CONFIG_WIN32),n,$(if $(CONFIG_SDL),y,$(CONFIG_GTK))) += x_keymap.o 19 20 20 21 ifeq ($(CONFIG_SDLABI),1.2) 21 22 sdl.mo-objs := sdl.o sdl_zoom.o
+123 -82
ui/gtk.c
··· 52 52 #include "ui/input.h" 53 53 #include "sysemu/sysemu.h" 54 54 #include "qmp-commands.h" 55 - #include "x_keymap.h" 56 55 #include "keymaps.h" 57 56 #include "chardev/char.h" 58 57 #include "qom/object.h" ··· 65 64 #define VC_SCALE_MIN 0.25 66 65 #define VC_SCALE_STEP 0.25 67 66 67 + #ifdef GDK_WINDOWING_X11 68 + #include "ui/x_keymap.h" 69 + 70 + /* Gtk2 compat */ 71 + #ifndef GDK_IS_X11_DISPLAY 72 + #define GDK_IS_X11_DISPLAY(dpy) (dpy != NULL) 73 + #endif 74 + #endif 75 + 76 + 77 + #ifdef GDK_WINDOWING_WAYLAND 78 + /* Gtk2 compat */ 79 + #ifndef GDK_IS_WAYLAND_DISPLAY 80 + #define GDK_IS_WAYLAND_DISPLAY(dpy) (dpy != NULL) 81 + #endif 82 + #endif 83 + 84 + 85 + #ifdef GDK_WINDOWING_WIN32 86 + /* Gtk2 compat */ 87 + #ifndef GDK_IS_WIN32_DISPLAY 88 + #define GDK_IS_WIN32_DISPLAY(dpy) (dpy != NULL) 89 + #endif 90 + #endif 91 + 92 + 93 + #ifdef GDK_WINDOWING_BROADWAY 94 + /* Gtk2 compat */ 95 + #ifndef GDK_IS_BROADWAY_DISPLAY 96 + #define GDK_IS_BROADWAY_DISPLAY(dpy) (dpy != NULL) 97 + #endif 98 + #endif 99 + 100 + 101 + #ifdef GDK_WINDOWING_QUARTZ 102 + /* Gtk2 compat */ 103 + #ifndef GDK_IS_QUARTZ_DISPLAY 104 + #define GDK_IS_QUARTZ_DISPLAY(dpy) (dpy != NULL) 105 + #endif 106 + #endif 107 + 108 + 68 109 #if !defined(CONFIG_VTE) 69 110 # define VTE_CHECK_VERSION(a, b, c) 0 70 111 #endif ··· 123 164 #define HOTKEY_MODIFIERS (GDK_CONTROL_MASK | GDK_MOD1_MASK) 124 165 125 166 static const int modifier_keycode[] = { 126 - /* shift, control, alt keys, meta keys, both left & right */ 127 - 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, 0xdb, 0xdd, 167 + Q_KEY_CODE_SHIFT, 168 + Q_KEY_CODE_SHIFT_R, 169 + Q_KEY_CODE_CTRL, 170 + Q_KEY_CODE_CTRL_R, 171 + Q_KEY_CODE_ALT, 172 + Q_KEY_CODE_ALT_R, 173 + Q_KEY_CODE_META_L, 174 + Q_KEY_CODE_META_R, 128 175 }; 176 + 177 + static const guint16 *keycode_map; 178 + static size_t keycode_maplen; 129 179 130 180 struct GtkDisplayState { 131 181 GtkWidget *window; ··· 178 228 bool external_pause_update; 179 229 180 230 bool modifier_pressed[ARRAY_SIZE(modifier_keycode)]; 181 - bool has_evdev; 182 231 bool ignore_keys; 183 232 }; 184 233 ··· 412 461 static void gtk_release_modifiers(GtkDisplayState *s) 413 462 { 414 463 VirtualConsole *vc = gd_vc_find_current(s); 415 - int i, keycode; 464 + int i, qcode; 416 465 417 466 if (vc->type != GD_VC_GFX || 418 467 !qemu_console_is_graphic(vc->gfx.dcl.con)) { 419 468 return; 420 469 } 421 470 for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) { 422 - keycode = modifier_keycode[i]; 471 + qcode = modifier_keycode[i]; 423 472 if (!s->modifier_pressed[i]) { 424 473 continue; 425 474 } 426 - qemu_input_event_send_key_number(vc->gfx.dcl.con, keycode, false); 475 + qemu_input_event_send_key_qcode(vc->gfx.dcl.con, qcode, false); 427 476 s->modifier_pressed[i] = false; 428 477 } 429 478 } ··· 1057 1106 return TRUE; 1058 1107 } 1059 1108 1060 - static int gd_map_keycode(GtkDisplayState *s, GdkDisplay *dpy, int gdk_keycode) 1109 + 1110 + static const guint16 *gd_get_keymap(size_t *maplen) 1061 1111 { 1062 - int qemu_keycode; 1112 + GdkDisplay *dpy = gdk_display_get_default(); 1113 + 1114 + #ifdef GDK_WINDOWING_X11 1115 + if (GDK_IS_X11_DISPLAY(dpy)) { 1116 + trace_gd_keymap_windowing("x11"); 1117 + return qemu_xkeymap_mapping_table( 1118 + gdk_x11_display_get_xdisplay(dpy), maplen); 1119 + } 1120 + #endif 1121 + 1122 + #ifdef GDK_WINDOWING_WAYLAND 1123 + if (GDK_IS_WAYLAND_DISPLAY(dpy)) { 1124 + trace_gd_keymap_windowing("wayland"); 1125 + *maplen = qemu_input_map_xorgevdev_to_qcode_len; 1126 + return qemu_input_map_xorgevdev_to_qcode; 1127 + } 1128 + #endif 1063 1129 1064 1130 #ifdef GDK_WINDOWING_WIN32 1065 1131 if (GDK_IS_WIN32_DISPLAY(dpy)) { 1066 - qemu_keycode = MapVirtualKey(gdk_keycode, MAPVK_VK_TO_VSC); 1067 - switch (qemu_keycode) { 1068 - case 103: /* alt gr */ 1069 - qemu_keycode = 56 | SCANCODE_GREY; 1070 - break; 1071 - } 1072 - return qemu_keycode; 1132 + trace_gd_keymap_windowing("win32"); 1133 + *maplen = qemu_input_map_win32_to_qcode_len; 1134 + return qemu_input_map_win32_to_qcode; 1073 1135 } 1074 1136 #endif 1075 1137 1076 - if (gdk_keycode < 9) { 1077 - qemu_keycode = 0; 1078 - } else if (gdk_keycode < 97) { 1079 - qemu_keycode = gdk_keycode - 8; 1080 - #ifdef GDK_WINDOWING_X11 1081 - } else if (GDK_IS_X11_DISPLAY(dpy) && gdk_keycode < 158) { 1082 - if (s->has_evdev) { 1083 - qemu_keycode = translate_evdev_keycode(gdk_keycode - 97); 1084 - } else { 1085 - qemu_keycode = translate_xfree86_keycode(gdk_keycode - 97); 1086 - } 1138 + #ifdef GDK_WINDOWING_QUARTZ 1139 + if (GDK_IS_QUARTZ_DISPLAY(dpy)) { 1140 + trace_gd_keymap_windowing("quartz"); 1141 + *maplen = qemu_input_map_osx_to_qcode_len; 1142 + return qemu_input_map_osx_to_qcode; 1143 + } 1087 1144 #endif 1088 - #ifdef GDK_WINDOWING_WAYLAND 1089 - } else if (GDK_IS_WAYLAND_DISPLAY(dpy) && gdk_keycode < 158) { 1090 - qemu_keycode = translate_evdev_keycode(gdk_keycode - 97); 1145 + 1146 + #ifdef GDK_WINDOWING_BROADWAY 1147 + if (GDK_IS_BROADWAY_DISPLAY(dpy)) { 1148 + trace_gd_keymap_windowing("broadway"); 1149 + g_warning("experimental: using broadway, x11 virtual keysym\n" 1150 + "mapping - with very limited support. See also\n" 1151 + "https://bugzilla.gnome.org/show_bug.cgi?id=700105"); 1152 + *maplen = qemu_input_map_x11_to_qcode_len; 1153 + return qemu_input_map_x11_to_qcode; 1154 + } 1091 1155 #endif 1092 - } else if (gdk_keycode == 208) { /* Hiragana_Katakana */ 1093 - qemu_keycode = 0x70; 1094 - } else if (gdk_keycode == 211) { /* backslash */ 1095 - qemu_keycode = 0x73; 1096 - } else { 1097 - qemu_keycode = 0; 1156 + 1157 + g_warning("Unsupported GDK Windowing platform.\n" 1158 + "Disabling extended keycode tables.\n" 1159 + "Please report to qemu-devel@nongnu.org\n" 1160 + "including the following information:\n" 1161 + "\n" 1162 + " - Operating system\n" 1163 + " - GDK Windowing system build\n"); 1164 + return NULL; 1165 + } 1166 + 1167 + 1168 + static int gd_map_keycode(int scancode) 1169 + { 1170 + if (!keycode_map) { 1171 + return 0; 1172 + } 1173 + if (scancode > keycode_maplen) { 1174 + return 0; 1098 1175 } 1099 1176 1100 - return qemu_keycode; 1177 + return keycode_map[scancode]; 1101 1178 } 1102 1179 1103 1180 static gboolean gd_text_key_down(GtkWidget *widget, ··· 1111 1188 } else if (key->length) { 1112 1189 kbd_put_string_console(con, key->string, key->length); 1113 1190 } else { 1114 - int num = gd_map_keycode(vc->s, gtk_widget_get_display(widget), 1115 - key->hardware_keycode); 1116 - int qcode = qemu_input_key_number_to_qcode(num); 1191 + int qcode = gd_map_keycode(key->hardware_keycode); 1117 1192 kbd_put_qcode_console(con, qcode); 1118 1193 } 1119 1194 return TRUE; ··· 1123 1198 { 1124 1199 VirtualConsole *vc = opaque; 1125 1200 GtkDisplayState *s = vc->s; 1126 - int gdk_keycode = key->hardware_keycode; 1127 - int qemu_keycode; 1201 + int qcode; 1128 1202 int i; 1129 1203 1130 1204 if (s->ignore_keys) { ··· 1138 1212 return TRUE; 1139 1213 } 1140 1214 1141 - qemu_keycode = gd_map_keycode(s, gtk_widget_get_display(widget), 1142 - gdk_keycode); 1215 + qcode = gd_map_keycode(key->hardware_keycode); 1143 1216 1144 - trace_gd_key_event(vc->label, gdk_keycode, qemu_keycode, 1217 + trace_gd_key_event(vc->label, key->hardware_keycode, qcode, 1145 1218 (key->type == GDK_KEY_PRESS) ? "down" : "up"); 1146 1219 1147 1220 for (i = 0; i < ARRAY_SIZE(modifier_keycode); i++) { 1148 - if (qemu_keycode == modifier_keycode[i]) { 1221 + if (qcode == modifier_keycode[i]) { 1149 1222 s->modifier_pressed[i] = (key->type == GDK_KEY_PRESS); 1150 1223 } 1151 1224 } 1152 1225 1153 - qemu_input_event_send_key_number(vc->gfx.dcl.con, qemu_keycode, 1154 - key->type == GDK_KEY_PRESS); 1226 + qemu_input_event_send_key_qcode(vc->gfx.dcl.con, qcode, 1227 + key->type == GDK_KEY_PRESS); 1155 1228 1156 1229 return TRUE; 1157 1230 } ··· 2200 2273 gtk_window_add_accel_group(GTK_WINDOW(s->window), s->accel_group); 2201 2274 } 2202 2275 2203 - static void gd_set_keycode_type(GtkDisplayState *s) 2204 - { 2205 - #ifdef GDK_WINDOWING_X11 2206 - GdkDisplay *display = gtk_widget_get_display(s->window); 2207 - if (GDK_IS_X11_DISPLAY(display)) { 2208 - Display *x11_display = gdk_x11_display_get_xdisplay(display); 2209 - XkbDescPtr desc = XkbGetMap(x11_display, XkbGBN_AllComponentsMask, 2210 - XkbUseCoreKbd); 2211 - char *keycodes = NULL; 2212 - 2213 - if (desc && 2214 - (XkbGetNames(x11_display, XkbKeycodesNameMask, desc) == Success)) { 2215 - keycodes = XGetAtomName(x11_display, desc->names->keycodes); 2216 - } 2217 - if (keycodes == NULL) { 2218 - fprintf(stderr, "could not lookup keycode name\n"); 2219 - } else if (strstart(keycodes, "evdev", NULL)) { 2220 - s->has_evdev = true; 2221 - } else if (!strstart(keycodes, "xfree86", NULL)) { 2222 - fprintf(stderr, "unknown keycodes `%s', please report to " 2223 - "qemu-devel@nongnu.org\n", keycodes); 2224 - } 2225 - 2226 - if (desc) { 2227 - XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); 2228 - } 2229 - if (keycodes) { 2230 - XFree(keycodes); 2231 - } 2232 - } 2233 - #endif 2234 - } 2235 2276 2236 2277 static gboolean gtkinit; 2237 2278 ··· 2339 2380 if (grab_on_hover) { 2340 2381 gtk_menu_item_activate(GTK_MENU_ITEM(s->grab_on_hover_item)); 2341 2382 } 2342 - 2343 - gd_set_keycode_type(s); 2344 2383 } 2345 2384 2346 2385 void early_gtk_display_init(int opengl) ··· 2386 2425 g_assert_not_reached(); 2387 2426 break; 2388 2427 } 2428 + 2429 + keycode_map = gd_get_keymap(&keycode_maplen); 2389 2430 2390 2431 #if defined(CONFIG_VTE) 2391 2432 type_register(&char_gd_vc_type_info);
+7
ui/input-keymap.c
··· 5 5 6 6 #include "standard-headers/linux/input.h" 7 7 8 + #include "ui/input-keymap-atset1-to-qcode.c" 8 9 #include "ui/input-keymap-linux-to-qcode.c" 9 10 #include "ui/input-keymap-qcode-to-qnum.c" 10 11 #include "ui/input-keymap-qnum-to-qcode.c" 11 12 #include "ui/input-keymap-qcode-to-linux.c" 12 13 #include "ui/input-keymap-usb-to-qcode.c" 14 + #include "ui/input-keymap-win32-to-qcode.c" 15 + #include "ui/input-keymap-x11-to-qcode.c" 16 + #include "ui/input-keymap-xorgevdev-to-qcode.c" 17 + #include "ui/input-keymap-xorgkbd-to-qcode.c" 18 + #include "ui/input-keymap-xorgxquartz-to-qcode.c" 19 + #include "ui/input-keymap-xorgxwin-to-qcode.c" 13 20 14 21 int qemu_input_linux_to_qcode(unsigned int lnx) 15 22 {
+31 -74
ui/sdl.c
··· 34 34 #include "ui/console.h" 35 35 #include "ui/input.h" 36 36 #include "sysemu/sysemu.h" 37 + #ifndef WIN32 37 38 #include "x_keymap.h" 39 + #endif 38 40 #include "sdl_zoom.h" 39 41 40 42 static DisplayChangeListener *dcl; ··· 63 65 static int scaling_active = 0; 64 66 static Notifier mouse_mode_notifier; 65 67 static int idle_counter; 68 + static const guint16 *keycode_map; 69 + static size_t keycode_maplen; 66 70 67 71 #define SDL_REFRESH_INTERVAL_BUSY 10 68 72 #define SDL_MAX_IDLE_COUNT (2 * GUI_REFRESH_INTERVAL_DEFAULT \ ··· 208 212 return keysym2scancode(kbd_layout, keysym) & SCANCODE_KEYMASK; 209 213 } 210 214 211 - /* specific keyboard conversions from scan codes */ 212 215 213 - #if defined(_WIN32) 214 - 215 - static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) 216 + static const guint16 *sdl_get_keymap(size_t *maplen) 216 217 { 217 - return ev->keysym.scancode; 218 - } 219 - 218 + #if defined(WIN32) 219 + *maplen = qemu_input_map_atset1_to_qcode_len; 220 + return qemu_input_map_atset1_to_qcode; 220 221 #else 221 - 222 222 #if defined(SDL_VIDEO_DRIVER_X11) 223 - #include <X11/XKBlib.h> 224 - 225 - static int check_for_evdev(void) 226 - { 227 223 SDL_SysWMinfo info; 228 - XkbDescPtr desc = NULL; 229 - int has_evdev = 0; 230 - char *keycodes = NULL; 231 224 232 225 SDL_VERSION(&info.version); 233 - if (!SDL_GetWMInfo(&info)) { 234 - return 0; 226 + if (SDL_GetWMInfo(&info) > 0) { 227 + return qemu_xkeymap_mapping_table( 228 + info.info.x11.display, maplen); 235 229 } 236 - desc = XkbGetMap(info.info.x11.display, 237 - XkbGBN_AllComponentsMask, 238 - XkbUseCoreKbd); 239 - if (desc && 240 - (XkbGetNames(info.info.x11.display, 241 - XkbKeycodesNameMask, desc) == Success)) { 242 - keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes); 243 - if (keycodes == NULL) { 244 - fprintf(stderr, "could not lookup keycode name\n"); 245 - } else if (strstart(keycodes, "evdev", NULL)) { 246 - has_evdev = 1; 247 - } else if (!strstart(keycodes, "xfree86", NULL)) { 248 - fprintf(stderr, "unknown keycodes `%s', please report to " 249 - "qemu-devel@nongnu.org\n", keycodes); 250 - } 251 - } 252 - 253 - if (desc) { 254 - XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); 255 - } 256 - if (keycodes) { 257 - XFree(keycodes); 258 - } 259 - return has_evdev; 230 + #endif 231 + g_warning("Unsupported SDL video driver / platform.\n" 232 + "Assuming Linux KBD scancodes, but probably wrong.\n" 233 + "Please report to qemu-devel@nongnu.org\n" 234 + "including the following information:\n" 235 + "\n" 236 + " - Operating system\n" 237 + " - SDL video driver\n"); 238 + *maplen = qemu_input_map_xorgkbd_to_qcode_len; 239 + return qemu_input_map_xorgkbd_to_qcode; 240 + #endif 260 241 } 261 - #else 262 - static int check_for_evdev(void) 263 - { 264 - return 0; 265 - } 266 - #endif 267 242 268 243 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) 269 244 { 270 - int keycode; 271 - static int has_evdev = -1; 245 + if (!keycode_map) { 246 + return 0; 247 + } 248 + if (ev->keysym.scancode > keycode_maplen) { 249 + return 0; 250 + } 272 251 273 - if (has_evdev == -1) 274 - has_evdev = check_for_evdev(); 275 - 276 - keycode = ev->keysym.scancode; 277 - 278 - if (keycode < 9) { 279 - keycode = 0; 280 - } else if (keycode < 97) { 281 - keycode -= 8; /* just an offset */ 282 - } else if (keycode < 158) { 283 - /* use conversion table */ 284 - if (has_evdev) 285 - keycode = translate_evdev_keycode(keycode - 97); 286 - else 287 - keycode = translate_xfree86_keycode(keycode - 97); 288 - } else if (keycode == 208) { /* Hiragana_Katakana */ 289 - keycode = 0x70; 290 - } else if (keycode == 211) { /* backslash */ 291 - keycode = 0x73; 292 - } else { 293 - keycode = 0; 294 - } 295 - return keycode; 252 + return keycode_map[ev->keysym.scancode]; 296 253 } 297 - 298 - #endif 299 254 300 255 static void reset_keys(void) 301 256 { ··· 994 949 } 995 950 vi = SDL_GetVideoInfo(); 996 951 host_format = *(vi->vfmt); 952 + 953 + keycode_map = sdl_get_keymap(&keycode_maplen); 997 954 998 955 /* Load a 32x32x4 image. White pixels are transparent. */ 999 956 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "qemu-icon.bmp");
+8 -1
ui/trace-events
··· 18 18 # ui/gtk.c 19 19 gd_switch(const char *tab, int width, int height) "tab=%s, width=%d, height=%d" 20 20 gd_update(const char *tab, int x, int y, int w, int h) "tab=%s, x=%d, y=%d, w=%d, h=%d" 21 - gd_key_event(const char *tab, int gdk_keycode, int qemu_keycode, const char *action) "tab=%s, translated GDK keycode %d to QEMU keycode %d (%s)" 21 + gd_key_event(const char *tab, int gdk_keycode, int qkeycode, const char *action) "tab=%s, translated GDK keycode %d to QKeyCode %d (%s)" 22 22 gd_grab(const char *tab, const char *device, const char *reason) "tab=%s, dev=%s, reason=%s" 23 23 gd_ungrab(const char *tab, const char *device) "tab=%s, dev=%s" 24 + gd_keymap_windowing(const char *name) "backend=%s" 24 25 25 26 # ui/vnc.c 26 27 vnc_key_guest_leds(bool caps, bool num, bool scroll) "caps %d, num %d, scroll %d" ··· 79 80 keymap_parse(const char *file) "file %s" 80 81 keymap_add(const char *type, int sym, int code, const char *line) "%-6s sym=0x%04x code=0x%04x (line: %s)" 81 82 keymap_unmapped(int sym) "sym=0x%04x" 83 + 84 + # ui/x_keymap.c 85 + xkeymap_extension(const char *name) "extension '%s'" 86 + xkeymap_vendor(const char *name) "vendor '%s'" 87 + xkeymap_keycodes(const char *name) "keycodes '%s'" 88 + xkeymap_keymap(const char *name) "keymap '%s'"
+96 -154
ui/x_keymap.c
··· 1 1 /* 2 - * QEMU SDL display driver 3 - * 4 - * Copyright (c) 2003 Fabrice Bellard 5 - * 6 - * Permission is hereby granted, free of charge, to any person obtaining a copy 7 - * of this software and associated documentation files (the "Software"), to deal 8 - * in the Software without restriction, including without limitation the rights 9 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 - * copies of the Software, and to permit persons to whom the Software is 11 - * furnished to do so, subject to the following conditions: 2 + * QEMU X11 keymaps 12 3 * 13 - * The above copyright notice and this permission notice shall be included in 14 - * all copies or substantial portions of the Software. 4 + * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com> 5 + * Copyright (C) 2017 Red Hat, Inc 15 6 * 16 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 - * THE SOFTWARE. 7 + * This program is free software; you can redistribute it and/or modify 8 + * it under the terms of the GNU Lesser General Public License version 2 as 9 + * published by the Free Software Foundation. 23 10 */ 11 + 24 12 #include "qemu/osdep.h" 25 - #include "qemu-common.h" 13 + 26 14 #include "x_keymap.h" 15 + #include "trace.h" 16 + #include "qemu/notify.h" 17 + #include "ui/input.h" 27 18 28 - static const uint8_t x_keycode_to_pc_keycode[115] = { 29 - 0xc7, /* 97 Home */ 30 - 0xc8, /* 98 Up */ 31 - 0xc9, /* 99 PgUp */ 32 - 0xcb, /* 100 Left */ 33 - 0x4c, /* 101 KP-5 */ 34 - 0xcd, /* 102 Right */ 35 - 0xcf, /* 103 End */ 36 - 0xd0, /* 104 Down */ 37 - 0xd1, /* 105 PgDn */ 38 - 0xd2, /* 106 Ins */ 39 - 0xd3, /* 107 Del */ 40 - 0x9c, /* 108 Enter */ 41 - 0x9d, /* 109 Ctrl-R */ 42 - 0x0, /* 110 Pause */ 43 - 0xb7, /* 111 Print */ 44 - 0xb5, /* 112 Divide */ 45 - 0xb8, /* 113 Alt-R */ 46 - 0xc6, /* 114 Break */ 47 - 0x0, /* 115 */ 48 - 0x0, /* 116 */ 49 - 0x0, /* 117 */ 50 - 0x0, /* 118 */ 51 - 0x0, /* 119 */ 52 - 0x0, /* 120 */ 53 - 0x0, /* 121 */ 54 - 0x0, /* 122 */ 55 - 0x0, /* 123 */ 56 - 0x0, /* 124 */ 57 - 0x0, /* 125 */ 58 - 0x0, /* 126 */ 59 - 0x0, /* 127 */ 60 - 0x0, /* 128 */ 61 - 0x79, /* 129 Henkan */ 62 - 0x0, /* 130 */ 63 - 0x7b, /* 131 Muhenkan */ 64 - 0x0, /* 132 */ 65 - 0x7d, /* 133 Yen */ 66 - 0x0, /* 134 */ 67 - 0x0, /* 135 */ 68 - 0x47, /* 136 KP_7 */ 69 - 0x48, /* 137 KP_8 */ 70 - 0x49, /* 138 KP_9 */ 71 - 0x4b, /* 139 KP_4 */ 72 - 0x4c, /* 140 KP_5 */ 73 - 0x4d, /* 141 KP_6 */ 74 - 0x4f, /* 142 KP_1 */ 75 - 0x50, /* 143 KP_2 */ 76 - 0x51, /* 144 KP_3 */ 77 - 0x52, /* 145 KP_0 */ 78 - 0x53, /* 146 KP_. */ 79 - 0x47, /* 147 KP_HOME */ 80 - 0x48, /* 148 KP_UP */ 81 - 0x49, /* 149 KP_PgUp */ 82 - 0x4b, /* 150 KP_Left */ 83 - 0x4c, /* 151 KP_ */ 84 - 0x4d, /* 152 KP_Right */ 85 - 0x4f, /* 153 KP_End */ 86 - 0x50, /* 154 KP_Down */ 87 - 0x51, /* 155 KP_PgDn */ 88 - 0x52, /* 156 KP_Ins */ 89 - 0x53, /* 157 KP_Del */ 90 - }; 19 + #include <X11/XKBlib.h> 91 20 92 - /* This table is generated based off the xfree86 -> scancode mapping above 93 - * and the keycode mappings in /usr/share/X11/xkb/keycodes/evdev 94 - * and /usr/share/X11/xkb/keycodes/xfree86 95 - */ 21 + static gboolean check_for_xwin(Display *dpy) 22 + { 23 + const char *vendor = ServerVendor(dpy); 96 24 97 - static const uint8_t evdev_keycode_to_pc_keycode[61] = { 98 - 0x73, /* 97 EVDEV - RO ("Internet" Keyboards) */ 99 - 0, /* 98 EVDEV - KATA (Katakana) */ 100 - 0, /* 99 EVDEV - HIRA (Hiragana) */ 101 - 0x79, /* 100 EVDEV - HENK (Henkan) */ 102 - 0x70, /* 101 EVDEV - HKTG (Hiragana/Katakana toggle) */ 103 - 0x7b, /* 102 EVDEV - MUHE (Muhenkan) */ 104 - 0, /* 103 EVDEV - JPCM (KPJPComma) */ 105 - 0x9c, /* 104 KPEN */ 106 - 0x9d, /* 105 RCTL */ 107 - 0xb5, /* 106 KPDV */ 108 - 0xb7, /* 107 PRSC */ 109 - 0xb8, /* 108 RALT */ 110 - 0, /* 109 EVDEV - LNFD ("Internet" Keyboards) */ 111 - 0xc7, /* 110 HOME */ 112 - 0xc8, /* 111 UP */ 113 - 0xc9, /* 112 PGUP */ 114 - 0xcb, /* 113 LEFT */ 115 - 0xcd, /* 114 RGHT */ 116 - 0xcf, /* 115 END */ 117 - 0xd0, /* 116 DOWN */ 118 - 0xd1, /* 117 PGDN */ 119 - 0xd2, /* 118 INS */ 120 - 0xd3, /* 119 DELE */ 121 - 0, /* 120 EVDEV - I120 ("Internet" Keyboards) */ 122 - 0, /* 121 EVDEV - MUTE */ 123 - 0, /* 122 EVDEV - VOL- */ 124 - 0, /* 123 EVDEV - VOL+ */ 125 - 0, /* 124 EVDEV - POWR */ 126 - 0, /* 125 EVDEV - KPEQ */ 127 - 0, /* 126 EVDEV - I126 ("Internet" Keyboards) */ 128 - 0, /* 127 EVDEV - PAUS */ 129 - 0, /* 128 EVDEV - ???? */ 130 - 0x7e, /* 129 EVDEV - KP_COMMA (brazilian) */ 131 - 0xf1, /* 130 EVDEV - HNGL (Korean Hangul Latin toggle) */ 132 - 0xf2, /* 131 EVDEV - HJCV (Korean Hangul Hanja toggle) */ 133 - 0x7d, /* 132 AE13 (Yen)*/ 134 - 0xdb, /* 133 EVDEV - LWIN */ 135 - 0xdc, /* 134 EVDEV - RWIN */ 136 - 0xdd, /* 135 EVDEV - MENU */ 137 - 0, /* 136 EVDEV - STOP */ 138 - 0, /* 137 EVDEV - AGAI */ 139 - 0, /* 138 EVDEV - PROP */ 140 - 0, /* 139 EVDEV - UNDO */ 141 - 0, /* 140 EVDEV - FRNT */ 142 - 0, /* 141 EVDEV - COPY */ 143 - 0, /* 142 EVDEV - OPEN */ 144 - 0, /* 143 EVDEV - PAST */ 145 - 0, /* 144 EVDEV - FIND */ 146 - 0, /* 145 EVDEV - CUT */ 147 - 0, /* 146 EVDEV - HELP */ 148 - 0, /* 147 EVDEV - I147 */ 149 - 0, /* 148 EVDEV - I148 */ 150 - 0, /* 149 EVDEV - I149 */ 151 - 0, /* 150 EVDEV - I150 */ 152 - 0, /* 151 EVDEV - I151 */ 153 - 0, /* 152 EVDEV - I152 */ 154 - 0, /* 153 EVDEV - I153 */ 155 - 0, /* 154 EVDEV - I154 */ 156 - 0, /* 155 EVDEV - I156 */ 157 - 0, /* 156 EVDEV - I157 */ 158 - 0, /* 157 EVDEV - I158 */ 159 - }; 25 + trace_xkeymap_vendor(vendor); 26 + 27 + if (strstr(vendor, "Cygwin/X")) { 28 + return TRUE; 29 + } 30 + 31 + return FALSE; 32 + } 160 33 161 - uint8_t translate_xfree86_keycode(const int key) 34 + static gboolean check_for_xquartz(Display *dpy) 162 35 { 163 - return x_keycode_to_pc_keycode[key]; 36 + int nextensions; 37 + int i; 38 + gboolean match = FALSE; 39 + char **extensions = XListExtensions(dpy, &nextensions); 40 + for (i = 0 ; extensions != NULL && i < nextensions ; i++) { 41 + trace_xkeymap_extension(extensions[i]); 42 + if (strcmp(extensions[i], "Apple-WM") == 0 || 43 + strcmp(extensions[i], "Apple-DRI") == 0) { 44 + match = TRUE; 45 + } 46 + } 47 + if (extensions) { 48 + XFreeExtensionList(extensions); 49 + } 50 + 51 + return match; 164 52 } 165 53 166 - uint8_t translate_evdev_keycode(const int key) 54 + const guint16 *qemu_xkeymap_mapping_table(Display *dpy, size_t *maplen) 167 55 { 168 - return evdev_keycode_to_pc_keycode[key]; 56 + XkbDescPtr desc; 57 + const gchar *keycodes = NULL; 58 + 59 + /* There is no easy way to determine what X11 server 60 + * and platform & keyboard driver is in use. Thus we 61 + * do best guess heuristics. 62 + * 63 + * This will need more work for people with other 64 + * X servers..... patches welcomed. 65 + */ 66 + 67 + desc = XkbGetMap(dpy, 68 + XkbGBN_AllComponentsMask, 69 + XkbUseCoreKbd); 70 + if (desc) { 71 + if (XkbGetNames(dpy, XkbKeycodesNameMask, desc) == Success) { 72 + keycodes = XGetAtomName (dpy, desc->names->keycodes); 73 + if (!keycodes) { 74 + g_warning("could not lookup keycode name"); 75 + } else { 76 + trace_xkeymap_keycodes(keycodes); 77 + } 78 + } 79 + XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); 80 + } 81 + 82 + if (check_for_xwin(dpy)) { 83 + trace_xkeymap_keymap("xwin"); 84 + *maplen = qemu_input_map_xorgxwin_to_qcode_len; 85 + return qemu_input_map_xorgxwin_to_qcode; 86 + } else if (check_for_xquartz(dpy)) { 87 + trace_xkeymap_keymap("xquartz"); 88 + *maplen = qemu_input_map_xorgxquartz_to_qcode_len; 89 + return qemu_input_map_xorgxquartz_to_qcode; 90 + } else if (keycodes && g_str_has_prefix(keycodes, "evdev")) { 91 + trace_xkeymap_keymap("evdev"); 92 + *maplen = qemu_input_map_xorgevdev_to_qcode_len; 93 + return qemu_input_map_xorgevdev_to_qcode; 94 + } else if (keycodes && g_str_has_prefix(keycodes, "xfree86")) { 95 + trace_xkeymap_keymap("kbd"); 96 + *maplen = qemu_input_map_xorgkbd_to_qcode_len; 97 + return qemu_input_map_xorgkbd_to_qcode; 98 + } else { 99 + trace_xkeymap_keymap("NULL"); 100 + g_warning("Unknown X11 keycode mapping '%s'.\n" 101 + "Please report to qemu-devel@nongnu.org\n" 102 + "including the following information:\n" 103 + "\n" 104 + " - Operating system\n" 105 + " - X11 Server\n" 106 + " - xprop -root\n" 107 + " - xdpyinfo\n", 108 + keycodes ? keycodes : "<null>"); 109 + return NULL; 110 + } 169 111 }
+4 -4
ui/x_keymap.h
··· 1 1 /* 2 - * QEMU SDL display driver 2 + * QEMU X11 keymaps 3 3 * 4 - * Copyright (c) 2003 Fabrice Bellard 4 + * Copyright (c) 2017 Red Hat, Inc. 5 5 * 6 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 7 * of this software and associated documentation files (the "Software"), to deal ··· 25 25 #ifndef QEMU_X_KEYMAP_H 26 26 #define QEMU_X_KEYMAP_H 27 27 28 - uint8_t translate_xfree86_keycode(const int key); 28 + #include <X11/Xlib.h> 29 29 30 - uint8_t translate_evdev_keycode(const int key); 30 + const guint16 *qemu_xkeymap_mapping_table(Display *dpy, size_t *maplen); 31 31 32 32 #endif