[User32|Win32k]
authorJames Tabor <james.tabor@reactos.org>
Mon, 25 Apr 2011 15:18:39 +0000 (15:18 +0000)
committerJames Tabor <james.tabor@reactos.org>
Mon, 25 Apr 2011 15:18:39 +0000 (15:18 +0000)
- Isolated Alt-Tab/Esc issues. Placed update_input_key_state when posting to a queue like wine. This fixed the shift key checks. The Alt-Space is handled after a Translate Message call (WM_SYSCHAR), developers need to check application code to help support it (ConCtrl32). Will move AltSwitch.c from win32csr and port patch from bug 5378 to User32. ReactOS registers the Switch Class in Win32k and it is not used.
- Implemented the rest of HotKey Support. ReactOS Explorer does not save hotkey actions.
- See related bugs 1091.

svn path=/trunk/; revision=51450

reactos/dll/win32/user32/windows/defwnd.c
reactos/subsystems/win32/win32k/include/hotkey.h
reactos/subsystems/win32/win32k/ntuser/defwnd.c
reactos/subsystems/win32/win32k/ntuser/hotkey.c
reactos/subsystems/win32/win32k/ntuser/message.c
reactos/subsystems/win32/win32k/ntuser/msgqueue.c

index edee49d..83155b6 100644 (file)
@@ -753,12 +753,12 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
 {
   WINDOWPLACEMENT wp;
   POINT Pt;
+  LRESULT lResult;
 
   if (!IsWindowEnabled( hWnd )) return 0;
 
   if (ISITHOOKED(WH_CBT))
   {
-     LRESULT lResult;
      NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
      if (lResult) return 0;
   }
@@ -795,7 +795,7 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
         break;
       case SC_CLOSE:
         return SendMessageW(hWnd, WM_CLOSE, 0, 0);
-
+//      case SC_DEFAULT:
       case SC_MOUSEMENU:
         {
           Pt.x = (short)LOWORD(lParam);
@@ -815,9 +815,40 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
         }
        break;
 
+      case SC_SCREENSAVE:
+        NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
+        break;
+
+      case SC_NEXTWINDOW:
+      case SC_PREVWINDOW:
+        FIXME("Implement Alt-Tab!!! wParam 0x%x lParam 0x%x\n",wParam,lParam);
+        break;
+
+      case SC_HOTKEY:
+        {
+           HWND hwnd, hWndLastActive;
+
+           hwnd = (HWND)lParam;
+           PWND pWnd = ValidateHwnd(hwnd);
+           if (pWnd)
+           {
+              hWndLastActive = GetLastActivePopup(hwnd);
+              if (hWndLastActive)
+              {
+                 hwnd = hWndLastActive;
+                 pWnd = ValidateHwnd(hwnd);
+              }
+              SetForegroundWindow(hwnd);
+              if (pWnd->style & WS_MINIMIZE)
+              {
+                 PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);
+              }
+           }
+        }
+        break;
+
       default:
-       /* FIXME: Implement */
-        UNIMPLEMENTED;
+        FIXME("Unimplemented DefWndHandleSysCommand wParam 0x%x\n",wParam);
         break;
     }
 
