#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"
static int miPointerScreenKeyIndex;
_X_EXPORT DevPrivateKey miPointerScreenKey = &miPointerScreenKeyIndex;
#define GetScreenPrivate(s) ((miPointerScreenPtr) \
dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey))
#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
static int miPointerPrivKeyIndex;
static DevPrivateKey miPointerPrivKey = &miPointerPrivKeyIndex;
#define MIPOINTER(dev) \
((DevHasCursor((dev)) || (!dev->isMaster && !dev->u.master)) ? \
(miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \
(miPointerPtr)dixLookupPrivate(&(dev)->u.master->devPrivates, miPointerPrivKey))
static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
CursorPtr pCursor);
static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
CursorPtr pCursor);
static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
CursorPtr pCursor);
static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen,
BoxPtr pBox);
static void miPointerPointerNonInterestBox(DeviceIntPtr pDev,
ScreenPtr pScreen, BoxPtr pBox);
static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen,
CursorPtr pCursor, BoxPtr pHotBox,
BoxPtr pTopLeftBox);
static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
int x, int y,
Bool generateEvent);
static Bool miPointerCloseScreen(int index, ScreenPtr pScreen);
static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen,
int x, int y);
static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen);
static void miPointerDeviceCleanup(DeviceIntPtr pDev,
ScreenPtr pScreen);
static EventList* events;
_X_EXPORT Bool
miPointerInitialize (ScreenPtr pScreen,
miPointerSpriteFuncPtr spriteFuncs,
miPointerScreenFuncPtr screenFuncs,
Bool waitForUpdate)
{
miPointerScreenPtr pScreenPriv;
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;
dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, 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;
pScreen->DeviceCursorInitialize = miPointerDeviceInitialize;
pScreen->DeviceCursorCleanup = miPointerDeviceCleanup;
events = NULL;
return TRUE;
}
static Bool
miPointerCloseScreen (int index, ScreenPtr pScreen)
{
#if 0
miPointerPtr pPointer;
DeviceIntPtr pDev;
#endif
SetupScreen(pScreen);
#if 0
for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
{
if (DevHasCursor(pDev))
{
pPointer = MIPOINTER(pDev);
if (pScreen == pPointer->pScreen)
pPointer->pScreen = 0;
if (pScreen == pPointer->pSpriteScreen)
pPointer->pSpriteScreen = 0;
}
}
if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen)
MIPOINTER(inputInfo.pointer)->pScreen = 0;
if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen)
MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0;
#endif
pScreen->CloseScreen = pScreenPriv->CloseScreen;
xfree ((pointer) pScreenPriv);
FreeEventList(events, GetMaximumEventsNum());
events = NULL;
return (*pScreen->CloseScreen) (index, pScreen);
}
static Bool
miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
{
SetupScreen(pScreen);
return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor);
}
static Bool
miPointerUnrealizeCursor (DeviceIntPtr pDev,
ScreenPtr pScreen,
CursorPtr pCursor)
{
SetupScreen(pScreen);
return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor);
}
static Bool
miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
{
miPointerPtr pPointer;
if ((pDev->isMaster && !DevHasCursor(pDev)) ||
(!pDev->isMaster && pDev->u.master && !DevHasCursor(pDev->u.master)))
return FALSE;
pPointer = MIPOINTER(pDev);
pPointer->pCursor = pCursor;
pPointer->pScreen = pScreen;
miPointerUpdateSprite(pDev);
return TRUE;
}
static void
miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox)
{
miPointerPtr pPointer;
pPointer = MIPOINTER(pDev);
pPointer->limits = *pBox;
pPointer->confined = PointerConfinedToScreen(pDev);
}
static void
miPointerPointerNonInterestBox (DeviceIntPtr pDev,
ScreenPtr pScreen,
BoxPtr pBox)
{
}
static void
miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor,
BoxPtr pHotBox, BoxPtr pTopLeftBox)
{
*pTopLeftBox = *pHotBox;
}
static Bool GenerateEvent;
static Bool
miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
int x, int y, Bool generateEvent)
{
SetupScreen (pScreen);
GenerateEvent = generateEvent;
(*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
if (!generateEvent)
miPointerUpdateSprite(pDev);
return TRUE;
}
static Bool
miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen)
{
miPointerPtr pPointer;
SetupScreen (pScreen);
pPointer = xalloc(sizeof(miPointerRec));
if (!pPointer)
return FALSE;
pPointer->pScreen = NULL;
pPointer->pSpriteScreen = NULL;
pPointer->pCursor = NULL;
pPointer->pSpriteCursor = NULL;
pPointer->limits.x1 = 0;
pPointer->limits.x2 = 32767;
pPointer->limits.y1 = 0;
pPointer->limits.y2 = 32767;
pPointer->confined = FALSE;
pPointer->x = 0;
pPointer->y = 0;
if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen)))
{
xfree(pPointer);
return FALSE;
}
dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer);
return TRUE;
}
static void
miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen)
{
if (!pDev->isMaster && pDev->u.master)
return;
SetupScreen(pScreen);
(*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen);
xfree(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey));
dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL);
}
_X_EXPORT void
miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
{
miPointerPtr pPointer;
BOOL changedScreen = FALSE;
pPointer = MIPOINTER(pDev);
SetupScreen (pScreen);
if (pPointer->pScreen != pScreen)
{
(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE);
changedScreen = TRUE;
}
if (GenerateEvent)
{
miPointerMove (pDev, pScreen, x, y);
}
else
{
if (!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
{
pPointer->devx = x;
pPointer->devy = y;
if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
}
pPointer->x = x;
pPointer->y = y;
pPointer->pScreen = pScreen;
}
if (changedScreen
#ifdef PANORAMIX
&& noPanoramiXExtension
#endif
)
UpdateSpriteForScreen (pDev, pScreen) ;
}
void
miPointerUpdateSprite (DeviceIntPtr pDev)
{
ScreenPtr pScreen;
miPointerScreenPtr pScreenPriv;
CursorPtr pCursor;
int x, y, devx, devy;
miPointerPtr pPointer;
if (!pDev || !pDev->coreEvents)
return;
pPointer = MIPOINTER(pDev);
pScreen = pPointer->pScreen;
if (!pScreen)
return;
x = pPointer->x;
y = pPointer->y;
devx = pPointer->devx;
devy = pPointer->devy;
pScreenPriv = GetScreenPrivate (pScreen);
if (pScreen != pPointer->pSpriteScreen)
{
if (pPointer->pSpriteScreen)
{
miPointerScreenPtr pOldPriv;
pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen);
if (pPointer->pCursor)
{
(*pOldPriv->spriteFuncs->SetCursor)
(pDev, pPointer->pSpriteScreen, NullCursor, 0, 0);
}
(*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE);
}
(*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
(*pScreenPriv->spriteFuncs->SetCursor)
(pDev, pScreen, pPointer->pCursor, x, y);
pPointer->devx = x;
pPointer->devy = y;
pPointer->pSpriteCursor = pPointer->pCursor;
pPointer->pSpriteScreen = pScreen;
}
else if (pPointer->pCursor != pPointer->pSpriteCursor)
{
pCursor = pPointer->pCursor;
if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent))
pCursor = NullCursor;
(*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y);
pPointer->devx = x;
pPointer->devy = y;
pPointer->pSpriteCursor = pPointer->pCursor;
}
else if (x != devx || y != devy)
{
pPointer->devx = x;
pPointer->devy = y;
if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
}
}
void
miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y)
{
miPointerScreenPtr pScreenPriv;
ScreenPtr pScreen;
miPointerPtr pPointer;
pPointer = MIPOINTER(pDev);
pScreen = screenInfo.screens[screen_no];
pScreenPriv = GetScreenPrivate (pScreen);
(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE);
NewCurrentScreen (pDev, pScreen, x, y);
pPointer->limits.x2 = pScreen->width;
pPointer->limits.y2 = pScreen->height;
}
_X_EXPORT ScreenPtr
miPointerCurrentScreen ()
{
return miPointerGetScreen(inputInfo.pointer);
}
_X_EXPORT ScreenPtr
miPointerGetScreen(DeviceIntPtr pDev)
{
miPointerPtr pPointer = MIPOINTER(pDev);
return (pPointer) ? pPointer->pScreen : NULL;
}
_X_EXPORT void
miPointerAbsoluteCursor (int x, int y, unsigned long time)
{
miPointerSetPosition(inputInfo.pointer, &x, &y);
}
static void
miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen,
int x, int y)
{
miPointerPtr pPointer;
SetupScreen(pScreen);
pPointer = MIPOINTER(pDev);
if ((pDev == inputInfo.pointer || (!pDev->isMaster && pDev->u.master == inputInfo.pointer))
&& !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen)
{
pPointer->devx = x;
pPointer->devy = y;
if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y);
}
pPointer->x = x;
pPointer->y = y;
pPointer->pScreen = pScreen;
}
_X_EXPORT void
miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
{
miPointerScreenPtr pScreenPriv;
ScreenPtr pScreen;
ScreenPtr newScreen;
miPointerPtr pPointer;
pPointer = MIPOINTER(pDev);
pScreen = pPointer->pScreen;
if (!pScreen)
return;
if (!pDev || !pDev->coreEvents)
return;
if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height)
{
pScreenPriv = GetScreenPrivate (pScreen);
if (!pPointer->confined)
{
newScreen = pScreen;
(*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y);
if (newScreen != pScreen)
{
pScreen = newScreen;
(*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen,
FALSE);
pScreenPriv = GetScreenPrivate (pScreen);
pPointer->limits.x2 = pScreen->width;
pPointer->limits.y2 = pScreen->height;
}
}
}
if (*x < pPointer->limits.x1)
*x = pPointer->limits.x1;
if (*x >= pPointer->limits.x2)
*x = pPointer->limits.x2 - 1;
if (*y < pPointer->limits.y1)
*y = pPointer->limits.y1;
if (*y >= pPointer->limits.y2)
*y = pPointer->limits.y2 - 1;
if (pPointer->x == *x && pPointer->y == *y &&
pPointer->pScreen == pScreen)
return;
miPointerMoved(pDev, pScreen, *x, *y);
}
_X_EXPORT void
miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
{
*x = MIPOINTER(pDev)->x;
*y = MIPOINTER(pDev)->y;
}
#ifdef XQUARTZ
#include <pthread.h>
void darwinEvents_lock(void);
void darwinEvents_unlock(void);
#endif
void
miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
{
int i, nevents;
int valuators[2];
miPointerMoved(pDev, pScreen, x, y);
valuators[0] = x;
valuators[1] = y;
if (!events)
{
events = InitEventList(GetMaximumEventsNum());
if (!events)
{
FatalError("Could not allocate event store.\n");
return;
}
}
nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_SCREEN | POINTER_ABSOLUTE, 0, 2, valuators);
OsBlockSignals();
#ifdef XQUARTZ
darwinEvents_lock();
#endif
for (i = 0; i < nevents; i++)
mieqEnqueue(pDev, events[i].event);
#ifdef XQUARTZ
darwinEvents_unlock();
#endif
OsReleaseSignals();
}