- 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

svn path=/trunk/; revision=65472
This commit is contained in:
James Tabor 2014-11-24 02:50:18 +00:00
parent 398b0a3c4f
commit 620eec28ea
5 changed files with 135 additions and 38 deletions

View file

@ -936,10 +936,16 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d
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 @@ IntTranslateKbdMessage(LPMSG lpMsg,
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 @@ IntTranslateKbdMessage(LPMSG lpMsg,
{
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;
}

View file

@ -802,6 +802,12 @@ co_IntPeekMessage( PMSG Msg,
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 @@ UserPostThreadMessage( PTHREADINFO pti,
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 @@ UserPostMessage( HWND Wnd,
}
else
{
MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0);
MsqPostMessage(pti, &Message, FALSE, QS_POSTMESSAGE, 0, 0);
}
}
return TRUE;
@ -1411,6 +1417,7 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
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 @@ CLEANUP:
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 @@ co_IntPostOrSendMessage( HWND hWnd,
return (LRESULT)Result;
}
#endif
static LRESULT FASTCALL
co_IntDoSendMessage( HWND hWnd,

View file

@ -15,6 +15,9 @@ DBG_DEFAULT_CHANNEL(UserMsgQ);
static PPAGED_LOOKASIDE_LIST pgMessageLookasideList;
PUSER_MESSAGE_QUEUE gpqCursor;
ULONG_PTR gdwMouseMoveExtraInfo = 0;
DWORD gdwMouseMoveTimeStamp = 0;
/* FUNCTIONS *****************************************************************/
@ -311,6 +314,36 @@ UpdateKeyStateFromMsg(PUSER_MESSAGE_QUEUE MessageQueue, MSG* msg)
}
}
/*
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 @@ MsqWakeQueue(PTHREADINFO pti, DWORD MessageBits, BOOL KeyEvent)
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 @@ MsqDecPaintCountQueue(PTHREADINFO pti)
}
/*
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 @@ MsqPostMouseMove(PTHREADINFO pti, MSG* Msg)
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 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
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 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
// 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 @@ MsqPostMessage(PTHREADINFO pti,
MSG* Msg,
BOOLEAN HardwareMessage,
DWORD MessageBits,
DWORD dwQEvent)
DWORD dwQEvent,
LONG_PTR ExtraInfo)
{
PUSER_MESSAGE Message;
PUSER_MESSAGE_QUEUE MessageQueue;
@ -1244,6 +1318,7 @@ MsqPostMessage(PTHREADINFO pti,
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 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
}
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;
@ -1470,6 +1546,12 @@ BOOL co_IntProcessMouseMessage(MSG* msg, BOOL* RemoveMessages, UINT first, UINT
TRACE("Message out of range!!!\n");
RETURN(FALSE);
}
// Update mouse move down keys.
if (message == WM_MOUSEMOVE)
{
msg->wParam = MsqGetDownKeyState(MessageQueue);
}
}
if(gspv.bMouseClickLock)
@ -1739,7 +1821,8 @@ co_MsqPeekHardwareMessage(IN PTHREADINFO pti,
*/
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 ) ) )
{

View file

@ -51,9 +51,7 @@ typedef struct _USER_MESSAGE_QUEUE
/* 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 @@ typedef struct _USER_MESSAGE_QUEUE
#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 @@ NTSTATUS FASTCALL co_MsqSendMessage(PTHREADINFO ptirec,
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 @@ co_MsqSendMessageAsync(PTHREADINFO ptiReceiver,
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 @@ BOOL FASTCALL co_MsqReplyMessage(LRESULT);
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

View file

@ -320,7 +320,7 @@ SystemTimerProc(HWND hwnd,
{
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 @@ PostTimerMessages(PWND Window)
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;