winemac: Use unixlib interface for dragdrop.c calls.
[wine.git] / dlls / user32 / input.c
blob5fd5fe6d04448f9e081be3de385e3f93868bd25e
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
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <ctype.h>
30 #include <assert.h>
32 #define NONAMELESSUNION
34 #include "ntstatus.h"
35 #define WIN32_NO_STATUS
36 #include "windef.h"
37 #include "winbase.h"
38 #include "wingdi.h"
39 #include "winuser.h"
40 #include "winnls.h"
41 #include "winternl.h"
42 #include "winerror.h"
43 #include "win.h"
44 #include "user_private.h"
45 #include "dbt.h"
46 #include "wine/server.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(win);
50 WINE_DECLARE_DEBUG_CHANNEL(keyboard);
52 /***********************************************************************
53 * get_locale_kbd_layout
55 static HKL get_locale_kbd_layout(void)
57 ULONG_PTR layout;
58 LANGID langid;
60 /* FIXME:
62 * layout = main_key_tab[kbd_layout].lcid;
64 * Winword uses return value of GetKeyboardLayout as a codepage
65 * to translate ANSI keyboard messages to unicode. But we have
66 * a problem with it: for instance Polish keyboard layout is
67 * identical to the US one, and therefore instead of the Polish
68 * locale id we return the US one.
71 layout = GetUserDefaultLCID();
74 * Microsoft Office expects this value to be something specific
75 * for Japanese and Korean Windows with an IME the value is 0xe001
76 * We should probably check to see if an IME exists and if so then
77 * set this word properly.
79 langid = PRIMARYLANGID( LANGIDFROMLCID( layout ) );
80 if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
81 layout = MAKELONG( layout, 0xe001 ); /* IME */
82 else
83 layout = MAKELONG( layout, layout );
85 return (HKL)layout;
89 /**********************************************************************
90 * set_capture_window
92 BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret )
94 /* FIXME: move callers to win32u or use NtUserSetCapture */
95 return NtUserCallHwndParam( hwnd, gui_flags, NtUserSetCaptureWindow );
99 /***********************************************************************
100 * keybd_event (USER32.@)
102 void WINAPI keybd_event( BYTE bVk, BYTE bScan,
103 DWORD dwFlags, ULONG_PTR dwExtraInfo )
105 INPUT input;
107 input.type = INPUT_KEYBOARD;
108 input.u.ki.wVk = bVk;
109 input.u.ki.wScan = bScan;
110 input.u.ki.dwFlags = dwFlags;
111 input.u.ki.time = 0;
112 input.u.ki.dwExtraInfo = dwExtraInfo;
113 NtUserSendInput( 1, &input, sizeof(input) );
117 /***********************************************************************
118 * mouse_event (USER32.@)
120 void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
121 DWORD dwData, ULONG_PTR dwExtraInfo )
123 INPUT input;
125 input.type = INPUT_MOUSE;
126 input.u.mi.dx = dx;
127 input.u.mi.dy = dy;
128 input.u.mi.mouseData = dwData;
129 input.u.mi.dwFlags = dwFlags;
130 input.u.mi.time = 0;
131 input.u.mi.dwExtraInfo = dwExtraInfo;
132 NtUserSendInput( 1, &input, sizeof(input) );
136 /***********************************************************************
137 * GetCursorPos (USER32.@)
139 BOOL WINAPI DECLSPEC_HOTPATCH GetCursorPos( POINT *pt )
141 return NtUserGetCursorPos( pt );
145 /**********************************************************************
146 * ReleaseCapture (USER32.@)
148 BOOL WINAPI DECLSPEC_HOTPATCH ReleaseCapture(void)
150 return NtUserReleaseCapture();
154 /**********************************************************************
155 * GetCapture (USER32.@)
157 HWND WINAPI GetCapture(void)
159 GUITHREADINFO info;
160 info.cbSize = sizeof(info);
161 return NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ) ? info.hwndCapture : 0;
165 /*****************************************************************
166 * DestroyCaret (USER32.@)
168 BOOL WINAPI DestroyCaret(void)
170 return NtUserDestroyCaret();
174 /*****************************************************************
175 * SetCaretPos (USER32.@)
177 BOOL WINAPI SetCaretPos( int x, int y )
179 return NtUserSetCaretPos( x, y );
183 /*****************************************************************
184 * SetCaretBlinkTime (USER32.@)
186 BOOL WINAPI SetCaretBlinkTime( unsigned int time )
188 return NtUserSetCaretBlinkTime( time );
192 /***********************************************************************
193 * GetInputState (USER32.@)
195 BOOL WINAPI GetInputState(void)
197 return NtUserGetInputState();
201 /******************************************************************
202 * GetLastInputInfo (USER32.@)
204 BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO plii)
206 BOOL ret;
208 TRACE("%p\n", plii);
210 if (plii->cbSize != sizeof (*plii) )
212 SetLastError(ERROR_INVALID_PARAMETER);
213 return FALSE;
216 SERVER_START_REQ( get_last_input_time )
218 ret = !wine_server_call_err( req );
219 if (ret)
220 plii->dwTime = reply->time;
222 SERVER_END_REQ;
223 return ret;
227 /**********************************************************************
228 * VkKeyScanA (USER32.@)
230 * VkKeyScan translates an ANSI character to a virtual-key and shift code
231 * for the current keyboard.
232 * high-order byte yields :
233 * 0 Unshifted
234 * 1 Shift
235 * 2 Ctrl
236 * 3-5 Shift-key combinations that are not used for characters
237 * 6 Ctrl-Alt
238 * 7 Ctrl-Alt-Shift
239 * I.e. : Shift = 1, Ctrl = 2, Alt = 4.
240 * FIXME : works ok except for dead chars :
241 * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
242 * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
244 SHORT WINAPI VkKeyScanA(CHAR cChar)
246 WCHAR wChar;
248 if (IsDBCSLeadByte(cChar)) return -1;
250 MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
251 return VkKeyScanW(wChar);
254 /******************************************************************************
255 * VkKeyScanW (USER32.@)
257 SHORT WINAPI VkKeyScanW(WCHAR cChar)
259 return NtUserVkKeyScanEx( cChar, NtUserGetKeyboardLayout(0) );
262 /**********************************************************************
263 * VkKeyScanExA (USER32.@)
265 WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
267 WCHAR wChar;
269 if (IsDBCSLeadByte(cChar)) return -1;
271 MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
272 return NtUserVkKeyScanEx( wChar, dwhkl );
275 /**********************************************************************
276 * OemKeyScan (USER32.@)
278 DWORD WINAPI OemKeyScan( WORD oem )
280 WCHAR wchr;
281 DWORD vkey, scan;
282 char oem_char = LOBYTE( oem );
284 if (!OemToCharBuffW( &oem_char, &wchr, 1 ))
285 return -1;
287 vkey = VkKeyScanW( wchr );
288 scan = MapVirtualKeyW( LOBYTE( vkey ), MAPVK_VK_TO_VSC );
289 if (!scan) return -1;
291 vkey &= 0xff00;
292 vkey <<= 8;
293 return vkey | scan;
296 /******************************************************************************
297 * GetKeyboardType (USER32.@)
299 INT WINAPI GetKeyboardType(INT nTypeFlag)
301 TRACE_(keyboard)("(%d)\n", nTypeFlag);
302 if (LOWORD(NtUserGetKeyboardLayout(0)) == MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN))
304 /* scan code for `_', the key left of r-shift, in Japanese 106 keyboard */
305 const UINT JP106_VSC_USCORE = 0x73;
307 switch(nTypeFlag)
309 case 0: /* Keyboard type */
310 return 7; /* Japanese keyboard */
311 case 1: /* Keyboard Subtype */
312 /* Test keyboard mappings to detect Japanese keyboard */
313 if (MapVirtualKeyW(VK_OEM_102, MAPVK_VK_TO_VSC) == JP106_VSC_USCORE
314 && MapVirtualKeyW(JP106_VSC_USCORE, MAPVK_VSC_TO_VK) == VK_OEM_102)
315 return 2; /* Japanese 106 */
316 else
317 return 0; /* AT-101 */
318 case 2: /* Number of F-keys */
319 return 12; /* It has 12 F-keys */
322 else
324 switch(nTypeFlag)
326 case 0: /* Keyboard type */
327 return 4; /* AT-101 */
328 case 1: /* Keyboard Subtype */
329 return 0; /* There are no defined subtypes */
330 case 2: /* Number of F-keys */
331 return 12; /* We're doing an 101 for now, so return 12 F-keys */
334 WARN_(keyboard)("Unknown type\n");
335 return 0; /* The book says 0 here, so 0 */
338 /******************************************************************************
339 * MapVirtualKeyA (USER32.@)
341 UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
343 return MapVirtualKeyExA( code, maptype, NtUserGetKeyboardLayout(0) );
346 /******************************************************************************
347 * MapVirtualKeyW (USER32.@)
349 UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
351 return NtUserMapVirtualKeyEx( code, maptype, NtUserGetKeyboardLayout(0) );
354 /******************************************************************************
355 * MapVirtualKeyExA (USER32.@)
357 UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
359 UINT ret;
361 ret = NtUserMapVirtualKeyEx( code, maptype, hkl );
362 if (maptype == MAPVK_VK_TO_CHAR)
364 BYTE ch = 0;
365 WCHAR wch = ret;
367 WideCharToMultiByte( CP_ACP, 0, &wch, 1, (LPSTR)&ch, 1, NULL, NULL );
368 ret = ch;
370 return ret;
373 /****************************************************************************
374 * GetKBCodePage (USER32.@)
376 UINT WINAPI GetKBCodePage(void)
378 return GetOEMCP();
381 /****************************************************************************
382 * GetKeyboardLayoutNameA (USER32.@)
384 BOOL WINAPI GetKeyboardLayoutNameA(LPSTR pszKLID)
386 WCHAR buf[KL_NAMELENGTH];
388 if (NtUserGetKeyboardLayoutName( buf ))
389 return WideCharToMultiByte( CP_ACP, 0, buf, -1, pszKLID, KL_NAMELENGTH, NULL, NULL ) != 0;
390 return FALSE;
393 /****************************************************************************
394 * GetKeyNameTextA (USER32.@)
396 INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
398 WCHAR buf[256];
399 INT ret;
401 if (!nSize || !NtUserGetKeyNameText( lParam, buf, ARRAYSIZE(buf) ))
403 lpBuffer[0] = 0;
404 return 0;
406 ret = WideCharToMultiByte(CP_ACP, 0, buf, -1, lpBuffer, nSize, NULL, NULL);
407 if (!ret && nSize)
409 ret = nSize - 1;
410 lpBuffer[ret] = 0;
412 else ret--;
414 return ret;
417 /****************************************************************************
418 * ToUnicode (USER32.@)
420 INT WINAPI ToUnicode( UINT virt, UINT scan, const BYTE *state, LPWSTR str, int size, UINT flags )
422 return NtUserToUnicodeEx( virt, scan, state, str, size, flags, NtUserGetKeyboardLayout(0) );
425 /****************************************************************************
426 * ToAscii (USER32.@)
428 INT WINAPI ToAscii( UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
429 LPWORD lpChar, UINT flags )
431 return ToAsciiEx( virtKey, scanCode, lpKeyState, lpChar, flags,
432 NtUserGetKeyboardLayout(0) );
435 /****************************************************************************
436 * ToAsciiEx (USER32.@)
438 INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
439 LPWORD lpChar, UINT flags, HKL dwhkl )
441 WCHAR uni_chars[2];
442 INT ret, n_ret;
444 ret = NtUserToUnicodeEx( virtKey, scanCode, lpKeyState, uni_chars, 2, flags, dwhkl );
445 if (ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
446 else n_ret = ret;
447 WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, NULL);
448 return ret;
451 /**********************************************************************
452 * BlockInput (USER32.@)
454 BOOL WINAPI BlockInput(BOOL fBlockIt)
456 FIXME_(keyboard)("(%d): stub\n", fBlockIt);
457 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
459 return FALSE;
463 /***********************************************************************
464 * LoadKeyboardLayoutW (USER32.@)
466 HKL WINAPI LoadKeyboardLayoutW( const WCHAR *name, UINT flags )
468 WCHAR layout_path[MAX_PATH], value[5];
469 DWORD value_size, tmp;
470 HKEY hkey;
471 HKL layout;
473 FIXME_(keyboard)( "name %s, flags %x, semi-stub!\n", debugstr_w( name ), flags );
475 tmp = wcstoul( name, NULL, 16 );
476 if (HIWORD( tmp )) layout = UlongToHandle( tmp );
477 else layout = UlongToHandle( MAKELONG( LOWORD( tmp ), LOWORD( tmp ) ) );
479 wcscpy( layout_path, L"System\\CurrentControlSet\\Control\\Keyboard Layouts\\" );
480 wcscat( layout_path, name );
482 if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, layout_path, &hkey ))
484 value_size = sizeof(value);
485 if (!RegGetValueW( hkey, NULL, L"Layout Id", RRF_RT_REG_SZ, NULL, (void *)&value, &value_size ))
486 layout = UlongToHandle( MAKELONG( LOWORD( tmp ), 0xf000 | (wcstoul( value, NULL, 16 ) & 0xfff) ) );
488 RegCloseKey( hkey );
491 if ((flags & KLF_ACTIVATE) && NtUserActivateKeyboardLayout( layout, 0 )) return layout;
493 /* FIXME: semi-stub: returning default layout */
494 return get_locale_kbd_layout();
497 /***********************************************************************
498 * LoadKeyboardLayoutA (USER32.@)
500 HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags)
502 HKL ret;
503 UNICODE_STRING pwszKLIDW;
505 if (pwszKLID) RtlCreateUnicodeStringFromAsciiz(&pwszKLIDW, pwszKLID);
506 else pwszKLIDW.Buffer = NULL;
508 ret = LoadKeyboardLayoutW(pwszKLIDW.Buffer, Flags);
509 RtlFreeUnicodeString(&pwszKLIDW);
510 return ret;
514 /***********************************************************************
515 * UnloadKeyboardLayout (USER32.@)
517 BOOL WINAPI UnloadKeyboardLayout( HKL layout )
519 FIXME_(keyboard)( "layout %p, stub!\n", layout );
520 SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
521 return FALSE;
525 /***********************************************************************
526 * EnableMouseInPointer (USER32.@)
528 BOOL WINAPI EnableMouseInPointer(BOOL enable)
530 FIXME("(%#x) stub\n", enable);
532 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
533 return FALSE;
536 static DWORD CALLBACK devnotify_window_callback(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header)
538 SendMessageTimeoutW(handle, WM_DEVICECHANGE, flags, (LPARAM)header, SMTO_ABORTIFHUNG, 2000, NULL);
539 return 0;
542 static DWORD CALLBACK devnotify_service_callback(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header)
544 FIXME("Support for service handles is not yet implemented!\n");
545 return 0;
548 struct device_notification_details
550 DWORD (CALLBACK *cb)(HANDLE handle, DWORD flags, DEV_BROADCAST_HDR *header);
551 HANDLE handle;
552 union
554 DEV_BROADCAST_HDR header;
555 DEV_BROADCAST_DEVICEINTERFACE_W iface;
556 } filter;
559 extern HDEVNOTIFY WINAPI I_ScRegisterDeviceNotification( struct device_notification_details *details,
560 void *filter, DWORD flags );
561 extern BOOL WINAPI I_ScUnregisterDeviceNotification( HDEVNOTIFY handle );
563 /***********************************************************************
564 * RegisterDeviceNotificationA (USER32.@)
566 * See RegisterDeviceNotificationW.
568 HDEVNOTIFY WINAPI RegisterDeviceNotificationA( HANDLE handle, void *filter, DWORD flags )
570 return RegisterDeviceNotificationW( handle, filter, flags );
573 /***********************************************************************
574 * RegisterDeviceNotificationW (USER32.@)
576 HDEVNOTIFY WINAPI RegisterDeviceNotificationW( HANDLE handle, void *filter, DWORD flags )
578 struct device_notification_details details;
579 DEV_BROADCAST_HDR *header = filter;
581 TRACE("handle %p, filter %p, flags %#lx\n", handle, filter, flags);
583 if (flags & ~(DEVICE_NOTIFY_SERVICE_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES))
585 SetLastError( ERROR_INVALID_PARAMETER );
586 return NULL;
589 if (!(flags & DEVICE_NOTIFY_SERVICE_HANDLE) && !IsWindow( handle ))
591 SetLastError( ERROR_INVALID_PARAMETER );
592 return NULL;
595 if (!header) details.filter.header.dbch_devicetype = 0;
596 else if (header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
598 DEV_BROADCAST_DEVICEINTERFACE_W *iface = (DEV_BROADCAST_DEVICEINTERFACE_W *)header;
599 details.filter.iface = *iface;
601 if (flags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
602 details.filter.iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_classguid );
603 else
604 details.filter.iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name );
606 else if (header->dbch_devicetype == DBT_DEVTYP_HANDLE)
608 FIXME( "DBT_DEVTYP_HANDLE filter type not implemented\n" );
609 details.filter.header.dbch_devicetype = 0;
611 else
613 SetLastError( ERROR_INVALID_DATA );
614 return NULL;
617 details.handle = handle;
619 if (flags & DEVICE_NOTIFY_SERVICE_HANDLE)
620 details.cb = devnotify_service_callback;
621 else
622 details.cb = devnotify_window_callback;
624 return I_ScRegisterDeviceNotification( &details, filter, 0 );
627 /***********************************************************************
628 * UnregisterDeviceNotification (USER32.@)
630 BOOL WINAPI UnregisterDeviceNotification( HDEVNOTIFY handle )
632 TRACE("%p\n", handle);
634 return I_ScUnregisterDeviceNotification( handle );