cmsCmap.c revision 61b2299d
1/* $Xorg: cmsCmap.c,v 1.3 2000/08/17 19:45:09 cpqbld Exp $ */ 2 3/* 4 * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc. 5 * All Rights Reserved 6 * 7 * This file is a component of an X Window System-specific implementation 8 * of Xcms based on the TekColor Color Management System. Permission is 9 * hereby granted to use, copy, modify, sell, and otherwise distribute this 10 * software and its documentation for any purpose and without fee, provided 11 * that this copyright, permission, and disclaimer notice is reproduced in 12 * all copies of this software and in supporting documentation. TekColor 13 * is a trademark of Tektronix, Inc. 14 * 15 * Tektronix makes no representation about the suitability of this software 16 * for any purpose. It is provided "as is" and with all faults. 17 * 18 * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE, 19 * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 20 * PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY 21 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 22 * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF 23 * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 24 * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE. 25 * 26 * 27 * NAME 28 * XcmsCmap.c - Client Colormap Management Routines 29 * 30 * DESCRIPTION 31 * Routines that store additional information about 32 * colormaps being used by the X Client. 33 * 34 * 35 */ 36/* $XFree86$ */ 37 38#define NEED_EVENTS 39#define NEED_REPLIES 40#ifdef HAVE_CONFIG_H 41#include <config.h> 42#endif 43#include "Xlibint.h" 44#include "Xcmsint.h" 45#include "Xutil.h" 46#include "Cmap.h" 47#include "Cv.h" 48 49/* 50 * FORWARD DECLARATIONS 51 */ 52static void _XcmsFreeClientCmaps(Display *dpy); 53 54 55/************************************************************************ 56 * * 57 * PRIVATE INTERFACES * 58 * * 59 ************************************************************************/ 60 61/* 62 * NAME 63 * CmapRecForColormap 64 * 65 * SYNOPSIS 66 */ 67static XcmsCmapRec * 68CmapRecForColormap( 69 Display *dpy, 70 Colormap cmap) 71/* 72 * DESCRIPTION 73 * Find the corresponding XcmsCmapRec for cmap. In not found 74 * this routines attempts to create one. 75 * 76 * RETURNS 77 * Returns NULL if failed; otherwise the address to 78 * the corresponding XcmsCmapRec. 79 * 80 */ 81{ 82 XcmsCmapRec *pRec; 83 int nScrn; 84 int i, j; 85 XVisualInfo visualTemplate; /* Template of the visual we want */ 86 XVisualInfo *visualList; /* List for visuals that match */ 87 int nVisualsMatched; /* Number of visuals that match */ 88 Window tmpWindow; 89 Visual *vp; 90 unsigned long border = 0; 91 _XAsyncHandler async; 92 _XAsyncErrorState async_state; 93 94 for (pRec = (XcmsCmapRec *)dpy->cms.clientCmaps; pRec != NULL; 95 pRec = pRec->pNext) { 96 if (pRec->cmapID == cmap) { 97 return(pRec); 98 } 99 } 100 101 /* 102 * Can't find an XcmsCmapRec associated with cmap in our records. 103 * Let's try to see if its a default colormap 104 */ 105 nScrn = ScreenCount(dpy); 106 for (i = 0; i < nScrn; i++) { 107 if (cmap == DefaultColormap(dpy, i)) { 108 /* It is ... lets go ahead and store that info */ 109 if ((pRec = _XcmsAddCmapRec(dpy, cmap, RootWindow(dpy, i), 110 DefaultVisual(dpy, i))) == NULL) { 111 return((XcmsCmapRec *)NULL); 112 } 113 pRec->ccc = XcmsCreateCCC( 114 dpy, 115 i, /* screenNumber */ 116 DefaultVisual(dpy, i), 117 (XcmsColor *)NULL, /* clientWhitePt */ 118 (XcmsCompressionProc)NULL, /* gamutCompProc */ 119 (XPointer)NULL, /* gamutCompClientData */ 120 (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ 121 (XPointer)NULL /* whitePtAdjClientData */ 122 ); 123 return(pRec); 124 } 125 } 126 127 /* 128 * Nope, its not a default colormap, so it's probably a foreign color map 129 * of which we have no specific details. Let's go through the 130 * rigorous process of finding this colormap: 131 * for each screen 132 * for each screen's visual types 133 * create a window with cmap specified as the colormap 134 * if successful 135 * Add a CmapRec 136 * Create an XcmsCCC 137 * return the CmapRec 138 * else 139 * continue 140 */ 141 142 async_state.error_code = 0; /* don't care */ 143 async_state.major_opcode = X_CreateWindow; 144 async_state.minor_opcode = 0; 145 for (i = 0; i < nScrn; i++) { 146 visualTemplate.screen = i; 147 visualList = XGetVisualInfo(dpy, VisualScreenMask, &visualTemplate, 148 &nVisualsMatched); 149 if (visualList == NULL) { 150 continue; 151 } 152 153 /* 154 * Attempt to create a window with cmap 155 */ 156 j = 0; 157 do { 158 vp = (visualList+j)->visual; 159 LockDisplay(dpy); 160 { 161 register xCreateWindowReq *req; 162 163 GetReq(CreateWindow, req); 164 async_state.min_sequence_number = dpy->request; 165 async_state.max_sequence_number = dpy->request; 166 async_state.error_count = 0; 167 async.next = dpy->async_handlers; 168 async.handler = _XAsyncErrorHandler; 169 async.data = (XPointer)&async_state; 170 dpy->async_handlers = &async; 171 req->parent = RootWindow(dpy, i); 172 req->x = 0; 173 req->y = 0; 174 req->width = 1; 175 req->height = 1; 176 req->borderWidth = 0; 177 req->depth = (visualList+j)->depth; 178 req->class = CopyFromParent; 179 req->visual = vp->visualid; 180 tmpWindow = req->wid = XAllocID(dpy); 181 req->mask = CWBorderPixel | CWColormap; 182 req->length += 2; 183 Data32 (dpy, (long *) &border, 4); 184 Data32 (dpy, (long *) &cmap, 4); 185 } 186 { 187 xGetInputFocusReply rep; 188 register xReq *req; 189 190 GetEmptyReq(GetInputFocus, req); 191 (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); 192 } 193 DeqAsyncHandler(dpy, &async); 194 UnlockDisplay(dpy); 195 SyncHandle(); 196 } while (async_state.error_count > 0 && ++j < nVisualsMatched); 197 198 Xfree((char *)visualList); 199 200 /* 201 * if successful 202 */ 203 if (j < nVisualsMatched) { 204 if ((pRec = _XcmsAddCmapRec(dpy, cmap, tmpWindow, vp)) == NULL) 205 return((XcmsCmapRec *)NULL); 206 pRec->ccc = XcmsCreateCCC( 207 dpy, 208 i, /* screenNumber */ 209 vp, 210 (XcmsColor *)NULL, /* clientWhitePt */ 211 (XcmsCompressionProc)NULL, /* gamutCompProc */ 212 (XPointer)NULL, /* gamutCompClientData */ 213 (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ 214 (XPointer)NULL /* whitePtAdjClientData */ 215 ); 216 XDestroyWindow(dpy, tmpWindow); 217 return(pRec); 218 } 219 } 220 221 return(NULL); 222} 223 224 225 226/************************************************************************ 227 * * 228 * API PRIVATE INTERFACES * 229 * * 230 ************************************************************************/ 231 232/* 233 * NAME 234 * _XcmsAddCmapRec 235 * 236 * SYNOPSIS 237 */ 238XcmsCmapRec * 239_XcmsAddCmapRec( 240 Display *dpy, 241 Colormap cmap, 242 Window windowID, 243 Visual *visual) 244/* 245 * DESCRIPTION 246 * Create an XcmsCmapRec for the specified cmap, windowID, 247 * and visual, then adds it to its list of CmapRec's. 248 * 249 * RETURNS 250 * Returns NULL if failed; otherwise the address to 251 * the added XcmsCmapRec. 252 * 253 */ 254{ 255 XcmsCmapRec *pNew; 256 257 if ((pNew = (XcmsCmapRec *) Xcalloc(1, (unsigned) sizeof(XcmsCmapRec))) 258 == NULL) { 259 return((XcmsCmapRec *)NULL); 260 } 261 262 pNew->cmapID = cmap; 263 pNew->dpy = dpy; 264 pNew->windowID = windowID; 265 pNew->visual = visual; 266 pNew->pNext = (XcmsCmapRec *)dpy->cms.clientCmaps; 267 dpy->cms.clientCmaps = (XPointer)pNew; 268 dpy->free_funcs->clientCmaps = _XcmsFreeClientCmaps; 269 270 /* 271 * Note, we don't create the XcmsCCC for pNew->ccc here because 272 * it may require the use of XGetWindowAttributes (a round trip request) 273 * to determine the screen. 274 */ 275 return(pNew); 276} 277 278 279/* 280 * NAME 281 * _XcmsCopyCmapRecAndFree 282 * 283 * SYNOPSIS 284 */ 285XcmsCmapRec * 286_XcmsCopyCmapRecAndFree( 287 Display *dpy, 288 Colormap src_cmap, 289 Colormap copy_cmap) 290/* 291 * DESCRIPTION 292 * Augments Xlib's XCopyColormapAndFree() to copy 293 * XcmsCmapRecs. 294 * 295 * RETURNS 296 * Returns NULL if failed; otherwise the address to 297 * the copy XcmsCmapRec. 298 * 299 */ 300{ 301 XcmsCmapRec *pRec_src; 302 XcmsCmapRec *pRec_copy; 303 304 if ((pRec_src = CmapRecForColormap(dpy, src_cmap)) != NULL) { 305 pRec_copy =_XcmsAddCmapRec(dpy, copy_cmap, pRec_src->windowID, 306 pRec_src->visual); 307 if (pRec_copy != NULL && pRec_src->ccc) { 308 pRec_copy->ccc = (XcmsCCC)Xcalloc(1, (unsigned) sizeof(XcmsCCCRec)); 309 memcpy((char *)pRec_copy->ccc, (char *)pRec_src->ccc, 310 sizeof(XcmsCCCRec)); 311 } 312 return(pRec_copy); 313 } 314 return((XcmsCmapRec *)NULL); 315} 316 317 318/* 319 * NAME 320 * _XcmsDeleteCmapRec 321 * 322 * SYNOPSIS 323 */ 324void 325_XcmsDeleteCmapRec( 326 Display *dpy, 327 Colormap cmap) 328/* 329 * DESCRIPTION 330 * Removes and frees the specified XcmsCmapRec structure 331 * from the linked list of structures. 332 * 333 * RETURNS 334 * void 335 * 336 */ 337{ 338 XcmsCmapRec **pPrevPtr; 339 XcmsCmapRec *pRec; 340 int scr; 341 342 /* If it is the default cmap for a screen, do not delete it, 343 * because the server will not actually free it */ 344 for (scr = ScreenCount(dpy); --scr >= 0; ) { 345 if (cmap == DefaultColormap(dpy, scr)) 346 return; 347 } 348 349 /* search for it in the list */ 350 pPrevPtr = (XcmsCmapRec **)&dpy->cms.clientCmaps; 351 while ((pRec = *pPrevPtr) && (pRec->cmapID != cmap)) { 352 pPrevPtr = &pRec->pNext; 353 } 354 355 if (pRec) { 356 if (pRec->ccc) { 357 XcmsFreeCCC(pRec->ccc); 358 } 359 *pPrevPtr = pRec->pNext; 360 Xfree((char *)pRec); 361 } 362} 363 364 365/* 366 * NAME 367 * _XcmsFreeClientCmaps 368 * 369 * SYNOPSIS 370 */ 371static void 372_XcmsFreeClientCmaps( 373 Display *dpy) 374/* 375 * DESCRIPTION 376 * Frees all XcmsCmapRec structures in the linked list 377 * and sets dpy->cms.clientCmaps to NULL. 378 * 379 * RETURNS 380 * void 381 * 382 */ 383{ 384 XcmsCmapRec *pRecNext, *pRecFree; 385 386 pRecNext = (XcmsCmapRec *)dpy->cms.clientCmaps; 387 while (pRecNext != NULL) { 388 pRecFree = pRecNext; 389 pRecNext = pRecNext->pNext; 390 if (pRecFree->ccc) { 391 /* Free the XcmsCCC structure */ 392 XcmsFreeCCC(pRecFree->ccc); 393 } 394 /* Now free the XcmsCmapRec structure */ 395 Xfree((char *)pRecFree); 396 } 397 dpy->cms.clientCmaps = (XPointer)NULL; 398} 399 400 401 402/************************************************************************ 403 * * 404 * PUBLIC INTERFACES * 405 * * 406 ************************************************************************/ 407 408/* 409 * NAME 410 * XcmsCCCOfColormap 411 * 412 * SYNOPSIS 413 */ 414XcmsCCC 415XcmsCCCOfColormap( 416 Display *dpy, 417 Colormap cmap) 418/* 419 * DESCRIPTION 420 * Finds the XcmsCCC associated with the specified colormap. 421 * 422 * RETURNS 423 * Returns NULL if failed; otherwise the address to 424 * the associated XcmsCCC structure. 425 * 426 */ 427{ 428 XWindowAttributes windowAttr; 429 XcmsCmapRec *pRec; 430 int nScrn = ScreenCount(dpy); 431 int i; 432 433 if ((pRec = CmapRecForColormap(dpy, cmap)) != NULL) { 434 if (pRec->ccc) { 435 /* XcmsCmapRec already has a XcmsCCC */ 436 return(pRec->ccc); 437 } 438 439 /* 440 * The XcmsCmapRec does not have a XcmsCCC yet, so let's create 441 * one. But first, we need to know the screen associated with 442 * cmap, so use XGetWindowAttributes() to extract that 443 * information. Unless, of course there is only one screen!! 444 */ 445 if (nScrn == 1) { 446 /* Assume screenNumber == 0 */ 447 return(pRec->ccc = XcmsCreateCCC( 448 dpy, 449 0, /* screenNumber */ 450 pRec->visual, 451 (XcmsColor *)NULL, /* clientWhitePt */ 452 (XcmsCompressionProc)NULL, /* gamutCompProc */ 453 (XPointer)NULL, /* gamutCompClientData */ 454 (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ 455 (XPointer)NULL /* whitePtAdjClientData */ 456 )); 457 } else { 458 if (XGetWindowAttributes(dpy, pRec->windowID, &windowAttr)) { 459 for (i = 0; i < nScrn; i++) { 460 if (ScreenOfDisplay(dpy, i) == windowAttr.screen) { 461 return(pRec->ccc = XcmsCreateCCC( 462 dpy, 463 i, /* screenNumber */ 464 pRec->visual, 465 (XcmsColor *)NULL, /* clientWhitePt */ 466 (XcmsCompressionProc)NULL, /* gamutCompProc */ 467 (XPointer)NULL, /* gamutCompClientData */ 468 (XcmsWhiteAdjustProc)NULL, /* whitePtAdjProc */ 469 (XPointer)NULL /* whitePtAdjClientData */ 470 )); 471 } 472 } 473 } 474 } 475 } 476 477 /* 478 * No such cmap 479 */ 480 return(NULL); 481} 482 483XcmsCCC XcmsSetCCCOfColormap( 484 Display *dpy, 485 Colormap cmap, 486 XcmsCCC ccc) 487{ 488 XcmsCCC prev_ccc = NULL; 489 XcmsCmapRec *pRec; 490 491 pRec = CmapRecForColormap(dpy, cmap); 492 if (pRec) { 493 prev_ccc = pRec->ccc; 494 pRec->ccc = ccc; 495 } 496 return prev_ccc; 497} 498