Commit d6ae45b5 authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

win32u: Move NtUserGetAsyncKeyState implementation from user32.

parent bd604c80
...@@ -455,7 +455,7 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA ...@@ -455,7 +455,7 @@ static LRESULT call_hook( struct hook_info *info, INT code, WPARAM wparam, LPARA
} }
if (info->id == WH_KEYBOARD_LL || info->id == WH_MOUSE_LL) if (info->id == WH_KEYBOARD_LL || info->id == WH_MOUSE_LL)
InterlockedIncrement( &global_key_state_counter ); /* force refreshing the key state cache */ NtUserCallOneParam( 1, NtUserIncrementKeyStateCounter ); /* force refreshing the key state cache */
return ret; return ret;
} }
......
...@@ -49,8 +49,6 @@ ...@@ -49,8 +49,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(win); WINE_DEFAULT_DEBUG_CHANNEL(win);
WINE_DECLARE_DEBUG_CHANNEL(keyboard); WINE_DECLARE_DEBUG_CHANNEL(keyboard);
LONG global_key_state_counter = 0;
/*********************************************************************** /***********************************************************************
* get_key_state * get_key_state
*/ */
...@@ -60,19 +58,19 @@ static WORD get_key_state(void) ...@@ -60,19 +58,19 @@ static WORD get_key_state(void)
if (GetSystemMetrics( SM_SWAPBUTTON )) if (GetSystemMetrics( SM_SWAPBUTTON ))
{ {
if (GetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON; if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_LBUTTON;
if (GetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON; if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_RBUTTON;
} }
else else
{ {
if (GetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON; if (NtUserGetAsyncKeyState(VK_LBUTTON) & 0x80) ret |= MK_LBUTTON;
if (GetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON; if (NtUserGetAsyncKeyState(VK_RBUTTON) & 0x80) ret |= MK_RBUTTON;
} }
if (GetAsyncKeyState(VK_MBUTTON) & 0x80) ret |= MK_MBUTTON; if (NtUserGetAsyncKeyState(VK_MBUTTON) & 0x80) ret |= MK_MBUTTON;
if (GetAsyncKeyState(VK_SHIFT) & 0x80) ret |= MK_SHIFT; if (NtUserGetAsyncKeyState(VK_SHIFT) & 0x80) ret |= MK_SHIFT;
if (GetAsyncKeyState(VK_CONTROL) & 0x80) ret |= MK_CONTROL; if (NtUserGetAsyncKeyState(VK_CONTROL) & 0x80) ret |= MK_CONTROL;
if (GetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1; if (NtUserGetAsyncKeyState(VK_XBUTTON1) & 0x80) ret |= MK_XBUTTON1;
if (GetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2; if (NtUserGetAsyncKeyState(VK_XBUTTON2) & 0x80) ret |= MK_XBUTTON2;
return ret; return ret;
} }
...@@ -376,75 +374,6 @@ HWND WINAPI GetCapture(void) ...@@ -376,75 +374,6 @@ HWND WINAPI GetCapture(void)
} }
static void check_for_events( UINT flags )
{
if (USER_Driver->pMsgWaitForMultipleObjectsEx( 0, NULL, 0, flags, 0 ) == WAIT_TIMEOUT)
flush_window_surfaces( TRUE );
}
/**********************************************************************
* GetAsyncKeyState (USER32.@)
*
* Determine if a key is or was pressed. retval has high-order
* bit set to 1 if currently pressed, low-order bit set to 1 if key has
* been pressed.
*/
SHORT WINAPI DECLSPEC_HOTPATCH GetAsyncKeyState( INT key )
{
struct user_key_state_info *key_state_info = get_user_thread_info()->key_state;
INT counter = global_key_state_counter;
BYTE prev_key_state;
SHORT ret;
if (key < 0 || key >= 256) return 0;
check_for_events( QS_INPUT );
if (key_state_info && !(key_state_info->state[key] & 0xc0) &&
key_state_info->counter == counter && GetTickCount() - key_state_info->time < 50)
{
/* use cached value */
return 0;
}
else if (!key_state_info)
{
key_state_info = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*key_state_info) );
get_user_thread_info()->key_state = key_state_info;
}
ret = 0;
SERVER_START_REQ( get_key_state )
{
req->async = 1;
req->key = key;
if (key_state_info)
{
prev_key_state = key_state_info->state[key];
wine_server_set_reply( req, key_state_info->state, sizeof(key_state_info->state) );
}
if (!wine_server_call( req ))
{
if (reply->state & 0x40) ret |= 0x0001;
if (reply->state & 0x80) ret |= 0x8000;
if (key_state_info)
{
/* force refreshing the key state cache - some multithreaded programs
* (like Adobe Photoshop CS5) expect that changes to the async key state
* are also immediately available in other threads. */
if (prev_key_state != key_state_info->state[key])
counter = InterlockedIncrement( &global_key_state_counter );
key_state_info->time = GetTickCount();
key_state_info->counter = counter;
}
}
}
SERVER_END_REQ;
return ret;
}
/*********************************************************************** /***********************************************************************
* GetInputState (USER32.@) * GetInputState (USER32.@)
*/ */
......
...@@ -3239,7 +3239,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r ...@@ -3239,7 +3239,7 @@ NTSTATUS send_hardware_message( HWND hwnd, const INPUT *input, const RAWINPUT *r
struct user_key_state_info *key_state_info = get_user_thread_info()->key_state; struct user_key_state_info *key_state_info = get_user_thread_info()->key_state;
struct send_message_info info; struct send_message_info info;
int prev_x, prev_y, new_x, new_y; int prev_x, prev_y, new_x, new_y;
INT counter = global_key_state_counter; INT counter = NtUserCallOneParam( 0, NtUserIncrementKeyStateCounter );
USAGE hid_usage_page, hid_usage; USAGE hid_usage_page, hid_usage;
NTSTATUS ret; NTSTATUS ret;
BOOL wait; BOOL wait;
......
...@@ -255,7 +255,7 @@ ...@@ -255,7 +255,7 @@
@ stdcall GetAncestor(long long) @ stdcall GetAncestor(long long)
@ stdcall GetAppCompatFlags(long) @ stdcall GetAppCompatFlags(long)
@ stdcall GetAppCompatFlags2(long) @ stdcall GetAppCompatFlags2(long)
@ stdcall GetAsyncKeyState(long) @ stdcall -import GetAsyncKeyState(long) NtUserGetAsyncKeyState
@ stdcall GetAutoRotationState(ptr) @ stdcall GetAutoRotationState(ptr)
@ stdcall GetAwarenessFromDpiAwarenessContext(long) @ stdcall GetAwarenessFromDpiAwarenessContext(long)
@ stdcall GetCapture() @ stdcall GetCapture()
......
...@@ -256,10 +256,10 @@ static void thread_detach(void) ...@@ -256,10 +256,10 @@ static void thread_detach(void)
WDML_NotifyThreadDetach(); WDML_NotifyThreadDetach();
USER_Driver->pThreadDetach(); USER_Driver->pThreadDetach();
NtUserCallNoParam( NtUserThreadDetach );
destroy_thread_windows(); destroy_thread_windows();
CloseHandle( thread_info->server_queue ); CloseHandle( thread_info->server_queue );
HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data ); HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
HeapFree( GetProcessHeap(), 0, thread_info->key_state );
HeapFree( GetProcessHeap(), 0, thread_info->rawinput ); HeapFree( GetProcessHeap(), 0, thread_info->rawinput );
exiting_thread_id = 0; exiting_thread_id = 0;
......
...@@ -102,7 +102,6 @@ struct rawinput_thread_data ...@@ -102,7 +102,6 @@ struct rawinput_thread_data
RAWINPUT buffer[1]; /* rawinput message data buffer */ RAWINPUT buffer[1]; /* rawinput message data buffer */
}; };
extern LONG global_key_state_counter DECLSPEC_HIDDEN;
extern BOOL (WINAPI *imm_register_window)(HWND) DECLSPEC_HIDDEN; extern BOOL (WINAPI *imm_register_window)(HWND) DECLSPEC_HIDDEN;
extern void (WINAPI *imm_unregister_window)(HWND) DECLSPEC_HIDDEN; extern void (WINAPI *imm_unregister_window)(HWND) DECLSPEC_HIDDEN;
#define WM_IME_INTERNAL 0x287 #define WM_IME_INTERNAL 0x287
......
...@@ -1159,6 +1159,7 @@ static struct unix_funcs unix_funcs = ...@@ -1159,6 +1159,7 @@ static struct unix_funcs unix_funcs =
NtUserEnumDisplayDevices, NtUserEnumDisplayDevices,
NtUserEnumDisplayMonitors, NtUserEnumDisplayMonitors,
NtUserEnumDisplaySettings, NtUserEnumDisplaySettings,
NtUserGetAsyncKeyState,
NtUserGetDisplayConfigBufferSizes, NtUserGetDisplayConfigBufferSizes,
NtUserGetKeyNameText, NtUserGetKeyNameText,
NtUserGetKeyboardLayoutList, NtUserGetKeyboardLayoutList,
......
...@@ -45,6 +45,8 @@ static const WCHAR keyboard_layouts_keyW[] = ...@@ -45,6 +45,8 @@ static const WCHAR keyboard_layouts_keyW[] =
}; };
LONG global_key_state_counter = 0;
/********************************************************************** /**********************************************************************
* NtUserAttachThreadInput (win32u.@) * NtUserAttachThreadInput (win32u.@)
*/ */
...@@ -135,6 +137,64 @@ static void check_for_events( UINT flags ) ...@@ -135,6 +137,64 @@ static void check_for_events( UINT flags )
flush_window_surfaces( TRUE ); flush_window_surfaces( TRUE );
} }
/**********************************************************************
* GetAsyncKeyState (win32u.@)
*/
SHORT WINAPI NtUserGetAsyncKeyState( INT key )
{
struct user_key_state_info *key_state_info = get_user_thread_info()->key_state;
INT counter = global_key_state_counter;
BYTE prev_key_state;
SHORT ret;
if (key < 0 || key >= 256) return 0;
check_for_events( QS_INPUT );
if (key_state_info && !(key_state_info->state[key] & 0xc0) &&
key_state_info->counter == counter && NtGetTickCount() - key_state_info->time < 50)
{
/* use cached value */
return 0;
}
else if (!key_state_info)
{
key_state_info = calloc( 1, sizeof(*key_state_info) );
get_user_thread_info()->key_state = key_state_info;
}
ret = 0;
SERVER_START_REQ( get_key_state )
{
req->async = 1;
req->key = key;
if (key_state_info)
{
prev_key_state = key_state_info->state[key];
wine_server_set_reply( req, key_state_info->state, sizeof(key_state_info->state) );
}
if (!wine_server_call( req ))
{
if (reply->state & 0x40) ret |= 0x0001;
if (reply->state & 0x80) ret |= 0x8000;
if (key_state_info)
{
/* force refreshing the key state cache - some multithreaded programs
* (like Adobe Photoshop CS5) expect that changes to the async key state
* are also immediately available in other threads. */
if (prev_key_state != key_state_info->state[key])
counter = InterlockedIncrement( &global_key_state_counter );
key_state_info->time = NtGetTickCount();
key_state_info->counter = counter;
}
}
}
SERVER_END_REQ;
return ret;
}
/*********************************************************************** /***********************************************************************
* NtUserGetQueueStatus (win32u.@) * NtUserGetQueueStatus (win32u.@)
*/ */
......
...@@ -4484,6 +4484,14 @@ static BOOL message_beep( UINT i ) ...@@ -4484,6 +4484,14 @@ static BOOL message_beep( UINT i )
return TRUE; return TRUE;
} }
static void thread_detach(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
free( thread_info->key_state );
thread_info->key_state = 0;
}
/*********************************************************************** /***********************************************************************
* NtUserCallOneParam (win32u.@) * NtUserCallOneParam (win32u.@)
*/ */
...@@ -4493,6 +4501,10 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code ) ...@@ -4493,6 +4501,10 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code )
{ {
case NtUserGetInputState: case NtUserGetInputState:
return get_input_state(); return get_input_state();
/* temporary exports */
case NtUserThreadDetach:
thread_detach();
return 0;
default: default:
FIXME( "invalid code %u\n", code ); FIXME( "invalid code %u\n", code );
return 0; return 0;
...@@ -4528,6 +4540,8 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code ) ...@@ -4528,6 +4540,8 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
return 0; return 0;
case NtUserGetDeskPattern: case NtUserGetDeskPattern:
return get_entry( &entry_DESKPATTERN, 256, (WCHAR *)arg ); return get_entry( &entry_DESKPATTERN, 256, (WCHAR *)arg );
case NtUserIncrementKeyStateCounter:
return InterlockedAdd( &global_key_state_counter, arg );
default: default:
FIXME( "invalid code %u\n", code ); FIXME( "invalid code %u\n", code );
return 0; return 0;
......
...@@ -891,7 +891,7 @@ ...@@ -891,7 +891,7 @@
@ stub NtUserGetAltTabInfo @ stub NtUserGetAltTabInfo
@ stub NtUserGetAncestor @ stub NtUserGetAncestor
@ stub NtUserGetAppImeLevel @ stub NtUserGetAppImeLevel
@ stub NtUserGetAsyncKeyState @ stdcall NtUserGetAsyncKeyState(long)
@ stub NtUserGetAtomName @ stub NtUserGetAtomName
@ stub NtUserGetAutoRotationState @ stub NtUserGetAutoRotationState
@ stub NtUserGetCIMSSM @ stub NtUserGetCIMSSM
......
...@@ -204,6 +204,7 @@ struct unix_funcs ...@@ -204,6 +204,7 @@ struct unix_funcs
BOOL (WINAPI *pNtUserEnumDisplayMonitors)( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp ); BOOL (WINAPI *pNtUserEnumDisplayMonitors)( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp );
BOOL (WINAPI *pNtUserEnumDisplaySettings)( UNICODE_STRING *device, DWORD mode, BOOL (WINAPI *pNtUserEnumDisplaySettings)( UNICODE_STRING *device, DWORD mode,
DEVMODEW *dev_mode, DWORD flags ); DEVMODEW *dev_mode, DWORD flags );
SHORT (WINAPI *pNtUserGetAsyncKeyState)( INT key );
LONG (WINAPI *pNtUserGetDisplayConfigBufferSizes)( UINT32 flags, UINT32 *num_path_info, LONG (WINAPI *pNtUserGetDisplayConfigBufferSizes)( UINT32 flags, UINT32 *num_path_info,
UINT32 *num_mode_info ); UINT32 *num_mode_info );
INT (WINAPI *pNtUserGetKeyNameText)( LONG lparam, WCHAR *buffer, INT size ); INT (WINAPI *pNtUserGetKeyNameText)( LONG lparam, WCHAR *buffer, INT size );
...@@ -248,6 +249,7 @@ struct unix_funcs ...@@ -248,6 +249,7 @@ struct unix_funcs
extern BOOL get_clip_cursor( RECT *rect ) DECLSPEC_HIDDEN; extern BOOL get_clip_cursor( RECT *rect ) DECLSPEC_HIDDEN;
/* input.c */ /* input.c */
extern LONG global_key_state_counter DECLSPEC_HIDDEN;
extern BOOL get_cursor_pos( POINT *pt ) DECLSPEC_HIDDEN; extern BOOL get_cursor_pos( POINT *pt ) DECLSPEC_HIDDEN;
extern DWORD get_input_state(void) DECLSPEC_HIDDEN; extern DWORD get_input_state(void) DECLSPEC_HIDDEN;
......
...@@ -758,6 +758,12 @@ BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD mode, ...@@ -758,6 +758,12 @@ BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD mode,
return unix_funcs->pNtUserEnumDisplaySettings( device, mode, dev_mode, flags ); return unix_funcs->pNtUserEnumDisplaySettings( device, mode, dev_mode, flags );
} }
SHORT WINAPI NtUserGetAsyncKeyState( INT key )
{
if (!unix_funcs) return 0;
return unix_funcs->pNtUserGetAsyncKeyState( key );
}
LONG WINAPI NtUserGetDisplayConfigBufferSizes( UINT32 flags, UINT32 *num_path_info, LONG WINAPI NtUserGetDisplayConfigBufferSizes( UINT32 flags, UINT32 *num_path_info,
UINT32 *num_mode_info ) UINT32 *num_mode_info )
{ {
......
...@@ -53,6 +53,8 @@ struct enum_display_monitor_params ...@@ -53,6 +53,8 @@ struct enum_display_monitor_params
enum enum
{ {
NtUserGetInputState, NtUserGetInputState,
/* temporary exports */
NtUserThreadDetach,
}; };
/* NtUserCallOneParam codes, not compatible with Windows */ /* NtUserCallOneParam codes, not compatible with Windows */
...@@ -69,6 +71,7 @@ enum ...@@ -69,6 +71,7 @@ enum
/* temporary exports */ /* temporary exports */
NtUserFlushWindowSurfaces, NtUserFlushWindowSurfaces,
NtUserGetDeskPattern, NtUserGetDeskPattern,
NtUserIncrementKeyStateCounter,
}; };
/* NtUserCallTwoParam codes, not compatible with Windows */ /* NtUserCallTwoParam codes, not compatible with Windows */
...@@ -128,6 +131,7 @@ NTSTATUS WINAPI NtUserEnumDisplayDevices( UNICODE_STRING *device, DWORD index, ...@@ -128,6 +131,7 @@ NTSTATUS WINAPI NtUserEnumDisplayDevices( UNICODE_STRING *device, DWORD index,
BOOL WINAPI NtUserEnumDisplayMonitors( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp ); BOOL WINAPI NtUserEnumDisplayMonitors( HDC hdc, RECT *rect, MONITORENUMPROC proc, LPARAM lp );
BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD mode, BOOL WINAPI NtUserEnumDisplaySettings( UNICODE_STRING *device, DWORD mode,
DEVMODEW *dev_mode, DWORD flags ); DEVMODEW *dev_mode, DWORD flags );
SHORT WINAPI NtUserGetAsyncKeyState( INT key );
INT WINAPI NtUserGetClipboardFormatName( UINT format, WCHAR *buffer, INT maxlen ); INT WINAPI NtUserGetClipboardFormatName( UINT format, WCHAR *buffer, INT maxlen );
HWND WINAPI NtUserGetClipboardOwner(void); HWND WINAPI NtUserGetClipboardOwner(void);
DWORD WINAPI NtUserGetClipboardSequenceNumber(void); DWORD WINAPI NtUserGetClipboardSequenceNumber(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment