[PATCH 3/3] Rewrite keymap code to work on more platforms



From: Daniel P. Berrange <berrange redhat com>

The current keymap code assumes an Xorg server on Linux with
either evdev or kbd drivers. This adds heuristics to detect
XQuartz (Xorg on OS-X) and XWin (Xorg on Cygwin). Further it
adds support for native GDK on OS-X and Win32.

It is not possible to assume that keycodes < 87 have a 1-1
mapping to RFB (XT) keycodes. Thus the keymap arrays must
have a complete dataset, all special casing is removed.

All master  keymaps are defined in a CSV file. THis covers
Linux keycodes, OSX keycodes, AT set1, 2 & 3, XT keycodes,
the XT encoding used by the Linux KBD driver, USB keycodes,
Win32 keycodes, the XT encoding used by Xorg on Cygwin,
the XT encoding used by Xorg on Linux with kbd driver.

Further RFB and final Xorg driver mappings are derived
from these master maps automatically. The keymap-gen.pl
tool can generate lookup tables between all possible
keycode sets as required.

eg To generate a map from native Win32 keycodes to RFB
keycodes

   keymap-gen.pl keymaps.csv win32 rfb

* gtk-vnc.spec.in, mingw32-gtk-vnc.spec.in: Require Text::CSV
  for generating keymaps
* src/Makefile.am: Generate keymaps dynamically
* src/keymap-gen.pl: Tool to generate keymaps from CSV file
* src/keymaps.csv: Master keymap definitions
* src/vncconnection.c: Improve keypress log message
* src/vncdisplay.c: Convert to guint16 for keymap table
* src/vncdisplaykeymap.c, src/vncdisplaykeymap.h: Use a
  new dynamically generated, full keymap.
---
 gtk-vnc.spec.in         |    1 +
 mingw32-gtk-vnc.spec.in |    1 +
 src/Makefile.am         |   39 ++++-
 src/keymap-gen.pl       |  180 ++++++++++++++++++
 src/keymaps.csv         |  461 +++++++++++++++++++++++++++++++++++++++++++++++
 src/vncconnection.c     |    2 +-
 src/vncdisplay.c        |   10 +-
 src/vncdisplaykeymap.c  |  287 +++++++++++-------------------
 src/vncdisplaykeymap.h  |    5 +-
 9 files changed, 793 insertions(+), 193 deletions(-)
 create mode 100644 src/keymap-gen.pl
 create mode 100644 src/keymaps.csv

diff --git a/gtk-vnc.spec.in b/gtk-vnc.spec.in
index 8fa8275..1fbc8d3 100644
--- a/gtk-vnc.spec.in
+++ b/gtk-vnc.spec.in
@@ -28,6 +28,7 @@ BuildRequires: gobject-introspection-devel
 BuildRequires: gir-repository-devel
 %endif
 %endif
+BuildRequires: perl(Text::CSV)
 %if %{with_plugin}
 %if 0%{?fedora} > 8
 BuildRequires: xulrunner-devel
diff --git a/mingw32-gtk-vnc.spec.in b/mingw32-gtk-vnc.spec.in
index edce574..7e98cf4 100644
--- a/mingw32-gtk-vnc.spec.in
+++ b/mingw32-gtk-vnc.spec.in
@@ -29,6 +29,7 @@ BuildRequires: mingw32-gnutls
 BuildRequires: mingw32-gtk2
 BuildRequires: pkgconfig
 BuildRequires: intltool
+BuildRequires: perl(Text::CSV)
 
 Requires: pkgconfig
 
diff --git a/src/Makefile.am b/src/Makefile.am
index b59f8d3..5ea1c51 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -123,6 +123,41 @@ libgtk_vnc_2_0_la_LDFLAGS = $(gtk_vnc_LDFLAGS) -version-info 0:2:0
 libgtk_vnc_2_0_la_SOURCES = $(gtk_vnc_SOURCES)
 endif
 
