source: trunk/third/mwm/WmColormap.c @ 9757

Revision 9757, 17.4 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9756, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
3 * ALL RIGHTS RESERVED
4*/
5/*
6 * Motif Release 1.2.3
7*/
8#ifdef REV_INFO
9#ifndef lint
10static char rcsid[] = "$RCSfile: WmColormap.c,v $ $Revision: 1.1.1.1 $ $Date: 1997-03-25 09:12:17 $"
11#endif
12#endif
13/*
14 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
15
16/*
17 * Included Files:
18 */
19
20#include "WmGlobal.h"
21
22/*
23 * include extern functions
24 */
25
26#include "WmKeyFocus.h"
27
28/*
29 * Function Declarations:
30 */
31
32#ifdef _NO_PROTO
33void    InitColormapFocus ();
34void    InitWorkspaceColormap ();
35void    ResetColormapData ();
36#ifndef OLD_COLORMAP
37void    ForceColormapFocus ();
38#endif
39void    SetColormapFocus ();
40void    WmInstallColormap ();
41void    ProcessColormapList();
42static Bool ProcessEvents();
43#else /* _NO_PROTO */
44void InitWorkspaceColormap (WmScreenData *pSD);
45void InitColormapFocus (WmScreenData *pSD);
46#ifndef OLD_COLORMAP
47void ForceColormapFocus (WmScreenData *pSD, ClientData *pCD);
48#endif
49void SetColormapFocus (WmScreenData *pSD, ClientData *pCD);
50void WmInstallColormap (WmScreenData *pSD, Colormap colormap);
51void ResetColormapData (ClientData *pCD, Window *pWindows, int count);
52void ProcessColormapList (WmScreenData *pSD, ClientData *pCD);
53static Bool ProcessEvents(Display *dpy, XEvent *Event, char *c_pCD);
54#endif /* _NO_PROTO */
55
56
57/* Global variables */
58        static unsigned long firstRequest, lastRequest;
59
60
61/*************************************<->*************************************
62 *
63 *  InitWorkspaceColormap ()
64 *
65 *
66 *  Description:
67 *  -----------
68 *  This function sets up the default workspace colormap and prepares for
69 *  workspace colormap processing.
70 *
71 *
72 *  Inputs:
73 *  -------
74 *  pSD = ptr to screen data
75 *
76 *  Outputs:
77 *  -------
78 *  wmGD = (workspaceColormap)
79 *
80 *************************************<->***********************************/
81
82#ifdef _NO_PROTO
83void InitWorkspaceColormap (pSD)
84    WmScreenData *pSD;
85
86#else /* _NO_PROTO */
87void InitWorkspaceColormap (WmScreenData *pSD)
88#endif /* _NO_PROTO */
89{
90    /*
91     * Setup the default (workspace) colormap:
92     * !!! this should be made more general to get the colormap for the !!!
93     * !!! workspace (root) and then track colormap changes             !!!
94     */
95
96    pSD->workspaceColormap = DefaultColormap (DISPLAY, pSD->screen);
97
98} /* END OF FUNCTION InitWorkspaceColormap */
99
100
101
102/*************************************<->*************************************
103 *
104 *  InitColormapFocus (pSD)
105 *
106 *
107 *  Description:
108 *  -----------
109 *  This function prepares for managing the colormap focus and sets the
110 *  initial colormap focus (if the focus policy is "keyboard" - i.e. the
111 *  colormap focus tracks the keyboard focus) the initial colormap
112 *  installation is done in InitKeyboardFocus.
113 *
114 *  Inputs:
115 *  -------
116 *  pSD = pointer to screen data
117 *
118 *  Outputs:
119 *  -------
120 *  *pSD = (colormapFocus)
121 *
122 *************************************<->***********************************/
123
124#ifdef _NO_PROTO
125void InitColormapFocus (pSD)
126    WmScreenData *pSD;
127
128#else /* _NO_PROTO */
129void InitColormapFocus (WmScreenData *pSD)
130#endif /* _NO_PROTO */
131{
132    ClientData *pCD;
133    Boolean sameScreen;
134
135
136    /*
137     * Set up the initial colormap focus.  If the colormapFocusPolicy is
138     * "keyboard" or it is "pointer" and the keyboard input focus policy
139     * is "pointer" then set up the initial colormap focus when the
140     * initial keyboard input focus is set up.
141     */
142
143    pSD->colormapFocus = NULL;
144
145    if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
146    {
147        if (wmGD.keyboardFocusPolicy != KEYBOARD_FOCUS_POINTER)
148        {
149            if ((pCD = GetClientUnderPointer (&sameScreen)) != NULL)
150            {
151                SetColormapFocus (pSD, pCD);
152            }
153            else
154            {
155                WmInstallColormap (pSD, pSD->workspaceColormap);
156            }
157        }
158    }
159    else
160    {
161        WmInstallColormap (pSD, pSD->workspaceColormap);
162    }
163
164} /* END OF FUNCTION InitColormapFocus */
165
166
167
168#ifndef OLD_COLORMAP
169/*************************************<->*************************************
170 *
171 *  ForceColormapFocus (pSD, pCD)
172 *
173 *
174 *  Description:
175 *  -----------
176 * ForceColormapFocus is the working part of the original SetColormapFocus.
177 * This function is used to unconditionally set the colormap focus to a
178 * particular client window or to clear the colormap focus (set focus to
179 * the root window).
180 *
181 * The reason is to permit focus to be coerced.  We need to do this because
182 * we can already have colormap focus, but still need to set the colormaps.
183 * Examples of when this occurs are:
184 *
185 *      * after the window manager itself has forced a colormap,
186 *        as happens when it draws transients in the overlay planes.
187 *      * when WM_COLORMAP_WINDOWS changes.
188 *      * when a ColormapNotify (new) event is received.
189 *
190 *
191 *  Inputs:
192 *  ------
193 *  pSD = pointer to Screen Data
194 *  pCD = pointer to client data (clientColormap ...)
195 *
196 *************************************<->***********************************/
197
198#ifdef _NO_PROTO
199void ForceColormapFocus (pSD, pCD)
200    WmScreenData *pSD;
201    ClientData *pCD;
202
203#else /* _NO_PROTO */
204void ForceColormapFocus (WmScreenData *pSD, ClientData *pCD)
205#endif /* _NO_PROTO */
206{
207    if (pCD && ((pCD->clientState == NORMAL_STATE) ||
208                (pCD->clientState == MAXIMIZED_STATE)))
209    {
210        pSD->colormapFocus = pCD;
211#ifndef OLD_COLORMAP /* colormaps */
212        ProcessColormapList (pSD, pCD);
213#else /* OSF original */
214        WmInstallColormap (pSD, pCD->clientColormap);
215#endif
216    }
217    else
218    {
219        /*
220         * The default colormap is installed for minimized windows that have
221         * the colormap focus.
222         * !!! should colormaps be installed for icons with client      !!!
223         * !!! icon windows?  should the client colormap be installed ? !!!
224         */
225
226        pSD->colormapFocus = NULL;
227        WmInstallColormap (pSD, pSD->workspaceColormap);
228    }
229
230} /* END OF FUNCTION ForceColormapFocus */
231#endif
232
233
234
235/*************************************<->*************************************
236 *
237 *  SetColormapFocus (pSD, pCD)
238 *
239 *
240 *  Description:
241 *  -----------
242 *  This function is used to set the colormap focus to a particular client
243 *  window or to clear the colormap focus (set focus to the root window).
244 *
245 *
246 *  Inputs:
247 *  ------
248 *  pSD = pointer to Screen Data
249 *  pCD = pointer to client data (clientColormap ...)
250 *
251 *************************************<->***********************************/
252
253#ifdef _NO_PROTO
254void SetColormapFocus (pSD, pCD)
255    WmScreenData *pSD;
256    ClientData *pCD;
257
258#else /* _NO_PROTO */
259void SetColormapFocus (WmScreenData *pSD, ClientData *pCD)
260#endif /* _NO_PROTO */
261{
262    if (pCD == pSD->colormapFocus)
263    {
264        /*
265         * The focus is already set to the right place.
266         */
267
268        return;
269    }
270#ifndef OLD_COLORMAP
271    ForceColormapFocus (pSD, pCD);
272#else /* OSF original */
273
274    if (pCD && ((pCD->clientState == NORMAL_STATE) ||
275                (pCD->clientState == MAXIMIZED_STATE)))
276    {
277        pSD->colormapFocus = pCD;
278#ifndef OLD_COLORMAP /* colormaps */
279        ProcessColormapList (pSD, pCD);
280#else /* OSF original */
281        WmInstallColormap (pSD, pCD->clientColormap);
282#endif
283    }
284    else
285    {
286        /*
287         * The default colormap is installed for minimized windows that have
288         * the colormap focus.
289         * !!! should colormaps be installed for icons with client      !!!
290         * !!! icon windows?  should the client colormap be installed ? !!!
291         */
292
293        pSD->colormapFocus = NULL;
294        WmInstallColormap (pSD, pSD->workspaceColormap);
295    }
296#endif
297
298} /* END OF FUNCTION SetColormapFocus */
299
300
301
302/*************************************<->*************************************
303 *
304 *  WmInstallColormap (pSD, colormap)
305 *
306 *
307 *  Description:
308 *  -----------
309 *  This function installs colormaps for the window manager.  It trys to be
310 *  intelligent and avoid unnecessary installations.  It assumes that no
311 *  other program is installing colormaps.
312 *
313 *
314 *  Inputs:
315 *  ------
316 *  pSD = ptr to screen data
317 *  colormap = the id for the colormap to be installed
318 *
319 *************************************<->***********************************/
320
321#ifdef _NO_PROTO
322void WmInstallColormap (pSD, colormap)
323    WmScreenData *pSD;
324    Colormap colormap;
325
326#else /* _NO_PROTO */
327void WmInstallColormap (WmScreenData *pSD, Colormap colormap)
328#endif /* _NO_PROTO */
329{
330    /*
331     * !!! this could be generalized to work better for systems that !!!
332     * !!! support multiple installed colormaps                      !!!
333     */
334
335    if (colormap != pSD->lastInstalledColormap)
336    {
337        XInstallColormap (DISPLAY, colormap);
338        pSD->lastInstalledColormap = colormap;
339    }
340
341} /* END OF FUNCTION WmInstallColormap */
342
343
344
345/*************************************<->*************************************
346 *
347 *  ResetColormapData (pCD, pWindows, count)
348 *
349 *
350 *  Description:
351 *  -----------
352 *  This function is used to release old colormap data (contexts, malloc'ed
353 *  space).
354 *
355 *
356 *  Inputs:
357 *  ------
358 *  pCD = pointer to client data (cmapWindows ...)
359 *
360 *  pWindows = new list of colormap windows
361 *
362 *  count = number of windows in new colormap windows list
363 *
364 *************************************<->***********************************/
365
366#ifdef _NO_PROTO
367void ResetColormapData (pCD, pWindows, count)
368    ClientData *pCD;
369    Window *pWindows;
370    int count;
371
372#else /* _NO_PROTO */
373void ResetColormapData (ClientData *pCD, Window *pWindows, int count)
374#endif /* _NO_PROTO */
375{
376    int i;
377
378
379    if (pCD->clientCmapCount)
380    {
381        if (count == 0)
382        {
383            /* reset the client colormap to the toplevel window colormap */
384            for (i = 0; i < pCD->clientCmapCount; i++)
385            {
386                if (pCD->cmapWindows[i] == pCD->client)
387                {
388                    pCD->clientColormap = pCD->clientCmapList[i];
389                    break;
390                }
391            }
392        }
393
394        /*
395         * Free up old contexts.
396         */
397
398        for (i = 0; i < pCD->clientCmapCount; i++)
399        {
400            if (pCD->cmapWindows[i] != pCD->client)
401            {
402                XDeleteContext (DISPLAY, pCD->cmapWindows[i],
403                    wmGD.windowContextType);
404            }
405        }
406
407        /*
408         * Free up old colormap data.
409         */
410
411        XtFree ((char *)(pCD->cmapWindows));
412        XtFree ((char *)(pCD->clientCmapList));
413        pCD->clientCmapCount = 0;
414#ifndef OLD_COLORMAP /* colormap */
415        XtFree ((char  *)(pCD->clientCmapFlags));
416        pCD->clientCmapFlags = 0;               /* DEBUG: */
417        pCD->clientCmapFlagsInitialized = 0;
418#endif
419    }
420
421    if (count)
422    {
423        /*
424         * Set new contexts.
425         */
426
427        for (i = 0; i < count; i++)
428        {
429            if (pWindows[i] != pCD->client)
430            {
431                XSaveContext (DISPLAY, pWindows[i], wmGD.windowContextType,
432                    (caddr_t)pCD);
433            }
434        }
435    }
436
437} /* END OF FUNCTION ResetColormapData */
438
439/*******************************************************************************
440 **
441 ** The rest of this module contains the SGI-added colormap handling.
442 **
443 ** mwm 1.1.3 didn't even try to deal with multiple colormaps, except to rotate
444 ** them.  We need to see that all of the colormaps from WM_COLORMAP_WINDOWS
445 ** are installed when a window gets colormap focus.
446 **
447 ** The general idea is to keep track of which colormaps bounce which other
448 ** ones, so we only flash the first time (usually not even then).
449 **
450 ** The conflict record of a window is cleared whenever:
451 **     * WM_COLORMAP_WINDOWS property changes
452 **     * ColormapNotify for a new colormap happens
453 **     * windows are rotated (prev_cmap, next_cmap)
454 ** This is because with a changed colormap list, we need to recalculate
455 ** which ones get bounced out during a full colormap installation.
456 **
457 ** We don't just lift the twm code because, after carefully looking over
458 ** the twm code, it appears to have some problems of its own.  In
459 ** particular, it assumes that if a given colormap displaces another one
460 ** once, it will always do so.  This isn't necessarily so for a multiple
461 ** hardware colormaps machine.
462 **
463 ** We still need to add code to keep track of which color maps are really
464 ** installed at any one time.  The current code is ready for this, but it has
465 ** not yet been done.  Then we could do two things:
466 **
467 **     * refrain from installing a colormap if it is already installed
468 **
469 **     * have a way to restore all installed colormaps after the window
470 **       manager overwrites with it's own.
471 **
472 ******************************************************************************/
473
474
475#ifdef _NO_PROTO
476void
477ProcessColormapList(pSD, pCD)
478        WmScreenData *pSD;
479        ClientData *pCD;
480#else /* _NO_PROTO */
481void
482ProcessColormapList (WmScreenData *pSD, ClientData *pCD)
483#endif /* _NO_PROTO */
484
485{
486        register int i;
487        XEvent event;
488
489
490    /*
491     * If there is no client, return.  This can happen when the root gets focus.
492     */
493        if (!pCD) return;
494
495    /*
496     * If the window does not have colormap focus, return.  We only install
497     * colormaps for windows with focus.  We'll get another chance when the
498     * window does get focus.
499     */
500        if (pCD != pSD->colormapFocus) return;
501
502    /*
503     * If window is iconified, return.
504     */
505        if (   (pCD->clientState != NORMAL_STATE)
506            && (pCD->clientState != MAXIMIZED_STATE)
507           ) return;
508
509    /*
510     * If the list doesn't exist, or has just a single item, no conflicts
511     * exist -- just go ahead and install the indicated colormap.
512     */
513        if (pCD->clientCmapCount == 0) {
514                WmInstallColormap (pSD, pCD->clientColormap);
515                return;
516        }
517        if (pCD->clientCmapCount == 1) {
518                WmInstallColormap (pSD, pCD->clientCmapList[0]);
519                return;
520        }
521
522    /*
523     * If the list has already been initialized, we just need to do installs.
524     * Separate out these loops for performance, and because it isn't nice
525     * to grab the server unnecessarily.
526     *
527     * This code should also check for already-installed, once we put in that
528     * capability.
529     */
530        if (pCD->clientCmapFlagsInitialized) {
531
532            /* Do the part between the index and zero */
533                for (i=pCD->clientCmapIndex; --i>=0; ) {
534                        if (pCD->clientCmapFlags[i] == ColormapInstalled) {
535                                WmInstallColormap (pSD, pCD->clientCmapList[i]);
536                           }
537                };
538       
539            /* Do the part from the end of the list to the index */
540                for (i=pCD->clientCmapCount; --i>= pCD->clientCmapIndex; ) {
541                        if (pCD->clientCmapFlags[i] == ColormapInstalled) {
542                                WmInstallColormap (pSD, pCD->clientCmapList[i]);
543                        }
544                }
545
546            /**/
547                return;
548        }
549
550    /*
551     * If we get this far, the list has not yet been initialized.
552     *
553     * Stabilize the input queue -- the issue is that we need to know
554     * which colormap notify install and uninstall events are ours.
555     */
556        XGrabServer (DISPLAY);  /* Ensure no one else's events for awhile */
557        XSync (DISPLAY, FALSE); /* Let pending events settle */
558        firstRequest = NextRequest (DISPLAY); /* First one that can be ours */
559
560    /*
561     * Install the colormaps from last to first -- first is the "highest
562     * priority".  "First" is pCD->clientCmapIndex.
563     *
564     * If the list has not been proocessed before, we need to unconditionally
565     * install each colormap.  Colormap flashing is possible this once.
566     *
567     * If the list has already been processed once, all conflict checking
568     * was done then.  All we need to do this time is to install the colormaps
569     * we know we need.
570     */
571
572        /* Do the part between the index and zero */
573        for (i=pCD->clientCmapIndex; --i>=0; ) {
574                WmInstallColormap (pSD, pCD->clientCmapList[i]);
575                pCD->clientCmapFlags[i] = ColormapInstalled;
576        };
577
578        /* Do the part from the end of the list to the index */
579        for (i=pCD->clientCmapCount; --i>= pCD->clientCmapIndex; ) {
580                WmInstallColormap (pSD, pCD->clientCmapList[i]);
581                pCD->clientCmapFlags[i] = ColormapInstalled;
582        }
583
584    /*
585     * Stabilize the input queue again -- the issue is that we need to know
586     * which colormap notify install and uninstall events we caused.
587     */
588        XSync (DISPLAY, FALSE);                 /* Let pending events settle */
589        lastRequest = NextRequest (DISPLAY);    /* Last one that can be ours */
590        XUngrabServer (DISPLAY);                /* Let others use it again */
591
592    /* Process the install & uninstall events */
593        XCheckIfEvent (DISPLAY, (XEvent *) &event, ProcessEvents, (char *)pCD);
594
595    /* Set that the list has been processed once */
596        pCD->clientCmapFlagsInitialized = True;
597}
598
599
600/*
601 * Look over the queue for install and uninstall events on colormap/window
602 * combinations we care about.  We don't actually disturb the queue, so
603 * events can be delivered in undisturbed order to the normal event handling
604 * routines.
605 *
606 * For each appropriate install/uninstall ColormapNotify event that is queued:
607 *         *) if uninstall event
608 *              *) Set the conflict flag for this colormap window
609 *         else if install event
610 *              *) Clear the conflict flag for this colormap window
611 */
612#ifdef _NO_PROTO
613static Bool
614ProcessEvents(dpy, Event, c_pCD)
615        Display        *dpy;
616        XEvent *Event;
617        char     *c_pCD;
618#else /* _NO_PROTO */
619static Bool
620ProcessEvents(Display *dpy, XEvent *Event, char *c_pCD)
621#endif /* _NO_PROTO */
622{
623        int i;
624        XColormapEvent *pEvent = (XColormapEvent *) Event;
625        ClientData *pCD = (ClientData *) c_pCD;
626
627        if (   (pEvent->type == ColormapNotify)
628            && (pEvent->serial >= firstRequest)
629            && (pEvent->serial <  lastRequest)
630            && (pEvent->colormap != None)
631            && (!pEvent->new)
632           ) {
633                switch (pEvent->state) {
634                case ColormapInstalled:
635                        for (i=0; i<pCD->clientCmapCount; i++) {
636                                if (  (pCD->clientCmapList[i]==pEvent->colormap)
637                                    &&(pCD->cmapWindows[i]==pEvent->window)
638                                   ) {
639                                        pCD->clientCmapFlags[i]
640                                                = ColormapInstalled;
641                                        break;
642                                }
643                        }
644                        break;
645                case ColormapUninstalled:
646                        for (i=0; i<pCD->clientCmapCount; i++) {
647                                if (  (pCD->clientCmapList[i]==pEvent->colormap)
648                                    &&(pCD->cmapWindows[i]==pEvent->window)
649                                   ) {
650                                        pCD->clientCmapFlags[i]
651                                                = ColormapUninstalled;
652                                        break;
653                                }
654                        }
655                        break;
656                default:                /* Should never get here */
657                        break;
658                }
659        }
660
661    /*
662     * Always return false:
663     *  * so that we get to search the entire queue -- it isn't very long
664     *  * so all events remain on the queue to be handled normally elsewhere
665     */
666        return False;   /* Always, so no events are lost from the queue */
667}
Note: See TracBrowser for help on using the repository browser.