implement IntKeyboardInput based on wine

svn path=/trunk/; revision=43772
This commit is contained in:
Christoph von Wittich 2009-10-26 08:50:00 +00:00
parent ddeb261349
commit a186a11520
2 changed files with 211 additions and 16 deletions

View file

@ -35,6 +35,8 @@ static HANDLE RawInputThreadHandle;
static CLIENT_ID RawInputThreadId;
static KEVENT InputThreadsStart;
static BOOLEAN InputThreadsRunning = FALSE;
static BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP
or a WM_KEYUP message */
/* FUNCTIONS *****************************************************************/
DWORD IntLastInputTick(BOOL LastInputTickSetGet);
@ -1303,7 +1305,177 @@ IntMouseInput(MOUSEINPUT *mi)
BOOL FASTCALL
IntKeyboardInput(KEYBDINPUT *ki)
{
return FALSE;
PUSER_MESSAGE_QUEUE FocusMessageQueue;
PTHREADINFO pti;
MSG Msg;
LARGE_INTEGER LargeTickCount;
KBDLLHOOKSTRUCT KbdHookData;
WORD flags, wVkStripped, wVkL, wVkR, wVk = ki->wVk, vk_hook = ki->wVk;
BOOLEAN Entered = FALSE;
Msg.lParam = 0;
// Condition may arise when calling MsqPostMessage and waiting for an event.
if (!UserIsEntered())
{
// Fixme: Not sure ATM if this thread is locked.
UserEnterExclusive();
Entered = TRUE;
}
wVk = LOBYTE(wVk);
Msg.wParam = wVk;
flags = LOBYTE(ki->wScan);
if (ki->dwFlags & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED;
/* FIXME: set KF_DLGMODE and KF_MENUMODE when needed */
/* strip left/right for menu, control, shift */
switch (wVk)
{
case VK_MENU:
case VK_LMENU:
case VK_RMENU:
wVk = (ki->dwFlags & KEYEVENTF_EXTENDEDKEY) ? VK_RMENU : VK_LMENU;
wVkStripped = VK_MENU;
wVkL = VK_LMENU;
wVkR = VK_RMENU;
break;
case VK_CONTROL:
case VK_LCONTROL:
case VK_RCONTROL:
wVk = (ki->dwFlags & KEYEVENTF_EXTENDEDKEY) ? VK_RCONTROL : VK_LCONTROL;
wVkStripped = VK_CONTROL;
wVkL = VK_LCONTROL;
wVkR = VK_RCONTROL;
break;
case VK_SHIFT:
case VK_LSHIFT:
case VK_RSHIFT:
wVk = (ki->dwFlags & KEYEVENTF_EXTENDEDKEY) ? VK_RSHIFT : VK_LSHIFT;
wVkStripped = VK_SHIFT;
wVkL = VK_LSHIFT;
wVkR = VK_RSHIFT;
break;
default:
wVkStripped = wVkL = wVkR = wVk;
}
if (ki->dwFlags & KEYEVENTF_KEYUP)
{
Msg.message = WM_KEYUP;
if ((gQueueKeyStateTable[VK_MENU] & 0x80) &&
((wVkStripped == VK_MENU) || (wVkStripped == VK_CONTROL)
|| !(gQueueKeyStateTable[VK_CONTROL] & 0x80)))
{
if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
(wVkStripped != VK_MENU)) /* <ALT>-down...<something else>-up */
Msg.message = WM_SYSKEYUP;
TrackSysKey = 0;
}
flags |= KF_REPEAT | KF_UP;
}
else
{
Msg.message = WM_KEYDOWN;
if ((gQueueKeyStateTable[VK_MENU] & 0x80 || wVkStripped == VK_MENU) &&
!(gQueueKeyStateTable[VK_CONTROL] & 0x80 || wVkStripped == VK_CONTROL))
{
Msg.message = WM_SYSKEYDOWN;
TrackSysKey = wVkStripped;
}
if (!(ki->dwFlags & KEYEVENTF_UNICODE) && gQueueKeyStateTable[wVk] & 0x80) flags |= KF_REPEAT;
}
if (ki->dwFlags & KEYEVENTF_UNICODE)
{
vk_hook = Msg.wParam = wVk = VK_PACKET;
Msg.lParam = MAKELPARAM(1 /* repeat count */, ki->wScan);
}
FocusMessageQueue = IntGetFocusMessageQueue();
Msg.hwnd = 0;
if (FocusMessageQueue && (FocusMessageQueue->FocusWindow != (HWND)0))
Msg.hwnd = FocusMessageQueue->FocusWindow;
if (!ki->time)
{
KeQueryTickCount(&LargeTickCount);
Msg.time = MsqCalculateMessageTime(&LargeTickCount);
}
else
Msg.time = ki->time;
/* All messages have to contain the cursor point. */
pti = PsGetCurrentThreadWin32Thread();
IntGetCursorLocation(pti->Desktop->WindowStation,
&Msg.pt);
DPRINT1("Kbd Hook msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
Msg.message, vk_hook, Msg.lParam);
KbdHookData.vkCode = vk_hook;
KbdHookData.scanCode = ki->wScan;
KbdHookData.flags = flags >> 8;
KbdHookData.time = Msg.time;
KbdHookData.dwExtraInfo = ki->dwExtraInfo;
if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
{
DPRINT("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
Msg.message, vk_hook, Msg.lParam);
if (Entered) UserLeave();
return FALSE;
}
if (!(ki->dwFlags & KEYEVENTF_UNICODE))
{
if (ki->dwFlags & KEYEVENTF_KEYUP)
{
gQueueKeyStateTable[wVk] &= ~0x80;
gQueueKeyStateTable[wVkStripped] = gQueueKeyStateTable[wVkL] | gQueueKeyStateTable[wVkR];
}
else
{
if (!(gQueueKeyStateTable[wVk] & 0x80)) gQueueKeyStateTable[wVk] ^= 0x01;
gQueueKeyStateTable[wVk] |= 0xc0;
gQueueKeyStateTable[wVkStripped] = gQueueKeyStateTable[wVkL] | gQueueKeyStateTable[wVkR];
}
if (gQueueKeyStateTable[VK_MENU] & 0x80) flags |= KF_ALTDOWN;
if (wVkStripped == VK_SHIFT) flags &= ~KF_EXTENDED;
Msg.lParam = MAKELPARAM(1 /* repeat count */, flags);
}
if (FocusMessageQueue == NULL)
{
DPRINT("No focus message queue\n");
if (Entered) UserLeave();
return FALSE;
}
if (FocusMessageQueue->FocusWindow != (HWND)0)
{
Msg.hwnd = FocusMessageQueue->FocusWindow;
DPRINT("Msg.hwnd = %x\n", Msg.hwnd);
FocusMessageQueue->Desktop->DesktopInfo->LastInputWasKbd = TRUE;
IntGetCursorLocation(FocusMessageQueue->Desktop->WindowStation,
&Msg.pt);
MsqPostMessage(FocusMessageQueue, &Msg, FALSE, QS_KEY);
}
else
{
DPRINT("Invalid focus window handle\n");
}
if (Entered) UserLeave();
return TRUE;
}
BOOL FASTCALL