+EXTRA_DIST += keymap-gen.pl keymaps.csv
+
+KEYMAP_GEN = $(srcdir)/keymap-gen.pl
+
+KEYMAPS = \
+	vncdisplaykeymap_xorgevdev2rfb.c \
+	vncdisplaykeymap_xorgkbd2rfb.c \
+	vncdisplaykeymap_xorgxquartz2rfb.c \
+	vncdisplaykeymap_xorgxwin2rfb.c \
+	vncdisplaykeymap_osx2rfb.c \
+	vncdisplaykeymap_win322rfb.c
+
+$(KEYMAPS): $(KEYMAP_GEN) keymaps.csv
+BUILT_SOURCES += $(KEYMAPS)
+
+vncdisplaykeymap.c: $(KEYMAPS)
+
+vncdisplaykeymap_xorgevdev2rfb.c:
+	$(AM_V_GEN)$(PERL) $(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgevdev rfb > $@ || rm $@
+
+vncdisplaykeymap_xorgkbd2rfb.c:
+	$(AM_V_GEN)$(PERL) $(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgkbd rfb > $@ || rm $@
+
+vncdisplaykeymap_xorgxquartz2rfb.c:
+	$(AM_V_GEN)$(PERL) $(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgxquartz rfb > $@ || rm $@
+
+vncdisplaykeymap_xorgxwin2rfb.c:
+	$(AM_V_GEN)$(PERL) $(KEYMAP_GEN) $(srcdir)/keymaps.csv xorgxwin rfb > $@ || rm $@
+
+vncdisplaykeymap_osx2rfb.c:
+	$(AM_V_GEN)$(PERL) $(KEYMAP_GEN) $(srcdir)/keymaps.csv osx rfb > $@ || rm $@
+
+vncdisplaykeymap_win322rfb.c:
+	$(AM_V_GEN)$(PERL) $(KEYMAP_GEN) $(srcdir)/keymaps.csv win32 rfb > $@ || rm $@
+
 
 vncdisplayenums.c: vncdisplay.h
 	$(AM_V_GEN)glib-mkenums    --fhead "#include <glib-object.h>\n" \
@@ -187,10 +222,12 @@ vncdisplay.c:: vncmarshal.h vncdisplayenums.h
 
 vncconnection.c:: vncmarshal.h vncconnectionenums.h
 
-CLEANFILES = vncmarshal.c vncmarshal.h \
+BUILT_SOURCES += vncmarshal.c vncmarshal.h \
 	vncdisplayenums.h vncdisplayenums.c \
 	vncconnectionenums.h vncconnectionenums.c
 
+CLEANFILES = $(BUILT_SOURCES)
+
 if WITH_PYTHON
 pyexec_LTLIBRARIES = gtkvnc.la
 
diff --git a/src/keymap-gen.pl b/src/keymap-gen.pl
new file mode 100644
index 0000000..56aca46
--- /dev/null
+++ b/src/keymap-gen.pl
@@ -0,0 +1,180 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+use Text::CSV;
+
+my %names = (
+    linux => [],
+    osx => []
+);
+
+my %namecolumns = (
+    linux => 0,
+    osx => 2,
+    win32 => 10,
+    );
+
+my @basemaps = qw(linux osx atset1 atset2 atset3 xt xtkbd usb win32 xwinxt xkbdxt);
+my @derivedmaps = qw(xorgevdev xorgkbd xorgxquartz xorgxwin rfb);
+my @maps = (@basemaps, @derivedmaps);
+
+my %maps;
+
+foreach my $map (@maps) {
+    $maps{$map} = [ [], [] ];
+}
+my %mapcolumns = (
+    osx => 3,
+    atset1 => 4,
+    atset2 => 5,
+    atset3 => 6,
+    xt => 7,
+    xtkbd => 8,
+    usb => 9,
+    win32 => 11,
+    xwinxt => 12,
+    xkbdxt => 13,
+    );
+
+sub help {
+    my $msg = shift;
+    print $msg;
+    print "\n";
+    print "Valid keymaps are:\n";
+    print "\n";
+    foreach my $name (sort { $a cmp $b } keys %maps) {
+	print "  $name\n";
+    }
+    print "\n";
+    exit (1);
+}
+
+if ($#ARGV != 2) {
+    help("syntax: $0 KEYMAPS SRCMAP DSTMAP\n");
+}
+
+my $keymaps = shift @ARGV;
+my $src = shift @ARGV;
+my $dst = shift @ARGV;
+
+help("$src is not a known keymap\n") unless exists $maps{$src};
+help("$dst is not a known keymap\n") unless exists $maps{$dst};
+
+
+open CSV, $keymaps
+    or die "cannot read $keymaps: $!";
+
+my $csv = Text::CSV->new();
+# Discard column headings
+$csv->getline(\*CSV);
+
+my $row;
+while ($row = $csv->getline(\*CSV)) {
+    my $linux = $row->[1];
+
+    $linux = hex($linux) if $linux =~ /0x/;
+
+    my $to = $maps{linux}->[0];
+    my $from = $maps{linux}->[1];
+    $to->[$linux] = $linux;
+    $from->[$linux] = $linux;
+
+    foreach my $name (keys %namecolumns) {
+	my $col = $namecolumns{$name};
+	my $val = $row->[$col];
+
+	$val = "" unless defined $val;
+
+	$names{$name}->[$linux] = $val;
+    }
+
+    foreach my $name (keys %mapcolumns) {
+	my $col = $mapcolumns{$name};
+	my $val = $row->[$col];
+
+	$val = 0 unless $val;
+	$val = hex($val) if $val =~ /0x/;
+
+	$to = $maps{$name}->[0];
+        $from = $maps{$name}->[1];
+	$to->[$linux] = $val;
+	$from->[$val] = $linux;
+    }
+
+    # XXX there are some special cases in kbd to handle
+    # Xorg KBD driver is the Xorg KBD XT codes offset by +8
+    # The XKBD XT codes are the same as normal XT codes
+    # for values <= 83, and completely made up for extended
+    # scancodes :-(
+    ($to, $from) = @{$maps{xorgkbd}};
+    $to->[$linux] = $maps{xkbdxt}->[0]->[$linux] + 8;
+    $from->[$to->[$linux]] = $linux;
+
+    # Xorg evdev is simply Linux keycodes offset by +8
+    ($to, $from) = @{$maps{xorgevdev}};
+    $to->[$linux] = $linux + 8;
+    $from->[$to->[$linux]] = $linux;
+
+    # Xorg XQuartz is simply OS-X keycodes offset by +8
+    ($to, $from) = @{$maps{xorgxquartz}};
+    $to->[$linux] = $maps{osx}->[0]->[$linux] + 8;
+    $from->[$to->[$linux]] = $linux;
+
+    # RFB keycodes are XT kbd keycodes with a slightly
+    # different encoding of 0xe0 scan codes. RFB uses
+    # the high bit of the first byte, instead of the low
+    # bit of the second byte.
+    ($to, $from) = @{$maps{rfb}};
+    my $xtkbd = $maps{xtkbd}->[0]->[$linux];
+    $to->[$linux] = $xtkbd ? (($xtkbd & 0x100)>>1) | ($xtkbd & 0x7f) : 0;
+    $from->[$to->[$linux]] = $linux;
+
+    # Xorg Cygwin is the Xorg Cygwin XT codes offset by +8
+    # The Cygwin XT codes are the same as normal XT codes
+    # for values <= 83, and completely made up for extended
+    # scancodes :-(
+    ($to, $from) = @{$maps{xorgxwin}};
+    $to->[$linux] = $maps{xwinxt}->[0]->[$linux] + 8;
+    $from->[$to->[$linux]] = $linux;
+
+#    print $linux, "\n";
+}
+
+close CSV;
+
+my $srcmap = $maps{$src}->[1];
+my $dstmap = $maps{$dst}->[0];
+
+printf "static const guint16 keymap_%s2%s[] = {\n", $src, $dst;
+
+for (my $i = 0 ; $i <= $#{$srcmap} ; $i++) {
+    my $linux = $srcmap->[$i] || 0;
+    my $j = $dstmap->[$linux];
+    next unless $linux && $j;
+
+    my $srcname = $names{$src}->[$linux] if exists $names{$src};
+    my $dstname = $names{$dst}->[$linux] if exists $names{$dst};
+    my $vianame = $names{linux}->[$linux] unless $src eq "linux" || $dst eq "linux";
+
+    $srcname = "" unless $srcname;
+    $dstname = "" unless $dstname;
+    $vianame = "" unless $vianame;
+    $srcname = " ($srcname)" if $srcname;
+    $dstname = " ($dstname)" if $dstname;
+    $vianame = " ($vianame)" if $vianame;
+
+    my $comment;
+    if ($src ne "linux" && $dst ne "linux") {
+	$comment = sprintf "%d%s => %d%s via %d%s", $i, $srcname, $j, $dstname, $linux, $vianame;
+    } else {
+	$comment = sprintf "%d%s => %d%s", $i, $srcname, $j, $dstname;
+    }
+
+    my $data = sprintf "[0x%x] = 0x%x,", $i, $j;
+
+    printf "  %-20s /* %s */\n", $data, $comment;
+}
+
+print "};\n";
diff --git a/src/keymaps.csv b/src/keymaps.csv
new file mode 100644
index 0000000..275dc17
--- /dev/null
+++ b/src/keymaps.csv
@@ -0,0 +1,461 @@
+"Linux Name","Linux Keycode","OS-X Name","OS-X Keycode","AT set1 keycode","AT set2 keycode","AT set3 keycode",XT,"XT KBD","USB Keycodes","Win32 Name","Win32 Keycode","Xwin XT","Xfree86 KBD XT"
+KEY_RESERVED,0,,0x0,,,,,,,,,,
+KEY_ESC,1,Escape,0x35,1,118,8,1,1,41,VK_ESCAPE,0x1b,1,1
+KEY_1,2,ANSI_1,0x12,2,22,22,2,2,30,VK_1,0x31,2,2
+KEY_2,3,ANSI_2,0x13,3,30,30,3,3,31,VK_2,0x32,3,3
+KEY_3,4,ANSI_3,0x14,4,38,38,4,4,32,VK_3,0x33,4,4
+KEY_4,5,ANSI_4,0x15,5,37,37,5,5,33,VK_4,0x34,5,5
+KEY_5,6,ANSI_5,0x17,6,46,46,6,6,34,VK_5,0x35,6,6
+KEY_6,7,ANSI_6,0x16,7,54,54,7,7,35,VK_6,0x36,7,7
+KEY_7,8,ANSI_7,0x1a,8,61,61,8,8,36,VK_7,0x37,8,8
+KEY_8,9,ANSI_8,0x1c,9,62,62,9,9,37,VK_8,0x38,9,9
+KEY_9,10,ANSI_9,0x19,10,70,70,10,10,38,VK_9,0x39,10,10
+KEY_0,11,ANSI_0,0x1d,11,69,69,11,11,39,VK_0,0x30,11,11
+KEY_MINUS,12,ANSI_Minus,0x1b,12,78,78,12,12,45,VK_OEM_MINUS,0xbd,12,12
+KEY_EQUAL,13,ANSI_Equal,0x18,13,85,85,13,13,46,VK_OEM_PLUS,0xbb,13,13
+KEY_BACKSPACE,14,Delete,0x33,14,102,102,14,14,42,VK_BACK,0x08,14,14
+KEY_TAB,15,Tab,0x30,15,13,13,15,15,43,VK_TAB,0x09,15,15
+KEY_Q,16,ANSI_Q,0xc,16,21,21,16,16,20,VK_Q,0x51,16,16
+KEY_W,17,ANSI_W,0xd,17,29,29,17,17,26,VK_W,0x57,17,17
+KEY_E,18,ANSI_E,0xe,18,36,36,18,18,8,VK_E,0x45,18,18
+KEY_R,19,ANSI_R,0xf,19,45,45,19,19,21,VK_R,0x52,19,19
+KEY_T,20,ANSI_T,0x11,20,44,44,20,20,23,VK_T,0x54,20,20
+KEY_Y,21,ANSI_Y,0x10,21,53,53,21,21,28,VK_Y,0x59,21,21
+KEY_U,22,ANSI_U,0x20,22,60,60,22,22,24,VK_U,0x55,22,22
+KEY_I,23,ANSI_I,0x22,23,67,67,23,23,12,VK_I,0x49,23,23
+KEY_O,24,ANSI_O,0x1f,24,68,68,24,24,18,VK_O,0x4f,24,24
+KEY_P,25,ANSI_P,0x23,25,77,77,25,25,19,VK_P,0x50,25,25
+KEY_LEFTBRACE,26,ANSI_LeftBracket,0x21,26,84,84,26,26,47,VK_OEM_4,0xdb,26,26
+KEY_RIGHTBRACE,27,ANSI_RightBracket,0x1e,27,91,91,27,27,48,VK_OEM_6,0xdd,27,27
+KEY_ENTER,28,Return,0x24,28,90,90,28,28,40,VK_RETURN,0x0d,28,28
+KEY_LEFTCTRL,29,Control,0x3b,29,20,17,29,29,224,VK_LCONTROL,0xa2,29,29
+KEY_A,30,ANSI_A,0x0,30,28,28,30,30,4,VK_A,0x41,30,30
+KEY_S,31,ANSI_S,0x1,31,27,27,31,31,22,VK_S,0x53,31,31
+KEY_D,32,ANSI_D,0x2,32,35,35,32,32,7,VK_D,0x44,32,32
+KEY_F,33,ANSI_F,0x3,33,43,43,33,33,9,VK_F,0x46,33,33
+KEY_G,34,ANSI_G,0x5,34,52,52,34,34,10,VK_G,0x47,34,34
+KEY_H,35,ANSI_H,0x4,35,51,51,35,35,11,VK_H,0x48,35,35
+KEY_J,36,ANSI_J,0x26,36,59,59,36,36,13,VK_J,0x4a,36,36
+KEY_K,37,ANSI_K,0x28,37,66,66,37,37,14,VK_K,0x4b,37,37
+KEY_L,38,ANSI_L,0x25,38,75,75,38,38,15,VK_L,0x4c,38,38
+KEY_SEMICOLON,39,ANSI_Semicolon,0x29,39,76,76,39,39,51,VK_OEM_1,0xba,39,39
+KEY_APOSTROPHE,40,ANSI_Quote,0x27,40,82,82,40,40,52,VK_OEM_2,0xbf,40,40
+KEY_GRAVE,41,ANSI_Grave,0x32,41,14,14,41,41,53,VK_OEM_3,0xc0,41,41
+KEY_LEFTSHIFT,42,Shift,0x38,42,18,18,42,42,225,VK_LSHIFT,0xa0,42,42
+KEY_BACKSLASH,43,ANSI_Backslash,0x2a,43,93,93,43,43,50,VK_OEM_5,0xdc,43,43
+KEY_Z,44,ANSI_Z,0x6,44,26,26,44,44,29,VK_Z,0x5a,44,44
+KEY_X,45,ANSI_X,0x7,45,34,34,45,45,27,VK_X,0x58,45,45
+KEY_C,46,ANSI_C,0x8,46,33,33,46,46,6,VK_C,0x43,46,46
+KEY_V,47,ANSI_V,0x9,47,42,42,47,47,25,VK_V,0x56,47,47
+KEY_B,48,ANSI_B,0xb,48,50,50,48,48,5,VK_B,0x42,48,48
+KEY_N,49,ANSI_N,0x2d,49,49,49,49,49,17,VK_N,0x4e,49,49
+KEY_M,50,ANSI_M,0x2e,50,58,58,50,50,16,VK_M,0x4d,50,50
+KEY_COMMA,51,ANSI_Comma,0x2b,51,65,65,51,51,54,VK_OEM_COMMA,0xbc,51,51
+KEY_DOT,52,ANSI_Period,0x2f,52,73,73,52,52,55,VK_OEM_PERIOD,0xbe,52,52
+KEY_SLASH,53,ANSI_Slash,0x2c,53,74,74,53,53,56,VK_OEM_2,0xbf,53,53
+KEY_RIGHTSHIFT,54,RightShift,0x3c,54,89,89,54,54,229,VK_RSHIFT,0xa1,54,54
+KEY_KPASTERISK,55,ANSI_KeypadMultiply,0x43,55,124,126,55,55,85,VK_MULTIPLY,0x6a,55,55
+KEY_LEFTALT,56,Option,0x3a,56,17,25,56,56,226,VK_LMENU,0xa4,56,56
+KEY_SPACE,57,Space,0x31,57,41,41,57,57,44,VK_SPACE,0x20,57,57
+KEY_CAPSLOCK,58,CapsLock,0x39,58,88,20,58,58,57,VK_CAPITAL,0x14,58,58
+KEY_F1,59,F1,0x7a,59,5,7,59,59,58,VK_F1,0x70,59,59
+KEY_F2,60,F2,0x78,60,6,15,60,60,59,VK_F2,0x71,60,60
+KEY_F3,61,F3,0x63,61,4,23,61,61,60,VK_F3,0x72,61,61
+KEY_F4,62,F4,0x76,62,12,31,62,62,61,VK_F4,0x73,62,62
+KEY_F5,63,F5,0x60,63,3,39,63,63,62,VK_F5,0x74,63,63
+KEY_F6,64,F6,0x61,64,11,47,64,64,63,VK_F6,0x75,64,64
+KEY_F7,65,F7,0x62,65,259,55,65,65,64,VK_F7,0x76,65,65
+KEY_F8,66,F8,0x64,66,10,63,66,66,65,VK_F8,0x77,66,66
+KEY_F9,67,F9,0x65,67,1,71,67,67,66,VK_F9,0x78,67,67
+KEY_F10,68,F10,0x6d,68,9,79,68,68,67,VK_F10,0x79,68,68
+KEY_NUMLOCK,69,,,69,119,118,69,69,83,VK_NUMLOCK,0x90,69,69
+KEY_SCROLLLOCK,70,,,70,126,95,70,70,71,VK_SCROLL,0x91,70,70
+KEY_KP7,71,ANSI_Keypad7,0x59,71,108,108,71,71,95,VK_NUMPAD7,0x67,71,71
+KEY_KP8,72,ANSI_Keypad8,0x5b,72,117,117,72,72,96,VK_NUMPAD8,0x68,72,72
+KEY_KP9,73,ANSI_Keypad9,0x5c,73,125,125,73,73,97,VK_NUMPAD9,0x69,73,73
+KEY_KPMINUS,74,ANSI_KeypadMinus,0x4e,74,123,132,74,74,86,VK_SUBTRACT,0x6d,74,74
+KEY_KP4,75,ANSI_Keypad4,0x56,75,107,107,75,75,92,VK_NUMPAD4,0x64,75,75
+KEY_KP5,76,ANSI_Keypad5,0x57,76,115,115,76,76,93,VK_NUMPAD5,0x65,76,76
+KEY_KP6,77,ANSI_Keypad6,0x58,77,116,116,77,77,94,VK_NUMPAD6,0x66,77,77
+KEY_KPPLUS,78,ANSI_KeypadPlus,0x45,78,121,124,78,78,87,VK_ADD,0x6b,78,78
+KEY_KP1,79,ANSI_Keypad1,0x53,79,105,105,79,79,89,VK_NUMPAD1,0x61,79,79
+KEY_KP2,80,ANSI_Keypad2,0x54,80,114,114,80,80,90,VK_NUMPAD2,0x62,80,80
+KEY_KP3,81,ANSI_Keypad3,0x55,81,122,122,81,81,91,VK_NUMPAD3,0x63,81,81
+KEY_KP0,82,ANSI_Keypad0,0x52,82,112,112,82,82,98,VK_NUMPAD0,0x60,82,82
+KEY_KPDOT,83,ANSI_KeypadDecimal,0x41,83,113,113,83,83,99,VK_DECIMAL,0x6e,83,83
+,84,,,,,,,84,,,,,
+KEY_ZENKAKUHANKAKU,85,,,118,95,,,118,148,,,,
+KEY_102ND,86,,,86,97,19,,86,100,VK_OEM_102,0xe1,,
+KEY_F11,87,F11,0x67,87,120,86,101,87,68,VK_F11,0x7a,,
+KEY_F12,88,F12,0x6f,88,7,94,102,88,69,VK_F12,0x7b,,
+KEY_RO,89,,,115,81,,,115,135,,,,
+KEY_KATAKANA,90,JIS_Kana????,0x68,120,99,,,120,146,VK_KANA,0x15,,
+KEY_HIRAGANA,91,,,119,98,,,119,147,,,,
+KEY_HENKAN,92,,,121,100,134,,121,138,,,,
+KEY_KATAKANAHIRAGANA,93,,,112,19,135,,,136,,,0xc8,0xc8
+KEY_MUHENKAN,94,,,123,103,133,,123,139,,,,
+KEY_KPJPCOMMA,95,JIS_KeypadComma,0x5f,92,39,,,92,140,,,,
+KEY_KPENTER,96,ANSI_KeypadEnter,0x4c,,158,121,,284,88,,,0x64,0x64
+KEY_RIGHTCTRL,97,RightControl,0x3e,,,88,,285,228,VK_RCONTROL,0xa3,0x65,0x65
+KEY_KPSLASH,98,ANSI_KeypadDivide,0x4b,,181,119,,309,84,VK_DIVIDE,0x6f,0x68,0x68
+KEY_SYSRQ,99,,,84,260,87,,84,70,"VK_SNAPSHOT ???",0x2c,0x67,0x67
+KEY_RIGHTALT,100,RightOption,0x3d,,,57,,312,230,VK_RMENU,0xa5,0x69,0x69
+KEY_LINEFEED,101,,,,,,,91,,,,,
+KEY_HOME,102,Home,0x73,,224,110,,327,74,VK_HOME,0x24,0x59,0x59
+KEY_UP,103,UpArrow,0x7e,,236,99,109,328,82,VK_UP,0x26,0x5a,0x5a
+KEY_PAGEUP,104,PageUp,0x74,,201,111,,329,75,VK_PRIOR,0x21,0x5b,0x5b
+KEY_LEFT,105,LeftArrow,0x7b,,203,97,111,331,80,VK_LEFT,0x25,0x5c,0x5c
+KEY_RIGHT,106,RightArrow,0x7c,,205,106,112,333,79,VK_RIGHT,0x27,0x5e,0x5e
+KEY_END,107,End,0x77,,225,101,,335,77,VK_END,0x23,0x5f,0x5f
+KEY_DOWN,108,DownArrow,0x7d,,254,96,110,336,81,VK_DOWN,0x28,0x60,0x60
+KEY_PAGEDOWN,109,PageDown,0x79,,243,109,,337,78,VK_NEXT,0x22,0x61,0x61
+KEY_INSERT,110,,,,210,103,107,338,73,VK_INSERT,0x2d,0x62,0x62
+KEY_DELETE,111,ForwardDelete,0x75,,244,100,108,339,76,VK_DELETE,0x2e,0x63,0x63
+KEY_MACRO,112,,,,239,142,,367,,,,,
+KEY_MUTE,113,Mute,0x4a,,251,156,,288,239,VK_VOLUME_MUTE,0xad,,
+KEY_VOLUMEDOWN,114,VolumeDown,0x49,,,157,,302,238,VK_VOLUME_DOWN,0xae,,
+KEY_VOLUMEUP,115,VolumeUp,0x48,,233,149,,304,237,VK_VOLUME_UP,0xaf,,
+KEY_POWER,116,,,,,,,350,102,,,,
+KEY_KPEQUAL,117,ANSI_KeypadEquals,0x51,89,15,,,89,103,,,0x76,0x76
+KEY_KPPLUSMINUS,118,,,,206,,,334,,,,,
+KEY_PAUSE,119,,,,198,98,,326,72,VK_PAUSE,0x013,0x66,0x66
+KEY_SCALE,120,,,,,,,267,,,,,
+KEY_KPCOMMA,121,ANSI_KeypadClear????,0x47,126,109,,,126,133,VK_SEPARATOR??,0x6c,,
+KEY_HANGEUL,122,,,,,,,,144,VK_HANGEUL,0x15,,
+KEY_HANJA,123,,,,,,,269,145,VK_HANJA,0x19,,
+KEY_YEN,124,JIS_Yen,0x5d,125,106,,,125,137,,,0x7d,0x7d
+KEY_LEFTMETA,125,Command,0x37,,,139,,347,227,VK_LWIN,0x5b,0x6b,0x6b
+KEY_RIGHTMETA,126,,,,,140,,348,231,VK_RWIN,0x5c,0x6c,0x6c
+KEY_COMPOSE,127,Function,0x3f,,,141,,349,101,VK_APPS,0x5d,0x6d,0x6d
+KEY_STOP,128,,,,,10,,360,243,VK_BROWSER_STOP,0xa9,,
+KEY_AGAIN,129,,,,,11,,261,121,,,,
+KEY_PROPS,130,,,,,12,,262,118,,,,
+KEY_UNDO,131,,,,,16,,263,122,,,,
+KEY_FRONT,132,,,,,,,268,119,,,,
+KEY_COPY,133,,,,,24,,376,124,,,,
+KEY_OPEN,134,,,,,32,,100,116,,,,
+KEY_PASTE,135,,,,,40,,101,125,,,,
+KEY_FIND,136,,,,,48,,321,244,,,,
+KEY_CUT,137,,,,,56,,316,123,,,,
+KEY_HELP,138,,,,,9,,373,117,VK_HELP,0x2f,,
+KEY_MENU,139,,,,,145,,286,,,,,
+KEY_CALC,140,,,,174,163,,289,251,,,,
+KEY_SETUP,141,,,,,,,102,,,,,
+KEY_SLEEP,142,,,,,,,351,248,VK_SLEEP,0x5f,,
+KEY_WAKEUP,143,,,,,,,355,,,,,
+KEY_FILE,144,,,,,,,103,,,,,
+KEY_SENDFILE,145,,,,,,,104,,,,,
+KEY_DELETEFILE,146,,,,,,,105,,,,,
+KEY_XFER,147,,,,,162,,275,,,,,
+KEY_PROG1,148,,,,,160,,287,,,,,
+KEY_PROG2,149,,,,,161,,279,,,,,
+KEY_WWW,150,,,,,,,258,240,,,,
+KEY_MSDOS,151,,,,,,,106,,,,,
+KEY_SCREENLOCK,152,,,,,150,,274,249,,,,
+KEY_DIRECTION,153,,,,,,,107,,,,,
+KEY_CYCLEWINDOWS,154,,,,,155,,294,,,,,
+KEY_MAIL,155,,,,,,,364,,,,,
+KEY_BOOKMARKS,156,,,,,,,358,,,,,
+KEY_COMPUTER,157,,,,,,,363,,,,,
+KEY_BACK,158,,,,,,,362,241,VK_BROWSER_BACK,0xa6,,
+KEY_FORWARD,159,,,,,,,361,242,VK_BROWSER_FORWARD,0xa7,,
+KEY_CLOSECD,160,,,,,154,,291,,,,,
+KEY_EJECTCD,161,,,,,,,108,236,,,,
+KEY_EJECTCLOSECD,162,,,,,,,381,,,,,
+KEY_NEXTSONG,163,,,,241,147,,281,235,VK_MEDIA_NEXT_TRACK,0xb0,,
+KEY_PLAYPAUSE,164,,,,173,,,290,232,VK_MEDIA_PLAY_PAUSE,0xb3,,
+KEY_PREVIOUSSONG,165,,,,250,148,,272,234,VK_MEDIA_PREV_TRACK,0xb1,,
+KEY_STOPCD,166,,,,164,152,,292,233,VK_MEDIA_STOP,0xb2,,
+KEY_RECORD,167,,,,,158,,305,,,,,
+KEY_REWIND,168,,,,,159,,280,,,,,
+KEY_PHONE,169,,,,,,,99,,,,,
+KEY_ISO,170,ISO_Section,0xa,,,,,112,,,,,
+KEY_CONFIG,171,,,,,,,257,,,,,
+KEY_HOMEPAGE,172,,,,178,151,,306,,VK_BROWSER_HOME,0xac,,
+KEY_REFRESH,173,,,,,,,359,250,VK_BROWSER_REFRESH,0xa8,,
+KEY_EXIT,174,,,,,,,113,,,,,
+KEY_MOVE,175,,,,,,,114,,,,,
+KEY_EDIT,176,,,,,,,264,247,,,,
+KEY_SCROLLUP,177,,,,,,,117,245,,,,
+KEY_SCROLLDOWN,178,,,,,,,271,246,,,,
+KEY_KPLEFTPAREN,179,,,,,,,374,182,,,,
+KEY_KPRIGHTPAREN,180,,,,,,,379,183,,,,
+KEY_NEW,181,,,,,,,265,,,,,
+KEY_REDO,182,,,,,,,266,,,,,
+KEY_F13,183,F13,0x69,93,47,127,,93,104,VK_F13,0x7c,0x6e,0x6e
+KEY_F14,184,F14,0x6b,94,55,128,,94,105,VK_F14,0x7d,0x6f,0x6f
+KEY_F15,185,F15,0x71,95,63,129,,95,106,VK_F15,0x7e,0x70,0x70
+KEY_F16,186,F16,0x6a,,,130,,85,107,VK_F16,0x7f,0x71,0x71
+KEY_F17,187,F17,0x40,,,131,,259,108,VK_F17,0x80,0x72,0x72
+KEY_F18,188,F18,0x4f,,,,,375,109,VK_F18,0x81,,
+KEY_F19,189,F19,0x50,,,,,260,110,VK_F19,0x82,,
+KEY_F20,190,F20,0x5a,,,,,90,111,VK_F20,0x83,,
+KEY_F21,191,,,,,,,116,112,VK_F21,0x84,,
+KEY_F22,192,,,,,,,377,113,VK_F22,0x85,,
+KEY_F23,193,,,,,,,109,114,VK_F23,0x86,,
+KEY_F24,194,,,,,,,111,115,VK_F24,0x87,,
+,195,,,,,,,277,,,,,
+,196,,,,,,,278,,,,,
+,197,,,,,,,282,,,,,
+,198,,,,,,,283,,,,,
+,199,,,,,,,295,,,,,
+KEY_PLAYCD,200,,,,,,,296,,,,,
+KEY_PAUSECD,201,,,,,,,297,,,,,
+KEY_PROG3,202,,,,,,,299,,,,,
+KEY_PROG4,203,,,,,,,300,,,,,
+KEY_DASHBOARD,204,,,,,,,301,,,,,
+KEY_SUSPEND,205,,,,,,,293,,,,,
+KEY_CLOSE,206,,,,,,,303,,,,,
+KEY_PLAY,207,,,,,,,307,,VK_PLAY,0xfa,,
+KEY_FASTFORWARD,208,,,,,,,308,,,,,
+KEY_BASSBOOST,209,,,,,,,310,,,,,
+KEY_PRINT,210,,,,,,,313,,VK_PRINT,0x2a,,
+KEY_HP,211,,,,,,,314,,,,,
+KEY_CAMERA,212,,,,,,,315,,,,,
+KEY_SOUND,213,,,,,,,317,,,,,
+KEY_QUESTION,214,,,,,,,318,,,,,
+KEY_EMAIL,215,,,,,,,319,,VK_LAUNCH_MAIL,0xb4,,
+KEY_CHAT,216,,,,,,,320,,,,,
+KEY_SEARCH,217,,,,,,,357,,VK_BROWSER_SEARCH,0xaa,,
+KEY_CONNECT,218,,,,,,,322,,,,,
+KEY_FINANCE,219,,,,,,,323,,,,,
+KEY_SPORT,220,,,,,,,324,,,,,
+KEY_SHOP,221,,,,,,,325,,,,,
+KEY_ALTERASE,222,,,,,,,276,,,,,
+KEY_CANCEL,223,,,,,,,330,,,,,
+KEY_BRIGHTNESSDOWN,224,,,,,,,332,,,,,
+KEY_BRIGHTNESSUP,225,,,,,,,340,,,,,
+KEY_MEDIA,226,,,,,,,365,,,,,
+KEY_SWITCHVIDEOMODE,227,,,,,,,342,,,,,
+KEY_KBDILLUMTOGGLE,228,,,,,,,343,,,,,
+KEY_KBDILLUMDOWN,229,,,,,,,344,,,,,
+KEY_KBDILLUMUP,230,,,,,,,345,,,,,
+KEY_SEND,231,,,,,,,346,,,,,
+KEY_REPLY,232,,,,,,,356,,,,,
+KEY_FORWARDMAIL,233,,,,,,,270,,,,,
+KEY_SAVE,234,,,,,,,341,,,,,
+KEY_DOCUMENTS,235,,,,,,,368,,,,,
+KEY_BATTERY,236,,,,,,,369,,,,,
+KEY_BLUETOOTH,237,,,,,,,370,,,,,
+KEY_WLAN,238,,,,,,,371,,,,,
+KEY_UWB,239,,,,,,,372,,,,,
+KEY_UNKNOWN,240,,,,,,,,,,,,
+KEY_VIDEO_NEXT,241,,,,,,,,,,,,
+KEY_VIDEO_PREV,242,,,,,,,,,,,,
+KEY_BRIGHTNESS_CYCLE,243,,,,,,,,,,,,
+KEY_BRIGHTNESS_ZERO,244,,,,,,,,,,,,
+KEY_DISPLAY_OFF,245,,,,,,,,,,,,
+KEY_WIMAX,246,,,,,,,,,,,,
+,247,,,,,,,,,,,,
+,248,,,,,,,,,,,,
+,249,,,,,,,,,,,,
+,250,,,,,,,,,,,,
+,251,,,,,,,,,,,,
+,252,,,,,,,,,,,,
+,253,,,,,,,,,,,,
+,254,,,,,,,,,,,,
+,255,,,,182,,,,,,,,
+BTN_MISC,0x100,,,,,,,,,,,,
+BTN_0,0x100,,,,,,,,,VK_LBUTTON,0x01,,
+BTN_1,0x101,,,,,,,,,VK_RBUTTON,0x02,,
+BTN_2,0x102,,,,,,,,,VK_MBUTTON,0x04,,
+BTN_3,0x103,,,,,,,,,VK_XBUTTON1,0x05,,
+BTN_4,0x104,,,,,,,,,VK_XBUTTON2,0x06,,
+BTN_5,0x105,,,,,,,,,,,,
+BTN_6,0x106,,,,,,,,,,,,
+BTN_7,0x107,,,,,,,,,,,,
+BTN_8,0x108,,,,,,,,,,,,
+BTN_9,0x109,,,,,,,,,,,,
+BTN_MOUSE,0x110,,,,,,,,,,,,
+BTN_LEFT,0x110,,,,,,,,,,,,
+BTN_RIGHT,0x111,,,,,,,,,,,,
+BTN_MIDDLE,0x112,,,,,,,,,,,,
+BTN_SIDE,0x113,,,,,,,,,,,,
+BTN_EXTRA,0x114,,,,,,,,,,,,
+BTN_FORWARD,0x115,,,,,,,,,,,,
+BTN_BACK,0x116,,,,,,,,,,,,
+BTN_TASK,0x117,,,,,,,,,,,,
+BTN_JOYSTICK,0x120,,,,,,,,,,,,
+BTN_TRIGGER,0x120,,,,,,,,,,,,
+BTN_THUMB,0x121,,,,,,,,,,,,
+BTN_THUMB2,0x122,,,,,,,,,,,,
+BTN_TOP,0x123,,,,,,,,,,,,
+BTN_TOP2,0x124,,,,,,,,,,,,
+BTN_PINKIE,0x125,,,,,,,,,,,,
+BTN_BASE,0x126,,,,,,,,,,,,
+BTN_BASE2,0x127,,,,,,,,,,,,
+BTN_BASE3,0x128,,,,,,,,,,,,
+BTN_BASE4,0x129,,,,,,,,,,,,
+BTN_BASE5,0x12a,,,,,,,,,,,,
+BTN_BASE6,0x12b,,,,,,,,,,,,
+BTN_DEAD,0x12f,,,,,,,,,,,,
+BTN_GAMEPAD,0x130,,,,,,,,,,,,
+BTN_A,0x130,,,,,,,,,,,,
+BTN_B,0x131,,,,,,,,,,,,
+BTN_C,0x132,,,,,,,,,,,,
+BTN_X,0x133,,,,,,,,,,,,
+BTN_Y,0x134,,,,,,,,,,,,
+BTN_Z,0x135,,,,,,,,,,,,
+BTN_TL,0x136,,,,,,,,,,,,
+BTN_TR,0x137,,,,,,,,,,,,
+BTN_TL2,0x138,,,,,,,,,,,,
+BTN_TR2,0x139,,,,,,,,,,,,
+BTN_SELECT,0x13a,,,,,,,,,,,,
+BTN_START,0x13b,,,,,,,,,,,,
+BTN_MODE,0x13c,,,,,,,,,,,,
+BTN_THUMBL,0x13d,,,,,,,,,,,,
+BTN_THUMBR,0x13e,,,,,,,,,,,,
+BTN_DIGI,0x140,,,,,,,,,,,,
+BTN_TOOL_PEN,0x140,,,,,,,,,,,,
+BTN_TOOL_RUBBER,0x141,,,,,,,,,,,,
+BTN_TOOL_BRUSH,0x142,,,,,,,,,,,,
+BTN_TOOL_PENCIL,0x143,,,,,,,,,,,,
+BTN_TOOL_AIRBRUSH,0x144,,,,,,,,,,,,
+BTN_TOOL_FINGER,0x145,,,,,,,,,,,,
+BTN_TOOL_MOUSE,0x146,,,,,,,,,,,,
+BTN_TOOL_LENS,0x147,,,,,,,,,,,,
+BTN_TOUCH,0x14a,,,,,,,,,,,,
+BTN_STYLUS,0x14b,,,,,,,,,,,,
+BTN_STYLUS2,0x14c,,,,,,,,,,,,
+BTN_TOOL_DOUBLETAP,0x14d,,,,,,,,,,,,
+BTN_TOOL_TRIPLETAP,0x14e,,,,,,,,,,,,
+BTN_TOOL_QUADTAP,0x14f,,,,,,,,,,,,
+BTN_WHEEL,0x150,,,,,,,,,,,,
+BTN_GEAR_DOWN,0x150,,,,,,,,,,,,
+BTN_GEAR_UP,0x151,,,,,,,,,,,,
+KEY_OK,0x160,,,,,,,,,,,,
+KEY_SELECT,0x161,,,,,,,,,VK_SELECT,0x29,,
+KEY_GOTO,0x162,,,,,,,,,,,,
+KEY_CLEAR,0x163,,,,,,,,,,,,
+KEY_POWER2,0x164,,,,,,,,,,,,
+KEY_OPTION,0x165,,,,,,,,,,,,
+KEY_INFO,0x166,,,,,,,,,,,,
+KEY_TIME,0x167,,,,,,,,,,,,
+KEY_VENDOR,0x168,,,,,,,,,,,,
+KEY_ARCHIVE,0x169,,,,,,,,,,,,
+KEY_PROGRAM,0x16a,,,,,,,,,,,,
+KEY_CHANNEL,0x16b,,,,,,,,,,,,
+KEY_FAVORITES,0x16c,,,,,,,,,VK_BROWSER_FAVOURITES,0xab,,
+KEY_EPG,0x16d,,,,,,,,,,,,
+KEY_PVR,0x16e,,,,,,,,,,,,
+KEY_MHP,0x16f,,,,,,,,,,,,
+KEY_LANGUAGE,0x170,,,,,,,,,,,,
+KEY_TITLE,0x171,,,,,,,,,,,,
+KEY_SUBTITLE,0x172,,,,,,,,,,,,
+KEY_ANGLE,0x173,,,,,,,,,,,,
+KEY_ZOOM,0x174,,,,,,,,,VK_ZOOM,0xfb,,
+KEY_MODE,0x175,,,,,,,,,,,,
+KEY_KEYBOARD,0x176,,,,,,,,,,,,
+KEY_SCREEN,0x177,,,,,,,,,,,,
+KEY_PC,0x178,,,,,,,,,,,,
+KEY_TV,0x179,,,,,,,,,,,,
+KEY_TV2,0x17a,,,,,,,,,,,,
+KEY_VCR,0x17b,,,,,,,,,,,,
+KEY_VCR2,0x17c,,,,,,,,,,,,
+KEY_SAT,0x17d,,,,,,,,,,,,
+KEY_SAT2,0x17e,,,,,,,,,,,,
+KEY_CD,0x17f,,,,,,,,,,,,
+KEY_TAPE,0x180,,,,,,,,,,,,
+KEY_RADIO,0x181,,,,,,,,,,,,
+KEY_TUNER,0x182,,,,,,,,,,,,
+KEY_PLAYER,0x183,,,,,,,,,,,,
+KEY_TEXT,0x184,,,,,,,,,,,,
+KEY_DVD,0x185,,,,,,,,,,,,
+KEY_AUX,0x186,,,,,,,,,,,,
+KEY_MP3,0x187,,,,,,,,,,,,
+KEY_AUDIO,0x188,,,,,,,,,,,,
+KEY_VIDEO,0x189,,,,,,,,,,,,
+KEY_DIRECTORY,0x18a,,,,,,,,,,,,
+KEY_LIST,0x18b,,,,,,,,,,,,
+KEY_MEMO,0x18c,,,,,,,,,,,,
+KEY_CALENDAR,0x18d,,,,,,,,,,,,
+KEY_RED,0x18e,,,,,,,,,,,,
+KEY_GREEN,0x18f,,,,,,,,,,,,
+KEY_YELLOW,0x190,,,,,,,,,,,,
+KEY_BLUE,0x191,,,,,,,,,,,,
+KEY_CHANNELUP,0x192,,,,,,,,,,,,
+KEY_CHANNELDOWN,0x193,,,,,,,,,,,,
+KEY_FIRST,0x194,,,,,,,,,,,,
+KEY_LAST,0x195,,,,,,,,,,,,
+KEY_AB,0x196,,,,,,,,,,,,
+KEY_NEXT,0x197,,,,,,,,,,,,
+KEY_RESTART,0x198,,,,,,,,,,,,
+KEY_SLOW,0x199,,,,,,,,,,,,
+KEY_SHUFFLE,0x19a,,,,,,,,,,,,
+KEY_BREAK,0x19b,,,,,,,,,,,,
+KEY_PREVIOUS,0x19c,,,,,,,,,,,,
+KEY_DIGITS,0x19d,,,,,,,,,,,,
+KEY_TEEN,0x19e,,,,,,,,,,,,
+KEY_TWEN,0x19f,,,,,,,,,,,,
+KEY_VIDEOPHONE,0x1a0,,,,,,,,,,,,
+KEY_GAMES,0x1a1,,,,,,,,,,,,
+KEY_ZOOMIN,0x1a2,,,,,,,,,,,,
+KEY_ZOOMOUT,0x1a3,,,,,,,,,,,,
+KEY_ZOOMRESET,0x1a4,,,,,,,,,,,,
+KEY_WORDPROCESSOR,0x1a5,,,,,,,,,,,,
+KEY_EDITOR,0x1a6,,,,,,,,,,,,
+KEY_SPREADSHEET,0x1a7,,,,,,,,,,,,
+KEY_GRAPHICSEDITOR,0x1a8,,,,,,,,,,,,
+KEY_PRESENTATION,0x1a9,,,,,,,,,,,,
+KEY_DATABASE,0x1aa,,,,,,,,,,,,
+KEY_NEWS,0x1ab,,,,,,,,,,,,
+KEY_VOICEMAIL,0x1ac,,,,,,,,,,,,
+KEY_ADDRESSBOOK,0x1ad,,,,,,,,,,,,
+KEY_MESSENGER,0x1ae,,,,,,,,,,,,
+KEY_DISPLAYTOGGLE,0x1af,,,,,,,,,,,,
+KEY_SPELLCHECK,0x1b0,,,,,,,,,,,,
+KEY_LOGOFF,0x1b1,,,,,,,,,,,,
+KEY_DOLLAR,0x1b2,,,,,,,,,,,,
+KEY_EURO,0x1b3,,,,,,,,,,,,
+KEY_FRAMEBACK,0x1b4,,,,,,,,,,,,
+KEY_FRAMEFORWARD,0x1b5,,,,,,,,,,,,
+KEY_CONTEXT_MENU,0x1b6,,,,,,,,,,,,
+KEY_MEDIA_REPEAT,0x1b7,,,,,,,,,,,,
+KEY_DEL_EOL,0x1c0,,,,,,,,,,,,
+KEY_DEL_EOS,0x1c1,,,,,,,,,,,,
+KEY_INS_LINE,0x1c2,,,,,,,,,,,,
+KEY_DEL_LINE,0x1c3,,,,,,,,,,,,
+KEY_FN,0x1d0,,,,,,,,,,,,
+KEY_FN_ESC,0x1d1,,,,,,,,,,,,
+KEY_FN_F1,0x1d2,,,,,,,,,,,,
+KEY_FN_F2,0x1d3,,,,,,,,,,,,
+KEY_FN_F3,0x1d4,,,,,,,,,,,,
+KEY_FN_F4,0x1d5,,,,,,,,,,,,
+KEY_FN_F5,0x1d6,,,,,,,,,,,,
+KEY_FN_F6,0x1d7,,,,,,,,,,,,
+KEY_FN_F7,0x1d8,,,,,,,,,,,,
+KEY_FN_F8,0x1d9,,,,,,,,,,,,
+KEY_FN_F9,0x1da,,,,,,,,,,,,
+KEY_FN_F10,0x1db,,,,,,,,,,,,
+KEY_FN_F11,0x1dc,,,,,,,,,,,,
+KEY_FN_F12,0x1dd,,,,,,,,,,,,
+KEY_FN_1,0x1de,,,,,,,,,,,,
+KEY_FN_2,0x1df,,,,,,,,,,,,
+KEY_FN_D,0x1e0,,,,,,,,,,,,
+KEY_FN_E,0x1e1,,,,,,,,,,,,
+KEY_FN_F,0x1e2,,,,,,,,,,,,
+KEY_FN_S,0x1e3,,,,,,,,,,,,
+KEY_FN_B,0x1e4,,,,,,,,,,,,
+KEY_BRL_DOT1,0x1f1,,,,,,,,,,,,
+KEY_BRL_DOT2,0x1f2,,,,,,,,,,,,
+KEY_BRL_DOT3,0x1f3,,,,,,,,,,,,
+KEY_BRL_DOT4,0x1f4,,,,,,,,,,,,
+KEY_BRL_DOT5,0x1f5,,,,,,,,,,,,
+KEY_BRL_DOT6,0x1f6,,,,,,,,,,,,
+KEY_BRL_DOT7,0x1f7,,,,,,,,,,,,
+KEY_BRL_DOT8,0x1f8,,,,,,,,,,,,
+KEY_BRL_DOT9,0x1f9,,,,,,,,,,,,
+KEY_BRL_DOT10,0x1fa,,,,,,,,,,,,
+KEY_NUMERIC_0,0x200,,,,,,,,,,,,
+KEY_NUMERIC_1,0x201,,,,,,,,,,,,
+KEY_NUMERIC_2,0x202,,,,,,,,,,,,
+KEY_NUMERIC_3,0x203,,,,,,,,,,,,
+KEY_NUMERIC_4,0x204,,,,,,,,,,,,
+KEY_NUMERIC_5,0x205,,,,,,,,,,,,
+KEY_NUMERIC_6,0x206,,,,,,,,,,,,
+KEY_NUMERIC_7,0x207,,,,,,,,,,,,
+KEY_NUMERIC_8,0x208,,,,,,,,,,,,
+KEY_NUMERIC_9,0x209,,,,,,,,,,,,
+KEY_NUMERIC_STAR,0x20a,,,,,,,,,,,,
+KEY_NUMERIC_POUND,0x20b,,,,,,,,,,,,
+KEY_RFKILL,0x20c,,,,,,,,,,,,
diff --git a/src/vncconnection.c b/src/vncconnection.c
index 3abec29..195200d 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -1569,7 +1569,7 @@ gboolean vnc_connection_key_event(VncConnection *conn, gboolean down_flag,
 	VncConnectionPrivate *priv = conn->priv;
 	guint8 pad[2] = {0};
 
-	VNC_DEBUG("Key event %d %d %d %d", key, scancode, down_flag, priv->has_ext_key_event);
+	VNC_DEBUG("Key event %d %d %d Extended: %d", key, scancode, down_flag, priv->has_ext_key_event);
 	if (priv->has_ext_key_event) {
 		vnc_connection_buffered_write_u8(conn, 255);
 		vnc_connection_buffered_write_u8(conn, 0);
diff --git a/src/vncdisplay.c b/src/vncdisplay.c
index e399b0d..3c522cc 100644
--- a/src/vncdisplay.c
+++ b/src/vncdisplay.c
@@ -77,7 +77,8 @@ struct _VncDisplayPrivate
 	gboolean force_size;
 
 	GSList *preferable_auths;
-	const guint8 const *keycode_map;
+	size_t keycode_maplen;
+	const guint16 const *keycode_map;
 
 	VncGrabSequence *vncgrabseq; /* the configured key sequence */
 	gboolean *vncactiveseq; /* the currently pressed keys */
@@ -753,6 +754,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
 		/* We were pressed, and now we're released, so... */
 		if (priv->down_scancode[i] == key->hardware_keycode) {
 			guint16 scancode = vnc_display_keymap_gdk2rfb(priv->keycode_map,
+								      priv->keycode_maplen,
 								      key->hardware_keycode);
 			/*
 			 * ..send the key release event we're dealing with
@@ -775,6 +777,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
 		for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) {
 			if (priv->down_scancode[i] == 0) {
 				guint16 scancode = vnc_display_keymap_gdk2rfb(priv->keycode_map,
+									      priv->keycode_maplen,
 									      key->hardware_keycode);
 				priv->down_keyval[i] = keyval;
 				priv->down_scancode[i] = key->hardware_keycode;
@@ -840,6 +843,7 @@ static gboolean focus_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSE
 		/* We are currently pressed so... */
 		if (priv->down_scancode[i] != 0) {
 			guint16 scancode = vnc_display_keymap_gdk2rfb(priv->keycode_map,
+								      priv->keycode_maplen,
 								      priv->down_scancode[i]);
 			/* ..send the fake key release event to match */
 			vnc_connection_key_event(priv->conn, 0,
@@ -1444,7 +1448,7 @@ static guint get_scancode_from_keyval(VncDisplay *obj, guint keyval)
 		g_free(keys);
 	}
 
-	return vnc_display_keymap_gdk2rfb(priv->keycode_map, keycode);
+	return vnc_display_keymap_gdk2rfb(priv->keycode_map, priv->keycode_maplen, keycode);
 }
 
 void vnc_display_send_keys_ex(VncDisplay *obj, const guint *keyvals,
@@ -1943,7 +1947,7 @@ static void vnc_display_init(VncDisplay *display)
 	g_signal_connect(G_OBJECT(priv->conn), "vnc-disconnected",
 			 G_CALLBACK(on_disconnected), display);
 
-	priv->keycode_map = vnc_display_keymap_gdk2rfb_table();
+	priv->keycode_map = vnc_display_keymap_gdk2rfb_table(&priv->keycode_maplen);
 }
 
 gboolean vnc_display_set_credential(VncDisplay *obj, int type, const gchar *data)
diff --git a/src/vncdisplaykeymap.c b/src/vncdisplaykeymap.c
index a958737..80d5edc 100644
--- a/src/vncdisplaykeymap.c
+++ b/src/vncdisplaykeymap.c
@@ -37,140 +37,6 @@
  * THE SOFTWARE.
  */
 
-static const guint8 xkbd_keycode_to_rfb_keycode_table[61] = {
-	0xc7,      /*  97  Home   */
-	0xc8,      /*  98  Up     */
-	0xc9,      /*  99  PgUp   */
-	0xcb,      /* 100  Left   */
-	0x4c,      /* 101  KP-5   */
-	0xcd,      /* 102  Right  */
-	0xcf,      /* 103  End    */
-	0xd0,      /* 104  Down   */
-	0xd1,      /* 105  PgDn   */
-	0xd2,      /* 106  Ins    */
-	0xd3,      /* 107  Del    */
-	0x9c,      /* 108  Enter  */
-	0x9d,      /* 109  Ctrl-R */
-	0,         /* 110  Pause  */
-	0xb7,      /* 111  Print  */
-	0xb5,      /* 112  Divide */
-	0xb8,      /* 113  Alt-R  */
-	0xc6,      /* 114  Break  */
-	0,         /* 115 */
-	0,         /* 116 */
-	0,         /* 117 */
-	0,         /* 118 */
-	0,         /* 119 */
-	0,         /* 120 */
-	0,         /* 121 */
-	0,         /* 122 */
-	0,         /* 123 */
-	0,         /* 124 */
-	0,         /* 125 */
-	0,         /* 126 */
-	0,         /* 127 */
-	0,         /* 128 */
-	0x79,      /* 129 Henkan */
-	0,         /* 130 */
-	0x7b,      /* 131 Muhenkan */
-	0,         /* 132 */
-	0x7d,      /* 133 Yen */
-	0,         /* 134 */
-	0,         /* 135 */
-	0x47,      /* 136 KP_7 */
-	0x48,      /* 137 KP_8 */
-	0x49,      /* 138 KP_9 */
-	0x4b,      /* 139 KP_4 */
-	0x4c,      /* 140 KP_5 */
-	0x4d,      /* 141 KP_6 */
-	0x4f,      /* 142 KP_1 */
-	0x50,      /* 143 KP_2 */
-	0x51,      /* 144 KP_3 */
-	0x52,      /* 145 KP_0 */
-	0x53,      /* 146 KP_. */
-	0x47,      /* 147 KP_HOME */
-	0x48,      /* 148 KP_UP */
-	0x49,      /* 149 KP_PgUp */
-	0x4b,      /* 150 KP_Left */
-	0x4c,      /* 151 KP_ */
-	0x4d,      /* 152 KP_Right */
-	0x4f,      /* 153 KP_End */
-	0x50,      /* 154 KP_Down */
-	0x51,      /* 155 KP_PgDn */
-	0x52,      /* 156 KP_Ins */
-	0x53,      /* 157 KP_Del */
-};
-
-/* This table is generated based off the xfree86 -> scancode mapping above
- * and the keycode mappings in /usr/share/X11/xkb/keycodes/evdev
- * and  /usr/share/X11/xkb/keycodes/xfree86
- */
-
-static const guint8 xevdev_keycode_to_rfb_keycode[61] = {
-	0,         /*  97 EVDEV - RO   ("Internet" Keyboards) */
-	0,         /*  98 EVDEV - KATA (Katakana) */
-	0,         /*  99 EVDEV - HIRA (Hiragana) */
-	0x79,      /* 100 EVDEV - HENK (Henkan) */
-	0x70,      /* 101 EVDEV - HKTG (Hiragana/Katakana toggle) */
-	0x7b,      /* 102 EVDEV - MUHE (Muhenkan) */
-	0,         /* 103 EVDEV - JPCM (KPJPComma) */
-	0x9c,      /* 104 KPEN */
-	0x9d,      /* 105 RCTL */
-	0xb5,      /* 106 KPDV */
-	0xb7,      /* 107 PRSC */
-	0xb8,      /* 108 RALT */
-	0,         /* 109 EVDEV - LNFD ("Internet" Keyboards) */
-	0xc7,      /* 110 HOME */
-	0xc8,      /* 111 UP */
-	0xc9,      /* 112 PGUP */
-	0xcb,      /* 113 LEFT */
-	0xcd,      /* 114 RGHT */
-	0xcf,      /* 115 END */
-	0xd0,      /* 116 DOWN */
-	0xd1,      /* 117 PGDN */
-	0xd2,      /* 118 INS */
-	0xd3,      /* 119 DELE */
-	0,         /* 120 EVDEV - I120 ("Internet" Keyboards) */
-	0,         /* 121 EVDEV - MUTE */
-	0,         /* 122 EVDEV - VOL- */
-	0,         /* 123 EVDEV - VOL+ */
-	0,         /* 124 EVDEV - POWR */
-	0,         /* 125 EVDEV - KPEQ */
-	0,         /* 126 EVDEV - I126 ("Internet" Keyboards) */
-	0,         /* 127 EVDEV - PAUS */
-	0,         /* 128 EVDEV - ???? */
-	0,         /* 129 EVDEV - I129 ("Internet" Keyboards) */
-	0xf1,      /* 130 EVDEV - HNGL (Korean Hangul Latin toggle) */
-	0xf2,      /* 131 EVDEV - HJCV (Korean Hangul Hanja toggle) */
-	0x7d,      /* 132 AE13 (Yen)*/
-	0xdb,      /* 133 EVDEV - LWIN */
-	0xdc,      /* 134 EVDEV - RWIN */
-	0xdd,      /* 135 EVDEV - MENU */
-	0,         /* 136 EVDEV - STOP */
-	0,         /* 137 EVDEV - AGAI */
-	0,         /* 138 EVDEV - PROP */
-	0,         /* 139 EVDEV - UNDO */
-	0,         /* 140 EVDEV - FRNT */
-	0,         /* 141 EVDEV - COPY */
-	0,         /* 142 EVDEV - OPEN */
-	0,         /* 143 EVDEV - PAST */
-	0,         /* 144 EVDEV - FIND */
-	0,         /* 145 EVDEV - CUT  */
-	0,         /* 146 EVDEV - HELP */
-	0,         /* 147 EVDEV - I147 */
-	0,         /* 148 EVDEV - I148 */
-	0,         /* 149 EVDEV - I149 */
-	0,         /* 150 EVDEV - I150 */
-	0,         /* 151 EVDEV - I151 */
-	0,         /* 152 EVDEV - I152 */
-	0,         /* 153 EVDEV - I153 */
-	0,         /* 154 EVDEV - I154 */
-	0,         /* 155 EVDEV - I156 */
-	0,         /* 156 EVDEV - I157 */
-	0,         /* 157 EVDEV - I158 */
-};
-
-
 /* keycode translation for sending ISO_Left_Send
  * to vncserver
  */
@@ -182,40 +48,91 @@ static struct {
 
 static unsigned int ref_count_for_untranslated_keys = 0;
 
-/* As best as I can tell, windows passes PC scan codes.  This code definitely
- * won't compile on windows so let's put in a guard anyway */
-
 #if defined(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_xorgkbd2rfb.c"
+/* Xorg Linux + evdev (offset evdev keycodes) */
+#include "vncdisplaykeymap_xorgevdev2rfb.c"
+/* Xorg OS-X aka XQuartz (offset OS-X keycodes) */
+#include "vncdisplaykeymap_xorgxquartz2rfb.c"
+/* Xorg Cygwin aka XWin (offset + mangled XT keycodes) */
+#include "vncdisplaykeymap_xorgxwin2rfb.c"
+
 #define STRPREFIX(a,b) (strncmp((a),(b),strlen((b))) == 0)
 
-const guint8 const *vnc_display_keymap_gdk2rfb_table(void)
+static gboolean check_for_xwin(void)
+{
+	char *vendor = ServerVendor(GDK_DISPLAY());
+
+	if (strstr(vendor, "Cygwin/X"))
+		return TRUE;
+
+	return FALSE;
+}
+
+static gboolean check_for_xquartz(void)
+{
+	int nextensions;
+	int i;
+	gboolean match = FALSE;
+	char **extensions = XListExtensions(GDK_DISPLAY(), &nextensions);
+	for (i = 0 ; extensions != NULL && i < nextensions ; i++) {
+		if (strcmp(extensions[i], "Apple-WM") == 0 ||
+		    strcmp(extensions[i], "Apple-DRI") == 0)
+			match = TRUE;
+	}
+	if (extensions)
+		XFreeExtensionList(extensions);
+
+	return match;
+}
+
+const guint16 const *vnc_display_keymap_gdk2rfb_table(size_t *maplen)
 {
 	XkbDescPtr desc;
-	const gchar *keycodes;
+	const gchar *keycodes = NULL;
+
+	/* 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.
+	 */
 
 	desc = XkbGetKeyboard(GDK_DISPLAY(), XkbGBN_AllComponentsMask,
 			      XkbUseCoreKbd);
-	if (desc == NULL || desc->names == NULL)
-		return NULL;
-
-	keycodes = gdk_x11_get_xatom_name(desc->names->keycodes);
-	XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
+	if (desc) {
+		if (desc->names) {
+			keycodes = gdk_x11_get_xatom_name(desc->names->keycodes);
+			if (!keycodes)
+				g_warning("could not lookup keycode name");
+		}
+		XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
+	}
 
-	if (keycodes == NULL) {
-		g_warning("could not lookup keycode name\n");
-		return NULL;
-	} else if (STRPREFIX(keycodes, "e2vdev_")) {
+	if (check_for_xwin()) {
+		VNC_DEBUG("Using xwin keycode mapping");
+		*maplen = G_N_ELEMENTS(keymap_xorgxwin2rfb);
+		return keymap_xorgxwin2rfb;
+	} else if (check_for_xquartz()) {
+		VNC_DEBUG("Using xquartz keycode mapping");
+		*maplen = G_N_ELEMENTS(keymap_xorgxquartz2rfb);
+		return keymap_xorgxquartz2rfb;
+	} else if (keycodes && STRPREFIX(keycodes, "e2vdev_")) {
 		VNC_DEBUG("Using evdev keycode mapping");
-		return xevdev_keycode_to_rfb_keycode;
-	} else if (STRPREFIX(keycodes, "xfr2ee86_")) {
+		*maplen = G_N_ELEMENTS(keymap_xorgevdev2rfb);
+		return keymap_xorgevdev2rfb;
+	} else if (keycodes && STRPREFIX(keycodes, "xfree86_")) {
 		VNC_DEBUG("Using xfree86 keycode mapping");
-		return xkbd_keycode_to_rfb_keycode_table;
-       } else {
+		*maplen = G_N_ELEMENTS(keymap_xorgkbd2rfb);
+		return keymap_xorgkbd2rfb;
+	} else {
                g_warning("Unknown keycode mapping.\n"
                           "Please report to gtk-vnc-list gnome org\n"
                          "including the following information:\n"
@@ -228,11 +145,36 @@ const guint8 const *vnc_display_keymap_gdk2rfb_table(void)
                return NULL;
 	}
 }
+
+#elif defined(GDK_WINDOWING_WIN32)
+/* Win32 native virtual keycodes */
+#include "vncdisplaykeymap_win322rfb.c"
+
+const guint16 const *vnc_display_keymap_gdk2rfb_table(size_t *maplen)
+{
+	VNC_DEBUG("Using Win32 virtual keycode mapping");
+	*maplen = sizeof(keymap_win322rfb);
+	return keymap_win322rfb;
+}
+
+#elif defined(GDK_WINDOWING_QUARTZ)
+/* OS-X native keycodes */
+#include "vncdisplaykeymap_osx2rfb.c"
+
+const guint16 const *vnc_display_keymap_gdk2rfb_table(size_t *maplen)
+{
+	VNC_DEBUG("Using OS-X virtual keycode mapping");
+	*maplen = sizeof(keymap_osx2rfb);
+	return keymap_osx2rfb;
+}
+
+
 #else
-const guint8 const *vnc_display_keymap_gdk2rfb_table(void)
+
+const guint16 const *vnc_display_keymap_gdk2rfb_table(size_t *maplen)
 {
 	g_warning("Unsupported GDK Windowing platform.\n"
-                 "Please report to gtk-vnc-list gnome org\n"
+		  "Please report to gtk-vnc-list gnome org\n"
 		  "including the following information:\n"
 		  "\n"
 		  "  - Operating system\n"
@@ -241,42 +183,15 @@ const guint8 const *vnc_display_keymap_gdk2rfb_table(void)
 }
 #endif
 
-
-/* All keycodes from 0 to 0xFF correspond to the hardware keycodes generated
- * by a US101 PC keyboard with the following encoding:
- *
- * 0) Sequences of XX are replaced with XX
- * 1) Sequences of 0xe0 XX are replaces with XX | 0x80
- * 2) All other keys are defined below
- */
-
-#define VKC_PAUSE	0x100
-
-guint16 vnc_display_keymap_gdk2rfb(const guint8 const *keycode_map,
+guint16 vnc_display_keymap_gdk2rfb(const guint16 const *keycode_map,
+				   size_t keycode_maplen,
 				   guint16 keycode)
 {
-	if (keycode_map == NULL)
+	if (!keycode_map)
 		return 0;
-
-	if (keycode == GDK_Pause)
-		return VKC_PAUSE;
-
-	if (keycode < 9)
+	if (keycode >= keycode_maplen)
 		return 0;
-
-	if (keycode < 97)
-		return keycode - 8; /* just an offset */
-
-	if (keycode < 158)
-		return keycode_map[keycode - 97];
-
-	if (keycode == 208) /* Hiragana_Katakana */
-		return 0x70;
-
-	if (keycode == 211) /* backslash */
-		return 0x73;
-
-	return 0;
+	return keycode_map[keycode];
 }
 
 /* Set the keymap entries */
diff --git a/src/vncdisplaykeymap.h b/src/vncdisplaykeymap.h
index ad5b47c..7cb9946 100644
--- a/src/vncdisplaykeymap.h
+++ b/src/vncdisplaykeymap.h
@@ -24,8 +24,9 @@
 
 #include <glib.h>
 
-const guint8 const *vnc_display_keymap_gdk2rfb_table(void);
-guint16 vnc_display_keymap_gdk2rfb(const guint8 *keycode_map,
+const guint16 const *vnc_display_keymap_gdk2rfb_table(size_t *maplen);
+guint16 vnc_display_keymap_gdk2rfb(const guint16 *keycode_map,
+				   size_t keycode_maplen,
 				   guint16 keycode);
 void vnc_display_keyval_set_entries(void);
 void vnc_display_keyval_free_entries(void);
-- 
1.7.1.1



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]