@@ -1380,39 +1411,49 @@ User32DefWindowProc(HWND hWnd,
             if(wParam == VK_F10) iF10Key = VK_F10;
             break;
 
-        /* FIXME: This is also incomplete. */
         case WM_SYSKEYDOWN:
         {
             if (HIWORD(lParam) & KEYDATA_ALT)
-            {
-                HWND top = GetAncestor(hWnd, GA_ROOT);
-             /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
-                if ( (wParam == VK_MENU || wParam == VK_LMENU
-                                    || wParam == VK_RMENU) && !iMenuSysKey )
-                   iMenuSysKey = 1;
-                else
-                   iMenuSysKey = 0;
+            {   /* Previous state, if the key was down before this message,
+                   this is a cheap way to ignore autorepeat keys. */
+                if ( !(HIWORD(lParam) & KEYDATA_PREVSTATE) )
+                {
+                   if ( ( wParam == VK_MENU  ||
+                          wParam == VK_LMENU ||
+                          wParam == VK_RMENU ) && !iMenuSysKey )
+                       iMenuSysKey = 1;
+                   else
+                       iMenuSysKey = 0;
+                }
 
                 iF10Key = 0;
 
                 if (wParam == VK_F4) /* Try to close the window */
                 {
-                    if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
-                    {
-                        if (bUnicode)
-                            PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
-                        else
-                            PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
-                    }
+                   HWND top = GetAncestor(hWnd, GA_ROOT);
+                   if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
+                      PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
                 }
-                else if (wParam == VK_SNAPSHOT)
+                else if (wParam == VK_SNAPSHOT) // Alt-VK_SNAPSHOT?
                 {
-                    HWND hwnd = hWnd;
-                    while (GetParent(hwnd) != NULL)
-                    {
-                        hwnd = GetParent(hwnd);
-                    }
-                    DefWndScreenshot(hwnd);
+                   HWND hwnd = hWnd;
+                   while (GetParent(hwnd) != NULL)
+                   {
+                       hwnd = GetParent(hwnd);
+                   }
+                   DefWndScreenshot(hwnd);
+                }
+                else if ( wParam == VK_ESCAPE || wParam == VK_TAB ) // Alt-Tab/ESC Alt-Shift-Tab/ESC
+                {
+                   WPARAM wParamTmp;
+                   HWND Active = GetActiveWindow(); // Noticed MDI problem.
+                   if (!Active)
+                   {
+                      FIXME("WM_SYSKEYDOWN VK_ESCAPE no active\n");
+                      break;
+                   }
+                   wParamTmp = GetKeyState(VK_SHIFT) & 0x8000 ? SC_PREVWINDOW : SC_NEXTWINDOW;
+                   SendMessageW( Active, WM_SYSCOMMAND, wParamTmp, wParam );
                 }
             }
             else if( wParam == VK_F10 )
@@ -1421,8 +1462,6 @@ User32DefWindowProc(HWND hWnd,
                     SendMessageW( hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, MAKELPARAM(-1, -1) );
                 iF10Key = 1;
             }
-            else if( wParam == VK_ESCAPE && (GetKeyState(VK_SHIFT) & 0x8000))
-                SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, ' ' );
             break;
         }
 
@@ -1440,38 +1479,24 @@ User32DefWindowProc(HWND hWnd,
         case WM_SYSCHAR:
         {
             iMenuSysKey = 0;
-            if (wParam == '\r' && IsIconic(hWnd))
+            if (wParam == VK_RETURN && IsIconic(hWnd))
             {
                 PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
                 break;
             }
             if ((HIWORD(lParam) & KEYDATA_ALT) && wParam)
             {
-                if (wParam == '\t' || wParam == '\x1b') break;
-                if (wParam == ' ' && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
+                if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
+                if (wParam == VK_SPACE && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
                     SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
                 else
                     SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
             }
             else /* check for Ctrl-Esc */
-                if (wParam != '\x1b') MessageBeep(0);
-            break;
-        }
-
-        case WM_SHOWWINDOW:
-        {
-            if (lParam) // Call when it is necessary.
-               NtUserMessageCall( hWnd, Msg, wParam, lParam, 0, FNID_DEFWINDOWPROC, FALSE);
+                if (wParam != VK_ESCAPE) MessageBeep(0);
             break;
         }
 
-        case WM_CLIENTSHUTDOWN:
-        {
-            LRESULT lResult;
-            NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
-            return lResult;   
-        }
-
         case WM_CANCELMODE:
         {
             iMenuSysKey = 0;
@@ -1800,6 +1825,17 @@ User32DefWindowProc(HWND hWnd,
             break;
         }
 
+/* Move to win32k !*/
+        case WM_SHOWWINDOW:
+            if (!lParam) break; // Call when it is necessary.
+        case WM_CLIENTSHUTDOWN:
+        case WM_GETHOTKEY:
+        case WM_SETHOTKEY:
+        {
+            LRESULT lResult;
+            NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, !bUnicode);
+            return lResult;
+        }
     }
     return 0;
 }
index 74f19a2..b8bbee9 100644 (file)
@@ -13,6 +13,8 @@ typedef struct _HOT_KEY_ITEM
   UINT vk;
 } HOT_KEY_ITEM, *PHOT_KEY_ITEM;
 
+#define IDHOT_REACTOS (-9)
+
 INIT_FUNCTION
 NTSTATUS
 NTAPI
@@ -33,5 +35,9 @@ UnregisterWindowHotKeys(PWND Window);
 
 VOID FASTCALL
 UnregisterThreadHotKeys(struct _ETHREAD *Thread);
+UINT FASTCALL
+DefWndGetHotKey(HWND hwnd);
+INT FASTCALL 
+DefWndSetHotKey( PWND pWnd, WPARAM wParam);
 
 /* EOF */
index 88d8280..f64caeb 100644 (file)
@@ -97,6 +97,34 @@ IntClientShutdown(
    return lResult;
 }
 
+LRESULT FASTCALL
+DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
+{
+   LRESULT lResult = 0;
+   BOOL Hook = FALSE;
+
+   if (ISITHOOKED(WH_CBT) || (pWnd->head.rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)))
+   {
+      Hook = TRUE;
+      lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam);
+      
+      if (lResult) return lResult;
+   }
+
+   switch (wParam & 0xfff0)
+   {
+      case SC_SCREENSAVE:
+        DPRINT1("Screensaver Called!\n");
+        break;
+
+      default:
+        UNIMPLEMENTED;
+        break;
+   }
+
+   return(Hook ? 1 : 0); // Don't call us again from user space.
+}
+
 /*
    Win32k counterpart of User DefWindowProc
  */
