From b8882998c7fb602a3aeb4480f797ed26e4f168ba Mon Sep 17 00:00:00 2001 From: Giannis Adamopoulos Date: Wed, 6 Jan 2010 12:44:31 +0000 Subject: [PATCH] [win32k] - Rewrite SetCursorPos and ShowCursror - Store coursor show count in SYSTEM_CURSORINFO and not in GDIPOINTER - Fix broken behaviour in ClipCursor svn path=/trunk/; revision=44975 --- reactos/dll/win32/user32/include/user32p.h | 3 + reactos/dll/win32/user32/windows/cursor.c | 13 +- reactos/subsystems/win32/win32k/eng/mouse.c | 17 +- .../win32/win32k/include/cursoricon.h | 6 +- .../subsystems/win32/win32k/include/pdevobj.h | 1 - .../win32/win32k/ntuser/cursoricon.c | 196 +++++++++--------- .../subsystems/win32/win32k/ntuser/input.c | 110 +--------- .../win32/win32k/ntuser/simplecall.c | 4 + 8 files changed, 123 insertions(+), 227 deletions(-) diff --git a/reactos/dll/win32/user32/include/user32p.h b/reactos/dll/win32/user32/include/user32p.h index 3f99b845e6c..fabbb092d4a 100644 --- a/reactos/dll/win32/user32/include/user32p.h +++ b/reactos/dll/win32/user32/include/user32p.h @@ -99,6 +99,9 @@ #define NtUserGetDesktopMapping(Ptr) \ (PVOID)NtUserCallOneParam((DWORD)Ptr, ONEPARAM_ROUTINE_GETDESKTOPMAPPING) +#define NtUserSetCursorPos(x, y) \ + (BOOL)NtUserCallTwoParam((DWORD)x, (DWORD)y, TWOPARAM_ROUTINE_SETCURSORPOS) + #define ShowCaret(hwnd) \ NtUserShowCaret(hwnd) diff --git a/reactos/dll/win32/user32/windows/cursor.c b/reactos/dll/win32/user32/windows/cursor.c index 6e804e3f7a6..1119ef1cd9a 100644 --- a/reactos/dll/win32/user32/windows/cursor.c +++ b/reactos/dll/win32/user32/windows/cursor.c @@ -280,18 +280,7 @@ WINAPI SetCursorPos(int X, int Y) { - INPUT Input; - - Input.type = INPUT_MOUSE; - Input.mi.dx = (LONG)X; - Input.mi.dy = (LONG)Y; - Input.mi.mouseData = 0; - Input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE; - Input.mi.time = 0; - Input.mi.dwExtraInfo = 0; - - NtUserSendInput(1, &Input, sizeof(INPUT)); - return TRUE; + return NtUserSetCursorPos(X,Y); } diff --git a/reactos/subsystems/win32/win32k/eng/mouse.c b/reactos/subsystems/win32/win32k/eng/mouse.c index 60e15b15aba..d96e8dd4ed2 100644 --- a/reactos/subsystems/win32/win32k/eng/mouse.c +++ b/reactos/subsystems/win32/win32k/eng/mouse.c @@ -157,12 +157,6 @@ IntHideMousePointer( pgp->Enabled = FALSE; - /* The mouse is hide from ShowCours and it is frist ?? */ - if (pgp->ShowPointer < 0) - { - return; - } - if (!pgp->psurfSave) { DPRINT1("No SaveSurface!\n"); @@ -215,12 +209,6 @@ IntShowMousePointer(PDEVOBJ *ppdev, SURFOBJ *psoDest) pgp->Enabled = TRUE; - /* Do not blt the pointer, if it is hidden */ - if (pgp->ShowPointer < 0) - { - return ; - } - /* Calculate pointer coordinates */ pt.x = ppdev->ptlPointer.x - pgp->HotSpot.x; pt.y = ppdev->ptlPointer.y - pgp->HotSpot.y; @@ -538,8 +526,11 @@ EngMovePointer( prcl->right = prcl->left + pgp->Size.cx; prcl->bottom = prcl->top + pgp->Size.cy; } - } else if (prcl != NULL) + } + else if (prcl != NULL) + { prcl->left = prcl->top = prcl->right = prcl->bottom = -1; + } } VOID APIENTRY diff --git a/reactos/subsystems/win32/win32k/include/cursoricon.h b/reactos/subsystems/win32/win32k/include/cursoricon.h index 12bf5b13a21..6e3b39a43f4 100644 --- a/reactos/subsystems/win32/win32k/include/cursoricon.h +++ b/reactos/subsystems/win32/win32k/include/cursoricon.h @@ -47,7 +47,7 @@ typedef struct _SYSTEM_CURSORINFO UINT ButtonsDown; CURSORCLIP_INFO CursorClipInfo; PCURICON_OBJECT CurrentCursorObject; - BYTE ShowingCursor; + INT ShowingCursor; /* UINT WheelScroLines; UINT WheelScroChars; @@ -77,9 +77,9 @@ BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxW INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags); PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon); -BOOL FASTCALL UserSetCursorPos( INT x, INT y); +BOOL UserSetCursorPos( INT x, INT y); -int APIENTRY UserShowCursor(BOOL bShow); +int UserShowCursor(BOOL bShow); PSYSTEM_CURSORINFO FASTCALL IntGetSysCursorInfo(); diff --git a/reactos/subsystems/win32/win32k/include/pdevobj.h b/reactos/subsystems/win32/win32k/include/pdevobj.h index 01b7c536c58..94b3d56405b 100644 --- a/reactos/subsystems/win32/win32k/include/pdevobj.h +++ b/reactos/subsystems/win32/win32k/include/pdevobj.h @@ -33,7 +33,6 @@ typedef struct _GDIPOINTER /* should stay private to ENG? No, part of PDEVOBJ ak SURFACE *psurfColor; SURFACE *psurfMask; SURFACE *psurfSave; - int ShowPointer; /* counter negtive do not show the mouse postive show the mouse */ /* public pointer information */ RECTL Exclude; /* required publicly for SPS_ACCEPT_EXCLUDE */ diff --git a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c index 40b6c68e4e7..e5befbf9962 100644 --- a/reactos/subsystems/win32/win32k/ntuser/cursoricon.c +++ b/reactos/subsystems/win32/win32k/ntuser/cursoricon.c @@ -137,7 +137,7 @@ UserSetCursor( { UserReferenceObject(NewCursor); - CurInfo->ShowingCursor = CURSOR_SHOWING; + CurInfo->ShowingCursor = 1; CurInfo->CurrentCursorObject = NewCursor; /* Call GDI to set the new screen cursor */ @@ -175,6 +175,101 @@ UserSetCursor( return hOldCursor; } +BOOL UserSetCursorPos( INT x, INT y) +{ + PWINDOW_OBJECT DesktopWindow; + PSYSTEM_CURSORINFO CurInfo; + HDC hDC; + MSG Msg; + + if(!(hDC = IntGetScreenDC())) + { + return FALSE; + } + + CurInfo = IntGetSysCursorInfo(); + + DesktopWindow = UserGetDesktopWindow(); + + if (DesktopWindow) + { + if(x >= DesktopWindow->Wnd->rcClient.right) + x = DesktopWindow->Wnd->rcClient.right - 1; + if(y >= DesktopWindow->Wnd->rcClient.bottom) + y = DesktopWindow->Wnd->rcClient.bottom - 1; + } + + if(x < 0) + x = 0; + if(y < 0) + y = 0; + + //Clip cursor position + if(CurInfo->CursorClipInfo.IsClipped) + { + if(x >= (LONG)CurInfo->CursorClipInfo.Right) + x = (LONG)CurInfo->CursorClipInfo.Right - 1; + if(x < (LONG)CurInfo->CursorClipInfo.Left) + x = (LONG)CurInfo->CursorClipInfo.Left; + if(y >= (LONG)CurInfo->CursorClipInfo.Bottom) + y = (LONG)CurInfo->CursorClipInfo.Bottom - 1; + if(y < (LONG)CurInfo->CursorClipInfo.Top) + y = (LONG)CurInfo->CursorClipInfo.Top; + } + + //Store the new cursor position + gpsi->ptCursor.x = x; + gpsi->ptCursor.y = y; + + //Move the mouse pointer + GreMovePointer(hDC, x, y); + + //Generate a mouse move message + Msg.message = WM_MOUSEMOVE; + Msg.wParam = CurInfo->ButtonsDown; + Msg.lParam = MAKELPARAM(x, y); + Msg.pt = gpsi->ptCursor; + MsqInsertSystemMessage(&Msg); + + return TRUE; +} + +/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR + * User32 macro NtUserShowCursor */ +int UserShowCursor(BOOL bShow) +{ + PSYSTEM_CURSORINFO CurInfo = IntGetSysCursorInfo();; + HDC hdcScreen; + + if (!(hdcScreen = IntGetScreenDC())) + { + return 0; /* No mouse */ + } + + if (bShow == FALSE) + { + /* Check if were diplaying a cursor */ + if (CurInfo->ShowingCursor == 1) + { + /* Remove the pointer */ + GreMovePointer(hdcScreen, -1, -1); + DPRINT("Removing pointer!\n"); + } + CurInfo->ShowingCursor--; + } + else + { + if (CurInfo->ShowingCursor == 0) + { + /*Show the pointer*/ + GreMovePointer(hdcScreen, gpsi->ptCursor.x, gpsi->ptCursor.y); + } + CurInfo->ShowingCursor++; + } + + return CurInfo->ShowingCursor; +} + /* * We have to register that this object is in use by the current * process. The only way to do that seems to be to walk the list @@ -712,21 +807,14 @@ NtUserClipCursor( if ((Rect.right > Rect.left) && (Rect.bottom > Rect.top) && DesktopWindow && UnsafeRect != NULL) { - MOUSEINPUT mi; CurInfo->CursorClipInfo.IsClipped = TRUE; CurInfo->CursorClipInfo.Left = max(Rect.left, DesktopWindow->Wnd->rcWindow.left); CurInfo->CursorClipInfo.Top = max(Rect.top, DesktopWindow->Wnd->rcWindow.top); - CurInfo->CursorClipInfo.Right = min(Rect.right - 1, DesktopWindow->Wnd->rcWindow.right - 1); - CurInfo->CursorClipInfo.Bottom = min(Rect.bottom - 1, DesktopWindow->Wnd->rcWindow.bottom - 1); + CurInfo->CursorClipInfo.Right = min(Rect.right, DesktopWindow->Wnd->rcWindow.right); + CurInfo->CursorClipInfo.Bottom = min(Rect.bottom, DesktopWindow->Wnd->rcWindow.bottom); - mi.dx = gpsi->ptCursor.x; - mi.dy = gpsi->ptCursor.y; - mi.mouseData = 0; - mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; - mi.time = 0; - mi.dwExtraInfo = 0; - IntMouseInput(&mi); + UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y); RETURN(TRUE); } @@ -1507,89 +1595,3 @@ NtUserDrawIconEx( return Ret; } -/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR - * User32 macro NtUserShowCursor */ -int -APIENTRY -UserShowCursor(BOOL bShow) -{ - PSYSTEM_CURSORINFO CurInfo; - HDC Screen; - PDC dc; - SURFOBJ *SurfObj; - SURFACE *psurfDc; - PDEVOBJ *ppdev; - GDIPOINTER *pgp; - int showpointer=0; - - CurInfo = IntGetSysCursorInfo(); - - if (!(Screen = IntGetScreenDC())) - { - return showpointer; /* No mouse */ - } - - dc = DC_LockDc(Screen); - - if (!dc) - { - return showpointer; /* No mouse */ - } - - psurfDc = dc->dclevel.pSurface; - - if (!psurfDc) - { - DC_UnlockDc(dc); - return showpointer; /* No Mouse */ - } - - SurfObj = &psurfDc->SurfObj; - if (SurfObj == NULL) - { - DC_UnlockDc(dc); - return showpointer; /* No mouse */ - } - - ppdev = GDIDEV(SurfObj); - - if (ppdev == NULL) - { - DC_UnlockDc(dc); - return showpointer; /* No mouse */ - } - - pgp = &ppdev->Pointer; - - if (bShow == FALSE) - { - pgp->ShowPointer--; - showpointer = pgp->ShowPointer; - - if (showpointer >= 0) - { - //ppdev->SafetyRemoveCount = 1; - //ppdev->SafetyRemoveLevel = 1; - IntEngMovePointer(SurfObj,-1,-1,NULL); - CurInfo->ShowingCursor = 0; - } - - } - else - { - pgp->ShowPointer++; - showpointer = pgp->ShowPointer; - - /* Show Cursor */ - if (showpointer < 0) - { - //ppdev->SafetyRemoveCount = 0; - //ppdev->SafetyRemoveLevel = 0; - IntEngMovePointer(SurfObj,-1,-1,NULL); - CurInfo->ShowingCursor = CURSOR_SHOWING; - } - } - - DC_UnlockDc(dc); - return showpointer; -} diff --git a/reactos/subsystems/win32/win32k/ntuser/input.c b/reactos/subsystems/win32/win32k/ntuser/input.c index 521fd15d906..2ecc9eda3e2 100644 --- a/reactos/subsystems/win32/win32k/ntuser/input.c +++ b/reactos/subsystems/win32/win32k/ntuser/input.c @@ -120,10 +120,8 @@ ProcessMouseInputData(PMOUSE_INPUT_DATA Data, ULONG InputCount) /* Check if the mouse move is absolute */ if (mid->Flags == MOUSE_MOVE_ABSOLUTE) { - /* Set flag and convert to screen location */ + /* Set flag to convert to screen location */ mi.dwFlags |= MOUSEEVENTF_ABSOLUTE; - mi.dx = mi.dx / (65535 / (UserGetSystemMetrics(SM_CXVIRTUALSCREEN) - 1)); - mi.dy = mi.dy / (65535 / (UserGetSystemMetrics(SM_CYVIRTUALSCREEN) - 1)); } if(mid->ButtonFlags) @@ -1052,48 +1050,19 @@ IntMouseInput(MOUSEINPUT *mi) { const UINT SwapBtnMsg[2][2] = { - { - WM_LBUTTONDOWN, WM_RBUTTONDOWN - }, + {WM_LBUTTONDOWN, WM_RBUTTONDOWN}, {WM_LBUTTONUP, WM_RBUTTONUP} }; const WPARAM SwapBtn[2] = { MK_LBUTTON, MK_RBUTTON }; - POINT MousePos = {0}, OrgPos; + POINT MousePos; PSYSTEM_CURSORINFO CurInfo; - PWINSTATION_OBJECT WinSta; - BOOL DoMove, SwapButtons; + BOOL SwapButtons; MSG Msg; - SURFACE *psurf; - SURFOBJ *pso; - PDC dc; - PWINDOW_OBJECT DesktopWindow; - -#if 1 - - HDC hDC; - - /* FIXME - get the screen dc from the window station or desktop */ - if(!(hDC = IntGetScreenDC())) - { - return FALSE; - } -#endif ASSERT(mi); -#if 0 - - WinSta = PsGetCurrentProcessWin32Process()->WindowStation; -#else - /* FIXME - ugly hack but as long as we're using this dumb callback from the - mouse class driver, we can't access the window station from the calling - process */ - WinSta = InputWindowStation; -#endif - - ASSERT(WinSta); CurInfo = IntGetSysCursorInfo(); @@ -1105,84 +1074,26 @@ IntMouseInput(MOUSEINPUT *mi) } SwapButtons = gspv.bMouseBtnSwap; - DoMove = FALSE; - OrgPos = MousePos = gpsi->ptCursor; + MousePos = gpsi->ptCursor; if(mi->dwFlags & MOUSEEVENTF_MOVE) { if(mi->dwFlags & MOUSEEVENTF_ABSOLUTE) { - MousePos.x = mi->dx; - MousePos.y = mi->dy; + 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; } - - DesktopWindow = IntGetWindowObject(WinSta->ActiveDesktop->DesktopWindow); - - if (DesktopWindow) - { - if(MousePos.x >= DesktopWindow->Wnd->rcClient.right) - MousePos.x = DesktopWindow->Wnd->rcClient.right - 1; - if(MousePos.y >= DesktopWindow->Wnd->rcClient.bottom) - MousePos.y = DesktopWindow->Wnd->rcClient.bottom - 1; - UserDereferenceObject(DesktopWindow); - } - - if(MousePos.x < 0) - MousePos.x = 0; - if(MousePos.y < 0) - MousePos.y = 0; - - if(CurInfo->CursorClipInfo.IsClipped) - { - /* The mouse cursor needs to be clipped */ - - if(MousePos.x >= (LONG)CurInfo->CursorClipInfo.Right) - MousePos.x = (LONG)CurInfo->CursorClipInfo.Right; - if(MousePos.x < (LONG)CurInfo->CursorClipInfo.Left) - MousePos.x = (LONG)CurInfo->CursorClipInfo.Left; - if(MousePos.y >= (LONG)CurInfo->CursorClipInfo.Bottom) - MousePos.y = (LONG)CurInfo->CursorClipInfo.Bottom; - if(MousePos.y < (LONG)CurInfo->CursorClipInfo.Top) - MousePos.y = (LONG)CurInfo->CursorClipInfo.Top; - } - - DoMove = (MousePos.x != OrgPos.x || MousePos.y != OrgPos.y); - } - - if (DoMove) - { - dc = DC_LockDc(hDC); - if (dc) - { - psurf = dc->dclevel.pSurface; - if (psurf) - { - pso = &psurf->SurfObj; - - if (CurInfo->ShowingCursor) - { - IntEngMovePointer(pso, MousePos.x, MousePos.y, &(GDIDEV(pso)->Pointer.Exclude)); - } - /* Only now, update the info in the PDEVOBJ, so EngMovePointer can - * use the old values to move the pointer image */ - gpsi->ptCursor.x = MousePos.x; - gpsi->ptCursor.y = MousePos.y; - } - - DC_UnlockDc(dc); - } } /* * Insert the messages into the system queue */ - Msg.wParam = CurInfo->ButtonsDown; Msg.lParam = MAKELPARAM(MousePos.x, MousePos.y); Msg.pt = MousePos; @@ -1197,13 +1108,10 @@ IntMouseInput(MOUSEINPUT *mi) Msg.wParam |= MK_CONTROL; } - if(DoMove) + if(mi->dwFlags & MOUSEEVENTF_MOVE) { - Msg.message = WM_MOUSEMOVE; - MsqInsertSystemMessage(&Msg); + UserSetCursorPos(MousePos.x, MousePos.y); } - - Msg.message = 0; if(mi->dwFlags & MOUSEEVENTF_LEFTDOWN) { gQueueKeyStateTable[VK_LBUTTON] |= 0xc0; diff --git a/reactos/subsystems/win32/win32k/ntuser/simplecall.c b/reactos/subsystems/win32/win32k/ntuser/simplecall.c index 2c978cb909c..072c9846aac 100644 --- a/reactos/subsystems/win32/win32k/ntuser/simplecall.c +++ b/reactos/subsystems/win32/win32k/ntuser/simplecall.c @@ -438,6 +438,10 @@ NtUserCallTwoParam( case TWOPARAM_ROUTINE_REGISTERLOGONPROC: RETURN( (DWORD_PTR)co_IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2)); + + case TWOPARAM_ROUTINE_SETCURSORPOS: + RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2)); + } DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n", Routine, Param1, Param2);