View file

@ -69,11 +69,11 @@ NTSTATUS FASTCALL InitKeyboardImpl(VOID)
static UINT DontDistinguishShifts( UINT ret )
{
if( ret == VK_LSHIFT || ret == VK_RSHIFT )
ret = VK_LSHIFT;
ret = VK_SHIFT;
if( ret == VK_LCONTROL || ret == VK_RCONTROL )
ret = VK_LCONTROL;
ret = VK_CONTROL;
if( ret == VK_LMENU || ret == VK_RMENU )
ret = VK_LMENU;
ret = VK_MENU;
return ret;
}
@ -435,15 +435,28 @@ IntTranslateKbdMessage(LPMSG lpMsg,
if( !keyLayout )
return FALSE;
if (lpMsg->message < WM_KEYFIRST || lpMsg->message > WM_KEYLAST)
return FALSE;
if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
return FALSE;
ScanCode = (lpMsg->lParam >> 16) & 0xff;
/* All messages have to contain the cursor point. */
IntGetCursorLocation(pti->Desktop->WindowStation,
&NewMsg.pt);
switch (lpMsg->wParam)
{
case VK_PACKET:
NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
NewMsg.hwnd = lpMsg->hwnd;
NewMsg.wParam = HIWORD(lpMsg->lParam);
NewMsg.lParam = LOWORD(lpMsg->lParam);
MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY);
return TRUE;
}
ScanCode = (lpMsg->lParam >> 16) & 0xff;
UState = ToUnicodeInner(lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff,
gQueueKeyStateTable, wp, 2, 0,
keyLayout );
@ -628,11 +641,11 @@ static UINT IntMapVirtualKeyEx( UINT Code, UINT Type, PKBDTABLES keyLayout )
switch( Type )
{
case 0:
if( Code == VK_RSHIFT )
if( Code == VK_SHIFT )
Code = VK_LSHIFT;
if( Code == VK_RMENU )
if( Code == VK_MENU )
Code = VK_LMENU;
if( Code == VK_RCONTROL )
if( Code == VK_CONTROL )
Code = VK_LCONTROL;
ret = VkToScan( Code, FALSE, keyLayout );
break;
@ -706,7 +719,7 @@ NtUserToUnicodeEx(
DECLARE_RETURN(int);
DPRINT("Enter NtUserSetKeyboardState\n");
UserEnterShared();//faxme: this syscall doesnt seem to need any locking...
UserEnterShared();//fixme: this syscall doesnt seem to need any locking...
if( !NT_SUCCESS(MmCopyFromCaller(KeyStateBuf,
@ -785,12 +798,22 @@ NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize )
if( lParam & (1<<25) )
{
CareVk = VkCode = ScanToVk( ScanCode, ExtKey, keyLayout );
if( VkCode == VK_LSHIFT || VkCode == VK_RSHIFT )
VkCode = VK_LSHIFT;
if( VkCode == VK_LCONTROL || VkCode == VK_RCONTROL )
VkCode = VK_LCONTROL;
if( VkCode == VK_LMENU || VkCode == VK_RMENU )
VkCode = VK_LMENU;
switch (VkCode)
{
case VK_RSHIFT:
ScanCode |= 0x100;
case VK_LSHIFT:
VkCode = VK_SHIFT;
break;
case VK_LCONTROL:
case VK_RCONTROL:
VkCode = VK_CONTROL;
break;
case VK_LMENU:
case VK_RMENU:
VkCode = VK_MENU;
break;
}
}
else
{