[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / input.c
index 2ecc9ed..13d9fc0 100644 (file)
@@ -2,7 +2,7 @@
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * PURPOSE:          Window classes
- * FILE:             subsys/win32k/ntuser/class.c
+ * FILE:             subsystems/win32/win32k/ntuser/input.c
  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
  * REVISION HISTORY:
  *       06-06-2001  CSH  Created
@@ -10,7 +10,7 @@
 
 /* INCLUDES ******************************************************************/
 
-#include <w32k.h>
+#include <win32k.h>
 #include <ntddkbd.h>
 
 #define NDEBUG
@@ -22,7 +22,9 @@ extern NTSTATUS Win32kInitWin32Thread(PETHREAD Thread);
 /* GLOBALS *******************************************************************/
 
 PTHREADINFO ptiRawInput;
-PKTIMER MasterTimer;
+PTHREADINFO ptiKeyboard;
+PTHREADINFO ptiMouse;
+PKTIMER MasterTimer = NULL;
 PATTACHINFO gpai = NULL;
 
 static HANDLE MouseDeviceHandle;
@@ -204,6 +206,9 @@ MouseThreadMain(PVOID StartContext)
    NTSTATUS Status;
    MOUSE_ATTRIBUTES MouseAttr;
 
+   KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
+                       LOW_REALTIME_PRIORITY + 3);
+
    InitializeObjectAttributes(&MouseObjectAttributes,
                               &MouseDeviceName,
                               0,
@@ -224,6 +229,18 @@ MouseThreadMain(PVOID StartContext)
                        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;
+   DPRINT("Mouse Thread 0x%x \n", ptiMouse);
+
    KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
                        LOW_REALTIME_PRIORITY + 3);
 
@@ -443,7 +460,7 @@ IntKeyboardUpdateLeds(HANDLE KeyboardDeviceHandle,
 static VOID APIENTRY
 IntKeyboardSendWinKeyMsg()
 {
-   PWINDOW_OBJECT Window;
+   PWND Window;
    MSG Mesg;
 
    if (!(Window = UserGetWindowObject(InputWindowStation->ShellWindow)))
@@ -458,7 +475,7 @@ IntKeyboardSendWinKeyMsg()
    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 APIENTRY
@@ -520,6 +537,10 @@ KeyboardThreadMain(PVOID StartContext)
       return; //(Status);
    }
 
+   ptiKeyboard = PsGetCurrentThreadWin32Thread();
+   ptiKeyboard->TIF_flags |= TIF_SYSTEMTHREAD;
+   DPRINT("Keyboard Thread 0x%x \n", ptiKeyboard);
+
    KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
                        LOW_REALTIME_PRIORITY + 3);
 
@@ -713,6 +734,7 @@ KeyboardThreadMain(PVOID StartContext)
          for (;NumKeys;memcpy(&KeyInput, &NextKeyInput, sizeof(KeyInput)),
                NumKeys--)
          {
+            PKBL keyboardLayout = NULL;
             lParam = 0;
 
             IntKeyboardUpdateLeds(KeyboardDeviceHandle,
@@ -783,29 +805,30 @@ KeyboardThreadMain(PVOID StartContext)
             }
 
             /* Find the target thread whose locale is in effect */
-               FocusQueue = IntGetFocusMessageQueue();
+            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;
+            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));
 
@@ -827,6 +850,11 @@ KeyboardThreadMain(PVOID StartContext)
                continue; /* Eat key up motion too */
             }
 
+            if (!FocusQueue)
+            {
+                /* There is no focused window to receive a keyboard message */
+                continue;
+            }
             /*
              * Post a keyboard message.
              */
@@ -862,14 +890,6 @@ RawInputThreadMain(PVOID StartContext)
 
 
   Objects[0] = &InputThreadsStart;
-
-  MasterTimer = ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), TAG_INPUT);
-  if (!MasterTimer)
-  {
-     DPRINT1("Win32K: Failed making Raw Input thread a win32 thread.\n");
-     return;
-  }
-  KeInitializeTimer(MasterTimer);
   Objects[1] = MasterTimer;
 
   // This thread requires win32k!
@@ -881,8 +901,8 @@ RawInputThreadMain(PVOID StartContext)
   }
 
   ptiRawInput = PsGetCurrentThreadWin32Thread();
-  DPRINT("\nRaw Input Thread 0x%x \n", ptiRawInput);
-
+  ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD;
+  DPRINT("Raw Input Thread 0x%x \n", ptiRawInput);
 
   KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
                        LOW_REALTIME_PRIORITY + 3);
@@ -913,13 +933,24 @@ RawInputThreadMain(PVOID StartContext)
   DPRINT1("Raw Input Thread Exit!\n");
 }
 
-NTSTATUS FASTCALL
+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())
    {
@@ -974,23 +1005,13 @@ CleanupInputImp(VOID)
    return(STATUS_SUCCESS);
 }
 
