Author: jimtabor
Date: Mon Nov 24 02:50:18 2014
New Revision: 65472

URL: http://svn.reactos.org/svn/reactos?rev=65472&view=rev
Log:
[NtUser]
- Synchronize mouse messages. Part II
- Dedicated to Giannis Adamopoulos and Amine Khaldi.
- Additional fixes are added.
- This should be more accurate, based on "Hit Testing: Which HWND is the mouse 
over?":
http://blogs.msdn.com/b/dwayneneed/archive/2008/09/08/transparent-windows-in-wpf.aspx
- Note: Older FireFox menu item hilite select seem to work now, do not need to 
keep moving the mouse to keep it hilited to be selected.
- Test results: 
https://reactos.org/sites/all/modules/reactos/testman/compare.php?ids=33709,33710,33713

Modified:
    trunk/reactos/win32ss/user/ntuser/keyboard.c
    trunk/reactos/win32ss/user/ntuser/message.c
    trunk/reactos/win32ss/user/ntuser/msgqueue.c
    trunk/reactos/win32ss/user/ntuser/msgqueue.h
    trunk/reactos/win32ss/user/ntuser/timer.c

Modified: trunk/reactos/win32ss/user/ntuser/keyboard.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/keyboard.c?rev=65472&r1=65471&r2=65472&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/keyboard.c        [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/keyboard.c        [iso-8859-1] Mon Nov 24 
02:50:18 2014
@@ -936,10 +936,16 @@
                 Msg.lParam |= KF_MENUMODE << 16;
         }
 
+        // Post mouse move before posting key buttons, to keep it syned.
+        if (pFocusQueue->QF_flags & QF_MOUSEMOVED)
+        {
+           IntCoalesceMouseMove(pti);
+        }
+
         /* Post a keyboard message */
         TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", 
Msg.message, Msg.wParam, Msg.lParam);
         if (!Wnd) {ERR("Window is NULL\n");}
-        MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0);
+        MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0, dwExtraInfo);
     }
 
     return TRUE;
@@ -1154,7 +1160,7 @@
         NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
         NewMsg.wParam = HIWORD(lpMsg->lParam);
         NewMsg.lParam = LOWORD(lpMsg->lParam);
-        MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0);
+        MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
         return TRUE;
     }
 
@@ -1183,7 +1189,7 @@
         {
             TRACE("Msg: %x '%lc' (%04x) %08x\n", NewMsg.message, wch[i], 
wch[i], NewMsg.lParam);
             NewMsg.wParam = wch[i];
-            MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0);
+            MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
         }
         bResult = TRUE;
     }

Modified: trunk/reactos/win32ss/user/ntuser/message.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/message.c?rev=65472&r1=65471&r2=65472&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/message.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/message.c [iso-8859-1] Mon Nov 24 
02:50:18 2014
@@ -802,6 +802,12 @@
         pti->timeLast = LargeTickCount.u.LowPart;
         pti->pcti->tickLastMsgChecked = LargeTickCount.u.LowPart;
 
+        // Post mouse moves while looping through peek messages.
+        if (pti->MessageQueue->QF_flags & QF_MOUSEMOVED)
+        {
+           IntCoalesceMouseMove(pti);
+        }
+
         /* Dispatch sent messages here. */
         while ( co_MsqDispatchOneSentMessage(pti) )
         {
@@ -1087,7 +1093,7 @@
 
     KeQueryTickCount(&LargeTickCount);
     Message.time = MsqCalculateMessageTime(&LargeTickCount);
-    MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0);
+    MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0, 0);
     return TRUE;
 }
 
@@ -1218,7 +1224,7 @@
         }
         else
         {
-            MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0);
+            MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0, 0);
         }
     }
     return TRUE;
@@ -1411,6 +1417,7 @@
 
 CLEANUP:
     if (Window) UserDerefObjectCo(Window);
+    // Current Thread and it's a Copy Data message, then free kernel memory.
     if ( !ptiSendTo && Msg == WM_COPYDATA )
     {
        ExFreePool((PVOID) lParam);
@@ -1677,7 +1684,7 @@
     END_CLEANUP;
 }
 
-
+#if 0
 /*
   This HACK function posts a message if the destination's message queue 
belongs to
   another thread, otherwise it sends the message. It does not support broadcast
@@ -1721,6 +1728,7 @@
 
     return (LRESULT)Result;
 }
+#endif
 
 static LRESULT FASTCALL
 co_IntDoSendMessage( HWND hWnd,

Modified: trunk/reactos/win32ss/user/ntuser/msgqueue.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/msgqueue.c?rev=65472&r1=65471&r2=65472&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/msgqueue.c        [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/msgqueue.c        [iso-8859-1] Mon Nov 24 
02:50:18 2014
@@ -15,6 +15,9 @@
 
 static PPAGED_LOOKASIDE_LIST pgMessageLookasideList;
 PUSER_MESSAGE_QUEUE gpqCursor;
+ULONG_PTR gdwMouseMoveExtraInfo = 0;
+DWORD gdwMouseMoveTimeStamp = 0;
+
 
 /* FUNCTIONS *****************************************************************/
 
@@ -311,6 +314,36 @@
     }
 }
 
+/*
+    Get down key states from the queue of prior processed input message key 
states.
+
+    This fixes the left button dragging on the desktop and release sticking 
outline issue.
+    USB Tablet pointer seems to stick the most and leaves the box outline 
displayed.
+ */
+WPARAM FASTCALL
+MsqGetDownKeyState(PUSER_MESSAGE_QUEUE MessageQueue)
+{
+    WPARAM ret = 0;
+
+    if (gspv.bMouseBtnSwap)
+    {
+       if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_RBUTTON)) ret |= 
MK_LBUTTON;
+       if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_LBUTTON)) ret |= 
MK_RBUTTON;
+    }
+    else
+    {
+       if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_LBUTTON)) ret |= 
MK_LBUTTON;
+       if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_RBUTTON)) ret |= 
MK_RBUTTON;
+    }
+
+    if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_MBUTTON))  ret |= MK_MBUTTON;
+    if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_SHIFT))    ret |= MK_SHIFT;
+    if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_CONTROL))  ret |= MK_CONTROL;
+    if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_XBUTTON1)) ret |= MK_XBUTTON1;
+    if (IS_KEY_DOWN(MessageQueue->afKeyState, VK_XBUTTON2)) ret |= MK_XBUTTON2;
+    return ret;
+}
+
 HANDLE FASTCALL
 IntMsqSetWakeMask(DWORD WakeMask)
 {
@@ -397,26 +430,18 @@
 VOID FASTCALL
 ClearMsgBitsMask(PTHREADINFO pti, UINT MessageBits)
 {
-   PUSER_MESSAGE_QUEUE Queue;
    UINT ClrMask = 0;
 
-   Queue = pti->MessageQueue;
-
    if (MessageBits & QS_KEY)
    {
       if (--pti->nCntsQBits[QSRosKey] == 0) ClrMask |= QS_KEY;
    }
-   if (MessageBits & QS_MOUSEMOVE) // ReactOS hard coded.
+   if (MessageBits & QS_MOUSEMOVE)
    {  // Account for tracking mouse moves..
       if (pti->nCntsQBits[QSRosMouseMove]) 
       {
          pti->nCntsQBits[QSRosMouseMove] = 0; // Throttle down count. Up to > 
3:1 entries are ignored.
-      }
-      // Handle mouse move bits here.
-      if (Queue->MouseMoved)
-      {
          ClrMask |= QS_MOUSEMOVE;
-         Queue->MouseMoved = FALSE;
       }
    }
    if (MessageBits & QS_MOUSEBUTTON)
@@ -472,10 +497,11 @@
 }
 
 /*
-    Post Mouse Move.
+    Post the move or update the message still pending to be processed.
+    Do not overload the queue with mouse move messages.
  */
 VOID FASTCALL
-MsqPostMouseMove(PTHREADINFO pti, MSG* Msg)
+MsqPostMouseMove(PTHREADINFO pti, MSG* Msg, LONG_PTR ExtraInfo)
 {
     PUSER_MESSAGE Message;
     PLIST_ENTRY ListHead;
@@ -483,22 +509,59 @@
 
     ListHead = &MessageQueue->HardwareMessagesListHead;
 
-    MessageQueue->MouseMoved = TRUE;
-
+    // Do nothing if empty.
     if (!IsListEmpty(ListHead->Flink))
-    {  // Look at the end of the list,
+    {
+       // Look at the end of the list,
        Message = CONTAINING_RECORD(ListHead->Blink, USER_MESSAGE, ListEntry);
-       // If the mouse move message is existing,
+
+       // If the mouse move message is existing on the list,
        if (Message->Msg.message == WM_MOUSEMOVE)
        {
-          TRACE("Post Old MM Message in Q\n");
-          Message->Msg = *Msg; // Overwrite the message with updated data!
+          // Overwrite the message with updated data!
+          Message->Msg = *Msg;
+
           MsqWakeQueue(pti, QS_MOUSEMOVE, TRUE);
           return;
        }
     }
-    TRACE("Post New MM Message to Q\n");
-    MsqPostMessage(pti, Msg, TRUE, QS_MOUSEMOVE, 0);
+
+    MsqPostMessage(pti, Msg, TRUE, QS_MOUSEMOVE, 0, ExtraInfo);
+}
+
+/*
+    Bring together the mouse move message.
+    Named "Coalesce" from Amine email ;^) (jt).
+ */
+VOID FASTCALL
+IntCoalesceMouseMove(PTHREADINFO pti)
+{
+    MSG Msg;
+    LARGE_INTEGER LargeTickCount;
+
+    // Force time stamp to update, keeping message time in sync.
+    if (gdwMouseMoveTimeStamp == 0)
+    {
+       KeQueryTickCount(&LargeTickCount);
+       gdwMouseMoveTimeStamp = MsqCalculateMessageTime(&LargeTickCount);
+    }
+
+    // Build mouse move message.
+    Msg.hwnd    = NULL;
+    Msg.message = WM_MOUSEMOVE;
+    Msg.wParam  = 0;
+    Msg.lParam  = MAKELONG(gpsi->ptCursor.x, gpsi->ptCursor.y);
+    Msg.time    = gdwMouseMoveTimeStamp;
+    Msg.pt      = gpsi->ptCursor;
+
+    // Post the move.
+    MsqPostMouseMove(pti, &Msg, gdwMouseMoveExtraInfo);
+
+    // Zero the time stamp.
+    gdwMouseMoveTimeStamp = 0;
+
+    // Clear flag since the move was posted.
+    pti->MessageQueue->QF_flags &= ~QF_MOUSEMOVED;
 }
 
 VOID FASTCALL
@@ -626,7 +689,10 @@
            gpqCursor = MessageQueue;
 
            /* Mouse move is a special case */
-           MsqPostMouseMove(pti, Msg);
+           MessageQueue->QF_flags |= QF_MOUSEMOVED;
+           gdwMouseMoveExtraInfo = dwExtraInfo;
+           gdwMouseMoveTimeStamp = Msg->time;
+           MsqWakeQueue(pti, QS_MOUSEMOVE, TRUE);
        }
        else
        {
@@ -636,8 +702,15 @@
              // ptiLastInput = pti; // Once this is set during Reboot or 
Shutdown, this prevents the exit window having foreground.
              // Find all the Move Mouse calls and fix mouse set active focus 
issues......
            }
+
+           // Post mouse move before posting mouse buttons, keep it in sync.
+           if (pti->MessageQueue->QF_flags & QF_MOUSEMOVED)
+           {
+              IntCoalesceMouseMove(pti);
+           }
+
            TRACE("Posting mouse message to hwnd=%p!\n", UserHMGetHandle(pwnd));
-           MsqPostMessage(pti, Msg, TRUE, QS_MOUSEBUTTON, 0);
+           MsqPostMessage(pti, Msg, TRUE, QS_MOUSEBUTTON, 0, dwExtraInfo);
        }
    }
    else if (hdcScreen)
