1、当界面触发发送按下的或者释放的按键
void spice_display_send_keys(SpiceDisplay *display, const guint *keyvals,
int nkeyvals, SpiceDisplayKeyEvent kind)
{
int i;
g_return_if_fail(SPICE_IS_DISPLAY(display));
g_return_if_fail(keyvals != NULL);
DISPLAY_DEBUG(display, "%s", __FUNCTION__);
if (kind & SPICE_DISPLAY_KEY_EVENT_PRESS) {
for (i = 0 ; i < nkeyvals ; i++)
send_key(display, get_scancode_from_keyval(display, keyvals[i]), SEND_KEY_PRESS, FALSE);
}
if (kind & SPICE_DISPLAY_KEY_EVENT_RELEASE) {
for (i = (nkeyvals-1) ; i >= 0 ; i--)
send_key(display, get_scancode_from_keyval(display, keyvals[i]), SEND_KEY_RELEASE, FALSE);
}
}
2、通过VNC表获取scancode对应系统的按键值
static guint get_scancode_from_keyval(SpiceDisplay *display, guint keyval)
{
SpiceDisplayPrivate *d = display->priv;
guint keycode = 0;
GdkKeymapKey *keys = NULL;
gint n_keys = 0;
GdkKeymap *keymap = gdk_keymap_get_for_display(gdk_display_get_default());
if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
/* FIXME what about levels? */
keycode = keys[0].keycode;
g_free(keys);
} else {
g_warning("could not lookup keyval %u, please report a bug", keyval);
return 0;
}
return vnc_display_keymap_gdk2xtkbd(d->keycode_map, d->keycode_maplen, keycode);
}
3、进入vncdisplaykeymap.c中,通过指针函数keycode_map相应的值
guint16 vnc_display_keymap_gdk2xtkbd(const guint16 *keycode_map,
size_t keycode_maplen,
guint16 keycode)
{
if (!keycode_map)
return 0;
if (keycode >= keycode_maplen)
return 0;
return keycode_map[keycode];
}
4、给
keycode_map赋值相应系统的对应表
static void realize(GtkWidget *widget)
{
SpiceDisplay *display = SPICE_DISPLAY(widget);
SpiceDisplayPrivate *d = display->priv;
GTK_WIDGET_CLASS(spice_display_parent_class)->realize(widget);
d->keycode_map = vnc_display_keymap_gdk2xtkbd_table(gtk_widget_get_window(widget),&d->keycode_maplen);
update_image(display);
}
5、通过宏和相应系统检测找到相应的对应表
const guint16 *vnc_display_keymap_gdk2xtkbd_table(GdkWindow *window,
size_t *maplen)
{
//X11系统
#ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_WINDOW(window)) {
XkbDescPtr desc;
const gchar *keycodes = NULL;
GdkDisplay *dpy = gdk_window_get_display(window);
/* There is no easy way to determine what X11 server
* and platform & keyboard driver is in use. Thus we
* do best guess heuristics.
*
* This will need more work for people with other
* X servers..... patches welcomed.
*/
Display *xdisplay = gdk_x11_display_get_xdisplay(dpy);
desc = XkbGetMap(xdisplay,XkbGBN_AllComponentsMask,XkbUseCoreKbd);
if (desc) {
if (XkbGetNames(xdisplay, XkbKeycodesNameMask, desc) == Success) {
keycodes = gdk_x11_get_xatom_name(desc->names->keycodes);
if (!keycodes)
g_warning("could not lookup keycode name");
}
XkbFreeKeyboard(desc, XkbGBN_AllComponentsMask, True);
}
if (check_for_xwin(dpy)) {
VNC_DEBUG("Using xwin keycode mapping");
*maplen = G_N_ELEMENTS(keymap_xorgxwin2xtkbd);
return keymap_xorgxwin2xtkbd;
} else if (check_for_xquartz(dpy)) {
VNC_DEBUG("Using xquartz keycode mapping");
*maplen = G_N_ELEMENTS(keymap_xorgxquartz2xtkbd);
return keymap_xorgxquartz2xtkbd;
} else if ((keycodes && STRPREFIX(keycodes, "evdev")) ||
(XKeysymToKeycode(xdisplay, XK_Page_Up) == 0x70)) {
VNC_DEBUG("Using evdev keycode mapping");
*maplen = G_N_ELEMENTS(keymap_xorgevdev2xtkbd);
return keymap_xorgevdev2xtkbd;
} else if ((keycodes && STRPREFIX(keycodes, "xfree86")) ||
(XKeysymToKeycode(xdisplay, XK_Page_Up) == 0x63)) {
VNC_DEBUG("Using xfree86 keycode mapping");
*maplen = G_N_ELEMENTS(keymap_xorgkbd2xtkbd);
return keymap_xorgkbd2xtkbd;
} else {
g_warning("Unknown keycode mapping '%s'.\n"
"Please report to gtk-vnc-list@gnome.org\n"
"including the following information:\n"
"\n"
" - Operating system\n"
" - GDK build\n"
" - X11 Server\n"
" - xprop -root\n"
" - xdpyinfo\n",
keycodes);
return NULL;
}
}
#endif
//windows系统
#ifdef GDK_WINDOWING_WIN32
if (GDK_IS_WIN32_WINDOW(window)) {
VNC_DEBUG("Using Win32 virtual keycode mapping");
*maplen = G_N_ELEMENTS(keymap_win322xtkbd);
return keymap_win322xtkbd;
}
#endif
//OSX系统
#ifdef GDK_WINDOWING_QUARTZ
if (GDK_IS_QUARTZ_WINDOW(window)) {
VNC_DEBUG("Using OS-X virtual keycode mapping");
*maplen = G_N_ELEMENTS(keymap_osx2xtkbd);
return keymap_osx2xtkbd;
}
#endif
//WAYLAND系统
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_WINDOW(window)) {
VNC_DEBUG("Using Wayland Xorg/evdev virtual keycode mapping");
*maplen = G_N_ELEMENTS(keymap_xorgevdev2xtkbd);
return keymap_xorgevdev2xtkbd;
}
#endif
//X11系统
#ifdef GDK_WINDOWING_BROADWAY
if (GDK_IS_BROADWAY_WINDOW(window)) {
g_warning("experimental: using broadway, x11 virtual keysym mapping - with very limited support. See also https://bugzilla.gnome.org/show_bug.cgi?id=700105");
*maplen = G_N_ELEMENTS(keymap_x112xtkbd);
return keymap_x112xtkbd;
}
#endif
g_warning("Unsupported GDK Windowing platform.\n"
"Disabling extended keycode tables.\n"
"Please report to gtk-vnc-list@gnome.org\n"
"including the following information:\n"
"\n"
" - Operating system\n"
" - GDK Windowing system build\n");
return NULL;
}
6、通过头文件获取相应的对应表
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif
//Xorg系统
#ifdef GDK_WINDOWING_BROADWAY
#include <gdk/gdkbroadway.h>
#endif
#if defined(GDK_WINDOWING_X11) || defined(GDK_WINDOWING_WAYLAND)
/* Xorg Linux + evdev (offset evdev keycodes) */
#include "vncdisplaykeymap_xorgevdev2xtkbd.h"
#endif
//Xorg系统
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#include <X11/XKBlib.h>
#include <stdbool.h>
#include <string.h>
/* Xorg Linux + kbd (offset + mangled XT keycodes) */
#include "vncdisplaykeymap_xorgkbd2xtkbd.h"
/* Xorg OS-X aka XQuartz (offset OS-X keycodes) */
#include "vncdisplaykeymap_xorgxquartz2xtkbd.h"
/* Xorg Cygwin aka XWin (offset + mangled XT keycodes) */
#include "vncdisplaykeymap_xorgxwin2xtkbd.h"
#endif
//Windows系统
#ifdef GDK_WINDOWING_WIN32
#include <gdk/gdkwin32.h>
/* Win32 native virtual keycodes */
#include "vncdisplaykeymap_win322xtkbd.h"
#endif
//OSX系统
#ifdef GDK_WINDOWING_QUARTZ
#include <gdk/gdkquartz.h>
/* OS-X native keycodes */
#include "vncdisplaykeymap_osx2xtkbd.h"
#endif
//X11系统
#ifdef GDK_WINDOWING_BROADWAY
/* X11 keysyms */
#include "vncdisplaykeymap_x112xtkbd.h"
#endif
其中keymap定义的头文件位置:
root@test-NI10:/mnt/spice-gtk# find . -name "vncdisplaykeymap_*"
./build/src/vncdisplaykeymap_xorgxwin2xtkbd.h./build/src/vncdisplaykeymap_xorgevdev2xtkbd.h./build/src/vncdisplaykeymap_osx2xtkbd.h./build/src/vncdisplaykeymap_x112xtkbd.h./build/src/vncdisplaykeymap_xorgxquartz2xtkbd.h./build/src/vncdisplaykeymap_xorgkbd2xtkbd.h./build/src/vncdisplaykeymap_win322xtkbd.h
以vncdisplaykeymap_win322xtkbd.h为例子,其他类似
注:生成命令
# keymap-gen --lang=glib2 --varname=keymap_win322xtkbd code-map keymaps.csv win32 xtkbd# keymap-gen --lang=glib2 --varname=keymap_osx2xtkbd code-map keymaps.csv osx xtkbd# keymap-gen --lang=glib2 --varname=keymap_x112xtkbd code-map keymaps.csv x11 xtkbd# keymap-gen --lang=glib2 --varname=keymap_xorgxwin2xtkbd code-map keymaps.csv xorgxwin xtkbd# keymap-gen --lang=glib2 --varname=keymap_xorgxquartz2xtkbd code-map keymaps.csv xorgxquartz xtkbd# keymap-gen --lang=glib2 --varname=keymap_xorgkbd2xtkbd code-map keymaps.csv xorgkbd xtkbd# keymap-gen --lang=glib2 --varname=keymap_xorgevdev2xtkbd code-map keymaps.csv xorgevdev xtkbd
/*
* This file is auto-generated from keymaps.csv
* Database checksum sha256(ef8f29f4e4294479e2789aa61e410c4b0464d4f0ad16bcc1526086a4f123bc10)
* To re-generate, run:
* keymap-gen --lang=glib2 --varname=keymap_win322xtkbd code-map keymaps.csv win32 xtkbd
*/
const guint16 keymap_win322xtkbd[252] = {
[0x8] = 0xe, /* win32:8 (VK_BACK) -> linux:14 (KEY_BACKSPACE) -> xtkbd:14 */
[0x9] = 0xf, /* win32:9 (VK_TAB) -> linux:15 (KEY_TAB) -> xtkbd:15 */
[0xd] = 0x1c, /* win32:13 (VK_RETURN) -> linux:28 (KEY_ENTER) -> xtkbd:28 */
[0x10] = 0x2a, /* win32:16 (VK_LSHIFT) -> linux:42 (KEY_LEFTSHIFT) -> xtkbd:42 */
[0x11] = 0x1d, /* win32:17 (VK_CONTROL) -> linux:29 (KEY_LEFTCTRL) -> xtkbd:29 */
[0x12] = 0x38, /* win32:18 (VK_MENU) -> linux:56 (KEY_LEFTALT) -> xtkbd:56 */
[0x13] = 0x146, /* win32:19 (VK_PAUSE) -> linux:119 (KEY_PAUSE) -> xtkbd:326 */
[0x14] = 0x3a, /* win32:20 (VK_CAPITAL) -> linux:58 (KEY_CAPSLOCK) -> xtkbd:58 */
[0x19] = 0x10d, /* win32:25 (VK_HANJA) -> linux:123 (KEY_HANJA) -> xtkbd:269 */
[0x1b] = 0x1, /* win32:27 (VK_ESCAPE) -> linux:1 (KEY_ESC) -> xtkbd:1 */
[0x20] = 0x39, /* win32:32 (VK_SPACE) -> linux:57 (KEY_SPACE) -> xtkbd:57 */
[0x21] = 0x149, /* win32:33 (VK_PRIOR) -> linux:104 (KEY_PAGEUP) -> xtkbd:329 */
[0x22] = 0x151, /* win32:34 (VK_NEXT) -> linux:109 (KEY_PAGEDOWN) -> xtkbd:337 */
[0x23] = 0x14f, /* win32:35 (VK_END) -> linux:107 (KEY_END) -> xtkbd:335 */
[0x24] = 0x147, /* win32:36 (VK_HOME) -> linux:102 (KEY_HOME) -> xtkbd:327 */
[0x25] = 0x14b, /* win32:37 (VK_LEFT) -> linux:105 (KEY_LEFT) -> xtkbd:331 */
[0x26] = 0x148, /* win32:38 (VK_UP) -> linux:103 (KEY_UP) -> xtkbd:328 */
[0x27] = 0x14d, /* win32:39 (VK_RIGHT) -> linux:106 (KEY_RIGHT) -> xtkbd:333 */
[0x28] = 0x150, /* win32:40 (VK_DOWN) -> linux:108 (KEY_DOWN) -> xtkbd:336 */
[0x2a] = 0x139, /* win32:42 (VK_PRINT) -> linux:210 (KEY_PRINT) -> xtkbd:313 */
[0x2c] = 0x54, /* win32:44 (VK_SNAPSHOT) -> linux:99 (KEY_SYSRQ) -> xtkbd:84 */
[0x2d] = 0x152, /* win32:45 (VK_INSERT) -> linux:110 (KEY_INSERT) -> xtkbd:338 */
[0x2e] = 0x153, /* win32:46 (VK_DELETE) -> linux:111 (KEY_DELETE) -> xtkbd:339 */
[0x2f] = 0x175, /* win32:47 (VK_HELP) -> linux:138 (KEY_HELP) -> xtkbd:373 */
[0x30] = 0xb, /* win32:48 (VK_0) -> linux:11 (KEY_0) -> xtkbd:11 */
[0x31] = 0x2, /* win32:49 (VK_1) -> linux:2 (KEY_1) -> xtkbd:2 */
[0x32] = 0x3, /* win32:50 (VK_2) -> linux:3 (KEY_2) -> xtkbd:3 */
[0x33] = 0x4, /* win32:51 (VK_3) -> linux:4 (KEY_3) -> xtkbd:4 */
[0x34] = 0x5, /* win32:52 (VK_4) -> linux:5 (KEY_4) -> xtkbd:5 */
[0x35] = 0x6, /* win32:53 (VK_5) -> linux:6 (KEY_5) -> xtkbd:6 */
[0x36] = 0x7, /* win32:54 (VK_6) -> linux:7 (KEY_6) -> xtkbd:7 */
[0x37] = 0x8, /* win32:55 (VK_7) -> linux:8 (KEY_7) -> xtkbd:8 */
[0x38] = 0x9, /* win32:56 (VK_8) -> linux:9 (KEY_8) -> xtkbd:9 */
[0x39] = 0xa, /* win32:57 (VK_9) -> linux:10 (KEY_9) -> xtkbd:10 */
[0x41] = 0x1e, /* win32:65 (VK_A) -> linux:30 (KEY_A) -> xtkbd:30 */
[0x42] = 0x30, /* win32:66 (VK_B) -> linux:48 (KEY_B) -> xtkbd:48 */
[0x43] = 0x2e, /* win32:67 (VK_C) -> linux:46 (KEY_C) -> xtkbd:46 */
[0x44] = 0x20, /* win32:68 (VK_D) -> linux:32 (KEY_D) -> xtkbd:32 */
[0x45] = 0x12, /* win32:69 (VK_E) -> linux:18 (KEY_E) -> xtkbd:18 */
[0x46] = 0x21, /* win32:70 (VK_F) -> linux:33 (KEY_F) -> xtkbd:33 */
[0x47] = 0x22, /* win32:71 (VK_G) -> linux:34 (KEY_G) -> xtkbd:34 */
[0x48] = 0x23, /* win32:72 (VK_H) -> linux:35 (KEY_H) -> xtkbd:35 */
[0x49] = 0x17, /* win32:73 (VK_I) -> linux:23 (KEY_I) -> xtkbd:23 */
[0x4a] = 0x24, /* win32:74 (VK_J) -> linux:36 (KEY_J) -> xtkbd:36 */
[0x4b] = 0x25, /* win32:75 (VK_K) -> linux:37 (KEY_K) -> xtkbd:37 */
[0x4c] = 0x26, /* win32:76 (VK_L) -> linux:38 (KEY_L) -> xtkbd:38 */
[0x4d] = 0x32, /* win32:77 (VK_M) -> linux:50 (KEY_M) -> xtkbd:50 */
[0x4e] = 0x31, /* win32:78 (VK_N) -> linux:49 (KEY_N) -> xtkbd:49 */
[0x4f] = 0x18, /* win32:79 (VK_O) -> linux:24 (KEY_O) -> xtkbd:24 */
[0x50] = 0x19, /* win32:80 (VK_P) -> linux:25 (KEY_P) -> xtkbd:25 */
[0x51] = 0x10, /* win32:81 (VK_Q) -> linux:16 (KEY_Q) -> xtkbd:16 */
[0x52] = 0x13, /* win32:82 (VK_R) -> linux:19 (KEY_R) -> xtkbd:19 */
[0x53] = 0x1f, /* win32:83 (VK_S) -> linux:31 (KEY_S) -> xtkbd:31 */
[0x54] = 0x14, /* win32:84 (VK_T) -> linux:20 (KEY_T) -> xtkbd:20 */
[0x55] = 0x16, /* win32:85 (VK_U) -> linux:22 (KEY_U) -> xtkbd:22 */
[0x56] = 0x2f, /* win32:86 (VK_V) -> linux:47 (KEY_V) -> xtkbd:47 */
[0x57] = 0x11, /* win32:87 (VK_W) -> linux:17 (KEY_W) -> xtkbd:17 */
[0x58] = 0x2d, /* win32:88 (VK_X) -> linux:45 (KEY_X) -> xtkbd:45 */
[0x59] = 0x15, /* win32:89 (VK_Y) -> linux:21 (KEY_Y) -> xtkbd:21 */
[0x5a] = 0x2c, /* win32:90 (VK_Z) -> linux:44 (KEY_Z) -> xtkbd:44 */
[0x5b] = 0x15b, /* win32:91 (VK_LWIN) -> linux:125 (KEY_LEFTMETA) -> xtkbd:347 */
[0x5c] = 0x15c, /* win32:92 (VK_RWIN) -> linux:126 (KEY_RIGHTMETA) -> xtkbd:348 */
[0x5d] = 0x15d, /* win32:93 (VK_APPS) -> linux:127 (KEY_COMPOSE) -> xtkbd:349 */
[0x5f] = 0x15f, /* win32:95 (VK_SLEEP) -> linux:142 (KEY_SLEEP) -> xtkbd:351 */
[0x60] = 0x52, /* win32:96 (VK_NUMPAD0) -> linux:82 (KEY_KP0) -> xtkbd:82 */
[0x61] = 0x4f, /* win32:97 (VK_NUMPAD1) -> linux:79 (KEY_KP1) -> xtkbd:79 */
[0x62] = 0x50, /* win32:98 (VK_NUMPAD2) -> linux:80 (KEY_KP2) -> xtkbd:80 */
[0x63] = 0x51, /* win32:99 (VK_NUMPAD3) -> linux:81 (KEY_KP3) -> xtkbd:81 */
[0x64] = 0x4b, /* win32:100 (VK_NUMPAD4) -> linux:75 (KEY_KP4) -> xtkbd:75 */
[0x65] = 0x4c, /* win32:101 (VK_NUMPAD5) -> linux:76 (KEY_KP5) -> xtkbd:76 */
[0x66] = 0x4d, /* win32:102 (VK_NUMPAD6) -> linux:77 (KEY_KP6) -> xtkbd:77 */
[0x67] = 0x47, /* win32:103 (VK_NUMPAD7) -> linux:71 (KEY_KP7) -> xtkbd:71 */
[0x68] = 0x48, /* win32:104 (VK_NUMPAD8) -> linux:72 (KEY_KP8) -> xtkbd:72 */
[0x69] = 0x49, /* win32:105 (VK_NUMPAD9) -> linux:73 (KEY_KP9) -> xtkbd:73 */
[0x6a] = 0x37, /* win32:106 (VK_MULTIPLY) -> linux:55 (KEY_KPASTERISK) -> xtkbd:55 */
[0x6b] = 0x4e, /* win32:107 (VK_ADD) -> linux:78 (KEY_KPPLUS) -> xtkbd:78 */
[0x6c] = 0x7e, /* win32:108 (VK_SEPARATOR??) -> linux:121 (KEY_KPCOMMA) -> xtkbd:126 */
[0x6d] = 0x4a, /* win32:109 (VK_SUBTRACT) -> linux:74 (KEY_KPMINUS) -> xtkbd:74 */
[0x6e] = 0x53, /* win32:110 (VK_DECIMAL) -> linux:83 (KEY_KPDOT) -> xtkbd:83 */
[0x6f] = 0x135, /* win32:111 (VK_DIVIDE) -> linux:98 (KEY_KPSLASH) -> xtkbd:309 */
[0x70] = 0x3b, /* win32:112 (VK_F1) -> linux:59 (KEY_F1) -> xtkbd:59 */
[0x71] = 0x3c, /* win32:113 (VK_F2) -> linux:60 (KEY_F2) -> xtkbd:60 */
[0x72] = 0x3d, /* win32:114 (VK_F3) -> linux:61 (KEY_F3) -> xtkbd:61 */
[0x73] = 0x3e, /* win32:115 (VK_F4) -> linux:62 (KEY_F4) -> xtkbd:62 */
[0x74] = 0x3f, /* win32:116 (VK_F5) -> linux:63 (KEY_F5) -> xtkbd:63 */
[0x75] = 0x40, /* win32:117 (VK_F6) -> linux:64 (KEY_F6) -> xtkbd:64 */
[0x76] = 0x41, /* win32:118 (VK_F7) -> linux:65 (KEY_F7) -> xtkbd:65 */
[0x77] = 0x42, /* win32:119 (VK_F8) -> linux:66 (KEY_F8) -> xtkbd:66 */
[0x78] = 0x43, /* win32:120 (VK_F9) -> linux:67 (KEY_F9) -> xtkbd:67 */
[0x79] = 0x44, /* win32:121 (VK_F10) -> linux:68 (KEY_F10) -> xtkbd:68 */
[0x7a] = 0x57, /* win32:122 (VK_F11) -> linux:87 (KEY_F11) -> xtkbd:87 */
[0x7b] = 0x58, /* win32:123 (VK_F12) -> linux:88 (KEY_F12) -> xtkbd:88 */
[0x7c] = 0x5d, /* win32:124 (VK_F13) -> linux:183 (KEY_F13) -> xtkbd:93 */
[0x7d] = 0x5e, /* win32:125 (VK_F14) -> linux:184 (KEY_F14) -> xtkbd:94 */
[0x7e] = 0x5f, /* win32:126 (VK_F15) -> linux:185 (KEY_F15) -> xtkbd:95 */
[0x7f] = 0x55, /* win32:127 (VK_F16) -> linux:186 (KEY_F16) -> xtkbd:85 */
[0x80] = 0x103, /* win32:128 (VK_F17) -> linux:187 (KEY_F17) -> xtkbd:259 */
[0x81] = 0x177, /* win32:129 (VK_F18) -> linux:188 (KEY_F18) -> xtkbd:375 */
[0x82] = 0x104, /* win32:130 (VK_F19) -> linux:189 (KEY_F19) -> xtkbd:260 */
[0x83] = 0x5a, /* win32:131 (VK_F20) -> linux:190 (KEY_F20) -> xtkbd:90 */
[0x84] = 0x74, /* win32:132 (VK_F21) -> linux:191 (KEY_F21) -> xtkbd:116 */
[0x85] = 0x179, /* win32:133 (VK_F22) -> linux:192 (KEY_F22) -> xtkbd:377 */
[0x86] = 0x6d, /* win32:134 (VK_F23) -> linux:193 (KEY_F23) -> xtkbd:109 */
[0x87] = 0x6f, /* win32:135 (VK_F24) -> linux:194 (KEY_F24) -> xtkbd:111 */
[0x90] = 0x45, /* win32:144 (VK_NUMLOCK) -> linux:69 (KEY_NUMLOCK) -> xtkbd:69 */
[0x91] = 0x46, /* win32:145 (VK_SCROLL) -> linux:70 (KEY_SCROLLLOCK) -> xtkbd:70 */
[0xa0] = 0x2a, /* win32:160 (VK_LSHIFT) -> linux:42 (KEY_LEFTSHIFT) -> xtkbd:42 */
[0xa1] = 0x36, /* win32:161 (VK_RSHIFT) -> linux:54 (KEY_RIGHTSHIFT) -> xtkbd:54 */
[0xa2] = 0x1d, /* win32:162 (VK_CONTROL) -> linux:29 (KEY_LEFTCTRL) -> xtkbd:29 */
[0xa3] = 0x11d, /* win32:163 (VK_RCONTROL) -> linux:97 (KEY_RIGHTCTRL) -> xtkbd:285 */
[0xa4] = 0x38, /* win32:164 (VK_MENU) -> linux:56 (KEY_LEFTALT) -> xtkbd:56 */
[0xa5] = 0x138, /* win32:165 (VK_RMENU) -> linux:100 (KEY_RIGHTALT) -> xtkbd:312 */
[0xa6] = 0x16a, /* win32:166 (VK_BROWSER_BACK) -> linux:158 (KEY_BACK) -> xtkbd:362 */
[0xa7] = 0x169, /* win32:167 (VK_BROWSER_FORWARD) -> linux:159 (KEY_FORWARD) -> xtkbd:361 */
[0xa8] = 0x167, /* win32:168 (VK_BROWSER_REFRESH) -> linux:173 (KEY_REFRESH) -> xtkbd:359 */
[0xa9] = 0x168, /* win32:169 (VK_BROWSER_STOP) -> linux:128 (KEY_STOP) -> xtkbd:360 */
[0xaa] = 0x165, /* win32:170 (VK_BROWSER_SEARCH) -> linux:217 (KEY_SEARCH) -> xtkbd:357 */
[0xac] = 0x132, /* win32:172 (VK_BROWSER_HOME) -> linux:172 (KEY_HOMEPAGE) -> xtkbd:306 */
[0xad] = 0x120, /* win32:173 (VK_VOLUME_MUTE) -> linux:113 (KEY_MUTE) -> xtkbd:288 */
[0xae] = 0x12e, /* win32:174 (VK_VOLUME_DOWN) -> linux:114 (KEY_VOLUMEDOWN) -> xtkbd:302 */
[0xaf] = 0x130, /* win32:175 (VK_VOLUME_UP) -> linux:115 (KEY_VOLUMEUP) -> xtkbd:304 */
[0xb0] = 0x119, /* win32:176 (VK_MEDIA_NEXT_TRACK) -> linux:163 (KEY_NEXTSONG) -> xtkbd:281 */
[0xb1] = 0x110, /* win32:177 (VK_MEDIA_PREV_TRACK) -> linux:165 (KEY_PREVIOUSSONG) -> xtkbd:272 */
[0xb2] = 0x124, /* win32:178 (VK_MEDIA_STOP) -> linux:166 (KEY_STOPCD) -> xtkbd:292 */
[0xb3] = 0x122, /* win32:179 (VK_MEDIA_PLAY_PAUSE) -> linux:164 (KEY_PLAYPAUSE) -> xtkbd:290 */
[0xb4] = 0x13f, /* win32:180 (VK_LAUNCH_MAIL) -> linux:215 (KEY_EMAIL) -> xtkbd:319 */
[0xba] = 0x27, /* win32:186 (VK_OEM_1) -> linux:39 (KEY_SEMICOLON) -> xtkbd:39 */
[0xbb] = 0xd, /* win32:187 (VK_OEM_PLUS) -> linux:13 (KEY_EQUAL) -> xtkbd:13 */
[0xbc] = 0x33, /* win32:188 (VK_OEM_COMMA) -> linux:51 (KEY_COMMA) -> xtkbd:51 */
[0xbd] = 0xc, /* win32:189 (VK_OEM_MINUS) -> linux:12 (KEY_MINUS) -> xtkbd:12 */
[0xbe] = 0x34, /* win32:190 (VK_OEM_PERIOD) -> linux:52 (KEY_DOT) -> xtkbd:52 */
[0xbf] = 0x35, /* win32:191 (VK_OEM_2) -> linux:53 (KEY_SLASH) -> xtkbd:53 */
[0xc0] = 0x29, /* win32:192 (VK_OEM_3) -> linux:41 (KEY_GRAVE) -> xtkbd:41 */
[0xdb] = 0x1a, /* win32:219 (VK_OEM_4) -> linux:26 (KEY_LEFTBRACE) -> xtkbd:26 */
[0xdc] = 0x2b, /* win32:220 (VK_OEM_5) -> linux:43 (KEY_BACKSLASH) -> xtkbd:43 */
[0xdd] = 0x1b, /* win32:221 (VK_OEM_6) -> linux:27 (KEY_RIGHTBRACE) -> xtkbd:27 */
[0xde] = 0x28, /* win32:222 (VK_OEM_7) -> linux:40 (KEY_APOSTROPHE) -> xtkbd:40 */
[0xe1] = 0x56, /* win32:225 (VK_OEM_102) -> linux:86 (KEY_102ND) -> xtkbd:86 */
[0xfa] = 0x133, /* win32:250 (VK_PLAY) -> linux:207 (KEY_PLAY) -> xtkbd:307 */
};
const guint keymap_win322xtkbd_len = sizeof(keymap_win322xtkbd)/sizeof(keymap_win322xtkbd[0]);