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>
29 BOOL32 MouseButtonsStates
[3];
30 BOOL32 AsyncMouseButtonsStates
[3];
31 BYTE InputKeyStateTable
[256];
32 BYTE QueueKeyStateTable
[256];
33 BYTE AsyncKeyStateTable
[256];
35 static int NumLockMask
;
37 static int min_keycode
, max_keycode
;
38 static int keyc2vkey
[256];
44 unsigned long count
: 16;
45 unsigned long code
: 8;
46 unsigned long extended
: 1;
47 unsigned long unused
: 2;
48 unsigned long win_internal
: 2;
49 unsigned long context
: 1;
50 unsigned long previous
: 1;
51 unsigned long transition
: 1;
56 /* Keyboard translation tables */
57 static const int special_key
[] =
59 VK_BACK
, VK_TAB
, 0, VK_CLEAR
, 0, VK_RETURN
, 0, 0, /* FF08 */
60 0, 0, 0, VK_PAUSE
, VK_SCROLL
, 0, 0, 0, /* FF10 */
61 0, 0, 0, VK_ESCAPE
/* FF18 */
64 static const int cursor_key
[] =
66 VK_HOME
, VK_LEFT
, VK_UP
, VK_RIGHT
, VK_DOWN
, VK_PRIOR
,
67 VK_NEXT
, VK_END
/* FF50 */
70 static const int misc_key
[] =
72 VK_SELECT
, VK_SNAPSHOT
, VK_EXECUTE
, VK_INSERT
, 0, 0, 0, 0, /* FF60 */
73 VK_CANCEL
, VK_HELP
, VK_CANCEL
, VK_MENU
/* FF68 */
76 static const int keypad_key
[] =
78 0, VK_NUMLOCK
, /* FF7E */
79 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
80 0, 0, 0, 0, 0, VK_RETURN
, 0, 0, /* FF88 */
81 0, 0, 0, 0, 0, VK_HOME
, VK_LEFT
, VK_UP
, /* FF90 */
82 VK_RIGHT
, VK_DOWN
, VK_PRIOR
, VK_NEXT
, VK_END
, 0,
83 VK_INSERT
, VK_DELETE
, /* FF98 */
84 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
85 0, 0, VK_MULTIPLY
, VK_ADD
, VK_SEPARATOR
, VK_SUBTRACT
,
86 VK_DECIMAL
, VK_DIVIDE
, /* FFA8 */
87 VK_NUMPAD0
, VK_NUMPAD1
, VK_NUMPAD2
, VK_NUMPAD3
, VK_NUMPAD4
,
88 VK_NUMPAD5
, VK_NUMPAD6
, VK_NUMPAD7
, /* FFB0 */
89 VK_NUMPAD8
, VK_NUMPAD9
/* FFB8 */
92 static const int function_key
[] =
94 VK_F1
, VK_F2
, /* FFBE */
95 VK_F3
, VK_F4
, VK_F5
, VK_F6
, VK_F7
, VK_F8
, VK_F9
, VK_F10
, /* FFC0 */
96 VK_F11
, VK_F12
, VK_F13
, VK_F14
, VK_F15
, VK_F16
/* FFC8 */
99 static const int modifier_key
[] =
101 VK_SHIFT
, VK_SHIFT
, VK_CONTROL
, VK_CONTROL
, VK_CAPITAL
, 0, /* FFE1 */
102 VK_MENU
, VK_MENU
, VK_MENU
, VK_MENU
/* FFE7 */
106 * Table for vkey to scancode translation - 5/29/97 chrisf@america.com
108 const BYTE vkey2scode
[512] = {
109 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0e,0x0f,0x00,0x00,0x00,0x1c,0x00,0x00,
110 0x2a,0x1d,0x38,0x00,0x3a,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,
111 0x39,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
112 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,
113 0x00,0x1e,0x30,0x2e,0x20,0x12,0x21,0x22, 0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,
114 0x19,0x10,0x13,0x1f,0x14,0x16,0x2f,0x11, 0x2d,0x15,0x2c,0x00,0x00,0x00,0x00,0x00,
115 0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x37,0x4e,0x00,0x4a,0x34,0x00,
116 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
117 0x00,0x46,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
118 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
119 0x00,0x00,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,0x29,0x0c,0x0d,0x1a,0x1b,0x2b,
121 0x27,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,0x00,0x28,0x33,0x34,0x35,0x4c,
123 0x00,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,0x00,0x00,0x00,0x00,0x00,
126 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,
127 0x00,0x1d,0x38,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
128 0x00,0x49,0x51,0x4f,0x47,0x4b,0x48,0x4d, 0x50,0x00,0x00,0x00,0x00,0x52,0x53,0x00,
129 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
130 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,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,0x35,
133 0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42, 0x43,0x44,0x57,0x58,0x00,0x00,0x00,0x00,
134 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
135 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,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,
144 static WORD
EVENT_event_to_vkey( XKeyEvent
*e
)
148 TSXLookupString(e
, NULL
, 0, &keysym
, NULL
);
150 if ((keysym
>= 0xFFAE) && (keysym
<= 0xFFB9) && (e
->state
& NumLockMask
))
151 /* Only the Keypad keys 0-9 and . send different keysyms
152 * depending on the NumLock state */
153 return keypad_key
[(keysym
& 0xFF) - 0x7E];
155 return keyc2vkey
[e
->keycode
];
158 /**********************************************************************
161 BOOL32
KEYBOARD_Init(void)
163 int i
, keysyms_per_keycode
;
165 XModifierKeymap
*mmp
;
171 TSXDisplayKeycodes(display
, &min_keycode
, &max_keycode
);
172 ksp
= TSXGetKeyboardMapping(display
, min_keycode
,
173 max_keycode
+ 1 - min_keycode
, &keysyms_per_keycode
);
174 /* We are only interested in keysyms_per_keycode.
175 There is no need to hold a local copy of the keysyms table */
177 mmp
= TSXGetModifierMapping(display
);
178 kcp
= mmp
->modifiermap
;
179 for (i
= 0; i
< 8; i
+= 1) /* There are 8 modifier keys */
183 for (j
= 0; j
< mmp
->max_keypermod
; j
+= 1, kcp
+= 1)
188 for (k
= 0; k
< keysyms_per_keycode
; k
+= 1)
189 if (TSXKeycodeToKeysym(display
, *kcp
, k
) == XK_Mode_switch
)
192 TRACE(key
, "AltGrMask is %x\n", AltGrMask
);
194 else if (TSXKeycodeToKeysym(display
, *kcp
, k
) == XK_Num_Lock
)
196 NumLockMask
= 1 << i
;
197 TRACE(key
, "NumLockMask is %x\n", NumLockMask
);
201 TSXFreeModifiermap(mmp
);
203 /* Now build two conversion arrays :
204 * keycode -> vkey + extended
205 * vkey + extended -> keycode */
207 e2
.display
= display
;
210 OEMvkey
= 0xb9; /* first OEM virtual key available is ba */
211 for (e2
.keycode
=min_keycode
; e2
.keycode
<=max_keycode
; e2
.keycode
++)
213 TSXLookupString(&e2
, NULL
, 0, &keysym
, NULL
);
215 if (keysym
) /* otherwise, keycode not used */
217 if ((keysym
>> 8) == 0xFF) /* non-character key */
219 int key
= keysym
& 0xff;
221 if (key
>= 0x08 && key
<= 0x1B) /* special key */
222 vkey
= special_key
[key
- 0x08];
223 else if (key
>= 0x50 && key
<= 0x57) /* cursor key */
224 vkey
= cursor_key
[key
- 0x50];
225 else if (key
>= 0x60 && key
<= 0x6B) /* miscellaneous key */
226 vkey
= misc_key
[key
- 0x60];
227 else if (key
>= 0x7E && key
<= 0xB9) /* keypad key */
228 vkey
= keypad_key
[key
- 0x7E];
229 else if (key
>= 0xBE && key
<= 0xCD) /* function key */
231 vkey
= function_key
[key
- 0xBE];
232 vkey
|= 0x100; /* set extended bit */
234 else if (key
>= 0xE1 && key
<= 0xEA) /* modifier key */
235 vkey
= modifier_key
[key
- 0xE1];
236 else if (key
== 0xFF) /* DEL key */
238 /* extended must also be set for ALT_R, CTRL_R,
239 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
240 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
241 /* FIXME should we set extended bit for NumLock ? My
242 * Windows does ... DF */
262 for (i
= 0; (i
< keysyms_per_keycode
) && (!vkey
); i
++)
264 keysym
= TSXLookupKeysym(&e2
, i
);
265 if ((keysym
>= VK_0
&& keysym
<= VK_9
)
266 || (keysym
>= VK_A
&& keysym
<= VK_Z
)
267 || keysym
== VK_SPACE
)
273 /* Others keys: let's assign OEM virtual key codes in the allowed range,
274 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
277 case 0xc1 : OEMvkey
=0xdb; break;
278 case 0xe5 : OEMvkey
=0xe9; break;
279 case 0xf6 : OEMvkey
=0xf5; fprintf(stderr
,"No more OEM vkey available!\n");
284 if (TRACE_ON(keyboard
))
286 dbg_decl_str(keyboard
, 1024);
288 TRACE(keyboard
, "OEM specific virtual key %X assigned"
289 "to keycode %X :\n", OEMvkey
, e2
.keycode
);
290 for (i
= 0; i
< keysyms_per_keycode
; i
+= 1)
294 keysym
= TSXLookupKeysym(&e2
, i
);
295 ksname
= TSXKeysymToString(keysym
);
298 dsprintf(keyboard
, "%lX (%s) ", keysym
, ksname
);
300 TRACE(keyboard
, "(%s)\n", dbg_str(keyboard
));
304 keyc2vkey
[e2
.keycode
] = vkey
;
309 static BOOL32 NumState
=FALSE
, CapsState
=FALSE
;
311 void KEYBOARD_GenerateMsg( WORD vkey
, int Evtype
, INT32 event_x
, INT32 event_y
,
312 DWORD event_time
, KEYLP localkeylp
)
314 BOOL32
* State
= (vkey
==VK_NUMLOCK
? &NumState
: &CapsState
);
317 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
318 don't treat it. It's from the same key press. Then the state goes to ON.
319 And from there, a 'release' event will switch off the toggle key. */
321 TRACE(keyboard
,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey
,InputKeyStateTable
[vkey
]);
324 if ( InputKeyStateTable
[vkey
] & 0x1 ) /* it was ON */
326 if (Evtype
!=KeyPress
)
328 TRACE(keyboard
,"ON + KeyRelease => generating DOWN and UP messages.\n");
329 localkeylp
.lp1
.previous
= 0; /* ? */
330 localkeylp
.lp1
.transition
= 0;
331 hardware_event( WM_KEYDOWN
, vkey
, localkeylp
.lp2
,
332 event_x
, event_y
, event_time
, 0 );
333 hardware_event( WM_KEYUP
, vkey
, localkeylp
.lp2
,
334 event_x
, event_y
, event_time
, 0 );
336 InputKeyStateTable
[vkey
] &= ~0x01; /* Toggle state to off. */
339 else /* it was OFF */
340 if (Evtype
==KeyPress
)
342 TRACE(keyboard
,"OFF + Keypress => generating DOWN and UP messages.\n");
343 hardware_event( WM_KEYDOWN
, vkey
, localkeylp
.lp2
,
344 event_x
, event_y
, event_time
, 0 );
345 localkeylp
.lp1
.previous
= 1;
346 localkeylp
.lp1
.transition
= 1;
347 hardware_event( WM_KEYUP
, vkey
, localkeylp
.lp2
,
348 event_x
, event_y
, event_time
, 0 );
349 *State
=TRUE
; /* Goes to intermediary state before going to ON */
350 InputKeyStateTable
[vkey
] |= 0x01; /* Toggle state to on. */
355 /***********************************************************************
356 * KEYBOARD_HandleEvent
358 * Handle a X key event
360 void KEYBOARD_HandleEvent( WND
*pWnd
, XKeyEvent
*event
)
367 static BOOL32 force_extended
= FALSE
; /* hack for AltGr translation */
369 int ascii_chars
= TSXLookupString(event
, Str
, 1, &keysym
, &cs
);
371 INT32 event_x
= pWnd
->rectWindow
.left
+ event
->x
;
372 INT32 event_y
= pWnd
->rectWindow
.top
+ event
->y
;
373 DWORD event_time
= event
->time
- MSG_WineStartTicks
;
375 TRACE(key
, "EVENT_key : state = %X\n", event
->state
);
376 if (keysym
== XK_Mode_switch
)
378 TRACE(key
, "Alt Gr key event received\n");
379 event
->keycode
= TSXKeysymToKeycode(event
->display
, XK_Control_L
);
380 TRACE(key
, "Control_L is keycode 0x%x\n", event
->keycode
);
381 KEYBOARD_HandleEvent( pWnd
, event
);
382 event
->keycode
= TSXKeysymToKeycode(event
->display
, XK_Alt_L
);
383 TRACE(key
, "Alt_L is keycode 0x%x\n", event
->keycode
);
384 force_extended
= TRUE
;
385 KEYBOARD_HandleEvent( pWnd
, event
);
386 force_extended
= FALSE
;
390 Str
[ascii_chars
] = '\0';
394 ksname
= TSXKeysymToString(keysym
);
397 TRACE(key
, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
398 (event
->type
== KeyPress
) ? "KeyPress" : "KeyRelease",
399 keysym
, ksname
, ascii_chars
, Str
[0] & 0xff, Str
);
402 vkey
= EVENT_event_to_vkey(event
);
403 if (force_extended
) vkey
|= 0x100;
405 TRACE(key
, "keycode 0x%x converted to vkey 0x%x\n",
406 event
->keycode
, vkey
);
411 keylp
.lp1
.code
= vkey2scode
[vkey
]; /* 5/29/97 chrisf@america.com */
412 keylp
.lp1
.extended
= (vkey
& 0x100 ? 1 : 0);
413 keylp
.lp1
.win_internal
= 0; /* this has something to do with dialogs,
414 * don't remember where I read it - AK */
415 /* it's '1' under windows, when a dialog box appears
416 * and you press one of the underlined keys - DF*/
422 KEYBOARD_GenerateMsg( VK_NUMLOCK
, event
->type
, event_x
, event_y
,
426 TRACE(keyboard
,"Caps Lock event. (type %d). State before : %#.2x\n",event
->type
,InputKeyStateTable
[vkey
]);
427 KEYBOARD_GenerateMsg( VK_CAPITAL
, event
->type
, event_x
, event_y
,
429 TRACE(keyboard
,"State after : %#.2x\n",InputKeyStateTable
[vkey
]);
434 if (event
->type
== KeyPress
)
436 keylp
.lp1
.previous
= (InputKeyStateTable
[vkey
] & 0x80) != 0;
437 if (!(InputKeyStateTable
[vkey
] & 0x80))
438 InputKeyStateTable
[vkey
] ^= 0x01;
439 InputKeyStateTable
[vkey
] |= 0x80;
440 keylp
.lp1
.transition
= 0;
441 message
= (InputKeyStateTable
[VK_MENU
] & 0x80)
442 && !(InputKeyStateTable
[VK_CONTROL
] & 0x80)
443 ? WM_SYSKEYDOWN
: WM_KEYDOWN
;
447 BOOL32 sysKey
= (InputKeyStateTable
[VK_MENU
] & 0x80)
448 && !(InputKeyStateTable
[VK_CONTROL
] & 0x80)
449 && (force_extended
== FALSE
); /* for Alt from AltGr */
451 InputKeyStateTable
[vkey
] &= ~0x80;
452 keylp
.lp1
.previous
= 1;
453 keylp
.lp1
.transition
= 1;
454 message
= sysKey
? WM_SYSKEYUP
: WM_KEYUP
;
456 keylp
.lp1
.context
= ( (event
->state
& Mod1Mask
) ||
457 (InputKeyStateTable
[VK_MENU
] & 0x80)) ? 1 : 0;
458 if (!(InputKeyStateTable
[VK_NUMLOCK
] & 0x01) != !(event
->state
& NumLockMask
))
460 TRACE(keyboard
,"Adjusting NumLock state. \n");
461 KEYBOARD_GenerateMsg( VK_NUMLOCK
, KeyPress
, event_x
, event_y
,
463 KEYBOARD_GenerateMsg( VK_NUMLOCK
, KeyRelease
, event_x
, event_y
,
466 if (!(InputKeyStateTable
[VK_CAPITAL
] & 0x01) != !(event
->state
& LockMask
))
468 TRACE(keyboard
,"Adjusting Caps Lock state. State before %#.2x \n",InputKeyStateTable
[VK_CAPITAL
]);
469 KEYBOARD_GenerateMsg( VK_CAPITAL
, KeyPress
, event_x
, event_y
,
471 KEYBOARD_GenerateMsg( VK_CAPITAL
, KeyRelease
, event_x
, event_y
,
473 TRACE(keyboard
,"State after %#.2x \n",InputKeyStateTable
[VK_CAPITAL
]);
475 /* End of intermediary states. */
479 TRACE(key
," wParam=%04X, lParam=%08lX\n",
481 TRACE(key
," InputKeyState=%X\n",
482 InputKeyStateTable
[vkey
]);
484 hardware_event( message
, vkey
, keylp
.lp2
,
485 event_x
, event_y
, event_time
, 0 );
492 /**********************************************************************
493 * GetKeyState [USER.106]
495 WORD WINAPI
GetKeyState16(INT16 vkey
)
497 return GetKeyState32(vkey
);
500 /**********************************************************************
501 * GetKeyState [USER32.248]
502 * An application calls the GetKeyState function in response to a
503 * keyboard-input message. This function retrieves the state of the key
504 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
506 WORD WINAPI
GetKeyState32(INT32 vkey
)
512 case VK_LBUTTON
: /* VK_LBUTTON is 1 */
513 retval
= MouseButtonsStates
[0] ? 0x8000 : 0;
515 case VK_MBUTTON
: /* VK_MBUTTON is 4 */
516 retval
= MouseButtonsStates
[1] ? 0x8000 : 0;
518 case VK_RBUTTON
: /* VK_RBUTTON is 2 */
519 retval
= MouseButtonsStates
[2] ? 0x8000 : 0;
522 if (vkey
>= 'a' && vkey
<= 'z')
524 retval
= ( (WORD
)(QueueKeyStateTable
[vkey
] & 0x80) << 8 ) |
525 (WORD
)(QueueKeyStateTable
[vkey
] & 0x01);
527 TRACE(key
, "(0x%x) -> %x\n", vkey
, retval
);
531 /**********************************************************************
532 * GetKeyboardState [USER.222][USER32.253]
533 * An application calls the GetKeyboardState function in response to a
534 * keyboard-input message. This function retrieves the state of the keyboard
535 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
537 VOID WINAPI
GetKeyboardState(LPBYTE lpKeyState
)
539 TRACE(key
, "(%p)\n", lpKeyState
);
540 if (lpKeyState
!= NULL
) {
541 QueueKeyStateTable
[VK_LBUTTON
] = MouseButtonsStates
[0] ? 0x80 : 0;
542 QueueKeyStateTable
[VK_MBUTTON
] = MouseButtonsStates
[1] ? 0x80 : 0;
543 QueueKeyStateTable
[VK_RBUTTON
] = MouseButtonsStates
[2] ? 0x80 : 0;
544 memcpy(lpKeyState
, QueueKeyStateTable
, 256);
548 /**********************************************************************
549 * SetKeyboardState [USER.223][USER32.483]
551 VOID WINAPI
SetKeyboardState(LPBYTE lpKeyState
)
553 TRACE(key
, "(%p)\n", lpKeyState
);
554 if (lpKeyState
!= NULL
) {
555 memcpy(QueueKeyStateTable
, lpKeyState
, 256);
556 MouseButtonsStates
[0] = (QueueKeyStateTable
[VK_LBUTTON
] != 0);
557 MouseButtonsStates
[1] = (QueueKeyStateTable
[VK_MBUTTON
] != 0);
558 MouseButtonsStates
[2] = (QueueKeyStateTable
[VK_RBUTTON
] != 0);
562 /**********************************************************************
563 * GetAsyncKeyState (USER32.206)
565 * Determine if a key is or was pressed. retval has high-order
566 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
569 * This uses the variable AsyncMouseButtonsStates and
570 * AsyncKeyStateTable (set in event.c) which have the mouse button
571 * number or key number (whichever is applicable) set to true if the
572 * mouse or key had been depressed since the last call to
575 WORD WINAPI
GetAsyncKeyState32(INT32 nKey
)
581 retval
= (AsyncMouseButtonsStates
[0] ? 0x0001 : 0) |
582 (MouseButtonsStates
[0] ? 0x8000 : 0);
585 retval
= (AsyncMouseButtonsStates
[1] ? 0x0001 : 0) |
586 (MouseButtonsStates
[1] ? 0x8000 : 0);
589 retval
= (AsyncMouseButtonsStates
[2] ? 0x0001 : 0) |
590 (MouseButtonsStates
[2] ? 0x8000 : 0);
593 retval
= AsyncKeyStateTable
[nKey
] |
594 ((InputKeyStateTable
[nKey
] & 0x80) ? 0x8000 : 0);
598 /* all states to false */
599 memset( AsyncMouseButtonsStates
, 0, sizeof(AsyncMouseButtonsStates
) );
600 memset( AsyncKeyStateTable
, 0, sizeof(AsyncKeyStateTable
) );
602 TRACE(key
, "(%x) -> %x\n", nKey
, retval
);
606 /**********************************************************************
607 * GetAsyncKeyState (USER.249)
609 WORD WINAPI
GetAsyncKeyState16(INT16 nKey
)
611 return GetAsyncKeyState32(nKey
);
614 /*********************************************************************
615 * CreateAcceleratorTable (USER.64)
617 HACCEL32 WINAPI
CreateAcceleratorTable32A(LPACCEL32 lpaccel
, INT32 cEntries
) {
618 fprintf(stderr
, "CreateAcceleratorTable32A Stub\n");
622 /**********************************************************************
623 * TranslateAccelerator [USER.178][USER32.551..]
625 * FIXME: should send some WM_INITMENU or/and WM_INITMENUPOPUP -messages
627 static BOOL32
KBD_translate_accelerator(HWND32 hWnd
,LPMSG32 msg
,
628 BYTE fVirt
,WORD key
,WORD cmd
)
630 BOOL32 sendmsg
= FALSE
;
632 if(msg
->wParam
== key
)
634 if (msg
->message
== WM_CHAR
) {
635 if ( !(fVirt
& FALT
) && !(fVirt
& FVIRTKEY
) )
637 TRACE(accel
,"found accel for WM_CHAR: ('%c')\n",
642 if(fVirt
& FVIRTKEY
) {
644 TRACE(accel
,"found accel for virt_key %04x (scan %04x)\n",
645 msg
->wParam
,0xff & HIWORD(msg
->lParam
));
646 if(GetKeyState32(VK_SHIFT
) & 0x8000) mask
|= FSHIFT
;
647 if(GetKeyState32(VK_CONTROL
) & 0x8000) mask
|= FCONTROL
;
648 if(GetKeyState32(VK_MENU
) & 0x8000) mask
|= FALT
;
649 if(mask
== (fVirt
& (FSHIFT
| FCONTROL
| FALT
)))
652 TRACE(accel
,", but incorrect SHIFT/CTRL/ALT-state\n");
656 if (!(msg
->lParam
& 0x01000000)) /* no special_key */
658 if ((fVirt
& FALT
) && (msg
->lParam
& 0x20000000))
659 { /* ^^ ALT pressed */
660 TRACE(accel
,"found accel for Alt-%c\n", msg
->wParam
&0xff);
667 if (sendmsg
) /* found an accelerator, but send a message... ? */
669 INT16 iSysStat
,iStat
,mesg
=0;
672 if (msg
->message
== WM_KEYUP
|| msg
->message
== WM_SYSKEYUP
)
678 if (!IsWindowEnabled32(hWnd
))
682 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
684 hMenu
= (wndPtr
->dwStyle
& WS_CHILD
) ? 0 : (HMENU32
)wndPtr
->wIDmenu
;
685 iSysStat
= (wndPtr
->hSysMenu
) ? GetMenuState32(GetSubMenu16(wndPtr
->hSysMenu
, 0),
686 cmd
, MF_BYCOMMAND
) : -1 ;
687 iStat
= (hMenu
) ? GetMenuState32(hMenu
,
688 cmd
, MF_BYCOMMAND
) : -1 ;
692 if (iSysStat
& (MF_DISABLED
|MF_GRAYED
))
701 if (IsIconic32(hWnd
))
705 if (iStat
& (MF_DISABLED
|MF_GRAYED
))
715 if ( mesg
==WM_COMMAND
|| mesg
==WM_SYSCOMMAND
)
717 TRACE(accel
,", sending %s, wParam=%0x\n",
718 mesg
==WM_COMMAND
? "WM_COMMAND" : "WM_SYSCOMMAND",
720 SendMessage32A(hWnd
, mesg
, cmd
, 0x00010000L
);
724 /* some reasons for NOT sending the WM_{SYS}COMMAND message:
725 * #0: unknown (please report!)
726 * #1: for WM_KEYUP,WM_SYSKEYUP
727 * #2: mouse is captured
728 * #3: window is disabled
729 * #4: it's a disabled system menu option
730 * #5: it's a menu option, but window is iconic
731 * #6: it's a menu option, but disabled
733 TRACE(accel
,", but won't send WM_{SYS}COMMAND, reason is #%d\n",mesg
);
735 ERR(accel
, " unknown reason - please report!");
743 INT32 WINAPI
TranslateAccelerator32(HWND32 hWnd
, HACCEL32 hAccel
, LPMSG32 msg
)
745 LPACCEL32 lpAccelTbl
= (LPACCEL32
)LockResource32(hAccel
);
748 if (hAccel
== 0 || msg
== NULL
) return 0;
749 if (msg
->message
!= WM_KEYDOWN
&&
750 msg
->message
!= WM_KEYUP
&&
751 msg
->message
!= WM_SYSKEYDOWN
&&
752 msg
->message
!= WM_SYSKEYUP
&&
753 msg
->message
!= WM_CHAR
) return 0;
755 TRACE(accel
, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
756 msg->hwnd=%04x, msg->message=%04x\n", hAccel
,hWnd
,msg
->hwnd
,msg
->message
);
758 for (i
= 0; lpAccelTbl
[i
].key
; i
++)
759 if (KBD_translate_accelerator(hWnd
,msg
,lpAccelTbl
[i
].fVirt
,
760 lpAccelTbl
[i
].key
,lpAccelTbl
[i
].cmd
))
765 INT16 WINAPI
TranslateAccelerator16(HWND16 hWnd
, HACCEL16 hAccel
, LPMSG16 msg
)
767 LPACCEL16 lpAccelTbl
= (LPACCEL16
)LockResource16(hAccel
);
771 if (hAccel
== 0 || msg
== NULL
) return 0;
772 if (msg
->message
!= WM_KEYDOWN
&&
773 msg
->message
!= WM_KEYUP
&&
774 msg
->message
!= WM_SYSKEYDOWN
&&
775 msg
->message
!= WM_SYSKEYUP
&&
776 msg
->message
!= WM_CHAR
) return 0;
778 TRACE(accel
, "TranslateAccelerators hAccel=%04x, hWnd=%04x,\
779 msg->hwnd=%04x, msg->message=%04x\n", hAccel
,hWnd
,msg
->hwnd
,msg
->message
);
780 STRUCT32_MSG16to32(msg
,&msg32
);
783 for (i
=0;lpAccelTbl
[i
].key
;i
++)
784 if (KBD_translate_accelerator(hWnd
,&msg32
,lpAccelTbl
[i
].fVirt
,
785 lpAccelTbl
[i
].key
,lpAccelTbl
[i
].cmd
))
791 /******************************************************************************
792 * OemKeyScan [KEYBOARD.128][USER32.400]
794 DWORD WINAPI
OemKeyScan(WORD wOemChar
)
796 TRACE(keyboard
,"*OemKeyScan (%d)\n",wOemChar
);
801 /******************************************************************************
802 * VkKeyScanA [USER32.572]
804 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
805 * for the current keyboard.
806 * high-order byte yields :
810 * 3-5 Shift-key combinations that are not used for characters
813 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
814 * FIXME : works ok except for dead chars :
815 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
816 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
819 WORD WINAPI
VkKeyScan32A(CHAR cChar
)
826 /* char->keysym (same for ANSI chars) */
827 keysym
=(unsigned char) cChar
;/* (!) cChar is signed */
828 if (keysym
<=27) keysym
+=0xFF00;/*special chars : return, backspace...*/
830 keycode
= TSXKeysymToKeycode(display
, keysym
); /* keysym -> keycode */
832 { /* It didn't work ... let's try with deadchar code. */
833 keycode
= TSXKeysymToKeycode(display
, keysym
| 0xFE00);
836 TRACE(keyboard
,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
837 cChar
,keysym
,keysym
,keycode
);
841 for (index
=-1, i
=0; (i
<8) && (index
<0); i
++) /* find shift state */
842 if (TSXKeycodeToKeysym(display
,keycode
,i
)==keysym
) index
=i
;
845 fprintf(stderr
,"Keysym %lx not found while parsing the keycode table\n",keysym
); break;
847 case 1 : highbyte
= 0x0100; break;
848 case 2 : highbyte
= 0X0600; break;
849 default : fprintf(stderr
,"index %d found by XKeycodeToKeysym. please report! \n",index
);
852 index : 0 adds 0x0000
853 index : 1 adds 0x0100 (shift)
854 index : ? adds 0x0200 (ctrl)
855 index : 2 adds 0x0600 (ctrl+alt)
856 index : ? adds 0x0700 (ctrl+alt+shift (used?))
859 TRACE(keyboard
," ... returning %#.2x\n", keyc2vkey
[keycode
]+highbyte
);
860 return keyc2vkey
[keycode
]+highbyte
; /* keycode -> (keyc2vkey) vkey */
863 /******************************************************************************
864 * VkKeyScan [KEYBOARD.129]
866 WORD WINAPI
VkKeyScan16(CHAR cChar
)
868 return VkKeyScan32A(cChar
);
871 /******************************************************************************
872 * VkKeyScanW [USER32.575]
874 WORD WINAPI
VkKeyScan32W(WCHAR cChar
)
876 return VkKeyScan32A((CHAR
)cChar
); /* FIXME: check unicode */
879 /******************************************************************************
880 * GetKeyboardType [KEYBOARD.130]
882 INT16 WINAPI
GetKeyboardType16(INT16 nTypeFlag
)
884 return GetKeyboardType32(nTypeFlag
);
887 /******************************************************************************
888 * GetKeyboardType [USER32.254]
890 INT32 WINAPI
GetKeyboardType32(INT32 nTypeFlag
)
892 TRACE(keyboard
,"(%d)\n",nTypeFlag
);
895 case 0: /* Keyboard type */
896 return 4; /* AT-101 */
898 case 1: /* Keyboard Subtype */
899 return 0; /* There are no defined subtypes */
901 case 2: /* Number of F-keys */
902 return 12; /* We're doing an 101 for now, so return 12 F-keys */
905 fprintf(stderr
, "Unknown type on GetKeyboardType\n");
906 return 0; /* The book says 0 here, so 0 */
911 /******************************************************************************
912 * MapVirtualKeyA [USER32.382]
914 UINT32 WINAPI
MapVirtualKey32A(UINT32 code
, UINT32 maptype
)
916 return MapVirtualKey16(code
,maptype
);
919 /******************************************************************************
920 * MapVirtualKeyA [USER32.384]
922 UINT32 WINAPI
MapVirtualKey32W(UINT32 code
, UINT32 maptype
)
924 return MapVirtualKey16(code
,maptype
);
927 /******************************************************************************
928 * MapVirtualKeyA [KEYBOARD.131]
929 * MapVirtualKey translates keycodes from one format to another
931 UINT16 WINAPI
MapVirtualKey16(UINT16 wCode
, UINT16 wMapType
)
933 #define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; }
935 TRACE(keyboard
,"MapVirtualKey wCode=0x%x wMapType=%d ... \n",
938 case 0: { /* vkey-code to scan-code */
939 /* let's do vkey -> keycode -> scan */
941 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++) /* see event.c */
942 if ((keyc2vkey
[keyc
] & 0xFF)== wCode
)
943 returnMVK (keyc
- 8);
946 case 1: /* scan-code to vkey-code */
947 /* let's do scan -> keycode -> vkey */
949 returnMVK (keyc2vkey
[(wCode
& 0xFF) + 8]);
951 case 2: { /* vkey-code to unshifted ANSI code */
952 /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */
953 /* My Windows returns 'A'. */
954 /* let's do vkey -> keycode -> (XLookupString) ansi char */
959 e
.state
= 0; /* unshifted */
960 e
.keycode
= MapVirtualKey16( wCode
, 0);
961 if (!TSXLookupString(&e
, s
, 2 , &keysym
, NULL
))
966 default: /* reserved */
967 fprintf(stderr
, "MapVirtualKey: unknown wMapType %d !\n",
975 /****************************************************************************
976 * GetKBCodePage16 (KEYBOARD.132)
978 INT16 WINAPI
GetKBCodePage16(void)
980 TRACE(keyboard
,"(void)\n");
985 /****************************************************************************
986 * GetKBCodePage32 (USER32.245)
988 UINT32 WINAPI
GetKBCodePage32(void)
990 TRACE(keyboard
,"(void)\n");
995 /****************************************************************************
996 * GetKeyNameText32W (USER32.247)
998 INT32 WINAPI
GetKeyNameText32W(LONG lParam
, LPWSTR lpBuffer
, INT32 nSize
)
1000 LPSTR buf
= HEAP_xalloc( GetProcessHeap(), 0, nSize
);
1001 int res
= GetKeyNameText32A(lParam
,buf
,nSize
);
1003 lstrcpynAtoW(lpBuffer
,buf
,nSize
);
1004 HeapFree( GetProcessHeap(), 0, buf
);
1008 /****************************************************************************
1009 * GetKeyNameText32A (USER32.246)
1011 INT32 WINAPI
GetKeyNameText32A(LONG lParam
, LPSTR lpBuffer
, INT32 nSize
)
1013 return GetKeyNameText16(lParam
,lpBuffer
,nSize
);
1016 /****************************************************************************
1017 * GetKeyNameText16 (KEYBOARD.133)
1019 INT16 WINAPI
GetKeyNameText16(LONG lParam
, LPSTR lpBuffer
, INT16 nSize
)
1023 TRACE(keyboard
,"(%ld,<ptr>,%d)\n",lParam
,nSize
);
1028 /* for (i = 0 ; i != KeyTableSize ; i++)
1029 if (KeyTable[i].scancode == lParam) {
1030 lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize );
1031 return strlen(lpBuffer);
1034 /* FIXME ! GetKeyNameText is still to do...
1041 /****************************************************************************
1042 * ToAscii (KEYBOARD.4)
1044 INT16 WINAPI
ToAscii16(UINT16 virtKey
,UINT16 scanCode
, LPBYTE lpKeyState
,
1045 LPVOID lpChar
, UINT16 flags
)
1047 return ToAscii32(virtKey
,scanCode
,lpKeyState
,lpChar
,flags
);
1050 /****************************************************************************
1051 * ToAscii (USER32.545)
1053 INT32 WINAPI
ToAscii32( UINT32 virtKey
,UINT32 scanCode
,LPBYTE lpKeyState
,
1054 LPWORD lpChar
,UINT32 flags
)
1058 static XComposeStatus cs
;
1062 e
.display
= display
;
1064 for (keyc
=min_keycode
; keyc
<=max_keycode
; keyc
++)
1065 { /* this could be speeded up by making another table, an array of struct vkey,keycode
1066 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)! DF */
1067 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... */
1069 if ((e
.keycode
) && ((virtKey
<0x10) || (virtKey
>0x12)))
1070 /* it's normal to have 2 shift, control, and alt ! */
1071 TRACE(keyboard
,"ToAscii : The keycodes %d and %d are matching the same vkey %#X\n",
1072 e
.keycode
,keyc
,virtKey
);
1076 if ((!e
.keycode
) && (lpKeyState
[VK_NUMLOCK
] & 0x01))
1078 if ((virtKey
>=VK_NUMPAD0
) && (virtKey
<=VK_NUMPAD9
))
1079 e
.keycode
= TSXKeysymToKeycode(e
.display
, virtKey
-VK_NUMPAD0
+XK_KP_0
);
1080 if (virtKey
==VK_DECIMAL
)
1081 e
.keycode
= TSXKeysymToKeycode(e
.display
, XK_KP_Decimal
);
1085 fprintf(stderr
,"ToAscii : Unknown virtual key %X !!! \n",virtKey
);
1086 return virtKey
; /* whatever */
1089 if (lpKeyState
[VK_SHIFT
] & 0x80)
1090 e
.state
|= ShiftMask
;
1091 TRACE(keyboard
,"ToAscii : lpKeyState[0x14(VK_CAPITAL)]=%#x\n",lpKeyState
[VK_CAPITAL
]);
1092 if (lpKeyState
[VK_CAPITAL
] & 0x01)
1093 e
.state
|= LockMask
;
1094 if (lpKeyState
[VK_CONTROL
] & 0x80)
1095 if (lpKeyState
[VK_MENU
] & 0x80)
1096 e
.state
|= AltGrMask
;
1098 e
.state
|= ControlMask
;
1099 if (lpKeyState
[VK_NUMLOCK
] & 0x01)
1100 e
.state
|= NumLockMask
;
1101 TRACE(key
, "(%04X, %04X) : faked state = %X\n",
1102 virtKey
, scanCode
, e
.state
);
1103 ret
= TSXLookupString(&e
, (LPVOID
)lpChar
, 2, &keysym
, &cs
);
1108 ((char*)lpChar
)[1] = '\0';
1111 /* symbolic ASCII is the same as defined in rfc1345 */
1112 #ifdef XK_dead_tilde
1113 case XK_dead_tilde
:
1115 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1116 dead_char
= '~'; /* '? */
1118 #ifdef XK_dead_acute
1119 case XK_dead_acute
:
1121 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1122 dead_char
= 0xb4; /* '' */
1124 #ifdef XK_dead_circumflex
1125 case XK_dead_circumflex
:
1127 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1128 dead_char
= '^'; /* '> */
1130 #ifdef XK_dead_grave
1131 case XK_dead_grave
:
1133 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1134 dead_char
= '`'; /* '! */
1136 #ifdef XK_dead_diaeresis
1137 case XK_dead_diaeresis
:
1139 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1140 dead_char
= 0xa8; /* ': */
1142 #ifdef XK_dead_cedilla
1143 case XK_dead_cedilla
:
1144 dead_char
= 0xb8; /* ', */
1147 #ifdef XK_dead_macron
1148 case XK_dead_macron
:
1149 dead_char
= '-'; /* 'm isn't defined on iso-8859-x */
1152 #ifdef XK_dead_breve
1153 case XK_dead_breve
:
1154 dead_char
= 0xa2; /* '( */
1157 #ifdef XK_dead_abovedot
1158 case XK_dead_abovedot
:
1159 dead_char
= 0xff; /* '. */
1162 #ifdef XK_dead_abovering
1163 case XK_dead_abovering
:
1164 dead_char
= '0'; /* '0 isn't defined on iso-8859-x */
1167 #ifdef XK_dead_doubleacute
1168 case XK_dead_doubleacute
:
1169 dead_char
= 0xbd; /* '" */
1172 #ifdef XK_dead_caron
1173 case XK_dead_caron
:
1174 dead_char
= 0xb7; /* '< */
1177 #ifdef XK_dead_ogonek
1178 case XK_dead_ogonek
:
1179 dead_char
= 0xb2; /* '; */
1182 /* FIXME: I don't know this three.
1186 case XK_dead_voiced_sound :
1189 case XK_dead_semivoiced_sound :
1196 *(char*)lpChar
= dead_char
;
1203 ksname
= TSXKeysymToString(keysym
);
1206 if ((keysym
>> 8) != 0xff)
1208 fprintf(stderr
, "Please report : no char for keysym %04lX (%s) :\n",
1210 fprintf(stderr
, " virtKey = %X, scanCode = %X, keycode = %X, state = %X\n",
1211 virtKey
, scanCode
, e
.keycode
, e
.state
);
1215 TRACE(key
, "ToAscii about to return %d with char %x\n",
1216 ret
, *(char*)lpChar
);
1221 /***********************************************************************
1222 * GetKeyboardLayout (USER32.249)
1224 HKL32 WINAPI
GetKeyboardLayout(DWORD dwLayout
)
1226 fprintf(stderr
,"GetKeyboardLayout(%ld),STUB!\n",dwLayout
);
1227 return (0xcafe<<16)|GetSystemDefaultLCID(); /* FIXME */
1230 /***********************************************************************
1231 * GetKeyboardLayoutList (USER32.250)
1234 INT32 WINAPI
GetKeyboardLayoutList(INT32 nBuff
,HKL32
*layouts
)
1236 fprintf(stderr
,"GetKeyboardLayoutList(%d,%p),STUB!\n",nBuff
,layouts
);
1238 layouts
[0] = GetKeyboardLayout(0);
1243 /***********************************************************************
1244 * RegisterHotKey (USER32.433)
1246 BOOL32 WINAPI
RegisterHotKey(HWND32 hwnd
,INT32 id
,UINT32 modifiers
,UINT32 vk
) {
1247 fprintf(stderr
,"RegisterHotKey(%08x,%d,%08x,%d), STUB!\n",
1248 hwnd
,id
,modifiers
,vk
1253 /***********************************************************************
1254 * UnregisterHotKey (USER32.565)
1256 BOOL32 WINAPI
UnregisterHotKey(HWND32 hwnd
,INT32 id
) {
1257 fprintf(stderr
,"UnregisterHotKey(%08x,%d),stub!\n",hwnd
,id
);