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 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 60 /* There is no easy way to determine what X11 server 61 * and platform & keyboard driver is in use. Thus we 62 * do best guess heuristics. 63 * 64 * This will need more work for people with other 65 * X servers..... patches welcomed. 66 */ 67 68 desc = XkbGetMap(dpy, 69 XkbGBN_AllComponentsMask, 70 XkbUseCoreKbd); 71 if (desc) { 72 if (XkbGetNames(dpy, XkbKeycodesNameMask, desc) == Success) { 73 keycodes = XGetAtomName (dpy, desc->names->keycodes); 74 if (!keycodes) { 75 g_warning("could not lookup keycode name"); 76 } else { 77 trace_xkeymap_keycodes(keycodes); 78 } 79 } 80 XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); 81 } 82 83 if (check_for_xwin(dpy)) { 84 trace_xkeymap_keymap("xwin"); 85 *maplen = qemu_input_map_xorgxwin_to_qcode_len; 86 return qemu_input_map_xorgxwin_to_qcode; 87 } else if (check_for_xquartz(dpy)) { 88 trace_xkeymap_keymap("xquartz"); 89 *maplen = qemu_input_map_xorgxquartz_to_qcode_len; 90 return qemu_input_map_xorgxquartz_to_qcode; 91 } else if ((keycodes && g_str_has_prefix(keycodes, "evdev")) || 92 (XKeysymToKeycode(dpy, XK_Page_Up) == 0x70)) { 93 trace_xkeymap_keymap("evdev"); 94 *maplen = qemu_input_map_xorgevdev_to_qcode_len; 95 return qemu_input_map_xorgevdev_to_qcode; 96 } else if ((keycodes && g_str_has_prefix(keycodes, "xfree86")) || 97 (XKeysymToKeycode(dpy, XK_Page_Up) == 0x63)) { 98 trace_xkeymap_keymap("kbd"); 99 *maplen = qemu_input_map_xorgkbd_to_qcode_len; 100 return qemu_input_map_xorgkbd_to_qcode; 101 } else { 102 trace_xkeymap_keymap("NULL"); 103 g_warning("Unknown X11 keycode mapping '%s'.\n" 104 "Please report to qemu-devel@nongnu.org\n" 105 "including the following information:\n" 106 "\n" 107 " - Operating system\n" 108 " - X11 Server\n" 109 " - xprop -root\n" 110 " - xdpyinfo\n", 111 keycodes ? keycodes : "<null>"); 112 return NULL; 113 } 114 } 115