cursor.c revision 05b261ec
1/*********************************************************** 2 3Copyright 1987, 1998 The Open Group 4 5Permission to use, copy, modify, distribute, and sell this software and its 6documentation for any purpose is hereby granted without fee, provided that 7the above copyright notice appear in all copies and that both that 8copyright notice and this permission notice appear in supporting 9documentation. 10 11The above copyright notice and this permission notice shall be included in 12all copies or substantial portions of the Software. 13 14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 21Except as contained in this notice, the name of The Open Group shall not be 22used in advertising or otherwise to promote the sale, use or other dealings 23in this Software without prior written authorization from The Open Group. 24 25 26Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 27 28 All Rights Reserved 29 30Permission to use, copy, modify, and distribute this software and its 31documentation for any purpose and without fee is hereby granted, 32provided that the above copyright notice appear in all copies and that 33both that copyright notice and this permission notice appear in 34supporting documentation, and that the name of Digital not be 35used in advertising or publicity pertaining to distribution of the 36software without specific, written prior permission. 37 38DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 39ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 40DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 41ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 42WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 43ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 44SOFTWARE. 45 46******************************************************************/ 47 48 49 50#ifdef HAVE_DIX_CONFIG_H 51#include <dix-config.h> 52#endif 53 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" 62 63typedef struct _GlyphShare { 64 FontPtr font; 65 unsigned short sourceChar; 66 unsigned short maskChar; 67 CursorBitsPtr bits; 68 struct _GlyphShare *next; 69} GlyphShare, *GlyphSharePtr; 70 71static GlyphSharePtr sharedGlyphs = (GlyphSharePtr)NULL; 72 73#ifdef XFIXES 74static CARD32 cursorSerial; 75#endif 76 77static void 78FreeCursorBits(CursorBitsPtr bits) 79{ 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) 88 { 89 GlyphSharePtr *prev, this; 90 91 for (prev = &sharedGlyphs; 92 (this = *prev) && (this->bits != bits); 93 prev = &this->next) 94 ; 95 if (this) 96 { 97 *prev = this->next; 98 CloseFont(this->font, (Font)0); 99 xfree(this); 100 } 101 xfree(bits); 102 } 103} 104 105/** 106 * To be called indirectly by DeleteResource; must use exactly two args. 107 * 108 * \param value must conform to DeleteType 109 */ 110_X_EXPORT int 111FreeCursor(pointer value, XID cid) 112{ 113 int nscr; 114 CursorPtr pCurs = (CursorPtr)value; 115 116 ScreenPtr pscr; 117 118 if ( --pCurs->refcnt > 0) 119 return(Success); 120 121 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) 122 { 123 pscr = screenInfo.screens[nscr]; 124 (void)( *pscr->UnrealizeCursor)( pscr, pCurs); 125 } 126 FreeCursorBits(pCurs->bits); 127 xfree( pCurs); 128 return(Success); 129} 130 131 132/* 133 * We check for empty cursors so that we won't have to display them 134 */ 135static void 136CheckForEmptyMask(CursorBitsPtr bits) 137{ 138 unsigned char *msk = bits->mask; 139 int n = BitmapBytePad(bits->width) * bits->height; 140 141 bits->emptyMask = FALSE; 142 while(n--) 143 if(*(msk++) != 0) return; 144#ifdef ARGB_CURSOR 145 if (bits->argb) 146 { 147 CARD32 *argb = bits->argb; 148 int n = bits->width * bits->height; 149 while (n--) 150 if (*argb++ & 0xff000000) return; 151 } 152#endif 153 bits->emptyMask = TRUE; 154} 155 156/** 157 * does nothing about the resource table, just creates the data structure. 158 * does not copy the src and mask bits 159 * 160 * \param psrcbits server-defined padding 161 * \param pmaskbits server-defined padding 162 * \param argb no padding 163 */ 164CursorPtr 165AllocCursorARGB(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) 169{ 170 CursorBitsPtr bits; 171 CursorPtr pCurs; 172 int nscr; 173 ScreenPtr pscr; 174 175 pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); 176 if (!pCurs) 177 { 178 xfree(psrcbits); 179 xfree(pmaskbits); 180 return (CursorPtr)NULL; 181 } 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); 194 195 pCurs->bits = bits; 196 pCurs->refcnt = 1; 197#ifdef XFIXES 198 pCurs->serialNumber = ++cursorSerial; 199 pCurs->name = None; 200#endif 201 202 pCurs->foreRed = foreRed; 203 pCurs->foreGreen = foreGreen; 204 pCurs->foreBlue = foreBlue; 205 206 pCurs->backRed = backRed; 207 pCurs->backGreen = backGreen; 208 pCurs->backBlue = backBlue; 209 210 /* 211 * realize the cursor for every screen 212 */ 213 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) 214 { 215 pscr = screenInfo.screens[nscr]; 216 if (!( *pscr->RealizeCursor)( pscr, pCurs)) 217 { 218 while (--nscr >= 0) 219 { 220 pscr = screenInfo.screens[nscr]; 221 ( *pscr->UnrealizeCursor)( pscr, pCurs); 222 } 223 FreeCursorBits(bits); 224 xfree(pCurs); 225 return (CursorPtr)NULL; 226 } 227 } 228 return pCurs; 229} 230 231/** 232 * 233 * \param psrcbits server-defined padding 234 * \param pmaskbits server-defined padding 235 */ 236CursorPtr 237AllocCursor(unsigned char *psrcbits, unsigned char *pmaskbits, 238 CursorMetricPtr cm, 239 unsigned foreRed, unsigned foreGreen, unsigned foreBlue, 240 unsigned backRed, unsigned backGreen, unsigned backBlue) 241{ 242 return AllocCursorARGB (psrcbits, pmaskbits, (CARD32 *) 0, cm, 243 foreRed, foreGreen, foreBlue, 244 backRed, backGreen, backBlue); 245} 246 247int 248AllocGlyphCursor(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) 252{ 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; 263 264 sourcefont = (FontPtr) SecurityLookupIDByType(client, source, RT_FONT, 265 DixReadAccess); 266 maskfont = (FontPtr) SecurityLookupIDByType(client, mask, RT_FONT, 267 DixReadAccess); 268 269 if (!sourcefont) 270 { 271 client->errorValue = source; 272 return(BadFont); 273 } 274 if (!maskfont && (mask != None)) 275 { 276 client->errorValue = mask; 277 return(BadFont); 278 } 279 if (sourcefont != maskfont) 280 pShare = (GlyphSharePtr)NULL; 281 else 282 { 283 for (pShare = sharedGlyphs; 284 pShare && 285 ((pShare->font != sourcefont) || 286 (pShare->sourceChar != sourceChar) || 287 (pShare->maskChar != maskChar)); 288 pShare = pShare->next) 289 ; 290 } 291 if (pShare) 292 { 293 pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); 294 if (!pCurs) 295 return BadAlloc; 296 bits = pShare->bits; 297 bits->refcnt++; 298 } 299 else 300 { 301 if (!CursorMetricsFromGlyph(sourcefont, sourceChar, &cm)) 302 { 303 client->errorValue = sourceChar; 304 return BadValue; 305 } 306 if (!maskfont) 307 { 308 long n; 309 unsigned char *mskptr; 310 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; 317 } 318 else 319 { 320 if (!CursorMetricsFromGlyph(maskfont, maskChar, &cm)) 321 { 322 client->errorValue = maskChar; 323 return BadValue; 324 } 325 if ((res = ServerBitsFromGlyph(maskfont, maskChar, &cm, &mskbits)) != 0) 326 return res; 327 } 328 if ((res = ServerBitsFromGlyph(sourcefont, sourceChar, &cm, &srcbits)) != 0) 329 { 330 xfree(mskbits); 331 return res; 332 } 333 if (sourcefont != maskfont) 334 { 335 pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); 336 if (pCurs) 337 bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec)); 338 else 339 bits = (CursorBitsPtr)NULL; 340 } 341 else 342 { 343 pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); 344 if (pCurs) 345 bits = (CursorBitsPtr)xalloc(sizeof(CursorBits)); 346 else 347 bits = (CursorBitsPtr)NULL; 348 } 349 if (!bits) 350 { 351 xfree(pCurs); 352 xfree(mskbits); 353 xfree(srcbits); 354 return BadAlloc; 355 } 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 368 { 369 bits->refcnt = 1; 370 pShare = (GlyphSharePtr)xalloc(sizeof(GlyphShare)); 371 if (!pShare) 372 { 373 FreeCursorBits(bits); 374 return BadAlloc; 375 } 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; 383 } 384 } 385 CheckForEmptyMask(bits); 386 pCurs->bits = bits; 387 pCurs->refcnt = 1; 388#ifdef XFIXES 389 pCurs->serialNumber = ++cursorSerial; 390 pCurs->name = None; 391#endif 392 393 pCurs->foreRed = foreRed; 394 pCurs->foreGreen = foreGreen; 395 pCurs->foreBlue = foreBlue; 396 397 pCurs->backRed = backRed; 398 pCurs->backGreen = backGreen; 399 pCurs->backBlue = backBlue; 400 401 /* 402 * realize the cursor for every screen 403 */ 404 for (nscr = 0; nscr < screenInfo.numScreens; nscr++) 405 { 406 pscr = screenInfo.screens[nscr]; 407 if (!( *pscr->RealizeCursor)( pscr, pCurs)) 408 { 409 while (--nscr >= 0) 410 { 411 pscr = screenInfo.screens[nscr]; 412 ( *pscr->UnrealizeCursor)( pscr, pCurs); 413 } 414 FreeCursorBits(pCurs->bits); 415 xfree(pCurs); 416 return BadAlloc; 417 } 418 } 419 *ppCurs = pCurs; 420 return Success; 421} 422 423/** CreateRootCursor 424 * 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 *************************************************************/ 431 432CursorPtr 433CreateRootCursor(char *unused1, unsigned int unused2) 434{ 435 CursorPtr curs; 436#ifdef NULL_ROOT_CURSOR 437 CursorMetricRec cm; 438#else 439 FontPtr cursorfont; 440 int err; 441 XID fontID; 442#endif 443 444#ifdef NULL_ROOT_CURSOR 445 cm.width = 0; 446 cm.height = 0; 447 cm.xhot = 0; 448 cm.yhot = 0; 449 450 curs = AllocCursor(NULL, NULL, &cm, 0, 0, 0, 0, 0, 0); 451 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; 460 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 468 469 if (!AddResource(FakeClientID(0), RT_CURSOR, (pointer)curs)) 470 return NullCursor; 471 472 return curs; 473} 474