-BOOL
-APIENTRY
-NtUserDragDetect(
-   HWND hWnd,
-   POINT pt) // Just like the User call.
-{
-   UNIMPLEMENTED
-   return 0;
-}
-
 BOOL FASTCALL
 IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt)
 {
    PTHREADINFO OldBlock;
    ASSERT(W32Thread);
 
-   if(!W32Thread->Desktop || ((W32Thread->TIF_flags & TIF_INCLEANUP) && BlockIt))
+   if(!W32Thread->rpdesk || ((W32Thread->TIF_flags & TIF_INCLEANUP) && BlockIt))
    {
       /*
        * fail blocking if exiting the thread
@@ -1004,14 +1025,14 @@ IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt)
     *         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)
@@ -1019,11 +1040,11 @@ IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt)
          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;
 }
 
@@ -1094,7 +1115,7 @@ IntMouseInput(MOUSEINPUT *mi)
    /*
     * Insert the messages into the system queue
     */
-   Msg.wParam = CurInfo->ButtonsDown;
+   Msg.wParam = 0;
    Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y);
    Msg.pt = MousePos;
 
@@ -1110,49 +1131,55 @@ IntMouseInput(MOUSEINPUT *mi)
 
    if(mi->dwFlags & MOUSEEVENTF_MOVE)
    {
-      UserSetCursorPos(MousePos.x, MousePos.y);
+      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;
+      co_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;
+      co_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;
+      co_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;
+      co_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;
+      co_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;
+      co_MsqInsertMouseMessage(&Msg);
    }
 
    if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) &&
@@ -1168,16 +1195,16 @@ IntMouseInput(MOUSEINPUT *mi)
       if(mi->mouseData & XBUTTON1)
       {
          gQueueKeyStateTable[VK_XBUTTON1] |= 0xc0;
+         CurInfo->ButtonsDown |= MK_XBUTTON1;
          Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
-         CurInfo->ButtonsDown |= XBUTTON1;
-         MsqInsertSystemMessage(&Msg);
+         co_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);
+         co_MsqInsertMouseMessage(&Msg);
       }
    }
    else if(mi->dwFlags & MOUSEEVENTF_XUP)
@@ -1186,23 +1213,23 @@ IntMouseInput(MOUSEINPUT *mi)
       if(mi->mouseData & XBUTTON1)
       {
          gQueueKeyStateTable[VK_XBUTTON1] &= ~0x80;
+         CurInfo->ButtonsDown &= ~MK_XBUTTON1;
          Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
-         CurInfo->ButtonsDown &= ~XBUTTON1;
-         MsqInsertSystemMessage(&Msg);
+         co_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);
+         co_MsqInsertMouseMessage(&Msg);
       }
    }
    if(mi->dwFlags & MOUSEEVENTF_WHEEL)
    {
       Msg.message = WM_MOUSEWHEEL;
       Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData);
-      MsqInsertSystemMessage(&Msg);
+      co_MsqInsertMouseMessage(&Msg);
    }
 
    return TRUE;
@@ -1212,7 +1239,6 @@ BOOL FASTCALL
 IntKeyboardInput(KEYBDINPUT *ki)
 {
    PUSER_MESSAGE_QUEUE FocusMessageQueue;
-   PTHREADINFO pti;
    MSG Msg;
    LARGE_INTEGER LargeTickCount;
    KBDLLHOOKSTRUCT KbdHookData;
@@ -1315,12 +1341,8 @@ IntKeyboardInput(KEYBDINPUT *ki)
       Msg.time = ki->time;
 
    /* All messages have to contain the cursor point. */
-   pti = PsGetCurrentThreadWin32Thread();
    Msg.pt = gpsi->ptCursor;
 
-    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;
@@ -1328,7 +1350,7 @@ IntKeyboardInput(KEYBDINPUT *ki)
    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",
+      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;
@@ -1370,8 +1392,9 @@ IntKeyboardInput(KEYBDINPUT *ki)
          FocusMessageQueue->Desktop->pDeskInfo->LastInputWasKbd = TRUE;
 
          Msg.pt = gpsi->ptCursor;
-
-         MsqPostMessage(FocusMessageQueue, &Msg, FALSE, QS_KEY);
+      // Post to hardware queue, based on the first part of wine "some GetMessage tests"
+      // in test_PeekMessage()
+         MsqPostMessage(FocusMessageQueue, &Msg, TRUE, QS_KEY);
    }
    else
    {
@@ -1394,7 +1417,7 @@ UserAttachThreadInput( PTHREADINFO pti, PTHREADINFO ptiTo, BOOL fAttach)
    /* Do not attach to system threads or between different desktops. */
    if ( pti->TIF_flags & TIF_DONTATTACHQUEUE ||
         ptiTo->TIF_flags & TIF_DONTATTACHQUEUE ||
-        pti->Desktop != ptiTo->Desktop )
+        pti->rpdesk != ptiTo->rpdesk )
       return FALSE;
 
    /* If Attach set, allocate and link. */
@@ -1451,7 +1474,7 @@ NtUserSendInput(
    W32Thread = PsGetCurrentThreadWin32Thread();
    ASSERT(W32Thread);
 
-   if(!W32Thread->Desktop)
+   if(!W32Thread->rpdesk)
    {
       RETURN( 0);
    }
@@ -1467,7 +1490,7 @@ NtUserSendInput(
     *         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);