Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xnest / Color.c
CommitLineData
a09e091a
JB
1/*
2
3Copyright 1993 by Davor Matic
4
5Permission to use, copy, modify, distribute, and sell this software
6and its documentation for any purpose is hereby granted without fee,
7provided that the above copyright notice appear in all copies and that
8both that copyright notice and this permission notice appear in
9supporting documentation. Davor Matic makes no representations about
10the suitability of this software for any purpose. It is provided "as
11is" 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
36DevPrivateKeyRec xnestColormapPrivateKeyRec;
37
38static 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
45Bool
46xnestCreateColormap(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
130void
131xnestDestroyColormap(ColormapPtr pCmap)
132{
133 XFreeColormap(xnestDisplay, xnestColormap(pCmap));
134}
135
136#define SEARCH_PREDICATE \
137 (xnestWindow(pWin) != None && wColormap(pWin) == icws->cmapIDs[i])
138
139static int
140xnestCountInstalledColormapWindows(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
154static int
155xnestGetInstalledColormapWindows(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
169static Window *xnestOldInstalledColormapWindows = NULL;
170static int xnestNumOldInstalledColormapWindows = 0;
171
172static Bool
173xnestSameInstalledColormapWindows(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
191void
192xnestSetInstalledColormapWindows(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
273void
274xnestSetScreenSaverColormapWindow(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
298void
299xnestDirectInstallColormaps(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
319void
320xnestDirectUninstallColormaps(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
340void
341xnestInstallColormap(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
360void
361xnestUninstallColormap(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
376static Bool xnestInstalledDefaultColormap = False;
377
378int
379xnestListInstalledColormaps(ScreenPtr pScreen, Colormap * pCmapIDs)
380{
381 if (xnestInstalledDefaultColormap) {
382 *pCmapIDs = GetInstalledColormap(pScreen)->mid;
383 return 1;
384 }
385 else
386 return 0;
387}
388
389void
390xnestStoreColors(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
414void
415xnestResolveColor(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
460Bool
461xnestCreateDefaultColormap(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}