* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window classes
- * FILE: subsys/win32k/ntuser/class.c
+ * FILE: subsystems/win32/win32k/ntuser/input.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
/* INCLUDES ******************************************************************/
-#include <w32k.h>
+#include <win32k.h>
#include <ntddkbd.h>
#define NDEBUG
/* GLOBALS *******************************************************************/
PTHREADINFO ptiRawInput;
-PKTIMER MasterTimer;
+PTHREADINFO ptiKeyboard;
+PTHREADINFO ptiMouse;
+PKTIMER MasterTimer = NULL;
PATTACHINFO gpai = NULL;
static HANDLE MouseDeviceHandle;
if(mi.dx != 0 || mi.dy != 0) \
mi.dwFlags |= MOUSEEVENTF_MOVE; \
if(mi.dwFlags) \
- IntMouseInput(&mi); \
+ IntMouseInput(&mi,FALSE); \
ClearMouseInput(mi);
{
if (ProbeForReadUint(&plii->cbSize) != sizeof(LASTINPUTINFO))
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
ret = FALSE;
_SEH2_LEAVE;
}
NTSTATUS Status;
MOUSE_ATTRIBUTES MouseAttr;
+ KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
+ LOW_REALTIME_PRIORITY + 3);
+
InitializeObjectAttributes(&MouseObjectAttributes,
&MouseDeviceName,
0,
FILE_SYNCHRONOUS_IO_ALERT);
} while (!NT_SUCCESS(Status));
+ /* Need to setup basic win32k for this thread to process WH_MOUSE_LL messages. */
+ Status = Win32kInitWin32Thread(PsGetCurrentThread());
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Win32K: Failed making mouse thread a win32 thread.\n");
+ return; //(Status);
+ }
+
+ ptiMouse = PsGetCurrentThreadWin32Thread();
+ ptiMouse->TIF_flags |= TIF_SYSTEMTHREAD;
+ DPRINT("Mouse Thread 0x%x \n", ptiMouse);
+
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
Ret = ExAllocatePoolWithTag(PagedPool,
Size,
- TAG_KEYBOARD);
+ USERTAG_KBDTABLE);
while (Ret)
{
if (Status != STATUS_BUFFER_TOO_SMALL)
break;
- ExFreePoolWithTag(Ret, TAG_KEYBOARD);
+ ExFreePoolWithTag(Ret, USERTAG_KBDTABLE);
Size += sizeof(KEYBOARD_INDICATOR_TRANSLATION);
Ret = ExAllocatePoolWithTag(PagedPool,
Size,
- TAG_KEYBOARD);
+ USERTAG_KBDTABLE);
}
if (!Ret)
if (Status != STATUS_SUCCESS)
{
- ExFreePoolWithTag(Ret, TAG_KEYBOARD);
+ ExFreePoolWithTag(Ret, USERTAG_KBDTABLE);
return Status;
}
static VOID APIENTRY
IntKeyboardSendWinKeyMsg()
{
- PWINDOW_OBJECT Window;
+ PWND Window;
MSG Mesg;
if (!(Window = UserGetWindowObject(InputWindowStation->ShellWindow)))
Mesg.lParam = 0;
/* The QS_HOTKEY is just a guess */
- MsqPostMessage(Window->pti->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
+ MsqPostMessage(Window->head.pti->MessageQueue, &Mesg, FALSE, QS_HOTKEY);
}
static VOID APIENTRY
co_IntKeyboardSendAltKeyMsg()
{
- co_MsqPostKeyboardMessage(WM_SYSCOMMAND,SC_KEYMENU,0);
+ DPRINT1("co_IntKeyboardSendAltKeyMsg\n");
+// co_MsqPostKeyboardMessage(WM_SYSCOMMAND,SC_KEYMENU,0); This sends everything into a msg loop!
}
static VOID APIENTRY
return; //(Status);
}
+ ptiKeyboard = PsGetCurrentThreadWin32Thread();
+ ptiKeyboard->TIF_flags |= TIF_SYSTEMTHREAD;
+ DPRINT("Keyboard Thread 0x%x \n", ptiKeyboard);
+
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
if (ModifierState == 0)
{
+ UserEnterExclusive();
if (fsModifiers == MOD_WIN)
IntKeyboardSendWinKeyMsg();
else if (fsModifiers == MOD_ALT)
}
co_IntKeyboardSendAltKeyMsg();
}
+ UserLeave();
continue;
}
}
}
+ UserEnterExclusive();
+
for (;NumKeys;memcpy(&KeyInput, &NextKeyInput, sizeof(KeyInput)),
NumKeys--)
{
+ PKBL keyboardLayout = NULL;
lParam = 0;
IntKeyboardUpdateLeds(KeyboardDeviceHandle,
if (ModifierState & MOD_ALT)
{
- lParam |= (1 << 29);
+ lParam |= (1 << 29); // wine -> (HIWORD(lParam) & KEYDATA_ALT) #define KEYDATA_ALT 0x2000
if (!(KeyInput.Flags & KEY_BREAK))
msg.message = WM_SYSKEYDOWN;
}
/* Find the target thread whose locale is in effect */
- FocusQueue = IntGetFocusMessageQueue();
-
- /* This might cause us to lose hot keys, which are important
- * (ctrl-alt-del secure attention sequence). Not sure if it
- * can happen though.
- */
- if (!FocusQueue)
- continue;
+ FocusQueue = IntGetFocusMessageQueue();
- msg.lParam = lParam;
- msg.hwnd = FocusQueue->FocusWindow;
+ if (FocusQueue)
+ {
+ msg.hwnd = FocusQueue->FocusWindow;
- FocusThread = FocusQueue->Thread;
+ FocusThread = FocusQueue->Thread;
+ if (FocusThread && FocusThread->Tcb.Win32Thread)
+ {
+ keyboardLayout = ((PTHREADINFO)FocusThread->Tcb.Win32Thread)->KeyboardLayout;
+ }
+ }
+ if (!keyboardLayout)
+ {
+ keyboardLayout = W32kGetDefaultKeyLayout();
+ }
- if (!(FocusThread && FocusThread->Tcb.Win32Thread &&
- ((PTHREADINFO)FocusThread->Tcb.Win32Thread)->KeyboardLayout))
- continue;
+ msg.lParam = lParam;
/* This function uses lParam to fill wParam according to the
* keyboard layout in use.
*/
W32kKeyProcessMessage(&msg,
- ((PTHREADINFO)FocusThread->Tcb.Win32Thread)->KeyboardLayout->KBTables,
+ keyboardLayout->KBTables,
KeyInput.Flags & KEY_E0 ? 0xE0 :
(KeyInput.Flags & KEY_E1 ? 0xE1 : 0));
continue; /* Eat key up motion too */
}
+ if (!FocusQueue)
+ {
+ /* There is no focused window to receive a keyboard message */
+ continue;
+ }
/*
* Post a keyboard message.
*/
co_MsqPostKeyboardMessage(msg.message,msg.wParam,msg.lParam);
}
+
+ UserLeave();
}
KeyboardEscape:
Objects[0] = &InputThreadsStart;
-
- MasterTimer = ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), TAG_INPUT);
- if (!MasterTimer)
- {
- DPRINT1("Win32K: Failed making Raw Input thread a win32 thread.\n");
- return;
- }
- KeInitializeTimer(MasterTimer);
Objects[1] = MasterTimer;
// This thread requires win32k!
}
ptiRawInput = PsGetCurrentThreadWin32Thread();
- DPRINT("\nRaw Input Thread 0x%x \n", ptiRawInput);
-
+ ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD;
+ DPRINT("Raw Input Thread 0x%x \n", ptiRawInput);
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
LOW_REALTIME_PRIORITY + 3);
DPRINT1("Raw Input Thread Exit!\n");
}
-NTSTATUS FASTCALL
+INIT_FUNCTION
+NTSTATUS
+NTAPI
InitInputImpl(VOID)
{
NTSTATUS Status;
KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
+ MasterTimer = ExAllocatePoolWithTag(NonPagedPool, sizeof(KTIMER), USERTAG_SYSTEM);
+ if (!MasterTimer)
+ {
+ DPRINT1("Win32K: Failed making Raw Input thread a win32 thread.\n");
+ ASSERT(FALSE);
+ return STATUS_UNSUCCESSFUL;
+ }
+ KeInitializeTimer(MasterTimer);
+
/* Initialize the default keyboard layout */
if(!UserInitDefaultKeyboardLayout())
{
return(STATUS_SUCCESS);
}
-BOOL
-APIENTRY
-NtUserDragDetect(
- HWND hWnd,
- POINT pt) // Just like the User call.
-{
- UNIMPLEMENTED
- return 0;
-}
-
BOOL FASTCALL
IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt)
{
if(!ThreadHasInputAccess(W32Thread) ||
!IntIsActiveDesktop(W32Thread->rpdesk))
{
- SetLastWin32Error(ERROR_ACCESS_DENIED);
+ EngSetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
{
if(OldBlock != W32Thread)
{
- SetLastWin32Error(ERROR_ACCESS_DENIED);
+ EngSetLastError(ERROR_ACCESS_DENIED);
return FALSE;
}
W32Thread->rpdesk->BlockInputThread = (BlockIt ? W32Thread : NULL);
}
BOOL FASTCALL
-IntMouseInput(MOUSEINPUT *mi)
+IntMouseInput(MOUSEINPUT *mi, BOOL Injected)
{
const UINT SwapBtnMsg[2][2] =
{
/*
* Insert the messages into the system queue
*/
- Msg.wParam = CurInfo->ButtonsDown;
+ Msg.wParam = 0;
Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y);
Msg.pt = MousePos;
if(mi->dwFlags & MOUSEEVENTF_MOVE)
{
- UserSetCursorPos(MousePos.x, MousePos.y);
+ UserSetCursorPos(MousePos.x, MousePos.y, Injected, mi->dwExtraInfo, TRUE);
}
if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN)
{
gQueueKeyStateTable[VK_LBUTTON] |= 0xc0;
Msg.message = SwapBtnMsg[0][SwapButtons];
CurInfo->ButtonsDown |= SwapBtn[SwapButtons];
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
else if(mi->dwFlags & MOUSEEVENTF_LEFTUP)
{
gQueueKeyStateTable[VK_LBUTTON] &= ~0x80;
Msg.message = SwapBtnMsg[1][SwapButtons];
CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons];
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
{
gQueueKeyStateTable[VK_MBUTTON] |= 0xc0;
Msg.message = WM_MBUTTONDOWN;
CurInfo->ButtonsDown |= MK_MBUTTON;
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
{
gQueueKeyStateTable[VK_MBUTTON] &= ~0x80;
Msg.message = WM_MBUTTONUP;
CurInfo->ButtonsDown &= ~MK_MBUTTON;
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN)
{
gQueueKeyStateTable[VK_RBUTTON] |= 0xc0;
Msg.message = SwapBtnMsg[0][!SwapButtons];
CurInfo->ButtonsDown |= SwapBtn[!SwapButtons];
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP)
{
gQueueKeyStateTable[VK_RBUTTON] &= ~0x80;
Msg.message = SwapBtnMsg[1][!SwapButtons];
CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons];
- MsqInsertSystemMessage(&Msg);
+ Msg.wParam |= CurInfo->ButtonsDown;
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) &&
if(mi->mouseData & XBUTTON1)
{
gQueueKeyStateTable[VK_XBUTTON1] |= 0xc0;
+ CurInfo->ButtonsDown |= MK_XBUTTON1;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
- CurInfo->ButtonsDown |= XBUTTON1;
- MsqInsertSystemMessage(&Msg);
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
if(mi->mouseData & XBUTTON2)
{
gQueueKeyStateTable[VK_XBUTTON2] |= 0xc0;
+ CurInfo->ButtonsDown |= MK_XBUTTON2;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
- CurInfo->ButtonsDown |= XBUTTON2;
- MsqInsertSystemMessage(&Msg);
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
}
else if(mi->dwFlags & MOUSEEVENTF_XUP)
if(mi->mouseData & XBUTTON1)
{
gQueueKeyStateTable[VK_XBUTTON1] &= ~0x80;
+ CurInfo->ButtonsDown &= ~MK_XBUTTON1;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1);
- CurInfo->ButtonsDown &= ~XBUTTON1;
- MsqInsertSystemMessage(&Msg);
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
if(mi->mouseData & XBUTTON2)
{
gQueueKeyStateTable[VK_XBUTTON2] &= ~0x80;
+ CurInfo->ButtonsDown &= ~MK_XBUTTON2;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2);
- CurInfo->ButtonsDown &= ~XBUTTON2;
- MsqInsertSystemMessage(&Msg);
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
}
if(mi->dwFlags & MOUSEEVENTF_WHEEL)
{
Msg.message = WM_MOUSEWHEEL;
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData);
- MsqInsertSystemMessage(&Msg);
+ co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE);
}
return TRUE;
}
BOOL FASTCALL
-IntKeyboardInput(KEYBDINPUT *ki)
+IntKeyboardInput(KEYBDINPUT *ki, BOOL Injected)
{
PUSER_MESSAGE_QUEUE FocusMessageQueue;
- PTHREADINFO pti;
MSG Msg;
LARGE_INTEGER LargeTickCount;
KBDLLHOOKSTRUCT KbdHookData;
WORD flags, wVkStripped, wVkL, wVkR, wVk = ki->wVk, vk_hook = ki->wVk;
- BOOLEAN Entered = FALSE;
Msg.lParam = 0;
- // Condition may arise when calling MsqPostMessage and waiting for an event.
- if (!UserIsEntered())
- {
- // Fixme: Not sure ATM if this thread is locked.
- UserEnterExclusive();
- Entered = TRUE;
- }
+ // Condition may arise when calling MsqPostMessage and waiting for an event.
+ ASSERT (UserIsEntered());
wVk = LOBYTE(wVk);
Msg.wParam = wVk;
if (ki->dwFlags & KEYEVENTF_KEYUP)
{
Msg.message = WM_KEYUP;
- if ((gQueueKeyStateTable[VK_MENU] & 0x80) &&
+ if (((gQueueKeyStateTable[VK_MENU] & 0x80) &&
((wVkStripped == VK_MENU) || (wVkStripped == VK_CONTROL)
|| !(gQueueKeyStateTable[VK_CONTROL] & 0x80)))
+ || (wVkStripped == VK_F10))
{
if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
(wVkStripped != VK_MENU)) /* <ALT>-down...<something else>-up */
else
{
Msg.message = WM_KEYDOWN;
- if ((gQueueKeyStateTable[VK_MENU] & 0x80 || wVkStripped == VK_MENU) &&
+ if (((gQueueKeyStateTable[VK_MENU] & 0x80 || wVkStripped == VK_MENU) &&
!(gQueueKeyStateTable[VK_CONTROL] & 0x80 || wVkStripped == VK_CONTROL))
+ || (wVkStripped == VK_F10))
{
Msg.message = WM_SYSKEYDOWN;
TrackSysKey = wVkStripped;
Msg.time = ki->time;
/* All messages have to contain the cursor point. */
- pti = PsGetCurrentThreadWin32Thread();
Msg.pt = gpsi->ptCursor;
- DPRINT1("Kbd Hook msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
- Msg.message, vk_hook, Msg.lParam);
-
KbdHookData.vkCode = vk_hook;
KbdHookData.scanCode = ki->wScan;
KbdHookData.flags = flags >> 8;
+ if (Injected) KbdHookData.flags |= LLKHF_INJECTED;
KbdHookData.time = Msg.time;
KbdHookData.dwExtraInfo = ki->dwExtraInfo;
if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
{
- DPRINT("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
+ DPRINT1("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
Msg.message, vk_hook, Msg.lParam);
- if (Entered) UserLeave();
+
return FALSE;
}
if (FocusMessageQueue == NULL)
{
DPRINT("No focus message queue\n");
- if (Entered) UserLeave();
+
return FALSE;
}
FocusMessageQueue->Desktop->pDeskInfo->LastInputWasKbd = TRUE;
Msg.pt = gpsi->ptCursor;
-
- MsqPostMessage(FocusMessageQueue, &Msg, FALSE, QS_KEY);
+ // Post to hardware queue, based on the first part of wine "some GetMessage tests"
+ // in test_PeekMessage()
+ MsqPostMessage(FocusMessageQueue, &Msg, TRUE, QS_KEY);
}
else
{
DPRINT("Invalid focus window handle\n");
}
- if (Entered) UserLeave();
-
return TRUE;
}
/* If Attach set, allocate and link. */
if ( fAttach )
{
- pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), TAG_ATTACHINFO);
+ pai = ExAllocatePoolWithTag(PagedPool, sizeof(ATTACHINFO), USERTAG_ATTACHINFO);
if ( !pai ) return FALSE;
pai->paiNext = gpai;
if (paiprev) paiprev->paiNext = pai->paiNext;
- ExFreePoolWithTag(pai, TAG_ATTACHINFO);
+ ExFreePoolWithTag(pai, USERTAG_ATTACHINFO);
}
return TRUE;
if(!nInputs || !pInput || (cbSize != sizeof(INPUT)))
{
- SetLastWin32Error(ERROR_INVALID_PARAMETER);
+ EngSetLastError(ERROR_INVALID_PARAMETER);
RETURN( 0);
}
if(!ThreadHasInputAccess(W32Thread) ||
!IntIsActiveDesktop(W32Thread->rpdesk))
{
- SetLastWin32Error(ERROR_ACCESS_DENIED);
+ EngSetLastError(ERROR_ACCESS_DENIED);
RETURN( 0);
}
switch(SafeInput.type)
{
case INPUT_MOUSE:
- if(IntMouseInput(&SafeInput.mi))
+ if(IntMouseInput(&SafeInput.mi, TRUE))
{
cnt++;
}
break;
case INPUT_KEYBOARD:
- if(IntKeyboardInput(&SafeInput.ki))
+ if(IntKeyboardInput(&SafeInput.ki, TRUE))
{
cnt++;
}
END_CLEANUP;
}
+BOOL
+FASTCALL
+IntQueryTrackMouseEvent(
+ LPTRACKMOUSEEVENT lpEventTrack)
+{
+ PDESKTOP pDesk;
+ PTHREADINFO pti;
+
+ pti = PsGetCurrentThreadWin32Thread();
+ pDesk = pti->rpdesk;
+
+ /* Always cleared with size set and return true. */
+ RtlZeroMemory(lpEventTrack ,sizeof(TRACKMOUSEEVENT));
+ lpEventTrack->cbSize = sizeof(TRACKMOUSEEVENT);
+
+ if ( pDesk->dwDTFlags & (DF_TME_LEAVE|DF_TME_HOVER) &&
+ pDesk->spwndTrack &&
+ pti->MessageQueue == pDesk->spwndTrack->head.pti->MessageQueue )
+ {
+ if ( pDesk->htEx != HTCLIENT )
+ lpEventTrack->dwFlags |= TME_NONCLIENT;
+
+ if ( pDesk->dwDTFlags & DF_TME_LEAVE )
+ lpEventTrack->dwFlags |= TME_LEAVE;
+
+ if ( pDesk->dwDTFlags & DF_TME_HOVER )
+ {
+ lpEventTrack->dwFlags |= TME_HOVER;
+ lpEventTrack->dwHoverTime = pDesk->dwMouseHoverTime;
+ }
+ lpEventTrack->hwndTrack = UserHMGetHandle(pDesk->spwndTrack);
+ }
+ return TRUE;
+}
+
+BOOL
+FASTCALL
+IntTrackMouseEvent(
+ LPTRACKMOUSEEVENT lpEventTrack)
+{
+ PDESKTOP pDesk;
+ PTHREADINFO pti;
+ PWND pWnd;
+ POINT point;
+
+ pti = PsGetCurrentThreadWin32Thread();
+ pDesk = pti->rpdesk;
+
+ if (!(pWnd = UserGetWindowObject(lpEventTrack->hwndTrack)))
+ return FALSE;
+
+ if ( pDesk->spwndTrack != pWnd ||
+ (pDesk->htEx != HTCLIENT) ^ !!(lpEventTrack->dwFlags & TME_NONCLIENT) )
+ {
+ if ( lpEventTrack->dwFlags & TME_LEAVE && !(lpEventTrack->dwFlags & TME_CANCEL) )
+ {
+ UserPostMessage( lpEventTrack->hwndTrack,
+ lpEventTrack->dwFlags & TME_NONCLIENT ? WM_NCMOUSELEAVE : WM_MOUSELEAVE,
+ 0, 0);
+ }
+ DPRINT("IntTrackMouseEvent spwndTrack 0x%x pwnd 0x%x\n", pDesk->spwndTrack,pWnd);
+ return TRUE;
+ }
+
+ /* Tracking spwndTrack same as pWnd */
+ if ( lpEventTrack->dwFlags & TME_CANCEL ) // Canceled mode.
+ {
+ if ( lpEventTrack->dwFlags & TME_LEAVE )
+ pDesk->dwDTFlags &= ~DF_TME_LEAVE;
+
+ if ( lpEventTrack->dwFlags & TME_HOVER )
+ {
+ if ( pDesk->dwDTFlags & DF_TME_HOVER )
+ { // Kill hover timer.
+ IntKillTimer(pWnd, ID_EVENT_SYSTIMER_MOUSEHOVER, TRUE);
+ pDesk->dwDTFlags &= ~DF_TME_HOVER;
+ }
+ }
+ }
+ else // Not Canceled.
+ {
+ if ( lpEventTrack->dwFlags & TME_LEAVE )
+ pDesk->dwDTFlags |= DF_TME_LEAVE;
+
+ if ( lpEventTrack->dwFlags & TME_HOVER )
+ {
+ pDesk->dwDTFlags |= DF_TME_HOVER;
+
+ if ( !lpEventTrack->dwHoverTime || lpEventTrack->dwHoverTime == HOVER_DEFAULT )
+ pDesk->dwMouseHoverTime = gspv.iMouseHoverTime; // use the system default hover time-out.
+ else
+ pDesk->dwMouseHoverTime = lpEventTrack->dwHoverTime;
+ // Start timer for the hover period.
+ IntSetTimer( pWnd, ID_EVENT_SYSTIMER_MOUSEHOVER, pDesk->dwMouseHoverTime, SystemTimerProc, TMRF_SYSTEM);
+ // Get windows thread message points.
+ point = pWnd->head.pti->ptLast;
+ // Set desktop mouse hover from the system default hover rectangle.
+ RECTL_vSetRect(&pDesk->rcMouseHover,
+ point.x - gspv.iMouseHoverWidth / 2,
+ point.y - gspv.iMouseHoverHeight / 2,
+ point.x + gspv.iMouseHoverWidth / 2,
+ point.y + gspv.iMouseHoverHeight / 2);
+ }
+ }
+ return TRUE;
+}
+
+BOOL
+APIENTRY
+NtUserTrackMouseEvent(
+ LPTRACKMOUSEEVENT lpEventTrack)
+{
+ TRACKMOUSEEVENT saveTME;
+ BOOL Ret = FALSE;
+
+ DPRINT("Enter NtUserTrackMouseEvent\n");
+ UserEnterExclusive();
+
+ _SEH2_TRY
+ {
+ ProbeForRead(lpEventTrack, sizeof(TRACKMOUSEEVENT), 1);
+ RtlCopyMemory(&saveTME, lpEventTrack, sizeof(TRACKMOUSEEVENT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(goto Exit;)
+ }
+ _SEH2_END;
+
+ if ( saveTME.cbSize != sizeof(TRACKMOUSEEVENT) )
+ {
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ goto Exit;
+ }
+
+ if (saveTME.dwFlags & ~(TME_CANCEL|TME_QUERY|TME_NONCLIENT|TME_LEAVE|TME_HOVER) )
+ {
+ EngSetLastError(ERROR_INVALID_FLAGS);
+ goto Exit;
+ }
+
+ if ( saveTME.dwFlags & TME_QUERY )
+ {
+ Ret = IntQueryTrackMouseEvent(&saveTME);
+ _SEH2_TRY
+ {
+ ProbeForWrite(lpEventTrack, sizeof(TRACKMOUSEEVENT), 1);
+ RtlCopyMemory(lpEventTrack, &saveTME, sizeof(TRACKMOUSEEVENT));
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ Ret = FALSE;
+ }
+ _SEH2_END;
+ }
+ else
+ {
+ Ret = IntTrackMouseEvent(&saveTME);
+ }
+
+Exit:
+ DPRINT("Leave NtUserTrackMouseEvent, ret=%i\n",Ret);
+ UserLeave();
+ return Ret;
+}
+
+extern MOUSEMOVEPOINT MouseHistoryOfMoves[];
+extern INT gcur_count;
+
+DWORD
+APIENTRY
+NtUserGetMouseMovePointsEx(
+ UINT cbSize,
+ LPMOUSEMOVEPOINT lpptIn,
+ LPMOUSEMOVEPOINT lpptOut,
+ int nBufPoints,
+ DWORD resolution)
+{
+ MOUSEMOVEPOINT Safeppt;
+ BOOL Hit;
+ INT Count = -1;
+ DECLARE_RETURN(DWORD);
+
+ DPRINT("Enter NtUserGetMouseMovePointsEx\n");
+ UserEnterExclusive();
+
+ if ((cbSize != sizeof(MOUSEMOVEPOINT)) || (nBufPoints < 0) || (nBufPoints > 64))
+ {
+ EngSetLastError(ERROR_INVALID_PARAMETER);
+ RETURN( -1);
+ }
+
+ if (!lpptIn || (!lpptOut && nBufPoints))
+ {
+ EngSetLastError(ERROR_NOACCESS);
+ RETURN( -1);
+ }
+
+ _SEH2_TRY
+ {
+ ProbeForRead( lpptIn, cbSize, 1);
+ RtlCopyMemory(&Safeppt, lpptIn, cbSize);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(RETURN( -1))
+ }
+ _SEH2_END;
+
+ // http://msdn.microsoft.com/en-us/library/ms646259(v=vs.85).aspx
+ // This explains the math issues in transforming points.
+ Count = gcur_count; // FIFO is forward so retrieve backward.
+ Hit = FALSE;
+ do
+ {
+ if (Safeppt.x == 0 && Safeppt.y == 0)
+ break; // No test.
+ // Finds the point, it returns the last nBufPoints prior to and including the supplied point.
+ if (MouseHistoryOfMoves[Count].x == Safeppt.x && MouseHistoryOfMoves[Count].y == Safeppt.y)
+ {
+ if ( Safeppt.time ) // Now test time and it seems to be absolute.
+ {
+ if (Safeppt.time == MouseHistoryOfMoves[Count].time)
+ {
+ Hit = TRUE;
+ break;
+ }
+ else
+ {
+ if (--Count < 0) Count = 63;
+ continue;
+ }
+ }
+ Hit = TRUE;
+ break;
+ }
+ if (--Count < 0) Count = 63;
+ }
+ while ( Count != gcur_count);
+
+ switch(resolution)
+ {
+ case GMMP_USE_DISPLAY_POINTS:
+ if (nBufPoints)
+ {
+ _SEH2_TRY
+ {
+ ProbeForWrite(lpptOut, cbSize, 1);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ SetLastNtError(_SEH2_GetExceptionCode());
+ _SEH2_YIELD(RETURN( -1))
+ }
+ _SEH2_END;
+ }
+ Count = nBufPoints;
+ break;
+ case GMMP_USE_HIGH_RESOLUTION_POINTS:
+ break;
+ default:
+ EngSetLastError(ERROR_POINT_NOT_FOUND);
+ RETURN( -1);
+ }
+
+ RETURN( Count);
+
+CLEANUP:
+ DPRINT("Leave NtUserGetMouseMovePointsEx, ret=%i\n",_ret_);
+ UserLeave();
+ END_CLEANUP;
+}
+
/* EOF */