* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: input.c,v 1.33 2004/05/14 23:57:32 weiden Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* INCLUDES ******************************************************************/
#include <w32k.h>
-
-#include <rosrtl/string.h>
+#include <ddk/ntddkbd.h>
#define NDEBUG
#include <debug.h>
-/* GLOBALS *******************************************************************/
+extern BYTE gQueueKeyStateTable[];
-#define ENABLEMOUSEGDICALLBACK 1
+/* GLOBALS *******************************************************************/
static HANDLE MouseDeviceHandle;
-#if !ENABLEMOUSEGDICALLBACK
static HANDLE MouseThreadHandle;
static CLIENT_ID MouseThreadId;
-#endif
static HANDLE KeyboardThreadHandle;
static CLIENT_ID KeyboardThreadId;
static HANDLE KeyboardDeviceHandle;
/* FUNCTIONS *****************************************************************/
-#if !ENABLEMOUSEGDICALLBACK
-VOID STDCALL_FUNC STATIC
+#define ClearMouseInput(mi) \
+ mi.dx = 0; \
+ mi.dy = 0; \
+ mi.mouseData = 0; \
+ mi.dwFlags = 0;
+
+#define SendMouseEvent(mi) \
+ if(mi.dx != 0 || mi.dy != 0) \
+ mi.dwFlags |= MOUSEEVENTF_MOVE; \
+ if(mi.dwFlags) \
+ IntMouseInput(&mi); \
+ ClearMouseInput(mi);
+
+VOID FASTCALL
+ProcessMouseInputData(PMOUSE_INPUT_DATA Data, ULONG InputCount)
+{
+ PMOUSE_INPUT_DATA mid;
+ MOUSEINPUT mi;
+ ULONG i;
+
+ ClearMouseInput(mi);
+ mi.time = 0;
+ mi.dwExtraInfo = 0;
+ for(i = 0; i < InputCount; i++)
+ {
+ mid = (Data + i);
+ mi.dx += mid->LastX;
+ mi.dy += mid->LastY;
+
+ if(mid->ButtonFlags)
+ {
+ if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_DOWN)
+ {
+ mi.dwFlags |= MOUSEEVENTF_LEFTDOWN;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_UP)
+ {
+ mi.dwFlags |= MOUSEEVENTF_LEFTUP;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN)
+ {
+ mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_UP)
+ {
+ mi.dwFlags |= MOUSEEVENTF_MIDDLEUP;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN)
+ {
+ mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_UP)
+ {
+ mi.dwFlags |= MOUSEEVENTF_RIGHTUP;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_BUTTON_4_DOWN)
+ {
+ mi.mouseData |= XBUTTON1;
+ mi.dwFlags |= MOUSEEVENTF_XDOWN;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_BUTTON_4_UP)
+ {
+ mi.mouseData |= XBUTTON1;
+ mi.dwFlags |= MOUSEEVENTF_XUP;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_BUTTON_5_DOWN)
+ {
+ mi.mouseData |= XBUTTON2;
+ mi.dwFlags |= MOUSEEVENTF_XDOWN;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_BUTTON_5_UP)
+ {
+ mi.mouseData |= XBUTTON2;
+ mi.dwFlags |= MOUSEEVENTF_XUP;
+ SendMouseEvent(mi);
+ }
+ if(mid->ButtonFlags & MOUSE_WHEEL)
+ {
+ mi.mouseData = mid->ButtonData;
+ mi.dwFlags |= MOUSEEVENTF_WHEEL;
+ SendMouseEvent(mi);
+ }
+ }
+ }
+
+ SendMouseEvent(mi);
+}
+
+VOID STDCALL
MouseThreadMain(PVOID StartContext)
{
- UNICODE_STRING MouseDeviceName;
- OBJECT_ATTRIBUTES MouseObjectAttributes;
- IO_STATUS_BLOCK Iosb;
- NTSTATUS Status;
-
- RtlRosInitUnicodeStringFromLiteral(&MouseDeviceName, L"\\??\\Mouse"); /* FIXME - does win use the same? */
- InitializeObjectAttributes(&MouseObjectAttributes,
- &MouseDeviceName,
- 0,
+ UNICODE_STRING MouseDeviceName = RTL_CONSTANT_STRING(L"\\Device\\PointerClass0");
+ OBJECT_ATTRIBUTES MouseObjectAttributes;
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
+
+ InitializeObjectAttributes(&MouseObjectAttributes,
+ &MouseDeviceName,
+ 0,
+ NULL,
+ NULL);
+ do
+ {
+ LARGE_INTEGER DueTime;
+ KEVENT Event;
+ DueTime.QuadPart = (LONGLONG)(-10000000);
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
+ Status = NtOpenFile(&MouseDeviceHandle,
+ FILE_ALL_ACCESS,
+ &MouseObjectAttributes,
+ &Iosb,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ } while (!NT_SUCCESS(Status));
+
+ for(;;)
+ {
+ /*
+ * Wait to start input.
+ */
+ DPRINT("Mouse Input Thread Waiting for start event\n");
+ Status = KeWaitForSingleObject(&InputThreadsStart,
+ 0,
+ KernelMode,
+ TRUE,
+ NULL);
+ DPRINT("Mouse Input Thread Starting...\n");
+
+ /*
+ * Receive and process mouse input.
+ */
+ while(InputThreadsRunning)
+ {
+ MOUSE_INPUT_DATA MouseInput;
+ Status = NtReadFile(MouseDeviceHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ &MouseInput,
+ sizeof(MOUSE_INPUT_DATA),
NULL,
NULL);
- Status = NtOpenFile(&MouseDeviceHandle,
- FILE_ALL_ACCESS,
- &MouseObjectAttributes,
- &Iosb,
- 0,
- FILE_SYNCHRONOUS_IO_ALERT);
- if(!NT_SUCCESS(Status))
- {
- DPRINT1("Win32K: Failed to open mouse.\n");
- return; //(Status);
- }
-
- for(;;)
- {
- /*
- * Wait to start input.
- */
- DPRINT("Mouse Input Thread Waiting for start event\n");
- Status = KeWaitForSingleObject(&InputThreadsStart,
- 0,
- KernelMode,
- TRUE,
- NULL);
- DPRINT("Mouse Input Thread Starting...\n");
-
- /*
- * Receive and process keyboard input.
- */
- while(InputThreadsRunning)
- {
- MOUSE_INPUT_DATA MouseInput;
- Status = NtReadFile(MouseDeviceHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- &MouseInput,
- sizeof(MOUSE_INPUT_DATA),
- NULL,
- NULL);
- if(Status == STATUS_ALERTED && !InputThreadsRunning)
+ if(Status == STATUS_ALERTED && !InputThreadsRunning)
+ {
+ break;
+ }
+ if(Status == STATUS_PENDING)
+ {
+ NtWaitForSingleObject(MouseDeviceHandle, FALSE, NULL);
+ Status = Iosb.Status;
+ }
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed to read from mouse.\n");
+ return; //(Status);
+ }
+ DPRINT("MouseEvent\n");
+
+ UserEnterExclusive();
+
+ ProcessMouseInputData(&MouseInput, Iosb.Information / sizeof(MOUSE_INPUT_DATA));
+
+ UserLeave();
+ }
+ DPRINT("Mouse Input Thread Stopped...\n");
+ }
+}
+
+/* Returns a value that indicates if the key is a modifier key, and
+ * which one.
+ */
+STATIC UINT STDCALL
+IntKeyboardGetModifiers(KEYBOARD_INPUT_DATA *InputData)
+{
+ if (InputData->Flags & KEY_E1)
+ return 0;
+
+ if (!(InputData->Flags & KEY_E0))
+ {
+ switch (InputData->MakeCode)
{
- break;
+ case 0x2a: /* left shift */
+ case 0x36: /* right shift */
+ return MOD_SHIFT;
+
+ case 0x1d: /* left control */
+ return MOD_CONTROL;
+
+ case 0x38: /* left alt */
+ return MOD_ALT;
+
+ default:
+ return 0;
}
- if(Status == STATUS_PENDING)
+ }
+ else
+ {
+ switch (InputData->MakeCode)
{
- NtWaitForSingleObject(MouseDeviceHandle, FALSE, NULL);
- Status = Iosb.Status;
+ case 0x1d: /* right control */
+ return MOD_CONTROL;
+
+ case 0x38: /* right alt */
+ return MOD_ALT;
+
+ case 0x5b: /* left gui (windows) */
+ case 0x5c: /* right gui (windows) */
+ return MOD_WIN;
+
+ default:
+ return 0;
}
- if(!NT_SUCCESS(Status))
+ }
+}
+
+/* Asks the keyboard driver to send a small table that shows which
+ * lights should connect with which scancodes
+ */
+STATIC NTSTATUS STDCALL
+IntKeyboardGetIndicatorTrans(HANDLE KeyboardDeviceHandle,
+ PKEYBOARD_INDICATOR_TRANSLATION *IndicatorTrans)
+{
+ NTSTATUS Status;
+ DWORD Size = 0;
+ IO_STATUS_BLOCK Block;
+ PKEYBOARD_INDICATOR_TRANSLATION Ret;
+
+ Size = sizeof(KEYBOARD_INDICATOR_TRANSLATION);
+
+ Ret = ExAllocatePoolWithTag(PagedPool,
+ Size,
+ TAG_KEYBOARD);
+
+ while (Ret)
+ {
+ Status = NtDeviceIoControlFile(KeyboardDeviceHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Block,
+ IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION,
+ NULL, 0,
+ Ret, Size);
+
+ if (Status != STATUS_BUFFER_TOO_SMALL)
+ break;
+
+ ExFreePool(Ret);
+
+ Size += sizeof(KEYBOARD_INDICATOR_TRANSLATION);
+
+ Ret = ExAllocatePoolWithTag(PagedPool,
+ Size,
+ TAG_KEYBOARD);
+ }
+
+ if (!Ret)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ if (Status != STATUS_SUCCESS)
+ {
+ ExFreePool(Ret);
+ return Status;
+ }
+
+ *IndicatorTrans = Ret;
+ return Status;
+}
+
+/* Sends the keyboard commands to turn on/off the lights.
+ */
+STATIC NTSTATUS STDCALL
+IntKeyboardUpdateLeds(HANDLE KeyboardDeviceHandle,
+ PKEYBOARD_INPUT_DATA KeyInput,
+ PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans)
+{
+ NTSTATUS Status;
+ UINT Count;
+ static KEYBOARD_INDICATOR_PARAMETERS Indicators;
+ IO_STATUS_BLOCK Block;
+
+ if (!IndicatorTrans)
+ return STATUS_NOT_SUPPORTED;
+
+ if (KeyInput->Flags & (KEY_E0 | KEY_E1 | KEY_BREAK))
+ return STATUS_SUCCESS;
+
+ for (Count = 0; Count < IndicatorTrans->NumberOfIndicatorKeys; Count++)
+ {
+ if (KeyInput->MakeCode == IndicatorTrans->IndicatorList[Count].MakeCode)
{
- DPRINT1("Win32K: Failed to read from mouse.\n");
- return; //(Status);
+ Indicators.LedFlags ^=
+ IndicatorTrans->IndicatorList[Count].IndicatorFlags;
+
+ /* Update the lights on the hardware */
+
+ Status = NtDeviceIoControlFile(KeyboardDeviceHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Block,
+ IOCTL_KEYBOARD_SET_INDICATORS,
+ &Indicators, sizeof(Indicators),
+ NULL, 0);
+
+ return Status;
}
- DPRINT("MouseEvent\n");
-
- MouseGDICallBack(&MouseInput, sizeof(MOUSE_INPUT_DATA));
- }
- DPRINT("Mouse Input Thread Stopped...\n");
- }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+STATIC VOID STDCALL
+IntKeyboardSendWinKeyMsg()
+{
+ PWINDOW_OBJECT Window;
+ MSG Mesg;
+
+ if (!(Window = UserGetWindowObject(InputWindowStation->ShellWindow)))
+ {
+ DPRINT1("Couldn't find window to send Windows key message!\n");
+ return;
+ }
+
+ Mesg.hwnd = InputWindowStation->ShellWindow;
+ Mesg.message = WM_SYSCOMMAND;
+ Mesg.wParam = SC_TASKLIST;
+ Mesg.lParam = 0;
+
+ /* The QS_HOTKEY is just a guess */
+ MsqPostMessage(Window->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
+}
+
+STATIC VOID STDCALL
+co_IntKeyboardSendAltKeyMsg()
+{
+ co_MsqPostKeyboardMessage(WM_SYSCOMMAND,SC_KEYMENU,0);
}
-#endif
STATIC VOID STDCALL
KeyboardThreadMain(PVOID StartContext)
{
- UNICODE_STRING KeyboardDeviceName;
- OBJECT_ATTRIBUTES KeyboardObjectAttributes;
- IO_STATUS_BLOCK Iosb;
- NTSTATUS Status;
- MSG msg;
- PUSER_MESSAGE_QUEUE FocusQueue;
- struct _ETHREAD *FocusThread;
-
- RtlRosInitUnicodeStringFromLiteral(&KeyboardDeviceName, L"\\??\\Keyboard");
- InitializeObjectAttributes(&KeyboardObjectAttributes,
- &KeyboardDeviceName,
- 0,
- NULL,
- NULL);
- Status = NtOpenFile(&KeyboardDeviceHandle,
- FILE_ALL_ACCESS,
- &KeyboardObjectAttributes,
- &Iosb,
- 0,
- FILE_SYNCHRONOUS_IO_ALERT);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Win32K: Failed to open keyboard.\n");
+ UNICODE_STRING KeyboardDeviceName = RTL_CONSTANT_STRING(L"\\Device\\KeyboardClass0");
+ OBJECT_ATTRIBUTES KeyboardObjectAttributes;
+ IO_STATUS_BLOCK Iosb;
+ NTSTATUS Status;
+ MSG msg;
+ PUSER_MESSAGE_QUEUE FocusQueue;
+ struct _ETHREAD *FocusThread;
+ extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread);
+
+ PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans = NULL;
+ UINT ModifierState = 0;
+ USHORT LastMakeCode = 0;
+ USHORT LastFlags = 0;
+ UINT RepeatCount = 0;
+
+ InitializeObjectAttributes(&KeyboardObjectAttributes,
+ &KeyboardDeviceName,
+ 0,
+ NULL,
+ NULL);
+ do
+ {
+ LARGE_INTEGER DueTime;
+ KEVENT Event;
+ DueTime.QuadPart = (LONGLONG)(-10000000);
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, &DueTime);
+ Status = NtOpenFile(&KeyboardDeviceHandle,
+ FILE_ALL_ACCESS,
+ &KeyboardObjectAttributes,
+ &Iosb,
+ 0,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ } while (!NT_SUCCESS(Status));
+
+ /* Not sure if converting this thread to a win32 thread is such
+ a great idea. Since we're posting keyboard messages to the focus
+ window message queue, we'll be (indirectly) doing sendmessage
+ stuff from this thread (for WH_KEYBOARD_LL processing), which
+ means we need our own message queue. If keyboard messages were
+ instead queued to the system message queue, the thread removing
+ the message from the system message queue would be responsible
+ for WH_KEYBOARD_LL processing and we wouldn't need this thread
+ to be a win32 thread. */
+ Status = Win32kInitWin32Thread(PsGetCurrentThread());
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed making keyboard thread a win32 thread.\n");
return; //(Status);
- }
+ }
+
+ IntKeyboardGetIndicatorTrans(KeyboardDeviceHandle,
+ &IndicatorTrans);
- for (;;)
- {
+ for (;;)
+ {
/*
* Wait to start input.
*/
DPRINT( "Keyboard Input Thread Waiting for start event\n" );
Status = KeWaitForSingleObject(&InputThreadsStart,
- 0,
- KernelMode,
- TRUE,
- NULL);
+ 0,
+ KernelMode,
+ TRUE,
+ NULL);
DPRINT( "Keyboard Input Thread Starting...\n" );
/*
* Receive and process keyboard input.
*/
while (InputThreadsRunning)
- {
- KEY_EVENT_RECORD KeyEvent;
- LPARAM lParam = 0;
- UINT fsModifiers;
- struct _ETHREAD *Thread;
- HWND hWnd;
- int id;
-
- Status = NtReadFile (KeyboardDeviceHandle,
- NULL,
- NULL,
- NULL,
- &Iosb,
- &KeyEvent,
- sizeof(KEY_EVENT_RECORD),
- NULL,
- NULL);
- DPRINT( "KeyRaw: %s %04x\n",
- KeyEvent.bKeyDown ? "down" : "up",
- KeyEvent.wVirtualScanCode );
-
- if (Status == STATUS_ALERTED && !InputThreadsRunning)
- {
- break;
- }
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Win32K: Failed to read from keyboard.\n");
- return; //(Status);
- }
-
- DPRINT( "Key: %s\n", KeyEvent.bKeyDown ? "down" : "up" );
-
- fsModifiers = 0;
- if (KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
- fsModifiers |= MOD_ALT;
-
- if (KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
- fsModifiers |= MOD_CONTROL;
-
- if (KeyEvent.dwControlKeyState & SHIFT_PRESSED)
- fsModifiers |= MOD_SHIFT;
-
- /* FIXME: Support MOD_WIN */
-
- lParam = KeyEvent.wRepeatCount |
- ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0x40000000;
-
- /* Bit 24 indicates if this is an extended key */
- if (KeyEvent.dwControlKeyState & ENHANCED_KEY)
- {
- lParam |= (1 << 24);
- }
-
- if (fsModifiers & MOD_ALT)
- {
- /* Context mode. 1 if ALT if pressed while the key is pressed */
- lParam |= (1 << 29);
- }
-
- if(KeyEvent.bKeyDown && (fsModifiers & MOD_ALT))
- msg.message = WM_SYSKEYDOWN;
- else if(KeyEvent.bKeyDown)
- msg.message = WM_KEYDOWN;
- else if(fsModifiers & MOD_ALT)
- msg.message = WM_SYSKEYUP;
- else
- msg.message = WM_KEYUP;
-
- /* Find the target thread whose locale is in effect */
- if (!IntGetScreenDC())
- {
- FocusQueue = W32kGetPrimitiveMessageQueue();
- }
- else
- {
- FocusQueue = IntGetFocusMessageQueue();
- }
-
- if (!FocusQueue) continue;
-
- msg.wParam = KeyEvent.wVirtualKeyCode;
- msg.lParam = lParam;
- msg.hwnd = FocusQueue->FocusWindow;
-
- FocusThread = FocusQueue->Thread;
-
- if (FocusThread && FocusThread->Win32Thread &&
- FocusThread->Win32Thread->KeyboardLayout)
- {
- W32kKeyProcessMessage(&msg,
- FocusThread->Win32Thread->KeyboardLayout);
- }
- else
- continue;
-
- if (GetHotKey(InputWindowStation,
- fsModifiers,
- msg.wParam,
- &Thread,
- &hWnd,
- &id))
- {
- if (KeyEvent.bKeyDown)
- {
- DPRINT("Hot key pressed (hWnd %lx, id %d)\n", hWnd, id);
- MsqPostHotKeyMessage (Thread,
- hWnd,
- (WPARAM)id,
- MAKELPARAM((WORD)fsModifiers,
- (WORD)msg.wParam));
- }
- }
- else
- {
- /*
- * Post a keyboard message.
- */
- MsqPostKeyboardMessage(msg.message,msg.wParam,msg.lParam);
- }
- }
+ {
+ BOOLEAN NumKeys = 1;
+ KEYBOARD_INPUT_DATA KeyInput;
+ KEYBOARD_INPUT_DATA NextKeyInput;
+ LPARAM lParam = 0;
+ UINT fsModifiers, fsNextModifiers;
+ struct _ETHREAD *Thread;
+ HWND hWnd;
+ int id;
+
+ DPRINT("KeyInput @ %08x\n", &KeyInput);
+
+ Status = NtReadFile (KeyboardDeviceHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ &KeyInput,
+ sizeof(KEYBOARD_INPUT_DATA),
+ NULL,
+ NULL);
+
+ if(Status == STATUS_ALERTED && !InputThreadsRunning)
+ {
+ break;
+ }
+ if(Status == STATUS_PENDING)
+ {
+ NtWaitForSingleObject(KeyboardDeviceHandle, FALSE, NULL);
+ Status = Iosb.Status;
+ }
+ if(!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed to read from mouse.\n");
+ return; //(Status);
+ }
+
+ DPRINT("KeyRaw: %s %04x\n",
+ (KeyInput.Flags & KEY_BREAK) ? "up" : "down",
+ KeyInput.MakeCode );
+
+ if (Status == STATUS_ALERTED && !InputThreadsRunning)
+ break;
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed to read from keyboard.\n");
+ return; //(Status);
+ }
+
+ /* Update modifier state */
+ fsModifiers = IntKeyboardGetModifiers(&KeyInput);
+
+ if (fsModifiers)
+ {
+ if (KeyInput.Flags & KEY_BREAK)
+ {
+ ModifierState &= ~fsModifiers;
+ }
+ else
+ {
+ ModifierState |= fsModifiers;
+
+ if (ModifierState == fsModifiers &&
+ (fsModifiers == MOD_ALT || fsModifiers == MOD_WIN))
+ {
+ /* First send out special notifications
+ * (For alt, the message that turns on accelerator
+ * display, not sure what for win. Both TODO though.)
+ */
+
+ /* Read the next key before sending this one */
+ do
+ {
+ Status = NtReadFile (KeyboardDeviceHandle,
+ NULL,
+ NULL,
+ NULL,
+ &Iosb,
+ &NextKeyInput,
+ sizeof(KEYBOARD_INPUT_DATA),
+ NULL,
+ NULL);
+ DPRINT("KeyRaw: %s %04x\n",
+ (NextKeyInput.Flags & KEY_BREAK) ? "up":"down",
+ NextKeyInput.MakeCode );
+
+ if (Status == STATUS_ALERTED && !InputThreadsRunning)
+ goto KeyboardEscape;
+
+ }
+ while ((!(NextKeyInput.Flags & KEY_BREAK)) &&
+ NextKeyInput.MakeCode == KeyInput.MakeCode);
+ /* ^ Ignore repeats, they'll be KEY_MAKE and the same
+ * code. I'm not caring about the counting, not sure
+ * if that matters. I think not.
+ */
+
+ /* If the ModifierState is now empty again, send a
+ * special notification and eat both keypresses
+ */
+
+ fsNextModifiers = IntKeyboardGetModifiers(&NextKeyInput);
+
+ if (fsNextModifiers)
+ ModifierState ^= fsNextModifiers;
+
+ if (ModifierState == 0)
+ {
+ if (fsModifiers == MOD_WIN)
+ IntKeyboardSendWinKeyMsg();
+ else if (fsModifiers == MOD_ALT)
+ co_IntKeyboardSendAltKeyMsg();
+ continue;
+ }
+
+ NumKeys = 2;
+ }
+ }
+ }
+
+ for (;NumKeys;memcpy(&KeyInput, &NextKeyInput, sizeof(KeyInput)),
+ NumKeys--)
+ {
+ lParam = 0;
+
+ IntKeyboardUpdateLeds(KeyboardDeviceHandle,
+ &KeyInput,
+ IndicatorTrans);
+
+ /* While we are working, we set up lParam. The format is:
+ * 0-15: The number of times this key has autorepeated
+ * 16-23: The keyboard scancode
+ * 24: Set if it's and extended key (I assume KEY_E0 | KEY_E1)
+ * Note that E1 is only used for PAUSE (E1-1D-45) and
+ * E0-45 happens not to be anything.
+ * 29: Alt is pressed ('Context code')
+ * 30: Previous state, if the key was down before this message
+ * This is a cheap way to ignore autorepeat keys
+ * 31: 1 if the key is being pressed
+ */
+
+ /* If it's a KEY_MAKE (which is 0, so test using !KEY_BREAK)
+ * and it's the same key as the last one, increase the repeat
+ * count.
+ */
+
+ if (!(KeyInput.Flags & KEY_BREAK))
+ {
+ if (((KeyInput.Flags & (KEY_E0 | KEY_E1)) == LastFlags) &&
+ (KeyInput.MakeCode == LastMakeCode))
+ {
+ RepeatCount++;
+ lParam |= (1 << 30);
+ }
+ else
+ {
+ RepeatCount = 0;
+ LastFlags = KeyInput.Flags & (KEY_E0 | KEY_E1);
+ LastMakeCode = KeyInput.MakeCode;
+ }
+ }
+ else
+ {
+ LastFlags = 0;
+ LastMakeCode = 0; /* Should never match */
+ lParam |= (1 << 30) | (1 << 31);
+ }
+
+ lParam |= RepeatCount;
+
+ lParam |= (KeyInput.MakeCode & 0xff) << 16;
+
+ if (KeyInput.Flags & KEY_E0)
+ lParam |= (1 << 24);
+
+ if (ModifierState & MOD_ALT)
+ {
+ lParam |= (1 << 29);
+
+ if (!(KeyInput.Flags & KEY_BREAK))
+ msg.message = WM_SYSKEYDOWN;
+ else
+ msg.message = WM_SYSKEYUP;
+ }
+ else
+ {
+ if (!(KeyInput.Flags & KEY_BREAK))
+ msg.message = WM_KEYDOWN;
+ else
+ msg.message = WM_KEYUP;
+ }
+
+ /* Find the target thread whose locale is in effect */
+ if (!IntGetScreenDC())
+ FocusQueue = W32kGetPrimitiveMessageQueue();
+ else
+ 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;
+
+ msg.lParam = lParam;
+ msg.hwnd = FocusQueue->FocusWindow;
+
+ FocusThread = FocusQueue->Thread;
+
+ if (!(FocusThread && FocusThread->Tcb.Win32Thread &&
+ ((PW32THREAD)FocusThread->Tcb.Win32Thread)->KeyboardLayout))
+ continue;
+
+ /* This function uses lParam to fill wParam according to the
+ * keyboard layout in use.
+ */
+ W32kKeyProcessMessage(&msg,
+ ((PW32THREAD)FocusThread->Tcb.Win32Thread)->KeyboardLayout,
+ KeyInput.Flags & KEY_E0 ? 0xE0 :
+ (KeyInput.Flags & KEY_E1 ? 0xE1 : 0));
+
+ if (GetHotKey(ModifierState,
+ msg.wParam,
+ &Thread,
+ &hWnd,
+ &id))
+ {
+ if (!(KeyInput.Flags & KEY_BREAK))
+ {
+ DPRINT("Hot key pressed (hWnd %lx, id %d)\n", hWnd, id);
+ MsqPostHotKeyMessage (Thread,
+ hWnd,
+ (WPARAM)id,
+ MAKELPARAM((WORD)ModifierState,
+ (WORD)msg.wParam));
+ }
+ continue; /* Eat key up motion too */
+ }
+
+ /*
+ * Post a keyboard message.
+ */
+ co_MsqPostKeyboardMessage(msg.message,msg.wParam,msg.lParam);
+ }
+ }
+
+KeyboardEscape:
DPRINT( "KeyboardInput Thread Stopped...\n" );
- }
+ }
}
-NTSTATUS STDCALL
-NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release)
+NTSTATUS FASTCALL
+UserAcquireOrReleaseInputOwnership(BOOLEAN Release)
{
- if (Release && InputThreadsRunning && !pmPrimitiveMessageQueue)
- {
+ if (Release && InputThreadsRunning && !pmPrimitiveMessageQueue)
+ {
DPRINT( "Releasing input: PM = %08x\n", pmPrimitiveMessageQueue );
KeClearEvent(&InputThreadsStart);
InputThreadsRunning = FALSE;
-
+
NtAlertThread(KeyboardThreadHandle);
- }
- else if (!Release && !InputThreadsRunning)
- {
+ NtAlertThread(MouseThreadHandle);
+ }
+ else if (!Release && !InputThreadsRunning)
+ {
InputThreadsRunning = TRUE;
KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
- }
+ }
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
+
+NTSTATUS STDCALL
+NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release)
+{
+ DECLARE_RETURN(NTSTATUS);
+
+ DPRINT("Enter NtUserAcquireOrReleaseInputOwnership\n");
+ UserEnterExclusive();
+
+ RETURN(UserAcquireOrReleaseInputOwnership(Release));
+
+CLEANUP:
+ DPRINT("Leave NtUserAcquireOrReleaseInputOwnership, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
+
NTSTATUS FASTCALL
InitInputImpl(VOID)
{
- NTSTATUS Status;
-#if ENABLEMOUSEGDICALLBACK
- UNICODE_STRING MouseDeviceName;
- OBJECT_ATTRIBUTES MouseObjectAttributes;
- IO_STATUS_BLOCK Iosb;
- PIRP Irp;
- PFILE_OBJECT FileObject;
- GDI_INFORMATION GdiInfo;
- KEVENT IoEvent;
- PIO_STACK_LOCATION StackPtr;
-#endif
+ NTSTATUS Status;
- KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
-
- Status = PsCreateSystemThread(&KeyboardThreadHandle,
- THREAD_ALL_ACCESS,
- NULL,
- NULL,
- &KeyboardThreadId,
- KeyboardThreadMain,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Win32K: Failed to create keyboard thread.\n");
- }
-
- /* Initialize the default keyboard layout */
- (VOID)W32kGetDefaultKeyLayout();
-
-#if ENABLEMOUSEGDICALLBACK
- /*
- * Connect to the mouse class driver.
- * Failures here don't result in a failure return, the system must be
- * able to operate without mouse
- */
- RtlRosInitUnicodeStringFromLiteral(&MouseDeviceName, L"\\??\\MouseClass");
- InitializeObjectAttributes(&MouseObjectAttributes,
- &MouseDeviceName,
- 0,
- NULL,
- NULL);
- Status = ZwOpenFile(&MouseDeviceHandle,
- FILE_ALL_ACCESS,
- &MouseObjectAttributes,
- &Iosb,
- 0,
- FILE_SYNCHRONOUS_IO_ALERT);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Win32K: Failed to open mouse.\n");
- return STATUS_SUCCESS;
- }
- Status = ObReferenceObjectByHandle(MouseDeviceHandle,
- FILE_READ_DATA | FILE_WRITE_DATA,
- IoFileObjectType,
- KernelMode,
- (PVOID *) &FileObject,
- NULL);
-
+ KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
+
+ Status = PsCreateSystemThread(&KeyboardThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ NULL,
+ &KeyboardThreadId,
+ KeyboardThreadMain,
+ NULL);
if (!NT_SUCCESS(Status))
- {
- DPRINT1("Win32K: Failed to reference mouse file object. (0x%X)\n", Status);
- ZwClose(MouseDeviceHandle);
- return STATUS_SUCCESS;
- }
- KeInitializeEvent(&IoEvent, FALSE, NotificationEvent);
- GdiInfo.CallBack = MouseGDICallBack;
- Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
- FileObject->DeviceObject,
- &GdiInfo,
- sizeof(GdiInfo),
- NULL,
- 0,
- TRUE,
- &FileObject->Event,
- &Iosb);
-
- //trigger FileObject/Event dereferencing
- Irp->Tail.Overlay.OriginalFileObject = FileObject;
-
- StackPtr = IoGetNextIrpStackLocation(Irp);
- StackPtr->FileObject = FileObject;
- StackPtr->DeviceObject = FileObject->DeviceObject;
- StackPtr->Parameters.DeviceIoControl.InputBufferLength = sizeof(GdiInfo);
- StackPtr->Parameters.DeviceIoControl.OutputBufferLength = 0;
-
- Status = IoCallDriver(FileObject->DeviceObject, Irp);
- if (Status == STATUS_PENDING)
- {
- KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE,
- NULL);
- Status = Iosb.Status;
- }
+ {
+ DPRINT1("Win32K: Failed to create keyboard thread.\n");
+ }
+
+ /* Initialize the default keyboard layout */
+ (VOID)W32kGetDefaultKeyLayout();
+
+
+ Status = PsCreateSystemThread(&MouseThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ NULL,
+ &MouseThreadId,
+ MouseThreadMain,
+ NULL);
if (!NT_SUCCESS(Status))
- {
- DPRINT1("Win32K: Failed to connect to mouse driver.\n");
- ObDereferenceObject(&FileObject);
- NtClose(MouseDeviceHandle);
- return STATUS_SUCCESS;
- }
-#else
- Status = PsCreateSystemThread(&MouseThreadHandle,
- THREAD_ALL_ACCESS,
- NULL,
- NULL,
- &MouseThreadId,
- MouseThreadMain,
- NULL);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Win32K: Failed to create mouse thread.\n");
- }
-#endif
-
- return STATUS_SUCCESS;
+ {
+ DPRINT1("Win32K: Failed to create mouse thread.\n");
+ }
+
+ return STATUS_SUCCESS;
}
NTSTATUS FASTCALL
CleanupInputImp(VOID)
{
- return(STATUS_SUCCESS);
+ return(STATUS_SUCCESS);
}
BOOL
STDCALL
NtUserDragDetect(
- HWND hWnd,
- LONG x,
- LONG y)
+ HWND hWnd,
+ LONG x,
+ LONG y)
{
- UNIMPLEMENTED
- return 0;
+ UNIMPLEMENTED
+ return 0;
}
BOOL FASTCALL
IntBlockInput(PW32THREAD W32Thread, BOOL BlockIt)
{
- PW32THREAD OldBlock;
- ASSERT(W32Thread);
-
- if(!W32Thread->Desktop || (W32Thread->IsExiting && BlockIt))
- {
- /*
- * fail blocking if exiting the thread
- */
-
- return FALSE;
- }
-
- /*
- * FIXME - check access rights of the window station
- * e.g. services running in the service window station cannot block input
- */
- if(!ThreadHasInputAccess(W32Thread) ||
- !IntIsActiveDesktop(W32Thread->Desktop))
- {
- SetLastWin32Error(ERROR_ACCESS_DENIED);
- return FALSE;
- }
-
- ASSERT(W32Thread->Desktop);
- OldBlock = W32Thread->Desktop->BlockInputThread;
- if(OldBlock)
- {
- if(OldBlock != W32Thread)
- {
+ PW32THREAD OldBlock;
+ ASSERT(W32Thread);
+
+ if(!W32Thread->Desktop || (W32Thread->IsExiting && BlockIt))
+ {
+ /*
+ * fail blocking if exiting the thread
+ */
+
+ return FALSE;
+ }
+
+ /*
+ * FIXME - check access rights of the window station
+ * e.g. services running in the service window station cannot block input
+ */
+ if(!ThreadHasInputAccess(W32Thread) ||
+ !IntIsActiveDesktop(W32Thread->Desktop))
+ {
SetLastWin32Error(ERROR_ACCESS_DENIED);
return FALSE;
- }
- W32Thread->Desktop->BlockInputThread = (BlockIt ? W32Thread : NULL);
- return OldBlock == NULL;
- }
-
- W32Thread->Desktop->BlockInputThread = (BlockIt ? W32Thread : NULL);
- return OldBlock == NULL;
+ }
+
+ ASSERT(W32Thread->Desktop);
+ OldBlock = W32Thread->Desktop->BlockInputThread;
+ if(OldBlock)
+ {
+ if(OldBlock != W32Thread)
+ {
+ SetLastWin32Error(ERROR_ACCESS_DENIED);
+ return FALSE;
+ }
+ W32Thread->Desktop->BlockInputThread = (BlockIt ? W32Thread : NULL);
+ return OldBlock == NULL;
+ }
+
+ W32Thread->Desktop->BlockInputThread = (BlockIt ? W32Thread : NULL);
+ return OldBlock == NULL;
}
BOOL
STDCALL
NtUserBlockInput(
- BOOL BlockIt)
+ BOOL BlockIt)
{
- return IntBlockInput(PsGetWin32Thread(), BlockIt);
+ DECLARE_RETURN(BOOLEAN);
+
+ DPRINT("Enter NtUserBlockInput\n");
+ UserEnterExclusive();
+
+ RETURN( IntBlockInput(PsGetWin32Thread(), BlockIt));
+
+CLEANUP:
+ DPRINT("Leave NtUserBlockInput, ret=%i\n",_ret_);
+ UserLeave();
+ 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;
+ 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_LBUTTONUP, WM_RBUTTONUP}};
- const WPARAM SwapBtn[2] = {MK_LBUTTON, MK_RBUTTON};
- POINT MousePos;
- PSYSTEM_CURSORINFO CurInfo;
- PWINSTATION_OBJECT WinSta;
- BOOL DoMove, SwapButtons;
- MSG Msg;
- SURFOBJ *SurfObj;
- PSURFGDI SurfGDI;
- PDC dc;
- RECTL PointerRect;
-
+ const UINT SwapBtnMsg[2][2] =
+ {
+ {
+ WM_LBUTTONDOWN, WM_RBUTTONDOWN
+ },
+ {WM_LBUTTONUP, WM_RBUTTONUP}
+ };
+ const WPARAM SwapBtn[2] =
+ {
+ MK_LBUTTON, MK_RBUTTON
+ };
+ POINT MousePos, OrgPos;
+ PSYSTEM_CURSORINFO CurInfo;
+ PWINSTATION_OBJECT WinSta;
+ BOOL DoMove, 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;
- }
+
+ HDC hDC;
+
+ /* FIXME - get the screen dc from the window station or desktop */
+ if(!(hDC = IntGetScreenDC()))
+ {
+ return FALSE;
+ }
#endif
-
- ASSERT(mi);
+
+ ASSERT(mi);
#if 0
- WinSta = PsGetWin32Process()->WindowStation;
+
+ WinSta = PsGetWin32Process()->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;
+ /* 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);
-
- dc = DC_LockDc(hDC);
- SurfObj = (SURFOBJ*)AccessUserObject((ULONG) dc->Surface);
- SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
- DC_UnlockDc(hDC);
- ASSERT(SurfObj);
- ASSERT(SurfGDI);
-
- if(!mi->time)
- {
- LARGE_INTEGER LargeTickCount;
- KeQueryTickCount(&LargeTickCount);
- mi->time = LargeTickCount.u.LowPart;
- }
-
- SwapButtons = CurInfo->SwapButtons;
- DoMove = FALSE;
- ExAcquireFastMutex(&CurInfo->CursorMutex);
- MousePos.x = CurInfo->x;
- MousePos.y = CurInfo->y;
- if(mi->dwFlags & MOUSEEVENTF_MOVE)
- {
- if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
- {
- MousePos.x = mi->dx;
- MousePos.y = mi->dy;
- }
- else
- {
- MousePos.x += mi->dx;
- MousePos.y += mi->dy;
- }
-
- if(MousePos.x < 0)
- MousePos.x = 0;
- if(MousePos.y < 0)
- MousePos.y = 0;
- if(MousePos.x >= SurfObj->sizlBitmap.cx)
- MousePos.x = SurfObj->sizlBitmap.cx - 1;
- if(MousePos.y >= SurfObj->sizlBitmap.cy)
- MousePos.y = SurfObj->sizlBitmap.cy - 1;
-
- 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;
- }
-
- if((DoMove = (MousePos.x != CurInfo->x || MousePos.y != CurInfo->y)))
- {
- CurInfo->x = MousePos.x;
- CurInfo->y = MousePos.y;
- if(SurfGDI->MovePointer)
+
+ ASSERT(WinSta);
+
+ CurInfo = IntGetSysCursorInfo(WinSta);
+
+ if(!mi->time)
+ {
+ LARGE_INTEGER LargeTickCount;
+ KeQueryTickCount(&LargeTickCount);
+ mi->time = LargeTickCount.u.LowPart;
+ }
+
+ SwapButtons = CurInfo->SwapButtons;
+ DoMove = FALSE;
+
+ IntGetCursorLocation(WinSta, &MousePos);
+ OrgPos.x = MousePos.x;
+ OrgPos.y = MousePos.y;
+
+ if(mi->dwFlags & MOUSEEVENTF_MOVE)
+ {
+ if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
{
- IntLockGDIDriver(SurfGDI);
- SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
- IntUnLockGDIDriver(SurfGDI);
+ MousePos.x = mi->dx;
+ MousePos.y = mi->dy;
}
else
{
- IntLockGDIDriver(SurfGDI);
- EngMovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
- IntUnLockGDIDriver(SurfGDI);
+ MousePos.x += mi->dx;
+ MousePos.y += mi->dy;
+ }
+
+ DesktopWindow = IntGetWindowObject(WinSta->ActiveDesktop->DesktopWindow);
+
+ if (DesktopWindow)
+ {
+ if(MousePos.x >= DesktopWindow->ClientRect.right)
+ MousePos.x = DesktopWindow->ClientRect.right - 1;
+ if(MousePos.y >= DesktopWindow->ClientRect.bottom)
+ MousePos.y = DesktopWindow->ClientRect.bottom - 1;
+ ObmDereferenceObject(DesktopWindow);
}
- SetPointerRect(CurInfo, &PointerRect);
- }
- }
-
- ExReleaseFastMutex(&CurInfo->CursorMutex);
-
- /*
- * Insert the messages into the system queue
- */
-
- Msg.wParam = CurInfo->ButtonsDown;
- Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y);
- Msg.pt = MousePos;
- if(DoMove)
- {
- Msg.message = WM_MOUSEMOVE;
- MsqInsertSystemMessage(&Msg);
- }
-
- Msg.message = 0;
- if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN)
- {
- Msg.message = SwapBtnMsg[0][SwapButtons];
- CurInfo->ButtonsDown |= SwapBtn[SwapButtons];
- MsqInsertSystemMessage(&Msg);
- }
- else if(mi->dwFlags & MOUSEEVENTF_LEFTUP)
- {
- Msg.message = SwapBtnMsg[1][SwapButtons];
- CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons];
- MsqInsertSystemMessage(&Msg);
- }
- if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
- {
- Msg.message = WM_MBUTTONDOWN;
- CurInfo->ButtonsDown |= MK_MBUTTON;
- MsqInsertSystemMessage(&Msg);
- }
- else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
- {
- Msg.message = WM_MBUTTONUP;
- CurInfo->ButtonsDown &= ~MK_MBUTTON;
- MsqInsertSystemMessage(&Msg);
- }
- if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN)
- {
- Msg.message = SwapBtnMsg[0][!SwapButtons];
- CurInfo->ButtonsDown |= SwapBtn[!SwapButtons];
- MsqInsertSystemMessage(&Msg);
- }
- else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP)
- {
- Msg.message = SwapBtnMsg[1][!SwapButtons];
- CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons];
- MsqInsertSystemMessage(&Msg);
- }
-
- if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) &&
- (mi->dwFlags & MOUSEEVENTF_WHEEL))
- {
- /* fail because both types of events use the mouseData field */
- return FALSE;
- }
-
- if(mi->dwFlags & MOUSEEVENTF_XDOWN)
- {
- Msg.message = WM_XBUTTONDOWN;
- if(mi->mouseData & XBUTTON1)
- {
- Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
- CurInfo->ButtonsDown |= XBUTTON1;
+
+ 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;
+
+ 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.lParam = MAKELPARAM(MousePos.x, MousePos.y);
+ Msg.pt = MousePos;
+ if(DoMove)
+ {
+ Msg.message = WM_MOUSEMOVE;
MsqInsertSystemMessage(&Msg);
- }
- if(mi->mouseData & XBUTTON2)
- {
- Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
- CurInfo->ButtonsDown |= XBUTTON2;
+ }
+
+ Msg.message = 0;
+ if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN)
+ {
+ gQueueKeyStateTable[VK_LBUTTON] |= 0xc0;
+ Msg.message = SwapBtnMsg[0][SwapButtons];
+ CurInfo->ButtonsDown |= SwapBtn[SwapButtons];
+ MsqInsertSystemMessage(&Msg);
+ }
+ else if(mi->dwFlags & MOUSEEVENTF_LEFTUP)
+ {
+ gQueueKeyStateTable[VK_LBUTTON] &= ~0x80;
+ Msg.message = SwapBtnMsg[1][SwapButtons];
+ CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons];
+ MsqInsertSystemMessage(&Msg);
+ }
+ if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
+ {
+ gQueueKeyStateTable[VK_MBUTTON] |= 0xc0;
+ Msg.message = WM_MBUTTONDOWN;
+ CurInfo->ButtonsDown |= MK_MBUTTON;
+ MsqInsertSystemMessage(&Msg);
+ }
+ else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
+ {
+ gQueueKeyStateTable[VK_MBUTTON] &= ~0x80;
+ Msg.message = WM_MBUTTONUP;
+ CurInfo->ButtonsDown &= ~MK_MBUTTON;
MsqInsertSystemMessage(&Msg);
- }
- }
- else if(mi->dwFlags & MOUSEEVENTF_XUP)
- {
- Msg.message = WM_XBUTTONUP;
- if(mi->mouseData & XBUTTON1)
- {
- Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
- CurInfo->ButtonsDown &= ~XBUTTON1;
+ }
+ if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN)
+ {
+ gQueueKeyStateTable[VK_RBUTTON] |= 0xc0;
+ Msg.message = SwapBtnMsg[0][!SwapButtons];
+ CurInfo->ButtonsDown |= SwapBtn[!SwapButtons];
MsqInsertSystemMessage(&Msg);
- }
- if(mi->mouseData & XBUTTON2)
- {
- Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
- CurInfo->ButtonsDown &= ~XBUTTON2;
+ }
+ else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP)
+ {
+ gQueueKeyStateTable[VK_RBUTTON] &= ~0x80;
+ Msg.message = SwapBtnMsg[1][!SwapButtons];
+ CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons];
MsqInsertSystemMessage(&Msg);
- }
- }
- if(mi->dwFlags & MOUSEEVENTF_WHEEL)
- {
- Msg.message = WM_MOUSEWHEEL;
- Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData);
- MsqInsertSystemMessage(&Msg);
- }
-
- return TRUE;
+ }
+
+ if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) &&
+ (mi->dwFlags & MOUSEEVENTF_WHEEL))
+ {
+ /* fail because both types of events use the mouseData field */
+ return FALSE;
+ }
+
+ if(mi->dwFlags & MOUSEEVENTF_XDOWN)
+ {
+ Msg.message = WM_XBUTTONDOWN;
+ if(mi->mouseData & XBUTTON1)
+ {
+ gQueueKeyStateTable[VK_XBUTTON1] |= 0xc0;
+ Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
+ CurInfo->ButtonsDown |= XBUTTON1;
+ MsqInsertSystemMessage(&Msg);
+ }
+ if(mi->mouseData & XBUTTON2)
+ {
+ gQueueKeyStateTable[VK_XBUTTON2] |= 0xc0;
+ Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
+ CurInfo->ButtonsDown |= XBUTTON2;
+ MsqInsertSystemMessage(&Msg);
+ }
+ }
+ else if(mi->dwFlags & MOUSEEVENTF_XUP)
+ {
+ Msg.message = WM_XBUTTONUP;
+ if(mi->mouseData & XBUTTON1)
+ {
+ gQueueKeyStateTable[VK_XBUTTON1] &= ~0x80;
+ Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
+ CurInfo->ButtonsDown &= ~XBUTTON1;
+ MsqInsertSystemMessage(&Msg);
+ }
+ if(mi->mouseData & XBUTTON2)
+ {
+ gQueueKeyStateTable[VK_XBUTTON2] &= ~0x80;
+ Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
+ CurInfo->ButtonsDown &= ~XBUTTON2;
+ MsqInsertSystemMessage(&Msg);
+ }
+ }
+ if(mi->dwFlags & MOUSEEVENTF_WHEEL)
+ {
+ Msg.message = WM_MOUSEWHEEL;
+ Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData);
+ MsqInsertSystemMessage(&Msg);
+ }
+
+ return TRUE;
}
BOOL FASTCALL
IntKeyboardInput(KEYBDINPUT *ki)
{
- return FALSE;
+ return FALSE;
}
UINT
STDCALL
NtUserSendInput(
- UINT nInputs,
- LPINPUT pInput,
- INT cbSize)
+ UINT nInputs,
+ LPINPUT pInput,
+ INT cbSize)
{
- PW32THREAD W32Thread;
- UINT cnt;
-
- W32Thread = PsGetWin32Thread();
- ASSERT(W32Thread);
-
- if(!W32Thread->Desktop)
- {
- return 0;
- }
-
- if(!nInputs || !pInput || (cbSize != sizeof(INPUT)))
- {
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- /*
- * FIXME - check access rights of the window station
- * e.g. services running in the service window station cannot block input
- */
- if(!ThreadHasInputAccess(W32Thread) ||
- !IntIsActiveDesktop(W32Thread->Desktop))
- {
- SetLastWin32Error(ERROR_ACCESS_DENIED);
- return 0;
- }
-
- cnt = 0;
- while(nInputs--)
- {
- INPUT SafeInput;
- NTSTATUS Status;
-
- Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT));
- if(!NT_SUCCESS(Status))
- {
- SetLastNtError(Status);
- return cnt;
- }
-
- switch(SafeInput.type)
- {
- case INPUT_MOUSE:
- if(IntMouseInput(&SafeInput.mi))
- {
- cnt++;
- }
- break;
- case INPUT_KEYBOARD:
- if(IntKeyboardInput(&SafeInput.ki))
- {
- cnt++;
- }
- break;
- case INPUT_HARDWARE:
- break;
+ PW32THREAD W32Thread;
+ UINT cnt;
+ DECLARE_RETURN(UINT);
+
+ DPRINT("Enter NtUserSendInput\n");
+ UserEnterExclusive();
+
+ W32Thread = PsGetWin32Thread();
+ ASSERT(W32Thread);
+
+ if(!W32Thread->Desktop)
+ {
+ RETURN( 0);
+ }
+
+ if(!nInputs || !pInput || (cbSize != sizeof(INPUT)))
+ {
+ SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ RETURN( 0);
+ }
+
+ /*
+ * FIXME - check access rights of the window station
+ * e.g. services running in the service window station cannot block input
+ */
+ if(!ThreadHasInputAccess(W32Thread) ||
+ !IntIsActiveDesktop(W32Thread->Desktop))
+ {
+ SetLastWin32Error(ERROR_ACCESS_DENIED);
+ RETURN( 0);
+ }
+
+ cnt = 0;
+ while(nInputs--)
+ {
+ INPUT SafeInput;
+ NTSTATUS Status;
+
+ Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT));
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastNtError(Status);
+ RETURN( cnt);
+ }
+
+ switch(SafeInput.type)
+ {
+ case INPUT_MOUSE:
+ if(IntMouseInput(&SafeInput.mi))
+ {
+ cnt++;
+ }
+ break;
+ case INPUT_KEYBOARD:
+ if(IntKeyboardInput(&SafeInput.ki))
+ {
+ cnt++;
+ }
+ break;
+ case INPUT_HARDWARE:
+ break;
#ifndef NDEBUG
- default:
- DPRINT1("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
- break;
+
+ default:
+ DPRINT1("SendInput(): Invalid input type: 0x%x\n", SafeInput.type);
+ break;
#endif
- }
- }
-
- return cnt;
+
+ }
+ }
+
+ RETURN( cnt);
+
+CLEANUP:
+ DPRINT("Leave NtUserSendInput, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
}
/* EOF */