@@ -117,7 +145,7 @@ IntDefWindowProc(
       case WM_SYSCOMMAND:
       {
          DPRINT1("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam );
-         lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam);
+         lResult = DefWndHandleSysCommand(Wnd, wParam, lParam);
          break;
       }
       case WM_SHOWWINDOW:
@@ -142,6 +170,12 @@ IntDefWindowProc(
       case WM_CLIENTSHUTDOWN:
          return IntClientShutdown(Wnd, wParam, lParam);
 
+      case WM_GETHOTKEY:
+         return DefWndGetHotKey(UserHMGetHandle(Wnd));                
+      case WM_SETHOTKEY:
+         return DefWndSetHotKey(Wnd, wParam);
+
+      /* ReactOS only. */
       case WM_CBT:
       {
          switch (wParam)
index 1d5322e..7f20d32 100644 (file)
@@ -61,7 +61,6 @@ InitHotkeyImpl(VOID)
    return STATUS_SUCCESS;
 }
 
-
 #if 0 //not used
 NTSTATUS FASTCALL
 CleanupHotKeys(VOID)
@@ -71,7 +70,6 @@ CleanupHotKeys(VOID)
 }
 #endif
 
-
 BOOL FASTCALL
 GetHotKey (UINT fsModifiers,
            UINT vk,
@@ -102,7 +100,6 @@ GetHotKey (UINT fsModifiers,
    return FALSE;
 }
 
-
 VOID FASTCALL
 UnregisterWindowHotKeys(PWND Window)
 {
@@ -119,7 +116,6 @@ UnregisterWindowHotKeys(PWND Window)
 
 }
 
-
 VOID FASTCALL
 UnregisterThreadHotKeys(struct _ETHREAD *Thread)
 {
@@ -136,7 +132,6 @@ UnregisterThreadHotKeys(struct _ETHREAD *Thread)
 
 }
 
-
 static
 BOOL FASTCALL
 IsHotKey (UINT fsModifiers, UINT vk)
@@ -154,7 +149,111 @@ IsHotKey (UINT fsModifiers, UINT vk)
    return FALSE;
 }
 
+//
+// Get/SetHotKey message support.
+//
+UINT FASTCALL
+DefWndGetHotKey( HWND hwnd )
+{
+   PHOT_KEY_ITEM HotKeyItem;
+
+   DPRINT1("DefWndGetHotKey\n");
+
+   if (IsListEmpty(&gHotkeyList)) return 0;
+
+   LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
+   {
+      if ( HotKeyItem->hWnd == hwnd &&
+           HotKeyItem->id == IDHOT_REACTOS )
+      {
+         return MAKELONG(HotKeyItem->vk, HotKeyItem->fsModifiers);
+      }
+   }
+   return 0;
+}
+
+INT FASTCALL 
+DefWndSetHotKey( PWND pWnd, WPARAM wParam )
+{
+   UINT fsModifiers, vk;
+   PHOT_KEY_ITEM HotKeyItem;
+   HWND hWnd;
+   BOOL HaveSameWnd = FALSE;
+   INT Ret = 1;
+
+   DPRINT1("DefWndSetHotKey wParam 0x%x\n", wParam);
+
+   // A hot key cannot be associated with a child window.
+   if (pWnd->style & WS_CHILD) return 0;
+
+   // VK_ESCAPE, VK_SPACE, and VK_TAB are invalid hot keys.
+   if ( LOWORD(wParam) == VK_ESCAPE ||
+        LOWORD(wParam) == VK_SPACE ||
+        LOWORD(wParam) == VK_TAB ) return -1;
+
+   vk = LOWORD(wParam);
+   fsModifiers = HIWORD(wParam);   
+   hWnd = UserHMGetHandle(pWnd);
 
+   if (wParam)
+   {
+      LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
+      {
+         if ( HotKeyItem->fsModifiers == fsModifiers &&
+              HotKeyItem->vk == vk &&
+              HotKeyItem->id == IDHOT_REACTOS )
+         {
+            if (HotKeyItem->hWnd != hWnd)
+               Ret = 2; // Another window already has the same hot key.
+            break;
+         }
+      }
+   }
+
+   LIST_FOR_EACH(HotKeyItem, &gHotkeyList, HOT_KEY_ITEM, ListEntry)
+   {
+      if ( HotKeyItem->hWnd == hWnd &&
+           HotKeyItem->id == IDHOT_REACTOS )
+      {
+         HaveSameWnd = TRUE;
+         break;
+      }
+   }
+
+   if (HaveSameWnd)
+   {
+      if (wParam == 0)
+      { // Setting wParam to NULL removes the hot key associated with a window.
+         UnregisterWindowHotKeys(pWnd);
+      }
+      else
+      { /* A window can only have one hot key. If the window already has a hot key
+           associated with it, the new hot key replaces the old one. */
+         HotKeyItem->fsModifiers = fsModifiers;
+         HotKeyItem->vk = vk;
+      }
+   }
+   else // 
+   {
+      if (wParam == 0)
+         return 1; // Do nothing, exit.
+
+      HotKeyItem = ExAllocatePoolWithTag (PagedPool, sizeof(HOT_KEY_ITEM), USERTAG_HOTKEY);
+      if (HotKeyItem == NULL)
+      {
+        return 0;
+      }
+
+      HotKeyItem->Thread = pWnd->head.pti->pEThread;
+      HotKeyItem->hWnd = hWnd;
+      HotKeyItem->id = IDHOT_REACTOS; // Don't care, these hot keys are unrelated to the hot keys set by RegisterHotKey.
+      HotKeyItem->fsModifiers = fsModifiers;
+      HotKeyItem->vk = vk;
+
+      InsertHeadList (&gHotkeyList, &HotKeyItem->ListEntry);
+   }
+   return Ret;
+}
 
 /* SYSCALLS *****************************************************************/
 
index 2a2097f..030b1c9 100644 (file)
@@ -735,7 +735,8 @@ co_IntPeekMessage( PMSG Msg,
         }
 
         /* Now check for normal messages. */
-        if ((ProcessMask & QS_POSTMESSAGE) &&
+        if (( (ProcessMask & QS_POSTMESSAGE) ||
+              (ProcessMask & QS_HOTKEY) ) &&
             MsqPeekMessage( ThreadQueue,
                             RemoveMessages,
                             Window,
index 90b11a9..e737127 100644 (file)
@@ -463,6 +463,7 @@ co_MsqPostKeyboardMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
          FocusMessageQueue->Desktop->pDeskInfo->LastInputWasKbd = TRUE;
 
          Msg.pt = gpsi->ptCursor;
+         update_input_key_state(FocusMessageQueue, &Msg);
          MsqPostMessage(FocusMessageQueue, &Msg, TRUE, QS_KEY);
    }
    else
@@ -481,6 +482,8 @@ MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam)
    MSG Mesg;
    LARGE_INTEGER LargeTickCount;
    NTSTATUS Status;
+   INT id;
+   DWORD Type;
 
    Status = ObReferenceObjectByPointer (Thread,
                                         THREAD_ALL_ACCESS,
@@ -503,14 +506,17 @@ MsqPostHotKeyMessage(PVOID Thread, HWND hWnd, WPARAM wParam, LPARAM lParam)
       return;
    }
 
-   Mesg.hwnd = hWnd;
-   Mesg.message = WM_HOTKEY;
-   Mesg.wParam = wParam;
-   Mesg.lParam = lParam;
+   id = wParam; // Check for hot keys unrelated to the hot keys set by RegisterHotKey.
+
+   Mesg.hwnd    = hWnd;
+   Mesg.message = id != IDHOT_REACTOS ? WM_HOTKEY : WM_SYSCOMMAND;
+   Mesg.wParam  = id != IDHOT_REACTOS ? wParam    : SC_HOTKEY;
+   Mesg.lParam  = id != IDHOT_REACTOS ? lParam    : (LPARAM)hWnd;
+   Type         = id != IDHOT_REACTOS ? QS_HOTKEY : QS_POSTMESSAGE;
    KeQueryTickCount(&LargeTickCount);
-   Mesg.time = MsqCalculateMessageTime(&LargeTickCount);
-   Mesg.pt = gpsi->ptCursor;
-   MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
+   Mesg.time    = MsqCalculateMessageTime(&LargeTickCount);
+   Mesg.pt      = gpsi->ptCursor;
+   MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, Type);
    UserDereferenceObject(Window);
    ObDereferenceObject (Thread);
 
@@ -543,8 +549,8 @@ co_MsqDispatchOneSentMessage(PUSER_MESSAGE_QUEUE MessageQueue)
 {
    PUSER_SENT_MESSAGE SaveMsg, Message;
    PLIST_ENTRY Entry;
-   LRESULT Result;
    PTHREADINFO pti;
+   LRESULT Result = 0;
 
    if (IsListEmpty(&MessageQueue->SentMessagesListHead))
    {
@@ -1321,6 +1327,10 @@ BOOL co_IntProcessKeyboardMessage(MSG* Msg, BOOL* RemoveMessages)
             case VK_LMENU: case VK_RMENU:
                 Msg->wParam = VK_MENU;
                 break;
+            case VK_F10:
+                if (Msg->message == WM_KEYUP) Msg->message = WM_SYSKEYUP;
+                if (Msg->message == WM_KEYDOWN) Msg->message = WM_SYSKEYDOWN;
+                break;
         }
     }
 
@@ -1450,7 +1460,7 @@ co_MsqPeekHardwareMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
            {
                update_input_key_state(MessageQueue, pMsg);
                RemoveEntryList(&CurrentMessage->ListEntry);
-               ClearMsgBitsMask(MessageQueue, QS_INPUT);
+               ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
                MsqDestroyMessage(CurrentMessage);
            }
 
@@ -1510,7 +1520,7 @@ MsqPeekMessage(IN PUSER_MESSAGE_QUEUE MessageQueue,
          if (Remove)
          {
              RemoveEntryList(&CurrentMessage->ListEntry);
-             ClearMsgBitsMask(MessageQueue, QS_POSTMESSAGE);
+             ClearMsgBitsMask(MessageQueue, CurrentMessage->QS_Flags);
              MsqDestroyMessage(CurrentMessage);
          }
          return(TRUE);