#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#define DMX_CURSOR_DEBUG 0
#include "dmx.h"
#include "dmxsync.h"
#include "dmxcursor.h"
#include "dmxlog.h"
#include "dmxprop.h"
#include "dmxinput.h"
#include "mipointer.h"
#include "windowstr.h"
#include "globals.h"
#include "cursorstr.h"
#include "dixevents.h"
#if DMX_CURSOR_DEBUG
#define DMXDBG0(f) dmxLog(dmxDebug,f)
#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
#else
#define DMXDBG0(f)
#define DMXDBG1(f,a)
#define DMXDBG2(f,a,b)
#define DMXDBG3(f,a,b,c)
#define DMXDBG4(f,a,b,c,d)
#define DMXDBG5(f,a,b,c,d,e)
#define DMXDBG6(f,a,b,c,d,e,g)
#define DMXDBG7(f,a,b,c,d,e,g,h)
#endif
static int dmxCursorDoMultiCursors = 1;
void dmxCursorNoMulti(void)
{
dmxCursorDoMultiCursors = 0;
}
static Bool dmxCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
{
DMXScreenInfo *dmxScreen;
int i;
int localX = *x;
int localY = *y;
int globalX;
int globalY;
if (screenInfo.numScreens == 1)
return FALSE;
dmxScreen = &dmxScreens[(*ppScreen)->myNum];
if (localX >= 0
&& localX < dmxScreen->rootWidth
&& localY >= 0
&& localY < dmxScreen->rootHeight)
return FALSE;
globalX = dmxScreen->rootXOrigin + localX;
globalY = dmxScreen->rootYOrigin + localY;
if (ppScreen && *ppScreen) {
dmxScreen = &dmxScreens[(*ppScreen)->myNum];
if (globalX >= dmxScreen->rootXOrigin
&& globalX < dmxScreen->rootXOrigin + dmxScreen->rootWidth
&& globalY >= dmxScreen->rootYOrigin
&& globalY < dmxScreen->rootYOrigin + dmxScreen->rootHeight)
return FALSE;
}
for (i = 0; i < dmxNumScreens; i++) {
dmxScreen = &dmxScreens[i];
if (globalX >= dmxScreen->rootXOrigin
&& globalX < dmxScreen->rootXOrigin + dmxScreen->rootWidth
&& globalY >= dmxScreen->rootYOrigin
&& globalY < dmxScreen->rootYOrigin + dmxScreen->rootHeight) {
if (dmxScreen->index == (*ppScreen)->myNum)
return FALSE;
*ppScreen = screenInfo.screens[dmxScreen->index];
*x = globalX - dmxScreen->rootXOrigin;
*y = globalY - dmxScreen->rootYOrigin;
return TRUE;
}
}
return FALSE;
}
static void dmxCrossScreen(ScreenPtr pScreen, Bool entering)
{
}
static void dmxWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
{
DMXDBG3("dmxWarpCursor(%d,%d,%d)\n", pScreen->myNum, x, y);
#if 11
miPointerWarpCursor(pDev, pScreen, x, y);
#else
pScreen->SetCursorPosition(pDev, pScreen, x, y, FALSE);
#endif
}
miPointerScreenFuncRec dmxPointerCursorFuncs =
{
dmxCursorOffScreen,
dmxCrossScreen,
dmxWarpCursor,
dmxeqEnqueue,
dmxeqSwitchScreen
};
static int *dmxSLCreate(void)
{
int *list = malloc(dmxNumScreens * sizeof(*list));
int i;
for (i = 0; i < dmxNumScreens; i++)
list[i] = 1;
return list;
}
static void dmxSLFree(int *list)
{
free(list);
}
static int dmxSLFindNext(int *list)
{
int i;
for (i = 0; i < dmxNumScreens; i++)
if (list[i])
return i;
return -1;
}
static int dmxTryComputeScreenOrigins(int *screensLeft)
{
ScreenPtr pScreen;
DMXScreenInfo *screen;
int i, ref;
int changed = 0;
for (i = 0; i < dmxNumScreens; i++) {
if (!screensLeft[i])
continue;
screen = &dmxScreens[i];
switch (screen->where) {
case PosAbsolute:
dixScreenOrigins[i].x = screen->whereX;
dixScreenOrigins[i].y = screen->whereY;
++changed, screensLeft[i] = 0;
break;
case PosRelative:
ref = screen->whereRefScreen;
if (screensLeft[ref])
break;
dixScreenOrigins[i].x = dixScreenOrigins[ref].x + screen->whereX;
dixScreenOrigins[i].y = dixScreenOrigins[ref].y + screen->whereY;
++changed, screensLeft[i] = 0;
break;
case PosRightOf:
ref = screen->whereRefScreen;
if (screensLeft[ref])
break;
pScreen = screenInfo.screens[ref];
dixScreenOrigins[i].x = dixScreenOrigins[ref].x + pScreen->width;
dixScreenOrigins[i].y = dixScreenOrigins[ref].y;
++changed, screensLeft[i] = 0;
break;
case PosLeftOf:
ref = screen->whereRefScreen;
if (screensLeft[ref])
break;
pScreen = screenInfo.screens[i];
dixScreenOrigins[i].x = dixScreenOrigins[ref].x - pScreen->width;
dixScreenOrigins[i].y = dixScreenOrigins[ref].y;
++changed, screensLeft[i] = 0;
break;
case PosBelow:
ref = screen->whereRefScreen;
if (screensLeft[ref])
break;
pScreen = screenInfo.screens[ref];
dixScreenOrigins[i].x = dixScreenOrigins[ref].x;
dixScreenOrigins[i].y = dixScreenOrigins[ref].y + pScreen->height;
++changed, screensLeft[i] = 0;
break;
case PosAbove:
ref = screen->whereRefScreen;
if (screensLeft[ref])
break;
pScreen = screenInfo.screens[i];
dixScreenOrigins[i].x = dixScreenOrigins[ref].x;
dixScreenOrigins[i].y = dixScreenOrigins[ref].y - pScreen->height;
++changed, screensLeft[i] = 0;
break;
case PosNone:
dmxLog(dmxFatal, "No position information for screen %d\n", i);
}
}
return changed;
}
static void dmxComputeScreenOrigins(void)
{
int *screensLeft;
int i, ref;
int minX, minY;
screensLeft = dmxSLCreate();
while ((i = dmxSLFindNext(screensLeft)) >= 0) {
while (dmxTryComputeScreenOrigins(screensLeft));
if ((i = dmxSLFindNext(screensLeft)) >= 0) {
ref = dmxScreens[i].whereRefScreen;
dixScreenOrigins[ref].x = dixScreenOrigins[ref].y = 0;
screensLeft[ref] = 0;
}
}
dmxSLFree(screensLeft);
minX = dixScreenOrigins[0].x;
minY = dixScreenOrigins[0].y;
for (i = 1; i < dmxNumScreens; i++) {
if (dixScreenOrigins[i].x < minX)
minX = dixScreenOrigins[i].x;
if (dixScreenOrigins[i].y < minY)
minY = dixScreenOrigins[i].y;
}
if (minX || minY) {
for (i = 0; i < dmxNumScreens; i++) {
dixScreenOrigins[i].x -= minX;
dixScreenOrigins[i].y -= minY;
}
}
}
void dmxReInitOrigins(void)
{
int i;
if (dmxNumScreens > MAXSCREENS)
dmxLog(dmxFatal, "dmxNumScreens = %d > MAXSCREENS = %d\n",
dmxNumScreens, MAXSCREENS);
for (i = 0; i < dmxNumScreens; i++) {
DMXScreenInfo *dmxScreen = &dmxScreens[i];
dmxLogOutput(dmxScreen,
"s=%dx%d%+d%+d r=%dx%d%+d%+d @%d,%d"
" (be=%dx%d depth=%d bpp=%d)\n",
dmxScreen->scrnWidth, dmxScreen->scrnHeight,
dmxScreen->scrnX, dmxScreen->scrnY,
dmxScreen->rootWidth, dmxScreen->rootHeight,
dmxScreen->rootX, dmxScreen->rootY,
dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
dmxScreen->beWidth, dmxScreen->beHeight,
dmxScreen->beDepth, dmxScreen->beBPP);
}
}
void dmxInitOrigins(void)
{
int i;
if (dmxNumScreens > MAXSCREENS)
dmxLog(dmxFatal, "dmxNumScreens = %d > MAXSCREENS = %d\n",
dmxNumScreens, MAXSCREENS);
for (i = 0; i < dmxNumScreens; i++) {
DMXScreenInfo *dmxScreen = &dmxScreens[i];
dmxLogOutput(dmxScreen,
"(request) s=%dx%d%+d%+d r=%dx%d%+d%+d @%d,%d (%d)"
" (be=%dx%d depth=%d bpp=%d)\n",
dmxScreen->scrnWidth, dmxScreen->scrnHeight,
dmxScreen->scrnX, dmxScreen->scrnY,
dmxScreen->rootWidth, dmxScreen->rootHeight,
dmxScreen->rootX, dmxScreen->rootY,
dmxScreen->whereX, dmxScreen->whereY,
dmxScreen->where,
dmxScreen->beWidth, dmxScreen->beHeight,
dmxScreen->beDepth, dmxScreen->beBPP);
}
dmxComputeScreenOrigins();
for (i = 0; i < dmxNumScreens; i++) {
DMXScreenInfo *dmxScreen = &dmxScreens[i];
dmxScreen->rootXOrigin = dixScreenOrigins[i].x;
dmxScreen->rootYOrigin = dixScreenOrigins[i].y;
}
dmxReInitOrigins();
}
int dmxOnScreen(int x, int y, DMXScreenInfo *dmxScreen)
{
#if DMX_CURSOR_DEBUG > 1
dmxLog(dmxDebug,
"dmxOnScreen %d %d,%d (r=%dx%d%+d%+d@%d,%d s=%dx%d%+d%+d)\n",
dmxScreen->index, x, y,
dmxScreen->rootWidth, dmxScreen->rootHeight,
dmxScreen->rootX, dmxScreen->rootY,
dmxScreen->rootXOrigin, dmxScreen->rootYOrigin,
dmxScreen->scrnWidth, dmxScreen->scrnHeight,
dmxScreen->scrnX, dmxScreen->scrnY);
#endif
if (x >= dmxScreen->rootXOrigin
&& x < dmxScreen->rootXOrigin + dmxScreen->rootWidth
&& y >= dmxScreen->rootYOrigin
&& y < dmxScreen->rootYOrigin + dmxScreen->rootHeight) return 1;
return 0;
}
static int dmxDoesOverlap(DMXScreenInfo *a, DMXScreenInfo *b)
{
if (dmxOnScreen(a->rootXOrigin,
a->rootYOrigin, b))
return 1;
if (dmxOnScreen(a->rootXOrigin,
a->rootYOrigin + a->scrnWidth, b))
return 1;
if (dmxOnScreen(a->rootXOrigin + a->scrnHeight,
a->rootYOrigin, b))
return 1;
if (dmxOnScreen(a->rootXOrigin + a->scrnHeight,
a->rootYOrigin + a->scrnWidth, b))
return 1;
if (dmxOnScreen(b->rootXOrigin,
b->rootYOrigin, a))
return 1;
if (dmxOnScreen(b->rootXOrigin,
b->rootYOrigin + b->scrnWidth, a))
return 1;
if (dmxOnScreen(b->rootXOrigin + b->scrnHeight,
b->rootYOrigin, a))
return 1;
if (dmxOnScreen(b->rootXOrigin + b->scrnHeight,
b->rootYOrigin + b->scrnWidth, a))
return 1;
return 0;
}
static void *dmxPrintOverlap(DMXScreenInfo *dmxScreen, void *closure)
{
DMXScreenInfo *a = closure;
if (dmxScreen != a) {
if (dmxScreen->cursorNotShared)
dmxLogOutputCont(a, " [%d/%s]", dmxScreen->index, dmxScreen->name);
else
dmxLogOutputCont(a, " %d/%s", dmxScreen->index, dmxScreen->name);
}
return NULL;
}
static void *dmxIterateOverlap(DMXScreenInfo *start,
void *(*f)(DMXScreenInfo *dmxScreen, void *),
void *closure)
{
DMXScreenInfo *pt;
if (!start->over) return f(start, closure);
for (pt = start->over; ; pt = pt->over) {
void *retval;
if ((retval = f(pt, closure))) return retval;
if (pt == start) break;
}
return NULL;
}
static void *dmxTestSameDisplay(DMXScreenInfo *a, void *closure)
{
DMXScreenInfo *b = closure;
if (a == b)
return a;
return NULL;
}
void dmxInitOverlap(void)
{
int i, j;
DMXScreenInfo *a, *b, *pt;
for (i = 0; i < dmxNumScreens; i++)
dmxScreens[i].over = NULL;
for (i = 0; i < dmxNumScreens; i++) {
a = &dmxScreens[i];
for (j = i+1; j < dmxNumScreens; j++) {
b = &dmxScreens[j];
if (b->over)
continue;
if (dmxDoesOverlap(a, b)) {
DMXDBG6("%d overlaps %d: a=%p %p b=%p %p\n",
a->index, b->index, a, a->over, b, b->over);
b->over = (a->over ? a->over : a);
a->over = b;
}
}
}
for (i = 0; i < dmxNumScreens; i++) {
a = &dmxScreens[i];
if (!a->over)
continue;
for (pt = a->over; pt != a; pt = pt->over) {
if (dmxPropertyIterate(a, dmxTestSameDisplay, pt)) {
if (!dmxDoesOverlap(a, pt))
continue;
a->cursorNotShared = 1;
pt->cursorNotShared = 1;
dmxLog(dmxInfo,
"Screen %d and %d overlap on %s\n",
a->index, pt->index, a->name);
}
}
}
for (i = 0; i < dmxNumScreens; i++) {
a = &dmxScreens[i];
if (a->over) {
dmxLogOutput(a, "Overlaps");
dmxIterateOverlap(a, dmxPrintOverlap, a);
dmxLogOutputCont(a, "\n");
}
}
}
void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
CursorBitsPtr pBits = pCursor->bits;
Pixmap src, msk;
XColor fg, bg;
XImage *img;
XlibGC gc = NULL;
XGCValues v;
unsigned long m;
int i;
if (!pCursorPriv)
return;
m = GCFunction | GCPlaneMask | GCForeground | GCBackground | GCClipMask;
v.function = GXcopy;
v.plane_mask = AllPlanes;
v.foreground = 1L;
v.background = 0L;
v.clip_mask = None;
for (i = 0; i < dmxScreen->beNumPixmapFormats; i++) {
if (dmxScreen->bePixmapFormats[i].depth == 1) {
gc = XCreateGC(dmxScreen->beDisplay, dmxScreen->scrnDefDrawables[i],
m, &v);
break;
}
}
if (!gc)
dmxLog(dmxFatal, "dmxRealizeCursor: gc not initialized\n");
src = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
pBits->width, pBits->height, 1);
msk = XCreatePixmap(dmxScreen->beDisplay, dmxScreen->scrnWin,
pBits->width, pBits->height, 1);
img = XCreateImage(dmxScreen->beDisplay,
dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
1, XYBitmap, 0, (char *)pBits->source,
pBits->width, pBits->height,
BitmapPad(dmxScreen->beDisplay), 0);
XPutImage(dmxScreen->beDisplay, src, gc, img, 0, 0, 0, 0,
pBits->width, pBits->height);
XFree(img);
img = XCreateImage(dmxScreen->beDisplay,
dmxScreen->beVisuals[dmxScreen->beDefVisualIndex].visual,
1, XYBitmap, 0, (char *)pBits->mask,
pBits->width, pBits->height,
BitmapPad(dmxScreen->beDisplay), 0);
XPutImage(dmxScreen->beDisplay, msk, gc, img, 0, 0, 0, 0,
pBits->width, pBits->height);
XFree(img);
fg.red = pCursor->foreRed;
fg.green = pCursor->foreGreen;
fg.blue = pCursor->foreBlue;
bg.red = pCursor->backRed;
bg.green = pCursor->backGreen;
bg.blue = pCursor->backBlue;
pCursorPriv->cursor = XCreatePixmapCursor(dmxScreen->beDisplay,
src, msk,
&fg, &bg,
pBits->xhot, pBits->yhot);
XFreePixmap(dmxScreen->beDisplay, src);
XFreePixmap(dmxScreen->beDisplay, msk);
XFreeGC(dmxScreen->beDisplay, gc);
dmxSync(dmxScreen, FALSE);
}
static Bool _dmxRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxCursorPrivPtr pCursorPriv;
DMXDBG2("_dmxRealizeCursor(%d,%p)\n", pScreen->myNum, pCursor);
DMX_SET_CURSOR_PRIV(pCursor, pScreen, xalloc(sizeof(*pCursorPriv)));
if (!DMX_GET_CURSOR_PRIV(pCursor, pScreen))
return FALSE;
pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
pCursorPriv->cursor = (Cursor)0;
if (!dmxScreen->beDisplay)
return TRUE;
dmxBECreateCursor(pScreen, pCursor);
return TRUE;
}
Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
if (pCursorPriv) {
XFreeCursor(dmxScreen->beDisplay, pCursorPriv->cursor);
pCursorPriv->cursor = (Cursor)0;
return TRUE;
}
return FALSE;
}
static Bool _dmxUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
DMXDBG2("_dmxUnrealizeCursor(%d,%p)\n",
pScreen->myNum, pCursor);
if (dmxScreen->beDisplay) {
if (dmxBEFreeCursor(pScreen, pCursor))
xfree(DMX_GET_CURSOR_PRIV(pCursor, pScreen));
}
DMX_SET_CURSOR_PRIV(pCursor, pScreen, NULL);
return TRUE;
}
static void _dmxMoveCursor(ScreenPtr pScreen, int x, int y)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
int newX = x + dmxScreen->rootX;
int newY = y + dmxScreen->rootY;
if (newX < 0) newX = 0;
if (newY < 0) newY = 0;
DMXDBG5("_dmxMoveCursor(%d,%d,%d) -> %d,%d\n",
pScreen->myNum, x, y, newX, newY);
if (dmxScreen->beDisplay) {
XWarpPointer(dmxScreen->beDisplay, None, dmxScreen->scrnWin,
0, 0, 0, 0, newX, newY);
dmxSync(dmxScreen, TRUE);
}
}
static void _dmxSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
DMXDBG4("_dmxSetCursor(%d,%p,%d,%d)\n", pScreen->myNum, pCursor, x, y);
if (pCursor) {
dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
if (pCursorPriv && dmxScreen->curCursor != pCursorPriv->cursor) {
if (dmxScreen->beDisplay)
XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
pCursorPriv->cursor);
dmxScreen->cursor = pCursor;
dmxScreen->curCursor = pCursorPriv->cursor;
dmxScreen->cursorVisible = 1;
}
_dmxMoveCursor(pScreen, x, y);
} else {
if (dmxScreen->beDisplay)
XDefineCursor(dmxScreen->beDisplay, dmxScreen->scrnWin,
dmxScreen->noCursor);
dmxScreen->cursor = NULL;
dmxScreen->curCursor = (Cursor)0;
dmxScreen->cursorVisible = 0;
}
if (dmxScreen->beDisplay) dmxSync(dmxScreen, TRUE);
}
static Bool dmxRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
{
DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
DMXScreenInfo *pt;
if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared)
return _dmxRealizeCursor(pScreen, pCursor);
for (pt = start->over; ; pt = pt->over) {
if (pt->cursorNotShared)
continue;
_dmxRealizeCursor(screenInfo.screens[pt->index], pCursor);
if (pt == start)
break;
}
return TRUE;
}
static Bool dmxUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
{
DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
DMXScreenInfo *pt;
if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared)
return _dmxUnrealizeCursor(pScreen, pCursor);
for (pt = start->over; ; pt = pt->over) {
if (pt->cursorNotShared)
continue;
_dmxUnrealizeCursor(screenInfo.screens[pt->index], pCursor);
if (pt == start)
break;
}
return TRUE;
}
static CursorPtr dmxFindCursor(DMXScreenInfo *start)
{
DMXScreenInfo *pt;
if (!start || !start->over)
return GetSpriteCursor(inputInfo.pointer);
for (pt = start->over; ; pt = pt->over) {
if (pt->cursor)
return pt->cursor;
if (pt == start)
break;
}
return GetSpriteCursor(inputInfo.pointer);
}
void dmxMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
{
DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
DMXScreenInfo *pt;
DMXDBG3("dmxMoveCursor(%d,%d,%d)\n", pScreen->myNum, x, y);
if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) {
_dmxMoveCursor(pScreen, x, y);
return;
}
for (pt = start->over; ; pt = pt->over) {
if (pt->cursorNotShared)
continue;
if (dmxOnScreen(x + start->rootXOrigin, y + start->rootYOrigin, pt)) {
if ( !pt->cursorVisible) {
if (!pt->cursor) {
CursorPtr pCursor;
if ((pCursor = dmxFindCursor(start)))
_dmxRealizeCursor(screenInfo.screens[pt->index],
pt->cursor = pCursor);
}
_dmxSetCursor(screenInfo.screens[pt->index],
pt->cursor,
x + start->rootXOrigin - pt->rootXOrigin,
y + start->rootYOrigin - pt->rootYOrigin);
}
_dmxMoveCursor(screenInfo.screens[pt->index],
x + start->rootXOrigin - pt->rootXOrigin,
y + start->rootYOrigin - pt->rootYOrigin);
} else if ( pt->cursorVisible) {
_dmxSetCursor(screenInfo.screens[pt->index],
NULL,
x + start->rootXOrigin - pt->rootXOrigin,
y + start->rootYOrigin - pt->rootYOrigin);
}
if (pt == start)
break;
}
}
static void dmxSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
{
DMXScreenInfo *start = &dmxScreens[pScreen->myNum];
DMXScreenInfo *pt;
int GX, GY, gx, gy;
DMXDBG5("dmxSetCursor(%d %p, %p,%d,%d)\n",
pScreen->myNum, start, pCursor, x, y);
dmxGetGlobalPosition(&GX, &GY);
gx = start->rootXOrigin + x;
gy = start->rootYOrigin + y;
if (x && y && (GX != gx || GY != gy))
dmxCoreMotion(NULL, gx, gy, 0, DMX_NO_BLOCK);
if (!start->over || !dmxCursorDoMultiCursors || start->cursorNotShared) {
_dmxSetCursor(pScreen, pCursor, x, y);
return;
}
for (pt = start->over; ; pt = pt->over) {
if (pt->cursorNotShared)
continue;
if (dmxOnScreen(x + start->rootXOrigin, y + start->rootYOrigin, pt)) {
_dmxSetCursor(screenInfo.screens[pt->index], pCursor,
x + start->rootXOrigin - pt->rootXOrigin,
y + start->rootYOrigin - pt->rootYOrigin);
} else {
_dmxSetCursor(screenInfo.screens[pt->index], NULL,
x + start->rootXOrigin - pt->rootXOrigin,
y + start->rootYOrigin - pt->rootYOrigin);
}
if (pt == start)
break;
}
}
void dmxHideCursor(DMXScreenInfo *dmxScreen)
{
int x, y;
ScreenPtr pScreen = screenInfo.screens[dmxScreen->index];
dmxGetGlobalPosition(&x, &y);
_dmxSetCursor(pScreen, NULL, x, y);
}
void dmxCheckCursor(void)
{
int i;
int x, y;
ScreenPtr pScreen;
DMXScreenInfo *firstScreen;
dmxGetGlobalPosition(&x, &y);
firstScreen = dmxFindFirstScreen(x, y);
DMXDBG2("dmxCheckCursor %d %d\n", x, y);
for (i = 0; i < dmxNumScreens; i++) {
DMXScreenInfo *dmxScreen = &dmxScreens[i];
pScreen = screenInfo.screens[dmxScreen->index];
if (!dmxOnScreen(x, y, dmxScreen)) {
if (firstScreen && i == miPointerGetScreen(inputInfo.pointer)->myNum)
miPointerSetScreen(inputInfo.pointer, firstScreen->index, x, y);
_dmxSetCursor(pScreen, NULL,
x - dmxScreen->rootXOrigin,
y - dmxScreen->rootYOrigin);
} else {
if (!dmxScreen->cursor) {
CursorPtr pCursor;
if ((pCursor = dmxFindCursor(dmxScreen))) {
_dmxRealizeCursor(pScreen, dmxScreen->cursor = pCursor);
}
}
_dmxSetCursor(pScreen, dmxScreen->cursor,
x - dmxScreen->rootXOrigin,
y - dmxScreen->rootYOrigin);
}
}
DMXDBG2(" leave dmxCheckCursor %d %d\n", x, y);
}
static Bool dmxDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr)
{
return TRUE;
}
static void dmxDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr)
{
}
miPointerSpriteFuncRec dmxPointerSpriteFuncs =
{
dmxRealizeCursor,
dmxUnrealizeCursor,
dmxSetCursor,
dmxMoveCursor,
dmxDeviceCursorInitialize,
dmxDeviceCursorCleanup
};