Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xnest / Color.c
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 = (XColor *) malloc(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 = (XColor *) malloc(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 = (XColor *) malloc(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, pointer 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, pointer 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 = (Colormap *) malloc(pScreen->maxInstalledCmaps *
198 sizeof(Colormap));
199 icws.numCmapIDs = xnestListInstalledColormaps(pScreen, icws.cmapIDs);
200 icws.numWindows = 0;
201 WalkTree(pScreen, xnestCountInstalledColormapWindows, (pointer) &icws);
202 if (icws.numWindows) {
203 icws.windows =
204 (Window *) malloc((icws.numWindows + 1) * sizeof(Window));
205 icws.index = 0;
206 WalkTree(pScreen, xnestGetInstalledColormapWindows, (pointer) &icws);
207 icws.windows[icws.numWindows] = xnestDefaultWindows[pScreen->myNum];
208 numWindows = icws.numWindows + 1;
209 }
210 else {
211 icws.windows = NULL;
212 numWindows = 0;
213 }
214
215 free(icws.cmapIDs);
216
217 if (!xnestSameInstalledColormapWindows(icws.windows, icws.numWindows)) {
218 free(xnestOldInstalledColormapWindows);
219
220 #ifdef _XSERVER64
221 {
222 int i;
223 Window64 *windows =
224 (Window64 *) malloc(numWindows * sizeof(Window64));
225
226 for (i = 0; i < numWindows; ++i)
227 windows[i] = icws.windows[i];
228 XSetWMColormapWindows(xnestDisplay,
229 xnestDefaultWindows[pScreen->myNum], windows,
230 numWindows);
231 free(windows);
232 }
233 #else
234 XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
235 icws.windows, numWindows);
236 #endif
237
238 xnestOldInstalledColormapWindows = icws.windows;
239 xnestNumOldInstalledColormapWindows = icws.numWindows;
240
241 #ifdef DUMB_WINDOW_MANAGERS
242 /*
243 This code is for dumb window managers.
244 This will only work with default local visual colormaps.
245 */
246 if (icws.numWindows) {
247 WindowPtr pWin;
248 Visual *visual;
249 ColormapPtr pCmap;
250
251 pWin = xnestWindowPtr(icws.windows[0]);
252 visual = xnestVisualFromID(pScreen, wVisual(pWin));
253
254 if (visual == xnestDefaultVisual(pScreen))
255 dixLookupResourceByType((pointer *) &pCmap, wColormap(pWin),
256 RT_COLORMAP, serverClient,
257 DixUseAccess);
258 else
259 dixLookupResourceByType((pointer *) &pCmap,
260 pScreen->defColormap, RT_COLORMAP,
261 serverClient, DixUseAccess);
262
263 XSetWindowColormap(xnestDisplay,
264 xnestDefaultWindows[pScreen->myNum],
265 xnestColormap(pCmap));
266 }
267 #endif /* DUMB_WINDOW_MANAGERS */
268 }
269 else
270 free(icws.windows);
271 }
272
273 void
274 xnestSetScreenSaverColormapWindow(ScreenPtr pScreen)
275 {
276 free(xnestOldInstalledColormapWindows);
277
278 #ifdef _XSERVER64
279 {
280 Window64 window;
281
282 window = xnestScreenSaverWindows[pScreen->myNum];
283 XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
284 &window, 1);
285 xnestScreenSaverWindows[pScreen->myNum] = window;
286 }
287 #else
288 XSetWMColormapWindows(xnestDisplay, xnestDefaultWindows[pScreen->myNum],
289 &xnestScreenSaverWindows[pScreen->myNum], 1);
290 #endif /* _XSERVER64 */
291
292 xnestOldInstalledColormapWindows = NULL;
293 xnestNumOldInstalledColormapWindows = 0;
294
295 xnestDirectUninstallColormaps(pScreen);
296 }
297
298 void
299 xnestDirectInstallColormaps(ScreenPtr pScreen)
300 {
301 int i, n;
302 Colormap pCmapIDs[MAXCMAPS];
303
304 if (!xnestDoDirectColormaps)
305 return;
306
307 n = (*pScreen->ListInstalledColormaps) (pScreen, pCmapIDs);
308
309 for (i = 0; i < n; i++) {
310 ColormapPtr pCmap;
311
312 dixLookupResourceByType((pointer *) &pCmap, pCmapIDs[i], RT_COLORMAP,
313 serverClient, DixInstallAccess);
314 if (pCmap)
315 XInstallColormap(xnestDisplay, xnestColormap(pCmap));
316 }
317 }
318
319 void
320 xnestDirectUninstallColormaps(ScreenPtr pScreen)
321 {
322 int i, n;
323 Colormap pCmapIDs[MAXCMAPS];
324
325 if (!xnestDoDirectColormaps)
326 return;
327
328 n = (*pScreen->ListInstalledColormaps) (pScreen, pCmapIDs);
329
330 for (i = 0; i < n; i++) {
331 ColormapPtr pCmap;
332
333 dixLookupResourceByType((pointer *) &pCmap, pCmapIDs[i], RT_COLORMAP,
334 serverClient, DixUninstallAccess);
335 if (pCmap)
336 XUninstallColormap(xnestDisplay, xnestColormap(pCmap));
337 }
338 }
339
340 void
341 xnestInstallColormap(ColormapPtr pCmap)
342 {
343 ColormapPtr pOldCmap = GetInstalledColormap(pCmap->pScreen);
344
345 if (pCmap != pOldCmap) {
346 xnestDirectUninstallColormaps(pCmap->pScreen);
347
348 /* Uninstall pInstalledMap. Notify all interested parties. */
349 if (pOldCmap != (ColormapPtr) None)
350 WalkTree(pCmap->pScreen, TellLostMap, (pointer) &pOldCmap->mid);
351
352 SetInstalledColormap(pCmap->pScreen, pCmap);
353 WalkTree(pCmap->pScreen, TellGainedMap, (pointer) &pCmap->mid);
354
355 xnestSetInstalledColormapWindows(pCmap->pScreen);
356 xnestDirectInstallColormaps(pCmap->pScreen);
357 }
358 }
359
360 void
361 xnestUninstallColormap(ColormapPtr pCmap)
362 {
363 ColormapPtr pCurCmap = GetInstalledColormap(pCmap->pScreen);
364
365 if (pCmap == pCurCmap) {
366 if (pCmap->mid != pCmap->pScreen->defColormap) {
367 dixLookupResourceByType((pointer *) &pCurCmap,
368 pCmap->pScreen->defColormap,
369 RT_COLORMAP,
370 serverClient, DixInstallAccess);
371 (*pCmap->pScreen->InstallColormap) (pCurCmap);
372 }
373 }
374 }
375
376 static Bool xnestInstalledDefaultColormap = False;
377
378 int
379 xnestListInstalledColormaps(ScreenPtr pScreen, Colormap * pCmapIDs)
380 {
381 if (xnestInstalledDefaultColormap) {
382 *pCmapIDs = GetInstalledColormap(pScreen)->mid;
383 return 1;
384 }
385 else
386 return 0;
387 }
388
389 void
390 xnestStoreColors(ColormapPtr pCmap, int nColors, xColorItem * pColors)
391 {
392 if (pCmap->pVisual->class & DynamicClass)
393 #ifdef _XSERVER64
394 {
395 int i;
396 XColor *pColors64 = (XColor *) malloc(nColors * sizeof(XColor));
397
398 for (i = 0; i < nColors; ++i) {
399 pColors64[i].pixel = pColors[i].pixel;
400 pColors64[i].red = pColors[i].red;
401 pColors64[i].green = pColors[i].green;
402 pColors64[i].blue = pColors[i].blue;
403 pColors64[i].flags = pColors[i].flags;
404 }
405 XStoreColors(xnestDisplay, xnestColormap(pCmap), pColors64, nColors);
406 free(pColors64);
407 }
408 #else
409 XStoreColors(xnestDisplay, xnestColormap(pCmap),
410 (XColor *) pColors, nColors);
411 #endif
412 }
413
414 void
415 xnestResolveColor(unsigned short *pRed, unsigned short *pGreen,
416 unsigned short *pBlue, VisualPtr pVisual)
417 {
418 int shift;
419 unsigned int lim;
420
421 shift = 16 - pVisual->bitsPerRGBValue;
422 lim = (1 << pVisual->bitsPerRGBValue) - 1;
423
424 if ((pVisual->class == PseudoColor) || (pVisual->class == DirectColor)) {
425 /* rescale to rgb bits */
426 *pRed = ((*pRed >> shift) * 65535) / lim;
427 *pGreen = ((*pGreen >> shift) * 65535) / lim;
428 *pBlue = ((*pBlue >> shift) * 65535) / lim;
429 }
430 else if (pVisual->class == GrayScale) {
431 /* rescale to gray then rgb bits */
432 *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100;
433 *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim;
434 }
435 else if (pVisual->class == StaticGray) {
436 unsigned int limg;
437
438 limg = pVisual->ColormapEntries - 1;
439 /* rescale to gray then [0..limg] then [0..65535] then rgb bits */
440 *pRed = (30L * *pRed + 59L * *pGreen + 11L * *pBlue) / 100;
441 *pRed = ((((*pRed * (limg + 1))) >> 16) * 65535) / limg;
442 *pBlue = *pGreen = *pRed = ((*pRed >> shift) * 65535) / lim;
443 }
444 else {
445 unsigned limr, limg, limb;
446
447 limr = pVisual->redMask >> pVisual->offsetRed;
448 limg = pVisual->greenMask >> pVisual->offsetGreen;
449 limb = pVisual->blueMask >> pVisual->offsetBlue;
450 /* rescale to [0..limN] then [0..65535] then rgb bits */
451 *pRed = ((((((*pRed * (limr + 1)) >> 16) *
452 65535) / limr) >> shift) * 65535) / lim;
453 *pGreen = ((((((*pGreen * (limg + 1)) >> 16) *
454 65535) / limg) >> shift) * 65535) / lim;
455 *pBlue = ((((((*pBlue * (limb + 1)) >> 16) *
456 65535) / limb) >> shift) * 65535) / lim;
457 }
458 }
459
460 Bool
461 xnestCreateDefaultColormap(ScreenPtr pScreen)
462 {
463 VisualPtr pVisual;
464 ColormapPtr pCmap;
465 unsigned short zero = 0, ones = 0xFFFF;
466 Pixel wp, bp;
467
468 if (!dixRegisterPrivateKey(&cmapScrPrivateKeyRec, PRIVATE_SCREEN, 0))
469 return FALSE;
470
471 for (pVisual = pScreen->visuals;
472 pVisual->vid != pScreen->rootVisual; pVisual++);
473
474 if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &pCmap,
475 (pVisual->class & DynamicClass) ? AllocNone : AllocAll,
476 0)
477 != Success)
478 return False;
479
480 wp = pScreen->whitePixel;
481 bp = pScreen->blackPixel;
482 if ((AllocColor(pCmap, &ones, &ones, &ones, &wp, 0) !=
483 Success) ||
484 (AllocColor(pCmap, &zero, &zero, &zero, &bp, 0) != Success))
485 return FALSE;
486 pScreen->whitePixel = wp;
487 pScreen->blackPixel = bp;
488 (*pScreen->InstallColormap) (pCmap);
489
490 xnestInstalledDefaultColormap = True;
491
492 return True;
493 }