mirror of
https://github.com/reactos/reactos.git
synced 2024-09-28 21:44:31 +00:00
[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 svn path=/trunk/; revision=65472
This commit is contained in:
parent
398b0a3c4f
commit
620eec28ea
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 ) ) )
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue