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-i…
- 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…
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/keyboa…
==============================================================================
--- 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/messag…
==============================================================================
--- 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/msgque…
==============================================================================
--- 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/msgque…
==============================================================================
--- 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.…
==============================================================================
--- 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;