- Rewrite GetKeyState based on wine. Now it's results are based on whether or nor the message queue has processed a keyboard message and not the actual state of the keyboard.c
- TODO: ensure it works corectly and use this implementation in most other places in win32k when we need to check the state of a key. To ensure nothing breaks, this change affects only GetKeyState

svn path=/trunk/; revision=51295
This commit is contained in:
Giannis Adamopoulos 2011-04-09 12:44:45 +00:00
parent 4041e16e6f
commit 893a0bfccb
4 changed files with 135 additions and 54 deletions

View file

@ -27,6 +27,22 @@ extern PATTACHINFO gpai;
#define KBL_PRELOAD 2
#define KBL_RESET 4
/* Key States */
#define KS_DOWN_MASK 0xc0
#define KS_DOWN_BIT 0x80
#define KS_LOCK_BIT 0x01
/* Lock modifiers */
#define CAPITAL_BIT 0x80000000
#define NUMLOCK_BIT 0x40000000
#define MOD_BITS_MASK 0x3fffffff
#define MOD_KCTRL 0x02
/* Scan Codes */
#define SC_KEY_UP 0x8000
/* lParam bits */
#define LP_EXT_BIT (1<<24)
/* From kbdxx.c -- Key changes with numlock */
#define KNUMP 0x400
INIT_FUNCTION
NTSTATUS
NTAPI

View file

@ -108,6 +108,9 @@ typedef struct _USER_MESSAGE_QUEUE
/* extra message information */
LPARAM ExtraInfo;
/* state of each key */
UCHAR KeyState[256];
/* messages that are currently dispatched by other threads */
LIST_ENTRY DispatchingMessagesHead;
/* messages that are currently dispatched by this message queue, required for cleanup */

View file

@ -33,28 +33,8 @@
#define NDEBUG
#include <debug.h>
/* Lock modifiers */
#define CAPITAL_BIT 0x80000000
#define NUMLOCK_BIT 0x40000000
#define MOD_BITS_MASK 0x3fffffff
#define MOD_KCTRL 0x02
/* Key States */
#define KS_DOWN_MASK 0xc0
#define KS_DOWN_BIT 0x80
#define KS_LOCK_BIT 0x01
/* Scan Codes */
#define SC_KEY_UP 0x8000
/* lParam bits */
#define LP_EXT_BIT (1<<24)
/* From kbdxx.c -- Key changes with numlock */
#define KNUMP 0x400
BYTE gQueueKeyStateTable[256];
/* FUNCTIONS *****************************************************************/
/* Initialization -- Right now, just zero the key state and init the lock */
@ -353,40 +333,6 @@ ToUnicodeInner(UINT wVirtKey,
}
DWORD FASTCALL UserGetKeyState(DWORD key)
{
DWORD ret = 0;
if( key < 0x100 )
{
ret = ((DWORD)(gQueueKeyStateTable[key] & KS_DOWN_BIT) << 8 ) |
(gQueueKeyStateTable[key] & KS_LOCK_BIT);
}
return ret;
}
SHORT
APIENTRY
NtUserGetKeyState(
INT key)
{
DECLARE_RETURN(DWORD);
DPRINT("Enter NtUserGetKeyState\n");
UserEnterExclusive();
RETURN(UserGetKeyState(key));
CLEANUP:
DPRINT("Leave NtUserGetKeyState, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
DWORD FASTCALL UserGetAsyncKeyState(DWORD key)
{
DWORD ret = 0;

View file

@ -41,6 +41,106 @@ MsqInitializeImpl(VOID)
return(STATUS_SUCCESS);
}
DWORD FASTCALL UserGetKeyState(DWORD key)
{
DWORD ret = 0;
PTHREADINFO pti;
PUSER_MESSAGE_QUEUE MessageQueue;
pti = PsGetCurrentThreadWin32Thread();
MessageQueue = pti->MessageQueue;
if( key < 0x100 )
{
ret = ((DWORD)(MessageQueue->KeyState[key] & KS_DOWN_BIT) << 8 ) |
(MessageQueue->KeyState[key] & KS_LOCK_BIT);
}
return ret;
}
/* change the input key state for a given key */
static void set_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue, UCHAR key, BOOL down )
{
if (down)
{
if (!(MessageQueue->KeyState[key] & KS_DOWN_BIT))
{
MessageQueue->KeyState[key] ^= KS_LOCK_BIT;
}
MessageQueue->KeyState[key] |= KS_DOWN_BIT;
}
else
{
MessageQueue->KeyState[key] &= ~KS_DOWN_BIT;
}
}
/* update the input key state for a keyboard message */
static void update_input_key_state( PUSER_MESSAGE_QUEUE MessageQueue, MSG* msg )
{
UCHAR key;
BOOL down = 0;
switch (msg->message)
{
case WM_LBUTTONDOWN:
down = 1;
/* fall through */
case WM_LBUTTONUP:
set_input_key_state( MessageQueue, VK_LBUTTON, down );
break;
case WM_MBUTTONDOWN:
down = 1;
/* fall through */
case WM_MBUTTONUP:
set_input_key_state( MessageQueue, VK_MBUTTON, down );
break;
case WM_RBUTTONDOWN:
down = 1;
/* fall through */
case WM_RBUTTONUP:
set_input_key_state( MessageQueue, VK_RBUTTON, down );
break;
case WM_XBUTTONDOWN:
down = 1;
/* fall through */
case WM_XBUTTONUP:
if (msg->wParam == XBUTTON1)
set_input_key_state( MessageQueue, VK_XBUTTON1, down );
else if (msg->wParam == XBUTTON2)
set_input_key_state( MessageQueue, VK_XBUTTON2, down );
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
down = 1;
/* fall through */
case WM_KEYUP:
case WM_SYSKEYUP:
key = (UCHAR)msg->wParam;
set_input_key_state( MessageQueue, key, down );
switch(key)
{
case VK_LCONTROL:
case VK_RCONTROL:
down = (MessageQueue->KeyState[VK_LCONTROL] | MessageQueue->KeyState[VK_RCONTROL]) & KS_DOWN_BIT;
set_input_key_state( MessageQueue, VK_CONTROL, down );
break;
case VK_LMENU:
case VK_RMENU:
down = (MessageQueue->KeyState[VK_LMENU] | MessageQueue->KeyState[VK_RMENU]) & KS_DOWN_BIT;
set_input_key_state( MessageQueue, VK_MENU, down );
break;
case VK_LSHIFT:
case VK_RSHIFT:
down = (MessageQueue->KeyState[VK_LSHIFT] | MessageQueue->KeyState[VK_RSHIFT]) & KS_DOWN_BIT;
set_input_key_state( MessageQueue, VK_SHIFT, down );
break;
}
break;
}
}
HANDLE FASTCALL
IntMsqSetWakeMask(DWORD WakeMask)
{
@ -1294,6 +1394,7 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
if (Remove)
{
update_input_key_state(MessageQueue, pMsg);
RemoveEntryList(&CurrentMessage->ListEntry);
ClearMsgBitsMask(MessageQueue, QS_INPUT);
MsqDestroyMessage(CurrentMessage);
@ -1714,4 +1815,19 @@ MsqSetStateWindow(PUSER_MESSAGE_QUEUE MessageQueue, ULONG Type, HWND hWnd)
return NULL;
}
SHORT
APIENTRY
NtUserGetKeyState(INT key)
{
DWORD Ret;
UserEnterExclusive();
Ret = UserGetKeyState(key);
UserLeave();
return Ret;
}
/* EOF */