@@ -1207,7 +1280,8 @@
                MSG* Msg,
                BOOLEAN HardwareMessage,
                DWORD MessageBits,
-               DWORD dwQEvent)
+               DWORD dwQEvent,
+               LONG_PTR ExtraInfo)
 {
    PUSER_MESSAGE Message;
    PUSER_MESSAGE_QUEUE MessageQueue;
@@ -1244,6 +1318,7 @@
 
    if (Msg->message == WM_HOTKEY) MessageBits |= QS_HOTKEY; // Justin Case, 
just set it.
    Message->dwQEvent = dwQEvent;
+   Message->ExtraInfo = ExtraInfo;
    Message->QS_Flags = MessageBits;
    Message->pti = pti;
    MsqWakeQueue(pti, MessageBits, TRUE);
@@ -1375,12 +1450,13 @@
     }
     else
     {
-        pwndMsg = co_WinPosWindowFromPoint(NULL, &msg->pt, &hittest, 
FALSE);//TRUE);
+        pwndMsg = co_WinPosWindowFromPoint(pwndMsg, &msg->pt, &hittest, FALSE);
     }
 
     TRACE("Got mouse message for %p, hittest: 0x%x\n", msg->hwnd, hittest);
 
-    if (pwndMsg == NULL || pwndMsg->head.pti != pti)
+    // Null window or not the same "Hardware" message queue.
+    if (pwndMsg == NULL || pwndMsg->head.pti->MessageQueue != 
pti->MessageQueue)
     {
         /* Remove and ignore the message */
         *RemoveMessages = TRUE;
@@ -1469,6 +1545,12 @@
         {
             TRACE("Message out of range!!!\n");
             RETURN(FALSE);
+        }
+
+        // Update mouse move down keys.
+        if (message == WM_MOUSEMOVE)
+        {
+           msg->wParam = MsqGetDownKeyState(MessageQueue);
         }
     }
 
