1 /* 2 * QEMU X11 keymaps 3 * 4 * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com> 5 * Copyright (C) 2017 Red Hat, Inc 6 * 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.1 as 9 * published by the Free Software Foundation. 10 */ 11 12 #include "qemu/osdep.h" 13 14 #include "x_keymap.h" 15 #include "trace.h" 16 #include "qemu/notify.h" 17 #include "ui/input.h" 18 19 #include <X11/XKBlib.h> 20 #include <X11/Xutil.h> 21 22 static gboolean check_for_xwin(Display *dpy) 23 { 24 const char *vendor = ServerVendor(dpy); 25 26 trace_xkeymap_vendor(vendor); 27 28 if (strstr(vendor, "Cygwin/X")) { 29 return TRUE; 30 } 31 32 return FALSE; 33 } 34 35 static gboolean check_for_xquartz(Display *dpy) 36 { 37 int nextensions; 38 int i; 39 gboolean match = FALSE; 40 char **extensions = XListExtensions(dpy, &nextensions); 41 for (i = 0 ; extensions != NULL && i < nextensions ; i++) { 42 trace_xkeymap_extension(extensions[i]); 43 if (strcmp(extensions[i], "Apple-WM") == 0 || 44 strcmp(extensions[i], "Apple-DRI") == 0) { 45 match = TRUE; 46 } 47 } 48 if (extensions) { 49 XFreeExtensionList(extensions); 50 } 51 52 return match; 53 } 54 55 const guint16 *qemu_xkeymap_mapping_table(Display *dpy, size_t *maplen) 56 { 57 XkbDescPtr desc; 58 const gchar *keycodes = NULL; 59 const guint16 *map; 60 61 /* There is no easy way to determine what X11 server 62 * and platform & keyboard driver is in use. Thus we 63 * do best guess heuristics. 64 * 65 * This will need more work for people with other 66 * X servers..... patches welcomed. 67 */ 68 69 desc = XkbGetMap(dpy, 70 XkbGBN_AllComponentsMask, 71 XkbUseCoreKbd); 72 if (desc) { 73 if (XkbGetNames(dpy, XkbKeycodesNameMask, desc) == Success) { 74 keycodes = XGetAtomName (dpy, desc->names->keycodes); 75 if (!keycodes) { 76 g_warning("could not lookup keycode name"); 77 } else { 78 trace_xkeymap_keycodes(keycodes); 79 } 80 } 81 XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); 82 } 83 84 if (check_for_xwin(dpy)) { 85 trace_xkeymap_keymap("xwin"); 86 *maplen = qemu_input_map_xorgxwin_to_qcode_len; 87 map = qemu_input_map_xorgxwin_to_qcode; 88 } else if (check_for_xquartz(dpy)) { 89 trace_xkeymap_keymap("xquartz"); 90 *maplen = qemu_input_map_xorgxquartz_to_qcode_len; 91 map = qemu_input_map_xorgxquartz_to_qcode; 92 } else if ((keycodes && g_str_has_prefix(keycodes, "evdev")) || 93 (XKeysymToKeycode(dpy, XK_Page_Up) == 0x70)) { 94 trace_xkeymap_keymap("evdev"); 95 *maplen = qemu_input_map_xorgevdev_to_qcode_len; 96 map = qemu_input_map_xorgevdev_to_qcode; 97 } else if ((keycodes && g_str_has_prefix(keycodes, "xfree86")) || 98 (XKeysymToKeycode(dpy, XK_Page_Up) == 0x63)) { 99 trace_xkeymap_keymap("kbd"); 100 *maplen = qemu_input_map_xorgkbd_to_qcode_len; 101 map = qemu_input_map_xorgkbd_to_qcode; 102 } else { 103 trace_xkeymap_keymap("NULL"); 104 g_warning("Unknown X11 keycode mapping '%s'.\n" 105 "Please report to qemu-devel@nongnu.org\n" 106 "including the following information:\n" 107 "\n" 108 " - Operating system\n" 109 " - X11 Server\n" 110 " - xprop -root\n" 111 " - xdpyinfo\n", 112 keycodes ? keycodes : "<null>"); 113 map = NULL; 114 } 115 if (keycodes) { 116 XFree((void *)keycodes); 117 } 118 return map; 119 } 120