]> source.dussan.org Git - tigervnc.git/commitdiff
x0vncserver: keyEvent(): use scancodes if available
authorPeter Korsgaard <peter.korsgaard@barco.com>
Wed, 12 Jul 2017 22:35:57 +0000 (00:35 +0200)
committerPierre Ossman <ossman@cendio.se>
Mon, 11 Sep 2017 14:40:12 +0000 (16:40 +0200)
Use the client provided (using QEMU extendend key event) scancodes if
available instead of reverse mapping the keysym.

X11 unfortunately uses keyboard driver specific keycodes and provides
no direct way to query this, so guess based on the keyboard mapping.

Handle the two most likely keyboard drivers, the old xorgkbd and evdev.

Signed-off-by: Peter Korsgaard <peter.korsgaard@barco.com>
unix/x0vncserver/CMakeLists.txt
unix/x0vncserver/qnum_to_xorgevdev.c [new file with mode: 0644]
unix/x0vncserver/qnum_to_xorgkbd.c [new file with mode: 0644]
unix/x0vncserver/x0vncserver.cxx
unix/x0vncserver/x0vncserver.man

index 82f0d2acce26242881e5aaef6ca91ac66b85bb72..7208f3125d8ac7572bae5452fcb830afa557373d 100644 (file)
@@ -10,6 +10,8 @@ add_executable(x0vncserver
   PollingManager.cxx
   PollingScheduler.cxx
   TimeMillis.cxx
+  qnum_to_xorgevdev.c
+  qnum_to_xorgkbd.c
   x0vncserver.cxx
   XPixelBuffer.cxx
   ../vncconfig/QueryConnectDialog.cxx
diff --git a/unix/x0vncserver/qnum_to_xorgevdev.c b/unix/x0vncserver/qnum_to_xorgevdev.c
new file mode 100644 (file)
index 0000000..357c88d
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * This file is auto-generated from keymaps.csv on 2017-08-28 13:03
+ * Database checksum sha256(f8aeff0c3430077a350e3d7ba2b335b381bd929ac4b193413730a402ff3f0097)
+ * To re-generate, run:
+ *   keymap-gen --lang=stdc code-map keymaps.csv qnum xorgevdev
+*/
+const unsigned short code_map_qnum_to_xorgevdev[254] = {
+  [0x1] = 0x9, /* qnum:1 -> linux:1 (KEY_ESC) -> xorgevdev:9 */
+  [0x2] = 0xa, /* qnum:2 -> linux:2 (KEY_1) -> xorgevdev:10 */
+  [0x3] = 0xb, /* qnum:3 -> linux:3 (KEY_2) -> xorgevdev:11 */
+  [0x4] = 0xc, /* qnum:4 -> linux:4 (KEY_3) -> xorgevdev:12 */
+  [0x5] = 0xd, /* qnum:5 -> linux:5 (KEY_4) -> xorgevdev:13 */
+  [0x6] = 0xe, /* qnum:6 -> linux:6 (KEY_5) -> xorgevdev:14 */
+  [0x7] = 0xf, /* qnum:7 -> linux:7 (KEY_6) -> xorgevdev:15 */
+  [0x8] = 0x10, /* qnum:8 -> linux:8 (KEY_7) -> xorgevdev:16 */
+  [0x9] = 0x11, /* qnum:9 -> linux:9 (KEY_8) -> xorgevdev:17 */
+  [0xa] = 0x12, /* qnum:10 -> linux:10 (KEY_9) -> xorgevdev:18 */
+  [0xb] = 0x13, /* qnum:11 -> linux:11 (KEY_0) -> xorgevdev:19 */
+  [0xc] = 0x14, /* qnum:12 -> linux:12 (KEY_MINUS) -> xorgevdev:20 */
+  [0xd] = 0x15, /* qnum:13 -> linux:13 (KEY_EQUAL) -> xorgevdev:21 */
+  [0xe] = 0x16, /* qnum:14 -> linux:14 (KEY_BACKSPACE) -> xorgevdev:22 */
+  [0xf] = 0x17, /* qnum:15 -> linux:15 (KEY_TAB) -> xorgevdev:23 */
+  [0x10] = 0x18, /* qnum:16 -> linux:16 (KEY_Q) -> xorgevdev:24 */
+  [0x11] = 0x19, /* qnum:17 -> linux:17 (KEY_W) -> xorgevdev:25 */
+  [0x12] = 0x1a, /* qnum:18 -> linux:18 (KEY_E) -> xorgevdev:26 */
+  [0x13] = 0x1b, /* qnum:19 -> linux:19 (KEY_R) -> xorgevdev:27 */
+  [0x14] = 0x1c, /* qnum:20 -> linux:20 (KEY_T) -> xorgevdev:28 */
+  [0x15] = 0x1d, /* qnum:21 -> linux:21 (KEY_Y) -> xorgevdev:29 */
+  [0x16] = 0x1e, /* qnum:22 -> linux:22 (KEY_U) -> xorgevdev:30 */
+  [0x17] = 0x1f, /* qnum:23 -> linux:23 (KEY_I) -> xorgevdev:31 */
+  [0x18] = 0x20, /* qnum:24 -> linux:24 (KEY_O) -> xorgevdev:32 */
+  [0x19] = 0x21, /* qnum:25 -> linux:25 (KEY_P) -> xorgevdev:33 */
+  [0x1a] = 0x22, /* qnum:26 -> linux:26 (KEY_LEFTBRACE) -> xorgevdev:34 */
+  [0x1b] = 0x23, /* qnum:27 -> linux:27 (KEY_RIGHTBRACE) -> xorgevdev:35 */
+  [0x1c] = 0x24, /* qnum:28 -> linux:28 (KEY_ENTER) -> xorgevdev:36 */
+  [0x1d] = 0x25, /* qnum:29 -> linux:29 (KEY_LEFTCTRL) -> xorgevdev:37 */
+  [0x1e] = 0x26, /* qnum:30 -> linux:30 (KEY_A) -> xorgevdev:38 */
+  [0x1f] = 0x27, /* qnum:31 -> linux:31 (KEY_S) -> xorgevdev:39 */
+  [0x20] = 0x28, /* qnum:32 -> linux:32 (KEY_D) -> xorgevdev:40 */
+  [0x21] = 0x29, /* qnum:33 -> linux:33 (KEY_F) -> xorgevdev:41 */
+  [0x22] = 0x2a, /* qnum:34 -> linux:34 (KEY_G) -> xorgevdev:42 */
+  [0x23] = 0x2b, /* qnum:35 -> linux:35 (KEY_H) -> xorgevdev:43 */
+  [0x24] = 0x2c, /* qnum:36 -> linux:36 (KEY_J) -> xorgevdev:44 */
+  [0x25] = 0x2d, /* qnum:37 -> linux:37 (KEY_K) -> xorgevdev:45 */
+  [0x26] = 0x2e, /* qnum:38 -> linux:38 (KEY_L) -> xorgevdev:46 */
+  [0x27] = 0x2f, /* qnum:39 -> linux:39 (KEY_SEMICOLON) -> xorgevdev:47 */
+  [0x28] = 0x30, /* qnum:40 -> linux:40 (KEY_APOSTROPHE) -> xorgevdev:48 */
+  [0x29] = 0x31, /* qnum:41 -> linux:41 (KEY_GRAVE) -> xorgevdev:49 */
+  [0x2a] = 0x32, /* qnum:42 -> linux:42 (KEY_LEFTSHIFT) -> xorgevdev:50 */
+  [0x2b] = 0x33, /* qnum:43 -> linux:43 (KEY_BACKSLASH) -> xorgevdev:51 */
+  [0x2c] = 0x34, /* qnum:44 -> linux:44 (KEY_Z) -> xorgevdev:52 */
+  [0x2d] = 0x35, /* qnum:45 -> linux:45 (KEY_X) -> xorgevdev:53 */
+  [0x2e] = 0x36, /* qnum:46 -> linux:46 (KEY_C) -> xorgevdev:54 */
+  [0x2f] = 0x37, /* qnum:47 -> linux:47 (KEY_V) -> xorgevdev:55 */
+  [0x30] = 0x38, /* qnum:48 -> linux:48 (KEY_B) -> xorgevdev:56 */
+  [0x31] = 0x39, /* qnum:49 -> linux:49 (KEY_N) -> xorgevdev:57 */
+  [0x32] = 0x3a, /* qnum:50 -> linux:50 (KEY_M) -> xorgevdev:58 */
+  [0x33] = 0x3b, /* qnum:51 -> linux:51 (KEY_COMMA) -> xorgevdev:59 */
+  [0x34] = 0x3c, /* qnum:52 -> linux:52 (KEY_DOT) -> xorgevdev:60 */
+  [0x35] = 0x3d, /* qnum:53 -> linux:53 (KEY_SLASH) -> xorgevdev:61 */
+  [0x36] = 0x3e, /* qnum:54 -> linux:54 (KEY_RIGHTSHIFT) -> xorgevdev:62 */
+  [0x37] = 0x3f, /* qnum:55 -> linux:55 (KEY_KPASTERISK) -> xorgevdev:63 */
+  [0x38] = 0x40, /* qnum:56 -> linux:56 (KEY_LEFTALT) -> xorgevdev:64 */
+  [0x39] = 0x41, /* qnum:57 -> linux:57 (KEY_SPACE) -> xorgevdev:65 */
+  [0x3a] = 0x42, /* qnum:58 -> linux:58 (KEY_CAPSLOCK) -> xorgevdev:66 */
+  [0x3b] = 0x43, /* qnum:59 -> linux:59 (KEY_F1) -> xorgevdev:67 */
+  [0x3c] = 0x44, /* qnum:60 -> linux:60 (KEY_F2) -> xorgevdev:68 */
+  [0x3d] = 0x45, /* qnum:61 -> linux:61 (KEY_F3) -> xorgevdev:69 */
+  [0x3e] = 0x46, /* qnum:62 -> linux:62 (KEY_F4) -> xorgevdev:70 */
+  [0x3f] = 0x47, /* qnum:63 -> linux:63 (KEY_F5) -> xorgevdev:71 */
+  [0x40] = 0x48, /* qnum:64 -> linux:64 (KEY_F6) -> xorgevdev:72 */
+  [0x41] = 0x49, /* qnum:65 -> linux:65 (KEY_F7) -> xorgevdev:73 */
+  [0x42] = 0x4a, /* qnum:66 -> linux:66 (KEY_F8) -> xorgevdev:74 */
+  [0x43] = 0x4b, /* qnum:67 -> linux:67 (KEY_F9) -> xorgevdev:75 */
+  [0x44] = 0x4c, /* qnum:68 -> linux:68 (KEY_F10) -> xorgevdev:76 */
+  [0x45] = 0x4d, /* qnum:69 -> linux:69 (KEY_NUMLOCK) -> xorgevdev:77 */
+  [0x46] = 0x4e, /* qnum:70 -> linux:70 (KEY_SCROLLLOCK) -> xorgevdev:78 */
+  [0x47] = 0x4f, /* qnum:71 -> linux:71 (KEY_KP7) -> xorgevdev:79 */
+  [0x48] = 0x50, /* qnum:72 -> linux:72 (KEY_KP8) -> xorgevdev:80 */
+  [0x49] = 0x51, /* qnum:73 -> linux:73 (KEY_KP9) -> xorgevdev:81 */
+  [0x4a] = 0x52, /* qnum:74 -> linux:74 (KEY_KPMINUS) -> xorgevdev:82 */
+  [0x4b] = 0x53, /* qnum:75 -> linux:75 (KEY_KP4) -> xorgevdev:83 */
+  [0x4c] = 0x54, /* qnum:76 -> linux:76 (KEY_KP5) -> xorgevdev:84 */
+  [0x4d] = 0x55, /* qnum:77 -> linux:77 (KEY_KP6) -> xorgevdev:85 */
+  [0x4e] = 0x56, /* qnum:78 -> linux:78 (KEY_KPPLUS) -> xorgevdev:86 */
+  [0x4f] = 0x57, /* qnum:79 -> linux:79 (KEY_KP1) -> xorgevdev:87 */
+  [0x50] = 0x58, /* qnum:80 -> linux:80 (KEY_KP2) -> xorgevdev:88 */
+  [0x51] = 0x59, /* qnum:81 -> linux:81 (KEY_KP3) -> xorgevdev:89 */
+  [0x52] = 0x5a, /* qnum:82 -> linux:82 (KEY_KP0) -> xorgevdev:90 */
+  [0x53] = 0x5b, /* qnum:83 -> linux:83 (KEY_KPDOT) -> xorgevdev:91 */
+  [0x54] = 0x6b, /* qnum:84 -> linux:99 (KEY_SYSRQ) -> xorgevdev:107 */
+  [0x55] = 0xc2, /* qnum:85 -> linux:186 (KEY_F16) -> xorgevdev:194 */
+  [0x56] = 0x5e, /* qnum:86 -> linux:86 (KEY_102ND) -> xorgevdev:94 */
+  [0x57] = 0x5f, /* qnum:87 -> linux:87 (KEY_F11) -> xorgevdev:95 */
+  [0x58] = 0x60, /* qnum:88 -> linux:88 (KEY_F12) -> xorgevdev:96 */
+  [0x59] = 0x7d, /* qnum:89 -> linux:117 (KEY_KPEQUAL) -> xorgevdev:125 */
+  [0x5a] = 0xc6, /* qnum:90 -> linux:190 (KEY_F20) -> xorgevdev:198 */
+  [0x5b] = 0x6d, /* qnum:91 -> linux:101 (KEY_LINEFEED) -> xorgevdev:109 */
+  [0x5c] = 0x67, /* qnum:92 -> linux:95 (KEY_KPJPCOMMA) -> xorgevdev:103 */
+  [0x5d] = 0xbf, /* qnum:93 -> linux:183 (KEY_F13) -> xorgevdev:191 */
+  [0x5e] = 0xc0, /* qnum:94 -> linux:184 (KEY_F14) -> xorgevdev:192 */
+  [0x5f] = 0xc1, /* qnum:95 -> linux:185 (KEY_F15) -> xorgevdev:193 */
+  [0x63] = 0xb1, /* qnum:99 -> linux:169 (KEY_PHONE) -> xorgevdev:177 */
+  [0x64] = 0x8e, /* qnum:100 -> linux:134 (KEY_OPEN) -> xorgevdev:142 */
+  [0x65] = 0x8f, /* qnum:101 -> linux:135 (KEY_PASTE) -> xorgevdev:143 */
+  [0x66] = 0x95, /* qnum:102 -> linux:141 (KEY_SETUP) -> xorgevdev:149 */
+  [0x67] = 0x98, /* qnum:103 -> linux:144 (KEY_FILE) -> xorgevdev:152 */
+  [0x68] = 0x99, /* qnum:104 -> linux:145 (KEY_SENDFILE) -> xorgevdev:153 */
+  [0x69] = 0x9a, /* qnum:105 -> linux:146 (KEY_DELETEFILE) -> xorgevdev:154 */
+  [0x6a] = 0x9f, /* qnum:106 -> linux:151 (KEY_MSDOS) -> xorgevdev:159 */
+  [0x6b] = 0xa1, /* qnum:107 -> linux:153 (KEY_DIRECTION) -> xorgevdev:161 */
+  [0x6c] = 0xa9, /* qnum:108 -> linux:161 (KEY_EJECTCD) -> xorgevdev:169 */
+  [0x6d] = 0xc9, /* qnum:109 -> linux:193 (KEY_F23) -> xorgevdev:201 */
+  [0x6f] = 0xca, /* qnum:111 -> linux:194 (KEY_F24) -> xorgevdev:202 */
+  [0x70] = 0xb2, /* qnum:112 -> linux:170 (KEY_ISO) -> xorgevdev:178 */
+  [0x71] = 0xb6, /* qnum:113 -> linux:174 (KEY_EXIT) -> xorgevdev:182 */
+  [0x72] = 0xb7, /* qnum:114 -> linux:175 (KEY_MOVE) -> xorgevdev:183 */
+  [0x73] = 0x61, /* qnum:115 -> linux:89 (KEY_RO) -> xorgevdev:97 */
+  [0x74] = 0xc7, /* qnum:116 -> linux:191 (KEY_F21) -> xorgevdev:199 */
+  [0x75] = 0xb9, /* qnum:117 -> linux:177 (KEY_SCROLLUP) -> xorgevdev:185 */
+  [0x76] = 0x5d, /* qnum:118 -> linux:85 (KEY_ZENKAKUHANKAKU) -> xorgevdev:93 */
+  [0x77] = 0x63, /* qnum:119 -> linux:91 (KEY_HIRAGANA) -> xorgevdev:99 */
+  [0x78] = 0x62, /* qnum:120 -> linux:90 (KEY_KATAKANA) -> xorgevdev:98 */
+  [0x79] = 0x64, /* qnum:121 -> linux:92 (KEY_HENKAN) -> xorgevdev:100 */
+  [0x7b] = 0x66, /* qnum:123 -> linux:94 (KEY_MUHENKAN) -> xorgevdev:102 */
+  [0x7d] = 0x84, /* qnum:125 -> linux:124 (KEY_YEN) -> xorgevdev:132 */
+  [0x7e] = 0x81, /* qnum:126 -> linux:121 (KEY_KPCOMMA) -> xorgevdev:129 */
+  [0x81] = 0xb3, /* qnum:129 -> linux:171 (KEY_CONFIG) -> xorgevdev:179 */
+  [0x82] = 0x9e, /* qnum:130 -> linux:150 (KEY_WWW) -> xorgevdev:158 */
+  [0x83] = 0xc3, /* qnum:131 -> linux:187 (KEY_F17) -> xorgevdev:195 */
+  [0x84] = 0xc5, /* qnum:132 -> linux:189 (KEY_F19) -> xorgevdev:197 */
+  [0x85] = 0x89, /* qnum:133 -> linux:129 (KEY_AGAIN) -> xorgevdev:137 */
+  [0x86] = 0x8a, /* qnum:134 -> linux:130 (KEY_PROPS) -> xorgevdev:138 */
+  [0x87] = 0x8b, /* qnum:135 -> linux:131 (KEY_UNDO) -> xorgevdev:139 */
+  [0x88] = 0xb8, /* qnum:136 -> linux:176 (KEY_EDIT) -> xorgevdev:184 */
+  [0x89] = 0xbd, /* qnum:137 -> linux:181 (KEY_NEW) -> xorgevdev:189 */
+  [0x8a] = 0xbe, /* qnum:138 -> linux:182 (KEY_REDO) -> xorgevdev:190 */
+  [0x8b] = 0x80, /* qnum:139 -> linux:120 (KEY_SCALE) -> xorgevdev:128 */
+  [0x8c] = 0x8c, /* qnum:140 -> linux:132 (KEY_FRONT) -> xorgevdev:140 */
+  [0x8d] = 0x83, /* qnum:141 -> linux:123 (KEY_HANJA) -> xorgevdev:131 */
+  [0x8e] = 0xf1, /* qnum:142 -> linux:233 (KEY_FORWARDMAIL) -> xorgevdev:241 */
+  [0x8f] = 0xba, /* qnum:143 -> linux:178 (KEY_SCROLLDOWN) -> xorgevdev:186 */
+  [0x90] = 0xad, /* qnum:144 -> linux:165 (KEY_PREVIOUSSONG) -> xorgevdev:173 */
+  [0x92] = 0xa0, /* qnum:146 -> linux:152 (KEY_SCREENLOCK) -> xorgevdev:160 */
+  [0x93] = 0x9b, /* qnum:147 -> linux:147 (KEY_XFER) -> xorgevdev:155 */
+  [0x94] = 0xe6, /* qnum:148 -> linux:222 (KEY_ALTERASE) -> xorgevdev:230 */
+  [0x95] = 0xcb, /* qnum:149 -> linux:195 (unnamed) -> xorgevdev:203 */
+  [0x96] = 0xcc, /* qnum:150 -> linux:196 (unnamed) -> xorgevdev:204 */
+  [0x97] = 0x9d, /* qnum:151 -> linux:149 (KEY_PROG2) -> xorgevdev:157 */
+  [0x98] = 0xb0, /* qnum:152 -> linux:168 (KEY_REWIND) -> xorgevdev:176 */
+  [0x99] = 0xab, /* qnum:153 -> linux:163 (KEY_NEXTSONG) -> xorgevdev:171 */
+  [0x9a] = 0xcd, /* qnum:154 -> linux:197 (unnamed) -> xorgevdev:205 */
+  [0x9b] = 0xce, /* qnum:155 -> linux:198 (unnamed) -> xorgevdev:206 */
+  [0x9c] = 0x68, /* qnum:156 -> linux:96 (KEY_KPENTER) -> xorgevdev:104 */
+  [0x9d] = 0x69, /* qnum:157 -> linux:97 (KEY_RIGHTCTRL) -> xorgevdev:105 */
+  [0x9e] = 0x93, /* qnum:158 -> linux:139 (KEY_MENU) -> xorgevdev:147 */
+  [0x9f] = 0x9c, /* qnum:159 -> linux:148 (KEY_PROG1) -> xorgevdev:156 */
+  [0xa0] = 0x79, /* qnum:160 -> linux:113 (KEY_MUTE) -> xorgevdev:121 */
+  [0xa1] = 0x94, /* qnum:161 -> linux:140 (KEY_CALC) -> xorgevdev:148 */
+  [0xa2] = 0xac, /* qnum:162 -> linux:164 (KEY_PLAYPAUSE) -> xorgevdev:172 */
+  [0xa3] = 0xa8, /* qnum:163 -> linux:160 (KEY_CLOSECD) -> xorgevdev:168 */
+  [0xa4] = 0xae, /* qnum:164 -> linux:166 (KEY_STOPCD) -> xorgevdev:174 */
+  [0xa5] = 0xd5, /* qnum:165 -> linux:205 (KEY_SUSPEND) -> xorgevdev:213 */
+  [0xa6] = 0xa2, /* qnum:166 -> linux:154 (KEY_CYCLEWINDOWS) -> xorgevdev:162 */
+  [0xa7] = 0xcf, /* qnum:167 -> linux:199 (unnamed) -> xorgevdev:207 */
+  [0xa8] = 0xd0, /* qnum:168 -> linux:200 (KEY_PLAYCD) -> xorgevdev:208 */
+  [0xa9] = 0xd1, /* qnum:169 -> linux:201 (KEY_PAUSECD) -> xorgevdev:209 */
+  [0xab] = 0xd2, /* qnum:171 -> linux:202 (KEY_PROG3) -> xorgevdev:210 */
+  [0xac] = 0xd3, /* qnum:172 -> linux:203 (KEY_PROG4) -> xorgevdev:211 */
+  [0xad] = 0xd4, /* qnum:173 -> linux:204 (KEY_DASHBOARD) -> xorgevdev:212 */
+  [0xae] = 0x7a, /* qnum:174 -> linux:114 (KEY_VOLUMEDOWN) -> xorgevdev:122 */
+  [0xaf] = 0xd6, /* qnum:175 -> linux:206 (KEY_CLOSE) -> xorgevdev:214 */
+  [0xb0] = 0x7b, /* qnum:176 -> linux:115 (KEY_VOLUMEUP) -> xorgevdev:123 */
+  [0xb1] = 0xaf, /* qnum:177 -> linux:167 (KEY_RECORD) -> xorgevdev:175 */
+  [0xb2] = 0xb4, /* qnum:178 -> linux:172 (KEY_HOMEPAGE) -> xorgevdev:180 */
+  [0xb3] = 0xd7, /* qnum:179 -> linux:207 (KEY_PLAY) -> xorgevdev:215 */
+  [0xb4] = 0xd8, /* qnum:180 -> linux:208 (KEY_FASTFORWARD) -> xorgevdev:216 */
+  [0xb5] = 0x6a, /* qnum:181 -> linux:98 (KEY_KPSLASH) -> xorgevdev:106 */
+  [0xb6] = 0xd9, /* qnum:182 -> linux:209 (KEY_BASSBOOST) -> xorgevdev:217 */
+  [0xb8] = 0x6c, /* qnum:184 -> linux:100 (KEY_RIGHTALT) -> xorgevdev:108 */
+  [0xb9] = 0xda, /* qnum:185 -> linux:210 (KEY_PRINT) -> xorgevdev:218 */
+  [0xba] = 0xdb, /* qnum:186 -> linux:211 (KEY_HP) -> xorgevdev:219 */
+  [0xbb] = 0xdc, /* qnum:187 -> linux:212 (KEY_CAMERA) -> xorgevdev:220 */
+  [0xbc] = 0x91, /* qnum:188 -> linux:137 (KEY_CUT) -> xorgevdev:145 */
+  [0xbd] = 0xdd, /* qnum:189 -> linux:213 (KEY_SOUND) -> xorgevdev:221 */
+  [0xbe] = 0xde, /* qnum:190 -> linux:214 (KEY_QUESTION) -> xorgevdev:222 */
+  [0xbf] = 0xdf, /* qnum:191 -> linux:215 (KEY_EMAIL) -> xorgevdev:223 */
+  [0xc0] = 0xe0, /* qnum:192 -> linux:216 (KEY_CHAT) -> xorgevdev:224 */
+  [0xc1] = 0x90, /* qnum:193 -> linux:136 (KEY_FIND) -> xorgevdev:144 */
+  [0xc2] = 0xe2, /* qnum:194 -> linux:218 (KEY_CONNECT) -> xorgevdev:226 */
+  [0xc3] = 0xe3, /* qnum:195 -> linux:219 (KEY_FINANCE) -> xorgevdev:227 */
+  [0xc4] = 0xe4, /* qnum:196 -> linux:220 (KEY_SPORT) -> xorgevdev:228 */
+  [0xc5] = 0xe5, /* qnum:197 -> linux:221 (KEY_SHOP) -> xorgevdev:229 */
+  [0xc6] = 0x7f, /* qnum:198 -> linux:119 (KEY_PAUSE) -> xorgevdev:127 */
+  [0xc7] = 0x6e, /* qnum:199 -> linux:102 (KEY_HOME) -> xorgevdev:110 */
+  [0xc8] = 0x6f, /* qnum:200 -> linux:103 (KEY_UP) -> xorgevdev:111 */
+  [0xc9] = 0x70, /* qnum:201 -> linux:104 (KEY_PAGEUP) -> xorgevdev:112 */
+  [0xca] = 0xe7, /* qnum:202 -> linux:223 (KEY_CANCEL) -> xorgevdev:231 */
+  [0xcb] = 0x71, /* qnum:203 -> linux:105 (KEY_LEFT) -> xorgevdev:113 */
+  [0xcc] = 0xe8, /* qnum:204 -> linux:224 (KEY_BRIGHTNESSDOWN) -> xorgevdev:232 */
+  [0xcd] = 0x72, /* qnum:205 -> linux:106 (KEY_RIGHT) -> xorgevdev:114 */
+  [0xce] = 0x7e, /* qnum:206 -> linux:118 (KEY_KPPLUSMINUS) -> xorgevdev:126 */
+  [0xcf] = 0x73, /* qnum:207 -> linux:107 (KEY_END) -> xorgevdev:115 */
+  [0xd0] = 0x74, /* qnum:208 -> linux:108 (KEY_DOWN) -> xorgevdev:116 */
+  [0xd1] = 0x75, /* qnum:209 -> linux:109 (KEY_PAGEDOWN) -> xorgevdev:117 */
+  [0xd2] = 0x76, /* qnum:210 -> linux:110 (KEY_INSERT) -> xorgevdev:118 */
+  [0xd3] = 0x77, /* qnum:211 -> linux:111 (KEY_DELETE) -> xorgevdev:119 */
+  [0xd4] = 0xe9, /* qnum:212 -> linux:225 (KEY_BRIGHTNESSUP) -> xorgevdev:233 */
+  [0xd5] = 0xf2, /* qnum:213 -> linux:234 (KEY_SAVE) -> xorgevdev:242 */
+  [0xd6] = 0xeb, /* qnum:214 -> linux:227 (KEY_SWITCHVIDEOMODE) -> xorgevdev:235 */
+  [0xd7] = 0xec, /* qnum:215 -> linux:228 (KEY_KBDILLUMTOGGLE) -> xorgevdev:236 */
+  [0xd8] = 0xed, /* qnum:216 -> linux:229 (KEY_KBDILLUMDOWN) -> xorgevdev:237 */
+  [0xd9] = 0xee, /* qnum:217 -> linux:230 (KEY_KBDILLUMUP) -> xorgevdev:238 */
+  [0xda] = 0xef, /* qnum:218 -> linux:231 (KEY_SEND) -> xorgevdev:239 */
+  [0xdb] = 0x85, /* qnum:219 -> linux:125 (KEY_LEFTMETA) -> xorgevdev:133 */
+  [0xdc] = 0x86, /* qnum:220 -> linux:126 (KEY_RIGHTMETA) -> xorgevdev:134 */
+  [0xdd] = 0x87, /* qnum:221 -> linux:127 (KEY_COMPOSE) -> xorgevdev:135 */
+  [0xde] = 0x7c, /* qnum:222 -> linux:116 (KEY_POWER) -> xorgevdev:124 */
+  [0xdf] = 0x96, /* qnum:223 -> linux:142 (KEY_SLEEP) -> xorgevdev:150 */
+  [0xe3] = 0x97, /* qnum:227 -> linux:143 (KEY_WAKEUP) -> xorgevdev:151 */
+  [0xe4] = 0xf0, /* qnum:228 -> linux:232 (KEY_REPLY) -> xorgevdev:240 */
+  [0xe5] = 0xe1, /* qnum:229 -> linux:217 (KEY_SEARCH) -> xorgevdev:225 */
+  [0xe6] = 0xa4, /* qnum:230 -> linux:156 (KEY_BOOKMARKS) -> xorgevdev:164 */
+  [0xe7] = 0xb5, /* qnum:231 -> linux:173 (KEY_REFRESH) -> xorgevdev:181 */
+  [0xe8] = 0x88, /* qnum:232 -> linux:128 (KEY_STOP) -> xorgevdev:136 */
+  [0xe9] = 0xa7, /* qnum:233 -> linux:159 (KEY_FORWARD) -> xorgevdev:167 */
+  [0xea] = 0xa6, /* qnum:234 -> linux:158 (KEY_BACK) -> xorgevdev:166 */
+  [0xeb] = 0xa5, /* qnum:235 -> linux:157 (KEY_COMPUTER) -> xorgevdev:165 */
+  [0xec] = 0xa3, /* qnum:236 -> linux:155 (KEY_MAIL) -> xorgevdev:163 */
+  [0xed] = 0xea, /* qnum:237 -> linux:226 (KEY_MEDIA) -> xorgevdev:234 */
+  [0xef] = 0x78, /* qnum:239 -> linux:112 (KEY_MACRO) -> xorgevdev:120 */
+  [0xf0] = 0xf3, /* qnum:240 -> linux:235 (KEY_DOCUMENTS) -> xorgevdev:243 */
+  [0xf1] = 0xf4, /* qnum:241 -> linux:236 (KEY_BATTERY) -> xorgevdev:244 */
+  [0xf2] = 0xf5, /* qnum:242 -> linux:237 (KEY_BLUETOOTH) -> xorgevdev:245 */
+  [0xf3] = 0xf6, /* qnum:243 -> linux:238 (KEY_WLAN) -> xorgevdev:246 */
+  [0xf4] = 0xf7, /* qnum:244 -> linux:239 (KEY_UWB) -> xorgevdev:247 */
+  [0xf5] = 0x92, /* qnum:245 -> linux:138 (KEY_HELP) -> xorgevdev:146 */
+  [0xf6] = 0xbb, /* qnum:246 -> linux:179 (KEY_KPLEFTPAREN) -> xorgevdev:187 */
+  [0xf7] = 0xc4, /* qnum:247 -> linux:188 (KEY_F18) -> xorgevdev:196 */
+  [0xf8] = 0x8d, /* qnum:248 -> linux:133 (KEY_COPY) -> xorgevdev:141 */
+  [0xf9] = 0xc8, /* qnum:249 -> linux:192 (KEY_F22) -> xorgevdev:200 */
+  [0xfb] = 0xbc, /* qnum:251 -> linux:180 (KEY_KPRIGHTPAREN) -> xorgevdev:188 */
+  [0xfd] = 0xaa, /* qnum:253 -> linux:162 (KEY_EJECTCLOSECD) -> xorgevdev:170 */
+};
+const unsigned int code_map_qnum_to_xorgevdev_len = sizeof(code_map_qnum_to_xorgevdev)/sizeof(code_map_qnum_to_xorgevdev[0]);
diff --git a/unix/x0vncserver/qnum_to_xorgkbd.c b/unix/x0vncserver/qnum_to_xorgkbd.c
new file mode 100644 (file)
index 0000000..57c2047
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * This file is auto-generated from keymaps.csv on 2017-08-28 13:04
+ * Database checksum sha256(f8aeff0c3430077a350e3d7ba2b335b381bd929ac4b193413730a402ff3f0097)
+ * To re-generate, run:
+ *   keymap-gen --lang=stdc code-map keymaps.csv qnum xorgkbd
+*/
+const unsigned short code_map_qnum_to_xorgkbd[254] = {
+  [0x1] = 0x9, /* qnum:1 -> linux:1 (KEY_ESC) -> xorgkbd:9 */
+  [0x2] = 0xa, /* qnum:2 -> linux:2 (KEY_1) -> xorgkbd:10 */
+  [0x3] = 0xb, /* qnum:3 -> linux:3 (KEY_2) -> xorgkbd:11 */
+  [0x4] = 0xc, /* qnum:4 -> linux:4 (KEY_3) -> xorgkbd:12 */
+  [0x5] = 0xd, /* qnum:5 -> linux:5 (KEY_4) -> xorgkbd:13 */
+  [0x6] = 0xe, /* qnum:6 -> linux:6 (KEY_5) -> xorgkbd:14 */
+  [0x7] = 0xf, /* qnum:7 -> linux:7 (KEY_6) -> xorgkbd:15 */
+  [0x8] = 0x10, /* qnum:8 -> linux:8 (KEY_7) -> xorgkbd:16 */
+  [0x9] = 0x11, /* qnum:9 -> linux:9 (KEY_8) -> xorgkbd:17 */
+  [0xa] = 0x12, /* qnum:10 -> linux:10 (KEY_9) -> xorgkbd:18 */
+  [0xb] = 0x13, /* qnum:11 -> linux:11 (KEY_0) -> xorgkbd:19 */
+  [0xc] = 0x14, /* qnum:12 -> linux:12 (KEY_MINUS) -> xorgkbd:20 */
+  [0xd] = 0x15, /* qnum:13 -> linux:13 (KEY_EQUAL) -> xorgkbd:21 */
+  [0xe] = 0x16, /* qnum:14 -> linux:14 (KEY_BACKSPACE) -> xorgkbd:22 */
+  [0xf] = 0x17, /* qnum:15 -> linux:15 (KEY_TAB) -> xorgkbd:23 */
+  [0x10] = 0x18, /* qnum:16 -> linux:16 (KEY_Q) -> xorgkbd:24 */
+  [0x11] = 0x19, /* qnum:17 -> linux:17 (KEY_W) -> xorgkbd:25 */
+  [0x12] = 0x1a, /* qnum:18 -> linux:18 (KEY_E) -> xorgkbd:26 */
+  [0x13] = 0x1b, /* qnum:19 -> linux:19 (KEY_R) -> xorgkbd:27 */
+  [0x14] = 0x1c, /* qnum:20 -> linux:20 (KEY_T) -> xorgkbd:28 */
+  [0x15] = 0x1d, /* qnum:21 -> linux:21 (KEY_Y) -> xorgkbd:29 */
+  [0x16] = 0x1e, /* qnum:22 -> linux:22 (KEY_U) -> xorgkbd:30 */
+  [0x17] = 0x1f, /* qnum:23 -> linux:23 (KEY_I) -> xorgkbd:31 */
+  [0x18] = 0x20, /* qnum:24 -> linux:24 (KEY_O) -> xorgkbd:32 */
+  [0x19] = 0x21, /* qnum:25 -> linux:25 (KEY_P) -> xorgkbd:33 */
+  [0x1a] = 0x22, /* qnum:26 -> linux:26 (KEY_LEFTBRACE) -> xorgkbd:34 */
+  [0x1b] = 0x23, /* qnum:27 -> linux:27 (KEY_RIGHTBRACE) -> xorgkbd:35 */
+  [0x1c] = 0x24, /* qnum:28 -> linux:28 (KEY_ENTER) -> xorgkbd:36 */
+  [0x1d] = 0x25, /* qnum:29 -> linux:29 (KEY_LEFTCTRL) -> xorgkbd:37 */
+  [0x1e] = 0x26, /* qnum:30 -> linux:30 (KEY_A) -> xorgkbd:38 */
+  [0x1f] = 0x27, /* qnum:31 -> linux:31 (KEY_S) -> xorgkbd:39 */
+  [0x20] = 0x28, /* qnum:32 -> linux:32 (KEY_D) -> xorgkbd:40 */
+  [0x21] = 0x29, /* qnum:33 -> linux:33 (KEY_F) -> xorgkbd:41 */
+  [0x22] = 0x2a, /* qnum:34 -> linux:34 (KEY_G) -> xorgkbd:42 */
+  [0x23] = 0x2b, /* qnum:35 -> linux:35 (KEY_H) -> xorgkbd:43 */
+  [0x24] = 0x2c, /* qnum:36 -> linux:36 (KEY_J) -> xorgkbd:44 */
+  [0x25] = 0x2d, /* qnum:37 -> linux:37 (KEY_K) -> xorgkbd:45 */
+  [0x26] = 0x2e, /* qnum:38 -> linux:38 (KEY_L) -> xorgkbd:46 */
+  [0x27] = 0x2f, /* qnum:39 -> linux:39 (KEY_SEMICOLON) -> xorgkbd:47 */
+  [0x28] = 0x30, /* qnum:40 -> linux:40 (KEY_APOSTROPHE) -> xorgkbd:48 */
+  [0x29] = 0x31, /* qnum:41 -> linux:41 (KEY_GRAVE) -> xorgkbd:49 */
+  [0x2a] = 0x32, /* qnum:42 -> linux:42 (KEY_LEFTSHIFT) -> xorgkbd:50 */
+  [0x2b] = 0x33, /* qnum:43 -> linux:43 (KEY_BACKSLASH) -> xorgkbd:51 */
+  [0x2c] = 0x34, /* qnum:44 -> linux:44 (KEY_Z) -> xorgkbd:52 */
+  [0x2d] = 0x35, /* qnum:45 -> linux:45 (KEY_X) -> xorgkbd:53 */
+  [0x2e] = 0x36, /* qnum:46 -> linux:46 (KEY_C) -> xorgkbd:54 */
+  [0x2f] = 0x37, /* qnum:47 -> linux:47 (KEY_V) -> xorgkbd:55 */
+  [0x30] = 0x38, /* qnum:48 -> linux:48 (KEY_B) -> xorgkbd:56 */
+  [0x31] = 0x39, /* qnum:49 -> linux:49 (KEY_N) -> xorgkbd:57 */
+  [0x32] = 0x3a, /* qnum:50 -> linux:50 (KEY_M) -> xorgkbd:58 */
+  [0x33] = 0x3b, /* qnum:51 -> linux:51 (KEY_COMMA) -> xorgkbd:59 */
+  [0x34] = 0x3c, /* qnum:52 -> linux:52 (KEY_DOT) -> xorgkbd:60 */
+  [0x35] = 0x3d, /* qnum:53 -> linux:53 (KEY_SLASH) -> xorgkbd:61 */
+  [0x36] = 0x3e, /* qnum:54 -> linux:54 (KEY_RIGHTSHIFT) -> xorgkbd:62 */
+  [0x37] = 0x3f, /* qnum:55 -> linux:55 (KEY_KPASTERISK) -> xorgkbd:63 */
+  [0x38] = 0x40, /* qnum:56 -> linux:56 (KEY_LEFTALT) -> xorgkbd:64 */
+  [0x39] = 0x41, /* qnum:57 -> linux:57 (KEY_SPACE) -> xorgkbd:65 */
+  [0x3a] = 0x42, /* qnum:58 -> linux:58 (KEY_CAPSLOCK) -> xorgkbd:66 */
+  [0x3b] = 0x43, /* qnum:59 -> linux:59 (KEY_F1) -> xorgkbd:67 */
+  [0x3c] = 0x44, /* qnum:60 -> linux:60 (KEY_F2) -> xorgkbd:68 */
+  [0x3d] = 0x45, /* qnum:61 -> linux:61 (KEY_F3) -> xorgkbd:69 */
+  [0x3e] = 0x46, /* qnum:62 -> linux:62 (KEY_F4) -> xorgkbd:70 */
+  [0x3f] = 0x47, /* qnum:63 -> linux:63 (KEY_F5) -> xorgkbd:71 */
+  [0x40] = 0x48, /* qnum:64 -> linux:64 (KEY_F6) -> xorgkbd:72 */
+  [0x41] = 0x49, /* qnum:65 -> linux:65 (KEY_F7) -> xorgkbd:73 */
+  [0x42] = 0x4a, /* qnum:66 -> linux:66 (KEY_F8) -> xorgkbd:74 */
+  [0x43] = 0x4b, /* qnum:67 -> linux:67 (KEY_F9) -> xorgkbd:75 */
+  [0x44] = 0x4c, /* qnum:68 -> linux:68 (KEY_F10) -> xorgkbd:76 */
+  [0x45] = 0x4d, /* qnum:69 -> linux:69 (KEY_NUMLOCK) -> xorgkbd:77 */
+  [0x46] = 0x4e, /* qnum:70 -> linux:70 (KEY_SCROLLLOCK) -> xorgkbd:78 */
+  [0x47] = 0x4f, /* qnum:71 -> linux:71 (KEY_KP7) -> xorgkbd:79 */
+  [0x48] = 0x50, /* qnum:72 -> linux:72 (KEY_KP8) -> xorgkbd:80 */
+  [0x49] = 0x51, /* qnum:73 -> linux:73 (KEY_KP9) -> xorgkbd:81 */
+  [0x4a] = 0x52, /* qnum:74 -> linux:74 (KEY_KPMINUS) -> xorgkbd:82 */
+  [0x4b] = 0x53, /* qnum:75 -> linux:75 (KEY_KP4) -> xorgkbd:83 */
+  [0x4c] = 0x54, /* qnum:76 -> linux:76 (KEY_KP5) -> xorgkbd:84 */
+  [0x4d] = 0x55, /* qnum:77 -> linux:77 (KEY_KP6) -> xorgkbd:85 */
+  [0x4e] = 0x56, /* qnum:78 -> linux:78 (KEY_KPPLUS) -> xorgkbd:86 */
+  [0x4f] = 0x57, /* qnum:79 -> linux:79 (KEY_KP1) -> xorgkbd:87 */
+  [0x50] = 0x58, /* qnum:80 -> linux:80 (KEY_KP2) -> xorgkbd:88 */
+  [0x51] = 0x59, /* qnum:81 -> linux:81 (KEY_KP3) -> xorgkbd:89 */
+  [0x52] = 0x5a, /* qnum:82 -> linux:82 (KEY_KP0) -> xorgkbd:90 */
+  [0x53] = 0x5b, /* qnum:83 -> linux:83 (KEY_KPDOT) -> xorgkbd:91 */
+  [0x54] = 0x6f, /* qnum:84 -> linux:99 (KEY_SYSRQ) -> xorgkbd:111 */
+  [0x55] = 0x79, /* qnum:85 -> linux:186 (KEY_F16) -> xorgkbd:121 */
+  [0x56] = 0x5e, /* qnum:86 -> linux:86 (KEY_102ND) -> xorgkbd:94 */
+  [0x57] = 0x5f, /* qnum:87 -> linux:87 (KEY_F11) -> xorgkbd:95 */
+  [0x58] = 0x60, /* qnum:88 -> linux:88 (KEY_F12) -> xorgkbd:96 */
+  [0x59] = 0x7e, /* qnum:89 -> linux:117 (KEY_KPEQUAL) -> xorgkbd:126 */
+  [0x5d] = 0x76, /* qnum:93 -> linux:183 (KEY_F13) -> xorgkbd:118 */
+  [0x5e] = 0x77, /* qnum:94 -> linux:184 (KEY_F14) -> xorgkbd:119 */
+  [0x5f] = 0x78, /* qnum:95 -> linux:185 (KEY_F15) -> xorgkbd:120 */
+  [0x7d] = 0x85, /* qnum:125 -> linux:124 (KEY_YEN) -> xorgkbd:133 */
+  [0x83] = 0x7a, /* qnum:131 -> linux:187 (KEY_F17) -> xorgkbd:122 */
+  [0x9c] = 0x6c, /* qnum:156 -> linux:96 (KEY_KPENTER) -> xorgkbd:108 */
+  [0x9d] = 0x6d, /* qnum:157 -> linux:97 (KEY_RIGHTCTRL) -> xorgkbd:109 */
+  [0xb5] = 0x70, /* qnum:181 -> linux:98 (KEY_KPSLASH) -> xorgkbd:112 */
+  [0xb8] = 0x71, /* qnum:184 -> linux:100 (KEY_RIGHTALT) -> xorgkbd:113 */
+  [0xc6] = 0x6e, /* qnum:198 -> linux:119 (KEY_PAUSE) -> xorgkbd:110 */
+  [0xc7] = 0x61, /* qnum:199 -> linux:102 (KEY_HOME) -> xorgkbd:97 */
+  [0xc8] = 0x62, /* qnum:200 -> linux:103 (KEY_UP) -> xorgkbd:98 */
+  [0xc9] = 0x63, /* qnum:201 -> linux:104 (KEY_PAGEUP) -> xorgkbd:99 */
+  [0xcb] = 0x64, /* qnum:203 -> linux:105 (KEY_LEFT) -> xorgkbd:100 */
+  [0xcd] = 0x66, /* qnum:205 -> linux:106 (KEY_RIGHT) -> xorgkbd:102 */
+  [0xcf] = 0x67, /* qnum:207 -> linux:107 (KEY_END) -> xorgkbd:103 */
+  [0xd0] = 0x68, /* qnum:208 -> linux:108 (KEY_DOWN) -> xorgkbd:104 */
+  [0xd1] = 0x69, /* qnum:209 -> linux:109 (KEY_PAGEDOWN) -> xorgkbd:105 */
+  [0xd2] = 0x6a, /* qnum:210 -> linux:110 (KEY_INSERT) -> xorgkbd:106 */
+  [0xd3] = 0x6b, /* qnum:211 -> linux:111 (KEY_DELETE) -> xorgkbd:107 */
+  [0xdb] = 0x73, /* qnum:219 -> linux:125 (KEY_LEFTMETA) -> xorgkbd:115 */
+  [0xdc] = 0x74, /* qnum:220 -> linux:126 (KEY_RIGHTMETA) -> xorgkbd:116 */
+  [0xdd] = 0x75, /* qnum:221 -> linux:127 (KEY_COMPOSE) -> xorgkbd:117 */
+};
+const unsigned int code_map_qnum_to_xorgkbd_len = sizeof(code_map_qnum_to_xorgkbd)/sizeof(code_map_qnum_to_xorgkbd[0]);
index 7fb197aad834cc9649c7b8dc382e99ff8d47f192..1ca737814230209d4b8518cce72ce9fef8558ac9 100644 (file)
 #include <x0vncserver/XPixelBuffer.h>
 #include <x0vncserver/PollingScheduler.h>
 
+extern const unsigned short code_map_qnum_to_xorgevdev[];
+extern const unsigned int code_map_qnum_to_xorgevdev_len;
+
+extern const unsigned short code_map_qnum_to_xorgkbd[];
+extern const unsigned int code_map_qnum_to_xorgkbd_len;
+
 // XXX Lynx/OS 2.3: protos for select(), bzero()
 #ifdef Lynx
 #include <sys/proto.h>
@@ -87,6 +93,10 @@ IntParameter queryConnectTimeout("QueryConnectTimeout",
                                  "rejecting the connection",
                                  10);
 StringParameter hostsFile("HostsFile", "File with IP access control rules", "");
+BoolParameter rawKeyboard("RawKeyboard",
+                          "Send keyboard events straight through and "
+                          "avoid mapping them to the current keyboard "
+                          "layout", false);
 
 //
 // Allow the main loop terminate itself gracefully on receiving a signal.
@@ -150,7 +160,8 @@ public:
   XDesktop(Display* dpy_, Geometry *geometry_)
     : dpy(dpy_), geometry(geometry_), pb(0), server(0),
       oldButtonMask(0), haveXtest(false), haveDamage(false),
-      maxButtons(0), running(false), ledMasks(), ledState(0)
+      maxButtons(0), running(false), ledMasks(), ledState(0),
+      codeMap(0), codeMapLen(0)
   {
     int major, minor;
 
@@ -183,6 +194,32 @@ public:
         ledState |= 1u << i;
     }
 
+    // X11 unfortunately uses keyboard driver specific keycodes and provides no
+    // direct way to query this, so guess based on the keyboard mapping
+    XkbDescPtr desc = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
+    if (desc && desc->names) {
+      char *keycodes = XGetAtomName(dpy, desc->names->keycodes);
+
+      if (keycodes) {
+        if (strncmp("evdev", keycodes, strlen("evdev")) == 0) {
+          codeMap = code_map_qnum_to_xorgevdev;
+          codeMapLen = code_map_qnum_to_xorgevdev_len;
+          vlog.info("Using evdev codemap\n");
+        } else if (strncmp("xfree86", keycodes, strlen("xfree86")) == 0) {
+          codeMap = code_map_qnum_to_xorgkbd;
+          codeMapLen = code_map_qnum_to_xorgkbd_len;
+          vlog.info("Using xorgkbd codemap\n");
+        } else {
+          vlog.info("Unknown keycode '%s', no codemap\n", keycodes);
+        }
+        XFree(keycodes);
+      } else {
+        vlog.debug("Unable to get keycode map\n");
+      }
+
+      XkbFreeKeyboard(desc, XkbAllComponentsMask, True);
+    }
+
 #ifdef HAVE_XTEST
     int xtestEventBase;
     int xtestErrorBase;
@@ -297,8 +334,16 @@ public:
 
   virtual void keyEvent(rdr::U32 keysym, rdr::U32 xtcode, bool down) {
 #ifdef HAVE_XTEST
+    int keycode = 0;
     if (!haveXtest) return;
-    int keycode = XKeysymToKeycode(dpy, keysym);
+
+    // Use scan code if provided and mapping exists
+    if (codeMap && rawKeyboard && xtcode < codeMapLen)
+        keycode = codeMap[xtcode];
+
+    if (!keycode)
+        keycode = XKeysymToKeycode(dpy, keysym);
+
     if (keycode)
       XTestFakeKeyEvent(dpy, keycode, down, CurrentTime);
 #endif
@@ -368,6 +413,8 @@ protected:
   int xkbEventBase;
   int ledMasks[N_LEDS];
   unsigned ledState;
+  const unsigned short *codeMap;
+  unsigned codeMapLen;
 };
 
 
index 095f6db363ec3f6cc7e1f1011c0df049779b9412..804a70fc746d4bfee1e68919f9d4112a1c65493a 100644 (file)
@@ -168,6 +168,13 @@ two hex values, prefixed by \fB0x\fP, and separated by \fB->\fP (`dash' and
 `greater than' characters).
 .
 .TP
+.B RawKeyboard
+Send keyboard events straight through and avoid mapping them to the current
+keyboard layout. This effectively makes the keyboard behave according to the
+layout configured on the server instead of the layout configured on the
+client. Default is off.
+.
+.TP
 .B Protocol3.3
 Always use RFB protocol version 3.3 for backwards compatibility with
 badly-behaved clients.  Default is off.