Use poll() on the client-side during server waits to implement
[wine.git] / windows / input.c
blob34063dcd29d2349d1391b3fce08d44ea9da1d376
1 /*
2 * USER Input processing
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
12 #include <stdlib.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <assert.h>
18 #include "windef.h"
19 #include "winnls.h"
20 #include "winbase.h"
21 #include "wingdi.h"
22 #include "winuser.h"
23 #include "wine/winbase16.h"
24 #include "wine/winuser16.h"
25 #include "wine/keyboard16.h"
26 #include "win.h"
27 #include "heap.h"
28 #include "input.h"
29 #include "keyboard.h"
30 #include "mouse.h"
31 #include "message.h"
32 #include "queue.h"
33 #include "debugtools.h"
34 #include "winerror.h"
36 DECLARE_DEBUG_CHANNEL(event);
37 DECLARE_DEBUG_CHANNEL(key);
38 DECLARE_DEBUG_CHANNEL(keyboard);
39 DECLARE_DEBUG_CHANNEL(win);
41 static BOOL InputEnabled = TRUE;
42 static BOOL SwappedButtons;
44 BOOL MouseButtonsStates[3];
45 BOOL AsyncMouseButtonsStates[3];
46 BYTE InputKeyStateTable[256];
47 BYTE QueueKeyStateTable[256];
48 BYTE AsyncKeyStateTable[256];
50 /* Storage for the USER-maintained mouse positions */
51 static DWORD PosX, PosY;
53 #define GET_KEYSTATE() \
54 ((MouseButtonsStates[SwappedButtons ? 2 : 0] ? MK_LBUTTON : 0) | \
55 (MouseButtonsStates[1] ? MK_RBUTTON : 0) | \
56 (MouseButtonsStates[SwappedButtons ? 0 : 2] ? MK_MBUTTON : 0) | \
57 (InputKeyStateTable[VK_SHIFT] & 0x80 ? MK_SHIFT : 0) | \
58 (InputKeyStateTable[VK_CONTROL] & 0x80 ? MK_CONTROL : 0))
60 typedef union
62 struct
64 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 } lp1;
73 unsigned long lp2;
74 } KEYLP;
76 /***********************************************************************
77 * keybd_event (USER32.@)
79 void WINAPI keybd_event( BYTE bVk, BYTE bScan,
80 DWORD dwFlags, DWORD dwExtraInfo )
82 DWORD time, extra;
83 WORD message;
84 KEYLP keylp;
85 keylp.lp2 = 0;
87 if (!InputEnabled) return;
90 * If we are called by the Wine keyboard driver, use the additional
91 * info pointed to by the dwExtraInfo argument.
92 * Otherwise, we need to determine that info ourselves (probably
93 * less accurate, but we can't help that ...).
95 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_KEYBDEVENT) )
96 && ((WINE_KEYBDEVENT *)dwExtraInfo)->magic == WINE_KEYBDEVENT_MAGIC )
98 WINE_KEYBDEVENT *wke = (WINE_KEYBDEVENT *)dwExtraInfo;
99 time = wke->time;
100 extra = 0;
102 else
104 time = GetTickCount();
105 extra = dwExtraInfo;
109 keylp.lp1.count = 1;
110 keylp.lp1.code = bScan;
111 keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
112 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
113 * don't remember where I read it - AK */
114 /* it's '1' under windows, when a dialog box appears
115 * and you press one of the underlined keys - DF*/
117 if ( dwFlags & KEYEVENTF_KEYUP )
119 BOOL sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
120 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
121 && !(dwFlags & KEYEVENTF_WINE_FORCEEXTENDED); /* for Alt from AltGr */
123 InputKeyStateTable[bVk] &= ~0x80;
124 keylp.lp1.previous = 1;
125 keylp.lp1.transition = 1;
126 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
128 else
130 keylp.lp1.previous = (InputKeyStateTable[bVk] & 0x80) != 0;
131 keylp.lp1.transition = 0;
133 if (!(InputKeyStateTable[bVk] & 0x80))
134 InputKeyStateTable[bVk] ^= 0x01;
135 InputKeyStateTable[bVk] |= 0x80;
137 message = (InputKeyStateTable[VK_MENU] & 0x80)
138 && !(InputKeyStateTable[VK_CONTROL] & 0x80)
139 ? WM_SYSKEYDOWN : WM_KEYDOWN;
142 if ( message == WM_SYSKEYDOWN || message == WM_SYSKEYUP )
143 keylp.lp1.context = (InputKeyStateTable[VK_MENU] & 0x80) != 0; /* 1 if alt */
146 TRACE_(key)(" wParam=%04X, lParam=%08lX\n", bVk, keylp.lp2 );
147 TRACE_(key)(" InputKeyState=%X\n", InputKeyStateTable[bVk] );
149 hardware_event( message, bVk, keylp.lp2, PosX, PosY, time, extra );
152 /***********************************************************************
153 * keybd_event (USER.289)
155 void WINAPI WIN16_keybd_event( CONTEXT86 *context )
157 DWORD dwFlags = 0;
159 if (AH_reg(context) & 0x80) dwFlags |= KEYEVENTF_KEYUP;
160 if (BH_reg(context) & 1 ) dwFlags |= KEYEVENTF_EXTENDEDKEY;
162 keybd_event( AL_reg(context), BL_reg(context),
163 dwFlags, MAKELONG(SI_reg(context), DI_reg(context)) );
166 /***********************************************************************
167 * mouse_event (USER32.@)
169 void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
170 DWORD cButtons, DWORD dwExtraInfo )
172 DWORD time, extra;
173 DWORD keyState;
175 if (!InputEnabled) return;
177 if ( dwFlags & MOUSEEVENTF_MOVE )
179 if ( dwFlags & MOUSEEVENTF_ABSOLUTE )
181 PosX = (dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
182 PosY = (dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
184 else
186 int width = GetSystemMetrics(SM_CXSCREEN);
187 int height = GetSystemMetrics(SM_CYSCREEN);
188 long posX = (long) PosX, posY = (long) PosY;
190 /* dx and dy can be negative numbers for relative movements */
191 posX += (long) dx;
192 posY += (long) dy;
194 /* Clip to the current screen size */
195 if (posX < 0) PosX = 0;
196 else if (posX >= width) PosX = width - 1;
197 else PosX = posX;
199 if (posY < 0) PosY = 0;
200 else if (posY >= height) PosY = height - 1;
201 else PosY = posY;
206 * If we are called by the Wine mouse driver, use the additional
207 * info pointed to by the dwExtraInfo argument.
208 * Otherwise, we need to determine that info ourselves (probably
209 * less accurate, but we can't help that ...).
211 if (dwExtraInfo && !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
212 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC )
214 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
215 time = wme->time;
216 extra = (DWORD)wme->hWnd;
217 keyState = wme->keyState;
219 if (keyState != GET_KEYSTATE()) {
220 /* We need to update the keystate with what X provides us */
221 MouseButtonsStates[SwappedButtons ? 2 : 0] = (keyState & MK_LBUTTON ? TRUE : FALSE);
222 MouseButtonsStates[SwappedButtons ? 0 : 2] = (keyState & MK_RBUTTON ? TRUE : FALSE);
223 MouseButtonsStates[1] = (keyState & MK_MBUTTON ? TRUE : FALSE);
224 InputKeyStateTable[VK_SHIFT] = (keyState & MK_SHIFT ? 0x80 : 0);
225 InputKeyStateTable[VK_CONTROL] = (keyState & MK_CONTROL ? 0x80 : 0);
228 else
230 time = GetTickCount();
231 extra = dwExtraInfo;
232 keyState = GET_KEYSTATE();
234 if ( dwFlags & MOUSEEVENTF_MOVE )
236 /* We have to actually move the cursor */
237 SetCursorPos( PosX, PosY );
242 if ( dwFlags & MOUSEEVENTF_MOVE )
244 hardware_event( WM_MOUSEMOVE,
245 keyState, 0L, PosX, PosY, time, extra );
247 if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN) )
249 MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE;
250 hardware_event( WM_LBUTTONDOWN,
251 keyState, 0L, PosX, PosY, time, extra );
253 if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP) )
255 MouseButtonsStates[0] = FALSE;
256 hardware_event( WM_LBUTTONUP,
257 keyState, 0L, PosX, PosY, time, extra );
259 if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN) )
261 MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE;
262 hardware_event( WM_RBUTTONDOWN,
263 keyState, 0L, PosX, PosY, time, extra );
265 if ( dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP) )
267 MouseButtonsStates[2] = FALSE;
268 hardware_event( WM_RBUTTONUP,
269 keyState, 0L, PosX, PosY, time, extra );
271 if ( dwFlags & MOUSEEVENTF_MIDDLEDOWN )
273 MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE;
274 hardware_event( WM_MBUTTONDOWN,
275 keyState, 0L, PosX, PosY, time, extra );
277 if ( dwFlags & MOUSEEVENTF_MIDDLEUP )
279 MouseButtonsStates[1] = FALSE;
280 hardware_event( WM_MBUTTONUP,
281 keyState, 0L, PosX, PosY, time, extra );
283 if ( dwFlags & MOUSEEVENTF_WHEEL )
285 hardware_event( WM_MOUSEWHEEL,
286 keyState, 0L, PosX, PosY, time, extra );
290 /***********************************************************************
291 * mouse_event (USER.299)
293 void WINAPI WIN16_mouse_event( CONTEXT86 *context )
295 mouse_event( AX_reg(context), BX_reg(context), CX_reg(context),
296 DX_reg(context), MAKELONG(SI_reg(context), DI_reg(context)) );
299 /***********************************************************************
300 * GetMouseEventProc (USER.337)
302 FARPROC16 WINAPI GetMouseEventProc16(void)
304 HMODULE16 hmodule = GetModuleHandle16("USER");
305 return GetProcAddress16( hmodule, "mouse_event" );
309 /**********************************************************************
310 * EnableHardwareInput (USER.331)
312 BOOL16 WINAPI EnableHardwareInput16(BOOL16 bEnable)
314 BOOL16 bOldState = InputEnabled;
315 FIXME_(event)("(%d) - stub\n", bEnable);
316 InputEnabled = bEnable;
317 return bOldState;
321 /***********************************************************************
322 * SwapMouseButton (USER.186)
324 BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
326 BOOL16 ret = SwappedButtons;
327 SwappedButtons = fSwap;
328 return ret;
332 /***********************************************************************
333 * SwapMouseButton (USER32.@)
335 BOOL WINAPI SwapMouseButton( BOOL fSwap )
337 BOOL ret = SwappedButtons;
338 SwappedButtons = fSwap;
339 return ret;
343 /***********************************************************************
344 * GetCursorPos (USER.17)
346 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
348 if (!pt) return 0;
349 pt->x = PosX;
350 pt->y = PosY;
351 return 1;
355 /***********************************************************************
356 * GetCursorPos (USER32.@)
358 BOOL WINAPI GetCursorPos( POINT *pt )
360 if (!pt) return 0;
361 pt->x = PosX;
362 pt->y = PosY;
363 return 1;
367 /**********************************************************************
368 * EVENT_Capture
370 * We need this to be able to generate double click messages
371 * when menu code captures mouse in the window without CS_DBLCLK style.
373 HWND EVENT_Capture(HWND hwnd, INT16 ht)
375 HWND capturePrev = 0, captureWnd = 0;
376 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
377 WND* wndPtr = 0;
378 INT16 captureHT = 0;
380 /* Get the messageQ for the current thread */
381 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
383 WARN_(win)("\tCurrent message queue not found. Exiting!\n" );
384 goto CLEANUP;
387 /* Get the current capture window from the perQ data of the current message Q */
388 capturePrev = PERQDATA_GetCaptureWnd( pCurMsgQ->pQData );
390 if (!hwnd)
392 captureWnd = 0L;
393 captureHT = 0;
395 else
397 wndPtr = WIN_FindWndPtr( hwnd );
398 if (wndPtr)
400 TRACE_(win)("(0x%04x)\n", hwnd );
401 captureWnd = hwnd;
402 captureHT = ht;
406 /* Update the perQ capture window and send messages */
407 if( capturePrev != captureWnd )
409 if (wndPtr)
411 /* Retrieve the message queue associated with this window */
412 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
413 if ( !pMsgQ )
415 WARN_(win)("\tMessage queue not found. Exiting!\n" );
416 goto CLEANUP;
419 /* Make sure that message queue for the window we are setting capture to
420 * shares the same perQ data as the current threads message queue.
422 if ( pCurMsgQ->pQData != pMsgQ->pQData )
423 goto CLEANUP;
426 PERQDATA_SetCaptureWnd( pCurMsgQ->pQData, captureWnd );
427 PERQDATA_SetCaptureInfo( pCurMsgQ->pQData, captureHT );
429 if( capturePrev )
431 WND* xwndPtr = WIN_FindWndPtr( capturePrev );
432 if( xwndPtr && (xwndPtr->flags & WIN_ISWIN32) )
433 SendMessageA( capturePrev, WM_CAPTURECHANGED, 0L, hwnd);
434 WIN_ReleaseWndPtr(xwndPtr);
438 CLEANUP:
439 /* Unlock the queues before returning */
440 if ( pMsgQ )
441 QUEUE_Unlock( pMsgQ );
442 if ( pCurMsgQ )
443 QUEUE_Unlock( pCurMsgQ );
445 WIN_ReleaseWndPtr(wndPtr);
446 return capturePrev;
450 /**********************************************************************
451 * SetCapture (USER.18)
453 HWND16 WINAPI SetCapture16( HWND16 hwnd )
455 return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
459 /**********************************************************************
460 * SetCapture (USER32.@)
462 HWND WINAPI SetCapture( HWND hwnd )
464 return EVENT_Capture( hwnd, HTCLIENT );
468 /**********************************************************************
469 * ReleaseCapture (USER.19) (USER32.@)
471 BOOL WINAPI ReleaseCapture(void)
473 return (EVENT_Capture( 0, 0 ) != 0);
477 /**********************************************************************
478 * GetCapture (USER.236)
480 HWND16 WINAPI GetCapture16(void)
482 return (HWND16)GetCapture();
485 /**********************************************************************
486 * GetCapture (USER32.@)
488 HWND WINAPI GetCapture(void)
490 MESSAGEQUEUE *pCurMsgQ = 0;
491 HWND hwndCapture = 0;
493 /* Get the messageQ for the current thread */
494 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
496 TRACE_(win)("GetCapture: Current message queue not found. Exiting!\n" );
497 return 0;
500 /* Get the current capture window from the perQ data of the current message Q */
501 hwndCapture = PERQDATA_GetCaptureWnd( pCurMsgQ->pQData );
503 QUEUE_Unlock( pCurMsgQ );
504 return hwndCapture;
507 /**********************************************************************
508 * GetKeyState (USER.106)
510 INT16 WINAPI GetKeyState16(INT16 vkey)
512 return GetKeyState(vkey);
515 /**********************************************************************
516 * GetKeyState (USER32.@)
518 * An application calls the GetKeyState function in response to a
519 * keyboard-input message. This function retrieves the state of the key
520 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
522 SHORT WINAPI GetKeyState(INT vkey)
524 INT retval;
526 switch (vkey)
528 case VK_LBUTTON : /* VK_LBUTTON is 1 */
529 retval = MouseButtonsStates[0] ? 0x8000 : 0;
530 break;
531 case VK_MBUTTON : /* VK_MBUTTON is 4 */
532 retval = MouseButtonsStates[1] ? 0x8000 : 0;
533 break;
534 case VK_RBUTTON : /* VK_RBUTTON is 2 */
535 retval = MouseButtonsStates[2] ? 0x8000 : 0;
536 break;
537 default :
538 if (vkey >= 'a' && vkey <= 'z')
539 vkey += 'A' - 'a';
540 retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
541 (WORD)(QueueKeyStateTable[vkey] & 0x01);
543 /* TRACE(key, "(0x%x) -> %x\n", vkey, retval); */
544 return retval;
547 /**********************************************************************
548 * GetKeyboardState (USER.222) (USER32.@)
550 * An application calls the GetKeyboardState function in response to a
551 * keyboard-input message. This function retrieves the state of the keyboard
552 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
554 BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState)
556 TRACE_(key)("(%p)\n", lpKeyState);
557 if (lpKeyState != NULL) {
558 QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
559 QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
560 QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
561 memcpy(lpKeyState, QueueKeyStateTable, 256);
564 return TRUE;
567 /**********************************************************************
568 * SetKeyboardState (USER.223) (USER32.@)
570 BOOL WINAPI SetKeyboardState(LPBYTE lpKeyState)
572 TRACE_(key)("(%p)\n", lpKeyState);
573 if (lpKeyState != NULL) {
574 memcpy(QueueKeyStateTable, lpKeyState, 256);
575 MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
576 MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
577 MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
580 return TRUE;
583 /**********************************************************************
584 * GetAsyncKeyState (USER32.@)
586 * Determine if a key is or was pressed. retval has high-order
587 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
588 * been pressed.
590 * This uses the variable AsyncMouseButtonsStates and
591 * AsyncKeyStateTable (set in event.c) which have the mouse button
592 * number or key number (whichever is applicable) set to true if the
593 * mouse or key had been depressed since the last call to
594 * GetAsyncKeyState.
596 WORD WINAPI GetAsyncKeyState(INT nKey)
598 short retval;
600 switch (nKey) {
601 case VK_LBUTTON:
602 retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
603 (MouseButtonsStates[0] ? 0x8000 : 0);
604 break;
605 case VK_MBUTTON:
606 retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
607 (MouseButtonsStates[1] ? 0x8000 : 0);
608 break;
609 case VK_RBUTTON:
610 retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
611 (MouseButtonsStates[2] ? 0x8000 : 0);
612 break;
613 default:
614 retval = AsyncKeyStateTable[nKey] |
615 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
616 break;
619 /* all states to false */
620 memset( AsyncMouseButtonsStates, 0, sizeof(AsyncMouseButtonsStates) );
621 memset( AsyncKeyStateTable, 0, sizeof(AsyncKeyStateTable) );
623 TRACE_(key)("(%x) -> %x\n", nKey, retval);
624 return retval;
627 /**********************************************************************
628 * GetAsyncKeyState (USER.249)
630 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
632 return GetAsyncKeyState(nKey);
635 /***********************************************************************
636 * IsUserIdle (USER.333)
638 BOOL16 WINAPI IsUserIdle16(void)
640 if ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 )
641 return FALSE;
643 if ( GetAsyncKeyState( VK_RBUTTON ) & 0x8000 )
644 return FALSE;
646 if ( GetAsyncKeyState( VK_MBUTTON ) & 0x8000 )
647 return FALSE;
649 /* Should check for screen saver activation here ... */
651 return TRUE;
654 /**********************************************************************
655 * VkKeyScanA (USER32.@)
657 WORD WINAPI VkKeyScanA(CHAR cChar)
659 return VkKeyScan16(cChar);
662 /******************************************************************************
663 * VkKeyScanW (USER32.@)
665 WORD WINAPI VkKeyScanW(WCHAR cChar)
667 return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
670 /**********************************************************************
671 * VkKeyScanExA (USER32.@)
673 WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
675 /* FIXME: complete workaround this is */
676 return VkKeyScan16(cChar);
679 /******************************************************************************
680 * VkKeyScanExW (USER32.@)
682 WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl)
684 /* FIXME: complete workaround this is */
685 return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
688 /******************************************************************************
689 * GetKeyboardType (USER32.@)
691 INT WINAPI GetKeyboardType(INT nTypeFlag)
693 return GetKeyboardType16(nTypeFlag);
696 /******************************************************************************
697 * MapVirtualKeyA (USER32.@)
699 UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
701 return MapVirtualKey16(code,maptype);
704 /******************************************************************************
705 * MapVirtualKeyW (USER32.@)
707 UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
709 return MapVirtualKey16(code,maptype);
712 /******************************************************************************
713 * MapVirtualKeyExA (USER32.@)
715 UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
717 if (hkl)
718 FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
719 return MapVirtualKey16(code,maptype);
722 /******************************************************************************
723 * MapVirtualKeyExW (USER32.@)
725 UINT WINAPI MapVirtualKeyExW(UINT code, UINT maptype, HKL hkl)
727 if (hkl)
728 FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
729 return MapVirtualKey16(code,maptype);
732 /****************************************************************************
733 * GetKBCodePage (USER32.@)
735 UINT WINAPI GetKBCodePage(void)
737 return GetOEMCP();
740 /****************************************************************************
741 * GetKeyboardLayoutName (USER.477)
743 INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID)
745 return GetKeyboardLayoutNameA(pwszKLID);
748 /***********************************************************************
749 * GetKeyboardLayout (USER32.@)
751 * FIXME: - device handle for keyboard layout defaulted to
752 * the language id. This is the way Windows default works.
753 * - the thread identifier (dwLayout) is also ignored.
755 HKL WINAPI GetKeyboardLayout(DWORD dwLayout)
757 HKL layout;
758 layout = GetSystemDefaultLCID(); /* FIXME */
759 layout |= (layout<<16); /* FIXME */
760 TRACE_(keyboard)("returning %08x\n",layout);
761 return layout;
764 /****************************************************************************
765 * GetKeyboardLayoutNameA (USER32.@)
767 INT WINAPI GetKeyboardLayoutNameA(LPSTR pwszKLID)
769 sprintf(pwszKLID, "%08x",GetKeyboardLayout(0));
770 return 1;
773 /****************************************************************************
774 * GetKeyboardLayoutNameW (USER32.@)
776 INT WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
778 char buf[KL_NAMELENGTH];
779 int res = GetKeyboardLayoutNameA(buf);
780 MultiByteToWideChar( CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH );
781 return res;
784 /****************************************************************************
785 * GetKeyNameTextA (USER32.@)
787 INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
789 return GetKeyNameText16(lParam,lpBuffer,nSize);
792 /****************************************************************************
793 * GetKeyNameTextW (USER32.@)
795 INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize)
797 int res;
798 LPSTR buf = HeapAlloc( GetProcessHeap(), 0, nSize );
799 if(buf == NULL) return 0; /* FIXME: is this the correct failure value?*/
800 res = GetKeyNameTextA(lParam,buf,nSize);
802 if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, buf, -1, lpBuffer, nSize ))
803 lpBuffer[nSize-1] = 0;
804 HeapFree( GetProcessHeap(), 0, buf );
805 return res;
808 /****************************************************************************
809 * ToUnicode (USER32.@)
811 INT WINAPI ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
812 LPWSTR lpwStr, int size, UINT flags)
814 return USER_Driver.pToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
817 /****************************************************************************
818 * ToUnicodeEx (USER32.@)
820 INT WINAPI ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
821 LPWSTR lpwStr, int size, UINT flags, HKL hkl)
823 /* FIXME: need true implementation */
824 return ToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
827 /****************************************************************************
828 * ToAscii (USER32.@)
830 INT WINAPI ToAscii( UINT virtKey,UINT scanCode,LPBYTE lpKeyState,
831 LPWORD lpChar,UINT flags )
833 WCHAR uni_chars[2];
834 INT ret, n_ret;
836 ret = ToUnicode(virtKey, scanCode, lpKeyState, uni_chars, 2, flags);
837 if(ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
838 else n_ret = ret;
839 WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
840 return ret;
843 /****************************************************************************
844 * ToAsciiEx (USER32.@)
846 INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
847 LPWORD lpChar, UINT flags, HKL dwhkl )
849 /* FIXME: need true implementation */
850 return ToAscii(virtKey, scanCode, lpKeyState, lpChar, flags);
853 /**********************************************************************
854 * ActivateKeyboardLayout (USER32.@)
856 * Call ignored. WINE supports only system default keyboard layout.
858 HKL WINAPI ActivateKeyboardLayout(HKL hLayout, UINT flags)
860 TRACE_(keyboard)("(%d, %d)\n", hLayout, flags);
861 ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
862 return 0;
866 /***********************************************************************
867 * GetKeyboardLayoutList (USER32.@)
869 * FIXME: Supports only the system default language and layout and
870 * returns only 1 value.
872 * Return number of values available if either input parm is
873 * 0, per MS documentation.
876 INT WINAPI GetKeyboardLayoutList(INT nBuff,HKL *layouts)
878 TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
879 if (!nBuff || !layouts)
880 return 1;
881 if (layouts)
882 layouts[0] = GetKeyboardLayout(0);
883 return 1;
887 /***********************************************************************
888 * RegisterHotKey (USER32.@)
890 BOOL WINAPI RegisterHotKey(HWND hwnd,INT id,UINT modifiers,UINT vk) {
891 FIXME_(keyboard)("(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk);
892 return TRUE;
895 /***********************************************************************
896 * UnregisterHotKey (USER32.@)
898 BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) {
899 FIXME_(keyboard)("(0x%08x,%d): stub\n",hwnd,id);
900 return TRUE;
903 /***********************************************************************
904 * LoadKeyboardLayoutA (USER32.@)
905 * Call ignored. WINE supports only system default keyboard layout.
907 HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags)
909 TRACE_(keyboard)("(%s, %d)\n", pwszKLID, Flags);
910 ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
911 return 0;
914 /***********************************************************************
915 * LoadKeyboardLayoutW (USER32.@)
917 HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags)
919 char buf[9];
921 WideCharToMultiByte( CP_ACP, 0, pwszKLID, -1, buf, sizeof(buf), NULL, NULL );
922 buf[8] = 0;
923 return LoadKeyboardLayoutA(buf, Flags);