/*
- * ReactOS W32 Subsystem
- * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/* $Id$
- *
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window classes
/* INCLUDES ******************************************************************/
-#include <w32k.h>
+#include <win32k.h>
#include <ntddkbd.h>
#define NDEBUG
#include <debug.h>
extern BYTE gQueueKeyStateTable[];
+extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread);
/* GLOBALS *******************************************************************/
+PTHREADINFO ptiRawInput;
+PTHREADINFO ptiKeyboard;
+PTHREADINFO ptiMouse;
+PKTIMER MasterTimer = NULL;
+PATTACHINFO gpai = NULL;
static HANDLE MouseDeviceHandle;
static HANDLE MouseThreadHandle;
static HANDLE KeyboardThreadHandle;
static CLIENT_ID KeyboardThreadId;
static HANDLE KeyboardDeviceHandle;
+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 *****************************************************************/
-ULONG FASTCALL
-IntSystemParametersInfo(UINT uiAction, UINT uiParam,PVOID pvParam, UINT fWinIni);
DWORD IntLastInputTick(BOOL LastInputTickSetGet);
#define ClearMouseInput(mi) \
}
BOOL
-STDCALL
+APIENTRY
NtUserGetLastInputInfo(PLASTINPUTINFO plii)
{
BOOL ret = TRUE;
UserEnterShared();
- _SEH_TRY
+ _SEH2_TRY
{
if (ProbeForReadUint(&plii->cbSize) != sizeof(LASTINPUTINFO))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
ret = FALSE;
- _SEH_LEAVE;
+ _SEH2_LEAVE;
}
ProbeForWrite(plii, sizeof(LASTINPUTINFO), sizeof(DWORD));
plii->dwTime = IntLastInputTick(FALSE);
}
- _SEH_HANDLE
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
- SetLastNtError(_SEH_GetExceptionCode());
+ SetLastNtError(_SEH2_GetExceptionCode());
ret = FALSE;
}
- _SEH_END;
+ _SEH2_END;
UserLeave();
mi.dx += mid->LastX;
mi.dy += mid->LastY;
+ /* Check if the mouse move is absolute */
+ if (mid->Flags == MOUSE_MOVE_ABSOLUTE)
+ {
+ /* Set flag to convert to screen location */
+ mi.dwFlags |= MOUSEEVENTF_ABSOLUTE;
+ }
+
if(mid->ButtonFlags)
{
if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_DOWN)
-VOID STDCALL
+VOID APIENTRY
MouseThreadMain(PVOID StartContext)
{
UNICODE_STRING MouseDeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
OBJECT_ATTRIBUTES MouseObjectAttributes;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
+ MOUSE_ATTRIBUTES MouseAttr;
+
+ Status = Win32kInitWin32Thread(PsGetCurrentThread());
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed making keyboard thread a win32 thread.\n");
+ return; //(Status);
+ }
+
+ KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
+ LOW_REALTIME_PRIORITY + 3);
InitializeObjectAttributes(&MouseObjectAttributes,
&MouseDeviceName,
FILE_SYNCHRONOUS_IO_ALERT);
} while (!NT_SUCCESS(Status));
+ /* Need to setup basic win32k for this thread to process WH_MOUSE_LL messages. */
+ Status = Win32kInitWin32Thread(PsGetCurrentThread());
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed making mouse thread a win32 thread.\n");
+ return; //(Status);
+ }
+
+ ptiMouse = PsGetCurrentThreadWin32Thread();
+ ptiMouse->TIF_flags |= TIF_SYSTEMTHREAD;
+ DPRINT1("\nMouse Thread 0x%x \n", ptiMouse);
+
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
NULL);
DPRINT("Mouse Input Thread Starting...\n");
+ /*FIXME: Does mouse attributes need to be used for anything */
+ Status = NtDeviceIoControlFile(MouseDeviceHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ IOCTL_MOUSE_QUERY_ATTRIBUTES,
+ &MouseAttr, sizeof(MOUSE_ATTRIBUTES),
+ NULL, 0);
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT("Failed to get mouse attributes\n");
+ }
+
/*
* Receive and process mouse input.
*/
/* Returns a value that indicates if the key is a modifier key, and
* which one.
*/
-static UINT STDCALL
+static UINT APIENTRY
IntKeyboardGetModifiers(KEYBOARD_INPUT_DATA *InputData)
{
if (InputData->Flags & KEY_E1)
/* Asks the keyboard driver to send a small table that shows which
* lights should connect with which scancodes
*/
-static NTSTATUS STDCALL
+static NTSTATUS APIENTRY
IntKeyboardGetIndicatorTrans(HANDLE KeyboardDeviceHandle,
PKEYBOARD_INDICATOR_TRANSLATION *IndicatorTrans)
{
if (Status != STATUS_BUFFER_TOO_SMALL)
break;
- ExFreePool(Ret);
+ ExFreePoolWithTag(Ret, TAG_KEYBOARD);
Size += sizeof(KEYBOARD_INDICATOR_TRANSLATION);
if (Status != STATUS_SUCCESS)
{
- ExFreePool(Ret);
+ ExFreePoolWithTag(Ret, TAG_KEYBOARD);
return Status;
}
/* Sends the keyboard commands to turn on/off the lights.
*/
-static NTSTATUS STDCALL
+static NTSTATUS APIENTRY
IntKeyboardUpdateLeds(HANDLE KeyboardDeviceHandle,
PKEYBOARD_INPUT_DATA KeyInput,
PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans)
return STATUS_SUCCESS;
}
-static VOID STDCALL
+static VOID APIENTRY
IntKeyboardSendWinKeyMsg()
{
- PWINDOW_OBJECT Window;
+ PWND Window;
MSG Mesg;
if (!(Window = UserGetWindowObject(InputWindowStation->ShellWindow)))
Mesg.lParam = 0;
/* The QS_HOTKEY is just a guess */
- MsqPostMessage(Window->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
+ MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
}
-static VOID STDCALL
+static VOID APIENTRY
co_IntKeyboardSendAltKeyMsg()
{
co_MsqPostKeyboardMessage(WM_SYSCOMMAND,SC_KEYMENU,0);
}
-static VOID STDCALL
+static VOID APIENTRY
KeyboardThreadMain(PVOID StartContext)
{
UNICODE_STRING KeyboardDeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
MSG msg;
PUSER_MESSAGE_QUEUE FocusQueue;
struct _ETHREAD *FocusThread;
- extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread);
PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans = NULL;
UINT ModifierState = 0;
return; //(Status);
}
+ ptiKeyboard = PsGetCurrentThreadWin32Thread();
+ ptiKeyboard->TIF_flags |= TIF_SYSTEMTHREAD;
+ DPRINT1("\nKeyboard Thread 0x%x \n", ptiKeyboard);
+
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
for (;NumKeys;memcpy(&KeyInput, &NextKeyInput, sizeof(KeyInput)),
NumKeys--)
{
+ PKBL keyboardLayout = NULL;
lParam = 0;
IntKeyboardUpdateLeds(KeyboardDeviceHandle,
}
else
{
- RepeatCount = 0;
+ RepeatCount = 1;
LastFlags = KeyInput.Flags & (KEY_E0 | KEY_E1);
LastMakeCode = KeyInput.MakeCode;
}
}
/* Find the target thread whose locale is in effect */
- FocusQueue = IntGetFocusMessageQueue();
-
- /* This might cause us to lose hot keys, which are important
- * (ctrl-alt-del secure attention sequence). Not sure if it
- * can happen though.
- */
- if (!FocusQueue)
- continue;
+ FocusQueue = IntGetFocusMessageQueue();
- msg.lParam = lParam;
- msg.hwnd = FocusQueue->FocusWindow;
+ if (FocusQueue)
+ {
+ msg.hwnd = FocusQueue->FocusWindow;
- FocusThread = FocusQueue->Thread;
+ FocusThread = FocusQueue->Thread;
+ if (FocusThread && FocusThread->Tcb.Win32Thread)
+ {
+ keyboardLayout = ((PTHREADINFO)FocusThread->Tcb.Win32Thread)->KeyboardLayout;
+ }
+ }
+ if (!keyboardLayout)
+ {
+ keyboardLayout = W32kGetDefaultKeyLayout();
+ }
- if (!(FocusThread && FocusThread->Tcb.Win32Thread &&
- ((PTHREADINFO)FocusThread->Tcb.Win32Thread)->KeyboardLayout))
- continue;
+ msg.lParam = lParam;
/* This function uses lParam to fill wParam according to the
* keyboard layout in use.
*/
W32kKeyProcessMessage(&msg,
- ((PTHREADINFO)FocusThread->Tcb.Win32Thread)->KeyboardLayout->KBTables,
+ keyboardLayout->KBTables,
KeyInput.Flags & KEY_E0 ? 0xE0 :
(KeyInput.Flags & KEY_E1 ? 0xE1 : 0));
continue; /* Eat key up motion too */
}
+ if (!FocusQueue)
+ {
+ /* There is no focused window to receive a keyboard message */
+ continue;
+ }
/*
* Post a keyboard message.
*/
}
-NTSTATUS FASTCALL
+static PVOID Objects[2];
+/*
+ Raw Input Thread.
+ Since this relies on InputThreadsStart, just fake it.
+ */
+static VOID APIENTRY
+RawInputThreadMain(PVOID StartContext)
+{
+ NTSTATUS Status;
+ LARGE_INTEGER DueTime;
+
+ DueTime.QuadPart = (LONGLONG)(-10000000);
+
+ do
+ {
+ KEVENT Event;
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
+ } while (!NT_SUCCESS(Status));
+
+
+ Objects[0] = &InputThreadsStart;
+ Objects[1] = MasterTimer;
+
+ // This thread requires win32k!
+ Status = Win32kInitWin32Thread(PsGetCurrentThread());
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed making Raw Input thread a win32 thread.\n");
+ return; //(Status);
+ }
+
+ ptiRawInput = PsGetCurrentThreadWin32Thread();
+ ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD;
+ DPRINT1("\nRaw Input Thread 0x%x \n", ptiRawInput);
+
+ KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
+ LOW_REALTIME_PRIORITY + 3);
+
+ UserEnterExclusive();
+ StartTheTimers();
+ UserLeave();
+
+ //
+ // ATM, we just have one job to handle, merge the other two later.
+ //
+ for(;;)
+ {
+ DPRINT( "Raw Input Thread Waiting for start event\n" );
+
+ Status = KeWaitForMultipleObjects( 2,
+ Objects,
+ WaitAll, //WaitAny,
+ WrUserRequest,
+ KernelMode,
+ TRUE,
+ NULL,
+ NULL);
+ DPRINT( "Raw Input Thread Starting...\n" );
+
+ ProcessTimers();
+ }
+ DPRINT1("Raw Input Thread Exit!\n");
+}
+
+INIT_FUNCTION
+NTSTATUS
+NTAPI
InitInputImpl(VOID)
{
NTSTATUS Status;
KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
+ MasterTimer = ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), TAG_INPUT);
+ if (!MasterTimer)
+ {
+ DPRINT1("Win32K: Failed making Raw Input thread a win32 thread.\n");
+ ASSERT(FALSE);
+ return STATUS_UNSUCCESSFUL;
+ }
+ KeInitializeTimer(MasterTimer);
+
/* Initialize the default keyboard layout */
if(!UserInitDefaultKeyboardLayout())
{
DPRINT1("Failed to initialize default keyboard layout!\n");
}
+ Status = PsCreateSystemThread(&RawInputThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ NULL,
+ &RawInputThreadId,
+ RawInputThreadMain,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed to create raw thread.\n");
+ }
+
Status = PsCreateSystemThread(&KeyboardThreadHandle,
THREAD_ALL_ACCESS,
NULL,
}
BOOL
-STDCALL
+APIENTRY
NtUserDragDetect(
HWND hWnd,
POINT pt) // Just like the User call.
PTHREADINFO OldBlock;
ASSERT(W32Thread);
- if(!W32Thread->Desktop || (W32Thread->IsExiting && BlockIt))
+ if(!W32Thread->rpdesk || ((W32Thread->TIF_flags & TIF_INCLEANUP) && BlockIt))
{
/*
* fail blocking if exiting the thread
* e.g. services running in the service window station cannot block input
*/
if(!ThreadHasInputAccess(W32Thread) ||
- !IntIsActiveDesktop(W32Thread->Desktop))
+ !IntIsActiveDesktop(W32Thread->rpdesk))
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
- ASSERT(W32Thread->Desktop);
- OldBlock = W32Thread->Desktop->BlockInputThread;
+ ASSERT(W32Thread->rpdesk);
+ OldBlock = W32Thread->rpdesk->BlockInputThread;
if(OldBlock)
{
if(OldBlock != W32Thread)
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
}
- W32Thread->Desktop->BlockInputThread = (BlockIt ? W32Thread : NULL);
+ W32Thread->rpdesk->BlockInputThread = (BlockIt ? W32Thread : NULL);
return OldBlock == NULL;
}
- W32Thread->Desktop->BlockInputThread = (BlockIt ? W32Thread : NULL);
+ W32Thread->rpdesk->BlockInputThread = (BlockIt ? W32Thread : NULL);
return OldBlock == NULL;
}
BOOL
-STDCALL
+APIENTRY
NtUserBlockInput(
BOOL BlockIt)
{
END_CLEANUP;
}
-BOOL FASTCALL
-IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject, BOOL Swap)
-{
- PSYSTEM_CURSORINFO CurInfo;
- BOOL res;
-
- CurInfo = IntGetSysCursorInfo(WinStaObject);
- res = CurInfo->SwapButtons;
- CurInfo->SwapButtons = Swap;
- return res;
-}
-
BOOL FASTCALL
IntMouseInput(MOUSEINPUT *mi)
{
const UINT SwapBtnMsg[2][2] =
{
- {
- WM_LBUTTONDOWN, WM_RBUTTONDOWN
- },
+ {WM_LBUTTONDOWN, WM_RBUTTONDOWN},
{WM_LBUTTONUP, WM_RBUTTONUP}
};
const WPARAM SwapBtn[2] =
{
MK_LBUTTON, MK_RBUTTON
};
- POINT MousePos = {0}, OrgPos;
+ POINT MousePos;
PSYSTEM_CURSORINFO CurInfo;
- PWINSTATION_OBJECT WinSta;
- BOOL DoMove, SwapButtons;
+ BOOL SwapButtons;
MSG Msg;
- HBITMAP hBitmap;
- BITMAPOBJ *BitmapObj;
- SURFOBJ *SurfObj;
- PDC dc;
- PWINDOW_OBJECT DesktopWindow;
-
-#if 1
-
- HDC hDC;
-
- /* FIXME - get the screen dc from the window station or desktop */
- if(!(hDC = IntGetScreenDC()))
- {
- return FALSE;
- }
-#endif
ASSERT(mi);
-#if 0
-
- WinSta = PsGetCurrentProcessWin32Process()->WindowStation;
-#else
- /* FIXME - ugly hack but as long as we're using this dumb callback from the
- mouse class driver, we can't access the window station from the calling
- process */
- WinSta = InputWindowStation;
-#endif
-
- ASSERT(WinSta);
- CurInfo = IntGetSysCursorInfo(WinSta);
+ CurInfo = IntGetSysCursorInfo();
if(!mi->time)
{
mi->time = MsqCalculateMessageTime(&LargeTickCount);
}
- SwapButtons = CurInfo->SwapButtons;
- DoMove = FALSE;
+ SwapButtons = gspv.bMouseBtnSwap;
- IntGetCursorLocation(WinSta, &MousePos);
- OrgPos.x = MousePos.x;
- OrgPos.y = MousePos.y;
+ MousePos = gpsi->ptCursor;
if(mi->dwFlags & MOUSEEVENTF_MOVE)
{
if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
{
- MousePos.x = mi->dx;
- MousePos.y = mi->dy;
+ MousePos.x = mi->dx * UserGetSystemMetrics(SM_CXVIRTUALSCREEN) >> 16;
+ MousePos.y = mi->dy * UserGetSystemMetrics(SM_CYVIRTUALSCREEN) >> 16;
}
else
{
MousePos.x += mi->dx;
MousePos.y += mi->dy;
}
-
- DesktopWindow = IntGetWindowObject(WinSta->ActiveDesktop->DesktopWindow);
-
- if (DesktopWindow)
- {
- if(MousePos.x >= DesktopWindow->Wnd->ClientRect.right)
- MousePos.x = DesktopWindow->Wnd->ClientRect.right - 1;
- if(MousePos.y >= DesktopWindow->Wnd->ClientRect.bottom)
- MousePos.y = DesktopWindow->Wnd->ClientRect.bottom - 1;
- UserDereferenceObject(DesktopWindow);
- }
-
- if(MousePos.x < 0)
- MousePos.x = 0;
- if(MousePos.y < 0)
- MousePos.y = 0;
-
- if(CurInfo->CursorClipInfo.IsClipped)
- {
- /* The mouse cursor needs to be clipped */
-
- if(MousePos.x >= (LONG)CurInfo->CursorClipInfo.Right)
- MousePos.x = (LONG)CurInfo->CursorClipInfo.Right;
- if(MousePos.x < (LONG)CurInfo->CursorClipInfo.Left)
- MousePos.x = (LONG)CurInfo->CursorClipInfo.Left;
- if(MousePos.y >= (LONG)CurInfo->CursorClipInfo.Bottom)
- MousePos.y = (LONG)CurInfo->CursorClipInfo.Bottom;
- if(MousePos.y < (LONG)CurInfo->CursorClipInfo.Top)
- MousePos.y = (LONG)CurInfo->CursorClipInfo.Top;
- }
-
- DoMove = (MousePos.x != OrgPos.x || MousePos.y != OrgPos.y);
- }
-
- if (DoMove)
- {
- dc = DC_LockDc(hDC);
- if (dc)
- {
- hBitmap = dc->w.hBitmap;
- DC_UnlockDc(dc);
-
- BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
- if (BitmapObj)
- {
- SurfObj = &BitmapObj->SurfObj;
-
- if (CurInfo->ShowingCursor)
- {
- IntEngMovePointer(SurfObj, MousePos.x, MousePos.y, &(GDIDEV(SurfObj)->Pointer.Exclude));
- }
- /* Only now, update the info in the GDIDEVICE, so EngMovePointer can
- * use the old values to move the pointer image */
- GDIDEV(SurfObj)->Pointer.Pos.x = MousePos.x;
- GDIDEV(SurfObj)->Pointer.Pos.y = MousePos.y;
-
- BITMAPOBJ_UnlockBitmap(BitmapObj);
- }
- }
}
/*
* Insert the messages into the system queue
*/
-
- Msg.wParam = CurInfo->ButtonsDown;
+ Msg.wParam = 0;
Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y);
Msg.pt = MousePos;
- if(DoMove)
+
+ if (gQueueKeyStateTable[VK_SHIFT] & 0xc0)
+ {
+ Msg.wParam |= MK_SHIFT;
+ }
+
+ if (gQueueKeyStateTable[VK_CONTROL] & 0xc0)
{
- Msg.message = WM_MOUSEMOVE;
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= MK_CONTROL;
}
- Msg.message = 0;
+ if(mi->dwFlags & MOUSEEVENTF_MOVE)
+ {
+ UserSetCursorPos(MousePos.x, MousePos.y, TRUE);
+ }
if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN)
{
gQueueKeyStateTable[VK_LBUTTON] |= 0xc0;
Msg.message = SwapBtnMsg[0][SwapButtons];
CurInfo->ButtonsDown |= SwapBtn[SwapButtons];
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ MsqInsertMouseMessage(&Msg);
}
else if(mi->dwFlags & MOUSEEVENTF_LEFTUP)
{
gQueueKeyStateTable[VK_LBUTTON] &= ~0x80;
Msg.message = SwapBtnMsg[1][SwapButtons];
CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons];
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ MsqInsertMouseMessage(&Msg);
}
if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
{
gQueueKeyStateTable[VK_MBUTTON] |= 0xc0;
Msg.message = WM_MBUTTONDOWN;
CurInfo->ButtonsDown |= MK_MBUTTON;
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ MsqInsertMouseMessage(&Msg);
}
else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
{
gQueueKeyStateTable[VK_MBUTTON] &= ~0x80;
Msg.message = WM_MBUTTONUP;
CurInfo->ButtonsDown &= ~MK_MBUTTON;
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ MsqInsertMouseMessage(&Msg);
}
if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN)
{
gQueueKeyStateTable[VK_RBUTTON] |= 0xc0;
Msg.message = SwapBtnMsg[0][!SwapButtons];
CurInfo->ButtonsDown |= SwapBtn[!SwapButtons];
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ MsqInsertMouseMessage(&Msg);
}
else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP)
{
gQueueKeyStateTable[VK_RBUTTON] &= ~0x80;
Msg.message = SwapBtnMsg[1][!SwapButtons];
CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons];
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ MsqInsertMouseMessage(&Msg);
}
if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) &&
if(mi->mouseData & XBUTTON1)
{
gQueueKeyStateTable[VK_XBUTTON1] |= 0xc0;
+ CurInfo->ButtonsDown |= MK_XBUTTON1;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
- CurInfo->ButtonsDown |= XBUTTON1;
- MsqInsertSystemMessage(&Msg);
+ MsqInsertMouseMessage(&Msg);
}
if(mi->mouseData & XBUTTON2)
{
gQueueKeyStateTable[VK_XBUTTON2] |= 0xc0;
+ CurInfo->ButtonsDown |= MK_XBUTTON2;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
- CurInfo->ButtonsDown |= XBUTTON2;
- MsqInsertSystemMessage(&Msg);
+ MsqInsertMouseMessage(&Msg);
}
}
else if(mi->dwFlags & MOUSEEVENTF_XUP)
if(mi->mouseData & XBUTTON1)
{
gQueueKeyStateTable[VK_XBUTTON1] &= ~0x80;
+ CurInfo->ButtonsDown &= ~MK_XBUTTON1;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
- CurInfo->ButtonsDown &= ~XBUTTON1;
- MsqInsertSystemMessage(&Msg);
+ MsqInsertMouseMessage(&Msg);
}
if(mi->mouseData & XBUTTON2)
{
gQueueKeyStateTable[VK_XBUTTON2] &= ~0x80;
+ CurInfo->ButtonsDown &= ~MK_XBUTTON2;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
- CurInfo->ButtonsDown &= ~XBUTTON2;
- MsqInsertSystemMessage(&Msg);
+ MsqInsertMouseMessage(&Msg);
}
}
if(mi->dwFlags & MOUSEEVENTF_WHEEL)
{
Msg.message = WM_MOUSEWHEEL;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData);
- MsqInsertSystemMessage(&Msg);
+ MsqInsertMouseMessage(&Msg);
}
return TRUE;
BOOL FASTCALL
IntKeyboardInput(KEYBDINPUT *ki)
{
- return FALSE;
+ PUSER_MESSAGE_QUEUE FocusMessageQueue;
+ 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. */
+ Msg.pt = gpsi->ptCursor;
+
+ 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))
+ {
+ DPRINT1("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->pDeskInfo->LastInputWasKbd = TRUE;
+
+ Msg.pt = gpsi->ptCursor;
+
+ MsqPostMessage(FocusMessageQueue, &Msg, FALSE, QS_KEY);
+ }
+ else
+ {
+ DPRINT("Invalid focus window handle\n");
+ }
+
+ if (Entered) UserLeave();
+
+ return TRUE;
+}
+
+BOOL FASTCALL
+UserAttachThreadInput( PTHREADINFO pti, PTHREADINFO ptiTo, BOOL fAttach)
+{
+ PATTACHINFO pai;
+
+ /* Can not be the same thread.*/
+ if (pti == ptiTo) return FALSE;
+
+ /* Do not attach to system threads or between different desktops. */
+ if ( pti->TIF_flags & TIF_DONTATTACHQUEUE ||
+ ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
+ pti->rpdesk != ptiTo->rpdesk )
+ return FALSE;
+
+ /* If Attach set, allocate and link. */
+ if ( fAttach )
+ {
+ pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), TAG_ATTACHINFO);
+ if ( !pai ) return FALSE;
+
+ pai->paiNext = gpai;
+ pai->pti1 = pti;
+ pai->pti2 = ptiTo;
+ gpai = pai;
+ }
+ else /* If clear, unlink and free it. */
+ {
+ PATTACHINFO paiprev = NULL;
+
+ if ( !gpai ) return FALSE;
+
+ pai = gpai;
+
+ /* Search list and free if found or return false. */
+ do
+ {
+ if ( pai->pti2 == ptiTo && pai->pti1 == pti ) break;
+ paiprev = pai;
+ pai = pai->paiNext;
+ } while (pai);
+
+ if ( !pai ) return FALSE;
+
+ if (paiprev) paiprev->paiNext = pai->paiNext;
+
+ ExFreePoolWithTag(pai, TAG_ATTACHINFO);
+ }
+
+ return TRUE;
}
UINT
-STDCALL
+APIENTRY
NtUserSendInput(
UINT nInputs,
LPINPUT pInput,
W32Thread = PsGetCurrentThreadWin32Thread();
ASSERT(W32Thread);
- if(!W32Thread->Desktop)
+ if(!W32Thread->rpdesk)
{
RETURN( 0);
}
* e.g. services running in the service window station cannot block input
*/
if(!ThreadHasInputAccess(W32Thread) ||
- !IntIsActiveDesktop(W32Thread->Desktop))
+ !IntIsActiveDesktop(W32Thread->rpdesk))
{
SetLastWin32Error(ERROR_ACCESS_DENIED);
RETURN( 0);