Avoid list corruption when linking window with HWND_BOTTOM (thanks to
[wine/multimedia.git] / windows / input.c
blob7d69b5cb7dfcd9895bdd34243c35ff10ae9c354c
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 "wine/server.h"
27 #include "win.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(key);
37 DECLARE_DEBUG_CHANNEL(keyboard);
38 DECLARE_DEBUG_CHANNEL(win);
39 DEFAULT_DEBUG_CHANNEL(event);
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;
77 /***********************************************************************
78 * queue_raw_hardware_message
80 * Add a message to the raw hardware queue.
81 * Note: the position is relative to the desktop window.
83 static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lParam,
84 int xPos, int yPos, DWORD time, DWORD extraInfo )
86 SERVER_START_REQ( send_message )
88 req->id = (void *)GetCurrentThreadId();
89 req->type = MSG_HARDWARE_RAW;
90 req->win = 0;
91 req->msg = message;
92 req->wparam = wParam;
93 req->lparam = lParam;
94 req->x = xPos;
95 req->y = yPos;
96 req->time = time;
97 req->info = extraInfo;
98 req->timeout = 0;
99 SERVER_CALL();
101 SERVER_END_REQ;
105 /***********************************************************************
106 * queue_kbd_event
108 * Put a keyboard event into a thread queue
110 static void queue_kbd_event( const KEYBDINPUT *ki )
112 UINT message;
113 KEYLP keylp;
115 keylp.lp2 = 0;
116 keylp.lp1.count = 1;
117 keylp.lp1.code = ki->wScan;
118 keylp.lp1.extended = (ki->dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
119 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
120 * don't remember where I read it - AK */
121 /* it's '1' under windows, when a dialog box appears
122 * and you press one of the underlined keys - DF*/
124 if (ki->dwFlags & KEYEVENTF_KEYUP )
126 BOOL sysKey = ((InputKeyStateTable[VK_MENU] & 0x80) &&
127 !(InputKeyStateTable[VK_CONTROL] & 0x80) &&
128 !(ki->dwFlags & KEYEVENTF_WINE_FORCEEXTENDED)); /* for Alt from AltGr */
129 InputKeyStateTable[ki->wVk] &= ~0x80;
130 keylp.lp1.previous = 1;
131 keylp.lp1.transition = 1;
132 message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
134 else
136 keylp.lp1.previous = (InputKeyStateTable[ki->wVk] & 0x80) != 0;
137 keylp.lp1.transition = 0;
138 if (!(InputKeyStateTable[ki->wVk] & 0x80)) InputKeyStateTable[ki->wVk] ^= 0x01;
139 InputKeyStateTable[ki->wVk] |= 0x80;
140 AsyncKeyStateTable[ki->wVk] |= 0x80;
142 message = (InputKeyStateTable[VK_MENU] & 0x80) && !(InputKeyStateTable[VK_CONTROL] & 0x80)
143 ? WM_SYSKEYDOWN : WM_KEYDOWN;
146 if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP )
147 keylp.lp1.context = (InputKeyStateTable[VK_MENU] & 0x80) != 0; /* 1 if alt */
149 TRACE_(key)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
150 ki->wVk, keylp.lp2, InputKeyStateTable[ki->wVk] );
152 queue_raw_hardware_message( message, ki->wVk, keylp.lp2,
153 PosX, PosY, ki->time, ki->dwExtraInfo );
157 /***********************************************************************
158 * queue_mouse_event
160 static void queue_mouse_event( const MOUSEINPUT *mi, WORD keystate )
162 if (mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
164 PosX = (mi->dx * GetSystemMetrics(SM_CXSCREEN)) >> 16;
165 PosY = (mi->dy * GetSystemMetrics(SM_CYSCREEN)) >> 16;
167 else if (mi->dwFlags & MOUSEEVENTF_MOVE)
169 int width = GetSystemMetrics(SM_CXSCREEN);
170 int height = GetSystemMetrics(SM_CYSCREEN);
171 long posX = (long) PosX, posY = (long) PosY;
173 /* dx and dy can be negative numbers for relative movements */
174 posX += (long)mi->dx;
175 posY += (long)mi->dy;
177 /* Clip to the current screen size */
178 if (posX < 0) PosX = 0;
179 else if (posX >= width) PosX = width - 1;
180 else PosX = posX;
182 if (posY < 0) PosY = 0;
183 else if (posY >= height) PosY = height - 1;
184 else PosY = posY;
187 if (mi->dwFlags & MOUSEEVENTF_MOVE)
189 queue_raw_hardware_message( WM_MOUSEMOVE, keystate, 0, PosX, PosY,
190 mi->time, mi->dwExtraInfo );
192 if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN))
194 MouseButtonsStates[0] = AsyncMouseButtonsStates[0] = TRUE;
195 queue_raw_hardware_message( WM_LBUTTONDOWN, keystate, 0, PosX, PosY,
196 mi->time, mi->dwExtraInfo );
198 if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP))
200 MouseButtonsStates[0] = FALSE;
201 queue_raw_hardware_message( WM_LBUTTONUP, keystate, 0, PosX, PosY,
202 mi->time, mi->dwExtraInfo );
204 if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN))
206 MouseButtonsStates[2] = AsyncMouseButtonsStates[2] = TRUE;
207 queue_raw_hardware_message( WM_RBUTTONDOWN, keystate, 0, PosX, PosY,
208 mi->time, mi->dwExtraInfo );
210 if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP))
212 MouseButtonsStates[2] = FALSE;
213 queue_raw_hardware_message( WM_RBUTTONUP, keystate, 0, PosX, PosY,
214 mi->time, mi->dwExtraInfo );
216 if (mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
218 MouseButtonsStates[1] = AsyncMouseButtonsStates[1] = TRUE;
219 queue_raw_hardware_message( WM_MBUTTONDOWN, keystate, 0, PosX, PosY,
220 mi->time, mi->dwExtraInfo );
222 if (mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
224 MouseButtonsStates[1] = FALSE;
225 queue_raw_hardware_message( WM_MBUTTONUP, keystate, 0, PosX, PosY,
226 mi->time, mi->dwExtraInfo );
228 if (mi->dwFlags & MOUSEEVENTF_WHEEL)
230 queue_raw_hardware_message( WM_MOUSEWHEEL, MAKELONG( keystate, mi->mouseData), 0,
231 PosX, PosY, mi->time, mi->dwExtraInfo );
236 /***********************************************************************
237 * SendInput (USER32.@)
239 UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
241 UINT i;
243 if (!InputEnabled) return 0;
245 for (i = 0; i < count; i++, inputs++)
247 switch(inputs->type)
249 case INPUT_MOUSE:
250 queue_mouse_event( &inputs->u.mi, GET_KEYSTATE() );
251 break;
252 case INPUT_KEYBOARD:
253 queue_kbd_event( &inputs->u.ki );
254 break;
255 case INPUT_HARDWARE:
256 FIXME( "INPUT_HARDWARE not supported\n" );
257 break;
260 return count;
264 /***********************************************************************
265 * keybd_event (USER32.@)
267 void WINAPI keybd_event( BYTE bVk, BYTE bScan,
268 DWORD dwFlags, DWORD dwExtraInfo )
270 INPUT input;
273 * If we are called by the Wine keyboard driver, use the additional
274 * info pointed to by the dwExtraInfo argument.
275 * Otherwise, we need to determine that info ourselves (probably
276 * less accurate, but we can't help that ...).
278 if ( !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_KEYBDEVENT) )
279 && ((WINE_KEYBDEVENT *)dwExtraInfo)->magic == WINE_KEYBDEVENT_MAGIC )
281 WINE_KEYBDEVENT *wke = (WINE_KEYBDEVENT *)dwExtraInfo;
282 input.u.ki.time = wke->time;
283 input.u.ki.dwExtraInfo = 0;
285 else
287 input.u.ki.time = GetTickCount();
288 input.u.ki.dwExtraInfo = dwExtraInfo;
290 input.type = INPUT_KEYBOARD;
291 input.u.ki.wVk = bVk;
292 input.u.ki.wScan = bScan;
293 input.u.ki.dwFlags = dwFlags;
294 SendInput( 1, &input, sizeof(input) );
298 /***********************************************************************
299 * keybd_event (USER.289)
301 void WINAPI keybd_event16( CONTEXT86 *context )
303 DWORD dwFlags = 0;
305 if (AH_reg(context) & 0x80) dwFlags |= KEYEVENTF_KEYUP;
306 if (BH_reg(context) & 1 ) dwFlags |= KEYEVENTF_EXTENDEDKEY;
308 keybd_event( AL_reg(context), BL_reg(context),
309 dwFlags, MAKELONG(SI_reg(context), DI_reg(context)) );
313 /***********************************************************************
314 * mouse_event (USER32.@)
316 void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
317 DWORD dwData, DWORD dwExtraInfo )
319 INPUT input;
320 WORD keyState;
322 input.type = INPUT_MOUSE;
323 input.u.mi.dx = dx;
324 input.u.mi.dy = dy;
325 input.u.mi.mouseData = dwData;
326 input.u.mi.dwFlags = dwFlags;
329 * If we are called by the Wine mouse driver, use the additional
330 * info pointed to by the dwExtraInfo argument.
331 * Otherwise, we need to determine that info ourselves (probably
332 * less accurate, but we can't help that ...).
334 if (dwExtraInfo && !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
335 && ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC )
337 WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
339 keyState = wme->keyState;
341 if (keyState != GET_KEYSTATE())
343 /* We need to update the keystate with what X provides us */
344 MouseButtonsStates[SwappedButtons ? 2 : 0] = (keyState & MK_LBUTTON ? TRUE : FALSE);
345 MouseButtonsStates[SwappedButtons ? 0 : 2] = (keyState & MK_RBUTTON ? TRUE : FALSE);
346 MouseButtonsStates[1] = (keyState & MK_MBUTTON ? TRUE : FALSE);
347 InputKeyStateTable[VK_SHIFT] = (keyState & MK_SHIFT ? 0x80 : 0);
348 InputKeyStateTable[VK_CONTROL] = (keyState & MK_CONTROL ? 0x80 : 0);
350 input.u.mi.time = wme->time;
351 input.u.mi.dwExtraInfo = (ULONG_PTR)wme->hWnd;
352 queue_mouse_event( &input.u.mi, keyState );
354 else
356 if ( dwFlags & MOUSEEVENTF_MOVE ) /* we have to actually move the cursor */
357 SetCursorPos( PosX, PosY );
359 input.u.mi.time = GetCurrentTime();
360 input.u.mi.dwExtraInfo = dwExtraInfo;
361 SendInput( 1, &input, sizeof(input) );
366 /***********************************************************************
367 * mouse_event (USER.299)
369 void WINAPI mouse_event16( CONTEXT86 *context )
371 mouse_event( AX_reg(context), BX_reg(context), CX_reg(context),
372 DX_reg(context), MAKELONG(SI_reg(context), DI_reg(context)) );
375 /***********************************************************************
376 * GetMouseEventProc (USER.337)
378 FARPROC16 WINAPI GetMouseEventProc16(void)
380 HMODULE16 hmodule = GetModuleHandle16("USER");
381 return GetProcAddress16( hmodule, "mouse_event" );
385 /**********************************************************************
386 * EnableHardwareInput (USER.331)
388 BOOL16 WINAPI EnableHardwareInput16(BOOL16 bEnable)
390 BOOL16 bOldState = InputEnabled;
391 FIXME_(event)("(%d) - stub\n", bEnable);
392 InputEnabled = bEnable;
393 return bOldState;
397 /***********************************************************************
398 * SwapMouseButton (USER.186)
400 BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
402 BOOL16 ret = SwappedButtons;
403 SwappedButtons = fSwap;
404 return ret;
408 /***********************************************************************
409 * SwapMouseButton (USER32.@)
411 BOOL WINAPI SwapMouseButton( BOOL fSwap )
413 BOOL ret = SwappedButtons;
414 SwappedButtons = fSwap;
415 return ret;
419 /***********************************************************************
420 * GetCursorPos (USER.17)
422 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
424 POINT pos;
425 if (!pt) return 0;
426 GetCursorPos(&pos);
427 pt->x = pos.x;
428 pt->y = pos.y;
429 return 1;
433 /***********************************************************************
434 * GetCursorPos (USER32.@)
436 BOOL WINAPI GetCursorPos( POINT *pt )
438 if (!pt) return 0;
439 pt->x = PosX;
440 pt->y = PosY;
441 if (USER_Driver.pGetCursorPos) USER_Driver.pGetCursorPos( pt );
442 return 1;
446 /***********************************************************************
447 * SetCursorPos (USER.70)
449 void WINAPI SetCursorPos16( INT16 x, INT16 y )
451 SetCursorPos( x, y );
455 /***********************************************************************
456 * SetCursorPos (USER32.@)
458 BOOL WINAPI SetCursorPos( INT x, INT y )
460 if (USER_Driver.pSetCursorPos) USER_Driver.pSetCursorPos( x, y );
461 PosX = x;
462 PosY = y;
463 return TRUE;
467 /**********************************************************************
468 * EVENT_Capture
470 * We need this to be able to generate double click messages
471 * when menu code captures mouse in the window without CS_DBLCLK style.
473 HWND EVENT_Capture(HWND hwnd, INT16 ht)
475 HWND capturePrev = 0, captureWnd = 0;
476 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
477 WND* wndPtr = 0;
478 INT16 captureHT = 0;
480 capturePrev = GetCapture();
482 if (!hwnd)
484 captureWnd = 0;
485 captureHT = 0;
487 else
489 wndPtr = WIN_FindWndPtr( hwnd );
490 if (wndPtr)
492 TRACE_(win)("(0x%04x)\n", hwnd );
493 captureWnd = wndPtr->hwndSelf;
494 captureHT = ht;
498 /* Get the messageQ for the current thread */
499 if (!(pCurMsgQ = QUEUE_Current()))
501 WARN_(win)("\tCurrent message queue not found. Exiting!\n" );
502 goto CLEANUP;
505 /* Update the perQ capture window and send messages */
506 if( capturePrev != captureWnd )
508 if (wndPtr)
510 /* Retrieve the message queue associated with this window */
511 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
512 if ( !pMsgQ )
514 WARN_(win)("\tMessage queue not found. Exiting!\n" );
515 goto CLEANUP;
518 /* Make sure that message queue for the window we are setting capture to
519 * shares the same perQ data as the current threads message queue.
521 if ( pCurMsgQ->pQData != pMsgQ->pQData )
522 goto CLEANUP;
525 PERQDATA_SetCaptureWnd( captureWnd, captureHT );
526 if (capturePrev) SendMessageA( capturePrev, WM_CAPTURECHANGED, 0, (LPARAM)hwnd );
529 CLEANUP:
530 /* Unlock the queues before returning */
531 if ( pMsgQ )
532 QUEUE_Unlock( pMsgQ );
534 WIN_ReleaseWndPtr(wndPtr);
535 return capturePrev;
539 /**********************************************************************
540 * SetCapture (USER32.@)
542 HWND WINAPI SetCapture( HWND hwnd )
544 return EVENT_Capture( hwnd, HTCLIENT );
548 /**********************************************************************
549 * ReleaseCapture (USER32.@)
551 BOOL WINAPI ReleaseCapture(void)
553 return (EVENT_Capture( 0, 0 ) != 0);
557 /**********************************************************************
558 * GetCapture (USER32.@)
560 HWND WINAPI GetCapture(void)
562 INT hittest;
563 return PERQDATA_GetCaptureWnd( &hittest );
566 /**********************************************************************
567 * GetKeyState (USER.106)
569 INT16 WINAPI GetKeyState16(INT16 vkey)
571 return GetKeyState(vkey);
574 /**********************************************************************
575 * GetKeyState (USER32.@)
577 * An application calls the GetKeyState function in response to a
578 * keyboard-input message. This function retrieves the state of the key
579 * at the time the input message was generated. (SDK 3.1 Vol 2. p 390)
581 SHORT WINAPI GetKeyState(INT vkey)
583 INT retval;
585 switch (vkey)
587 case VK_LBUTTON : /* VK_LBUTTON is 1 */
588 retval = MouseButtonsStates[0] ? 0x8000 : 0;
589 break;
590 case VK_MBUTTON : /* VK_MBUTTON is 4 */
591 retval = MouseButtonsStates[1] ? 0x8000 : 0;
592 break;
593 case VK_RBUTTON : /* VK_RBUTTON is 2 */
594 retval = MouseButtonsStates[2] ? 0x8000 : 0;
595 break;
596 default :
597 if (vkey >= 'a' && vkey <= 'z')
598 vkey += 'A' - 'a';
599 retval = ( (WORD)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
600 (WORD)(QueueKeyStateTable[vkey] & 0x01);
602 /* TRACE(key, "(0x%x) -> %x\n", vkey, retval); */
603 return retval;
606 /**********************************************************************
607 * GetKeyboardState (USER.222)
608 * GetKeyboardState (USER32.@)
610 * An application calls the GetKeyboardState function in response to a
611 * keyboard-input message. This function retrieves the state of the keyboard
612 * at the time the input message was generated. (SDK 3.1 Vol 2. p 387)
614 BOOL WINAPI GetKeyboardState(LPBYTE lpKeyState)
616 TRACE_(key)("(%p)\n", lpKeyState);
617 if (lpKeyState != NULL) {
618 QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] ? 0x80 : 0;
619 QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] ? 0x80 : 0;
620 QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] ? 0x80 : 0;
621 memcpy(lpKeyState, QueueKeyStateTable, 256);
624 return TRUE;
627 /**********************************************************************
628 * SetKeyboardState (USER.223)
629 * SetKeyboardState (USER32.@)
631 BOOL WINAPI SetKeyboardState(LPBYTE lpKeyState)
633 TRACE_(key)("(%p)\n", lpKeyState);
634 if (lpKeyState != NULL) {
635 memcpy(QueueKeyStateTable, lpKeyState, 256);
636 MouseButtonsStates[0] = (QueueKeyStateTable[VK_LBUTTON] != 0);
637 MouseButtonsStates[1] = (QueueKeyStateTable[VK_MBUTTON] != 0);
638 MouseButtonsStates[2] = (QueueKeyStateTable[VK_RBUTTON] != 0);
641 return TRUE;
644 /**********************************************************************
645 * GetAsyncKeyState (USER32.@)
647 * Determine if a key is or was pressed. retval has high-order
648 * bit set to 1 if currently pressed, low-order bit set to 1 if key has
649 * been pressed.
651 * This uses the variable AsyncMouseButtonsStates and
652 * AsyncKeyStateTable (set in event.c) which have the mouse button
653 * number or key number (whichever is applicable) set to true if the
654 * mouse or key had been depressed since the last call to
655 * GetAsyncKeyState.
657 WORD WINAPI GetAsyncKeyState(INT nKey)
659 WORD retval;
661 switch (nKey) {
662 case VK_LBUTTON:
663 retval = (AsyncMouseButtonsStates[0] ? 0x0001 : 0) |
664 (MouseButtonsStates[0] ? 0x8000 : 0);
665 AsyncMouseButtonsStates[0] = 0;
666 break;
667 case VK_MBUTTON:
668 retval = (AsyncMouseButtonsStates[1] ? 0x0001 : 0) |
669 (MouseButtonsStates[1] ? 0x8000 : 0);
670 AsyncMouseButtonsStates[1] = 0;
671 break;
672 case VK_RBUTTON:
673 retval = (AsyncMouseButtonsStates[2] ? 0x0001 : 0) |
674 (MouseButtonsStates[2] ? 0x8000 : 0);
675 AsyncMouseButtonsStates[2] = 0;
676 break;
677 default:
678 retval = ((AsyncKeyStateTable[nKey] & 0x80) ? 0x0001 : 0) |
679 ((InputKeyStateTable[nKey] & 0x80) ? 0x8000 : 0);
680 AsyncKeyStateTable[nKey] = 0;
681 break;
684 TRACE_(key)("(%x) -> %x\n", nKey, retval);
685 return retval;
688 /**********************************************************************
689 * GetAsyncKeyState (USER.249)
691 WORD WINAPI GetAsyncKeyState16(INT16 nKey)
693 return GetAsyncKeyState(nKey);
696 /***********************************************************************
697 * IsUserIdle (USER.333)
699 BOOL16 WINAPI IsUserIdle16(void)
701 if ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 )
702 return FALSE;
704 if ( GetAsyncKeyState( VK_RBUTTON ) & 0x8000 )
705 return FALSE;
707 if ( GetAsyncKeyState( VK_MBUTTON ) & 0x8000 )
708 return FALSE;
710 /* Should check for screen saver activation here ... */
712 return TRUE;
715 /**********************************************************************
716 * VkKeyScanA (USER32.@)
718 WORD WINAPI VkKeyScanA(CHAR cChar)
720 return VkKeyScan16(cChar);
723 /******************************************************************************
724 * VkKeyScanW (USER32.@)
726 WORD WINAPI VkKeyScanW(WCHAR cChar)
728 return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
731 /**********************************************************************
732 * VkKeyScanExA (USER32.@)
734 WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
736 /* FIXME: complete workaround this is */
737 return VkKeyScan16(cChar);
740 /******************************************************************************
741 * VkKeyScanExW (USER32.@)
743 WORD WINAPI VkKeyScanExW(WCHAR cChar, HKL dwhkl)
745 /* FIXME: complete workaround this is */
746 return VkKeyScanA((CHAR)cChar); /* FIXME: check unicode */
749 /******************************************************************************
750 * GetKeyboardType (USER32.@)
752 INT WINAPI GetKeyboardType(INT nTypeFlag)
754 return GetKeyboardType16(nTypeFlag);
757 /******************************************************************************
758 * MapVirtualKeyA (USER32.@)
760 UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
762 return MapVirtualKey16(code,maptype);
765 /******************************************************************************
766 * MapVirtualKeyW (USER32.@)
768 UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
770 return MapVirtualKey16(code,maptype);
773 /******************************************************************************
774 * MapVirtualKeyExA (USER32.@)
776 UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
778 if (hkl)
779 FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
780 return MapVirtualKey16(code,maptype);
783 /******************************************************************************
784 * MapVirtualKeyExW (USER32.@)
786 UINT WINAPI MapVirtualKeyExW(UINT code, UINT maptype, HKL hkl)
788 if (hkl)
789 FIXME_(keyboard)("(%d,%d,0x%08lx), hkl unhandled!\n",code,maptype,(DWORD)hkl);
790 return MapVirtualKey16(code,maptype);
793 /****************************************************************************
794 * GetKBCodePage (USER32.@)
796 UINT WINAPI GetKBCodePage(void)
798 return GetOEMCP();
801 /****************************************************************************
802 * GetKeyboardLayoutName (USER.477)
804 INT16 WINAPI GetKeyboardLayoutName16(LPSTR pwszKLID)
806 return GetKeyboardLayoutNameA(pwszKLID);
809 /***********************************************************************
810 * GetKeyboardLayout (USER32.@)
812 * FIXME: - device handle for keyboard layout defaulted to
813 * the language id. This is the way Windows default works.
814 * - the thread identifier (dwLayout) is also ignored.
816 HKL WINAPI GetKeyboardLayout(DWORD dwLayout)
818 HKL layout;
819 layout = GetSystemDefaultLCID(); /* FIXME */
820 layout |= (layout<<16); /* FIXME */
821 TRACE_(keyboard)("returning %08x\n",layout);
822 return layout;
825 /****************************************************************************
826 * GetKeyboardLayoutNameA (USER32.@)
828 INT WINAPI GetKeyboardLayoutNameA(LPSTR pwszKLID)
830 sprintf(pwszKLID, "%08x",GetKeyboardLayout(0));
831 return 1;
834 /****************************************************************************
835 * GetKeyboardLayoutNameW (USER32.@)
837 INT WINAPI GetKeyboardLayoutNameW(LPWSTR pwszKLID)
839 char buf[KL_NAMELENGTH];
840 int res = GetKeyboardLayoutNameA(buf);
841 MultiByteToWideChar( CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH );
842 return res;
845 /****************************************************************************
846 * GetKeyNameTextA (USER32.@)
848 INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
850 return GetKeyNameText16(lParam,lpBuffer,nSize);
853 /****************************************************************************
854 * GetKeyNameTextW (USER32.@)
856 INT WINAPI GetKeyNameTextW(LONG lParam, LPWSTR lpBuffer, INT nSize)
858 int res;
859 LPSTR buf = HeapAlloc( GetProcessHeap(), 0, nSize );
860 if(buf == NULL) return 0; /* FIXME: is this the correct failure value?*/
861 res = GetKeyNameTextA(lParam,buf,nSize);
863 if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, buf, -1, lpBuffer, nSize ))
864 lpBuffer[nSize-1] = 0;
865 HeapFree( GetProcessHeap(), 0, buf );
866 return res;
869 /****************************************************************************
870 * ToUnicode (USER32.@)
872 INT WINAPI ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
873 LPWSTR lpwStr, int size, UINT flags)
875 return USER_Driver.pToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
878 /****************************************************************************
879 * ToUnicodeEx (USER32.@)
881 INT WINAPI ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
882 LPWSTR lpwStr, int size, UINT flags, HKL hkl)
884 /* FIXME: need true implementation */
885 return ToUnicode(virtKey, scanCode, lpKeyState, lpwStr, size, flags);
888 /****************************************************************************
889 * ToAscii (USER32.@)
891 INT WINAPI ToAscii( UINT virtKey,UINT scanCode,LPBYTE lpKeyState,
892 LPWORD lpChar,UINT flags )
894 WCHAR uni_chars[2];
895 INT ret, n_ret;
897 ret = ToUnicode(virtKey, scanCode, lpKeyState, uni_chars, 2, flags);
898 if(ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
899 else n_ret = ret;
900 WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
901 return ret;
904 /****************************************************************************
905 * ToAsciiEx (USER32.@)
907 INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
908 LPWORD lpChar, UINT flags, HKL dwhkl )
910 /* FIXME: need true implementation */
911 return ToAscii(virtKey, scanCode, lpKeyState, lpChar, flags);
914 /**********************************************************************
915 * ActivateKeyboardLayout (USER32.@)
917 * Call ignored. WINE supports only system default keyboard layout.
919 HKL WINAPI ActivateKeyboardLayout(HKL hLayout, UINT flags)
921 TRACE_(keyboard)("(%d, %d)\n", hLayout, flags);
922 ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
923 return 0;
927 /***********************************************************************
928 * GetKeyboardLayoutList (USER32.@)
930 * FIXME: Supports only the system default language and layout and
931 * returns only 1 value.
933 * Return number of values available if either input parm is
934 * 0, per MS documentation.
937 INT WINAPI GetKeyboardLayoutList(INT nBuff,HKL *layouts)
939 TRACE_(keyboard)("(%d,%p)\n",nBuff,layouts);
940 if (!nBuff || !layouts)
941 return 1;
942 if (layouts)
943 layouts[0] = GetKeyboardLayout(0);
944 return 1;
948 /***********************************************************************
949 * RegisterHotKey (USER32.@)
951 BOOL WINAPI RegisterHotKey(HWND hwnd,INT id,UINT modifiers,UINT vk) {
952 FIXME_(keyboard)("(0x%08x,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk);
953 return TRUE;
956 /***********************************************************************
957 * UnregisterHotKey (USER32.@)
959 BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) {
960 FIXME_(keyboard)("(0x%08x,%d): stub\n",hwnd,id);
961 return TRUE;
964 /***********************************************************************
965 * LoadKeyboardLayoutA (USER32.@)
966 * Call ignored. WINE supports only system default keyboard layout.
968 HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags)
970 TRACE_(keyboard)("(%s, %d)\n", pwszKLID, Flags);
971 ERR_(keyboard)("Only default system keyboard layout supported. Call ignored.\n");
972 return 0;
975 /***********************************************************************
976 * LoadKeyboardLayoutW (USER32.@)
978 HKL WINAPI LoadKeyboardLayoutW(LPCWSTR pwszKLID, UINT Flags)
980 char buf[9];
982 WideCharToMultiByte( CP_ACP, 0, pwszKLID, -1, buf, sizeof(buf), NULL, NULL );
983 buf[8] = 0;
984 return LoadKeyboardLayoutA(buf, Flags);