First import
[xorg_rtime.git] / xorg-server-1.4 / dix / cursor.c
blobd903124c49a2f6790dbdd975f22b925e99c50c27
1 /***********************************************************
3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
28 All Rights Reserved
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44 SOFTWARE.
46 ******************************************************************/
50 #ifdef HAVE_DIX_CONFIG_H
51 #include <dix-config.h>
52 #endif
54 #include <X11/X.h>
55 #include <X11/Xmd.h>
56 #include "servermd.h"
57 #include "scrnintstr.h"
58 #include "dixstruct.h"
59 #include "cursorstr.h"
60 #include "dixfontstr.h"
61 #include "opaque.h"
63 typedef struct _GlyphShare {
64 FontPtr font;
65 unsigned short sourceChar;
66 unsigned short maskChar;
67 CursorBitsPtr bits;
68 struct _GlyphShare *next;
69 } GlyphShare, *GlyphSharePtr;
71 static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL;
73 #ifdef XFIXES
74 static CARD32 cursorSerial;
75 #endif
77 static void
78 FreeCursorBits(CursorBitsPtr bits)
80 if (--bits->refcnt > 0)
81 return;
82 xfree(bits->source);
83 xfree(bits->mask);
84 #ifdef ARGB_CURSOR
85 xfree(bits->argb);
86 #endif
87 if (bits->refcnt == 0)
89 GlyphSharePtr *prev, this;
91 for (prev = &sharedGlyphs;
92 (this = *prev) && (this->bits != bits);
93 prev = &this->next)
95 if (this)
97 *prev = this->next;
98 CloseFont(this->font, (Font)0);
99 xfree(this);
101 xfree(bits);
106 * To be called indirectly by DeleteResource; must use exactly two args.
108 * \param value must conform to DeleteType
110 _X_EXPORT int
111 FreeCursor(pointer value, XID cid)
113 int nscr;
114 CursorPtr pCurs = (CursorPtr)value;
116 ScreenPtr pscr;
118 if ( --pCurs->refcnt > 0)
119 return(Success);
121 for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
123 pscr = screenInfo.screens[nscr];
124 (void)( *pscr->UnrealizeCursor)( pscr, pCurs);
126 FreeCursorBits(pCurs->bits);
127 xfree( pCurs);
128 return(Success);
133 * We check for empty cursors so that we won't have to display them
135 static void
136 CheckForEmptyMask(CursorBitsPtr bits)
138 unsigned char *msk = bits->mask;
139 int n = BitmapBytePad(bits->width) * bits->height;
141 bits->emptyMask = FALSE;
142 while(n--)
143 if(*(msk++) != 0) return;
144 #ifdef ARGB_CURSOR
145 if (bits->argb)
147 CARD32 *argb = bits->argb;
148 int n = bits->width * bits->height;
149 while (n--)
150 if (*argb++ & 0xff000000) return;
152 #endif
153 bits->emptyMask = TRUE;
157 * does nothing about the resource table, just creates the data structure.
158 * does not copy the src and mask bits
160 * \param psrcbits server-defined padding
161 * \param pmaskbits server-defined padding
162 * \param argb no padding
164 CursorPtr
165 AllocCursorARGB(unsigned char *psrcbits, unsigned char *pmaskbits, CARD32 *argb,
166 CursorMetricPtr cm,
167 unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
168 unsigned backRed, unsigned backGreen, unsigned backBlue)
170 CursorBitsPtr bits;
171 CursorPtr pCurs;
172 int nscr;
173 ScreenPtr pscr;
175 pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
176 if (!pCurs)
178 xfree(psrcbits);
179 xfree(pmaskbits);
180 return (CursorPtr)NULL;
182 bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
183 bits->source = psrcbits;
184 bits->mask = pmaskbits;
185 #ifdef ARGB_CURSOR
186 bits->argb = argb;
187 #endif
188 bits->width = cm->width;
189 bits->height = cm->height;
190 bits->xhot = cm->xhot;
191 bits->yhot = cm->yhot;
192 bits->refcnt = -1;
193 CheckForEmptyMask(bits);
195 pCurs->bits = bits;
196 pCurs->refcnt = 1;
197 #ifdef XFIXES
198 pCurs->serialNumber = ++cursorSerial;
199 pCurs->name = None;
200 #endif
202 pCurs->foreRed = foreRed;
203 pCurs->foreGreen = foreGreen;
204 pCurs->foreBlue = foreBlue;
206 pCurs->backRed = backRed;
207 pCurs->backGreen = backGreen;
208 pCurs->backBlue = backBlue;
211 * realize the cursor for every screen
213 for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
215 pscr = screenInfo.screens[nscr];
216 if (!( *pscr->RealizeCursor)( pscr, pCurs))
218 while (--nscr >= 0)
220 pscr = screenInfo.screens[nscr];
221 ( *pscr->UnrealizeCursor)( pscr, pCurs);
223 FreeCursorBits(bits);
224 xfree(pCurs);
225 return (CursorPtr)NULL;
228 return pCurs;
233 * \param psrcbits server-defined padding
234 * \param pmaskbits server-defined padding
236 CursorPtr
237 AllocCursor(unsigned char *psrcbits, unsigned char *pmaskbits,
238 CursorMetricPtr cm,
239 unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
240 unsigned backRed, unsigned backGreen, unsigned backBlue)
242 return AllocCursorARGB (psrcbits, pmaskbits, (CARD32 *) 0, cm,
243 foreRed, foreGreen, foreBlue,
244 backRed, backGreen, backBlue);
248 AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar,
249 unsigned foreRed, unsigned foreGreen, unsigned foreBlue,
250 unsigned backRed, unsigned backGreen, unsigned backBlue,
251 CursorPtr *ppCurs, ClientPtr client)
253 FontPtr sourcefont, maskfont;
254 unsigned char *srcbits;
255 unsigned char *mskbits;
256 CursorMetricRec cm;
257 int res;
258 CursorBitsPtr bits;
259 CursorPtr pCurs;
260 int nscr;
261 ScreenPtr pscr;
262 GlyphSharePtr pShare;
264 sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT,
265 DixReadAccess);
266 maskfont = (FontPtr) SecurityLookupIDByType(client, mask, RT_FONT,
267 DixReadAccess);
269 if (!sourcefont)
271 client->errorValue = source;
272 return(BadFont);
274 if (!maskfont && (mask != None))
276 client->errorValue = mask;
277 return(BadFont);
279 if (sourcefont != maskfont)
280 pShare = (GlyphSharePtr)NULL;
281 else
283 for (pShare = sharedGlyphs;
284 pShare &&
285 ((pShare->font != sourcefont) ||
286 (pShare->sourceChar != sourceChar) ||
287 (pShare->maskChar != maskChar));
288 pShare = pShare->next)
291 if (pShare)
293 pCurs = (CursorPtr)xalloc(sizeof(CursorRec));
294 if (!pCurs)
295 return BadAlloc;
296 bits = pShare->bits;
297 bits->refcnt++;
299 else
301 if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm))
303 client->errorValue = sourceChar;
304 return BadValue;
306 if (!maskfont)
308 long n;
309 unsigned char *mskptr;
311 n = BitmapBytePad(cm.width)*(long)cm.height;
312 mskptr = mskbits = (unsigned char *)xalloc(n);
313 if (!mskptr)
314 return BadAlloc;
315 while (--n >= 0)
316 *mskptr++ = ~0;
318 else
320 if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm))
322 client->errorValue = maskChar;
323 return BadValue;
325 if ((res = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)) != 0)
326 return res;
328 if ((res = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits)) != 0)
330 xfree(mskbits);
331 return res;
333 if (sourcefont != maskfont)
335 pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits));
336 if (pCurs)
337 bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec));
338 else
339 bits = (CursorBitsPtr)NULL;
341 else
343 pCurs = (CursorPtr)xalloc(sizeof(CursorRec));
344 if (pCurs)
345 bits = (CursorBitsPtr)xalloc(sizeof(CursorBits));
346 else
347 bits = (CursorBitsPtr)NULL;
349 if (!bits)
351 xfree(pCurs);
352 xfree(mskbits);
353 xfree(srcbits);
354 return BadAlloc;
356 bits->source = srcbits;
357 bits->mask = mskbits;
358 #ifdef ARGB_CURSOR
359 bits->argb = 0;
360 #endif
361 bits->width = cm.width;
362 bits->height = cm.height;
363 bits->xhot = cm.xhot;
364 bits->yhot = cm.yhot;
365 if (sourcefont != maskfont)
366 bits->refcnt = -1;
367 else
369 bits->refcnt = 1;
370 pShare = (GlyphSharePtr)xalloc(sizeof(GlyphShare));
371 if (!pShare)
373 FreeCursorBits(bits);
374 return BadAlloc;
376 pShare->font = sourcefont;
377 sourcefont->refcnt++;
378 pShare->sourceChar = sourceChar;
379 pShare->maskChar = maskChar;
380 pShare->bits = bits;
381 pShare->next = sharedGlyphs;
382 sharedGlyphs = pShare;
385 CheckForEmptyMask(bits);
386 pCurs->bits = bits;
387 pCurs->refcnt = 1;
388 #ifdef XFIXES
389 pCurs->serialNumber = ++cursorSerial;
390 pCurs->name = None;
391 #endif
393 pCurs->foreRed = foreRed;
394 pCurs->foreGreen = foreGreen;
395 pCurs->foreBlue = foreBlue;
397 pCurs->backRed = backRed;
398 pCurs->backGreen = backGreen;
399 pCurs->backBlue = backBlue;
402 * realize the cursor for every screen
404 for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
406 pscr = screenInfo.screens[nscr];
407 if (!( *pscr->RealizeCursor)( pscr, pCurs))
409 while (--nscr >= 0)
411 pscr = screenInfo.screens[nscr];
412 ( *pscr->UnrealizeCursor)( pscr, pCurs);
414 FreeCursorBits(pCurs->bits);
415 xfree(pCurs);
416 return BadAlloc;
419 *ppCurs = pCurs;
420 return Success;
423 /** CreateRootCursor
425 * look up the name of a font
426 * open the font
427 * add the font to the resource table
428 * make a cursor from the glyphs
429 * add the cursor to the resource table
430 *************************************************************/
432 CursorPtr
433 CreateRootCursor(char *unused1, unsigned int unused2)
435 CursorPtr curs;
436 #ifdef NULL_ROOT_CURSOR
437 CursorMetricRec cm;
438 #else
439 FontPtr cursorfont;
440 int err;
441 XID fontID;
442 #endif
444 #ifdef NULL_ROOT_CURSOR
445 cm.width = 0;
446 cm.height = 0;
447 cm.xhot = 0;
448 cm.yhot = 0;
450 curs = AllocCursor(NULL, NULL, &cm, 0, 0, 0, 0, 0, 0);
452 if (curs == NullCursor)
453 return NullCursor;
454 #else
455 fontID = FakeClientID(0);
456 err = OpenFont(serverClient, fontID, FontLoadAll | FontOpenSync,
457 (unsigned)strlen(defaultCursorFont), defaultCursorFont);
458 if (err != Success)
459 return NullCursor;
461 cursorfont = (FontPtr)LookupIDByType(fontID, RT_FONT);
462 if (!cursorfont)
463 return NullCursor;
464 if (AllocGlyphCursor(fontID, 0, fontID, 1,
465 0, 0, 0, ~0, ~0, ~0, &curs, serverClient) != Success)
466 return NullCursor;
467 #endif
469 if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs))
470 return NullCursor;
472 return curs;