Color.c (15034B)
1 /* 2 3 Copyright 1993 by Davor Matic 4 5 Permission to use, copy, modify, distribute, and sell this software 6 and its documentation for any purpose is hereby granted without fee, 7 provided that the above copyright notice appear in all copies and that 8 both that copyright notice and this permission notice appear in 9 supporting documentation. Davor Matic makes no representations about 10 the suitability of this software for any purpose. It is provided "as 11 is" without express or implied warranty. 12 13 */ 14 15 #ifdef HAVE_XNEST_CONFIG_H 16 #include <xnest-config.h> 17 #endif 18 19 #include <X11/X.h> 20 #include <X11/Xproto.h> 21 #include "scrnintstr.h" 22 #include "window.h" 23 #include "windowstr.h" 24 #include "colormapst.h" 25 #include "resource.h" 26 27 #include "Xnest.h" 28 29 #include "Display.h" 30 #include "Screen.h" 31 #include "Color.h" 32 #include "Visual.h" 33 #include "XNWindow.h" 34 #include "Args.h" 35 36 DevPrivateKeyRec xnestColormapPrivateKeyRec; 37 38 static DevPrivateKeyRec cmapScrPrivateKeyRec; 39 40 #define cmapScrPrivateKey (&cmapScrPrivateKeyRec) 41 42 #define GetInstalledColormap(s) ((ColormapPtr) dixLookupPrivate(&(s)->devPrivates, cmapScrPrivateKey)) 43 #define SetInstalledColormap(s,c) (dixSetPrivate(&(s)->devPrivates, cmapScrPrivateKey, c)) 44 45 Bool 46 xnestCreateColormap(ColormapPtr pCmap) 47 { 48 VisualPtr pVisual; 49 XColor *colors; 50 int i, ncolors; 51 Pixel red, green, blue; 52 Pixel redInc, greenInc, blueInc; 53 54 pVisual = pCmap->pVisual; 55 ncolors = pVisual->ColormapEntries; 56 57 xnestColormapPriv(pCmap)->colormap = 58 XCreateColormap(xnestDisplay, 59 xnestDefaultWindows[pCmap->pScreen->myNum], 60 xnestVisual(pVisual), 61 (pVisual->class & DynamicClass) ? AllocAll : AllocNone); 62 63 switch (pVisual->class) { 64 case StaticGray: /* read only */ 65 colors = xallocarray(ncolors, sizeof(XColor)); 66 for (i = 0; i < ncolors; i++) 67 colors[i].pixel = i; 68 XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); 69 for (i = 0; i < ncolors; i++) { 70 pCmap->red[i].co.local.red = colors[i].red; 71 pCmap->red[i].co.local.green = colors[i].red; 72 pCmap->red[i].co.local.blue = colors[i].red; 73 } 74 free(colors); 75 break; 76 77 case StaticColor: /* read only */ 78 colors = xallocarray(ncolors, sizeof(XColor)); 79 for (i = 0; i < ncolors; i++) 80 colors[i].pixel = i; 81 XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); 82 for (i = 0; i < ncolors; i++) { 83 pCmap->red[i].co.local.red = colors[i].red; 84 pCmap->red[i].co.local.green = colors[i].green; 85 pCmap->red[i].co.local.blue = colors[i].blue; 86 } 87 free(colors); 88 break; 89 90 case TrueColor: /* read only */ 91 colors = xallocarray(ncolors, sizeof(XColor)); 92 red = green = blue = 0L; 93 redInc = lowbit(pVisual->redMask); 94 greenInc = lowbit(pVisual->greenMask); 95 blueInc = lowbit(pVisual->blueMask); 96 for (i = 0; i < ncolors; i++) { 97 colors[i].pixel = red | green | blue; 98 red += redInc; 99 if (red > pVisual->redMask) 100 red = 0L; 101 green += greenInc; 102 if (green > pVisual->greenMask) 103 green = 0L; 104 blue += blueInc; 105 if (blue > pVisual->blueMask) 106 blue = 0L; 107 } 108 XQueryColors(xnestDisplay, xnestColormap(pCmap), colors, ncolors); 109 for (i = 0; i < ncolors; i++) { 110 pCmap->red[i].co.local.red = colors[i].red; 111 pCmap->green[i].co.local.green = colors[i].green; 112 pCmap->blue[i].co.local.blue = colors[i].blue; 113 } 114 free(colors); 115 break; 116 117 case GrayScale: /* read and write */ 118 break; 119 120 case PseudoColor: /* read and write */ 121 break; 122 123 case DirectColor: /* read and write */ 124 break; 125 } 126 127 return True; 128 } 129 130 void 131 xnestDestroyColormap(ColormapPtr pCmap) 132 { 133 XFreeColormap(xnestDisplay, xnestColormap(pCmap)); 134 } 135 136 #define SEARCH_PREDICATE \ 137 (xnestWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i]) 138 139 static int 140 xnestCountInstalledColormapWindows(WindowPtr pWin, void *ptr) 141 { 142 xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *) ptr; 143 int i; 144 145 for (i = 0; i < icws->numCmapIDs; i++) 146 if (SEARCH_PREDICATE) { 147 icws->numWindows++; 148 return WT_DONTWALKCHILDREN; 149 } 150 151 return WT_WALKCHILDREN; 152 } 153 154 static int 155 xnestGetInstalledColormapWindows(WindowPtr pWin, void *ptr) 156 { 157 xnestInstalledColormapWindows *icws = (xnestInstalledColormapWindows *) ptr; 158 int i; 159 160 for (i = 0; i < icws->numCmapIDs; i++) 161 if (SEARCH_PREDICATE) { 162 icws->windows[icws->index++] = xnestWindow(pWin); 163 return WT_DONTWALKCHILDREN; 164 } 165 166 return WT_WALKCHILDREN; 167 } 168 169 static Window *xnestOldInstalledColormapWindows = NULL; 170 static int xnestNumOldInstalledColormapWindows = 0; 171 172 static Bool 173 xnestSameInstalledColormapWindows(Window *windows, int numWindows) 174 { 175 if (xnestNumOldInstalledColormapWindows != numWindows) 176 return False; 177 178 if (xnestOldInstalledColormapWindows == windows) 179 return True; 180 181 if (xnestOldInstalledColormapWindows == NULL || windows == NULL) 182 return False; 183 184 if (memcmp(xnestOldInstalledColormapWindows, windows, 185 numWindows * sizeof(Window))) 186 return False; 187 188 return True; 189 } 190 191 void 192 xnestSetInstalledColormapWindows(ScreenPtr pScreen) 193 { 194 xnestInstalledColormapWindows icws; 195 int numWindows; 196 197 icws.cmapIDs = xallocarray(pScreen->maxInstalledCmaps, sizeof(Colormap)); 198 icws.numCmapIDs = xnestListInstalledColormaps(pScreen, icws.cmapIDs); 199 icws.numWindows = 0; 200 WalkTree(pScreen, xnestCountInstalledColormapWindows, (void *) &icws); 201 if (icws.numWindows) { 202 icws.windows = xallocarray(icws.numWindows + 1, sizeof(Window)); 203 icws.index = 0; 204 WalkTree(pScreen, xnestGetInstalledColormapWindows, (void *) &icws); 205 icws.windows[icws.numWindows] = xnestDefaultWindows[pScreen->myNum]; 206 numWindows = icws.numWindows + 1; 207 } 208 else { 209 icws.windows = NULL; 210 numWindows = 0; 211 } 212 213 free(icws.cmapIDs); 214 215 if (!xnestSameInstalledColormapWindows(icws.windows, icws.numWindows)) { 216 free(xnestOldInstalledColormapWindows); 217 218 #ifdef _XSERVER64 219 { 220 int i; 221 Window64 *windows = xallocarray(numWindows, sizeof(Window64)); 222 223 for (i = 0; i < numWindows; ++i) 224 windows[i] = icws.windows[i]; 225 XSetWMColormapWindows(xnestDisplay, 226 xnestDefaultWindows[pScreen->myNum], windows, 227 numWindows); 228 free(windows); 229 } 230 #else 231 XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], 232 icws.windows, numWindows); 233 #endif 234 235 xnestOldInstalledColormapWindows = icws.windows; 236 xnestNumOldInstalledColormapWindows = icws.numWindows; 237 238 #ifdef DUMB_WINDOW_MANAGERS 239 /* 240 This code is for dumb window managers. 241 This will only work with default local visual colormaps. 242 */ 243 if (icws.numWindows) { 244 WindowPtr pWin; 245 Visual *visual; 246 ColormapPtr pCmap; 247 248 pWin = xnestWindowPtr(icws.windows[0]); 249 visual = xnestVisualFromID(pScreen, wVisual(pWin)); 250 251 if (visual == xnestDefaultVisual(pScreen)) 252 dixLookupResourceByType((void **) &pCmap, wColormap(pWin), 253 RT_COLORMAP, serverClient, 254 DixUseAccess); 255 else 256 dixLookupResourceByType((void **) &pCmap, 257 pScreen->defColormap, RT_COLORMAP, 258 serverClient, DixUseAccess); 259 260 XSetWindowColormap(xnestDisplay, 261 xnestDefaultWindows[pScreen->myNum], 262 xnestColormap(pCmap)); 263 } 264 #endif /* DUMB_WINDOW_MANAGERS */ 265 } 266 else 267 free(icws.windows); 268 } 269 270 void 271 xnestSetScreenSaverColormapWindow(ScreenPtr pScreen) 272 { 273 free(xnestOldInstalledColormapWindows); 274 275 #ifdef _XSERVER64 276 { 277 Window64 window; 278 279 window = xnestScreenSaverWindows[pScreen->myNum]; 280 XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], 281 &window, 1); 282 xnestScreenSaverWindows[pScreen->myNum] = window; 283 } 284 #else 285 XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum], 286 &xnestScreenSaverWindows[pScreen->myNum], 1); 287 #endif /* _XSERVER64 */ 288 289 xnestOldInstalledColormapWindows = NULL; 290 xnestNumOldInstalledColormapWindows = 0; 291 292 xnestDirectUninstallColormaps(pScreen); 293 } 294 295 void 296 xnestDirectInstallColormaps(ScreenPtr pScreen) 297 { 298 int i, n; 299 Colormap pCmapIDs[MAXCMAPS]; 300 301 if (!xnestDoDirectColormaps) 302 return; 303 304 n = (*pScreen->ListInstalledColormaps) (pScreen, pCmapIDs); 305 306 for (i = 0; i < n; i++) { 307 ColormapPtr pCmap; 308 309 dixLookupResourceByType((void **) &pCmap, pCmapIDs[i], RT_COLORMAP, 310 serverClient, DixInstallAccess); 311 if (pCmap) 312 XInstallColormap(xnestDisplay, xnestColormap(pCmap)); 313 } 314 } 315 316 void 317 xnestDirectUninstallColormaps(ScreenPtr pScreen) 318 { 319 int i, n; 320 Colormap pCmapIDs[MAXCMAPS]; 321 322 if (!xnestDoDirectColormaps) 323 return; 324 325 n = (*pScreen->ListInstalledColormaps) (pScreen, pCmapIDs); 326 327 for (i = 0; i < n; i++) { 328 ColormapPtr pCmap; 329 330 dixLookupResourceByType((void **) &pCmap, pCmapIDs[i], RT_COLORMAP, 331 serverClient, DixUninstallAccess); 332 if (pCmap) 333 XUninstallColormap(xnestDisplay, xnestColormap(pCmap)); 334 } 335 } 336 337 void 338 xnestInstallColormap(ColormapPtr pCmap) 339 { 340 ColormapPtr pOldCmap = GetInstalledColormap(pCmap->pScreen); 341 342 if (pCmap != pOldCmap) { 343 xnestDirectUninstallColormaps(pCmap->pScreen); 344 345 /* Uninstall pInstalledMap. Notify all interested parties. */ 346 if (pOldCmap != (ColormapPtr) None) 347 WalkTree(pCmap->pScreen, TellLostMap, (void *) &pOldCmap->mid); 348 349 SetInstalledColormap(pCmap->pScreen, pCmap); 350 WalkTree(pCmap->pScreen, TellGainedMap, (void *) &pCmap->mid); 351 352 xnestSetInstalledColormapWindows(pCmap->pScreen); 353 xnestDirectInstallColormaps(pCmap->pScreen); 354 } 355 } 356 357 void 358 xnestUninstallColormap(ColormapPtr pCmap) 359 { 360 ColormapPtr pCurCmap = GetInstalledColormap(pCmap->pScreen); 361 362 if (pCmap == pCurCmap) { 363 if (pCmap->mid != pCmap->pScreen->defColormap) { 364 dixLookupResourceByType((void **) &pCurCmap, 365 pCmap->pScreen->defColormap, 366 RT_COLORMAP, 367 serverClient, DixInstallAccess); 368 (*pCmap->pScreen->InstallColormap) (pCurCmap); 369 } 370 } 371 } 372 373 static Bool xnestInstalledDefaultColormap = False; 374 375 int 376 xnestListInstalledColormaps(ScreenPtr pScreen, Colormap * pCmapIDs) 377 { 378 if (xnestInstalledDefaultColormap) { 379 *pCmapIDs = GetInstalledColormap(pScreen)->mid; 380 return 1; 381 } 382 else 383 return 0; 384 } 385 386 void 387 xnestStoreColors(ColormapPtr pCmap, int nColors, xColorItem * pColors) 388 { 389 if (pCmap->pVisual->class & DynamicClass) 390 #ifdef _XSERVER64 391 { 392 int i; 393 XColor *pColors64 = xallocarray(nColors, sizeof(XColor)); 394 395 for (i = 0; i < nColors; ++i) { 396 pColors64[i].pixel = pColors[i].pixel; 397 pColors64[i].red = pColors[i].red; 398 pColors64[i].green = pColors[i].green; 399 pColors64[i].blue = pColors[i].blue; 400 pColors64[i].flags = pColors[i].flags; 401 } 402 XStoreColors(xnestDisplay, xnestColormap(pCmap), pColors64, nColors); 403 free(pColors64); 404 } 405 #else 406 XStoreColors(xnestDisplay, xnestColormap(pCmap), 407 (XColor *) pColors, nColors); 408 #endif 409 } 410 411 void 412 xnestResolveColor(unsigned short *pRed, unsigned short *pGreen, 413 unsigned short *pBlue, VisualPtr pVisual) 414 { 415 int shift; 416 unsigned int lim; 417 418 shift = 16 - pVisual->bitsPerRGBValue; 419 lim = (1 << pVisual->bitsPerRGBValue) - 1; 420 421 if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor)) { 422 /* rescale to rgb bits */ 423 *pRed = ((*pRed >> shift) * 65535) / lim; 424 *pGreen = ((*pGreen >> shift) * 65535) / lim; 425 *pBlue = ((*pBlue >> shift) * 65535) / lim; 426 } 427 else if (pVisual->class == GrayScale) { 428 /* rescale to gray then rgb bits */ 429 *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; 430 *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; 431 } 432 else if (pVisual->class == StaticGray) { 433 unsigned int limg; 434 435 limg = pVisual->ColormapEntries - 1; 436 /* rescale to gray then [0..limg] then [0..65535] then rgb bits */ 437 *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100; 438 *pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg; 439 *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim; 440 } 441 else { 442 unsigned limr, limg, limb; 443 444 limr = pVisual->redMask >> pVisual->offsetRed; 445 limg = pVisual->greenMask >> pVisual->offsetGreen; 446 limb = pVisual->blueMask >> pVisual->offsetBlue; 447 /* rescale to [0..limN] then [0..65535] then rgb bits */ 448 *pRed = ((((((*pRed * (limr + 1)) >> 16) * 449 65535) / limr) >> shift) * 65535) / lim; 450 *pGreen = ((((((*pGreen * (limg + 1)) >> 16) * 451 65535) / limg) >> shift) * 65535) / lim; 452 *pBlue = ((((((*pBlue * (limb + 1)) >> 16) * 453 65535) / limb) >> shift) * 65535) / lim; 454 } 455 } 456 457 Bool 458 xnestCreateDefaultColormap(ScreenPtr pScreen) 459 { 460 VisualPtr pVisual; 461 ColormapPtr pCmap; 462 unsigned short zero = 0, ones = 0xFFFF; 463 Pixel wp, bp; 464 465 if (!dixRegisterPrivateKey(&cmapScrPrivateKeyRec, PRIVATE_SCREEN, 0)) 466 return FALSE; 467 468 for (pVisual = pScreen->visuals; 469 pVisual->vid != pScreen->rootVisual; pVisual++); 470 471 if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap, 472 (pVisual->class & DynamicClass) ? AllocNone : AllocAll, 473 0) 474 != Success) 475 return False; 476 477 wp = pScreen->whitePixel; 478 bp = pScreen->blackPixel; 479 if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) != 480 Success) || 481 (AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) != Success)) 482 return FALSE; 483 pScreen->whitePixel = wp; 484 pScreen->blackPixel = bp; 485 (*pScreen->InstallColormap) (pCmap); 486 487 xnestInstalledDefaultColormap = True; 488 489 return True; 490 }