Commit | Line | Data |
---|---|---|
a09e091a JB |
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 | } |