#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
# define NEED_EVENTS
# include <X11/X.h>
# include <X11/Xmd.h>
# include <X11/Xproto.h>
# include "misc.h"
# include "windowstr.h"
# include "pixmapstr.h"
# include "mi.h"
# include "scrnintstr.h"
# include "mipointrst.h"
# include "cursorstr.h"
# include "dixstruct.h"
# include "inputstr.h"
_X_EXPORT int miPointerScreenIndex;
static unsigned long miPointerGeneration = 0;
#define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr))
#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
static miPointerRec miPointer;
static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
static void miPointerConstrainCursor(ScreenPtr pScreen, BoxPtr pBox);
static void miPointerPointerNonInterestBox(ScreenPtr pScreen, BoxPtr pBox);
static void miPointerCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
BoxPtr pHotBox, BoxPtr pTopLeftBox);
static Bool miPointerSetCursorPosition(ScreenPtr pScreen, int x, int y,
Bool generateEvent);
static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
static void miPointerMove(ScreenPtr pScreen, int x, int y, unsigned long time);
static xEvent* events;
_X_EXPORT Bool
miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
ScreenPtr pScreen;
miPointerSpriteFuncPtr spriteFuncs;
miPointerScreenFuncPtr screenFuncs;
Bool waitForUpdate;
{
miPointerScreenPtr pScreenPriv;
if (miPointerGeneration != serverGeneration)
{
miPointerScreenIndex = AllocateScreenPrivateIndex();
if (miPointerScreenIndex < 0)
return FALSE;
miPointerGeneration = serverGeneration;
}
pScreenPriv = (miPointerScreenPtr) xalloc (sizeof (miPointerScreenRec));
if (!pScreenPriv)
return FALSE;
pScreenPriv->spriteFuncs = spriteFuncs;
pScreenPriv->screenFuncs = screenFuncs;
if (!screenFuncs->EnqueueEvent)
screenFuncs->EnqueueEvent = mieqEnqueue;
if (!screenFuncs->NewEventScreen)
screenFuncs->NewEventScreen = mieqSwitchScreen;
pScreenPriv->waitForUpdate = waitForUpdate;
pScreenPriv->showTransparent = FALSE;
pScreenPriv->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = miPointerCloseScreen;
pScreen->devPrivates[miPointerScreenIndex].ptr = (pointer) pScreenPriv;
pScreen->ConstrainCursor = miPointerConstrainCursor;
pScreen->CursorLimits = miPointerCursorLimits;
pScreen->DisplayCursor = miPointerDisplayCursor;
pScreen->RealizeCursor = miPointerRealizeCursor;
pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
pScreen->SetCursorPosition = miPointerSetCursorPosition;
pScreen->RecolorCursor = miRecolorCursor;
pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
miPointer.pScreen = NULL;
miPointer.pSpriteScreen = NULL;
miPointer.pCursor = NULL;
miPointer.pSpriteCursor = NULL;
miPointer.limits.x1 = 0;
miPointer.limits.x2 = 32767;
miPointer.limits.y1 = 0;
miPointer.limits.y2 = 32767;
miPointer.confined = FALSE;
miPointer.x = 0;
miPointer.y = 0;
events = NULL;
return TRUE;
}
static Bool
miPointerCloseScreen (index, pScreen)
int index;
ScreenPtr pScreen;
{
SetupScreen(pScreen);
if (pScreen == miPointer.pScreen)
miPointer.pScreen = 0;
if (pScreen == miPointer.pSpriteScreen)
miPointer.pSpriteScreen = 0;
pScreen->CloseScreen = pScreenPriv->CloseScreen;
xfree ((pointer) pScreenPriv);
xfree ((pointer) events);
events = NULL;
return (*pScreen->CloseScreen) (index, pScreen);
}
static Bool
miPointerRealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
SetupScreen(pScreen);
return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor);
}
static Bool
miPointerUnrealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
SetupScreen(pScreen);
return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor);
}
static Bool
miPointerDisplayCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
miPointer.pCursor = pCursor;
miPointer.pScreen = pScreen;
miPointerUpdateSprite(inputInfo.pointer);
return TRUE;
}
static void
miPointerConstrainCursor (pScreen, pBox)
ScreenPtr pScreen;
BoxPtr pBox;
{
miPointer.limits = *pBox;
miPointer.confined = PointerConfinedToScreen();
}
static void
miPointerPointerNonInterestBox (pScreen, pBox)
ScreenPtr pScreen;
BoxPtr pBox;
{
}
static void
miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox)
ScreenPtr pScreen;
CursorPtr pCursor;
BoxPtr pHotBox;
BoxPtr pTopLeftBox;
{
*pTopLeftBox = *pHotBox;
}
static Bool GenerateEvent;
static Bool
miPointerSetCursorPosition(pScreen, x, y, generateEvent)
ScreenPtr pScreen;
int x, y;
Bool generateEvent;
{
SetupScreen (pScreen);
GenerateEvent = generateEvent;
(*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y);
if (!generateEvent)
miPointerUpdateSprite(inputInfo.pointer);
return TRUE;
}
_X_EXPORT void
miPointerWarpCursor (pScreen, x, y)
ScreenPtr pScreen;
int x, y;
{
SetupScreen (pScreen);
if (miPointer.pScreen != pScreen)
(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
if (GenerateEvent)
{
miPointerMove (pScreen, x, y, GetTimeInMillis());
}
else
{
if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
{
miPointer.devx = x;
miPointer.devy = y;
if(!miPointer.pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
}
miPointer.x = x;
miPointer.y = y;
miPointer.pScreen = pScreen;
}
}
void
miPointerUpdate ()
{
miPointerUpdateSprite(inputInfo.pointer);
}
void
miPointerUpdateSprite (DeviceIntPtr pDev)
{
ScreenPtr pScreen;
miPointerScreenPtr pScreenPriv;
CursorPtr pCursor;
int x, y, devx, devy;
if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer))
return;
pScreen = miPointer.pScreen;
if (!pScreen)
return;
x = miPointer.x;
y = miPointer.y;
devx = miPointer.devx;
devy = miPointer.devy;
pScreenPriv = GetScreenPrivate (pScreen);
if (pScreen != miPointer.pSpriteScreen)
{
if (miPointer.pSpriteScreen)
{
miPointerScreenPtr pOldPriv;
pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen);
if (miPointer.pCursor)
{
(*pOldPriv->spriteFuncs->SetCursor)
(miPointer.pSpriteScreen, NullCursor, 0, 0);
}
(*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE);
}
(*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
(*pScreenPriv->spriteFuncs->SetCursor)
(pScreen, miPointer.pCursor, x, y);
miPointer.devx = x;
miPointer.devy = y;
miPointer.pSpriteCursor = miPointer.pCursor;
miPointer.pSpriteScreen = pScreen;
}
else if (miPointer.pCursor != miPointer.pSpriteCursor)
{
pCursor = miPointer.pCursor;
if (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)
pCursor = NullCursor;
(*pScreenPriv->spriteFuncs->SetCursor) (pScreen, pCursor, x, y);
miPointer.devx = x;
miPointer.devy = y;
miPointer.pSpriteCursor = miPointer.pCursor;
}
else if (x != devx || y != devy)
{
miPointer.devx = x;
miPointer.devy = y;
if(!miPointer.pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
}
}
void
miPointerDeltaCursor (int dx, int dy, unsigned long time)
{
int x = miPointer.x + dx, y = miPointer.y + dy;
miPointerSetPosition(inputInfo.pointer, &x, &y, time);
}
void
miPointerSetNewScreen(int screen_no, int x, int y)
{
miPointerSetScreen(inputInfo.pointer, screen_no, x, y);
}
void
miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
{
miPointerScreenPtr pScreenPriv;
ScreenPtr pScreen;
pScreen = screenInfo.screens[screen_no];
pScreenPriv = GetScreenPrivate (pScreen);
(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
NewCurrentScreen (pScreen, x, y);
miPointer.limits.x2 = pScreen->width;
miPointer.limits.y2 = pScreen->height;
}
_X_EXPORT ScreenPtr
miPointerCurrentScreen ()
{
return miPointerGetScreen(inputInfo.pointer);
}
_X_EXPORT ScreenPtr
miPointerGetScreen(DeviceIntPtr pDev)
{
return miPointer.pScreen;
}
_X_EXPORT void
miPointerAbsoluteCursor (int x, int y, unsigned long time)
{
miPointerSetPosition(inputInfo.pointer, &x, &y, time);
}
static void
miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y,
unsigned long time)
{
SetupScreen(pScreen);
if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer) &&
!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
{
miPointer.devx = x;
miPointer.devy = y;
if(!miPointer.pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
}
miPointer.x = x;
miPointer.y = y;
miPointer.pScreen = pScreen;
}
_X_EXPORT void
miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time)
{
miPointerScreenPtr pScreenPriv;
ScreenPtr pScreen;
ScreenPtr newScreen;
pScreen = miPointer.pScreen;
if (!pScreen)
return;
if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer))
return;
if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
{
pScreenPriv = GetScreenPrivate (pScreen);
if (!miPointer.confined)
{
newScreen = pScreen;
(*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
if (newScreen != pScreen)
{
pScreen = newScreen;
(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
pScreenPriv = GetScreenPrivate (pScreen);
miPointer.limits.x2 = pScreen->width;
miPointer.limits.y2 = pScreen->height;
}
}
}
if (*x < miPointer.limits.x1)
*x = miPointer.limits.x1;
if (*x >= miPointer.limits.x2)
*x = miPointer.limits.x2 - 1;
if (*y < miPointer.limits.y1)
*y = miPointer.limits.y1;
if (*y >= miPointer.limits.y2)
*y = miPointer.limits.y2 - 1;
if (miPointer.x == *x && miPointer.y == *y && miPointer.pScreen == pScreen)
return;
miPointerMoved(pDev, pScreen, *x, *y, time);
}
_X_EXPORT void
miPointerPosition (int *x, int *y)
{
miPointerGetPosition(inputInfo.pointer, x, y);
}
_X_EXPORT void
miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
{
*x = miPointer.x;
*y = miPointer.y;
}
#ifdef XQUARTZ
#include <pthread.h>
void darwinEvents_lock(void);
void darwinEvents_unlock(void);
#endif
void
miPointerMove (ScreenPtr pScreen, int x, int y, unsigned long time)
{
int i, nevents;
int valuators[2];
miPointerMoved(inputInfo.pointer, pScreen, x, y, time);
valuators[0] = x;
valuators[1] = y;
if (!events)
{
events = (xEvent*)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
if (!events)
{
FatalError("Could not allocate event store.\n");
return;
}
}
nevents = GetPointerEvents(events, inputInfo.pointer, MotionNotify, 0,
POINTER_ABSOLUTE, 0, 2, valuators);
#ifdef XQUARTZ
darwinEvents_lock();
#endif
for (i = 0; i < nevents; i++)
mieqEnqueue(inputInfo.pointer, &events[i]);
#ifdef XQUARTZ
darwinEvents_unlock();
#endif
}