From 53ee161d923cfbfe34644f5bb91637ba4d559e0b Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Sun, 24 Aug 2003 01:12:16 +0000 Subject: [PATCH] 1. ClipCursor(), GetClipCursor() in user32 2. NtUserClipCursor() and NtUserGetClipCursor() in win32k 3. moved system cursor information to WINSTATION_OBJECT 4. modified win32k mousedriver callback routine for cursor clipping svn path=/trunk/; revision=5807 --- reactos/lib/user32/misc/stubs.c | 15 +-- reactos/lib/user32/windows/cursor.c | 40 ++++++- reactos/ntoskrnl/include/internal/ex.h | 19 ++++ reactos/subsys/win32k/eng/mouse.c | 119 +++++++++++++++++---- reactos/subsys/win32k/include/mouse.h | 1 + reactos/subsys/win32k/include/winsta.h | 5 + reactos/subsys/win32k/ntuser/winsta.c | 29 ++++- reactos/subsys/win32k/objects/cursoricon.c | 71 ++++++++++-- 8 files changed, 252 insertions(+), 47 deletions(-) diff --git a/reactos/lib/user32/misc/stubs.c b/reactos/lib/user32/misc/stubs.c index 3bbfad6abc9..a1ed6a6447e 100644 --- a/reactos/lib/user32/misc/stubs.c +++ b/reactos/lib/user32/misc/stubs.c @@ -1,4 +1,4 @@ -/* $Id: stubs.c,v 1.36 2003/08/22 00:33:47 weiden Exp $ +/* $Id: stubs.c,v 1.37 2003/08/24 01:12:15 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS user32.dll @@ -109,19 +109,6 @@ CheckRadioButton( } -/* - * @unimplemented - */ -WINBOOL -STDCALL -ClipCursor( - CONST RECT *lpRect) -{ - UNIMPLEMENTED; - return FALSE; -} - - /* * @unimplemented */ diff --git a/reactos/lib/user32/windows/cursor.c b/reactos/lib/user32/windows/cursor.c index dc4e561df7e..ef93355ba38 100644 --- a/reactos/lib/user32/windows/cursor.c +++ b/reactos/lib/user32/windows/cursor.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: cursor.c,v 1.8 2003/07/27 11:54:41 dwelch Exp $ +/* $Id: cursor.c,v 1.9 2003/08/24 01:12:15 weiden Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/cursor.c @@ -30,6 +30,7 @@ #include #include +#include #include /* FUNCTIONS *****************************************************************/ @@ -65,13 +66,25 @@ DestroyCursor(HCURSOR hCursor) /* - * @unimplemented + * @implemented */ WINBOOL STDCALL GetClipCursor(LPRECT lpRect) { - UNIMPLEMENTED; - return FALSE; + RECT rc; + WINBOOL res; + + if(!lpRect) + { + SetLastError(ERROR_NOACCESS); + return FALSE; + } + + RtlCopyMemory(&rc, lpRect, sizeof(RECT)); + res = NtUserGetClipCursor(&rc); + RtlCopyMemory(lpRect, &rc, sizeof(RECT)); + + return res; } @@ -159,6 +172,25 @@ LoadCursorW(HINSTANCE hInstance, } +/* + * @implemented + */ +WINBOOL +STDCALL +ClipCursor( + CONST RECT *lpRect) +{ + RECT rc; + if(lpRect) + { + RtlCopyMemory(&rc, lpRect, sizeof(RECT)); + return NtUserClipCursor(&rc); + } + else + return NtUserClipCursor(NULL); +} + + /* * @unimplemented */ diff --git a/reactos/ntoskrnl/include/internal/ex.h b/reactos/ntoskrnl/include/internal/ex.h index cd29ca83187..6379098496e 100644 --- a/reactos/ntoskrnl/include/internal/ex.h +++ b/reactos/ntoskrnl/include/internal/ex.h @@ -8,6 +8,24 @@ #define NTOS_MODE_KERNEL #include +typedef struct _CURSORCLIP_INFO +{ + BOOL IsClipped; + UINT Left; + UINT Top; + UINT Right; + UINT Bottom; +} CURSORCLIP_INFO, *PCURSORCLIP_INFO; + +typedef struct _SYSTEM_CURSORINFO +{ + BOOL Visible; + HANDLE hCursor; + LONG x, y; + LONG cx, cy; + CURSORCLIP_INFO CursorClipInfo; +} SYSTEM_CURSORINFO, *PSYSTEM_CURSORINFO; + typedef struct _WINSTATION_OBJECT { CSHORT Type; @@ -19,6 +37,7 @@ typedef struct _WINSTATION_OBJECT PRTL_ATOM_TABLE AtomTable; PVOID HandleTable; HANDLE SystemMenuTemplate; + SYSTEM_CURSORINFO SystemCursor; struct _DESKTOP_OBJECT* ActiveDesktop; /* FIXME: Clipboard */ } WINSTATION_OBJECT, *PWINSTATION_OBJECT; diff --git a/reactos/subsys/win32k/eng/mouse.c b/reactos/subsys/win32k/eng/mouse.c index f18c72b5d5a..ba2fb0646dc 100644 --- a/reactos/subsys/win32k/eng/mouse.c +++ b/reactos/subsys/win32k/eng/mouse.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: mouse.c,v 1.29 2003/08/20 07:45:01 gvg Exp $ +/* $Id: mouse.c,v 1.30 2003/08/24 01:12:15 weiden Exp $ * * PROJECT: ReactOS kernel * PURPOSE: Mouse @@ -45,8 +45,8 @@ static BOOLEAN SafetySwitch = FALSE; static BOOLEAN SafetySwitch2 = FALSE; static BOOLEAN MouseEnabled = FALSE; -static LONG mouse_x, mouse_y; -static LONG mouse_width = 0, mouse_height = 0; +//static LONG mouse_x, mouse_y; +//static LONG mouse_width = 0, mouse_height = 0; static ULONG PointerStatus; static UCHAR DefaultCursor[256] = { @@ -118,6 +118,24 @@ static UCHAR DefaultCursor[256] = { /* FUNCTIONS *****************************************************************/ +BOOL FASTCALL +CheckClipCursor(LONG *x, LONG *y, PWINSTATION_OBJECT WinSta) +{ + if(WinSta->SystemCursor.CursorClipInfo.IsClipped) + { + if(*x > WinSta->SystemCursor.CursorClipInfo.Right) + *x = WinSta->SystemCursor.CursorClipInfo.Right; + if(*x < WinSta->SystemCursor.CursorClipInfo.Left) + *x = WinSta->SystemCursor.CursorClipInfo.Left; + if(*y > WinSta->SystemCursor.CursorClipInfo.Bottom) + *y = WinSta->SystemCursor.CursorClipInfo.Bottom; + if(*y < WinSta->SystemCursor.CursorClipInfo.Top) + *y = WinSta->SystemCursor.CursorClipInfo.Top; + return TRUE; + } + return TRUE; +} + INT STDCALL MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, LONG HazardY1, LONG HazardX2, LONG HazardY2) @@ -128,6 +146,8 @@ MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, { RECTL MouseRect; LONG tmp; + LONG mouse_x, mouse_y; + LONG mouse_width, mouse_height; /* Mouse is not allowed to move if GDI is busy drawing */ @@ -137,6 +157,16 @@ MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, { return(FALSE); } + + if(IntGetWindowStationObject(InputWindowStation)) + { + mouse_x = InputWindowStation->SystemCursor.x; + mouse_y = InputWindowStation->SystemCursor.y; + mouse_width = InputWindowStation->SystemCursor.cx; + mouse_height = InputWindowStation->SystemCursor.cy; + /* Dereference window station in MouseSafetyOnDrawEnd() */ + } + if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE) { @@ -175,12 +205,18 @@ MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI) */ { RECTL MouseRect; + LONG mouse_x, mouse_y; - if (SurfObj == NULL) + if ((SurfObj == NULL) || !InputWindowStation) { SafetySwitch2 = FALSE; return(FALSE); } + + mouse_x = InputWindowStation->SystemCursor.x; + mouse_y = InputWindowStation->SystemCursor.y; + + ObDereferenceObject(InputWindowStation); if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE) { @@ -213,6 +249,7 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) */ { ULONG i; + LONG mouse_x, mouse_y, mouse_ox, mouse_oy; LONG mouse_cx = 0, mouse_cy = 0; HDC hDC = IntGetScreenDC(); PDC dc; @@ -223,14 +260,24 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) LARGE_INTEGER LargeTickCount; ULONG TickCount; static ULONG ButtonsDown = 0; - - KeQueryTickCount(&LargeTickCount); - TickCount = LargeTickCount.u.LowPart; - - if (hDC == 0) + + if ((hDC == 0) || !InputWindowStation) { return; } + + if(IntGetWindowStationObject(InputWindowStation)) + { + mouse_ox = mouse_x = InputWindowStation->SystemCursor.x; + mouse_oy = mouse_y = InputWindowStation->SystemCursor.y; + ObDereferenceObject(InputWindowStation); + } + else + return; + + + KeQueryTickCount(&LargeTickCount); + TickCount = LargeTickCount.u.LowPart; dc = DC_LockDc(hDC); SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface); @@ -249,6 +296,13 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) Msg.time = TickCount; Msg.pt.x = mouse_x + mouse_cx; Msg.pt.y = mouse_y + mouse_cy; + + if(IntGetWindowStationObject(InputWindowStation)) + { + CheckClipCursor(&Msg.pt.x, &Msg.pt.y, InputWindowStation); + ObDereferenceObject(InputWindowStation); + } + if ((0 != Data[i].LastX) || (0 != Data[i].LastY)) { MsqInsertSystemMessage(&Msg); @@ -295,6 +349,11 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) /* If the mouse moved then move the pointer. */ if ((mouse_cx != 0 || mouse_cy != 0) && MouseEnabled) { + if(!IntGetWindowStationObject(InputWindowStation)) + { + return; + } + mouse_x += mouse_cx; mouse_y += mouse_cy; @@ -302,9 +361,16 @@ MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount) mouse_y = max(mouse_y, 0); mouse_x = min(mouse_x, SurfObj->sizlBitmap.cx - 20); mouse_y = min(mouse_y, SurfObj->sizlBitmap.cy - 20); + + CheckClipCursor(&mouse_x, &mouse_y, InputWindowStation); + + InputWindowStation->SystemCursor.x = mouse_x; + InputWindowStation->SystemCursor.y = mouse_y; + + ObDereferenceObject(InputWindowStation); - - if (SafetySwitch == FALSE && SafetySwitch2 == FALSE) + if (SafetySwitch == FALSE && SafetySwitch2 == FALSE && + ((mouse_ox != mouse_x) || (mouse_oy != mouse_y))) { SurfGDI->MovePointer(SurfObj, mouse_x, mouse_y, &MouseRect); } @@ -322,31 +388,44 @@ EnableMouse(HDC hDisplayDC) SIZEL MouseSize; RECTL MouseRect; - if( hDisplayDC ) + if( hDisplayDC && InputWindowStation) { + if(!IntGetWindowStationObject(InputWindowStation)) + { + MouseEnabled = FALSE; + return; + } dc = DC_LockDc(hDisplayDC); SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface); SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface); DC_UnlockDc( hDisplayDC ); /* Create the default mouse cursor. */ - mouse_width = 32; - mouse_height = 32; + InputWindowStation->SystemCursor.cx = 32; + InputWindowStation->SystemCursor.cy = 32; MouseSize.cx = 32; MouseSize.cy = 64; hMouseSurf = EngCreateBitmap(MouseSize, 4, BMF_1BPP, BMF_TOPDOWN, DefaultCursor); MouseSurf = (PSURFOBJ)AccessUserObject((ULONG) hMouseSurf); /* Tell the display driver to set the pointer shape. */ -#if 0 - mouse_x = SurfObj->sizlBitmap.cx / 2; - mouse_y = SurfObj->sizlBitmap.cy / 2; +#if 1 + InputWindowStation->SystemCursor.x = SurfObj->sizlBitmap.cx / 2; + InputWindowStation->SystemCursor.y = SurfObj->sizlBitmap.cy / 2; #else - mouse_x = 320; - mouse_y = 240; + InputWindowStation->SystemCursor.x = 320; + InputWindowStation->SystemCursor.y = 240; #endif + CheckClipCursor(&InputWindowStation->SystemCursor.x, + &InputWindowStation->SystemCursor.y, + InputWindowStation); + ObDereferenceObject(InputWindowStation); + PointerStatus = SurfGDI->SetPointerShape(SurfObj, MouseSurf, NULL, NULL, - 0, 0, mouse_x, mouse_y, &MouseRect, + 0, 0, + InputWindowStation->SystemCursor.x, + InputWindowStation->SystemCursor.y, + &MouseRect, SPS_CHANGE); MouseEnabled = (SPS_ACCEPT_EXCLUDE == PointerStatus || diff --git a/reactos/subsys/win32k/include/mouse.h b/reactos/subsys/win32k/include/mouse.h index 58cf588bd62..0c2d3ae87df 100644 --- a/reactos/subsys/win32k/include/mouse.h +++ b/reactos/subsys/win32k/include/mouse.h @@ -2,6 +2,7 @@ #define __WIN32K_MOUSE_H #include "../eng/misc.h" +#include //#include INT STDCALL MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1, LONG HazardY1, LONG HazardX2, LONG HazardY2); diff --git a/reactos/subsys/win32k/include/winsta.h b/reactos/subsys/win32k/include/winsta.h index 9ee63814b16..2de713a5427 100644 --- a/reactos/subsys/win32k/include/winsta.h +++ b/reactos/subsys/win32k/include/winsta.h @@ -13,6 +13,8 @@ #define SET_PROCESS_WINDOW_STATION(WinSta) \ ((IoGetCurrentProcess()->Win32WindowStation) = (PVOID)(WinSta)) + +WINSTATION_OBJECT *InputWindowStation; NTSTATUS FASTCALL @@ -53,6 +55,9 @@ IntGetCaptureWindow(VOID); VOID STDCALL IntSetCaptureWindow(struct _WINDOW_OBJECT* Window); +BOOL FASTCALL +IntGetWindowStationObject(PWINSTATION_OBJECT Object); + #endif /* __WIN32K_WINSTA_H */ /* EOF */ diff --git a/reactos/subsys/win32k/ntuser/winsta.c b/reactos/subsys/win32k/ntuser/winsta.c index 58bde4d5f6a..16b294dee67 100644 --- a/reactos/subsys/win32k/ntuser/winsta.c +++ b/reactos/subsys/win32k/ntuser/winsta.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: winsta.c,v 1.26 2003/08/19 11:48:50 weiden Exp $ +/* $Id: winsta.c,v 1.27 2003/08/24 01:12:15 weiden Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -62,7 +62,7 @@ STATIC PWNDCLASS_OBJECT DesktopWindowClass; /* Currently active desktop */ STATIC HDESK InputDesktopHandle = NULL; STATIC PDESKTOP_OBJECT InputDesktop = NULL; -STATIC PWINSTATION_OBJECT InputWindowStation = NULL; +//STATIC PWINSTATION_OBJECT InputWindowStation = NULL; static HDC ScreenDeviceContext = NULL; @@ -135,7 +135,9 @@ InitWindowStationImpl(VOID) UNICODE_STRING UnicodeString; NTSTATUS Status; WNDCLASSEXW wcx; - + + InputWindowStation = NULL; + /* * Create the '\Windows\WindowStations' directory */ @@ -349,6 +351,14 @@ NtUserCreateWindowStation(PUNICODE_STRING lpszWindowStationName, SetLastNtError(STATUS_INSUFFICIENT_RESOURCES); return((HWINSTA)0); } + + WinStaObject->SystemCursor.Visible = TRUE; + WinStaObject->SystemCursor.hCursor = (HANDLE)0; + WinStaObject->SystemCursor.x = 0; + WinStaObject->SystemCursor.y = 0; + WinStaObject->SystemCursor.cx = 32; + WinStaObject->SystemCursor.cy = 32; + WinStaObject->SystemCursor.CursorClipInfo.IsClipped = FALSE; DPRINT("Window station successfully created (%wZ)\n", &WindowStationName); @@ -954,4 +964,17 @@ IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) } } +BOOL FASTCALL +IntGetWindowStationObject(PWINSTATION_OBJECT Object) +{ + NTSTATUS Status; + + Status = ObReferenceObjectByPointer(Object, + KernelMode, + ExWindowStationObjectType, + 0); + + return NT_SUCCESS(Status); +} + /* EOF */ diff --git a/reactos/subsys/win32k/objects/cursoricon.c b/reactos/subsys/win32k/objects/cursoricon.c index 943727ed905..4e1f79f24a0 100644 --- a/reactos/subsys/win32k/objects/cursoricon.c +++ b/reactos/subsys/win32k/objects/cursoricon.c @@ -1,8 +1,11 @@ #undef WIN32_LEAN_AND_MEAN +#include #include #include #include #include +#include +#include #define NDEBUG #include @@ -218,16 +221,40 @@ NtUserGetCursorInfo( /* - * @unimplemented + * @implemented */ BOOL STDCALL NtUserClipCursor( RECT *lpRect) { - UNIMPLEMENTED + PWINSTATION_OBJECT WinStaObject; - return 0; + NTSTATUS Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(), + KernelMode, + 0, + &WinStaObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of window station handle (0x%X) failed\n", + PROCESS_WINDOW_STATION()); + SetLastWin32Error(Status); + return FALSE; + } + if(lpRect) + { + WinStaObject->SystemCursor.CursorClipInfo.IsClipped = TRUE; + WinStaObject->SystemCursor.CursorClipInfo.Left = lpRect->left; + WinStaObject->SystemCursor.CursorClipInfo.Top = lpRect->top; + WinStaObject->SystemCursor.CursorClipInfo.Right = lpRect->right; + WinStaObject->SystemCursor.CursorClipInfo.Bottom = lpRect->bottom; + } + else + WinStaObject->SystemCursor.CursorClipInfo.IsClipped = FALSE; + + ObDereferenceObject(WinStaObject); + + return TRUE; } @@ -263,16 +290,48 @@ NtUserFindExistingCursorIcon( /* - * @unimplemented + * @implemented */ BOOL STDCALL NtUserGetClipCursor( RECT *lpRect) { - UNIMPLEMENTED + PWINSTATION_OBJECT WinStaObject; + + if(!lpRect) + return FALSE; - return 0; + NTSTATUS Status = ValidateWindowStationHandle(PROCESS_WINDOW_STATION(), + KernelMode, + 0, + &WinStaObject); + if (!NT_SUCCESS(Status)) + { + DPRINT("Validation of window station handle (0x%X) failed\n", + PROCESS_WINDOW_STATION()); + SetLastWin32Error(Status); + return FALSE; + } + + if(WinStaObject->SystemCursor.CursorClipInfo.IsClipped) + { + lpRect->left = WinStaObject->SystemCursor.CursorClipInfo.Left; + lpRect->top = WinStaObject->SystemCursor.CursorClipInfo.Top; + lpRect->right = WinStaObject->SystemCursor.CursorClipInfo.Right; + lpRect->bottom = WinStaObject->SystemCursor.CursorClipInfo.Bottom; + } + else + { + lpRect->left = 0; + lpRect->top = 0; + lpRect->right = NtUserGetSystemMetrics(SM_CXSCREEN); + lpRect->bottom = NtUserGetSystemMetrics(SM_CYSCREEN); + } + + ObDereferenceObject(WinStaObject); + + return TRUE; }