4 * Copyright 1993 Bob Amstadt
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1997 David Faure
7 * Copyright 1998 Morten Welinder
8 * Copyright 1998 Ulrich Weigand
9 * Copyright 1999 Ove Kåven
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include <X11/Xatom.h>
29 #include <X11/keysym.h>
31 #include <X11/Xresource.h>
32 #include <X11/Xutil.h>
34 #include <X11/XKBlib.h>
41 #define NONAMELESSUNION
42 #define NONAMELESSSTRUCT
47 #include "wine/winuser16.h"
51 #include "wine/server.h"
52 #include "wine/unicode.h"
53 #include "wine/debug.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(keyboard
);
56 WINE_DECLARE_DEBUG_CHANNEL(key
);
62 #ifndef BITFIELDS_BIGENDIAN
63 unsigned long count
: 16;
65 unsigned long code
: 8;
66 unsigned long extended
: 1;
67 unsigned long unused
: 2;
68 unsigned long win_internal
: 2;
69 unsigned long context
: 1;
70 unsigned long previous
: 1;
71 unsigned long transition
: 1;
72 #ifdef BITFIELDS_BIGENDIAN
73 unsigned long count
: 16;
79 /* key state table bits:
80 0x80 -> key is pressed
81 0x40 -> key got pressed since last time
82 0x01 -> key is toggled
84 BYTE key_state_table
[256];
86 static BYTE TrackSysKey
= 0; /* determine whether ALT key up will cause a WM_SYSKEYUP
87 or a WM_KEYUP message */
89 static int min_keycode
, max_keycode
, keysyms_per_keycode
;
90 static WORD keyc2vkey
[256], keyc2scan
[256];
92 static int NumLockMask
, AltGrMask
; /* mask in the XKeyEvent state */
93 static int kcControl
, kcAlt
, kcShift
, kcNumLock
, kcCapsLock
; /* keycodes */
95 static char KEYBOARD_MapDeadKeysym(KeySym keysym
);
97 /* Keyboard translation tables */
99 static const WORD main_key_scan_qwerty
[MAIN_LEN
] =
101 /* this is my (102-key) keyboard layout, sorry if it doesn't quite match yours */
102 /* ` 1 2 3 4 5 6 7 8 9 0 - = */
103 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
104 /* q w e r t y u i o p [ ] */
105 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
106 /* a s d f g h j k l ; ' \ */
107 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
108 /* z x c v b n m , . / */
109 0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
110 0x56 /* the 102nd key (actually to the right of l-shift) */
113 static const WORD main_key_scan_abnt_qwerty
[MAIN_LEN
] =
115 /* ` 1 2 3 4 5 6 7 8 9 0 - = */
116 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
117 /* q w e r t y u i o p [ ] */
118 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
119 /* a s d f g h j k l ; ' \ */
120 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
121 /* \ z x c v b n m , . / */
122 0x5e,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
123 0x56, /* the 102nd key (actually to the right of l-shift) */
126 static const WORD main_key_scan_dvorak
[MAIN_LEN
] =
128 /* ` 1 2 3 4 5 6 7 8 9 0 [ ] */
129 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x1A,0x1B,
130 /* ' , . p y f g c r l / = */
131 0x28,0x33,0x34,0x19,0x15,0x21,0x22,0x2E,0x13,0x26,0x35,0x0D,
132 /* a o e u i d h t n s - \ */
133 0x1E,0x18,0x12,0x16,0x17,0x20,0x23,0x14,0x31,0x1F,0x0C,0x2B,
134 /* ; q j k x b m w v z */
135 0x27,0x10,0x24,0x25,0x2D,0x30,0x32,0x11,0x2F,0x2C,
136 0x56 /* the 102nd key (actually to the right of l-shift) */
139 static const WORD main_key_scan_qwerty_jp106
[MAIN_LEN
] =
141 /* this is my (106-key) keyboard layout, sorry if it doesn't quite match yours */
142 /* 1 2 3 4 5 6 7 8 9 0 - ^ \ */
143 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x29,
144 /* q w e r t y u i o p @ [ */
145 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
146 /* a s d f g h j k l ; : ] */
147 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
148 /* z x c v b n m , . / */
149 0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
150 0x56 /* the 102nd key (actually to the right of l-shift) */
154 static const WORD main_key_vkey_qwerty
[MAIN_LEN
] =
156 /* NOTE: this layout must concur with the scan codes layout above */
157 VK_OEM_3
,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS
,VK_OEM_PLUS
,
158 'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4
,VK_OEM_6
,
159 'A','S','D','F','G','H','J','K','L',VK_OEM_1
,VK_OEM_7
,VK_OEM_5
,
160 'Z','X','C','V','B','N','M',VK_OEM_COMMA
,VK_OEM_PERIOD
,VK_OEM_2
,
161 VK_OEM_102
/* the 102nd key (actually to the right of l-shift) */
164 static const WORD main_key_vkey_qwerty_jp106
[MAIN_LEN
] =
166 /* NOTE: this layout must concur with the scan codes layout above */
167 '1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS
,VK_OEM_PLUS
,VK_OEM_3
,
168 'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4
,VK_OEM_6
,
169 'A','S','D','F','G','H','J','K','L',VK_OEM_1
,VK_OEM_7
,VK_OEM_5
,
170 'Z','X','C','V','B','N','M',VK_OEM_COMMA
,VK_OEM_PERIOD
,VK_OEM_2
,
171 VK_OEM_102
/* the 102nd key (actually to the right of l-shift) */
174 static const WORD main_key_vkey_qwerty_v2
[MAIN_LEN
] =
176 /* NOTE: this layout must concur with the scan codes layout above */
177 VK_OEM_5
,'1','2','3','4','5','6','7','8','9','0',VK_OEM_PLUS
,VK_OEM_4
,
178 'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_6
,VK_OEM_1
,
179 'A','S','D','F','G','H','J','K','L',VK_OEM_3
,VK_OEM_7
,VK_OEM_2
,
180 'Z','X','C','V','B','N','M',VK_OEM_COMMA
,VK_OEM_PERIOD
,VK_OEM_MINUS
,
181 VK_OEM_102
/* the 102nd key (actually to the right of l-shift) */
184 static const WORD main_key_vkey_qwertz
[MAIN_LEN
] =
186 /* NOTE: this layout must concur with the scan codes layout above */
187 VK_OEM_3
,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS
,VK_OEM_PLUS
,
188 'Q','W','E','R','T','Z','U','I','O','P',VK_OEM_4
,VK_OEM_6
,
189 'A','S','D','F','G','H','J','K','L',VK_OEM_1
,VK_OEM_7
,VK_OEM_5
,
190 'Y','X','C','V','B','N','M',VK_OEM_COMMA
,VK_OEM_PERIOD
,VK_OEM_2
,
191 VK_OEM_102
/* the 102nd key (actually to the right of l-shift) */
194 static const WORD main_key_vkey_qwertz_105
[MAIN_LEN
] =
196 /* NOTE: this layout must concur with the scan codes layout above */
197 VK_OEM_3
,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS
,VK_OEM_PLUS
,
198 'Q','W','E','R','T','Z','U','I','O','P',VK_OEM_4
,VK_OEM_6
,
199 'A','S','D','F','G','H','J','K','L',VK_OEM_1
,VK_OEM_7
,VK_OEM_5
,
200 VK_OEM_102
,'Y','X','C','V','B','N','M',VK_OEM_COMMA
,VK_OEM_PERIOD
,VK_OEM_2
203 static const WORD main_key_vkey_abnt_qwerty
[MAIN_LEN
] =
205 /* NOTE: this layout must concur with the scan codes layout above */
206 VK_OEM_3
,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS
,VK_OEM_PLUS
,
207 'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4
,VK_OEM_6
,
208 'A','S','D','F','G','H','J','K','L',VK_OEM_1
,VK_OEM_8
,VK_OEM_5
,
209 VK_OEM_7
,'Z','X','C','V','B','N','M',VK_OEM_COMMA
,VK_OEM_PERIOD
,VK_OEM_2
,
210 VK_OEM_102
, /* the 102nd key (actually to the right of l-shift) */
213 static const WORD main_key_vkey_azerty
[MAIN_LEN
] =
215 /* NOTE: this layout must concur with the scan codes layout above */
216 VK_OEM_7
,'1','2','3','4','5','6','7','8','9','0',VK_OEM_4
,VK_OEM_PLUS
,
217 'A','Z','E','R','T','Y','U','I','O','P',VK_OEM_6
,VK_OEM_1
,
218 'Q','S','D','F','G','H','J','K','L','M',VK_OEM_3
,VK_OEM_5
,
219 'W','X','C','V','B','N',VK_OEM_COMMA
,VK_OEM_PERIOD
,VK_OEM_2
,VK_OEM_8
,
220 VK_OEM_102
/* the 102nd key (actually to the right of l-shift) */
223 static const WORD main_key_vkey_dvorak
[MAIN_LEN
] =
225 /* NOTE: this layout must concur with the scan codes layout above */
226 VK_OEM_3
,'1','2','3','4','5','6','7','8','9','0',VK_OEM_4
,VK_OEM_6
,
227 VK_OEM_7
,VK_OEM_COMMA
,VK_OEM_PERIOD
,'P','Y','F','G','C','R','L',VK_OEM_2
,VK_OEM_PLUS
,
228 'A','O','E','U','I','D','H','T','N','S',VK_OEM_MINUS
,VK_OEM_5
,
229 VK_OEM_1
,'Q','J','K','X','B','M','W','V','Z',
230 VK_OEM_102
/* the 102nd key (actually to the right of l-shift) */
233 /*** DEFINE YOUR NEW LANGUAGE-SPECIFIC MAPPINGS BELOW, SEE EXISTING TABLES */
235 /* the VK mappings for the main keyboard will be auto-assigned as before,
236 so what we have here is just the character tables */
237 /* order: Normal, Shift, AltGr, Shift-AltGr */
238 /* We recommend you write just what is guaranteed to be correct (i.e. what's
239 written on the keycaps), not the bunch of special characters behind AltGr
240 and Shift-AltGr if it can vary among different X servers */
241 /* Remember that your 102nd key (to the right of l-shift) should be on a
242 separate line, see existing tables */
243 /* If Wine fails to match your new table, use WINEDEBUG=+key to find out why */
244 /* Remember to also add your new table to the layout index table far below! */
246 /*** German Logitech Desktop Pro keyboard layout */
247 static const char main_key_DE_logitech
[MAIN_LEN
][4] =
249 "^\xb0","1!","2\"","3\xa7","4$","5%","6&","7/{","8([","9)]","0=}","\xdf?\\","'`",
250 "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","\xfc\xdc","+*~",
251 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xf6\xd6","\xe4\xc4","#'",
252 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
256 /*** United States keyboard layout (mostly contributed by Uwe Bonnes) */
257 static const char main_key_US
[MAIN_LEN
][4] =
259 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
260 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
261 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
262 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?"
265 /*** United States keyboard layout (phantom key version) */
266 /* (XFree86 reports the <> key even if it's not physically there) */
267 static const char main_key_US_phantom
[MAIN_LEN
][4] =
269 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
270 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
271 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
272 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
273 "<>" /* the phantom key */
276 /*** United States keyboard layout (dvorak version) */
277 static const char main_key_US_dvorak
[MAIN_LEN
][4] =
279 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","[{","]}",
280 "'\"",",<",".>","pP","yY","fF","gG","cC","rR","lL","/?","=+",
281 "aA","oO","eE","uU","iI","dD","hH","tT","nN","sS","-_","\\|",
282 ";:","qQ","jJ","kK","xX","bB","mM","wW","vV","zZ"
285 /*** British keyboard layout */
286 static const char main_key_UK
[MAIN_LEN
][4] =
288 "`","1!","2\"","3£","4$","5%","6^","7&","8*","9(","0)","-_","=+",
289 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
290 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'@","#~",
291 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
295 /*** French keyboard layout (setxkbmap fr) */
296 static const char main_key_FR
[MAIN_LEN
][4] =
298 "²","&1","é2","\"3","'4","(5","-6","è7","_8","ç9","à0",")°","=+",
299 "aA","zZ","eE","rR","tT","yY","uU","iI","oO","pP","^¨","$£",
300 "qQ","sS","dD","fF","gG","hH","jJ","kK","lL","mM","ù%","*µ",
301 "wW","xX","cC","vV","bB","nN",",?",";.",":/","!§",
305 /*** Icelandic keyboard layout (setxkbmap is) */
306 static const char main_key_IS
[MAIN_LEN
][4] =
308 "°","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","öÖ","-_",
309 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ðÐ","'?",
310 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","æÆ","´Ä","+*",
311 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","þÞ",
315 /*** German keyboard layout (setxkbmap de) */
316 static const char main_key_DE
[MAIN_LEN
][4] =
318 "^°","1!","2\"","3§","4$","5%","6&","7/","8(","9)","0=","ß?","´`",
319 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*",
320 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
321 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
325 /*** German keyboard layout without dead keys */
326 static const char main_key_DE_nodead
[MAIN_LEN
][4] =
328 "^°","1!","2\"","3§","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","´",
329 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
330 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
331 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
335 /*** German keyboard layout without dead keys 105 Keys (contributed by Matthias Fechner)*/
336 static const char main_key_DE_nodead_105
[MAIN_LEN
][4] =
338 "^°","1!","2\"²","3§³","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","'`",
339 "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
340 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
341 "<>|","yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
344 /*** Swiss German keyboard layout (setxkbmap ch -variant de) */
345 static const char main_key_SG
[MAIN_LEN
][4] =
347 "§°","1+","2\"","3*","4ç","5%","6&","7/","8(","9)","0=","'?","^`",
348 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üè","¨!",
349 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öé","äà","$£",
350 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
354 /*** Swiss French keyboard layout (setxkbmap ch -variant fr) */
355 static const char main_key_SF
[MAIN_LEN
][4] =
357 "§°","1+","2\"","3*","4ç","5%","6&","7/","8(","9)","0=","'?","^`",
358 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","èü","¨!",
359 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","éö","àä","$£",
360 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
364 /*** Norwegian keyboard layout (contributed by Ove Kåven) */
365 static const char main_key_NO
[MAIN_LEN
][4] =
367 "|§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","\\`´",
368 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
369 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","øØ","æÆ","'*",
370 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
374 /*** Danish keyboard layout (setxkbmap dk) */
375 static const char main_key_DA
[MAIN_LEN
][4] =
377 "½§","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
378 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
379 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","æÆ","øØ","'*",
380 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
384 /*** Swedish keyboard layout (setxkbmap se) */
385 static const char main_key_SE
[MAIN_LEN
][4] =
387 "§½","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
388 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
389 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
390 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
394 /*** Estonian keyboard layout (setxkbmap ee) */
395 static const char main_key_ET
[MAIN_LEN
][4] =
397 "·~","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
398 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","üÜ","õÕ",
399 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
400 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
404 /*** Canadian French keyboard layout (setxkbmap ca_enhanced) */
405 static const char main_key_CF
[MAIN_LEN
][4] =
407 "#|\\","1!±","2\"@","3/£","4$¢","5%¤","6?¬","7&¦","8*²","9(³","0)¼","-_½","=+¾",
408 "qQ","wW","eE","rR","tT","yY","uU","iI","oO§","pP¶","^^[","¸¨]",
409 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:~","``{","<>}",
410 "zZ","xX","cC","vV","bB","nN","mM",",'-",".","éÉ",
414 /*** Canadian French keyboard layout (setxkbmap ca -variant fr) */
415 static const char main_key_CA_fr
[MAIN_LEN
][4] =
417 "#|","1!","2\"","3/","4$","5%","6?","7&","8*","9(","0)","-_","=+",
418 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","^^","¸¨",
419 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","``","<>",
420 "zZ","xX","cC","vV","bB","nN","mM",",'",".","éÉ",
424 /*** Canadian keyboard layout (setxkbmap ca) */
425 static const char main_key_CA
[MAIN_LEN
][4] =
427 "/\\","1!¹¡","2@²","3#³£","4$¼¤","5%½","6?¾","7&","8*","9(","0)","-_","=+",
428 "qQ","wW","eE","rR","tT","yY","uU","iI","oOøØ","pPþÞ","^¨¨","çÇ~",
429 "aAæÆ","sSߧ","dDðÐ","fF","gG","hH","jJ","kK","lL",";:´","èÈ","àÀ",
430 "zZ","xX","cC¢©","vV","bB","nN","mMµº",",'",".\"·÷","éÉ",
434 /*** Portuguese keyboard layout (setxkbmap pt) */
435 static const char main_key_PT
[MAIN_LEN
][4] =
437 "\\|","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","«»",
438 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","+*","´`",
439 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","çÇ","ºª","~^",
440 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
444 /*** Italian keyboard layout (setxkbmap it) */
445 static const char main_key_IT
[MAIN_LEN
][4] =
447 "\\|","1!","2\"","3£","4$","5%","6&","7/","8(","9)","0=","'?","ì^",
448 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","èé","+*",
449 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","òç","à°","ù§",
450 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
454 /*** Finnish keyboard layout (setxkbmap fi) */
455 static const char main_key_FI
[MAIN_LEN
][4] =
457 "§½","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
458 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
459 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
460 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
464 /*** Bulgarian bds keyboard layout */
465 static const char main_key_BG_bds
[MAIN_LEN
][4] =
467 "`~()","1!","2@2?","3#3+","4$4\"","5%","6^6=","7&7:","8*8/","9(","0)","-_-I","=+.V",
468 "qQ,û","wWóÓ","eEåÅ","rRèÈ","tTøØ","yYùÙ","uUêÊ","iIñÑ","oOäÄ","pPçÇ","[{öÖ","]};",
469 "aAüÜ","sSÿß","dDàÀ","fFîÎ","gGæÆ","hHãÃ","jJòÒ","kKíÍ","lLâÂ",";:ìÌ","'\"÷×","\\|'Û",
470 "zZþÞ","xXéÉ","cCúÚ","vVýÝ","bBôÔ","nNõÕ","mMïÏ",",<ðÐ",".>ëË","/?áÁ",
471 "<>" /* the phantom key */
474 /*** Bulgarian phonetic keyboard layout */
475 static const char main_key_BG_phonetic
[MAIN_LEN
][4] =
477 "`~÷×","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
478 "qQÿß","wWâÂ","eEåÅ","rRðÐ","tTòÒ","yYúÚ","uUóÓ","iIèÈ","oOîÎ","pPïÏ","[{øØ","]}ùÙ",
479 "aAàÀ","sSñÑ","dDäÄ","fFôÔ","gGãÃ","hHõÕ","jJéÉ","kKêÊ","lLëË",";:","'\"","\\|þÞ",
480 "zZçÇ","xXüÜ","cCöÖ","vVæÆ","bBáÁ","nNíÍ","mMìÌ",",<",".>","/?",
481 "<>" /* the phantom key */
484 /*** Belarusian standard keyboard layout (contributed by Hleb Valoska) */
485 /*** It matches belarusian layout for XKB from Alexander Mikhailian */
486 static const char main_key_BY
[MAIN_LEN
][4] =
488 "`~£³","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
489 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oO®¾","pPÚú","[{Èè","]}''",
490 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|/|",
491 "zZÑñ","xXÞþ","cCÓó","vVÍí","bB¦¶","nNÔô","mMØø",",<Ââ",".>Àà","/?.,", "<>|¦",
495 /*** Russian keyboard layout (contributed by Pavel Roskin) */
496 static const char main_key_RU
[MAIN_LEN
][4] =
498 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
499 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
500 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
501 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?"
504 /*** Russian keyboard layout (phantom key version) */
505 static const char main_key_RU_phantom
[MAIN_LEN
][4] =
507 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
508 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
509 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
510 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?",
511 "<>" /* the phantom key */
514 /*** Russian keyboard layout KOI8-R */
515 static const char main_key_RU_koi8r
[MAIN_LEN
][4] =
517 "()","1!","2\"","3/","4$","5:","6,","7.","8;","9?","0%","-_","=+",
518 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
519 "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\|",
520 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà","/?",
521 "<>" /* the phantom key */
524 /*** Russian keyboard layout cp1251 */
525 static const char main_key_RU_cp1251
[MAIN_LEN
][4] =
527 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
528 "qQéÉ","wWöÖ","eEóÓ","rRêÊ","tTåÅ","yYíÍ","uUãÃ","iIøØ","oOùÙ","pPçÇ","[{õÕ","]}úÚ",
529 "aAôÔ","sSûÛ","dDâÂ","fFàÀ","gGïÏ","hHðÐ","jJîÎ","kKëË","lLäÄ",";:æÆ","'\"ýÝ","\\|",
530 "zZÿß","xX÷×","cCñÑ","vVìÌ","bBèÈ","nNòÒ","mMüÜ",",<áÁ",".>þÞ","/?",
531 "<>" /* the phantom key */
534 /*** Russian phonetic keyboard layout */
535 static const char main_key_RU_phonetic
[MAIN_LEN
][4] =
537 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
538 "qQÑñ","wW×÷","eEÅå","rRÒò","tTÔô","yYÙù","uUÕõ","iIÉé","oOÏï","pPÐð","[{Ûû","]}Ýý",
539 "aAÁá","sSÓó","dDÄä","fFÆæ","gGÇç","hHÈè","jJÊê","kKËë","lLÌì",";:","'\"","\\|",
540 "zZÚú","xXØø","cCÃã","vVÖö","bBÂâ","nNÎî","mMÍí",",<",".>","/?",
541 "<>" /* the phantom key */
544 /*** Ukrainian keyboard layout KOI8-U */
545 static const char main_key_UA
[MAIN_LEN
][4] =
547 "`~½","1!1!","2@2\"","3#3'","4$4*","5%5:","6^6,","7&7.","8*8;","9(9(","0)0)","-_-_","=+=+",
548 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}§·",
549 "aAÆæ","sS¦¶","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"¤´","\\|\\|",
550 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?/?",
551 "<>" /* the phantom key */
554 /*** Ukrainian keyboard layout KOI8-U by O. Nykyforchyn */
555 /*** (as it appears on most of keyboards sold today) */
556 static const char main_key_UA_std
[MAIN_LEN
][4] =
558 "½","1!","2\"","3'","4;","5%","6:","7?","8*","9(","0)","-_","=+",
559 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","§·",
560 "Ææ","¦¶","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","¤´","\\/",
561 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà",".,",
562 "<>" /* the phantom key */
565 /*** Russian keyboard layout KOI8-R (pair to the previous) */
566 static const char main_key_RU_std
[MAIN_LEN
][4] =
568 "£³","1!","2\"","3'","4;","5%","6:","7?","8*","9(","0)","-_","=+",
569 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
570 "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\/",
571 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà",".,",
572 "<>" /* the phantom key */
575 /*** Spanish keyboard layout (setxkbmap es) */
576 static const char main_key_ES
[MAIN_LEN
][4] =
578 "ºª","1!","2\"","3·","4$","5%","6&","7/","8(","9)","0=","'?","¡¿",
579 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","`^","+*",
580 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","´¨","çÇ",
581 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
585 /*** Belgian keyboard layout ***/
586 static const char main_key_BE
[MAIN_LEN
][4] =
588 "","&1|","é2@","\"3#","'4","(5","§6^","è7","!8","ç9{","à0}",")°","-_",
589 "aA","zZ","eE¤","rR","tT","yY","uU","iI","oO","pP","^¨[","$*]",
590 "qQ","sSß","dD","fF","gG","hH","jJ","kK","lL","mM","ù%´","µ£`",
591 "wW","xX","cC","vV","bB","nN",",?",";.",":/","=+~",
595 /*** Hungarian keyboard layout (setxkbmap hu) */
596 static const char main_key_HU
[MAIN_LEN
][4] =
598 "0§","1'","2\"","3+","4!","5%","6/","7=","8(","9)","öÖ","üÜ","óÓ",
599 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","õÕ","úÚ",
600 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","éÉ","áÁ","ûÛ",
601 "yY","xX","cC","vV","bB","nN","mM",",?",".:","-_",
605 /*** Polish (programmer's) keyboard layout ***/
606 static const char main_key_PL
[MAIN_LEN
][4] =
608 "`~","1!","2@","3#","4$","5%","6^","7&§","8*","9(","0)","-_","=+",
609 "qQ","wW","eEêÊ","rR","tT","yY","uU","iI","oOóÓ","pP","[{","]}",
610 "aA±¡","sS¶¦","dD","fF","gG","hH","jJ","kK","lL³£",";:","'\"","\\|",
611 "zZ¿¯","xX¼¬","cCæÆ","vV","bB","nNñÑ","mM",",<",".>","/?",
615 /*** Slovenian keyboard layout (setxkbmap si) ***/
616 static const char main_key_SI
[MAIN_LEN
][4] =
618 "¸¨","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
619 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","¹©","ðÐ",
620 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","èÈ","æÆ","¾®",
621 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
625 /*** Serbian keyboard layout (setxkbmap sr) ***/
626 static const char main_key_SR
[MAIN_LEN
][4] =
628 "`~","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
629 "©¹","ªº","Åå","Òò","Ôô","Úú","Õõ","Éé","Ïï","Ðð","Ûû","[]",
630 "Áá","Óó","Ää","Ææ","Çç","Èè","¨¸","Ëë","Ìì","Þþ","«»","-_",
631 "¡±","¯¿","Ãã","×÷","Ââ","Îî","Íí",",;",".:","Öö",
632 "<>" /* the phantom key */
635 /*** Serbian keyboard layout (setxkbmap us,sr) ***/
636 static const char main_key_US_SR
[MAIN_LEN
][4] =
638 "`~","1!","2@2\"","3#","4$","5%","6^6&","7&7/","8*8(","9(9)","0)0=","-_'?","=++*",
639 "qQ©¹","wWªº","eEÅå","rRÒò","tTÔô","yYÚú","uUÕõ","iIÉé","oOÏï","pPÐð","[{Ûû","]}[]",
640 "aAÁá","sSÓó","dDÄä","fFÆæ","gGÇç","hHÈè","jJ¨¸","kKËë","lLÌì",";:Þþ","'\"«»","\\|-_",
641 "zZ¡±","xX¯¿","cCÃã","vV×÷","bBÂâ","nNÎî","mMÍí",",<,;",".>.:","/?Öö",
642 "<>" /* the phantom key */
645 /*** Croatian keyboard layout specific for me <jelly@srk.fer.hr> ***/
646 static const char main_key_HR_jelly
[MAIN_LEN
][4] =
648 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
649 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{¹©","]}ðÐ",
650 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:èÈ","'\"æÆ","\\|¾®",
651 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
655 /*** Croatian keyboard layout (setxkbmap hr) ***/
656 static const char main_key_HR
[MAIN_LEN
][4] =
658 "¸¨","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
659 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","¹©","ðÐ",
660 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","èÈ","æÆ","¾®",
661 "yY","xX","cC","vV","bB","nN","mM",",;",".:","/?",
665 /*** Japanese 106 keyboard layout ***/
666 static const char main_key_JA_jp106
[MAIN_LEN
][4] =
668 "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0~","-=","^~","\\|",
669 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@`","[{",
670 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
671 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
675 /*** Japanese pc98x1 keyboard layout ***/
676 static const char main_key_JA_pc98x1
[MAIN_LEN
][4] =
678 "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0","-=","^`","\\|",
679 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@~","[{",
680 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
681 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
685 /*** Brazilian ABNT-2 keyboard layout (contributed by Raul Gomes Fernandes) */
686 static const char main_key_PT_br
[MAIN_LEN
][4] =
688 "'\"","1!","2@","3#","4$","5%","6¨","7&","8*","9(","0)","-_","=+",
689 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","´`","[{",
690 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","çÇ","~^","]}",
691 "\\|","zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?",
694 /*** Brazilian ABNT-2 keyboard layout with <ALT GR> (contributed by Mauro Carvalho Chehab) */
695 static const char main_key_PT_br_alt_gr
[MAIN_LEN
][4] =
697 "'\"","1!9","2@2","3#3","4$#","5%\"","6(,","7&","8*","9(","0)","-_","=+'",
698 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","4`","[{*",
699 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","gG","~^","]}:",
700 "\\|","zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?0"
703 /*** US international keyboard layout (contributed by Gustavo Noronha (kov@debian.org)) */
704 static const char main_key_US_intl
[MAIN_LEN
][4] =
706 "`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+", "\\|",
707 "qQ", "wW", "eE", "rR", "tT", "yY", "uU", "iI", "oO", "pP", "[{", "]}",
708 "aA", "sS", "dD", "fF", "gG", "hH", "jJ", "kK", "lL", ";:", "'\"",
709 "zZ", "xX", "cC", "vV", "bB", "nN", "mM", ",<", ".>", "/?"
712 /*** Slovak keyboard layout (see cssk_ibm(sk_qwerty) in xkbsel)
713 - dead_abovering replaced with degree - no symbol in iso8859-2
714 - brokenbar replaced with bar */
715 static const char main_key_SK
[MAIN_LEN
][4] =
717 ";0","+1","µ2","¹3","è4","»5","¾6","ý7","á8","í9","é0","=%","'v",
718 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/","ä(",
719 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ô\"","§!","ò)",
720 "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
724 /*** Czech keyboard layout (setxkbmap cz) */
725 static const char main_key_CZ
[MAIN_LEN
][4] =
727 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0","=%","´·",
728 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","ú/",")(",
729 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ù\"","§!","¨'",
730 "yY","xX","cC","vV","bB","nN","mM",",?",".:","-_",
734 /*** Czech keyboard layout (setxkbmap cz_qwerty) */
735 static const char main_key_CZ_qwerty
[MAIN_LEN
][4] =
737 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0","=%","´·",
738 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/",")(",
739 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ù\"","§!","¨'",
740 "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
744 /*** Slovak and Czech (programmer's) keyboard layout (see cssk_dual(cs_sk_ucw)) */
745 static const char main_key_SK_prog
[MAIN_LEN
][4] =
747 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
748 "qQäÄ","wWìÌ","eEéÉ","rRøØ","tT»«","yYýÝ","uUùÙ","iIíÍ","oOóÓ","pPöÖ","[{","]}",
749 "aAáÁ","sS¹©","dDïÏ","fFëË","gGàÀ","hHúÚ","jJüÜ","kKôÔ","lLµ¥",";:","'\"","\\|",
750 "zZ¾®","xX¤","cCèÈ","vVçÇ","bB","nNòÒ","mMåÅ",",<",".>","/?",
754 /*** Czech keyboard layout (see cssk_ibm(cs_qwerty) in xkbsel) */
755 static const char main_key_CS
[MAIN_LEN
][4] =
757 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0½)","=%","",
758 "qQ\\","wW|","eE","rR","tT","yY","uU","iI","oO","pP","ú/[{",")(]}",
759 "aA","sSð","dDÐ","fF[","gG]","hH","jJ","kK³","lL£","ù\"$","§!ß","¨'",
760 "zZ>","xX#","cC&","vV@","bB{","nN}","mM",",?<",".:>","-_*",
764 /*** Latin American keyboard layout (contributed by Gabriel Orlando Garcia) */
765 static const char main_key_LA
[MAIN_LEN
][4] =
767 "|°","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","¿¡",
768 "qQ@","wW","eE","rR","tT","yY","uU","iI","oO","pP","´¨","+*",
769 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","{[^","}]",
770 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
774 /*** Lithuanian keyboard layout (setxkbmap lt) */
775 static const char main_key_LT_B
[MAIN_LEN
][4] =
777 "`~","àÀ","èÈ","æÆ","ëË","áÁ","ðÐ","øØ","ûÛ","¥(","´)","-_","þÞ","\\|",
778 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
779 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"",
780 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
784 /*** Turkish keyboard Layout */
785 static const char main_key_TK
[MAIN_LEN
][4] =
787 "\"é","1!","2'","3^#","4+$","5%","6&","7/{","8([","9)]","0=}","*?\\","-_",
788 "qQ@","wW","eE","rR","tT","yY","uU","ýIî","oO","pP","ðÐ","üÜ~",
789 "aAæ","sSß","dD","fF","gG","hH","jJ","kK","lL","þÞ","iÝ",",;`",
790 "zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:"
793 /*** Turkish keyboard layout (setxkbmap tr) */
794 static const char main_key_TR
[MAIN_LEN
][4] =
796 "\"\\","1!","2'","3^","4+","5%","6&","7/","8(","9)","0=","*?","-_",
797 "qQ","wW","eE","rR","tT","yY","uU","\xb9I","oO","pP","\xbb\xab","üÜ",
798 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xba\xaa","i\0",",;",
799 "zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:",
803 /*** Turkish F keyboard layout (setxkbmap trf) */
804 static const char main_key_TR_F
[MAIN_LEN
][4] =
806 "+*","1!","2\"","3^#","4$","5%","6&","7'","8(","9)","0=","/?","-_",
807 "fF","gG","\xbb\xab","\xb9I","oO","dD","rR","nN","hH","pP","qQ","wW",
808 "uU","i\0","eE","aA","üÜ","tT","kK","mM","lL","yY","\xba\xaa","xX",
809 "jJ","öÖ","vV","cC","çÇ","zZ","sS","bB",".:",",;",
813 /*** Israelian keyboard layout (setxkbmap us,il) */
814 static const char main_key_IL
[MAIN_LEN
][4] =
816 "`~;","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
817 "qQ/","wW'","eE÷","rRø","tTà","yYè","uUå","iIï","oOí","pPô","[{","]}",
818 "aAù","sSã","dDâ","fFë","gGò","hHé","jJç","kKì","lLê",";:ó","\'\",","\\|",
819 "zZæ","xXñ","cCá","vVä","bBð","nNî","mMö",",<ú",".>õ","/?.",
823 /*** Israelian phonetic keyboard layout (setxkbmap us,il_phonetic) */
824 static const char main_key_IL_phonetic
[MAIN_LEN
][4] =
826 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
827 "qQ÷","wWå","eEà","rRø","tTú","yYò","uUå","iIé","oOñ","pPô","[{","]}",
828 "aAà","sSù","dDã","fFô","gGâ","hHä","jJé","kKë","lLì",";:","'\"","\\|",
829 "zZæ","xXç","cCö","vVå","bBá","nNð","mMî",",<",".>","/?",
833 /*** Israelian Saharon keyboard layout (setxkbmap -symbols "us(pc105)+il_saharon") */
834 static const char main_key_IL_saharon
[MAIN_LEN
][4] =
836 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
837 "qQ÷","wWñ","eE","rRø","tTè","yYã","uU","iI","oO","pPô","[{","]}",
838 "aAà","sSå","dDì","fFú","gGâ","hHä","jJù","kKë","lLé",";:","'\"","\\|",
839 "zZæ","xXç","cCö","vVò","bBá","nNð","mMî",",<",".>","/?",
843 /*** Greek keyboard layout (contributed by Kriton Kyrimis <kyrimis@cti.gr>)
844 Greek characters for "wW" and "sS" are omitted to not produce a mismatch
845 message since they have different characters in gr and el XFree86 layouts. */
846 static const char main_key_EL
[MAIN_LEN
][4] =
848 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
849 "qQ;:","wW","eEåÅ","rRñÑ","tTôÔ","yYõÕ","uUèÈ","iIéÉ","oOïÏ","pPðÐ","[{","]}",
850 "aAáÁ","sS","dDäÄ","fFöÖ","gGãÃ","hHçÇ","jJîÎ","kKêÊ","lLëË",";:´¨","'\"","\\|",
851 "zZæÆ","xX÷×","cCøØ","vVùÙ","bBâÂ","nNíÍ","mMìÌ",",<",".>","/?",
855 /*** Thai (Kedmanee) keyboard layout by Supphachoke Suntiwichaya <mrchoke@opentle.org> */
856 static const char main_key_th
[MAIN_LEN
][4] =
858 "`~_%","1!å+","2@/ñ","3#-ò","4$Àó","5%¶ô","6^ØÙ","7&Öß","8*¤õ","9(µö","0)¨÷","-_¢ø","=+ªù",
859 "qQæð","wWä\"","eEÓ®","rR¾±","tTи","yYÑí","uUÕê","iIó","oO¹Ï","pPÂ","[{º°","]}Å,",
860 "aA¿Ä","sS˦","dD¡¯","fF´â","gGà¬","hHéç","jJèë","kKÒÉ","lLÊÈ",";:Ç«","\'\"§.","\\|£¥",
861 "zZ¼(","xX»)","cCá©","vVÍÎ","bBÚ","nN×ì","mM·?",",<Á²",".>ãÌ","/?½Æ"
864 /*** VNC keyboard layout */
865 static const WORD main_key_scan_vnc
[MAIN_LEN
] =
867 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x1A,0x1B,0x27,0x28,0x29,0x33,0x34,0x35,0x2B,
868 0x1E,0x30,0x2E,0x20,0x12,0x21,0x22,0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,0x19,0x10,0x13,0x1F,0x14,0x16,0x2F,0x11,0x2D,0x15,0x2C,
872 static const WORD main_key_vkey_vnc
[MAIN_LEN
] =
874 '1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS
,VK_OEM_PLUS
,VK_OEM_4
,VK_OEM_6
,VK_OEM_1
,VK_OEM_7
,VK_OEM_3
,VK_OEM_COMMA
,VK_OEM_PERIOD
,VK_OEM_2
,VK_OEM_5
,
875 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
879 static const char main_key_vnc
[MAIN_LEN
][4] =
881 "1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+","[{","]}",";:","'\"","`~",",<",".>","/?","\\|",
882 "aA","bB","cC","dD","eE","fF","gG","hH","iI","jJ","kK","lL","mM","nN","oO","pP","qQ","rR","sS","tT","uU","vV","wW","xX","yY","zZ"
885 /*** Dutch keyboard layout (setxkbmap nl) ***/
886 static const char main_key_NL
[MAIN_LEN
][4] =
888 "@§","1!","2\"","3#","4$","5%","6&","7_","8(","9)","0'","/?","°~",
889 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","¨~","*|",
890 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","+±","'`","<>",
891 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-=",
897 /*** Layout table. Add your keyboard mappings to this list */
898 static const struct {
899 LCID lcid
; /* input locale identifier, look for LOCALE_ILANGUAGE
900 in the appropriate dlls/kernel/nls/.nls file */
902 const char (*key
)[MAIN_LEN
][4];
903 const WORD (*scan
)[MAIN_LEN
]; /* scan codes mapping */
904 const WORD (*vkey
)[MAIN_LEN
]; /* virtual key codes mapping */
906 {0x0409, "United States keyboard layout", &main_key_US
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
907 {0x0409, "United States keyboard layout (phantom key version)", &main_key_US_phantom
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
908 {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak
, &main_key_scan_dvorak
, &main_key_vkey_dvorak
},
909 {0x0409, "United States International keyboard layout", &main_key_US_intl
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
910 {0x0809, "British keyboard layout", &main_key_UK
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
911 {0x0407, "German keyboard layout", &main_key_DE
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
912 {0x0407, "German keyboard layout without dead keys", &main_key_DE_nodead
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
913 {0x0407, "German keyboard layout for logitech desktop pro", &main_key_DE_logitech
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
914 {0x0407, "German keyboard layout without dead keys 105", &main_key_DE_nodead_105
, &main_key_scan_qwerty
, &main_key_vkey_qwertz_105
},
915 {0x0807, "Swiss German keyboard layout", &main_key_SG
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
916 {0x100c, "Swiss French keyboard layout", &main_key_SF
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
917 {0x041d, "Swedish keyboard layout", &main_key_SE
, &main_key_scan_qwerty
, &main_key_vkey_qwerty_v2
},
918 {0x0425, "Estonian keyboard layout", &main_key_ET
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
919 {0x0414, "Norwegian keyboard layout", &main_key_NO
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
920 {0x0406, "Danish keyboard layout", &main_key_DA
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
921 {0x040c, "French keyboard layout", &main_key_FR
, &main_key_scan_qwerty
, &main_key_vkey_azerty
},
922 {0x0c0c, "Canadian French keyboard layout", &main_key_CF
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
923 {0x0c0c, "Canadian French keyboard layout (CA_fr)", &main_key_CA_fr
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
924 {0x0c0c, "Canadian keyboard layout", &main_key_CA
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
925 {0x080c, "Belgian keyboard layout", &main_key_BE
, &main_key_scan_qwerty
, &main_key_vkey_azerty
},
926 {0x0816, "Portuguese keyboard layout", &main_key_PT
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
927 {0x0416, "Brazilian ABNT-2 keyboard layout", &main_key_PT_br
, &main_key_scan_abnt_qwerty
, &main_key_vkey_abnt_qwerty
},
928 {0x0416, "Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr
,&main_key_scan_abnt_qwerty
, &main_key_vkey_abnt_qwerty
},
929 {0x040b, "Finnish keyboard layout", &main_key_FI
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
930 {0x0402, "Bulgarian bds keyboard layout", &main_key_BG_bds
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
931 {0x0402, "Bulgarian phonetic keyboard layout", &main_key_BG_phonetic
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
932 {0x0423, "Belarusian keyboard layout", &main_key_BY
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
933 {0x0419, "Russian keyboard layout", &main_key_RU
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
934 {0x0419, "Russian keyboard layout (phantom key version)", &main_key_RU_phantom
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
935 {0x0419, "Russian keyboard layout KOI8-R", &main_key_RU_koi8r
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
936 {0x0419, "Russian keyboard layout cp1251", &main_key_RU_cp1251
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
937 {0x0419, "Russian phonetic keyboard layout", &main_key_RU_phonetic
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
938 {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
939 {0x0422, "Ukrainian keyboard layout (standard)", &main_key_UA_std
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
940 {0x0419, "Russian keyboard layout (standard)", &main_key_RU_std
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
941 {0x040a, "Spanish keyboard layout", &main_key_ES
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
942 {0x0410, "Italian keyboard layout", &main_key_IT
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
943 {0x040f, "Icelandic keyboard layout", &main_key_IS
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
944 {0x040e, "Hungarian keyboard layout", &main_key_HU
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
945 {0x0415, "Polish (programmer's) keyboard layout", &main_key_PL
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
946 {0x0424, "Slovenian keyboard layout", &main_key_SI
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
947 {0x0c1a, "Serbian keyboard layout sr", &main_key_SR
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */
948 {0x0c1a, "Serbian keyboard layout us,sr", &main_key_US_SR
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */
949 {0x041a, "Croatian keyboard layout", &main_key_HR
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
950 {0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
951 {0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106
, &main_key_scan_qwerty_jp106
, &main_key_vkey_qwerty_jp106
},
952 {0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
953 {0x041b, "Slovak keyboard layout", &main_key_SK
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
954 {0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
955 {0x0405, "Czech keyboard layout", &main_key_CS
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
956 {0x0405, "Czech keyboard layout cz", &main_key_CZ
, &main_key_scan_qwerty
, &main_key_vkey_qwertz
},
957 {0x0405, "Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
958 {0x040a, "Latin American keyboard layout", &main_key_LA
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
959 {0x0427, "Lithuanian (Baltic) keyboard layout", &main_key_LT_B
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
960 {0x041f, "Turkish keyboard layout", &main_key_TK
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
961 {0x041f, "Turkish keyboard layout tr", &main_key_TR
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
962 {0x041f, "Turkish keyboard layout trf", &main_key_TR_F
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
963 {0x040d, "Israelian keyboard layout", &main_key_IL
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
964 {0x040d, "Israelian phonetic keyboard layout", &main_key_IL_phonetic
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
965 {0x040d, "Israelian Saharon keyboard layout", &main_key_IL_saharon
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
966 {0x0409, "VNC keyboard layout", &main_key_vnc
, &main_key_scan_vnc
, &main_key_vkey_vnc
},
967 {0x0408, "Greek keyboard layout", &main_key_EL
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
968 {0x041e, "Thai (Kedmanee) keyboard layout", &main_key_th
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
969 {0x0413, "Dutch keyboard layout", &main_key_NL
, &main_key_scan_qwerty
, &main_key_vkey_qwerty
},
971 {0, NULL
, NULL
, NULL
, NULL
} /* sentinel */
973 static unsigned kbd_layout
=0; /* index into above table of layouts */
975 /* maybe more of these scancodes should be extended? */
976 /* extended must be set for ALT_R, CTRL_R,
977 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
978 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
979 /* FIXME should we set extended bit for NumLock ? My
980 * Windows does ... DF */
981 /* Yes, to distinguish based on scan codes, also
982 for PrtScn key ... GA */
984 static const WORD nonchar_key_vkey
[256] =
987 0, 0, 0, 0, 0, 0, 0, 0, /* FF00 */
989 VK_BACK
, VK_TAB
, 0, VK_CLEAR
, 0, VK_RETURN
, 0, 0, /* FF08 */
990 0, 0, 0, VK_PAUSE
, VK_SCROLL
, 0, 0, 0, /* FF10 */
991 0, 0, 0, VK_ESCAPE
, 0, 0, 0, 0, /* FF18 */
993 0, 0, 0, 0, 0, 0, 0, 0, /* FF20 */
994 0, 0, 0, 0, 0, 0, 0, 0, /* FF28 */
995 0, 0, 0, 0, 0, 0, 0, 0, /* FF30 */
996 0, 0, 0, 0, 0, 0, 0, 0, /* FF38 */
997 0, 0, 0, 0, 0, 0, 0, 0, /* FF40 */
998 0, 0, 0, 0, 0, 0, 0, 0, /* FF48 */
1000 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, /* FF50 */
1001 VK_DOWN
, VK_PRIOR
, VK_NEXT
, VK_END
,
1002 0, 0, 0, 0, 0, 0, 0, 0, /* FF58 */
1004 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
1005 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_CANCEL
, 0, 0, 0, 0, /* FF68 */
1006 0, 0, 0, 0, 0, 0, 0, 0, /* FF70 */
1008 0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK
, /* FF78 */
1009 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
1010 0, 0, 0, 0, 0, VK_RETURN
, 0, 0, /* FF88 */
1011 0, 0, 0, 0, 0, VK_HOME
, VK_LEFT
, VK_UP
, /* FF90 */
1012 VK_RIGHT
, VK_DOWN
, VK_PRIOR
, VK_NEXT
, /* FF98 */
1013 VK_END
, VK_CLEAR
, VK_INSERT
, VK_DELETE
,
1014 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
1015 0, 0, VK_MULTIPLY
, VK_ADD
, /* FFA8 */
1016 VK_SEPARATOR
, VK_SUBTRACT
, VK_DECIMAL
, VK_DIVIDE
,
1017 VK_NUMPAD0
, VK_NUMPAD1
, VK_NUMPAD2
, VK_NUMPAD3
, /* FFB0 */
1018 VK_NUMPAD4
, VK_NUMPAD5
, VK_NUMPAD6
, VK_NUMPAD7
,
1019 VK_NUMPAD8
, VK_NUMPAD9
, 0, 0, 0, 0, /* FFB8 */
1022 VK_F3
, VK_F4
, VK_F5
, VK_F6
, VK_F7
, VK_F8
, VK_F9
, VK_F10
, /* FFC0 */
1023 VK_F11
, VK_F12
, VK_F13
, VK_F14
, VK_F15
, VK_F16
, 0, 0, /* FFC8 */
1024 0, 0, 0, 0, 0, 0, 0, 0, /* FFD0 */
1025 0, 0, 0, 0, 0, 0, 0, 0, /* FFD8 */
1027 0, VK_SHIFT
, VK_SHIFT
, VK_CONTROL
, /* FFE0 */
1028 VK_CONTROL
, VK_CAPITAL
, 0, VK_MENU
,
1029 VK_MENU
, VK_MENU
, VK_MENU
, 0, 0, 0, 0, 0, /* FFE8 */
1030 0, 0, 0, 0, 0, 0, 0, 0, /* FFF0 */
1031 0, 0, 0, 0, 0, 0, 0, VK_DELETE
/* FFF8 */
1034 static const WORD nonchar_key_scan
[256] =
1037 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF00 */
1039 0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00, /* FF08 */
1040 0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00, /* FF10 */
1041 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, /* FF18 */
1043 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF20 */
1044 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF28 */
1045 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF30 */
1046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF38 */
1047 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF40 */
1048 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF48 */
1050 0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F, /* FF50 */
1051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF58 */
1053 /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00, /* FF60 */
1054 /*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00, /* FF68 */
1055 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF70 */
1057 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145, /* FF78 */
1058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF80 */
1059 0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00, /* FF88 */
1060 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48, /* FF90 */
1061 0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53, /* FF98 */
1062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFA0 */
1063 0x00, 0x00, 0x37, 0x4E, 0x53, 0x4A, 0x53, 0x135, /* FFA8 */
1064 0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, /* FFB0 */
1065 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, /* FFB8 */
1068 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, /* FFC0 */
1069 0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFC8 */
1070 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFD0 */
1071 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFD8 */
1073 0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38, /* FFE0 */
1074 0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFE8 */
1075 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFF0 */
1076 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153 /* FFF8 */
1080 /* Returns the Windows virtual key code associated with the X event <e> */
1081 /* x11 lock must be held */
1082 static WORD
EVENT_event_to_vkey( XIC xic
, XKeyEvent
*e
)
1089 XmbLookupString(xic
, e
, buf
, sizeof(buf
), &keysym
, &status
);
1091 XLookupString(e
, buf
, sizeof(buf
), &keysym
, NULL
);
1093 if ((e
->state
& NumLockMask
) &&
1094 (keysym
== XK_KP_Separator
|| keysym
== XK_KP_Decimal
||
1095 (keysym
>= XK_KP_0
&& keysym
<= XK_KP_9
)))
1096 /* Only the Keypad keys 0-9 and . send different keysyms
1097 * depending on the NumLock state */
1098 return nonchar_key_vkey
[keysym
& 0xFF];
1100 TRACE_(key
)("e->keycode = %x\n", e
->keycode
);
1102 return keyc2vkey
[e
->keycode
];
1105 static BOOL NumState
=FALSE
, CapsState
=FALSE
;
1108 /***********************************************************************
1109 * X11DRV_send_keyboard_input
1111 void X11DRV_send_keyboard_input( WORD wVk
, WORD wScan
, DWORD dwFlags
, DWORD time
,
1112 DWORD dwExtraInfo
, UINT injected_flags
)
1116 KBDLLHOOKSTRUCT hook
;
1121 /* strip left/right for menu, control, shift */
1122 if (wVk
== VK_LMENU
|| wVk
== VK_RMENU
)
1123 wVkStripped
= VK_MENU
;
1124 else if (wVk
== VK_LCONTROL
|| wVk
== VK_RCONTROL
)
1125 wVkStripped
= VK_CONTROL
;
1126 else if (wVk
== VK_LSHIFT
|| wVk
== VK_RSHIFT
)
1127 wVkStripped
= VK_SHIFT
;
1132 keylp
.lp1
.count
= 1;
1133 keylp
.lp1
.code
= wScan
;
1134 keylp
.lp1
.extended
= (dwFlags
& KEYEVENTF_EXTENDEDKEY
) != 0;
1135 keylp
.lp1
.win_internal
= 0; /* this has something to do with dialogs,
1136 * don't remember where I read it - AK */
1137 /* it's '1' under windows, when a dialog box appears
1138 * and you press one of the underlined keys - DF*/
1140 /* note that there is a test for all this */
1141 if (dwFlags
& KEYEVENTF_KEYUP
)
1144 if ((key_state_table
[VK_MENU
] & 0x80) &&
1145 ((wVkStripped
== VK_MENU
) || (wVkStripped
== VK_CONTROL
)
1146 || !(key_state_table
[VK_CONTROL
] & 0x80)))
1148 if( TrackSysKey
== VK_MENU
|| /* <ALT>-down/<ALT>-up sequence */
1149 (wVkStripped
!= VK_MENU
)) /* <ALT>-down...<something else>-up */
1150 message
= WM_SYSKEYUP
;
1153 key_state_table
[wVk
] &= ~0x80;
1154 key_state_table
[wVkStripped
] &= ~0x80;
1155 keylp
.lp1
.previous
= 1;
1156 keylp
.lp1
.transition
= 1;
1160 keylp
.lp1
.previous
= (key_state_table
[wVk
] & 0x80) != 0;
1161 keylp
.lp1
.transition
= 0;
1162 if (!(key_state_table
[wVk
] & 0x80)) key_state_table
[wVk
] ^= 0x01;
1163 key_state_table
[wVk
] |= 0xc0;
1164 key_state_table
[wVkStripped
] |= 0xc0;
1166 message
= WM_KEYDOWN
;
1167 if ((key_state_table
[VK_MENU
] & 0x80) && !(key_state_table
[VK_CONTROL
] & 0x80))
1169 message
= WM_SYSKEYDOWN
;
1170 TrackSysKey
= wVkStripped
;
1174 keylp
.lp1
.context
= (key_state_table
[VK_MENU
] & 0x80) != 0; /* 1 if alt */
1176 TRACE_(key
)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
1177 wVk
, keylp
.lp2
, key_state_table
[wVk
] );
1180 hook
.scanCode
= wScan
;
1181 hook
.flags
= (keylp
.lp2
>> 24) | injected_flags
;
1183 hook
.dwExtraInfo
= dwExtraInfo
;
1184 if (HOOK_CallHooks( WH_KEYBOARD_LL
, HC_ACTION
, message
, (LPARAM
)&hook
, TRUE
)) return;
1186 SERVER_START_REQ( send_hardware_message
)
1188 req
->id
= (injected_flags
& LLKHF_INJECTED
) ? 0 : GetCurrentThreadId();
1192 req
->lparam
= keylp
.lp2
;
1193 req
->x
= cursor_pos
.x
;
1194 req
->y
= cursor_pos
.y
;
1196 req
->info
= dwExtraInfo
;
1197 wine_server_call( req
);
1203 /**********************************************************************
1204 * KEYBOARD_GenerateMsg
1206 * Generate Down+Up messages when NumLock or CapsLock is pressed.
1208 * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
1211 static void KEYBOARD_GenerateMsg( WORD vkey
, WORD scan
, int Evtype
, DWORD event_time
)
1213 BOOL
* State
= (vkey
==VK_NUMLOCK
? &NumState
: &CapsState
);
1217 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
1218 don't treat it. It's from the same key press. Then the state goes to ON.
1219 And from there, a 'release' event will switch off the toggle key. */
1221 TRACE("INTERM : don't treat release of toggle key. key_state_table[%#x] = %#x\n",
1222 vkey
,key_state_table
[vkey
]);
1225 down
= (vkey
==VK_NUMLOCK
? KEYEVENTF_EXTENDEDKEY
: 0);
1226 up
= (vkey
==VK_NUMLOCK
? KEYEVENTF_EXTENDEDKEY
: 0) | KEYEVENTF_KEYUP
;
1227 if ( key_state_table
[vkey
] & 0x1 ) /* it was ON */
1229 if (Evtype
!=KeyPress
)
1231 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
1232 X11DRV_send_keyboard_input( vkey
, scan
, down
, event_time
, 0, 0 );
1233 X11DRV_send_keyboard_input( vkey
, scan
, up
, event_time
, 0, 0 );
1235 key_state_table
[vkey
] &= ~0x01; /* Toggle state to off. */
1238 else /* it was OFF */
1239 if (Evtype
==KeyPress
)
1241 TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
1242 X11DRV_send_keyboard_input( vkey
, scan
, down
, event_time
, 0, 0 );
1243 X11DRV_send_keyboard_input( vkey
, scan
, up
, event_time
, 0, 0 );
1244 *State
=TRUE
; /* Goes to intermediary state before going to ON */
1245 key_state_table
[vkey
] |= 0x01; /* Toggle state to on. */
1250 /***********************************************************************
1251 * KEYBOARD_UpdateOneState
1253 * Updates internal state for <vkey>, depending on key <state> under X
1256 inline static void KEYBOARD_UpdateOneState ( int vkey
, int state
, DWORD time
)
1258 /* Do something if internal table state != X state for keycode */
1259 if (((key_state_table
[vkey
] & 0x80)!=0) != state
)
1261 TRACE("Adjusting state for vkey %#.2x. State before %#.2x\n",
1262 vkey
, key_state_table
[vkey
]);
1264 /* Fake key being pressed inside wine */
1265 X11DRV_send_keyboard_input( vkey
, 0, state
? 0 : KEYEVENTF_KEYUP
, time
, 0, 0 );
1267 TRACE("State after %#.2x\n",key_state_table
[vkey
]);
1271 /***********************************************************************
1272 * X11DRV_KeymapNotify
1274 * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
1276 * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
1277 * from wine to another application and back.
1278 * Toggle keys are handled in HandleEvent.
1280 void X11DRV_KeymapNotify( HWND hwnd
, XEvent
*event
)
1282 int i
, j
, alt
, control
, shift
;
1283 DWORD time
= GetCurrentTime();
1285 alt
= control
= shift
= 0;
1286 for (i
= 0; i
< 32; i
++)
1288 if (!event
->xkeymap
.key_vector
[i
]) continue;
1289 for (j
= 0; j
< 8; j
++)
1291 if (!(event
->xkeymap
.key_vector
[i
] & (1<<j
))) continue;
1292 switch(keyc2vkey
[(i
* 8) + j
] & 0xff)
1294 case VK_MENU
: alt
= 1; break;
1295 case VK_CONTROL
: control
= 1; break;
1296 case VK_SHIFT
: shift
= 1; break;
1300 KEYBOARD_UpdateOneState( VK_MENU
, alt
, time
);
1301 KEYBOARD_UpdateOneState( VK_CONTROL
, control
, time
);
1302 KEYBOARD_UpdateOneState( VK_SHIFT
, shift
, time
);
1305 /***********************************************************************
1308 * Handle a X key event
1310 void X11DRV_KeyEvent( HWND hwnd
, XEvent
*xev
)
1312 XKeyEvent
*event
= &xev
->xkey
;
1315 WORD vkey
= 0, bScan
;
1318 XIC xic
= X11DRV_get_ic( hwnd
);
1319 DWORD event_time
= EVENT_x11_time_to_win32_time(event
->time
);
1322 TRACE_(key
)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
1323 event
->type
, event
->window
, event
->state
, event
->keycode
);
1327 ascii_chars
= XmbLookupString(xic
, event
, Str
, sizeof(Str
), &keysym
, &status
);
1329 ascii_chars
= XLookupString(event
, Str
, sizeof(Str
), &keysym
, NULL
);
1330 wine_tsx11_unlock();
1332 /* Ignore some unwanted events */
1333 if ((keysym
>= XK_ISO_Lock
&& keysym
<= XK_ISO_Last_Group_Lock
) ||
1334 keysym
== XK_Mode_switch
)
1337 TRACE("Ignoring %s keyboard event\n", XKeysymToString(keysym
));
1338 wine_tsx11_unlock();
1342 TRACE_(key
)("state = %X nbyte = %d, status 0x%x\n", event
->state
, ascii_chars
, status
);
1344 if (status
== XBufferOverflow
)
1345 ERR("Buffer Overflow need %i!\n",ascii_chars
);
1347 if (status
== XLookupChars
)
1349 X11DRV_XIMLookupChars( Str
, ascii_chars
);
1353 /* If XKB extensions are used, the state mask for AltGr will use the group
1354 index instead of the modifier mask. The group index is set in bits
1355 13-14 of the state field in the XKeyEvent structure. So if AltGr is
1356 pressed, look if the group index is different than 0. From XKB
1357 extension documentation, the group index for AltGr should be 2
1358 (event->state = 0x2000). It's probably better to not assume a
1359 predefined group index and find it dynamically
1361 Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
1362 /* Save also all possible modifier states. */
1363 AltGrMask
= event
->state
& (0x6000 | Mod1Mask
| Mod2Mask
| Mod3Mask
| Mod4Mask
| Mod5Mask
);
1365 Str
[ascii_chars
] = '\0';
1370 ksname
= XKeysymToString(keysym
);
1371 wine_tsx11_unlock();
1374 TRACE_(key
)("%s : keysym=%lX (%s), # of chars=%d / 0x%02x / '%s'\n",
1375 (event
->type
== KeyPress
) ? "KeyPress" : "KeyRelease",
1376 keysym
, ksname
, ascii_chars
, Str
[0] & 0xff, Str
);
1380 vkey
= EVENT_event_to_vkey(xic
,event
);
1381 /* X returns keycode 0 for composed characters */
1382 if (!vkey
&& ascii_chars
) vkey
= VK_NONAME
;
1383 wine_tsx11_unlock();
1385 TRACE_(key
)("keycode 0x%x converted to vkey 0x%x\n",
1386 event
->keycode
, vkey
);
1390 switch (vkey
& 0xff)
1393 KEYBOARD_GenerateMsg( VK_NUMLOCK
, 0x45, event
->type
, event_time
);
1396 TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event
->type
,key_state_table
[vkey
]);
1397 KEYBOARD_GenerateMsg( VK_CAPITAL
, 0x3A, event
->type
, event_time
);
1398 TRACE("State after : %#.2x\n",key_state_table
[vkey
]);
1401 /* Adjust the NUMLOCK state if it has been changed outside wine */
1402 if (!(key_state_table
[VK_NUMLOCK
] & 0x01) != !(event
->state
& NumLockMask
))
1404 TRACE("Adjusting NumLock state.\n");
1405 KEYBOARD_GenerateMsg( VK_NUMLOCK
, 0x45, KeyPress
, event_time
);
1406 KEYBOARD_GenerateMsg( VK_NUMLOCK
, 0x45, KeyRelease
, event_time
);
1408 /* Adjust the CAPSLOCK state if it has been changed outside wine */
1409 if (!(key_state_table
[VK_CAPITAL
] & 0x01) != !(event
->state
& LockMask
))
1411 TRACE("Adjusting Caps Lock state.\n");
1412 KEYBOARD_GenerateMsg( VK_CAPITAL
, 0x3A, KeyPress
, event_time
);
1413 KEYBOARD_GenerateMsg( VK_CAPITAL
, 0x3A, KeyRelease
, event_time
);
1415 /* Not Num nor Caps : end of intermediary states for both. */
1419 bScan
= keyc2scan
[event
->keycode
] & 0xFF;
1420 TRACE_(key
)("bScan = 0x%02x.\n", bScan
);
1423 if ( event
->type
== KeyRelease
) dwFlags
|= KEYEVENTF_KEYUP
;
1424 if ( vkey
& 0x100 ) dwFlags
|= KEYEVENTF_EXTENDEDKEY
;
1426 X11DRV_send_keyboard_input( vkey
& 0xff, bScan
, dwFlags
, event_time
, 0, 0 );
1431 /**********************************************************************
1432 * X11DRV_KEYBOARD_DetectLayout
1434 * Called from X11DRV_InitKeyboard
1435 * This routine walks through the defined keyboard layouts and selects
1436 * whichever matches most closely.
1437 * X11 lock must be held.
1440 X11DRV_KEYBOARD_DetectLayout (void)
1442 Display
*display
= thread_display();
1443 unsigned current
, match
, mismatch
, seq
, i
, syms
;
1444 int score
, keyc
, key
, pkey
, ok
;
1446 const char (*lkey
)[MAIN_LEN
][4];
1447 unsigned max_seq
= 0;
1448 int max_score
= 0, ismatch
= 0;
1452 syms
= keysyms_per_keycode
;
1454 WARN("%d keysyms per keycode not supported, set to 4\n", syms
);
1457 for (current
= 0; main_key_tab
[current
].comment
; current
++) {
1458 TRACE("Attempting to match against \"%s\"\n", main_key_tab
[current
].comment
);
1463 lkey
= main_key_tab
[current
].key
;
1465 for (keyc
= min_keycode
; keyc
<= max_keycode
; keyc
++) {
1466 /* get data for keycode from X server */
1467 for (i
= 0; i
< syms
; i
++) {
1468 keysym
= XKeycodeToKeysym (display
, keyc
, i
);
1469 /* Allow both one-byte and two-byte national keysyms */
1470 if ((keysym
< 0x8000) && (keysym
!= ' '))
1473 if (!use_xkb
|| !XkbTranslateKeySym(display
, &keysym
, 0, &ckey
[i
], 1, NULL
))
1476 TRACE("XKB could not translate keysym %ld\n", keysym
);
1477 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1478 * with appropriate ShiftMask and Mode_switch, use XLookupString
1479 * to get character in the local encoding.
1481 ckey
[i
] = keysym
& 0xFF;
1485 ckey
[i
] = KEYBOARD_MapDeadKeysym(keysym
);
1489 /* search for a match in layout table */
1490 /* right now, we just find an absolute match for defined positions */
1491 /* (undefined positions are ignored, so if it's defined as "3#" in */
1492 /* the table, it's okay that the X server has "3#£", for example) */
1493 /* however, the score will be higher for longer matches */
1494 for (key
= 0; key
< MAIN_LEN
; key
++) {
1495 for (ok
= 0, i
= 0; (ok
>= 0) && (i
< syms
); i
++) {
1496 if ((*lkey
)[key
][i
] && ((*lkey
)[key
][i
] == ckey
[i
]))
1498 if ((*lkey
)[key
][i
] && ((*lkey
)[key
][i
] != ckey
[i
]))
1506 /* count the matches and mismatches */
1509 /* and how much the keycode order matches */
1510 if (key
> pkey
) seq
++;
1513 /* print spaces instead of \0's */
1514 for (i
= 0; i
< sizeof(ckey
); i
++) if (!ckey
[i
]) ckey
[i
] = ' ';
1515 TRACE_(key
)("mismatch for keysym 0x%04lX, keycode %d, got %c%c%c%c\n",
1516 keysym
, keyc
, ckey
[0], ckey
[1], ckey
[2], ckey
[3]);
1522 TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1523 match
, mismatch
, seq
, score
);
1524 if ((score
> max_score
) ||
1525 ((score
== max_score
) && (seq
> max_seq
))) {
1526 /* best match so far */
1527 kbd_layout
= current
;
1530 ismatch
= !mismatch
;
1533 /* we're done, report results if necessary */
1535 WARN("Using closest match (%s) for scan/virtual codes mapping.\n",
1536 main_key_tab
[kbd_layout
].comment
);
1538 TRACE("detected layout is \"%s\"\n", main_key_tab
[kbd_layout
].comment
);
1541 /**********************************************************************
1542 * X11DRV_InitKeyboard
1544 void X11DRV_InitKeyboard(void)
1546 Display
*display
= thread_display();
1548 XModifierKeymap
*mmp
;
1552 WORD scan
, vkey
, OEMvkey
;
1553 int keyc
, i
, keyn
, syms
;
1554 char ckey
[4]={0,0,0,0};
1555 const char (*lkey
)[MAIN_LEN
][4];
1558 XDisplayKeycodes(display
, &min_keycode
, &max_keycode
);
1559 ksp
= XGetKeyboardMapping(display
, min_keycode
,
1560 max_keycode
+ 1 - min_keycode
, &keysyms_per_keycode
);
1561 /* We are only interested in keysyms_per_keycode.
1562 There is no need to hold a local copy of the keysyms table */
1565 mmp
= XGetModifierMapping(display
);
1566 kcp
= mmp
->modifiermap
;
1567 for (i
= 0; i
< 8; i
+= 1) /* There are 8 modifier keys */
1571 for (j
= 0; j
< mmp
->max_keypermod
; j
+= 1, kcp
+= 1)
1576 for (k
= 0; k
< keysyms_per_keycode
; k
+= 1)
1577 if (XKeycodeToKeysym(display
, *kcp
, k
) == XK_Num_Lock
)
1579 NumLockMask
= 1 << i
;
1580 TRACE_(key
)("NumLockMask is %x\n", NumLockMask
);
1584 XFreeModifiermap(mmp
);
1586 /* Detect the keyboard layout */
1587 X11DRV_KEYBOARD_DetectLayout();
1588 lkey
= main_key_tab
[kbd_layout
].key
;
1589 syms
= (keysyms_per_keycode
> 4) ? 4 : keysyms_per_keycode
;
1591 /* Now build two conversion arrays :
1592 * keycode -> vkey + scancode + extended
1593 * vkey + extended -> keycode */
1595 e2
.display
= display
;
1598 OEMvkey
= VK_OEM_8
; /* next is available. */
1599 for (keyc
= min_keycode
; keyc
<= max_keycode
; keyc
++)
1605 e2
.keycode
= (KeyCode
)keyc
;
1606 have_chars
= XLookupString(&e2
, buf
, sizeof(buf
), &keysym
, NULL
);
1608 if (keysym
) /* otherwise, keycode not used */
1610 if ((keysym
>> 8) == 0xFF) /* non-character key */
1612 vkey
= nonchar_key_vkey
[keysym
& 0xff];
1613 scan
= nonchar_key_scan
[keysym
& 0xff];
1614 /* set extended bit when necessary */
1615 if (scan
& 0x100) vkey
|= 0x100;
1616 } else if (keysym
== 0x20) { /* Spacebar */
1619 } else if (have_chars
) {
1620 /* we seem to need to search the layout-dependent scancodes */
1621 int maxlen
=0,maxval
=-1,ok
;
1622 for (i
=0; i
<syms
; i
++) {
1623 keysym
= XKeycodeToKeysym(display
, keyc
, i
);
1624 if ((keysym
<0x8000) && (keysym
!=' '))
1627 if (!use_xkb
|| !XkbTranslateKeySym(display
, &keysym
, 0, &ckey
[i
], 1, NULL
))
1630 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1631 * with appropriate ShiftMask and Mode_switch, use XLookupString
1632 * to get character in the local encoding.
1634 ckey
[i
] = keysym
& 0xFF;
1637 ckey
[i
] = KEYBOARD_MapDeadKeysym(keysym
);
1640 /* find key with longest match streak */
1641 for (keyn
=0; keyn
<MAIN_LEN
; keyn
++) {
1642 for (ok
=(*lkey
)[keyn
][i
=0]; ok
&&(i
<4); i
++)
1643 if ((*lkey
)[keyn
][i
] && (*lkey
)[keyn
][i
]!=ckey
[i
]) ok
=0;
1644 if (ok
||(i
>maxlen
)) {
1645 maxlen
=i
; maxval
=keyn
;
1651 const WORD (*lscan
)[MAIN_LEN
] = main_key_tab
[kbd_layout
].scan
;
1652 const WORD (*lvkey
)[MAIN_LEN
] = main_key_tab
[kbd_layout
].vkey
;
1653 scan
= (*lscan
)[maxval
];
1654 vkey
= (*lvkey
)[maxval
];
1657 #if 0 /* this breaks VK_OEM_x VKeys in some layout tables by inserting
1658 * a VK code into a not appropriate place.
1660 /* find a suitable layout-dependent VK code */
1661 /* (most Winelib apps ought to be able to work without layout tables!) */
1662 for (i
= 0; (i
< keysyms_per_keycode
) && (!vkey
); i
++)
1664 keysym
= XLookupKeysym(&e2
, i
);
1665 if ((keysym
>= VK_0
&& keysym
<= VK_9
)
1666 || (keysym
>= VK_A
&& keysym
<= VK_Z
)) {
1671 for (i
= 0; (i
< keysyms_per_keycode
) && (!vkey
); i
++)
1673 keysym
= XLookupKeysym(&e2
, i
);
1676 case ';': vkey
= VK_OEM_1
; break;
1677 case '/': vkey
= VK_OEM_2
; break;
1678 case '`': vkey
= VK_OEM_3
; break;
1679 case '[': vkey
= VK_OEM_4
; break;
1680 case '\\': vkey
= VK_OEM_5
; break;
1681 case ']': vkey
= VK_OEM_6
; break;
1682 case '\'': vkey
= VK_OEM_7
; break;
1683 case ',': vkey
= VK_OEM_COMMA
; break;
1684 case '.': vkey
= VK_OEM_PERIOD
; break;
1685 case '-': vkey
= VK_OEM_MINUS
; break;
1686 case '+': vkey
= VK_OEM_PLUS
; break;
1692 /* Others keys: let's assign OEM virtual key codes in the allowed range,
1693 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1696 case 0xc1 : OEMvkey
=0xdb; break;
1697 case 0xe5 : OEMvkey
=0xe9; break;
1698 case 0xf6 : OEMvkey
=0xf5; WARN("No more OEM vkey available!\n");
1703 if (TRACE_ON(keyboard
))
1705 TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
1706 OEMvkey
, e2
.keycode
);
1708 for (i
= 0; i
< keysyms_per_keycode
; i
+= 1)
1712 keysym
= XLookupKeysym(&e2
, i
);
1713 ksname
= XKeysymToString(keysym
);
1715 ksname
= "NoSymbol";
1716 TRACE( "%lX (%s) ", keysym
, ksname
);
1723 TRACE("keycode %04x => vkey %04x\n", e2
.keycode
, vkey
);
1724 keyc2vkey
[e2
.keycode
] = vkey
;
1725 keyc2scan
[e2
.keycode
] = scan
;
1728 /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1729 for (scan
= 0x60, keyc
= min_keycode
; keyc
<= max_keycode
; keyc
++)
1730 if (keyc2vkey
[keyc
]&&!keyc2scan
[keyc
]) {
1732 keysym
= XKeycodeToKeysym(display
, keyc
, 0);
1733 ksname
= XKeysymToString(keysym
);
1734 if (!ksname
) ksname
= "NoSymbol";
1736 /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1738 TRACE_(key
)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan
,keyc
,ksname
);
1739 keyc2scan
[keyc
]=scan
++;
1742 /* Now store one keycode for each modifier. Used to simulate keypresses. */
1743 kcControl
= XKeysymToKeycode(display
, XK_Control_L
);
1744 kcAlt
= XKeysymToKeycode(display
, XK_Alt_L
);
1745 if (!kcAlt
) kcAlt
= XKeysymToKeycode(display
, XK_Meta_L
);
1746 kcShift
= XKeysymToKeycode(display
, XK_Shift_L
);
1747 kcNumLock
= XKeysymToKeycode(display
, XK_Num_Lock
);
1748 kcCapsLock
= XKeysymToKeycode(display
, XK_Caps_Lock
);
1749 wine_tsx11_unlock();
1753 /**********************************************************************
1754 * GetAsyncKeyState (X11DRV.@)
1756 SHORT
X11DRV_GetAsyncKeyState(INT key
)
1758 SHORT retval
= ((key_state_table
[key
] & 0x40) ? 0x0001 : 0) |
1759 ((key_state_table
[key
] & 0x80) ? 0x8000 : 0);
1760 key_state_table
[key
] &= ~0x40;
1761 TRACE_(key
)("(%x) -> %x\n", key
, retval
);
1766 /***********************************************************************
1767 * GetKeyboardLayoutList (X11DRV.@)
1769 UINT
X11DRV_GetKeyboardLayoutList(INT size
, HKL
*hkl
)
1773 TRACE("%d, %p\n", size
, hkl
);
1777 size
= 4096; /* hope we will never have that many */
1781 for (i
= 0; main_key_tab
[i
].comment
&& (i
< size
); i
++)
1785 ULONG_PTR layout
= main_key_tab
[i
].lcid
;
1788 /* see comment for GetKeyboardLayout */
1789 langid
= PRIMARYLANGID(LANGIDFROMLCID(layout
));
1790 if (langid
== LANG_CHINESE
|| langid
== LANG_JAPANESE
|| langid
== LANG_KOREAN
)
1791 layout
|= 0xe001 << 16; /* FIXME */
1793 layout
|= layout
<< 16;
1795 hkl
[i
] = (HKL
)layout
;
1802 /***********************************************************************
1803 * GetKeyboardLayout (X11DRV.@)
1805 HKL
X11DRV_GetKeyboardLayout(DWORD dwThreadid
)
1810 if (dwThreadid
&& dwThreadid
!= GetCurrentThreadId())
1811 FIXME("couldn't return keyboard layout for thread %04lx\n", dwThreadid
);
1814 layout
= main_key_tab
[kbd_layout
].lcid
;
1817 * Winword uses return value of GetKeyboardLayout as a codepage
1818 * to translate ANSI keyboard messages to unicode. But we have
1819 * a problem with it: for instance Polish keyboard layout is
1820 * identical to the US one, and therefore instead of the Polish
1821 * locale id we return the US one.
1823 layout
= GetUserDefaultLCID();
1826 * Microsoft Office expects this value to be something specific
1827 * for Japanese and Korean Windows with an IME the value is 0xe001
1828 * We should probably check to see if an IME exists and if so then
1829 * set this word properly.
1831 langid
= PRIMARYLANGID(LANGIDFROMLCID(layout
));
1832 if (langid
== LANG_CHINESE
|| langid
== LANG_JAPANESE
|| langid
== LANG_KOREAN
)
1833 layout
|= 0xe001 << 16; /* FIXME */
1835 layout
|= layout
<< 16;
1841 /***********************************************************************
1842 * GetKeyboardLayoutName (X11DRV.@)
1844 BOOL
X11DRV_GetKeyboardLayoutName(LPWSTR name
)
1846 static const WCHAR formatW
[] = {'%','0','8','l','x',0};
1850 layout
= main_key_tab
[kbd_layout
].lcid
;
1851 /* see comment for GetKeyboardLayout */
1852 langid
= PRIMARYLANGID(LANGIDFROMLCID(layout
));
1853 if (langid
== LANG_CHINESE
|| langid
== LANG_JAPANESE
|| langid
== LANG_KOREAN
)
1854 layout
|= 0xe001 << 16; /* FIXME */
1856 layout
|= layout
<< 16;
1858 sprintfW(name
, formatW
, layout
);
1859 TRACE("returning %s\n", debugstr_w(name
));
1864 /***********************************************************************
1865 * LoadKeyboardLayout (X11DRV.@)
1867 HKL
X11DRV_LoadKeyboardLayout(LPCWSTR name
, UINT flags
)
1869 FIXME("%s, %04x: stub!\n", debugstr_w(name
), flags
);
1870 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1875 /***********************************************************************
1876 * UnloadKeyboardLayout (X11DRV.@)
1878 BOOL
X11DRV_UnloadKeyboardLayout(HKL hkl
)
1880 FIXME("%p: stub!\n", hkl
);
1881 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1886 /***********************************************************************
1887 * ActivateKeyboardLayout (X11DRV.@)
1889 HKL
X11DRV_ActivateKeyboardLayout(HKL hkl
, UINT flags
)
1891 FIXME("%p, %04x: stub!\n", hkl
, flags
);
1892 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1897 /***********************************************************************
1898 * X11DRV_MappingNotify
1900 void X11DRV_MappingNotify( HWND dummy
, XEvent
*event
)
1905 XRefreshKeyboardMapping(&event
->xmapping
);
1906 wine_tsx11_unlock();
1907 X11DRV_InitKeyboard();
1910 if (!hwnd
) hwnd
= GetActiveWindow();
1911 PostMessageW(hwnd
, WM_INPUTLANGCHANGEREQUEST
,
1912 0 /*FIXME*/, (LPARAM
)X11DRV_GetKeyboardLayout(0));
1916 /***********************************************************************
1917 * VkKeyScanEx (X11DRV.@)
1919 * Note: Windows ignores HKL parameter and uses current active layout instead
1921 SHORT
X11DRV_VkKeyScanEx(WCHAR wChar
, HKL hkl
)
1923 Display
*display
= thread_display();
1930 /* FIXME: what happens if wChar is not a Latin1 character and CP_UNIXCP
1931 * is UTF-8 (multibyte encoding)?
1933 if (!WideCharToMultiByte(CP_UNIXCP
, 0, &wChar
, 1, &cChar
, 1, NULL
, NULL
))
1935 WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar
);
1939 TRACE("wChar 0x%02x -> cChar '%c'\n", wChar
, cChar
);
1941 /* char->keysym (same for ANSI chars) */
1942 keysym
= (unsigned char)cChar
; /* (!) cChar is signed */
1943 if (keysym
<= 27) keysym
+= 0xFF00; /* special chars : return, backspace... */
1946 keycode
= XKeysymToKeycode(display
, keysym
); /* keysym -> keycode */
1949 if (keysym
>= 0xFF00) /* Windows returns 0x0240 + cChar in this case */
1951 ret
= 0x0240 + cChar
; /* 0x0200 indicates a control character */
1952 TRACE(" ... returning ctrl char %#.2x\n", ret
);
1953 wine_tsx11_unlock();
1956 /* It didn't work ... let's try with deadchar code. */
1957 TRACE("retrying with | 0xFE00\n");
1958 keycode
= XKeysymToKeycode(display
, keysym
| 0xFE00);
1960 wine_tsx11_unlock();
1962 TRACE("'%c'(%#lx, %lu): got keycode %#.2x (%d)\n",
1963 cChar
, keysym
, keysym
, keycode
, keycode
);
1965 /* keycode -> (keyc2vkey) vkey */
1966 ret
= keyc2vkey
[keycode
];
1968 if (!keycode
|| !ret
)
1970 TRACE("keycode for '%c' not found, returning -1\n", cChar
);
1976 for (i
= 0; i
< 4; i
++) /* find shift state */
1978 if (XKeycodeToKeysym(display
, keycode
, i
) == keysym
)
1984 wine_tsx11_unlock();
1990 WARN("Keysym %lx not found while parsing the keycode table\n", keysym
);
1994 case 1: ret
+= 0x0100; break;
1995 case 2: ret
+= 0x0600; break;
1996 case 3: ret
+= 0x0700; break;
1999 index : 0 adds 0x0000
2000 index : 1 adds 0x0100 (shift)
2001 index : ? adds 0x0200 (ctrl)
2002 index : 2 adds 0x0600 (ctrl+alt)
2003 index : 3 adds 0x0700 (ctrl+alt+shift)
2006 TRACE(" ... returning %#.2x\n", ret
);
2010 /***********************************************************************
2011 * MapVirtualKeyEx (X11DRV.@)
2013 UINT
X11DRV_MapVirtualKeyEx(UINT wCode
, UINT wMapType
, HKL hkl
)
2015 Display
*display
= thread_display();
2017 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
2019 TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode
, wMapType
, hkl
);
2020 if (hkl
!= X11DRV_GetKeyboardLayout(0))
2021 FIXME("keyboard layout %p is not supported\n", hkl
);
2024 case 0: { /* vkey-code to scan-code */
2025 /* let's do vkey -> keycode -> scan */
2027 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++)
2028 if ((keyc2vkey
[keyc
] & 0xFF) == wCode
)
2029 returnMVK (keyc2scan
[keyc
] & 0xFF);
2030 TRACE("returning no scan-code.\n");
2033 case 1: { /* scan-code to vkey-code */
2034 /* let's do scan -> keycode -> vkey */
2036 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++)
2037 if ((keyc2scan
[keyc
] & 0xFF) == (wCode
& 0xFF))
2038 returnMVK (keyc2vkey
[keyc
] & 0xFF);
2039 TRACE("returning no vkey-code.\n");
2042 case 2: { /* vkey-code to unshifted ANSI code */
2043 /* we still don't know what "unshifted" means. in windows VK_W (0x57)
2044 * returns 0x57, which is upercase 'W'. So we have to return the uppercase
2045 * key.. Looks like something is wrong with the MS docs?
2046 * This is only true for letters, for example VK_0 returns '0' not ')'.
2047 * - hence we use the lock mask to ensure this happens.
2049 /* let's do vkey -> keycode -> (XLookupString) ansi char */
2054 e
.display
= display
;
2057 /* LockMask should behave exactly like caps lock - upercase
2058 * the letter keys and thats about it. */
2063 /* We exit on the first keycode found, to speed up the thing. */
2064 for (keyc
=min_keycode
; (keyc
<=max_keycode
) && (!e
.keycode
) ; keyc
++)
2065 { /* Find a keycode that could have generated this virtual key */
2066 if ((keyc2vkey
[keyc
] & 0xFF) == wCode
)
2067 { /* We filter the extended bit, we don't know it */
2068 e
.keycode
= keyc
; /* Store it temporarily */
2069 if ((EVENT_event_to_vkey(0,&e
) & 0xFF) != wCode
) {
2070 e
.keycode
= 0; /* Wrong one (ex: because of the NumLock
2071 state), so set it to 0, we'll find another one */
2076 if ((wCode
>=VK_NUMPAD0
) && (wCode
<=VK_NUMPAD9
))
2077 e
.keycode
= XKeysymToKeycode(e
.display
, wCode
-VK_NUMPAD0
+XK_KP_0
);
2079 if (wCode
==VK_DECIMAL
)
2080 e
.keycode
= XKeysymToKeycode(e
.display
, XK_KP_Decimal
);
2084 WARN("Unknown virtual key %X !!!\n", wCode
);
2085 wine_tsx11_unlock();
2086 return 0; /* whatever */
2088 TRACE("Found keycode %d (0x%2X)\n",e
.keycode
,e
.keycode
);
2090 if (XLookupString(&e
, s
, 2, &keysym
, NULL
))
2092 wine_tsx11_unlock();
2096 TRACE("returning no ANSI.\n");
2097 wine_tsx11_unlock();
2101 case 3: /* **NT only** scan-code to vkey-code but distinguish between */
2102 /* left and right */
2103 FIXME(" stub for NT\n");
2106 default: /* reserved */
2107 WARN("Unknown wMapType %d !\n", wMapType
);
2113 /***********************************************************************
2114 * GetKeyNameText (X11DRV.@)
2116 INT
X11DRV_GetKeyNameText(LONG lParam
, LPWSTR lpBuffer
, INT nSize
)
2118 int vkey
, ansi
, scanCode
;
2124 scanCode
= lParam
>> 16;
2125 scanCode
&= 0x1ff; /* keep "extended-key" flag with code */
2127 /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
2128 vkey
= X11DRV_MapVirtualKeyEx(scanCode
, 1, X11DRV_GetKeyboardLayout(0));
2130 /* handle "don't care" bit (0x02000000) */
2131 if (!(lParam
& 0x02000000)) {
2150 ansi
= X11DRV_MapVirtualKeyEx(vkey
, 2, X11DRV_GetKeyboardLayout(0));
2151 TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode
, vkey
, ansi
);
2153 /* first get the name of the "regular" keys which is the Upper case
2154 value of the keycap imprint. */
2155 if ( ((ansi
>= 0x21) && (ansi
<= 0x7e)) &&
2156 (scanCode
!= 0x137) && /* PrtScn */
2157 (scanCode
!= 0x135) && /* numpad / */
2158 (scanCode
!= 0x37 ) && /* numpad * */
2159 (scanCode
!= 0x4a ) && /* numpad - */
2160 (scanCode
!= 0x4e ) ) /* numpad + */
2162 if ((nSize
>= 2) && lpBuffer
)
2164 *lpBuffer
= toupperW((WCHAR
)ansi
);
2172 /* FIXME: horrible hack to fix function keys. Windows reports scancode
2173 without "extended-key" flag. However Wine generates scancode
2174 *with* "extended-key" flag. Seems to occur *only* for the
2175 function keys. Soooo.. We will leave the table alone and
2176 fudge the lookup here till the other part is found and fixed!!! */
2178 if ( ((scanCode
>= 0x13b) && (scanCode
<= 0x144)) ||
2179 (scanCode
== 0x157) || (scanCode
== 0x158))
2180 scanCode
&= 0xff; /* remove "extended-key" flag for Fx keys */
2182 /* let's do scancode -> keycode -> keysym -> String */
2184 for (keyi
=min_keycode
; keyi
<=max_keycode
; keyi
++)
2185 if ((keyc2scan
[keyi
]) == scanCode
)
2187 if (keyi
<= max_keycode
)
2190 keyc
= (KeyCode
) keyi
;
2191 keys
= XKeycodeToKeysym(thread_display(), keyc
, 0);
2192 name
= XKeysymToString(keys
);
2193 wine_tsx11_unlock();
2194 TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
2195 scanCode
, keyc
, (int)keys
, name
);
2196 if (lpBuffer
&& nSize
&& name
)
2198 MultiByteToWideChar(CP_UNIXCP
, 0, name
, -1, lpBuffer
, nSize
);
2199 lpBuffer
[nSize
- 1] = 0;
2204 /* Finally issue FIXME for unknown keys */
2206 FIXME("(%08lx,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam
,lpBuffer
,nSize
,vkey
,ansi
);
2207 if (lpBuffer
&& nSize
)
2212 /***********************************************************************
2213 * X11DRV_KEYBOARD_MapDeadKeysym
2215 static char KEYBOARD_MapDeadKeysym(KeySym keysym
)
2219 /* symbolic ASCII is the same as defined in rfc1345 */
2220 #ifdef XK_dead_tilde
2221 case XK_dead_tilde
:
2223 case 0x1000FE7E : /* Xfree's XK_Dtilde */
2224 return '~'; /* '? */
2225 #ifdef XK_dead_acute
2226 case XK_dead_acute
:
2228 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2229 return 0xb4; /* '' */
2230 #ifdef XK_dead_circumflex
2231 case XK_dead_circumflex
:
2233 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2234 return '^'; /* '> */
2235 #ifdef XK_dead_grave
2236 case XK_dead_grave
:
2238 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2239 return '`'; /* '! */
2240 #ifdef XK_dead_diaeresis
2241 case XK_dead_diaeresis
:
2243 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2244 return 0xa8; /* ': */
2245 #ifdef XK_dead_cedilla
2246 case XK_dead_cedilla
:
2247 return 0xb8; /* ', */
2249 #ifdef XK_dead_macron
2250 case XK_dead_macron
:
2251 return '-'; /* 'm isn't defined on iso-8859-x */
2253 #ifdef XK_dead_breve
2254 case XK_dead_breve
:
2255 return 0xa2; /* '( */
2257 #ifdef XK_dead_abovedot
2258 case XK_dead_abovedot
:
2259 return 0xff; /* '. */
2261 #ifdef XK_dead_abovering
2262 case XK_dead_abovering
:
2263 return '0'; /* '0 isn't defined on iso-8859-x */
2265 #ifdef XK_dead_doubleacute
2266 case XK_dead_doubleacute
:
2267 return 0xbd; /* '" */
2269 #ifdef XK_dead_caron
2270 case XK_dead_caron
:
2271 return 0xb7; /* '< */
2273 #ifdef XK_dead_ogonek
2274 case XK_dead_ogonek
:
2275 return 0xb2; /* '; */
2277 /* FIXME: I don't know this three.
2280 case XK_dead_voiced_sound :
2282 case XK_dead_semivoiced_sound :
2286 TRACE("no character for dead keysym 0x%08lx\n",keysym
);
2290 /***********************************************************************
2291 * ToUnicodeEx (X11DRV.@)
2293 * The ToUnicode function translates the specified virtual-key code and keyboard
2294 * state to the corresponding Windows character or characters.
2296 * If the specified key is a dead key, the return value is negative. Otherwise,
2297 * it is one of the following values:
2299 * 0 The specified virtual key has no translation for the current state of the keyboard.
2300 * 1 One Windows character was copied to the buffer.
2301 * 2 Two characters were copied to the buffer. This usually happens when a
2302 * dead-key character (accent or diacritic) stored in the keyboard layout cannot
2303 * be composed with the specified virtual key to form a single character.
2305 * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2308 INT
X11DRV_ToUnicodeEx(UINT virtKey
, UINT scanCode
, LPBYTE lpKeyState
,
2309 LPWSTR bufW
, int bufW_size
, UINT flags
, HKL hkl
)
2311 Display
*display
= thread_display();
2321 if (scanCode
& 0x8000)
2323 TRACE("Key UP, doing nothing\n" );
2327 if (hkl
!= X11DRV_GetKeyboardLayout(0))
2328 FIXME("keyboard layout %p is not supported\n", hkl
);
2330 if ((lpKeyState
[VK_MENU
] & 0x80) && (lpKeyState
[VK_CONTROL
] & 0x80))
2332 TRACE("Ctrl+Alt+[key] won't generate a character\n");
2336 e
.display
= display
;
2342 if (focus
) focus
= GetAncestor( focus
, GA_ROOT
);
2343 if (!focus
) focus
= GetActiveWindow();
2344 e
.window
= X11DRV_get_whole_window( focus
);
2345 xic
= X11DRV_get_ic( focus
);
2347 if (lpKeyState
[VK_SHIFT
] & 0x80)
2349 TRACE("ShiftMask = %04x\n", ShiftMask
);
2350 e
.state
|= ShiftMask
;
2352 if (lpKeyState
[VK_CAPITAL
] & 0x01)
2354 TRACE("LockMask = %04x\n", LockMask
);
2355 e
.state
|= LockMask
;
2357 if (lpKeyState
[VK_CONTROL
] & 0x80)
2359 TRACE("ControlMask = %04x\n", ControlMask
);
2360 e
.state
|= ControlMask
;
2362 if (lpKeyState
[VK_NUMLOCK
] & 0x01)
2364 TRACE("NumLockMask = %04x\n", NumLockMask
);
2365 e
.state
|= NumLockMask
;
2368 /* Restore saved AltGr state */
2369 TRACE("AltGrMask = %04x\n", AltGrMask
);
2370 e
.state
|= AltGrMask
;
2372 TRACE_(key
)("(%04X, %04X) : faked state = 0x%04x\n",
2373 virtKey
, scanCode
, e
.state
);
2375 /* We exit on the first keycode found, to speed up the thing. */
2376 for (keyc
=min_keycode
; (keyc
<=max_keycode
) && (!e
.keycode
) ; keyc
++)
2377 { /* Find a keycode that could have generated this virtual key */
2378 if ((keyc2vkey
[keyc
] & 0xFF) == virtKey
)
2379 { /* We filter the extended bit, we don't know it */
2380 e
.keycode
= keyc
; /* Store it temporarily */
2381 if ((EVENT_event_to_vkey(xic
,&e
) & 0xFF) != virtKey
) {
2382 e
.keycode
= 0; /* Wrong one (ex: because of the NumLock
2383 state), so set it to 0, we'll find another one */
2388 if ((virtKey
>=VK_NUMPAD0
) && (virtKey
<=VK_NUMPAD9
))
2389 e
.keycode
= XKeysymToKeycode(e
.display
, virtKey
-VK_NUMPAD0
+XK_KP_0
);
2391 if (virtKey
==VK_DECIMAL
)
2392 e
.keycode
= XKeysymToKeycode(e
.display
, XK_KP_Decimal
);
2394 if (virtKey
==VK_SEPARATOR
)
2395 e
.keycode
= XKeysymToKeycode(e
.display
, XK_KP_Separator
);
2397 if (!e
.keycode
&& virtKey
!= VK_NONAME
)
2399 WARN("Unknown virtual key %X !!!\n", virtKey
);
2400 wine_tsx11_unlock();
2401 return virtKey
; /* whatever */
2403 else TRACE("Found keycode %d (0x%2X)\n",e
.keycode
,e
.keycode
);
2405 TRACE_(key
)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
2406 e
.type
, e
.window
, e
.state
, e
.keycode
);
2409 ret
= XmbLookupString(xic
, &e
, lpChar
, sizeof(lpChar
), &keysym
, &status
);
2411 ret
= XLookupString(&e
, lpChar
, sizeof(lpChar
), &keysym
, NULL
);
2412 wine_tsx11_unlock();
2419 /* An ugly hack for EuroSign: X can't translate it to a character
2420 for some locales. */
2421 if (keysym
== XK_EuroSign
)
2428 /* Special case: X turns shift-tab into ISO_Left_Tab. */
2429 /* Here we change it back. */
2430 if (keysym
== XK_ISO_Left_Tab
)
2437 dead_char
= KEYBOARD_MapDeadKeysym(keysym
);
2440 MultiByteToWideChar(CP_UNIXCP
, 0, &dead_char
, 1, bufW
, bufW_size
);
2448 ksname
= XKeysymToString(keysym
);
2449 wine_tsx11_unlock();
2452 if ((keysym
>> 8) != 0xff)
2454 ERR("Please report: no char for keysym %04lX (%s) :\n",
2456 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
2457 virtKey
, scanCode
, e
.keycode
, e
.state
);
2461 else { /* ret != 0 */
2462 /* We have a special case to handle : Shift + arrow, shift + home, ...
2463 X returns a char for it, but Windows doesn't. Let's eat it. */
2464 if (!(e
.state
& NumLockMask
) /* NumLock is off */
2465 && (e
.state
& ShiftMask
) /* Shift is pressed */
2466 && (keysym
>=XK_KP_0
) && (keysym
<=XK_KP_9
))
2472 /* more areas where X returns characters but Windows does not
2473 CTRL + number or CTRL + symbol */
2474 if (e
.state
& ControlMask
)
2476 if (((keysym
>=33) && (keysym
< 'A')) ||
2477 ((keysym
> 'Z') && (keysym
< 'a')))
2484 /* We have another special case for delete key (XK_Delete) on an
2485 extended keyboard. X returns a char for it, but Windows doesn't */
2486 if (keysym
== XK_Delete
)
2491 else if((lpKeyState
[VK_SHIFT
] & 0x80) /* Shift is pressed */
2492 && (keysym
== XK_KP_Decimal
))
2498 /* perform translation to unicode */
2501 TRACE_(key
)("Translating char 0x%02x to unicode\n", *(BYTE
*)lpChar
);
2502 ret
= MultiByteToWideChar(CP_UNIXCP
, 0, lpChar
, ret
, bufW
, bufW_size
);
2507 TRACE_(key
)("ToUnicode about to return %d with char %x %s\n",
2508 ret
, (ret
&& bufW
) ? bufW
[0] : 0, bufW
? "" : "(no buffer)");
2512 /***********************************************************************
2515 void X11DRV_Beep(void)
2518 XBell(thread_display(), 0);
2519 wine_tsx11_unlock();