@@ -1739,7 +1821,8 @@
  */
       if ( ( !Window || // 1
             ( Window == PWND_BOTTOM && CurrentMessage->Msg.hwnd == NULL ) || 
// 2
-            ( Window != PWND_BOTTOM && Window->head.h == 
CurrentMessage->Msg.hwnd ) ) && // 3
+            ( Window != PWND_BOTTOM && Window->head.h == 
CurrentMessage->Msg.hwnd ) || // 3
+            ( CurrentMessage->Msg.message == WM_MOUSEMOVE ) ) && // Null 
window for mouse moves.
             ( ( ( MsgFilterLow == 0 && MsgFilterHigh == 0 ) && 
CurrentMessage->QS_Flags & QSflags ) ||
               ( MsgFilterLow <= CurrentMessage->Msg.message && MsgFilterHigh 
>= CurrentMessage->Msg.message ) ) )
         {

Modified: trunk/reactos/win32ss/user/ntuser/msgqueue.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/msgqueue.h?rev=65472&r1=65471&r2=65472&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/msgqueue.h        [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/msgqueue.h        [iso-8859-1] Mon Nov 24 
02:50:18 2014
@@ -51,9 +51,7 @@
 
   /* Queue for hardware messages for the queue. */
   LIST_ENTRY HardwareMessagesListHead;
-  /* True if a WM_MOUSEMOVE is pending */
-  BOOLEAN MouseMoved;
-  /* Current WM_MOUSEMOVE message */
+  /* Last click message for translating double clicks */
   MSG msgDblClk;
   /* Current capture window for this queue. */
   PWND spwndCapture;
@@ -92,7 +90,7 @@
 #define QF_FMENUSTATUSBREAK       0x00000004
 #define QF_FMENUSTATUS            0x00000008
 #define QF_FF10STATUS             0x00000010
-#define QF_MOUSEMOVED             0x00000020 // See MouseMoved.
+#define QF_MOUSEMOVED             0x00000020
 #define QF_ACTIVATIONCHANGE       0x00000040
 #define QF_TABSWITCHING           0x00000080
 #define QF_KEYSTATERESET          0x00000100
@@ -122,7 +120,7 @@
            UINT uTimeout, BOOL Block, INT HookMessage, ULONG_PTR *uResult);
 PUSER_MESSAGE FASTCALL MsqCreateMessage(LPMSG Msg);
 VOID FASTCALL MsqDestroyMessage(PUSER_MESSAGE Message);
-VOID FASTCALL MsqPostMessage(PTHREADINFO, MSG*, BOOLEAN, DWORD, DWORD);
+VOID FASTCALL MsqPostMessage(PTHREADINFO, MSG*, BOOLEAN, DWORD, DWORD, 
LONG_PTR);
 VOID FASTCALL MsqPostQuitMessage(PTHREADINFO pti, ULONG ExitCode);
 BOOLEAN APIENTRY
 MsqPeekMessage(IN PTHREADINFO pti,
@@ -186,6 +184,7 @@
                        BOOL HasPackedLParam,
                        INT HookMessage);
 
+VOID FASTCALL IntCoalesceMouseMove(PTHREADINFO);
 LRESULT FASTCALL IntDispatchMessage(MSG* Msg);
 BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, UINT flags);
 VOID FASTCALL co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR 
dwExtraInfo, BOOL Hook);
@@ -246,6 +245,7 @@
 VOID FASTCALL MsqWakeQueue(PTHREADINFO,DWORD,BOOL);
 VOID FASTCALL ClearMsgBitsMask(PTHREADINFO,UINT);
 BOOL FASTCALL IntCallMsgFilter(LPMSG,INT);
+WPARAM FASTCALL MsqGetDownKeyState(PUSER_MESSAGE_QUEUE);
 
 int UserShowCursor(BOOL bShow);
 PCURICON_OBJECT

Modified: trunk/reactos/win32ss/user/ntuser/timer.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/timer.c?rev=65472&r1=65471&r2=65472&view=diff
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/timer.c   [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/timer.c   [iso-8859-1] Mon Nov 24 
02:50:18 2014
@@ -320,7 +320,7 @@
              {
                 if (pDesk->htEx == HTCLIENT) // In a client area.
                 {
-                   wParam = UserGetMouseButtonsState();
+                   wParam = MsqGetDownKeyState(pWnd->head.pti->MessageQueue);
                    Msg = WM_MOUSEHOVER;
 
                    if (pWnd->ExStyle & WS_EX_LAYOUTRTL)
@@ -405,7 +405,7 @@
            Msg.wParam  = (WPARAM) pTmr->nID;
            Msg.lParam  = (LPARAM) pTmr->pfn;
 
-           MsqPostMessage(pti, &Msg, FALSE, 
(QS_POSTMESSAGE|QS_ALLPOSTMESSAGE), 0);
+           MsqPostMessage(pti, &Msg, FALSE, 
(QS_POSTMESSAGE|QS_ALLPOSTMESSAGE), 0, 0);
            pTmr->flags &= ~TMRF_READY;
            ClearMsgBitsMask(pti, QS_TIMER);
            Hit = TRUE;


Reply via email to