CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/colormaps.c
Go to the documentation of this file.
1/*
2 * Colormap handling
3 */
4
5#include "ctwm.h"
6
7#include <stdio.h>
8#include <stdlib.h>
9
10#include "colormaps.h"
11#include "screen.h"
12
13
14/*
15 * From events.c; imported manually since I'm not listing it in events.h
16 * because nowhere but here needs it.
17 */
18extern bool ColortableThrashing;
19
21 char *args);
22
23
24/***********************************************************************
25 *
26 * Procedure:
27 * InstallWindowColormaps - install the colormaps for one twm window
28 *
29 * Inputs:
30 * type - type of event that caused the installation
31 * tmp - for a subset of event types, the address of the
32 * window structure, whose colormaps are to be installed.
33 *
34 ***********************************************************************
35 *
36 * Previously in events.c
37 */
38bool
40{
41 if(tmp) {
42 return InstallColormaps(type, &tmp->cmaps);
43 }
44 else {
45 return InstallColormaps(type, NULL);
46 }
47}
48
49
50bool
51InstallColormaps(int type, Colormaps *cmaps)
52{
53 int i, j, n, number_cwins, state;
54 ColormapWindow **cwins, *cwin, **maxcwin = NULL;
56 char *row, *scoreboard;
57
58 switch(type) {
59 case EnterNotify:
60 case LeaveNotify:
61 case DestroyNotify:
62 default:
63 /* Save the colormap to be loaded for when force loading of
64 * root colormap(s) ends.
65 */
66 Scr->cmapInfo.pushed_cmaps = cmaps;
67 /* Don't load any new colormap if root colormap(s) has been
68 * force loaded.
69 */
70 if(Scr->cmapInfo.root_pushes) {
71 return false;
72 }
73 /* Don't reload the current window colormap list.
74 if (Scr->cmapInfo.cmaps == cmaps)
75 return false;
76 */
77 if(Scr->cmapInfo.cmaps) {
78 for(i = Scr->cmapInfo.cmaps->number_cwins,
79 cwins = Scr->cmapInfo.cmaps->cwins; i-- > 0; cwins++) {
80 (*cwins)->colormap->state &= ~CM_INSTALLABLE;
81 }
82 }
83 Scr->cmapInfo.cmaps = cmaps;
84 break;
85
86 case PropertyNotify:
88 case ColormapNotify:
89 break;
90 }
91
92 number_cwins = Scr->cmapInfo.cmaps->number_cwins;
93 cwins = Scr->cmapInfo.cmaps->cwins;
94 scoreboard = Scr->cmapInfo.cmaps->scoreboard;
95
96 ColortableThrashing = false; /* in case installation aborted */
97
98 state = CM_INSTALLED;
99
100 for(i = 0; i < number_cwins; i++) {
101 cwins[i]->colormap->state &= ~CM_INSTALL;
102 }
103 for(i = n = 0; i < number_cwins && n < Scr->cmapInfo.maxCmaps; i++) {
104 cwin = cwins[i];
105 cmap = cwin->colormap;
106 if(cmap->state & CM_INSTALL) {
107 continue;
108 }
110 cmap->w = cwin->w;
111 if(cwin->visibility != VisibilityFullyObscured) {
112 row = scoreboard + (i * (i - 1) / 2);
113 for(j = 0; j < i; j++)
114 if(row[j] && (cwins[j]->colormap->state & CM_INSTALL)) {
115 break;
116 }
117 if(j != i) {
118 continue;
119 }
120 n++;
121 maxcwin = &cwins[i];
122 state &= (cmap->state & CM_INSTALLED);
123 cmap->state |= CM_INSTALL;
124 }
125 }
126
127 // Hack: special-case startup
128 if(!dpy) {
129 return true;
130 }
131
132 Scr->cmapInfo.first_req = NextRequest(dpy);
133
134 for(; n > 0 && maxcwin >= &cwins[0]; maxcwin--) {
135 cmap = (*maxcwin)->colormap;
136 if(cmap->state & CM_INSTALL) {
137 cmap->state &= ~CM_INSTALL;
138 if(!(state & CM_INSTALLED)) {
139 cmap->install_req = NextRequest(dpy);
140 /* printf ("XInstallColormap : %x, %x\n", cmap, cmap->c); */
142 }
143 cmap->state |= CM_INSTALLED;
144 n--;
145 }
146 }
147 return true;
148}
149
150
151
152/***********************************************************************
153 *
154 * Procedures:
155 * <Uni/I>nstallRootColormap - Force (un)loads root colormap(s)
156 *
157 * These matching routines provide a mechanism to insure that
158 * the root colormap(s) is installed during operations like
159 * rubber banding or menu display that require colors from
160 * that colormap. Calls may be nested arbitrarily deeply,
161 * as long as there is one UninstallRootColormap call per
162 * InstallRootColormap call.
163 *
164 * The final UninstallRootColormap will cause the colormap list
165 * which would otherwise have be loaded to be loaded, unless
166 * Enter or Leave Notify events are queued, indicating some
167 * other colormap list would potentially be loaded anyway.
168 ***********************************************************************
169 *
170 * Previously in events.c
171 */
172void
174{
175 Colormaps *tmp;
176 if(Scr->cmapInfo.root_pushes == 0) {
177 /*
178 * The saving and restoring of cmapInfo.pushed_window here
179 * is a slimy way to remember the actual pushed list and
180 * not that of the root window.
181 */
182 tmp = Scr->cmapInfo.pushed_cmaps;
183 InstallColormaps(0, &Scr->RootColormaps);
184 Scr->cmapInfo.pushed_cmaps = tmp;
185 }
186 Scr->cmapInfo.root_pushes++;
187}
188
189
190/* ARGSUSED*/
191static Bool
193 char *args)
194{
195 if(!*args) {
196 if(ev->type == EnterNotify) {
197 if(ev->xcrossing.mode != NotifyGrab) {
198 *args = 1;
199 }
200 }
201 else if(ev->type == LeaveNotify) {
202 if(ev->xcrossing.mode == NotifyNormal) {
203 *args = 1;
204 }
205 }
206 }
207
208 return (False);
209}
210
211
212void
214{
215 char args;
217
218 if(Scr->cmapInfo.root_pushes) {
219 Scr->cmapInfo.root_pushes--;
220 }
221
222 if(!Scr->cmapInfo.root_pushes) {
223 /*
224 * If we have subsequent Enter or Leave Notify events,
225 * we can skip the reload of pushed colormaps.
226 */
227 XSync(dpy, 0);
228 args = 0;
230
231 if(!args) {
232 InstallColormaps(0, Scr->cmapInfo.pushed_cmaps);
233 }
234 }
235}
236
237
238/*
239 * Create a TwmColormap struct and tie it to an [X] Colormap. Places
240 * that need to mess with colormaps and look up the metainfo we hang off
241 * them need to look this up and find it via the X Context.
242 *
243 * Previously in add_window.c
244 */
247{
249 cmap = malloc(sizeof(TwmColormap));
250 if(!cmap) {
251 return NULL;
252 }
253 cmap->c = c;
254 cmap->state = 0;
255 cmap->install_req = 0;
256 cmap->w = None;
257 cmap->refcnt = 1;
258
260 free(cmap);
261 return NULL;
262 }
263 return (cmap);
264}
265
266
267/*
268 * Put together a ColormapWindow struct. This is a thing we hang off a
269 * TwmWindow for some colormap tracking stuff.
270 *
271 * Previously in add_window.c
272 */
275{
279
280 cwin = malloc(sizeof(ColormapWindow));
281 if(cwin == NULL) {
282 return NULL;
283 }
284
285 // Common
286 cwin->w = w;
287
288 /*
289 * Assume that windows in colormap list are
290 * obscured if we are creating the parent window.
291 * Otherwise, we assume they are unobscured.
292 */
293 cwin->visibility = creating_parent ?
295 cwin->refcnt = 1;
296
297
298 // Stub for special cases
299 if(dpy == NULL) {
300 cwin->colormap = NULL;
301 cwin->colormap = calloc(1, sizeof(TwmColormap));
302 cwin->colormap->refcnt = 1;
303
304 return cwin;
305 }
306
307
310 free(cwin);
311 return (NULL);
312 }
313
315 (XPointer *)&cwin->colormap) == XCNOENT) {
316 cwin->colormap = cmap = CreateTwmColormap(attributes.colormap);
317 if(!cmap) {
319 free(cwin);
320 return (NULL);
321 }
322 }
323 else {
324 cwin->colormap->refcnt++;
325 }
326
327 /*
328 * If this is a ColormapWindow property window and we
329 * are not monitoring ColormapNotify or VisibilityNotify
330 * events, we need to.
331 */
332 if(property_window &&
333 (attributes.your_event_mask &
336 XSelectInput(dpy, w, attributes.your_event_mask |
338 }
339
340 return (cwin);
341}
342
343
344/*
345 * Do something with looking up stuff from WM_COLORMAPS_WINDOWS (relating
346 * to windows with their own colormap) and finding or putting this window
347 * into it.
348 *
349 * XXX Someone should figure it out better than that...
350 *
351 * Previously in add_window.c
352 */
353void
355{
356 int i, j;
358 bool can_free_cmap_windows = false;
359 int number_cmap_windows = 0;
360 ColormapWindow **cwins = NULL;
361 bool previnst;
362
364
365 previnst = (Scr->cmapInfo.cmaps == &tmp->cmaps && tmp->cmaps.number_cwins);
366 if(previnst) {
367 cwins = tmp->cmaps.cwins;
368 for(i = 0; i < tmp->cmaps.number_cwins; i++) {
369 cwins[i]->colormap->state = 0;
370 }
371 }
372
376
377 /*
378 * check if the top level is in the list, add to front if not
379 */
380 for(i = 0; i < number_cmap_windows; i++) {
381 if(cmap_windows[i] == tmp->w) {
382 break;
383 }
384 }
385 if(i == number_cmap_windows) { /* not in list */
387 calloc((number_cmap_windows + 1), sizeof(Window));
388
389 if(!new_cmap_windows) {
391 "%s: unable to allocate %d element colormap window array\n",
393 goto done;
394 }
395 new_cmap_windows[0] = tmp->w; /* add to front */
396 for(i = 0; i < number_cmap_windows; i++) { /* append rest */
397 new_cmap_windows[i + 1] = cmap_windows[i];
398 }
400 can_free_cmap_windows = true; /* do not use XFree any more */
403 }
404
405 cwins = calloc(number_cmap_windows, sizeof(ColormapWindow *));
406 if(cwins) {
407 for(i = 0; i < number_cmap_windows; i++) {
408
409 /*
410 * Copy any existing entries into new list.
411 */
412 for(j = 0; j < tmp->cmaps.number_cwins; j++) {
413 if(tmp->cmaps.cwins[j]->w == cmap_windows[i]) {
414 cwins[i] = tmp->cmaps.cwins[j];
415 cwins[i]->refcnt++;
416 break;
417 }
418 }
419
420 /*
421 * If the colormap window is not being pointed by
422 * some other applications colormap window list,
423 * create a new entry.
424 */
425 if(j == tmp->cmaps.number_cwins) {
427 (XPointer *)&cwins[i]) == XCNOENT) {
428 if((cwins[i] = CreateColormapWindow(cmap_windows[i],
429 tmp->cmaps.number_cwins == 0,
430 true)) == NULL) {
431 int k;
432 for(k = i + 1; k < number_cmap_windows; k++) {
434 }
435 i--;
437 }
438 }
439 else {
440 cwins[i]->refcnt++;
441 }
442 }
443 }
444 }
445 }
446
447 /* No else here, in case we bailed out of clause above.
448 */
449 if(number_cmap_windows == 0) {
450
452
453 cwins = malloc(sizeof(ColormapWindow *));
454 if(XFindContext(dpy, tmp->w, ColormapContext, (XPointer *)&cwins[0]) ==
455 XCNOENT)
456 cwins[0] = CreateColormapWindow(tmp->w,
457 tmp->cmaps.number_cwins == 0, false);
458 else {
459 cwins[0]->refcnt++;
460 }
461 }
462
463 if(tmp->cmaps.number_cwins) {
465 }
466
467 tmp->cmaps.cwins = cwins;
468 tmp->cmaps.number_cwins = number_cmap_windows;
469 if(number_cmap_windows > 1)
470 tmp->cmaps.scoreboard =
472
473 if(previnst) {
475 }
476
477done:
478 if(cmap_windows) {
481 }
482 else {
484 }
485 }
486}
487
488
489/*
490 * BumpWindowColormap - rotate our internal copy of WM_COLORMAP_WINDOWS.
491 * This is the backend for f.colormap.
492 *
493 * Previously in functions.c
494 */
495void
497{
498 int i, j;
500 ColormapWindow **cwins;
501
502 if(!tmp) {
503 return;
504 }
505
506 if(inc && tmp->cmaps.number_cwins > 0) {
507 cwins = calloc(tmp->cmaps.number_cwins, sizeof(ColormapWindow *));
508 if(cwins) {
509 previously_installed = (Scr->cmapInfo.cmaps == &tmp->cmaps &&
510 tmp->cmaps.number_cwins);
512 for(i = tmp->cmaps.number_cwins; i-- > 0;) {
513 tmp->cmaps.cwins[i]->colormap->state = 0;
514 }
515 }
516
517 for(i = 0; i < tmp->cmaps.number_cwins; i++) {
518 j = i - inc;
519 if(j >= tmp->cmaps.number_cwins) {
520 j -= tmp->cmaps.number_cwins;
521 }
522 else if(j < 0) {
523 j += tmp->cmaps.number_cwins;
524 }
525 cwins[j] = tmp->cmaps.cwins[i];
526 }
527
528 free(tmp->cmaps.cwins);
529
530 tmp->cmaps.cwins = cwins;
531
532 if(tmp->cmaps.number_cwins > 1)
533 memset(tmp->cmaps.scoreboard, 0,
535
538 }
539 }
540 }
541 else {
543 }
544 return;
545}
546
547
548/*
549 * Handlers for creating and linkin in, as well as deleting, a StdCmap
550 * for a given XStandardColormap.
551 *
552 * Previously in util.c
553 */
554void
556 bool replace)
557{
558 StdCmap *sc = NULL;
559
560 if(replace) { /* locate existing entry */
561 for(sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
562 if(sc->atom == a) {
563 break;
564 }
565 }
566 }
567
568 if(!sc) { /* no existing, allocate new */
569 sc = calloc(1, sizeof(StdCmap));
570 if(!sc) {
571 fprintf(stderr, "%s: unable to allocate %lu bytes for StdCmap\n",
572 ProgramName, (unsigned long) sizeof(StdCmap));
573 return;
574 }
575 replace = false; // Didn't find one, can't replace
576 }
577
578 if(replace) { /* just update contents */
579 if(sc->maps) {
580 XFree(sc->maps);
581 }
582 if(sc == Scr->StdCmapInfo.mru) {
583 Scr->StdCmapInfo.mru = NULL;
584 }
585 }
586 else { /* else appending */
587 sc->next = NULL;
588 sc->atom = a;
589 if(Scr->StdCmapInfo.tail) {
590 Scr->StdCmapInfo.tail->next = sc;
591 }
592 else {
593 Scr->StdCmapInfo.head = sc;
594 }
595 Scr->StdCmapInfo.tail = sc;
596 }
597 sc->nmaps = nmaps;
598 sc->maps = maps;
599
600 return;
601}
602
603
604void
606{
607 StdCmap *sc, *prev;
608
609 prev = NULL;
610 for(sc = Scr->StdCmapInfo.head; sc; sc = sc->next) {
611 if(sc->atom == a) {
612 break;
613 }
614 prev = sc;
615 }
616 if(sc) { /* found one */
617 if(sc->maps) {
618 XFree(sc->maps);
619 }
620 if(prev) {
621 prev->next = sc->next;
622 }
623 if(Scr->StdCmapInfo.head == sc) {
624 Scr->StdCmapInfo.head = sc->next;
625 }
626 if(Scr->StdCmapInfo.tail == sc) {
627 Scr->StdCmapInfo.tail = prev;
628 }
629 if(Scr->StdCmapInfo.mru == sc) {
630 Scr->StdCmapInfo.mru = NULL;
631 }
632 }
633 return;
634}
635
636
637/*
638 * Go through all the properties of the root window and setup
639 * XStandardColormap's and our StdCmap's for any of them that are
640 * actually RGB_COLORMAP types. We're not actually _checking_ the types,
641 * just letting XGetRGBColormaps() refuse to handle probably most of
642 * them. Called during startup.
643 *
644 * Previouly in util.c
645 */
646void
648{
649 Atom *atoms;
650 int natoms;
651 int i;
652
653 atoms = XListProperties(dpy, Scr->Root, &natoms);
654 for(i = 0; i < natoms; i++) {
655 XStandardColormap *maps = NULL;
656 int nmaps;
657
658 if(XGetRGBColormaps(dpy, Scr->Root, &maps, &nmaps, atoms[i])) {
659 /* if got one, then append to current list */
660 InsertRGBColormap(atoms[i], maps, nmaps, false);
661 }
662 }
663 if(atoms) {
664 XFree(atoms);
665 }
666 return;
667}
668
669
670/*
671 * Clear out and free TwmWindow.cmaps (struct Colormaps) bits for a window.
672 *
673 * Previously in events.c
674 */
675void
677{
678 int i;
680
681 if(tmp->cmaps.number_cwins) {
682 for(i = 0; i < tmp->cmaps.number_cwins; i++) {
683 if(--tmp->cmaps.cwins[i]->refcnt == 0) {
684 cmap = tmp->cmaps.cwins[i]->colormap;
685 if(--cmap->refcnt == 0) {
687 free(cmap);
688 }
689 XDeleteContext(dpy, tmp->cmaps.cwins[i]->w, ColormapContext);
690 free(tmp->cmaps.cwins[i]);
691 }
692 }
693 free(tmp->cmaps.cwins);
694 if(tmp->cmaps.number_cwins > 1) {
695 free(tmp->cmaps.scoreboard);
696 tmp->cmaps.scoreboard = NULL;
697 }
698 tmp->cmaps.number_cwins = 0;
699 }
700}
static int PlaceX
Definition add_window.c:82
bool ColortableThrashing
Definition event_core.c:90
void FetchWmColormapWindows(TwmWindow *tmp)
Definition colormaps.c:354
bool InstallWindowColormaps(int type, TwmWindow *tmp)
Definition colormaps.c:39
void BumpWindowColormap(TwmWindow *tmp, int inc)
Definition colormaps.c:496
void free_cwins(TwmWindow *tmp)
Definition colormaps.c:676
void RemoveRGBColormap(Atom a)
Definition colormaps.c:605
bool InstallColormaps(int type, Colormaps *cmaps)
Definition colormaps.c:51
void UninstallRootColormap(void)
Definition colormaps.c:213
static Bool UninstallRootColormapQScanner(Display *display, XEvent *ev, char *args)
Definition colormaps.c:192
TwmColormap * CreateTwmColormap(Colormap c)
Definition colormaps.c:246
ColormapWindow * CreateColormapWindow(Window w, bool creating_parent, bool property_window)
Definition colormaps.c:274
void InsertRGBColormap(Atom a, XStandardColormap *maps, int nmaps, bool replace)
Definition colormaps.c:555
void InstallRootColormap(void)
Definition colormaps.c:173
void LocateStandardColormaps(void)
Definition colormaps.c:647
char * ProgramName
Definition ctwm_main.c:146
#define CM_INSTALL
Definition ctwm.h:268
#define CM_INSTALLED
Definition ctwm.h:267
#define ColormapsScoreboardLength(cm)
Definition ctwm.h:284
Display * dpy
Definition ctwm_main.c:84
XContext ColormapContext
Definition ctwm_main.c:122
#define CM_INSTALLABLE
Definition ctwm.h:266
#define Scr
TwmColormap * colormap
Definition ctwm.h:273
int number_cwins
Definition ctwm.h:280
Information about some XStandardColormap we're using.
Definition screen.h:46
struct StdCmap * next
Definition screen.h:47
int state
Definition ctwm.h:259
Info and control for every X Window we take over.