13e230dd2SCorentin Chary /* 22ec78706SDaniel P. Berrange * QEMU X11 keymaps 33e230dd2SCorentin Chary * 42ec78706SDaniel P. Berrange * Copyright (C) 2009-2010 Daniel P. Berrange <dan@berrange.com> 52ec78706SDaniel P. Berrange * Copyright (C) 2017 Red Hat, Inc 63e230dd2SCorentin Chary * 72ec78706SDaniel P. Berrange * This program is free software; you can redistribute it and/or modify 861f3c91aSChetan Pant * it under the terms of the GNU Lesser General Public License version 2.1 as 92ec78706SDaniel P. Berrange * published by the Free Software Foundation. 103e230dd2SCorentin Chary */ 112ec78706SDaniel P. Berrange 12e16f4c87SPeter Maydell #include "qemu/osdep.h" 132ec78706SDaniel P. Berrange 143e230dd2SCorentin Chary #include "x_keymap.h" 152ec78706SDaniel P. Berrange #include "trace.h" 162ec78706SDaniel P. Berrange #include "qemu/notify.h" 172ec78706SDaniel P. Berrange #include "ui/input.h" 183e230dd2SCorentin Chary 192ec78706SDaniel P. Berrange #include <X11/XKBlib.h> 201e70de67SDaniel P. Berrangé #include <X11/Xutil.h> 213e230dd2SCorentin Chary 222ec78706SDaniel P. Berrange static gboolean check_for_xwin(Display *dpy) 233e230dd2SCorentin Chary { 242ec78706SDaniel P. Berrange const char *vendor = ServerVendor(dpy); 252ec78706SDaniel P. Berrange 262ec78706SDaniel P. Berrange trace_xkeymap_vendor(vendor); 272ec78706SDaniel P. Berrange 282ec78706SDaniel P. Berrange if (strstr(vendor, "Cygwin/X")) { 292ec78706SDaniel P. Berrange return TRUE; 303e230dd2SCorentin Chary } 313e230dd2SCorentin Chary 322ec78706SDaniel P. Berrange return FALSE; 332ec78706SDaniel P. Berrange } 342ec78706SDaniel P. Berrange 352ec78706SDaniel P. Berrange static gboolean check_for_xquartz(Display *dpy) 363e230dd2SCorentin Chary { 372ec78706SDaniel P. Berrange int nextensions; 382ec78706SDaniel P. Berrange int i; 392ec78706SDaniel P. Berrange gboolean match = FALSE; 402ec78706SDaniel P. Berrange char **extensions = XListExtensions(dpy, &nextensions); 412ec78706SDaniel P. Berrange for (i = 0 ; extensions != NULL && i < nextensions ; i++) { 422ec78706SDaniel P. Berrange trace_xkeymap_extension(extensions[i]); 432ec78706SDaniel P. Berrange if (strcmp(extensions[i], "Apple-WM") == 0 || 442ec78706SDaniel P. Berrange strcmp(extensions[i], "Apple-DRI") == 0) { 452ec78706SDaniel P. Berrange match = TRUE; 462ec78706SDaniel P. Berrange } 472ec78706SDaniel P. Berrange } 482ec78706SDaniel P. Berrange if (extensions) { 492ec78706SDaniel P. Berrange XFreeExtensionList(extensions); 502ec78706SDaniel P. Berrange } 512ec78706SDaniel P. Berrange 522ec78706SDaniel P. Berrange return match; 532ec78706SDaniel P. Berrange } 542ec78706SDaniel P. Berrange 552ec78706SDaniel P. Berrange const guint16 *qemu_xkeymap_mapping_table(Display *dpy, size_t *maplen) 562ec78706SDaniel P. Berrange { 572ec78706SDaniel P. Berrange XkbDescPtr desc; 582ec78706SDaniel P. Berrange const gchar *keycodes = NULL; 59*7c06a34cSPhilippe Mathieu-Daudé const guint16 *map; 602ec78706SDaniel P. Berrange 612ec78706SDaniel P. Berrange /* There is no easy way to determine what X11 server 622ec78706SDaniel P. Berrange * and platform & keyboard driver is in use. Thus we 632ec78706SDaniel P. Berrange * do best guess heuristics. 642ec78706SDaniel P. Berrange * 652ec78706SDaniel P. Berrange * This will need more work for people with other 662ec78706SDaniel P. Berrange * X servers..... patches welcomed. 672ec78706SDaniel P. Berrange */ 682ec78706SDaniel P. Berrange 692ec78706SDaniel P. Berrange desc = XkbGetMap(dpy, 702ec78706SDaniel P. Berrange XkbGBN_AllComponentsMask, 712ec78706SDaniel P. Berrange XkbUseCoreKbd); 722ec78706SDaniel P. Berrange if (desc) { 732ec78706SDaniel P. Berrange if (XkbGetNames(dpy, XkbKeycodesNameMask, desc) == Success) { 742ec78706SDaniel P. Berrange keycodes = XGetAtomName (dpy, desc->names->keycodes); 752ec78706SDaniel P. Berrange if (!keycodes) { 762ec78706SDaniel P. Berrange g_warning("could not lookup keycode name"); 772ec78706SDaniel P. Berrange } else { 782ec78706SDaniel P. Berrange trace_xkeymap_keycodes(keycodes); 792ec78706SDaniel P. Berrange } 802ec78706SDaniel P. Berrange } 812ec78706SDaniel P. Berrange XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True); 822ec78706SDaniel P. Berrange } 832ec78706SDaniel P. Berrange 842ec78706SDaniel P. Berrange if (check_for_xwin(dpy)) { 852ec78706SDaniel P. Berrange trace_xkeymap_keymap("xwin"); 862ec78706SDaniel P. Berrange *maplen = qemu_input_map_xorgxwin_to_qcode_len; 87*7c06a34cSPhilippe Mathieu-Daudé map = qemu_input_map_xorgxwin_to_qcode; 882ec78706SDaniel P. Berrange } else if (check_for_xquartz(dpy)) { 892ec78706SDaniel P. Berrange trace_xkeymap_keymap("xquartz"); 902ec78706SDaniel P. Berrange *maplen = qemu_input_map_xorgxquartz_to_qcode_len; 91*7c06a34cSPhilippe Mathieu-Daudé map = qemu_input_map_xorgxquartz_to_qcode; 921e70de67SDaniel P. Berrangé } else if ((keycodes && g_str_has_prefix(keycodes, "evdev")) || 931e70de67SDaniel P. Berrangé (XKeysymToKeycode(dpy, XK_Page_Up) == 0x70)) { 942ec78706SDaniel P. Berrange trace_xkeymap_keymap("evdev"); 952ec78706SDaniel P. Berrange *maplen = qemu_input_map_xorgevdev_to_qcode_len; 96*7c06a34cSPhilippe Mathieu-Daudé map = qemu_input_map_xorgevdev_to_qcode; 971e70de67SDaniel P. Berrangé } else if ((keycodes && g_str_has_prefix(keycodes, "xfree86")) || 981e70de67SDaniel P. Berrangé (XKeysymToKeycode(dpy, XK_Page_Up) == 0x63)) { 992ec78706SDaniel P. Berrange trace_xkeymap_keymap("kbd"); 1002ec78706SDaniel P. Berrange *maplen = qemu_input_map_xorgkbd_to_qcode_len; 101*7c06a34cSPhilippe Mathieu-Daudé map = qemu_input_map_xorgkbd_to_qcode; 1022ec78706SDaniel P. Berrange } else { 1032ec78706SDaniel P. Berrange trace_xkeymap_keymap("NULL"); 1042ec78706SDaniel P. Berrange g_warning("Unknown X11 keycode mapping '%s'.\n" 1052ec78706SDaniel P. Berrange "Please report to qemu-devel@nongnu.org\n" 1062ec78706SDaniel P. Berrange "including the following information:\n" 1072ec78706SDaniel P. Berrange "\n" 1082ec78706SDaniel P. Berrange " - Operating system\n" 1092ec78706SDaniel P. Berrange " - X11 Server\n" 1102ec78706SDaniel P. Berrange " - xprop -root\n" 1112ec78706SDaniel P. Berrange " - xdpyinfo\n", 1122ec78706SDaniel P. Berrange keycodes ? keycodes : "<null>"); 113*7c06a34cSPhilippe Mathieu-Daudé map = NULL; 1142ec78706SDaniel P. Berrange } 115*7c06a34cSPhilippe Mathieu-Daudé if (keycodes) { 116*7c06a34cSPhilippe Mathieu-Daudé XFree((void *)keycodes); 117*7c06a34cSPhilippe Mathieu-Daudé } 118*7c06a34cSPhilippe Mathieu-Daudé return map; 1193e230dd2SCorentin Chary } 120