mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 21:12:59 +00:00
880 lines
25 KiB
C
880 lines
25 KiB
C
/*
|
|
* ReactOS W32 Subsystem
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* 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.59 2004/02/06 21:12:55 navaraf Exp $
|
|
*
|
|
* PROJECT: ReactOS kernel
|
|
* PURPOSE: Mouse
|
|
* FILE: subsys/win32k/eng/mouse.c
|
|
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
* REVISION HISTORY:
|
|
* 06-06-2001 CSH Created
|
|
*/
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include <ddk/ntddk.h>
|
|
#include <ddk/ntddmou.h>
|
|
#include <win32k/win32k.h>
|
|
#include <win32k/dc.h>
|
|
#include "objects.h"
|
|
#include "include/msgqueue.h"
|
|
#include "include/object.h"
|
|
#include "include/winsta.h"
|
|
#include "include/desktop.h"
|
|
#include "include/window.h"
|
|
#include "include/cursoricon.h"
|
|
#include "include/callback.h"
|
|
#include "include/palette.h"
|
|
#include "include/inteng.h"
|
|
#include "include/eng.h"
|
|
#include <include/mouse.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#define GETSYSCURSOR(x) ((x) - OCR_NORMAL)
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
BOOL FASTCALL
|
|
IntCheckClipCursor(LONG *x, LONG *y, PSYSTEM_CURSORINFO CurInfo)
|
|
{
|
|
if(CurInfo->CursorClipInfo.IsClipped)
|
|
{
|
|
if(*x > CurInfo->CursorClipInfo.Right)
|
|
*x = CurInfo->CursorClipInfo.Right;
|
|
if(*x < CurInfo->CursorClipInfo.Left)
|
|
*x = CurInfo->CursorClipInfo.Left;
|
|
if(*y > CurInfo->CursorClipInfo.Bottom)
|
|
*y = CurInfo->CursorClipInfo.Bottom;
|
|
if(*y < CurInfo->CursorClipInfo.Top)
|
|
*y = CurInfo->CursorClipInfo.Top;
|
|
return TRUE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL FASTCALL
|
|
IntSwapMouseButton(PWINSTATION_OBJECT WinStaObject, BOOL Swap)
|
|
{
|
|
BOOL res = WinStaObject->SystemCursor.SwapButtons;
|
|
WinStaObject->SystemCursor.SwapButtons = Swap;
|
|
return res;
|
|
}
|
|
|
|
INT STDCALL
|
|
MouseSafetyOnDrawStart(PSURFOBJ SurfObj, PSURFGDI SurfGDI, LONG HazardX1,
|
|
LONG HazardY1, LONG HazardX2, LONG HazardY2)
|
|
/*
|
|
* FUNCTION: Notify the mouse driver that drawing is about to begin in
|
|
* a rectangle on a particular surface.
|
|
*/
|
|
{
|
|
LONG tmp;
|
|
PSYSTEM_CURSORINFO CurInfo;
|
|
BOOL MouseEnabled = FALSE;
|
|
PCURICON_OBJECT Cursor;
|
|
|
|
|
|
/* Mouse is not allowed to move if GDI is busy drawing */
|
|
|
|
if(IntGetWindowStationObject(InputWindowStation))
|
|
{
|
|
CurInfo = &InputWindowStation->SystemCursor;
|
|
|
|
MouseEnabled = CurInfo->Enabled && CurInfo->ShowingCursor;
|
|
}
|
|
else
|
|
return FALSE;
|
|
|
|
if (SurfObj == NULL)
|
|
{
|
|
ObDereferenceObject(InputWindowStation);
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
|
|
{
|
|
ObDereferenceObject(InputWindowStation);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (SPS_ACCEPT_NOEXCLUDE == SurfGDI->PointerStatus)
|
|
{
|
|
/* Hardware cursor, no need to remove it */
|
|
ObDereferenceObject(InputWindowStation);
|
|
return(FALSE);
|
|
}
|
|
|
|
if(!(Cursor = CurInfo->CurrentCursorObject))
|
|
{
|
|
ObDereferenceObject(InputWindowStation);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (HazardX1 > HazardX2)
|
|
{
|
|
tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp;
|
|
}
|
|
if (HazardY1 > HazardY2)
|
|
{
|
|
tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
|
|
}
|
|
|
|
if (CurInfo->PointerRectRight >= HazardX1
|
|
&& CurInfo->PointerRectLeft <= HazardX2
|
|
&& CurInfo->PointerRectBottom >= HazardY1
|
|
&& CurInfo->PointerRectTop <= HazardY2)
|
|
{
|
|
/* Mouse is not allowed to move if GDI is busy drawing */
|
|
ExAcquireFastMutex(&CurInfo->CursorMutex);
|
|
if (0 != CurInfo->SafetyRemoveCount++)
|
|
{
|
|
/* Was already removed */
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
ObDereferenceObject(InputWindowStation);
|
|
return FALSE;
|
|
}
|
|
CurInfo->SafetySwitch = TRUE;
|
|
ExAcquireFastMutex(SurfGDI->DriverLock);
|
|
SurfGDI->MovePointer(SurfObj, -1, -1, NULL);
|
|
ExReleaseFastMutex(SurfGDI->DriverLock);
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
}
|
|
|
|
ObDereferenceObject(InputWindowStation);
|
|
return(TRUE);
|
|
}
|
|
|
|
STATIC VOID FASTCALL
|
|
SetPointerRect(PSYSTEM_CURSORINFO CurInfo, PRECTL PointerRect)
|
|
{
|
|
CurInfo->PointerRectLeft = PointerRect->left;
|
|
CurInfo->PointerRectRight = PointerRect->right;
|
|
CurInfo->PointerRectTop = PointerRect->top;
|
|
CurInfo->PointerRectBottom = PointerRect->bottom;
|
|
}
|
|
|
|
INT FASTCALL
|
|
MouseSafetyOnDrawEnd(PSURFOBJ SurfObj, PSURFGDI SurfGDI)
|
|
/*
|
|
* FUNCTION: Notify the mouse driver that drawing has finished on a surface.
|
|
*/
|
|
{
|
|
PSYSTEM_CURSORINFO CurInfo;
|
|
BOOL MouseEnabled = FALSE;
|
|
RECTL PointerRect;
|
|
|
|
if(IntGetWindowStationObject(InputWindowStation))
|
|
{
|
|
CurInfo = &InputWindowStation->SystemCursor;
|
|
}
|
|
else
|
|
return FALSE;
|
|
|
|
ExAcquireFastMutex(&CurInfo->CursorMutex);
|
|
if(SurfObj == NULL)
|
|
{
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
ObDereferenceObject(InputWindowStation);
|
|
return FALSE;
|
|
}
|
|
|
|
MouseEnabled = CurInfo->Enabled && CurInfo->ShowingCursor;
|
|
|
|
if (SurfObj->iType != STYPE_DEVICE || MouseEnabled == FALSE)
|
|
{
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
ObDereferenceObject(InputWindowStation);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (SPS_ACCEPT_NOEXCLUDE == SurfGDI->PointerStatus)
|
|
{
|
|
/* Hardware cursor, it wasn't removed so need to restore it */
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
ObDereferenceObject(InputWindowStation);
|
|
return(FALSE);
|
|
}
|
|
|
|
if (CurInfo->SafetySwitch)
|
|
{
|
|
if (1 < CurInfo->SafetyRemoveCount--)
|
|
{
|
|
/* Someone else removed it too, let them restore it */
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
ObDereferenceObject(InputWindowStation);
|
|
return FALSE;
|
|
}
|
|
ExAcquireFastMutex(SurfGDI->DriverLock);
|
|
SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
|
|
ExReleaseFastMutex(SurfGDI->DriverLock);
|
|
SetPointerRect(CurInfo, &PointerRect);
|
|
CurInfo->SafetySwitch = FALSE;
|
|
}
|
|
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
ObDereferenceObject(InputWindowStation);
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL FASTCALL
|
|
MouseMoveCursor(LONG X, LONG Y)
|
|
{
|
|
HDC hDC;
|
|
PDC dc;
|
|
BOOL res = FALSE;
|
|
PSURFOBJ SurfObj;
|
|
PSURFGDI SurfGDI;
|
|
PSYSTEM_CURSORINFO CurInfo;
|
|
MSG Msg;
|
|
LARGE_INTEGER LargeTickCount;
|
|
ULONG TickCount;
|
|
RECTL PointerRect;
|
|
|
|
if(!InputWindowStation)
|
|
return FALSE;
|
|
|
|
if(IntGetWindowStationObject(InputWindowStation))
|
|
{
|
|
CurInfo = &InputWindowStation->SystemCursor;
|
|
if(!CurInfo->Enabled)
|
|
{
|
|
ObDereferenceObject(InputWindowStation);
|
|
return FALSE;
|
|
}
|
|
hDC = IntGetScreenDC();
|
|
if(!hDC)
|
|
{
|
|
ObDereferenceObject(InputWindowStation);
|
|
return FALSE;
|
|
}
|
|
dc = DC_LockDc(hDC);
|
|
SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
|
|
SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
|
|
DC_UnlockDc( hDC );
|
|
IntCheckClipCursor(&X, &Y, CurInfo);
|
|
if((X != CurInfo->x) || (Y != CurInfo->y))
|
|
{
|
|
/* move cursor */
|
|
CurInfo->x = X;
|
|
CurInfo->y = Y;
|
|
if(CurInfo->Enabled)
|
|
{
|
|
ExAcquireFastMutex(&CurInfo->CursorMutex);
|
|
ExAcquireFastMutex(SurfGDI->DriverLock);
|
|
SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
|
|
ExReleaseFastMutex(SurfGDI->DriverLock);
|
|
SetPointerRect(CurInfo, &PointerRect);
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
}
|
|
/* send MOUSEMOVE message */
|
|
KeQueryTickCount(&LargeTickCount);
|
|
TickCount = LargeTickCount.u.LowPart;
|
|
Msg.wParam = CurInfo->ButtonsDown;
|
|
Msg.lParam = MAKELPARAM(X, Y);
|
|
Msg.message = WM_MOUSEMOVE;
|
|
Msg.time = TickCount;
|
|
Msg.pt.x = X;
|
|
Msg.pt.y = Y;
|
|
MsqInsertSystemMessage(&Msg, TRUE);
|
|
res = TRUE;
|
|
}
|
|
|
|
ObDereferenceObject(InputWindowStation);
|
|
return res;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
VOID /* STDCALL */
|
|
MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount)
|
|
/*
|
|
* FUNCTION: Call by the mouse driver when input events occur.
|
|
*/
|
|
{
|
|
ULONG i;
|
|
PSYSTEM_CURSORINFO CurInfo;
|
|
BOOL MouseEnabled = FALSE;
|
|
BOOL Moved = FALSE;
|
|
LONG mouse_ox, mouse_oy;
|
|
LONG mouse_cx = 0, mouse_cy = 0;
|
|
LONG dScroll = 0;
|
|
HDC hDC;
|
|
PDC dc;
|
|
PSURFOBJ SurfObj;
|
|
PSURFGDI SurfGDI;
|
|
MSG Msg;
|
|
RECTL PointerRect;
|
|
|
|
hDC = IntGetScreenDC();
|
|
|
|
if(!hDC || !InputWindowStation)
|
|
return;
|
|
|
|
if(IntGetWindowStationObject(InputWindowStation))
|
|
{
|
|
CurInfo = &InputWindowStation->SystemCursor;
|
|
MouseEnabled = CurInfo->Enabled;
|
|
if(!MouseEnabled)
|
|
{
|
|
ObDereferenceObject(InputWindowStation);
|
|
return;
|
|
}
|
|
mouse_ox = CurInfo->x;
|
|
mouse_oy = CurInfo->y;
|
|
}
|
|
else
|
|
return;
|
|
|
|
dc = DC_LockDc(hDC);
|
|
SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
|
|
SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
|
|
DC_UnlockDc( hDC );
|
|
|
|
/* Compile the total mouse movement change and dispatch button events. */
|
|
for (i = 0; i < InputCount; i++)
|
|
{
|
|
mouse_cx += Data[i].LastX;
|
|
mouse_cy += Data[i].LastY;
|
|
|
|
CurInfo->x += Data[i].LastX;
|
|
CurInfo->y += Data[i].LastY;
|
|
|
|
CurInfo->x = max(CurInfo->x, 0);
|
|
CurInfo->y = max(CurInfo->y, 0);
|
|
CurInfo->x = min(CurInfo->x, SurfObj->sizlBitmap.cx - 1);
|
|
CurInfo->y = min(CurInfo->y, SurfObj->sizlBitmap.cy - 1);
|
|
|
|
IntCheckClipCursor(&CurInfo->x, &CurInfo->y, CurInfo);
|
|
|
|
Msg.wParam = CurInfo->ButtonsDown;
|
|
Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
|
|
Msg.message = WM_MOUSEMOVE;
|
|
Msg.pt.x = CurInfo->x;
|
|
Msg.pt.y = CurInfo->y;
|
|
|
|
if (Data[i].ButtonFlags != 0)
|
|
{
|
|
if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_DOWN) > 0)
|
|
{
|
|
CurInfo->ButtonsDown |= (CurInfo->SwapButtons ? MK_RBUTTON : MK_LBUTTON);
|
|
Msg.message = (CurInfo->SwapButtons ? WM_RBUTTONDOWN : WM_LBUTTONDOWN);
|
|
}
|
|
if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_DOWN) > 0)
|
|
{
|
|
CurInfo->ButtonsDown |= MK_MBUTTON;
|
|
Msg.message = WM_MBUTTONDOWN;
|
|
}
|
|
if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_DOWN) > 0)
|
|
{
|
|
CurInfo->ButtonsDown |= (CurInfo->SwapButtons ? MK_LBUTTON : MK_RBUTTON);
|
|
Msg.message = (CurInfo->SwapButtons ? WM_LBUTTONDOWN : WM_RBUTTONDOWN);
|
|
}
|
|
|
|
if ((Data[i].ButtonFlags & MOUSE_BUTTON_4_DOWN) > 0)
|
|
{
|
|
CurInfo->ButtonsDown |= MK_XBUTTON1;
|
|
Msg.message = WM_XBUTTONDOWN;
|
|
}
|
|
if ((Data[i].ButtonFlags & MOUSE_BUTTON_5_DOWN) > 0)
|
|
{
|
|
CurInfo->ButtonsDown |= MK_XBUTTON2;
|
|
Msg.message = WM_XBUTTONDOWN;
|
|
}
|
|
|
|
if ((Data[i].ButtonFlags & MOUSE_LEFT_BUTTON_UP) > 0)
|
|
{
|
|
CurInfo->ButtonsDown &= (CurInfo->SwapButtons ? ~MK_RBUTTON : ~MK_LBUTTON);
|
|
Msg.message = (CurInfo->SwapButtons ? WM_RBUTTONUP : WM_LBUTTONUP);
|
|
}
|
|
if ((Data[i].ButtonFlags & MOUSE_MIDDLE_BUTTON_UP) > 0)
|
|
{
|
|
CurInfo->ButtonsDown &= ~MK_MBUTTON;
|
|
Msg.message = WM_MBUTTONUP;
|
|
}
|
|
if ((Data[i].ButtonFlags & MOUSE_RIGHT_BUTTON_UP) > 0)
|
|
{
|
|
CurInfo->ButtonsDown &= (CurInfo->SwapButtons ? ~MK_LBUTTON : ~MK_RBUTTON);
|
|
Msg.message = (CurInfo->SwapButtons ? WM_LBUTTONUP : WM_RBUTTONUP);
|
|
}
|
|
if ((Data[i].ButtonFlags & MOUSE_BUTTON_4_UP) > 0)
|
|
{
|
|
CurInfo->ButtonsDown &= ~MK_XBUTTON1;
|
|
Msg.message = WM_XBUTTONUP;
|
|
}
|
|
if ((Data[i].ButtonFlags & MOUSE_BUTTON_5_UP) > 0)
|
|
{
|
|
CurInfo->ButtonsDown &= ~MK_XBUTTON2;
|
|
Msg.message = WM_XBUTTONUP;
|
|
}
|
|
if ((Data[i].ButtonFlags & MOUSE_WHEEL) > 0)
|
|
{
|
|
dScroll += (LONG)Data[i].ButtonData;
|
|
}
|
|
|
|
if (Data[i].ButtonFlags != MOUSE_WHEEL)
|
|
{
|
|
Moved = (0 != mouse_cx) || (0 != mouse_cy);
|
|
if(Moved && MouseEnabled)
|
|
{
|
|
if (!CurInfo->SafetySwitch && 0 == CurInfo->SafetyRemoveCount &&
|
|
((mouse_ox != CurInfo->x) || (mouse_oy != CurInfo->y)))
|
|
{
|
|
ExAcquireFastMutex(&CurInfo->CursorMutex);
|
|
ExAcquireFastMutex(SurfGDI->DriverLock);
|
|
SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
|
|
ExReleaseFastMutex(SurfGDI->DriverLock);
|
|
SetPointerRect(CurInfo, &PointerRect);
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
mouse_cx = 0;
|
|
mouse_cy = 0;
|
|
}
|
|
}
|
|
|
|
Msg.wParam = CurInfo->ButtonsDown;
|
|
MsqInsertSystemMessage(&Msg, FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* If the mouse moved then move the pointer. */
|
|
if ((mouse_cx != 0 || mouse_cy != 0) && MouseEnabled)
|
|
{
|
|
Msg.wParam = CurInfo->ButtonsDown;
|
|
Msg.message = WM_MOUSEMOVE;
|
|
Msg.pt.x = CurInfo->x;
|
|
Msg.pt.y = CurInfo->y;
|
|
Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
|
|
MsqInsertSystemMessage(&Msg, TRUE);
|
|
|
|
if (!CurInfo->SafetySwitch && 0 == CurInfo->SafetyRemoveCount &&
|
|
((mouse_ox != CurInfo->x) || (mouse_oy != CurInfo->y)))
|
|
{
|
|
ExAcquireFastMutex(&CurInfo->CursorMutex);
|
|
ExAcquireFastMutex(SurfGDI->DriverLock);
|
|
SurfGDI->MovePointer(SurfObj, CurInfo->x, CurInfo->y, &PointerRect);
|
|
ExReleaseFastMutex(SurfGDI->DriverLock);
|
|
SetPointerRect(CurInfo, &PointerRect);
|
|
ExReleaseFastMutex(&CurInfo->CursorMutex);
|
|
}
|
|
}
|
|
|
|
/* send WM_MOUSEWHEEL message */
|
|
if(dScroll && MouseEnabled)
|
|
{
|
|
Msg.message = WM_MOUSEWHEEL;
|
|
Msg.wParam = MAKEWPARAM(CurInfo->ButtonsDown, dScroll);
|
|
Msg.lParam = MAKELPARAM(CurInfo->x, CurInfo->y);
|
|
Msg.pt.x = CurInfo->x;
|
|
Msg.pt.y = CurInfo->y;
|
|
MsqInsertSystemMessage(&Msg, FALSE);
|
|
}
|
|
|
|
ObDereferenceObject(InputWindowStation);
|
|
}
|
|
|
|
VOID FASTCALL
|
|
EnableMouse(HDC hDisplayDC)
|
|
{
|
|
PDC dc;
|
|
PSURFOBJ SurfObj;
|
|
PSURFGDI SurfGDI;
|
|
|
|
if( hDisplayDC && InputWindowStation)
|
|
{
|
|
if(!IntGetWindowStationObject(InputWindowStation))
|
|
{
|
|
InputWindowStation->SystemCursor.Enabled = FALSE;
|
|
return;
|
|
}
|
|
|
|
dc = DC_LockDc(hDisplayDC);
|
|
SurfObj = (PSURFOBJ)AccessUserObject((ULONG) dc->Surface);
|
|
SurfGDI = (PSURFGDI)AccessInternalObject((ULONG) dc->Surface);
|
|
DC_UnlockDc( hDisplayDC );
|
|
|
|
IntSetCursor(InputWindowStation, NULL, TRUE);
|
|
|
|
InputWindowStation->SystemCursor.Enabled = (SPS_ACCEPT_EXCLUDE == SurfGDI->PointerStatus ||
|
|
SPS_ACCEPT_NOEXCLUDE == SurfGDI->PointerStatus);
|
|
|
|
/* Move the cursor to the screen center */
|
|
DPRINT("Setting Cursor up at 0x%x, 0x%x\n", SurfObj->sizlBitmap.cx / 2, SurfObj->sizlBitmap.cy / 2);
|
|
MouseMoveCursor(SurfObj->sizlBitmap.cx / 2, SurfObj->sizlBitmap.cy / 2);
|
|
|
|
ObDereferenceObject(InputWindowStation);
|
|
}
|
|
else
|
|
{
|
|
if(IntGetWindowStationObject(InputWindowStation))
|
|
{
|
|
IntSetCursor(InputWindowStation, NULL, TRUE);
|
|
InputWindowStation->SystemCursor.Enabled = FALSE;
|
|
InputWindowStation->SystemCursor.CursorClipInfo.IsClipped = FALSE;
|
|
ObDereferenceObject(InputWindowStation);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
|
|
|
|
#define MOUSE_TAG TAG('M', 'O', 'U', 'S')
|
|
|
|
VOID FASTCALL
|
|
IntHideMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
|
|
{
|
|
if (ppdev->PointerAttributes.Enable == FALSE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ppdev->PointerAttributes.Enable = FALSE;
|
|
|
|
if (ppdev->PointerAttributes.Column + ppdev->PointerHotSpot.x == -1)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (ppdev->PointerSaveSurface != NULL)
|
|
{
|
|
RECTL DestRect;
|
|
POINTL SrcPoint;
|
|
SURFOBJ *SaveSurface;
|
|
SURFOBJ *MaskSurface;
|
|
|
|
DestRect.left = max(ppdev->PointerAttributes.Column, 0);
|
|
DestRect.top = max(ppdev->PointerAttributes.Row, 0);
|
|
DestRect.right = min(
|
|
ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
|
|
DestSurface->sizlBitmap.cx - 1);
|
|
DestRect.bottom = min(
|
|
ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
|
|
DestSurface->sizlBitmap.cy - 1);
|
|
|
|
SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
|
|
SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
|
|
|
|
SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
|
|
MaskSurface = EngLockSurface(ppdev->PointerMaskSurface);
|
|
EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL,
|
|
&DestRect, &SrcPoint, &SrcPoint, NULL, NULL, SRCCOPY);
|
|
EngUnlockSurface(MaskSurface);
|
|
EngUnlockSurface(SaveSurface);
|
|
}
|
|
}
|
|
|
|
VOID FASTCALL
|
|
IntShowMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
|
|
{
|
|
if (ppdev->PointerAttributes.Enable == TRUE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ppdev->PointerAttributes.Enable = TRUE;
|
|
|
|
/*
|
|
* Copy the pixels under the cursor to temporary surface.
|
|
*/
|
|
|
|
if (ppdev->PointerSaveSurface != NULL)
|
|
{
|
|
RECTL DestRect;
|
|
POINTL SrcPoint;
|
|
SURFOBJ *SaveSurface;
|
|
|
|
SrcPoint.x = max(ppdev->PointerAttributes.Column, 0);
|
|
SrcPoint.y = max(ppdev->PointerAttributes.Row, 0);
|
|
|
|
DestRect.left = SrcPoint.x - ppdev->PointerAttributes.Column;
|
|
DestRect.top = SrcPoint.y - ppdev->PointerAttributes.Row;
|
|
DestRect.right = min(
|
|
ppdev->PointerAttributes.Width,
|
|
DestSurface->sizlBitmap.cx - ppdev->PointerAttributes.Column - 1);
|
|
DestRect.bottom = min(
|
|
ppdev->PointerAttributes.Height,
|
|
DestSurface->sizlBitmap.cy - ppdev->PointerAttributes.Row - 1);
|
|
|
|
SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
|
|
EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL,
|
|
&DestRect, &SrcPoint, NULL, NULL, NULL, SRCCOPY);
|
|
EngUnlockSurface(SaveSurface);
|
|
}
|
|
|
|
/*
|
|
* Blit the cursor on the screen.
|
|
*/
|
|
|
|
{
|
|
RECTL DestRect;
|
|
POINTL SrcPoint;
|
|
SURFOBJ *ColorSurf;
|
|
SURFOBJ *MaskSurf;
|
|
|
|
DestRect.left = max(ppdev->PointerAttributes.Column, 0);
|
|
DestRect.top = max(ppdev->PointerAttributes.Row, 0);
|
|
DestRect.right = min(
|
|
ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
|
|
DestSurface->sizlBitmap.cx - 1);
|
|
DestRect.bottom = min(
|
|
ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
|
|
DestSurface->sizlBitmap.cy - 1);
|
|
|
|
SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
|
|
SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
|
|
|
|
MaskSurf = EngLockSurface(ppdev->PointerMaskSurface);
|
|
if (ppdev->PointerColorSurface != NULL)
|
|
{
|
|
ColorSurf = EngLockSurface(ppdev->PointerColorSurface);
|
|
EngBitBlt(DestSurface, ColorSurf, MaskSurf, NULL, ppdev->PointerXlateObject,
|
|
&DestRect, &SrcPoint, &SrcPoint, NULL, NULL, 0xAACC);
|
|
EngUnlockSurface(ColorSurf);
|
|
}
|
|
else
|
|
{
|
|
EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
|
|
&DestRect, &SrcPoint, NULL, NULL, NULL, SRCAND);
|
|
SrcPoint.y += ppdev->PointerAttributes.Height;
|
|
EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
|
|
&DestRect, &SrcPoint, NULL, NULL, NULL, SRCINVERT);
|
|
}
|
|
EngUnlockSurface(MaskSurf);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
|
|
ULONG STDCALL
|
|
EngSetPointerShape(
|
|
IN SURFOBJ *pso,
|
|
IN SURFOBJ *psoMask,
|
|
IN SURFOBJ *psoColor,
|
|
IN XLATEOBJ *pxlo,
|
|
IN LONG xHot,
|
|
IN LONG yHot,
|
|
IN LONG x,
|
|
IN LONG y,
|
|
IN RECTL *prcl,
|
|
IN FLONG fl)
|
|
{
|
|
GDIDEVICE *ppdev = (GDIDEVICE *)pso->hdev;
|
|
SURFOBJ *TempSurfObj;
|
|
|
|
IntHideMousePointer(ppdev, pso);
|
|
|
|
if (ppdev->PointerColorSurface != NULL)
|
|
{
|
|
/* FIXME: Is this really needed? */
|
|
TempSurfObj = EngLockSurface(ppdev->PointerColorSurface);
|
|
EngFreeMem(TempSurfObj->pvBits);
|
|
TempSurfObj->pvBits = 0;
|
|
EngUnlockSurface(TempSurfObj);
|
|
|
|
EngDeleteSurface(ppdev->PointerColorSurface);
|
|
ppdev->PointerMaskSurface = NULL;
|
|
}
|
|
|
|
if (ppdev->PointerMaskSurface != NULL)
|
|
{
|
|
/* FIXME: Is this really needed? */
|
|
TempSurfObj = EngLockSurface(ppdev->PointerMaskSurface);
|
|
EngFreeMem(TempSurfObj->pvBits);
|
|
TempSurfObj->pvBits = 0;
|
|
EngUnlockSurface(TempSurfObj);
|
|
|
|
EngDeleteSurface(ppdev->PointerMaskSurface);
|
|
ppdev->PointerMaskSurface = NULL;
|
|
}
|
|
|
|
if (ppdev->PointerSaveSurface != NULL)
|
|
{
|
|
EngDeleteSurface(ppdev->PointerSaveSurface);
|
|
ppdev->PointerSaveSurface = NULL;
|
|
}
|
|
|
|
if (ppdev->PointerXlateObject != NULL)
|
|
{
|
|
EngDeleteXlate(ppdev->PointerXlateObject);
|
|
ppdev->PointerXlateObject = NULL;
|
|
}
|
|
|
|
/*
|
|
* See if we are being asked to hide the pointer.
|
|
*/
|
|
|
|
if (psoMask == NULL)
|
|
{
|
|
return SPS_ACCEPT_NOEXCLUDE;
|
|
}
|
|
|
|
ppdev->PointerHotSpot.x = xHot;
|
|
ppdev->PointerHotSpot.y = yHot;
|
|
|
|
ppdev->PointerAttributes.Column = x - xHot;
|
|
ppdev->PointerAttributes.Row = y - yHot;
|
|
ppdev->PointerAttributes.Width = psoMask->lDelta << 3;
|
|
ppdev->PointerAttributes.Height = (psoMask->cjBits / psoMask->lDelta) >> 1;
|
|
|
|
if (prcl != NULL)
|
|
{
|
|
prcl->left = ppdev->PointerAttributes.Column;
|
|
prcl->top = ppdev->PointerAttributes.Row;
|
|
prcl->right = prcl->left + ppdev->PointerAttributes.Width;
|
|
prcl->bottom = prcl->top + ppdev->PointerAttributes.Height;
|
|
}
|
|
|
|
if (psoColor != NULL)
|
|
{
|
|
SIZEL Size;
|
|
PBYTE Bits;
|
|
|
|
Size.cx = ppdev->PointerAttributes.Width;
|
|
Size.cy = ppdev->PointerAttributes.Height;
|
|
Bits = EngAllocMem(0, psoColor->cjBits, MOUSE_TAG);
|
|
memcpy(Bits, psoColor->pvBits, psoColor->cjBits);
|
|
|
|
ppdev->PointerColorSurface = (HSURF)EngCreateBitmap(Size,
|
|
psoColor->lDelta, psoColor->iBitmapFormat, 0, Bits);
|
|
}
|
|
else
|
|
{
|
|
ppdev->PointerColorSurface = NULL;
|
|
}
|
|
|
|
{
|
|
SIZEL Size;
|
|
PBYTE Bits;
|
|
|
|
Size.cx = ppdev->PointerAttributes.Width;
|
|
Size.cy = ppdev->PointerAttributes.Height << 1;
|
|
Bits = EngAllocMem(0, psoMask->cjBits, MOUSE_TAG);
|
|
memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
|
|
|
|
ppdev->PointerMaskSurface = (HSURF)EngCreateBitmap(Size,
|
|
psoMask->lDelta, psoMask->iBitmapFormat, 0, Bits);
|
|
}
|
|
|
|
/*
|
|
* Create and XLATEOBJ that will be used for drawing masks.
|
|
* FIXME: We should get this in pxlo parameter!
|
|
*/
|
|
|
|
if (pxlo == NULL)
|
|
{
|
|
HPALETTE BWPalette, DestPalette;
|
|
ULONG BWColors[] = {0, 0xFFFFFF};
|
|
PDC Dc;
|
|
PPALGDI PalObj;
|
|
LONG DestMode;
|
|
|
|
BWPalette = EngCreatePalette(PAL_INDEXED, sizeof(BWColors) / sizeof(ULONG),
|
|
BWColors, 0, 0, 0);
|
|
Dc = DC_LockDc(IntGetScreenDC());
|
|
DestPalette = Dc->w.hPalette;
|
|
PalObj = PALETTE_LockPalette(DestPalette);
|
|
DestMode = PalObj->Mode;
|
|
PALETTE_UnlockPalette(DestPalette);
|
|
DC_UnlockDc(IntGetScreenDC());
|
|
ppdev->PointerXlateObject = IntEngCreateXlate(DestMode, PAL_INDEXED,
|
|
DestPalette, BWPalette);
|
|
EngDeletePalette(BWPalette);
|
|
}
|
|
else
|
|
{
|
|
ppdev->PointerXlateObject = pxlo;
|
|
}
|
|
|
|
/*
|
|
* Create surface for saving the pixels under the cursor.
|
|
*/
|
|
|
|
{
|
|
SIZEL Size;
|
|
LONG lDelta;
|
|
|
|
Size.cx = ppdev->PointerAttributes.Width;
|
|
Size.cy = ppdev->PointerAttributes.Height;
|
|
|
|
switch (pso->iBitmapFormat)
|
|
{
|
|
case BMF_1BPP: lDelta = Size.cx >> 3; break;
|
|
case BMF_4BPP: lDelta = Size.cx >> 1; break;
|
|
case BMF_8BPP: lDelta = Size.cx; break;
|
|
case BMF_16BPP: lDelta = Size.cx << 1; break;
|
|
case BMF_24BPP: lDelta = Size.cx * 3; break;
|
|
case BMF_32BPP: lDelta = Size.cx << 2; break;
|
|
}
|
|
|
|
ppdev->PointerSaveSurface = (HSURF)EngCreateBitmap(
|
|
Size, lDelta, pso->iBitmapFormat, BMF_NOZEROINIT, NULL);
|
|
}
|
|
|
|
IntShowMousePointer(ppdev, pso);
|
|
|
|
return SPS_ACCEPT_EXCLUDE;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
|
|
VOID STDCALL
|
|
EngMovePointer(
|
|
IN SURFOBJ *pso,
|
|
IN LONG x,
|
|
IN LONG y,
|
|
IN RECTL *prcl)
|
|
{
|
|
GDIDEVICE *ppdev = (GDIDEVICE *)pso->hdev;
|
|
PSURFGDI SurfGDI = AccessInternalObjectFromUserObject(pso);
|
|
|
|
/*
|
|
* Prevent GDI from trying to remve the mouse cursor,
|
|
* because it would cause unexpected reentrancy effects.
|
|
*/
|
|
|
|
SurfGDI->PointerStatus = SPS_ACCEPT_NOEXCLUDE;
|
|
|
|
IntHideMousePointer(ppdev, pso);
|
|
ppdev->PointerAttributes.Column = x - ppdev->PointerHotSpot.x;
|
|
ppdev->PointerAttributes.Row = y - ppdev->PointerHotSpot.y;
|
|
if (x != -1)
|
|
{
|
|
IntShowMousePointer(ppdev, pso);
|
|
}
|
|
|
|
if (prcl != NULL)
|
|
{
|
|
prcl->left = ppdev->PointerAttributes.Column;
|
|
prcl->top = ppdev->PointerAttributes.Row;
|
|
prcl->right = prcl->left + ppdev->PointerAttributes.Width;
|
|
prcl->bottom = prcl->top + ppdev->PointerAttributes.Height;
|
|
}
|
|
|
|
SurfGDI->PointerStatus = SPS_ACCEPT_EXCLUDE;
|
|
}
|
|
|
|
/* EOF */
|