2 * Keyboard related functions
4 * Copyright 1993 Bob Amstadt
5 * Copyright 1996 Albrecht Kleine
6 * Copyright 1997 David Faure
14 #include <X11/keysym.h>
16 #include "ts_xresource.h"
18 #include <X11/Xatom.h>
27 #include "debugtools.h"
31 BOOL32 MouseButtonsStates
[3];
32 BOOL32 AsyncMouseButtonsStates
[3];
33 BYTE InputKeyStateTable
[256];
34 BYTE QueueKeyStateTable
[256];
35 BYTE AsyncKeyStateTable
[256];
37 static int NumLockMask
;
39 static int min_keycode
, max_keycode
;
40 static int keyc2vkey
[256];
46 unsigned long count
: 16;
47 unsigned long code
: 8;
48 unsigned long extended
: 1;
49 unsigned long unused
: 2;
50 unsigned long win_internal
: 2;
51 unsigned long context
: 1;
52 unsigned long previous
: 1;
53 unsigned long transition
: 1;
58 /* Keyboard translation tables */
59 static const int special_key
[] =
61 VK_BACK
, VK_TAB
, 0, VK_CLEAR
, 0, VK_RETURN
, 0, 0, /* FF08 */
62 0, 0, 0, VK_PAUSE
, VK_SCROLL
, 0, 0, 0, /* FF10 */
63 0, 0, 0, VK_ESCAPE
/* FF18 */
66 static const int cursor_key
[] =
68 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, VK_DOWN
, VK_PRIOR
,
69 VK_NEXT
, VK_END
/* FF50 */
72 static const int misc_key
[] =
74 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
75 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_MENU
/* FF68 */
78 static const int keypad_key
[] =
80 0, VK_NUMLOCK
, /* FF7E */
81 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
82 0, 0, 0, 0, 0, VK_RETURN
, 0, 0, /* FF88 */
83 0, 0, 0, 0, 0, VK_HOME
, VK_LEFT
, VK_UP
, /* FF90 */
84 VK_RIGHT
, VK_DOWN
, VK_PRIOR
, VK_NEXT
, VK_END
, 0,
85 VK_INSERT
, VK_DELETE
, /* FF98 */
86 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
87 0, 0, VK_MULTIPLY
, VK_ADD
, VK_SEPARATOR
, VK_SUBTRACT
,
88 VK_DECIMAL
, VK_DIVIDE
, /* FFA8 */
89 VK_NUMPAD0
, VK_NUMPAD1
, VK_NUMPAD2
, VK_NUMPAD3
, VK_NUMPAD4
,
90 VK_NUMPAD5
, VK_NUMPAD6
, VK_NUMPAD7
, /* FFB0 */
91 VK_NUMPAD8
, VK_NUMPAD9
/* FFB8 */
94 static const int function_key
[] =
96 VK_F1
, VK_F2
, /* FFBE */
97 VK_F3
, VK_F4
, VK_F5
, VK_F6
, VK_F7
, VK_F8
, VK_F9
, VK_F10
, /* FFC0 */
98 VK_F11
, VK_F12
, VK_F13
, VK_F14
, VK_F15
, VK_F16
/* FFC8 */
101 static const int modifier_key
[] =
103 VK_SHIFT
, VK_SHIFT
, VK_CONTROL
, VK_CONTROL
, VK_CAPITAL
, 0, /* FFE1 */
104 VK_MENU
, VK_MENU
, VK_MENU
, VK_MENU
/* FFE7 */
108 * Table for vkey to scancode translation - 5/29/97 chrisf@america.com
110 const BYTE vkey2scode
[512] = {
111 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0e,0x0f,0x00,0x00,0x00,0x1c,0x00,0x00,
112 0x2a,0x1d,0x38,0x00,0x3a,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
113 0x39,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
114 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,
115 0x00,0x1e,0x30,0x2e,0x20,0x12,0x21,0x22, 0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,
116 0x19,0x10,0x13,0x1f,0x14,0x16,0x2f,0x11, 0x2d,0x15,0x2c,0x00,0x00,0x00,0x00,0x00,
117 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x37,0x4e,0x00,0x4a,0x34,0x00,
118 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119 0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
121 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x29,0x0c,0x0d,0x1a,0x1b,0x2b,
123 0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
124 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x28,0x33,0x34,0x35,0x4c,
125 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,
129 0x00,0x1d,0x38,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130 0x00,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
131 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
132 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
133 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
134 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x35,
135 0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42, 0x43,0x44,0x57,0x58,0x00,0x00,0x00,0x00,
136 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
137 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
138 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
139 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
140 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
141 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
142 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
143 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
146 static WORD
EVENT_event_to_vkey( XKeyEvent
*e
)
150 TSXLookupString(e
, NULL
, 0, &keysym
, NULL
);
152 if ((keysym
>= 0xFFAE) && (keysym
<= 0xFFB9) && (e
->state
& NumLockMask
))
153 /* Only the Keypad keys 0-9 and . send different keysyms
154 * depending on the NumLock state */
155 return keypad_key
[(keysym
& 0xFF) - 0x7E];
157 return keyc2vkey
[e
->keycode
];
160 /**********************************************************************
163 BOOL32
KEYBOARD_Init(void)
165 int i
, keysyms_per_keycode
;
167 XModifierKeymap
*mmp
;
173 TSXDisplayKeycodes(display
, &min_keycode
, &max_keycode
);
174 ksp
= TSXGetKeyboardMapping(display
, min_keycode
,
175 max_keycode
+ 1 - min_keycode
, &keysyms_per_keycode
);
176 /* We are only interested in keysyms_per_keycode.
177 There is no need to hold a local copy of the keysyms table */
179 mmp
= TSXGetModifierMapping(display
);
180 kcp
= mmp
->modifiermap
;
181 for (i
= 0; i
< 8; i
+= 1) /* There are 8 modifier keys */
185 for (j
= 0; j
< mmp
->max_keypermod
; j
+= 1, kcp
+= 1)
190 for (k
= 0; k
< keysyms_per_keycode
; k
+= 1)
191 if (TSXKeycodeToKeysym(display
, *kcp
, k
) == XK_Mode_switch
)
194 TRACE(key
, "AltGrMask is %x\n", AltGrMask
);
196 else if (TSXKeycodeToKeysym(display
, *kcp
, k
) == XK_Num_Lock
)
198 NumLockMask
= 1 << i
;
199 TRACE(key
, "NumLockMask is %x\n", NumLockMask
);
203 TSXFreeModifiermap(mmp
);
205 /* Now build two conversion arrays :
206 * keycode -> vkey + extended
207 * vkey + extended -> keycode */
209 e2
.display
= display
;
212 OEMvkey
= 0xb9; /* first OEM virtual key available is ba */
213 for (e2
.keycode
=min_keycode
; e2
.keycode
<=max_keycode
; e2
.keycode
++)
215 TSXLookupString(&e2
, NULL
, 0, &keysym
, NULL
);
217 if (keysym
) /* otherwise, keycode not used */
219 if ((keysym
>> 8) == 0xFF) /* non-character key */
221 int key
= keysym
& 0xff;
223 if (key
>= 0x08 && key
<= 0x1B) /* special key */
224 vkey
= special_key
[key
- 0x08];
225 else if (key
>= 0x50 && key
<= 0x57) /* cursor key */
226 vkey
= cursor_key
[key
- 0x50];
227 else if (key
>= 0x60 && key
<= 0x6B) /* miscellaneous key */
228 vkey
= misc_key
[key
- 0x60];
229 else if (key
>= 0x7E && key
<= 0xB9) /* keypad key */
230 vkey
= keypad_key
[key
- 0x7E];
231 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
233 vkey
= function_key
[key
- 0xBE];
234 vkey
|= 0x100; /* set extended bit */
236 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
237 vkey
= modifier_key
[key
- 0xE1];
238 else if (key
== 0xFF) /* DEL key */
240 /* extended must also be set for ALT_R, CTRL_R,
241 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
242 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
243 /* FIXME should we set extended bit for NumLock ? My
244 * Windows does ... DF */
264 for (i
= 0; (i
< keysyms_per_keycode
) && (!vkey
); i
++)
266 keysym
= TSXLookupKeysym(&e2
, i
);
267 if ((keysym
>= VK_0
&& keysym
<= VK_9
)
268 || (keysym
>= VK_A
&& keysym
<= VK_Z
)
269 || keysym
== VK_SPACE
)
275 /* Others keys: let's assign OEM virtual key codes in the allowed range,
276 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
279 case 0xc1 : OEMvkey
=0xdb; break;
280 case 0xe5 : OEMvkey
=0xe9; break;
281 case 0xf6 : OEMvkey
=0xf5; fprintf(stderr
,"No more OEM vkey available!\n");
286 if (TRACE_ON(keyboard
))
288 dbg_decl_str(keyboard
, 1024);
290 TRACE(keyboard
, "OEM specific virtual key %X assigned"
291 "to keycode %X :\n", OEMvkey
, e2
.keycode
);
292 for (i
= 0; i
< keysyms_per_keycode
; i
+= 1)
296 keysym
= TSXLookupKeysym(&e2
, i
);
297 ksname
= TSXKeysymToString(keysym
);
300 dsprintf(keyboard
, "%lX (%s) ", keysym
, ksname
);
302 TRACE(keyboard
, "(%s)\n", dbg_str(keyboard
));
306 keyc2vkey
[e2
.keycode
] = vkey
;
311 static BOOL32 NumState
=FALSE
, CapsState
=FALSE
;
313 void KEYBOARD_GenerateMsg( WORD vkey
, int Evtype
, INT32 event_x
, INT32 event_y
,
314 DWORD event_time
, KEYLP localkeylp
)
316 BOOL32
* State
= (vkey
==VK_NUMLOCK
? &NumState
: &CapsState
);
319 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
320 don't treat it. It's from the same key press. Then the state goes to ON.
321 And from there, a 'release' event will switch off the toggle key. */
323 TRACE(keyboard
,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey
,InputKeyStateTable
[vkey
]);
326 if ( InputKeyStateTable
[vkey
] & 0x1 ) /* it was ON */
328 if (Evtype
!=KeyPress
)
330 TRACE(keyboard
,"ON + KeyRelease => generating DOWN and UP messages.\n");
331 localkeylp
.lp1
.previous
= 0; /* ? */
332 localkeylp
.lp1
.transition
= 0;
333 hardware_event( WM_KEYDOWN
, vkey
, localkeylp
.lp2
,
334 event_x
, event_y
, event_time
, 0 );
335 hardware_event( WM_KEYUP
, vkey
, localkeylp
.lp2
,
336 event_x
, event_y
, event_time
, 0 );
338 InputKeyStateTable
[vkey
] &= ~0x01; /* Toggle state to off. */
341 else /* it was OFF */
342 if (Evtype
==KeyPress
)
344 TRACE(keyboard
,"OFF + Keypress => generating DOWN and UP messages.\n");
345 hardware_event( WM_KEYDOWN
, vkey
, localkeylp
.lp2
,
346 event_x
, event_y
, event_time
, 0 );
347 localkeylp
.lp1
.previous
= 1;
348 localkeylp
.lp1
.transition
= 1;
349 hardware_event( WM_KEYUP
, vkey
, localkeylp
.lp2
,
350 event_x
, event_y
, event_time
, 0 );
351 *State
=TRUE
; /* Goes to intermediary state before going to ON */
352 InputKeyStateTable
[vkey
] |= 0x01; /* Toggle state to on. */
357 /***********************************************************************
358 * KEYBOARD_HandleEvent
360 * Handle a X key event
362 void KEYBOARD_HandleEvent( WND
*pWnd
, XKeyEvent
*event
)
369 static BOOL32 force_extended
= FALSE
; /* hack for AltGr translation */
371 int ascii_chars
= TSXLookupString(event
, Str
, 1, &keysym
, &cs
);
373 INT32 event_x
= pWnd
->rectWindow
.left
+ event
->x
;
374 INT32 event_y
= pWnd
->rectWindow
.top
+ event
->y
;
375 DWORD event_time
= event
->time
- MSG_WineStartTicks
;
377 TRACE(key
, "EVENT_key : state = %X\n", event
->state
);
378 if (keysym
== XK_Mode_switch
)
380 TRACE(key
, "Alt Gr key event received\n");
381 event
->keycode
= TSXKeysymToKeycode(event
->display
, XK_Control_L
);
382 TRACE(key
, "Control_L is keycode 0x%x\n", event
->keycode
);
383 KEYBOARD_HandleEvent( pWnd
, event
);
384 event
->keycode
= TSXKeysymToKeycode(event
->display
, XK_Alt_L
);
385 TRACE(key
, "Alt_L is keycode 0x%x\n", event
->keycode
);
386 force_extended
= TRUE
;
387 KEYBOARD_HandleEvent( pWnd
, event
);
388 force_extended
= FALSE
;
392 Str
[ascii_chars
] = '\0';
396 ksname
= TSXKeysymToString(keysym
);
399 TRACE(key
, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
400 (event
->type
== KeyPress
) ? "KeyPress" : "KeyRelease",
401 keysym
, ksname
, ascii_chars
, Str
[0] & 0xff, Str
);
404 vkey
= EVENT_event_to_vkey(event
);
405 if (force_extended
) vkey
|= 0x100;
407 TRACE(key
, "keycode 0x%x converted to vkey 0x%x\n",
408 event
->keycode
, vkey
);
413 keylp
.lp1
.code
= vkey2scode
[vkey
]; /* 5/29/97 chrisf@america.com */
414 keylp
.lp1
.extended
= (vkey
& 0x100 ? 1 : 0);
415 keylp
.lp1
.win_internal
= 0; /* this has something to do with dialogs,
416 * don't remember where I read it - AK */
417 /* it's '1' under windows, when a dialog box appears
418 * and you press one of the underlined keys - DF*/
424 KEYBOARD_GenerateMsg( VK_NUMLOCK
, event
->type
, event_x
, event_y
,
428 TRACE(keyboard
,"Caps Lock event. (type %d). State before : %#.2x\n",event
->type
,InputKeyStateTable
[vkey
]);
429 KEYBOARD_GenerateMsg( VK_CAPITAL
, event
->type
, event_x
, event_y
,
431 TRACE(keyboard
,"State after : %#.2x\n",InputKeyStateTable
[vkey
]);
436 if (event
->type
== KeyPress
)
438 keylp
.lp1
.previous
= (InputKeyStateTable
[vkey
] & 0x80) != 0;
439 if (!(InputKeyStateTable
[vkey
] & 0x80))
440 InputKeyStateTable
[vkey
] ^= 0x01;
441 InputKeyStateTable
[vkey
] |= 0x80;
442 keylp
.lp1
.transition
= 0;
443 message
= (InputKeyStateTable
[VK_MENU
] & 0x80)
444 && !(InputKeyStateTable
[VK_CONTROL
] & 0x80)
445 ? WM_SYSKEYDOWN
: WM_KEYDOWN
;
449 BOOL32 sysKey
= (InputKeyStateTable
[VK_MENU
] & 0x80)
450 && !(InputKeyStateTable
[VK_CONTROL
] & 0x80)
451 && (force_extended
== FALSE
); /* for Alt from AltGr */
453 InputKeyStateTable
[vkey
] &= ~0x80;
454 keylp
.lp1
.previous
= 1;
455 keylp
.lp1
.transition
= 1;
456 message
= sysKey
? WM_SYSKEYUP
: WM_KEYUP
;
458 keylp
.lp1
.context
= ( (event
->state
& Mod1Mask
) ||
459 (InputKeyStateTable
[VK_MENU
] & 0x80)) ? 1 : 0;
460 if (!(InputKeyStateTable
[VK_NUMLOCK
] & 0x01) != !(event
->state
& NumLockMask
))
462 TRACE(keyboard
,"Adjusting NumLock state. \n");
463 KEYBOARD_GenerateMsg( VK_NUMLOCK
, KeyPress
, event_x
, event_y
,
465 KEYBOARD_GenerateMsg( VK_NUMLOCK
, KeyRelease
, event_x
, event_y
,
468 if (!(InputKeyStateTable
[VK_CAPITAL
] & 0x01) != !(event
->state
& LockMask
))
470 TRACE(keyboard
,"Adjusting Caps Lock state. State before %#.2x \n",InputKeyStateTable
[VK_CAPITAL
]);
471 KEYBOARD_GenerateMsg( VK_CAPITAL
, KeyPress
, event_x
, event_y
,
473 KEYBOARD_GenerateMsg( VK_CAPITAL
, KeyRelease
, event_x
, event_y
,
475 TRACE(keyboard
,"State after %#.2x \n",InputKeyStateTable
[VK_CAPITAL
]);
477 /* End of intermediary states. */
481 TRACE(key
," wParam=%04X, lParam=%08lX\n",
483 TRACE(key
," InputKeyState=%X\n",
484 InputKeyStateTable
[vkey
]);
486 hardware_event( message
, vkey
, keylp
.lp2
,
487 event_x
, event_y
, event_time
, 0 );
494 /**********************************************************************
495 * GetKeyState [USER.106]
497 WORD WINAPI
GetKeyState16(INT16 vkey
)
499 return GetKeyState32(vkey
);
502 /**********************************************************************
503 * GetKeyState [USER32.248]
504 * An application calls the GetKeyState function in response to a
505 * keyboard-input message. This function retrieves the state of the key
506 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
508 WORD WINAPI
GetKeyState32(INT32 vkey
)
514 case VK_LBUTTON
: /* VK_LBUTTON is 1 */
515 retval
= MouseButtonsStates
[0] ? 0x8000 : 0;
517 case VK_MBUTTON
: /* VK_MBUTTON is 4 */
518 retval
= MouseButtonsStates
[1] ? 0x8000 : 0;
520 case VK_RBUTTON
: /* VK_RBUTTON is 2 */
521 retval
= MouseButtonsStates
[2] ? 0x8000 : 0;
524 if (vkey
>= 'a' && vkey
<= 'z')
526 retval
= ( (WORD
)(QueueKeyStateTable
[vkey
] & 0x80) << 8 ) |
527 (WORD
)(QueueKeyStateTable
[vkey
] & 0x01);
529 TRACE(key
, "(0x%x) -> %x\n", vkey
, retval
);
533 /**********************************************************************
534 * GetKeyboardState [USER.222][USER32.253]
535 * An application calls the GetKeyboardState function in response to a
536 * keyboard-input message. This function retrieves the state of the keyboard
537 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
539 VOID WINAPI
GetKeyboardState(LPBYTE lpKeyState
)
541 TRACE(key
, "(%p)\n", lpKeyState
);
542 if (lpKeyState
!= NULL
) {
543 QueueKeyStateTable
[VK_LBUTTON
] = MouseButtonsStates
[0] ? 0x80 : 0;
544 QueueKeyStateTable
[VK_MBUTTON
] = MouseButtonsStates
[1] ? 0x80 : 0;
545 QueueKeyStateTable
[VK_RBUTTON
] = MouseButtonsStates
[2] ? 0x80 : 0;
546 memcpy(lpKeyState
, QueueKeyStateTable
, 256);
550 /**********************************************************************
551 * SetKeyboardState [USER.223][USER32.483]
553 VOID WINAPI
SetKeyboardState(LPBYTE lpKeyState
)
555 TRACE(key
, "(%p)\n", lpKeyState
);
556 if (lpKeyState
!= NULL
) {
557 memcpy(QueueKeyStateTable
, lpKeyState
, 256);
558 MouseButtonsStates
[0] = (QueueKeyStateTable
[VK_LBUTTON
] != 0);
559 MouseButtonsStates
[1] = (QueueKeyStateTable
[VK_MBUTTON
] != 0);
560 MouseButtonsStates
[2] = (QueueKeyStateTable
[VK_RBUTTON
] != 0);
564 /**********************************************************************
565 * GetAsyncKeyState (USER32.206)
567 * Determine if a key is or was pressed. retval has high-order
568 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
571 * This uses the variable AsyncMouseButtonsStates and
572 * AsyncKeyStateTable (set in event.c) which have the mouse button
573 * number or key number (whichever is applicable) set to true if the
574 * mouse or key had been depressed since the last call to
577 WORD WINAPI
GetAsyncKeyState32(INT32 nKey
)
583 retval
= (AsyncMouseButtonsStates
[0] ? 0x0001 : 0) |
584 (MouseButtonsStates
[0] ? 0x8000 : 0);
587 retval
= (AsyncMouseButtonsStates
[1] ? 0x0001 : 0) |
588 (MouseButtonsStates
[1] ? 0x8000 : 0);
591 retval
= (AsyncMouseButtonsStates
[2] ? 0x0001 : 0) |
592 (MouseButtonsStates
[2] ? 0x8000 : 0);
595 retval
= AsyncKeyStateTable
[nKey
] |
596 ((InputKeyStateTable
[nKey
] & 0x80) ? 0x8000 : 0);
600 /* all states to false */
601 memset( AsyncMouseButtonsStates
, 0, sizeof(AsyncMouseButtonsStates
) );
602 memset( AsyncKeyStateTable
, 0, sizeof(AsyncKeyStateTable
) );
604 TRACE(key
, "(%x) -> %x\n", nKey
, retval
);
608 /**********************************************************************
609 * GetAsyncKeyState (USER.249)
611 WORD WINAPI
GetAsyncKeyState16(INT16 nKey
)
613 return GetAsyncKeyState32(nKey
);
616 /**********************************************************************
617 * TranslateAccelerator [USER.178][USER32.551..]
619 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
621 static BOOL32
KBD_translate_accelerator(HWND32 hWnd
,LPMSG32 msg
,
622 BYTE fVirt
,WORD key
,WORD cmd
)
624 BOOL32 sendmsg
= FALSE
;
626 if(msg
->wParam
== key
)
628 if (msg
->message
== WM_CHAR
) {
629 if ( !(fVirt
& FALT
) && !(fVirt
& FVIRTKEY
) )
631 TRACE(accel
,"found accel for WM_CHAR: ('%c')\n",
636 if(fVirt
& FVIRTKEY
) {
638 TRACE(accel
,"found accel for virt_key %04x (scan %04x)\n",
639 msg
->wParam
,0xff & HIWORD(msg
->lParam
));
640 if(GetKeyState32(VK_SHIFT
) & 0x8000) mask
|= FSHIFT
;
641 if(GetKeyState32(VK_CONTROL
) & 0x8000) mask
|= FCONTROL
;
642 if(GetKeyState32(VK_MENU
) & 0x8000) mask
|= FALT
;
643 if(mask
== (fVirt
& (FSHIFT
| FCONTROL
| FALT
)))
646 TRACE(accel
,", but incorrect SHIFT/CTRL/ALT-state\n");
650 if (!(msg
->lParam
& 0x01000000)) /* no special_key */
652 if ((fVirt
& FALT
) && (msg
->lParam
& 0x20000000))
653 { /* ^^ ALT pressed */
654 TRACE(accel
,"found accel for Alt-%c\n", msg
->wParam
&0xff);
661 if (sendmsg
) /* found an accelerator, but send a message... ? */
663 INT16 iSysStat
,iStat
,mesg
=0;
666 if (msg
->message
== WM_KEYUP
|| msg
->message
== WM_SYSKEYUP
)
672 if (!IsWindowEnabled32(hWnd
))
676 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
678 hMenu
= (wndPtr
->dwStyle
& WS_CHILD
) ? 0 : (HMENU32
)wndPtr
->wIDmenu
;
679 iSysStat
= (wndPtr
->hSysMenu
) ? GetMenuState32(GetSubMenu16(wndPtr
->hSysMenu
, 0),
680 cmd
, MF_BYCOMMAND
) : -1 ;
681 iStat
= (hMenu
) ? GetMenuState32(hMenu
,
682 cmd
, MF_BYCOMMAND
) : -1 ;
686 if (iSysStat
& (MF_DISABLED
|MF_GRAYED
))
695 if (IsIconic32(hWnd
))
699 if (iStat
& (MF_DISABLED
|MF_GRAYED
))
709 if ( mesg
==WM_COMMAND
|| mesg
==WM_SYSCOMMAND
)
711 TRACE(accel
,", sending %s, wParam=%0x\n",
712 mesg
==WM_COMMAND
? "WM_COMMAND" : "WM_SYSCOMMAND",
714 SendMessage32A(hWnd
, mesg
, cmd
, 0x00010000L
);
718 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
719 * #0: unknown (please report!)
720 * #1: for WM_KEYUP,WM_SYSKEYUP
721 * #2: mouse is captured
722 * #3: window is disabled
723 * #4: it's a disabled system menu option
724 * #5: it's a menu option, but window is iconic
725 * #6: it's a menu option, but disabled
727 TRACE(accel
,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg
);
729 ERR(accel
, " unknown reason - please report!");
737 INT32 WINAPI
TranslateAccelerator32(HWND32 hWnd
, HACCEL32 hAccel
, LPMSG32 msg
)
739 LPACCEL32 lpAccelTbl
= (LPACCEL32
)LockResource32(hAccel
);
742 if (hAccel
== 0 || msg
== NULL
||
743 (msg
->message
!= WM_KEYDOWN
&&
744 msg
->message
!= WM_KEYUP
&&
745 msg
->message
!= WM_SYSKEYDOWN
&&
746 msg
->message
!= WM_SYSKEYUP
&&
747 msg
->message
!= WM_CHAR
)) {
748 WARN(accel
, "erraneous input parameters\n");
749 SetLastError(ERROR_INVALID_PARAMETER
);
753 TRACE(accel
, "TranslateAccelerators hAccel=%04x, hWnd=%04x,"
754 "msg->hwnd=%04x, msg->message=%04x\n",
755 hAccel
,hWnd
,msg
->hwnd
,msg
->message
);
757 for (i
= 0; lpAccelTbl
[i
].key
; i
++)
758 if (KBD_translate_accelerator(hWnd
,msg
,lpAccelTbl
[i
].fVirt
,
759 lpAccelTbl
[i
].key
,lpAccelTbl
[i
].cmd
))
761 WARN(accel
, "couldn't translate accelerator key");
765 INT16 WINAPI
TranslateAccelerator16(HWND16 hWnd
, HACCEL16 hAccel
, LPMSG16 msg
)
767 LPACCEL16 lpAccelTbl
= (LPACCEL16
)LockResource16(hAccel
);
771 if (hAccel
== 0 || msg
== NULL
||
772 (msg
->message
!= WM_KEYDOWN
&&
773 msg
->message
!= WM_KEYUP
&&
774 msg
->message
!= WM_SYSKEYDOWN
&&
775 msg
->message
!= WM_SYSKEYUP
&&
776 msg
->message
!= WM_CHAR
)) {
777 WARN(accel
, "erraneous input parameters\n");
778 SetLastError(ERROR_INVALID_PARAMETER
);
782 TRACE(accel
, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
783 msg->hwnd=%04x, msg->message=%04x\n", hAccel
,hWnd
,msg
->hwnd
,msg
->message
);
784 STRUCT32_MSG16to32(msg
,&msg32
);
787 for (i
=0;lpAccelTbl
[i
].key
;i
++)
788 if (KBD_translate_accelerator(hWnd
,&msg32
,lpAccelTbl
[i
].fVirt
,
789 lpAccelTbl
[i
].key
,lpAccelTbl
[i
].cmd
))
791 WARN(accel
, "couldn't translate accelerator key");
796 /******************************************************************************
797 * OemKeyScan [KEYBOARD.128][USER32.400]
799 DWORD WINAPI
OemKeyScan(WORD wOemChar
)
801 TRACE(keyboard
,"*OemKeyScan (%d)\n",wOemChar
);
806 /******************************************************************************
807 * VkKeyScanA [USER32.572]
809 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
810 * for the current keyboard.
811 * high-order byte yields :
815 * 3-5 Shift-key combinations that are not used for characters
818 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
819 * FIXME : works ok except for dead chars :
820 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
821 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
824 WORD WINAPI
VkKeyScan32A(CHAR cChar
)
831 /* char->keysym (same for ANSI chars) */
832 keysym
=(unsigned char) cChar
;/* (!) cChar is signed */
833 if (keysym
<=27) keysym
+=0xFF00;/*special chars : return, backspace...*/
835 keycode
= TSXKeysymToKeycode(display
, keysym
); /* keysym -> keycode */
837 { /* It didn't work ... let's try with deadchar code. */
838 keycode
= TSXKeysymToKeycode(display
, keysym
| 0xFE00);
841 TRACE(keyboard
,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
842 cChar
,keysym
,keysym
,keycode
);
846 for (index
=-1, i
=0; (i
<8) && (index
<0); i
++) /* find shift state */
847 if (TSXKeycodeToKeysym(display
,keycode
,i
)==keysym
) index
=i
;
850 fprintf(stderr
,"Keysym %lx not found while parsing the keycode table\n",keysym
); break;
852 case 1 : highbyte
= 0x0100; break;
853 case 2 : highbyte
= 0X0600; break;
854 default : fprintf(stderr
,"index %d found by XKeycodeToKeysym. please report! \n",index
);
857 index : 0 adds 0x0000
858 index : 1 adds 0x0100 (shift)
859 index : ? adds 0x0200 (ctrl)
860 index : 2 adds 0x0600 (ctrl+alt)
861 index : ? adds 0x0700 (ctrl+alt+shift (used?))
864 TRACE(keyboard
," ... returning %#.2x\n", keyc2vkey
[keycode
]+highbyte
);
865 return keyc2vkey
[keycode
]+highbyte
; /* keycode -> (keyc2vkey) vkey */
868 /******************************************************************************
869 * VkKeyScan [KEYBOARD.129]
871 WORD WINAPI
VkKeyScan16(CHAR cChar
)
873 return VkKeyScan32A(cChar
);
876 /******************************************************************************
877 * VkKeyScanW [USER32.575]
879 WORD WINAPI
VkKeyScan32W(WCHAR cChar
)
881 return VkKeyScan32A((CHAR
)cChar
); /* FIXME: check unicode */
884 /******************************************************************************
885 * GetKeyboardType [KEYBOARD.130]
887 INT16 WINAPI
GetKeyboardType16(INT16 nTypeFlag
)
889 return GetKeyboardType32(nTypeFlag
);
892 /******************************************************************************
893 * GetKeyboardType [USER32.254]
895 INT32 WINAPI
GetKeyboardType32(INT32 nTypeFlag
)
897 TRACE(keyboard
,"(%d)\n",nTypeFlag
);
900 case 0: /* Keyboard type */
901 return 4; /* AT-101 */
903 case 1: /* Keyboard Subtype */
904 return 0; /* There are no defined subtypes */
906 case 2: /* Number of F-keys */
907 return 12; /* We're doing an 101 for now, so return 12 F-keys */
910 fprintf(stderr
, "Unknown type on GetKeyboardType\n");
911 return 0; /* The book says 0 here, so 0 */
916 /******************************************************************************
917 * MapVirtualKeyA [USER32.382]
919 UINT32 WINAPI
MapVirtualKey32A(UINT32 code
, UINT32 maptype
)
921 return MapVirtualKey16(code
,maptype
);
924 /******************************************************************************
925 * MapVirtualKeyA [USER32.384]
927 UINT32 WINAPI
MapVirtualKey32W(UINT32 code
, UINT32 maptype
)
929 return MapVirtualKey16(code
,maptype
);
932 /******************************************************************************
933 * MapVirtualKeyA [KEYBOARD.131]
934 * MapVirtualKey translates keycodes from one format to another
936 UINT16 WINAPI
MapVirtualKey16(UINT16 wCode
, UINT16 wMapType
)
938 #define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; }
940 TRACE(keyboard
,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
943 case 0: { /* vkey-code to scan-code */
944 /* let's do vkey -> keycode -> scan */
946 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++) /* see event.c */
947 if ((keyc2vkey
[keyc
] & 0xFF)== wCode
)
948 returnMVK (keyc
- 8);
951 case 1: /* scan-code to vkey-code */
952 /* let's do scan -> keycode -> vkey */
954 returnMVK (keyc2vkey
[(wCode
& 0xFF) + 8]);
956 case 2: { /* vkey-code to unshifted ANSI code */
957 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
958 /* My Windows returns 'A'. */
959 /* let's do vkey -> keycode -> (XLookupString) ansi char */
964 e
.state
= 0; /* unshifted */
965 e
.keycode
= MapVirtualKey16( wCode
, 0);
966 if (!TSXLookupString(&e
, s
, 2 , &keysym
, NULL
))
971 default: /* reserved */
972 fprintf(stderr
, "MapVirtualKey: unknown wMapType %d !\n",
980 /****************************************************************************
981 * GetKBCodePage16 (KEYBOARD.132)
983 INT16 WINAPI
GetKBCodePage16(void)
985 TRACE(keyboard
,"(void)\n");
990 /****************************************************************************
991 * GetKBCodePage32 (USER32.245)
993 UINT32 WINAPI
GetKBCodePage32(void)
995 TRACE(keyboard
,"(void)\n");
1000 /****************************************************************************
1001 * GetKeyNameText32W (USER32.247)
1003 INT32 WINAPI
GetKeyNameText32W(LONG lParam
, LPWSTR lpBuffer
, INT32 nSize
)
1005 LPSTR buf
= HEAP_xalloc( GetProcessHeap(), 0, nSize
);
1006 int res
= GetKeyNameText32A(lParam
,buf
,nSize
);
1008 lstrcpynAtoW(lpBuffer
,buf
,nSize
);
1009 HeapFree( GetProcessHeap(), 0, buf
);
1013 /****************************************************************************
1014 * GetKeyNameText32A (USER32.246)
1016 INT32 WINAPI
GetKeyNameText32A(LONG lParam
, LPSTR lpBuffer
, INT32 nSize
)
1018 return GetKeyNameText16(lParam
,lpBuffer
,nSize
);
1021 /****************************************************************************
1022 * GetKeyNameText16 (KEYBOARD.133)
1024 INT16 WINAPI
GetKeyNameText16(LONG lParam
, LPSTR lpBuffer
, INT16 nSize
)
1028 TRACE(keyboard
,"(%ld,<ptr>,%d)\n",lParam
,nSize
);
1033 /* for (i = 0 ; i != KeyTableSize ; i++)
1034 if (KeyTable[i].scancode == lParam) {
1035 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1036 return strlen(lpBuffer);
1039 /* FIXME ! GetKeyNameText is still to do...
1046 /****************************************************************************
1047 * ToAscii (KEYBOARD.4)
1049 INT16 WINAPI
ToAscii16(UINT16 virtKey
,UINT16 scanCode
, LPBYTE lpKeyState
,
1050 LPVOID lpChar
, UINT16 flags
)
1052 return ToAscii32(virtKey
,scanCode
,lpKeyState
,lpChar
,flags
);
1055 /****************************************************************************
1056 * ToAscii (USER32.545)
1058 INT32 WINAPI
ToAscii32( UINT32 virtKey
,UINT32 scanCode
,LPBYTE lpKeyState
,
1059 LPWORD lpChar
,UINT32 flags
)
1063 static XComposeStatus cs
;
1067 e
.display
= display
;
1069 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++)
1070 { /* this could be speeded up by making another table, an array of struct vkey,keycode
1071 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
1072 if ((keyc2vkey
[keyc
] & 0xFF)== virtKey
) /* no need to make a more precise test (with the extended bit correctly set above virtKey ... VK* are different enough... */
1074 if ((e
.keycode
) && ((virtKey
<0x10) || (virtKey
>0x12)))
1075 /* it's normal to have 2 shift, control, and alt ! */
1076 TRACE(keyboard
,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1077 e
.keycode
,keyc
,virtKey
);
1081 if ((!e
.keycode
) && (lpKeyState
[VK_NUMLOCK
] & 0x01))
1083 if ((virtKey
>=VK_NUMPAD0
) && (virtKey
<=VK_NUMPAD9
))
1084 e
.keycode
= TSXKeysymToKeycode(e
.display
, virtKey
-VK_NUMPAD0
+XK_KP_0
);
1085 if (virtKey
==VK_DECIMAL
)
1086 e
.keycode
= TSXKeysymToKeycode(e
.display
, XK_KP_Decimal
);
1090 fprintf(stderr
,"ToAscii : Unknown virtual key %X !!! \n",virtKey
);
1091 return virtKey
; /* whatever */
1094 if (lpKeyState
[VK_SHIFT
] & 0x80)
1095 e
.state
|= ShiftMask
;
1096 TRACE(keyboard
,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState
[VK_CAPITAL
]);
1097 if (lpKeyState
[VK_CAPITAL
] & 0x01)
1098 e
.state
|= LockMask
;
1099 if (lpKeyState
[VK_CONTROL
] & 0x80)
1100 if (lpKeyState
[VK_MENU
] & 0x80)
1101 e
.state
|= AltGrMask
;
1103 e
.state
|= ControlMask
;
1104 if (lpKeyState
[VK_NUMLOCK
] & 0x01)
1105 e
.state
|= NumLockMask
;
1106 TRACE(key
, "(%04X, %04X) : faked state = %X\n",
1107 virtKey
, scanCode
, e
.state
);
1108 ret
= TSXLookupString(&e
, (LPVOID
)lpChar
, 2, &keysym
, &cs
);
1113 ((char*)lpChar
)[1] = '\0';
1116 /* symbolic ASCII is the same as defined in rfc1345 */
1117 #ifdef XK_dead_tilde
1118 case XK_dead_tilde
:
1120 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1121 dead_char
= '~'; /* '? */
1123 #ifdef XK_dead_acute
1124 case XK_dead_acute
:
1126 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1127 dead_char
= 0xb4; /* '' */
1129 #ifdef XK_dead_circumflex
1130 case XK_dead_circumflex
:
1132 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1133 dead_char
= '^'; /* '> */
1135 #ifdef XK_dead_grave
1136 case XK_dead_grave
:
1138 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1139 dead_char
= '`'; /* '! */
1141 #ifdef XK_dead_diaeresis
1142 case XK_dead_diaeresis
:
1144 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1145 dead_char
= 0xa8; /* ': */
1147 #ifdef XK_dead_cedilla
1148 case XK_dead_cedilla
:
1149 dead_char
= 0xb8; /* ', */
1152 #ifdef XK_dead_macron
1153 case XK_dead_macron
:
1154 dead_char
= '-'; /* 'm isn't defined on iso-8859-x */
1157 #ifdef XK_dead_breve
1158 case XK_dead_breve
:
1159 dead_char
= 0xa2; /* '( */
1162 #ifdef XK_dead_abovedot
1163 case XK_dead_abovedot
:
1164 dead_char
= 0xff; /* '. */
1167 #ifdef XK_dead_abovering
1168 case XK_dead_abovering
:
1169 dead_char
= '0'; /* '0 isn't defined on iso-8859-x */
1172 #ifdef XK_dead_doubleacute
1173 case XK_dead_doubleacute
:
1174 dead_char
= 0xbd; /* '" */
1177 #ifdef XK_dead_caron
1178 case XK_dead_caron
:
1179 dead_char
= 0xb7; /* '< */
1182 #ifdef XK_dead_ogonek
1183 case XK_dead_ogonek
:
1184 dead_char
= 0xb2; /* '; */
1187 /* FIXME: I don't know this three.
1191 case XK_dead_voiced_sound :
1194 case XK_dead_semivoiced_sound :
1201 *(char*)lpChar
= dead_char
;
1208 ksname
= TSXKeysymToString(keysym
);
1211 if ((keysym
>> 8) != 0xff)
1213 fprintf(stderr
, "Please report : no char for keysym %04lX (%s) :\n",
1215 fprintf(stderr
, " virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1216 virtKey
, scanCode
, e
.keycode
, e
.state
);
1220 TRACE(key
, "ToAscii about to return %d with char %x\n",
1221 ret
, *(char*)lpChar
);
1226 /***********************************************************************
1227 * GetKeyboardLayout (USER32.249)
1229 HKL32 WINAPI
GetKeyboardLayout(DWORD dwLayout
)
1231 fprintf(stderr
,"GetKeyboardLayout(%ld),STUB!\n",dwLayout
);
1232 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1235 /***********************************************************************
1236 * GetKeyboardLayoutList (USER32.250)
1239 INT32 WINAPI
GetKeyboardLayoutList(INT32 nBuff
,HKL32
*layouts
)
1241 fprintf(stderr
,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff
,layouts
);
1243 layouts
[0] = GetKeyboardLayout(0);
1248 /***********************************************************************
1249 * RegisterHotKey (USER32.433)
1251 BOOL32 WINAPI
RegisterHotKey(HWND32 hwnd
,INT32 id
,UINT32 modifiers
,UINT32 vk
) {
1252 fprintf(stderr
,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
1253 hwnd
,id
,modifiers
,vk
1258 /***********************************************************************
1259 * UnregisterHotKey (USER32.565)
1261 BOOL32 WINAPI
UnregisterHotKey(HWND32 hwnd
,INT32 id
) {
1262 fprintf(stderr
,"UnregisterHotKey(%08x,%d),stub!\n",hwnd
,id
);