From 77fc4e22d15b13ec8de6d5f5672cfd3ea8ea9537 Mon Sep 17 00:00:00 2001 From: Rafal Harabien Date: Fri, 14 Oct 2011 18:41:06 +0000 Subject: [PATCH] [WIN32K] - Move mouse specific input processing from input.c to mouse.c svn path=/trunk/; revision=54140 --- .../subsystems/win32/win32k/CMakeLists.txt | 1 + .../subsystems/win32/win32k/include/input.h | 1 + .../subsystems/win32/win32k/ntuser/input.c | 544 +---------------- .../subsystems/win32/win32k/ntuser/mouse.c | 548 ++++++++++++++++++ reactos/subsystems/win32/win32k/win32k.rbuild | 1 + 5 files changed, 555 insertions(+), 540 deletions(-) create mode 100644 reactos/subsystems/win32/win32k/ntuser/mouse.c diff --git a/reactos/subsystems/win32/win32k/CMakeLists.txt b/reactos/subsystems/win32/win32k/CMakeLists.txt index 4dc998c1246..15611011731 100644 --- a/reactos/subsystems/win32/win32k/CMakeLists.txt +++ b/reactos/subsystems/win32/win32k/CMakeLists.txt @@ -106,6 +106,7 @@ list(APPEND SOURCE ntuser/metric.c ntuser/misc.c ntuser/monitor.c + ntuser/mouse.c ntuser/msgqueue.c ntuser/ntstubs.c ntuser/ntuser.c diff --git a/reactos/subsystems/win32/win32k/include/input.h b/reactos/subsystems/win32/win32k/include/input.h index 3101c104f98..ba7d52b8b28 100644 --- a/reactos/subsystems/win32/win32k/include/input.h +++ b/reactos/subsystems/win32/win32k/include/input.h @@ -42,6 +42,7 @@ VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice); PKBL W32kGetDefaultKeyLayout(VOID); VOID NTAPI UserProcessKeyboardInput(PKEYBOARD_INPUT_DATA pKeyInput); BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected); +VOID NTAPI UserProcessMouseInput(PMOUSE_INPUT_DATA Data, ULONG InputCount); BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt); BOOL FASTCALL IntMouseInput(MOUSEINPUT *mi, BOOL Injected); BOOL UserInitDefaultKeyboardLayout(VOID); diff --git a/reactos/subsystems/win32/win32k/ntuser/input.c b/reactos/subsystems/win32/win32k/ntuser/input.c index e51667753c8..ed2ba56a2c7 100644 --- a/reactos/subsystems/win32/win32k/ntuser/input.c +++ b/reactos/subsystems/win32/win32k/ntuser/input.c @@ -1,7 +1,7 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * PURPOSE: Window classes + * PURPOSE: General input functions * FILE: subsystems/win32/win32k/ntuser/input.c * PROGRAMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) * Rafal Harabien (rafalh@reactos.org) @@ -29,19 +29,6 @@ static BOOLEAN InputThreadsRunning = FALSE; /* FUNCTIONS *****************************************************************/ -#define ClearMouseInput(mi) \ - mi.dx = 0; \ - mi.dy = 0; \ - mi.mouseData = 0; \ - mi.dwFlags = 0; - -#define SendMouseEvent(mi) \ - if(mi.dx != 0 || mi.dy != 0) \ - mi.dwFlags |= MOUSEEVENTF_MOVE; \ - if(mi.dwFlags) \ - IntMouseInput(&mi,FALSE); \ - ClearMouseInput(mi); - static DWORD FASTCALL IntLastInputTick(BOOL bUpdate) { @@ -91,97 +78,6 @@ DoTheScreenSaver(VOID) } } -static VOID NTAPI -IntProcessMouseInputData(PMOUSE_INPUT_DATA Data, ULONG InputCount) -{ - PMOUSE_INPUT_DATA mid; - MOUSEINPUT mi; - ULONG i; - - ClearMouseInput(mi); - mi.time = 0; - mi.dwExtraInfo = 0; - for(i = 0; i < InputCount; i++) - { - mid = (Data + i); - mi.dx += mid->LastX; - mi.dy += mid->LastY; - - /* Check if the mouse move is absolute */ - if (mid->Flags == MOUSE_MOVE_ABSOLUTE) - { - /* Set flag to convert to screen location */ - mi.dwFlags |= MOUSEEVENTF_ABSOLUTE; - } - - if(mid->ButtonFlags) - { - if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) - { - mi.dwFlags |= MOUSEEVENTF_LEFTDOWN; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_UP) - { - mi.dwFlags |= MOUSEEVENTF_LEFTUP; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) - { - mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) - { - mi.dwFlags |= MOUSEEVENTF_MIDDLEUP; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) - { - mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_UP) - { - mi.dwFlags |= MOUSEEVENTF_RIGHTUP; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_BUTTON_4_DOWN) - { - mi.mouseData |= XBUTTON1; - mi.dwFlags |= MOUSEEVENTF_XDOWN; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_BUTTON_4_UP) - { - mi.mouseData |= XBUTTON1; - mi.dwFlags |= MOUSEEVENTF_XUP; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_BUTTON_5_DOWN) - { - mi.mouseData |= XBUTTON2; - mi.dwFlags |= MOUSEEVENTF_XDOWN; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_BUTTON_5_UP) - { - mi.mouseData |= XBUTTON2; - mi.dwFlags |= MOUSEEVENTF_XUP; - SendMouseEvent(mi); - } - if(mid->ButtonFlags & MOUSE_WHEEL) - { - mi.mouseData = mid->ButtonData; - mi.dwFlags |= MOUSEEVENTF_WHEEL; - SendMouseEvent(mi); - } - } - } - - SendMouseEvent(mi); -} - static VOID APIENTRY MouseThreadMain(PVOID StartContext) { @@ -282,7 +178,7 @@ MouseThreadMain(PVOID StartContext) UserEnterExclusive(); - IntProcessMouseInputData(&MouseInput, Iosb.Information / sizeof(MOUSE_INPUT_DATA)); + UserProcessMouseInput(&MouseInput, Iosb.Information / sizeof(MOUSE_INPUT_DATA)); UserLeave(); } @@ -570,175 +466,6 @@ NtUserBlockInput( return ret; } -BOOL FASTCALL -IntMouseInput(MOUSEINPUT *mi, BOOL Injected) -{ - const UINT SwapBtnMsg[2][2] = - { - {WM_LBUTTONDOWN, WM_RBUTTONDOWN}, - {WM_LBUTTONUP, WM_RBUTTONUP} - }; - const WPARAM SwapBtn[2] = - { - MK_LBUTTON, MK_RBUTTON - }; - POINT MousePos; - PSYSTEM_CURSORINFO CurInfo; - BOOL SwapButtons; - MSG Msg; - - ASSERT(mi); - - CurInfo = IntGetSysCursorInfo(); - - if(!mi->time) - { - LARGE_INTEGER LargeTickCount; - KeQueryTickCount(&LargeTickCount); - mi->time = MsqCalculateMessageTime(&LargeTickCount); - } - - SwapButtons = gspv.bMouseBtnSwap; - - MousePos = gpsi->ptCursor; - - if(mi->dwFlags & MOUSEEVENTF_MOVE) - { - if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE) - { - MousePos.x = mi->dx * UserGetSystemMetrics(SM_CXVIRTUALSCREEN) >> 16; - MousePos.y = mi->dy * UserGetSystemMetrics(SM_CYVIRTUALSCREEN) >> 16; - } - else - { - MousePos.x += mi->dx; - MousePos.y += mi->dy; - } - } - - /* - * Insert the messages into the system queue - */ - Msg.wParam = 0; - Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y); - Msg.pt = MousePos; - - if (IS_KEY_DOWN(gafAsyncKeyState, VK_SHIFT)) - { - Msg.wParam |= MK_SHIFT; - } - - if (IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL)) - { - Msg.wParam |= MK_CONTROL; - } - - if(mi->dwFlags & MOUSEEVENTF_MOVE) - { - UserSetCursorPos(MousePos.x, MousePos.y, Injected, mi->dwExtraInfo, TRUE); - } - if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON, TRUE); - Msg.message = SwapBtnMsg[0][SwapButtons]; - CurInfo->ButtonsDown |= SwapBtn[SwapButtons]; - Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - else if(mi->dwFlags & MOUSEEVENTF_LEFTUP) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON, FALSE); - Msg.message = SwapBtnMsg[1][SwapButtons]; - CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons]; - Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON, TRUE); - Msg.message = WM_MBUTTONDOWN; - CurInfo->ButtonsDown |= MK_MBUTTON; - Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON, FALSE); - Msg.message = WM_MBUTTONUP; - CurInfo->ButtonsDown &= ~MK_MBUTTON; - Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON, TRUE); - Msg.message = SwapBtnMsg[0][!SwapButtons]; - CurInfo->ButtonsDown |= SwapBtn[!SwapButtons]; - Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON, FALSE); - Msg.message = SwapBtnMsg[1][!SwapButtons]; - CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons]; - Msg.wParam |= CurInfo->ButtonsDown; - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - - if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) && - (mi->dwFlags & MOUSEEVENTF_WHEEL)) - { - /* fail because both types of events use the mouseData field */ - return FALSE; - } - - if(mi->dwFlags & MOUSEEVENTF_XDOWN) - { - Msg.message = WM_XBUTTONDOWN; - if(mi->mouseData & XBUTTON1) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1, TRUE); - CurInfo->ButtonsDown |= MK_XBUTTON1; - Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - if(mi->mouseData & XBUTTON2) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2, TRUE); - CurInfo->ButtonsDown |= MK_XBUTTON2; - Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - } - else if(mi->dwFlags & MOUSEEVENTF_XUP) - { - Msg.message = WM_XBUTTONUP; - if(mi->mouseData & XBUTTON1) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1, FALSE); - CurInfo->ButtonsDown &= ~MK_XBUTTON1; - Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - if(mi->mouseData & XBUTTON2) - { - SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2, FALSE); - CurInfo->ButtonsDown &= ~MK_XBUTTON2; - Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - } - if(mi->dwFlags & MOUSEEVENTF_WHEEL) - { - Msg.message = WM_MOUSEWHEEL; - Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData); - co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); - } - - return TRUE; -} - BOOL FASTCALL UserAttachThreadInput(PTHREADINFO pti, PTHREADINFO ptiTo, BOOL fAttach) { @@ -823,7 +550,7 @@ NtUserSendInput( * e.g. services running in the service window station cannot block input */ if (!ThreadHasInputAccess(pti) || - !IntIsActiveDesktop(pti->rpdesk)) + !IntIsActiveDesktop(pti->rpdesk)) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( 0); @@ -853,6 +580,7 @@ NtUserSendInput( cnt++; break; case INPUT_HARDWARE: + FIXME("INPUT_HARDWARE not supported!"); break; default: ERR("SendInput(): Invalid input type: 0x%x\n", SafeInput.type); @@ -868,268 +596,4 @@ CLEANUP: 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; - - /* 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. - { - pDesk->spwndTrack = pWnd; - 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; - - TRACE("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: - TRACE("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); - - TRACE("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: - TRACE("Leave NtUserGetMouseMovePointsEx, ret=%i\n", _ret_); - UserLeave(); - END_CLEANUP; -} - /* EOF */ diff --git a/reactos/subsystems/win32/win32k/ntuser/mouse.c b/reactos/subsystems/win32/win32k/ntuser/mouse.c new file mode 100644 index 00000000000..e3c4e239943 --- /dev/null +++ b/reactos/subsystems/win32/win32k/ntuser/mouse.c @@ -0,0 +1,548 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * PURPOSE: Mouse functions + * FILE: subsystems/win32/win32k/ntuser/input.c + * PROGRAMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) + * Rafal Harabien (rafalh@reactos.org) + */ + +#include +DBG_DEFAULT_CHANNEL(UserInput); + +#define ClearMouseInput(mi) \ + mi.dx = 0; \ + mi.dy = 0; \ + mi.mouseData = 0; \ + mi.dwFlags = 0; + +#define SendMouseEvent(mi) \ + if(mi.dx != 0 || mi.dy != 0) \ + mi.dwFlags |= MOUSEEVENTF_MOVE; \ + if(mi.dwFlags) \ + IntMouseInput(&mi,FALSE); \ + ClearMouseInput(mi); + +VOID NTAPI +UserProcessMouseInput(PMOUSE_INPUT_DATA Data, ULONG InputCount) +{ + PMOUSE_INPUT_DATA mid; + MOUSEINPUT mi; + ULONG i; + + ClearMouseInput(mi); + mi.time = 0; + mi.dwExtraInfo = 0; + for(i = 0; i < InputCount; i++) + { + mid = (Data + i); + mi.dx += mid->LastX; + mi.dy += mid->LastY; + + /* Check if the mouse move is absolute */ + if (mid->Flags == MOUSE_MOVE_ABSOLUTE) + { + /* Set flag to convert to screen location */ + mi.dwFlags |= MOUSEEVENTF_ABSOLUTE; + } + + if(mid->ButtonFlags) + { + if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) + { + mi.dwFlags |= MOUSEEVENTF_LEFTDOWN; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_LEFT_BUTTON_UP) + { + mi.dwFlags |= MOUSEEVENTF_LEFTUP; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) + { + mi.dwFlags |= MOUSEEVENTF_MIDDLEDOWN; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) + { + mi.dwFlags |= MOUSEEVENTF_MIDDLEUP; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) + { + mi.dwFlags |= MOUSEEVENTF_RIGHTDOWN; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_RIGHT_BUTTON_UP) + { + mi.dwFlags |= MOUSEEVENTF_RIGHTUP; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_BUTTON_4_DOWN) + { + mi.mouseData |= XBUTTON1; + mi.dwFlags |= MOUSEEVENTF_XDOWN; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_BUTTON_4_UP) + { + mi.mouseData |= XBUTTON1; + mi.dwFlags |= MOUSEEVENTF_XUP; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_BUTTON_5_DOWN) + { + mi.mouseData |= XBUTTON2; + mi.dwFlags |= MOUSEEVENTF_XDOWN; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_BUTTON_5_UP) + { + mi.mouseData |= XBUTTON2; + mi.dwFlags |= MOUSEEVENTF_XUP; + SendMouseEvent(mi); + } + if(mid->ButtonFlags & MOUSE_WHEEL) + { + mi.mouseData = mid->ButtonData; + mi.dwFlags |= MOUSEEVENTF_WHEEL; + SendMouseEvent(mi); + } + } + } + + SendMouseEvent(mi); +} + +BOOL FASTCALL +IntMouseInput(MOUSEINPUT *mi, BOOL Injected) +{ + const UINT SwapBtnMsg[2][2] = + { + {WM_LBUTTONDOWN, WM_RBUTTONDOWN}, + {WM_LBUTTONUP, WM_RBUTTONUP} + }; + const WPARAM SwapBtn[2] = + { + MK_LBUTTON, MK_RBUTTON + }; + POINT MousePos; + PSYSTEM_CURSORINFO CurInfo; + BOOL SwapButtons; + MSG Msg; + + ASSERT(mi); + + CurInfo = IntGetSysCursorInfo(); + + if(!mi->time) + { + LARGE_INTEGER LargeTickCount; + KeQueryTickCount(&LargeTickCount); + mi->time = MsqCalculateMessageTime(&LargeTickCount); + } + + SwapButtons = gspv.bMouseBtnSwap; + + MousePos = gpsi->ptCursor; + + if(mi->dwFlags & MOUSEEVENTF_MOVE) + { + if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE) + { + MousePos.x = mi->dx * UserGetSystemMetrics(SM_CXVIRTUALSCREEN) >> 16; + MousePos.y = mi->dy * UserGetSystemMetrics(SM_CYVIRTUALSCREEN) >> 16; + } + else + { + MousePos.x += mi->dx; + MousePos.y += mi->dy; + } + } + + /* + * Insert the messages into the system queue + */ + Msg.wParam = 0; + Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y); + Msg.pt = MousePos; + + if (IS_KEY_DOWN(gafAsyncKeyState, VK_SHIFT)) + { + Msg.wParam |= MK_SHIFT; + } + + if (IS_KEY_DOWN(gafAsyncKeyState, VK_CONTROL)) + { + Msg.wParam |= MK_CONTROL; + } + + if(mi->dwFlags & MOUSEEVENTF_MOVE) + { + UserSetCursorPos(MousePos.x, MousePos.y, Injected, mi->dwExtraInfo, TRUE); + } + if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON, TRUE); + Msg.message = SwapBtnMsg[0][SwapButtons]; + CurInfo->ButtonsDown |= SwapBtn[SwapButtons]; + Msg.wParam |= CurInfo->ButtonsDown; + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + else if(mi->dwFlags & MOUSEEVENTF_LEFTUP) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_LBUTTON, FALSE); + Msg.message = SwapBtnMsg[1][SwapButtons]; + CurInfo->ButtonsDown &= ~SwapBtn[SwapButtons]; + Msg.wParam |= CurInfo->ButtonsDown; + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + if(mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON, TRUE); + Msg.message = WM_MBUTTONDOWN; + CurInfo->ButtonsDown |= MK_MBUTTON; + Msg.wParam |= CurInfo->ButtonsDown; + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + else if(mi->dwFlags & MOUSEEVENTF_MIDDLEUP) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_MBUTTON, FALSE); + Msg.message = WM_MBUTTONUP; + CurInfo->ButtonsDown &= ~MK_MBUTTON; + Msg.wParam |= CurInfo->ButtonsDown; + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + if(mi->dwFlags & MOUSEEVENTF_RIGHTDOWN) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON, TRUE); + Msg.message = SwapBtnMsg[0][!SwapButtons]; + CurInfo->ButtonsDown |= SwapBtn[!SwapButtons]; + Msg.wParam |= CurInfo->ButtonsDown; + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + else if(mi->dwFlags & MOUSEEVENTF_RIGHTUP) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_RBUTTON, FALSE); + Msg.message = SwapBtnMsg[1][!SwapButtons]; + CurInfo->ButtonsDown &= ~SwapBtn[!SwapButtons]; + Msg.wParam |= CurInfo->ButtonsDown; + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + + if((mi->dwFlags & (MOUSEEVENTF_XDOWN | MOUSEEVENTF_XUP)) && + (mi->dwFlags & MOUSEEVENTF_WHEEL)) + { + /* fail because both types of events use the mouseData field */ + return FALSE; + } + + if(mi->dwFlags & MOUSEEVENTF_XDOWN) + { + Msg.message = WM_XBUTTONDOWN; + if(mi->mouseData & XBUTTON1) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1, TRUE); + CurInfo->ButtonsDown |= MK_XBUTTON1; + Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + if(mi->mouseData & XBUTTON2) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2, TRUE); + CurInfo->ButtonsDown |= MK_XBUTTON2; + Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + } + else if(mi->dwFlags & MOUSEEVENTF_XUP) + { + Msg.message = WM_XBUTTONUP; + if(mi->mouseData & XBUTTON1) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON1, FALSE); + CurInfo->ButtonsDown &= ~MK_XBUTTON1; + Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON1); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + if(mi->mouseData & XBUTTON2) + { + SET_KEY_DOWN(gafAsyncKeyState, VK_XBUTTON2, FALSE); + CurInfo->ButtonsDown &= ~MK_XBUTTON2; + Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, XBUTTON2); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + } + if(mi->dwFlags & MOUSEEVENTF_WHEEL) + { + Msg.message = WM_MOUSEWHEEL; + Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, mi->mouseData); + co_MsqInsertMouseMessage(&Msg, Injected, mi->dwExtraInfo, TRUE); + } + + return TRUE; +} + +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; + + /* 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. + { + pDesk->spwndTrack = pWnd; + 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; + + TRACE("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: + TRACE("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); + + TRACE("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: + TRACE("Leave NtUserGetMouseMovePointsEx, ret=%i\n", _ret_); + UserLeave(); + END_CLEANUP; +} diff --git a/reactos/subsystems/win32/win32k/win32k.rbuild b/reactos/subsystems/win32/win32k/win32k.rbuild index 5be2e9422c4..c4f7d130766 100644 --- a/reactos/subsystems/win32/win32k/win32k.rbuild +++ b/reactos/subsystems/win32/win32k/win32k.rbuild @@ -144,6 +144,7 @@ metric.c misc.c monitor.c + mouse.c msgqueue.c ntstubs.c ntuser.c