2
* $Id: cursor.c,v 1.6 2005/07/03 07:37:35 daniels Exp $
4
* Copyright Ā© 2002 Keith Packard
6
* Permission to use, copy, modify, distribute, and sell this software and its
7
* documentation for any purpose is hereby granted without fee, provided that
8
* the above copyright notice appear in all copies and that both that
9
* copyright notice and this permission notice appear in supporting
10
* documentation, and that the name of Keith Packard not be used in
11
* advertising or publicity pertaining to distribution of the software without
12
* specific, written prior permission. Keith Packard makes no
13
* representations about the suitability of this software for any purpose. It
14
* is provided "as is" without express or implied warranty.
16
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
* PERFORMANCE OF THIS SOFTWARE.
25
#ifdef HAVE_DIX_CONFIG_H
26
#include <dix-config.h>
29
#include "xfixesint.h"
30
#include "scrnintstr.h"
31
#include "cursorstr.h"
32
#include "dixevents.h"
35
#include "windowstr.h"
37
static RESTYPE CursorClientType;
38
static RESTYPE CursorWindowType;
39
static int CursorScreenPrivateIndex = -1;
40
static int CursorGeneration;
41
static CursorPtr CursorCurrent;
43
#define VERIFY_CURSOR(pCursor, cursor, client, access) { \
44
pCursor = (CursorPtr)SecurityLookupIDByType((client), (cursor), \
45
RT_CURSOR, (access)); \
47
(client)->errorValue = (cursor); \
53
* There is a global list of windows selecting for cursor events
56
typedef struct _CursorEvent *CursorEventPtr;
58
typedef struct _CursorEvent {
66
static CursorEventPtr cursorEvents;
69
* Wrap DisplayCursor to catch cursor change events
72
typedef struct _CursorScreen {
73
DisplayCursorProcPtr DisplayCursor;
74
CloseScreenProcPtr CloseScreen;
75
} CursorScreenRec, *CursorScreenPtr;
77
#define GetCursorScreen(s) ((CursorScreenPtr) ((s)->devPrivates[CursorScreenPrivateIndex].ptr))
78
#define GetCursorScreenIfSet(s) ((CursorScreenPrivateIndex != -1) ? GetCursorScreen(s) : NULL)
79
#define SetCursorScreen(s,p) ((s)->devPrivates[CursorScreenPrivateIndex].ptr = (pointer) (p))
80
#define Wrap(as,s,elt,func) (((as)->elt = (s)->elt), (s)->elt = func)
81
#define Unwrap(as,s,elt) ((s)->elt = (as)->elt)
84
CursorDisplayCursor (ScreenPtr pScreen,
87
CursorScreenPtr cs = GetCursorScreen(pScreen);
90
Unwrap (cs, pScreen, DisplayCursor);
91
ret = (*pScreen->DisplayCursor) (pScreen, pCursor);
92
if (pCursor != CursorCurrent)
96
CursorCurrent = pCursor;
97
for (e = cursorEvents; e; e = e->next)
99
if (e->eventMask & XFixesDisplayCursorNotifyMask)
101
xXFixesCursorNotifyEvent ev;
102
ev.type = XFixesEventBase + XFixesCursorNotify;
103
ev.subtype = XFixesDisplayCursorNotify;
104
ev.sequenceNumber = e->pClient->sequence;
105
ev.window = e->pWindow->drawable.id;
106
ev.cursorSerial = pCursor->serialNumber;
107
ev.timestamp = currentTime.milliseconds;
108
ev.name = pCursor->name;
109
WriteEventsToClient (e->pClient, 1, (xEvent *) &ev);
113
Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
118
CursorCloseScreen (int index, ScreenPtr pScreen)
120
CursorScreenPtr cs = GetCursorScreen (pScreen);
123
Unwrap (cs, pScreen, CloseScreen);
124
Unwrap (cs, pScreen, DisplayCursor);
125
ret = (*pScreen->CloseScreen) (index, pScreen);
128
CursorScreenPrivateIndex = -1;
132
#define CursorAllEvents (XFixesDisplayCursorNotifyMask)
135
XFixesSelectCursorInput (ClientPtr pClient,
139
CursorEventPtr *prev, e;
141
for (prev = &cursorEvents; (e = *prev); prev = &e->next)
143
if (e->pClient == pClient &&
144
e->pWindow == pWindow)
153
FreeResource (e->clientResource, 0);
159
e = (CursorEventPtr) xalloc (sizeof (CursorEventRec));
164
e->pClient = pClient;
165
e->pWindow = pWindow;
166
e->clientResource = FakeClientID(pClient->index);
169
* Add a resource hanging from the window to
170
* catch window destroy
172
if (!LookupIDByType(pWindow->drawable.id, CursorWindowType))
173
if (!AddResource (pWindow->drawable.id, CursorWindowType,
180
if (!AddResource (e->clientResource, CursorClientType, (pointer) e))
185
e->eventMask = eventMask;
190
ProcXFixesSelectCursorInput (ClientPtr client)
192
REQUEST (xXFixesSelectCursorInputReq);
195
REQUEST_SIZE_MATCH (xXFixesSelectCursorInputReq);
196
pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
200
if (stuff->eventMask & ~CursorAllEvents)
202
client->errorValue = stuff->eventMask;
205
return XFixesSelectCursorInput (client, pWin, stuff->eventMask);
209
GetBit (unsigned char *line, int x)
213
if (screenInfo.bitmapBitOrder == LSBFirst)
214
mask = (1 << (x & 7));
216
mask = (0x80 >> (x & 7));
217
/* XXX assumes byte order is host byte order */
225
SProcXFixesSelectCursorInput (ClientPtr client)
228
REQUEST(xXFixesSelectCursorInputReq);
230
swaps(&stuff->length, n);
231
swapl(&stuff->window, n);
232
swapl(&stuff->eventMask, n);
233
return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
237
SXFixesCursorNotifyEvent (xXFixesCursorNotifyEvent *from,
238
xXFixesCursorNotifyEvent *to)
240
to->type = from->type;
241
cpswaps (from->sequenceNumber, to->sequenceNumber);
242
cpswapl (from->window, to->window);
243
cpswapl (from->cursorSerial, to->cursorSerial);
244
cpswapl (from->timestamp, to->timestamp);
245
cpswapl (from->name, to->name);
249
CopyCursorToImage (CursorPtr pCursor, CARD32 *image)
251
int width = pCursor->bits->width;
252
int height = pCursor->bits->height;
253
int npixels = width * height;
256
if (pCursor->bits->argb)
257
memcpy (image, pCursor->bits->argb, npixels * sizeof (CARD32));
261
unsigned char *srcLine = pCursor->bits->source;
262
unsigned char *mskLine = pCursor->bits->mask;
263
int stride = BitmapBytePad (width);
268
((pCursor->foreRed & 0xff00) << 8) |
269
(pCursor->foreGreen & 0xff00) |
270
(pCursor->foreBlue >> 8));
272
((pCursor->backRed & 0xff00) << 8) |
273
(pCursor->backGreen & 0xff00) |
274
(pCursor->backBlue >> 8));
275
for (y = 0; y < height; y++)
277
for (x = 0; x < width; x++)
279
if (GetBit (mskLine, x))
281
if (GetBit (srcLine, x))
296
ProcXFixesGetCursorImage (ClientPtr client)
298
/* REQUEST(xXFixesGetCursorImageReq); */
299
xXFixesGetCursorImageReply *rep;
306
REQUEST_SIZE_MATCH(xXFixesGetCursorImageReq);
307
pCursor = CursorCurrent;
310
GetSpritePosition (&x, &y);
311
width = pCursor->bits->width;
312
height = pCursor->bits->height;
313
npixels = width * height;
314
rep = xalloc (sizeof (xXFixesGetCursorImageReply) +
315
npixels * sizeof (CARD32));
320
rep->sequenceNumber = client->sequence;
321
rep->length = npixels;
323
rep->height = height;
326
rep->xhot = pCursor->bits->xhot;
327
rep->yhot = pCursor->bits->yhot;
328
rep->cursorSerial = pCursor->serialNumber;
330
image = (CARD32 *) (rep + 1);
331
CopyCursorToImage (pCursor, image);
335
swaps (&rep->sequenceNumber, n);
336
swapl (&rep->length, n);
339
swaps (&rep->width, n);
340
swaps (&rep->height, n);
341
swaps (&rep->xhot, n);
342
swaps (&rep->yhot, n);
343
swapl (&rep->cursorSerial, n);
344
SwapLongs (image, npixels);
346
(void) WriteToClient(client, sizeof (xXFixesGetCursorImageReply) +
347
(npixels << 2), (char *) rep);
349
return client->noClientException;
353
SProcXFixesGetCursorImage (ClientPtr client)
356
REQUEST(xXFixesGetCursorImageReq);
357
swaps (&stuff->length, n);
358
return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
362
ProcXFixesSetCursorName (ClientPtr client)
366
REQUEST(xXFixesSetCursorNameReq);
369
REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
370
VERIFY_CURSOR(pCursor, stuff->cursor, client, SecurityWriteAccess);
371
tchar = (char *) &stuff[1];
372
atom = MakeAtom (tchar, stuff->nbytes, TRUE);
373
if (atom == BAD_RESOURCE)
376
pCursor->name = atom;
377
return(client->noClientException);
381
SProcXFixesSetCursorName (ClientPtr client)
384
REQUEST(xXFixesSetCursorNameReq);
386
swaps (&stuff->length, n);
387
REQUEST_AT_LEAST_SIZE(xXFixesSetCursorNameReq);
388
swapl (&stuff->cursor, n);
389
swaps (&stuff->nbytes, n);
390
return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
394
ProcXFixesGetCursorName (ClientPtr client)
397
xXFixesGetCursorNameReply reply;
398
REQUEST(xXFixesGetCursorNameReq);
402
REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
403
VERIFY_CURSOR(pCursor, stuff->cursor, client, SecurityReadAccess);
405
str = NameForAtom (pCursor->name);
410
reply.type = X_Reply;
411
reply.length = (len + 3) >> 2;
412
reply.sequenceNumber = client->sequence;
413
reply.atom = pCursor->name;
418
swaps (&reply.sequenceNumber, n);
419
swapl (&reply.length, n);
420
swapl (&reply.atom, n);
421
swaps (&reply.nbytes, n);
423
WriteReplyToClient(client, sizeof(xXFixesGetCursorNameReply), &reply);
424
(void)WriteToClient(client, len, str);
426
return(client->noClientException);
430
SProcXFixesGetCursorName (ClientPtr client)
433
REQUEST(xXFixesSetCursorNameReq);
435
swaps (&stuff->length, n);
436
REQUEST_SIZE_MATCH(xXFixesGetCursorNameReq);
437
swapl (&stuff->cursor, n);
438
return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
442
ProcXFixesGetCursorImageAndName (ClientPtr client)
444
/* REQUEST(xXFixesGetCursorImageAndNameReq); */
445
xXFixesGetCursorImageAndNameReply *rep;
450
int nbytes, nbytesRound;
454
REQUEST_SIZE_MATCH(xXFixesGetCursorImageAndNameReq);
455
pCursor = CursorCurrent;
458
GetSpritePosition (&x, &y);
459
width = pCursor->bits->width;
460
height = pCursor->bits->height;
461
npixels = width * height;
462
name = pCursor->name ? NameForAtom (pCursor->name) : "";
463
nbytes = strlen (name);
464
nbytesRound = (nbytes + 3) & ~3;
465
rep = xalloc (sizeof (xXFixesGetCursorImageAndNameReply) +
466
npixels * sizeof (CARD32) + nbytesRound);
471
rep->sequenceNumber = client->sequence;
472
rep->length = npixels + (nbytesRound >> 2);
474
rep->height = height;
477
rep->xhot = pCursor->bits->xhot;
478
rep->yhot = pCursor->bits->yhot;
479
rep->cursorSerial = pCursor->serialNumber;
480
rep->cursorName = pCursor->name;
481
rep->nbytes = nbytes;
483
image = (CARD32 *) (rep + 1);
484
CopyCursorToImage (pCursor, image);
485
memcpy ((image + npixels), name, nbytes);
489
swaps (&rep->sequenceNumber, n);
490
swapl (&rep->length, n);
493
swaps (&rep->width, n);
494
swaps (&rep->height, n);
495
swaps (&rep->xhot, n);
496
swaps (&rep->yhot, n);
497
swapl (&rep->cursorSerial, n);
498
swapl (&rep->cursorName, n);
499
swaps (&rep->nbytes, n);
500
SwapLongs (image, npixels);
502
(void) WriteToClient(client, sizeof (xXFixesGetCursorImageAndNameReply) +
503
(npixels << 2) + nbytesRound, (char *) rep);
505
return client->noClientException;
509
SProcXFixesGetCursorImageAndName (ClientPtr client)
512
REQUEST(xXFixesGetCursorImageAndNameReq);
513
swaps (&stuff->length, n);
514
return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
518
* Find every cursor reference in the system, ask testCursor
519
* whether it should be replaced with a reference to pCursor.
522
typedef Bool (*TestCursorFunc) (CursorPtr pOld, pointer closure);
526
TestCursorFunc testCursor;
529
} ReplaceCursorLookupRec, *ReplaceCursorLookupPtr;
531
static const RESTYPE CursorRestypes[] = {
532
RT_WINDOW, RT_PASSIVEGRAB, RT_CURSOR
535
#define NUM_CURSOR_RESTYPES (sizeof (CursorRestypes) / sizeof (CursorRestypes[0]))
538
ReplaceCursorLookup (pointer value, XID id, pointer closure)
540
ReplaceCursorLookupPtr rcl = (ReplaceCursorLookupPtr) closure;
543
CursorPtr pCursor = 0, *pCursorRef = 0;
548
pWin = (WindowPtr) value;
551
pCursorRef = &pWin->optional->cursor;
552
pCursor = *pCursorRef;
556
pGrab = (GrabPtr) value;
557
pCursorRef = &pGrab->cursor;
558
pCursor = *pCursorRef;
562
pCursor = (CursorPtr) value;
566
if (pCursor && pCursor != rcl->pNew)
568
if ((*rcl->testCursor) (pCursor, rcl->closure))
571
/* either redirect reference or update resource database */
573
*pCursorRef = rcl->pNew;
575
ChangeResourceValue (id, RT_CURSOR, rcl->pNew);
576
FreeCursor (pCursor, cursor);
579
return FALSE; /* keep walking */
583
ReplaceCursor (CursorPtr pCursor,
584
TestCursorFunc testCursor,
589
ReplaceCursorLookupRec rcl;
592
* Cursors exist only in the resource database, windows and grabs.
593
* All of these are always pointed at by the resource database. Walk
594
* the whole thing looking for cursors
596
rcl.testCursor = testCursor;
598
rcl.closure = closure;
600
/* for each client */
601
for (clientIndex = 0; clientIndex < currentMaxClients; clientIndex++)
603
if (!clients[clientIndex])
605
for (resIndex = 0; resIndex < NUM_CURSOR_RESTYPES; resIndex++)
607
rcl.type = CursorRestypes[resIndex];
609
* This function walks the entire client resource database
611
LookupClientResourceComplex (clients[clientIndex],
617
/* this "knows" that WindowHasNewCursor doesn't depend on it's argument */
618
WindowHasNewCursor (WindowTable[0]);
622
TestForCursor (CursorPtr pCursor, pointer closure)
624
return (pCursor == (CursorPtr) closure);
628
ProcXFixesChangeCursor (ClientPtr client)
630
CursorPtr pSource, pDestination;
631
REQUEST(xXFixesChangeCursorReq);
633
REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
634
VERIFY_CURSOR (pSource, stuff->source, client, SecurityReadAccess);
635
VERIFY_CURSOR (pDestination, stuff->destination, client, SecurityWriteAccess);
637
ReplaceCursor (pSource, TestForCursor, (pointer) pDestination);
638
return (client->noClientException);
642
SProcXFixesChangeCursor (ClientPtr client)
645
REQUEST(xXFixesChangeCursorReq);
647
swaps (&stuff->length, n);
648
REQUEST_SIZE_MATCH(xXFixesChangeCursorReq);
649
swapl (&stuff->source, n);
650
swapl (&stuff->destination, n);
651
return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
655
TestForCursorName (CursorPtr pCursor, pointer closure)
657
return (pCursor->name == (Atom) closure);
661
ProcXFixesChangeCursorByName (ClientPtr client)
666
REQUEST(xXFixesChangeCursorByNameReq);
668
REQUEST_FIXED_SIZE(xXFixesChangeCursorByNameReq, stuff->nbytes);
669
VERIFY_CURSOR(pSource, stuff->source, client, SecurityReadAccess);
670
tchar = (char *) &stuff[1];
671
name = MakeAtom (tchar, stuff->nbytes, FALSE);
673
ReplaceCursor (pSource, TestForCursorName, (pointer) name);
674
return (client->noClientException);
678
SProcXFixesChangeCursorByName (ClientPtr client)
681
REQUEST(xXFixesChangeCursorByNameReq);
683
swaps (&stuff->length, n);
684
REQUEST_AT_LEAST_SIZE (xXFixesChangeCursorByNameReq);
685
swapl (&stuff->source, n);
686
swaps (&stuff->nbytes, n);
687
return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
691
CursorFreeClient (pointer data, XID id)
693
CursorEventPtr old = (CursorEventPtr) data;
694
CursorEventPtr *prev, e;
696
for (prev = &cursorEvents; (e = *prev); prev = &e->next)
709
CursorFreeWindow (pointer data, XID id)
711
WindowPtr pWindow = (WindowPtr) data;
712
CursorEventPtr e, next;
714
for (e = cursorEvents; e; e = next)
717
if (e->pWindow == pWindow)
719
FreeResource (e->clientResource, 0);
726
XFixesCursorInit (void)
730
if (CursorGeneration != serverGeneration)
732
CursorScreenPrivateIndex = AllocateScreenPrivateIndex ();
733
if (CursorScreenPrivateIndex < 0)
735
CursorGeneration = serverGeneration;
737
for (i = 0; i < screenInfo.numScreens; i++)
739
ScreenPtr pScreen = screenInfo.screens[i];
742
cs = (CursorScreenPtr) xalloc (sizeof (CursorScreenRec));
745
Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
746
Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
747
SetCursorScreen (pScreen, cs);
749
CursorClientType = CreateNewResourceType(CursorFreeClient);
750
CursorWindowType = CreateNewResourceType(CursorFreeWindow);
751
return CursorClientType && CursorWindowType;