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
xnestCreateColormap(ColormapPtr pCmap)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
xnestDestroyColormap(ColormapPtr pCmap)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
xnestCountInstalledColormapWindows(WindowPtr pWin,void * ptr)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
xnestGetInstalledColormapWindows(WindowPtr pWin,void * ptr)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
xnestSameInstalledColormapWindows(Window * windows,int numWindows)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
xnestSetInstalledColormapWindows(ScreenPtr pScreen)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
xnestSetScreenSaverColormapWindow(ScreenPtr pScreen)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
xnestDirectInstallColormaps(ScreenPtr pScreen)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
xnestDirectUninstallColormaps(ScreenPtr pScreen)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
xnestInstallColormap(ColormapPtr pCmap)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
xnestUninstallColormap(ColormapPtr pCmap)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
xnestListInstalledColormaps(ScreenPtr pScreen,Colormap * pCmapIDs)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
xnestStoreColors(ColormapPtr pCmap,int nColors,xColorItem * pColors)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
xnestResolveColor(unsigned short * pRed,unsigned short * pGreen,unsigned short * pBlue,VisualPtr pVisual)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
xnestCreateDefaultColormap(ScreenPtr pScreen)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 }
491