xref: /OK3568_Linux_fs/external/xserver/dix/dixutils.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /***********************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1987, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun                         All Rights Reserved
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
30*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
31*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
32*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
33*4882a593Smuzhiyun supporting documentation, and that the name of Digital not be
34*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
35*4882a593Smuzhiyun software without specific, written prior permission.
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39*4882a593Smuzhiyun DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43*4882a593Smuzhiyun SOFTWARE.
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun ******************************************************************/
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun (c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved.
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sublicense this software and its
52*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted, provided that
53*4882a593Smuzhiyun the above copyright notices appear in all copies and that both those copyright
54*4882a593Smuzhiyun notices and this permission notice appear in supporting documentation and that
55*4882a593Smuzhiyun the name of Adobe Systems Incorporated not be used in advertising or publicity
56*4882a593Smuzhiyun pertaining to distribution of the software without specific, written prior
57*4882a593Smuzhiyun permission.  No trademark license to use the Adobe trademarks is hereby
58*4882a593Smuzhiyun granted.  If the Adobe trademark "Display PostScript"(tm) is used to describe
59*4882a593Smuzhiyun this software, its functionality or for any other purpose, such use shall be
60*4882a593Smuzhiyun limited to a statement that this software works in conjunction with the Display
61*4882a593Smuzhiyun PostScript system.  Proper trademark attribution to reflect Adobe's ownership
62*4882a593Smuzhiyun of the trademark shall be given whenever any such reference to the Display
63*4882a593Smuzhiyun PostScript system is made.
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
66*4882a593Smuzhiyun PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.  ADOBE
67*4882a593Smuzhiyun DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
68*4882a593Smuzhiyun WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
69*4882a593Smuzhiyun INFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
70*4882a593Smuzhiyun OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
71*4882a593Smuzhiyun DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
72*4882a593Smuzhiyun LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
73*4882a593Smuzhiyun PERFORMANCE OF THIS SOFTWARE.  ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
74*4882a593Smuzhiyun SUPPORT FOR THE SOFTWARE.
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
77*4882a593Smuzhiyun Incorporated which may be registered in certain jurisdictions.
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun Author:  Adobe Systems Incorporated
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun */
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
84*4882a593Smuzhiyun #include <dix-config.h>
85*4882a593Smuzhiyun #endif
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun #include <X11/X.h>
88*4882a593Smuzhiyun #include <X11/Xmd.h>
89*4882a593Smuzhiyun #include "misc.h"
90*4882a593Smuzhiyun #include "windowstr.h"
91*4882a593Smuzhiyun #include "dixstruct.h"
92*4882a593Smuzhiyun #include "pixmapstr.h"
93*4882a593Smuzhiyun #include "gcstruct.h"
94*4882a593Smuzhiyun #include "scrnintstr.h"
95*4882a593Smuzhiyun #define  XK_LATIN1
96*4882a593Smuzhiyun #include <X11/keysymdef.h>
97*4882a593Smuzhiyun #include "xace.h"
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun  * CompareTimeStamps returns -1, 0, or +1 depending on if the first
101*4882a593Smuzhiyun  * argument is less than, equal to or greater than the second argument.
102*4882a593Smuzhiyun  */
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun int
CompareTimeStamps(TimeStamp a,TimeStamp b)105*4882a593Smuzhiyun CompareTimeStamps(TimeStamp a, TimeStamp b)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun     if (a.months < b.months)
108*4882a593Smuzhiyun         return EARLIER;
109*4882a593Smuzhiyun     if (a.months > b.months)
110*4882a593Smuzhiyun         return LATER;
111*4882a593Smuzhiyun     if (a.milliseconds < b.milliseconds)
112*4882a593Smuzhiyun         return EARLIER;
113*4882a593Smuzhiyun     if (a.milliseconds > b.milliseconds)
114*4882a593Smuzhiyun         return LATER;
115*4882a593Smuzhiyun     return SAMETIME;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun /*
119*4882a593Smuzhiyun  * convert client times to server TimeStamps
120*4882a593Smuzhiyun  */
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun #define HALFMONTH ((unsigned long) 1<<31)
123*4882a593Smuzhiyun TimeStamp
ClientTimeToServerTime(CARD32 c)124*4882a593Smuzhiyun ClientTimeToServerTime(CARD32 c)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun     TimeStamp ts;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun     if (c == CurrentTime)
129*4882a593Smuzhiyun         return currentTime;
130*4882a593Smuzhiyun     ts.months = currentTime.months;
131*4882a593Smuzhiyun     ts.milliseconds = c;
132*4882a593Smuzhiyun     if (c > currentTime.milliseconds) {
133*4882a593Smuzhiyun         if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH)
134*4882a593Smuzhiyun             ts.months -= 1;
135*4882a593Smuzhiyun     }
136*4882a593Smuzhiyun     else if (c < currentTime.milliseconds) {
137*4882a593Smuzhiyun         if (((unsigned long) currentTime.milliseconds - c) > HALFMONTH)
138*4882a593Smuzhiyun             ts.months += 1;
139*4882a593Smuzhiyun     }
140*4882a593Smuzhiyun     return ts;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun /*
144*4882a593Smuzhiyun  * ISO Latin-1 case conversion routine
145*4882a593Smuzhiyun  *
146*4882a593Smuzhiyun  * this routine always null-terminates the result, so
147*4882a593Smuzhiyun  * beware of too-small buffers
148*4882a593Smuzhiyun  */
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun static unsigned char
ISOLatin1ToLower(unsigned char source)151*4882a593Smuzhiyun ISOLatin1ToLower(unsigned char source)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun     unsigned char dest;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun     if ((source >= XK_A) && (source <= XK_Z))
156*4882a593Smuzhiyun         dest = source + (XK_a - XK_A);
157*4882a593Smuzhiyun     else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis))
158*4882a593Smuzhiyun         dest = source + (XK_agrave - XK_Agrave);
159*4882a593Smuzhiyun     else if ((source >= XK_Ooblique) && (source <= XK_Thorn))
160*4882a593Smuzhiyun         dest = source + (XK_oslash - XK_Ooblique);
161*4882a593Smuzhiyun     else
162*4882a593Smuzhiyun         dest = source;
163*4882a593Smuzhiyun     return dest;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun int
CompareISOLatin1Lowered(const unsigned char * s1,int s1len,const unsigned char * s2,int s2len)167*4882a593Smuzhiyun CompareISOLatin1Lowered(const unsigned char *s1, int s1len,
168*4882a593Smuzhiyun                         const unsigned char *s2, int s2len)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun     unsigned char c1, c2;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun     for (;;) {
173*4882a593Smuzhiyun         /* note -- compare against zero so that -1 ignores len */
174*4882a593Smuzhiyun         c1 = s1len-- ? *s1++ : '\0';
175*4882a593Smuzhiyun         c2 = s2len-- ? *s2++ : '\0';
176*4882a593Smuzhiyun         if (!c1 ||
177*4882a593Smuzhiyun             (c1 != c2 &&
178*4882a593Smuzhiyun              (c1 = ISOLatin1ToLower(c1)) != (c2 = ISOLatin1ToLower(c2))))
179*4882a593Smuzhiyun             break;
180*4882a593Smuzhiyun     }
181*4882a593Smuzhiyun     return (int) c1 - (int) c2;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun /*
185*4882a593Smuzhiyun  * dixLookupWindow and dixLookupDrawable:
186*4882a593Smuzhiyun  * Look up the window/drawable taking into account the client doing the
187*4882a593Smuzhiyun  * lookup, the type of drawable desired, and the type of access desired.
188*4882a593Smuzhiyun  * Return Success with *pDraw set if the window/drawable exists and the client
189*4882a593Smuzhiyun  * is allowed access, else return an error code with *pDraw set to NULL.  The
190*4882a593Smuzhiyun  * access mask values are defined in resource.h.  The type mask values are
191*4882a593Smuzhiyun  * defined in pixmap.h, with zero equivalent to M_DRAWABLE.
192*4882a593Smuzhiyun  */
193*4882a593Smuzhiyun int
dixLookupDrawable(DrawablePtr * pDraw,XID id,ClientPtr client,Mask type,Mask access)194*4882a593Smuzhiyun dixLookupDrawable(DrawablePtr *pDraw, XID id, ClientPtr client,
195*4882a593Smuzhiyun                   Mask type, Mask access)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun     DrawablePtr pTmp;
198*4882a593Smuzhiyun     int rc;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun     *pDraw = NULL;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun     rc = dixLookupResourceByClass((void **) &pTmp, id, RC_DRAWABLE, client,
203*4882a593Smuzhiyun                                   access);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun     if (rc != Success)
206*4882a593Smuzhiyun         client->errorValue = id;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun     if (rc == BadValue)
209*4882a593Smuzhiyun         return BadDrawable;
210*4882a593Smuzhiyun     if (rc != Success)
211*4882a593Smuzhiyun         return rc;
212*4882a593Smuzhiyun     if (!((1 << pTmp->type) & (type ? type : M_DRAWABLE)))
213*4882a593Smuzhiyun         return BadMatch;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun     *pDraw = pTmp;
216*4882a593Smuzhiyun     return Success;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun int
dixLookupWindow(WindowPtr * pWin,XID id,ClientPtr client,Mask access)220*4882a593Smuzhiyun dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun     int rc;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun     rc = dixLookupDrawable((DrawablePtr *) pWin, id, client, M_WINDOW, access);
225*4882a593Smuzhiyun     /* dixLookupDrawable returns BadMatch iff id is a valid Drawable
226*4882a593Smuzhiyun        but is not a Window. Users of dixLookupWindow expect a BadWindow
227*4882a593Smuzhiyun        error in this case; they don't care that it's a valid non-Window XID */
228*4882a593Smuzhiyun     if (rc == BadMatch)
229*4882a593Smuzhiyun         rc = BadWindow;
230*4882a593Smuzhiyun     /* Similarly, users of dixLookupWindow don't want BadDrawable. */
231*4882a593Smuzhiyun     if (rc == BadDrawable)
232*4882a593Smuzhiyun         rc = BadWindow;
233*4882a593Smuzhiyun     return rc;
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun int
dixLookupGC(GCPtr * pGC,XID id,ClientPtr client,Mask access)237*4882a593Smuzhiyun dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun     return dixLookupResourceByType((void **) pGC, id, RT_GC, client, access);
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun int
dixLookupFontable(FontPtr * pFont,XID id,ClientPtr client,Mask access)243*4882a593Smuzhiyun dixLookupFontable(FontPtr *pFont, XID id, ClientPtr client, Mask access)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun     int rc;
246*4882a593Smuzhiyun     GC *pGC;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun     client->errorValue = id;    /* EITHER font or gc */
249*4882a593Smuzhiyun     rc = dixLookupResourceByType((void **) pFont, id, RT_FONT, client,
250*4882a593Smuzhiyun                                  access);
251*4882a593Smuzhiyun     if (rc != BadFont)
252*4882a593Smuzhiyun         return rc;
253*4882a593Smuzhiyun     rc = dixLookupResourceByType((void **) &pGC, id, RT_GC, client, access);
254*4882a593Smuzhiyun     if (rc == BadGC)
255*4882a593Smuzhiyun         return BadFont;
256*4882a593Smuzhiyun     if (rc == Success)
257*4882a593Smuzhiyun         *pFont = pGC->font;
258*4882a593Smuzhiyun     return rc;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun int
dixLookupClient(ClientPtr * pClient,XID rid,ClientPtr client,Mask access)262*4882a593Smuzhiyun dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun     void *pRes;
265*4882a593Smuzhiyun     int rc = BadValue, clientIndex = CLIENT_ID(rid);
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun     if (!clientIndex || !clients[clientIndex] || (rid & SERVER_BIT))
268*4882a593Smuzhiyun         goto bad;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun     rc = dixLookupResourceByClass(&pRes, rid, RC_ANY, client, DixGetAttrAccess);
271*4882a593Smuzhiyun     if (rc != Success)
272*4882a593Smuzhiyun         goto bad;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun     rc = XaceHook(XACE_CLIENT_ACCESS, client, clients[clientIndex], access);
275*4882a593Smuzhiyun     if (rc != Success)
276*4882a593Smuzhiyun         goto bad;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun     *pClient = clients[clientIndex];
279*4882a593Smuzhiyun     return Success;
280*4882a593Smuzhiyun  bad:
281*4882a593Smuzhiyun     if (client)
282*4882a593Smuzhiyun         client->errorValue = rid;
283*4882a593Smuzhiyun     *pClient = NULL;
284*4882a593Smuzhiyun     return rc;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun int
AlterSaveSetForClient(ClientPtr client,WindowPtr pWin,unsigned mode,Bool toRoot,Bool map)288*4882a593Smuzhiyun AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
289*4882a593Smuzhiyun                       Bool toRoot, Bool map)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun     int numnow;
292*4882a593Smuzhiyun     SaveSetElt *pTmp = NULL;
293*4882a593Smuzhiyun     int j;
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun     numnow = client->numSaved;
296*4882a593Smuzhiyun     j = 0;
297*4882a593Smuzhiyun     if (numnow) {
298*4882a593Smuzhiyun         pTmp = client->saveSet;
299*4882a593Smuzhiyun         while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (void *) pWin))
300*4882a593Smuzhiyun             j++;
301*4882a593Smuzhiyun     }
302*4882a593Smuzhiyun     if (mode == SetModeInsert) {
303*4882a593Smuzhiyun         if (j < numnow)         /* duplicate */
304*4882a593Smuzhiyun             return Success;
305*4882a593Smuzhiyun         numnow++;
306*4882a593Smuzhiyun         pTmp = (SaveSetElt *) realloc(client->saveSet, sizeof(*pTmp) * numnow);
307*4882a593Smuzhiyun         if (!pTmp)
308*4882a593Smuzhiyun             return BadAlloc;
309*4882a593Smuzhiyun         client->saveSet = pTmp;
310*4882a593Smuzhiyun         client->numSaved = numnow;
311*4882a593Smuzhiyun         SaveSetAssignWindow(client->saveSet[numnow - 1], pWin);
312*4882a593Smuzhiyun         SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot);
313*4882a593Smuzhiyun         SaveSetAssignMap(client->saveSet[numnow - 1], map);
314*4882a593Smuzhiyun         return Success;
315*4882a593Smuzhiyun     }
316*4882a593Smuzhiyun     else if ((mode == SetModeDelete) && (j < numnow)) {
317*4882a593Smuzhiyun         while (j < numnow - 1) {
318*4882a593Smuzhiyun             pTmp[j] = pTmp[j + 1];
319*4882a593Smuzhiyun             j++;
320*4882a593Smuzhiyun         }
321*4882a593Smuzhiyun         numnow--;
322*4882a593Smuzhiyun         if (numnow) {
323*4882a593Smuzhiyun             pTmp =
324*4882a593Smuzhiyun                 (SaveSetElt *) realloc(client->saveSet, sizeof(*pTmp) * numnow);
325*4882a593Smuzhiyun             if (pTmp)
326*4882a593Smuzhiyun                 client->saveSet = pTmp;
327*4882a593Smuzhiyun         }
328*4882a593Smuzhiyun         else {
329*4882a593Smuzhiyun             free(client->saveSet);
330*4882a593Smuzhiyun             client->saveSet = (SaveSetElt *) NULL;
331*4882a593Smuzhiyun         }
332*4882a593Smuzhiyun         client->numSaved = numnow;
333*4882a593Smuzhiyun         return Success;
334*4882a593Smuzhiyun     }
335*4882a593Smuzhiyun     return Success;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun void
DeleteWindowFromAnySaveSet(WindowPtr pWin)339*4882a593Smuzhiyun DeleteWindowFromAnySaveSet(WindowPtr pWin)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun     int i;
342*4882a593Smuzhiyun     ClientPtr client;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun     for (i = 0; i < currentMaxClients; i++) {
345*4882a593Smuzhiyun         client = clients[i];
346*4882a593Smuzhiyun         if (client && client->numSaved)
347*4882a593Smuzhiyun             (void) AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE,
348*4882a593Smuzhiyun                                          TRUE);
349*4882a593Smuzhiyun     }
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun /* No-op Don't Do Anything : sometimes we need to be able to call a procedure
353*4882a593Smuzhiyun  * that doesn't do anything.  For example, on screen with only static
354*4882a593Smuzhiyun  * colormaps, if someone calls install colormap, it's easier to have a dummy
355*4882a593Smuzhiyun  * procedure to call than to check if there's a procedure
356*4882a593Smuzhiyun  */
357*4882a593Smuzhiyun void
NoopDDA(void)358*4882a593Smuzhiyun NoopDDA(void)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun typedef struct _BlockHandler {
363*4882a593Smuzhiyun     ServerBlockHandlerProcPtr BlockHandler;
364*4882a593Smuzhiyun     ServerWakeupHandlerProcPtr WakeupHandler;
365*4882a593Smuzhiyun     void *blockData;
366*4882a593Smuzhiyun     Bool deleted;
367*4882a593Smuzhiyun } BlockHandlerRec, *BlockHandlerPtr;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun static BlockHandlerPtr handlers;
370*4882a593Smuzhiyun static int numHandlers;
371*4882a593Smuzhiyun static int sizeHandlers;
372*4882a593Smuzhiyun static Bool inHandler;
373*4882a593Smuzhiyun static Bool handlerDeleted;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun /**
376*4882a593Smuzhiyun  *
377*4882a593Smuzhiyun  *  \param pTimeout   DIX doesn't want to know how OS represents time
378*4882a593Smuzhiyun  *  \param pReadMask  nor how it represents the det of descriptors
379*4882a593Smuzhiyun  */
380*4882a593Smuzhiyun void
BlockHandler(void * pTimeout)381*4882a593Smuzhiyun BlockHandler(void *pTimeout)
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun     int i, j;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun     ++inHandler;
386*4882a593Smuzhiyun     for (i = 0; i < numHandlers; i++)
387*4882a593Smuzhiyun         if (!handlers[i].deleted)
388*4882a593Smuzhiyun             (*handlers[i].BlockHandler) (handlers[i].blockData, pTimeout);
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numGPUScreens; i++)
391*4882a593Smuzhiyun         (*screenInfo.gpuscreens[i]->BlockHandler) (screenInfo.gpuscreens[i], pTimeout);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numScreens; i++)
394*4882a593Smuzhiyun         (*screenInfo.screens[i]->BlockHandler) (screenInfo.screens[i], pTimeout);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun     if (handlerDeleted) {
397*4882a593Smuzhiyun         for (i = 0; i < numHandlers;)
398*4882a593Smuzhiyun             if (handlers[i].deleted) {
399*4882a593Smuzhiyun                 for (j = i; j < numHandlers - 1; j++)
400*4882a593Smuzhiyun                     handlers[j] = handlers[j + 1];
401*4882a593Smuzhiyun                 numHandlers--;
402*4882a593Smuzhiyun             }
403*4882a593Smuzhiyun             else
404*4882a593Smuzhiyun                 i++;
405*4882a593Smuzhiyun         handlerDeleted = FALSE;
406*4882a593Smuzhiyun     }
407*4882a593Smuzhiyun     --inHandler;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun /**
411*4882a593Smuzhiyun  *
412*4882a593Smuzhiyun  *  \param result    32 bits of undefined result from the wait
413*4882a593Smuzhiyun  *  \param pReadmask the resulting descriptor mask
414*4882a593Smuzhiyun  */
415*4882a593Smuzhiyun void
WakeupHandler(int result)416*4882a593Smuzhiyun WakeupHandler(int result)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun     int i, j;
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun     ++inHandler;
421*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numScreens; i++)
422*4882a593Smuzhiyun         (*screenInfo.screens[i]->WakeupHandler) (screenInfo.screens[i], result);
423*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numGPUScreens; i++)
424*4882a593Smuzhiyun         (*screenInfo.gpuscreens[i]->WakeupHandler) (screenInfo.gpuscreens[i], result);
425*4882a593Smuzhiyun     for (i = numHandlers - 1; i >= 0; i--)
426*4882a593Smuzhiyun         if (!handlers[i].deleted)
427*4882a593Smuzhiyun             (*handlers[i].WakeupHandler) (handlers[i].blockData, result);
428*4882a593Smuzhiyun     if (handlerDeleted) {
429*4882a593Smuzhiyun         for (i = 0; i < numHandlers;)
430*4882a593Smuzhiyun             if (handlers[i].deleted) {
431*4882a593Smuzhiyun                 for (j = i; j < numHandlers - 1; j++)
432*4882a593Smuzhiyun                     handlers[j] = handlers[j + 1];
433*4882a593Smuzhiyun                 numHandlers--;
434*4882a593Smuzhiyun             }
435*4882a593Smuzhiyun             else
436*4882a593Smuzhiyun                 i++;
437*4882a593Smuzhiyun         handlerDeleted = FALSE;
438*4882a593Smuzhiyun     }
439*4882a593Smuzhiyun     --inHandler;
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun /**
443*4882a593Smuzhiyun  * Reentrant with BlockHandler and WakeupHandler, except wakeup won't
444*4882a593Smuzhiyun  * get called until next time
445*4882a593Smuzhiyun  */
446*4882a593Smuzhiyun Bool
RegisterBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler,ServerWakeupHandlerProcPtr wakeupHandler,void * blockData)447*4882a593Smuzhiyun RegisterBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler,
448*4882a593Smuzhiyun                                ServerWakeupHandlerProcPtr wakeupHandler,
449*4882a593Smuzhiyun                                void *blockData)
450*4882a593Smuzhiyun {
451*4882a593Smuzhiyun     BlockHandlerPtr new;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun     if (numHandlers >= sizeHandlers) {
454*4882a593Smuzhiyun         new = (BlockHandlerPtr) realloc(handlers, (numHandlers + 1) *
455*4882a593Smuzhiyun                                         sizeof(BlockHandlerRec));
456*4882a593Smuzhiyun         if (!new)
457*4882a593Smuzhiyun             return FALSE;
458*4882a593Smuzhiyun         handlers = new;
459*4882a593Smuzhiyun         sizeHandlers = numHandlers + 1;
460*4882a593Smuzhiyun     }
461*4882a593Smuzhiyun     handlers[numHandlers].BlockHandler = blockHandler;
462*4882a593Smuzhiyun     handlers[numHandlers].WakeupHandler = wakeupHandler;
463*4882a593Smuzhiyun     handlers[numHandlers].blockData = blockData;
464*4882a593Smuzhiyun     handlers[numHandlers].deleted = FALSE;
465*4882a593Smuzhiyun     numHandlers = numHandlers + 1;
466*4882a593Smuzhiyun     return TRUE;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun void
RemoveBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler,ServerWakeupHandlerProcPtr wakeupHandler,void * blockData)470*4882a593Smuzhiyun RemoveBlockAndWakeupHandlers(ServerBlockHandlerProcPtr blockHandler,
471*4882a593Smuzhiyun                              ServerWakeupHandlerProcPtr wakeupHandler,
472*4882a593Smuzhiyun                              void *blockData)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun     int i;
475*4882a593Smuzhiyun 
476*4882a593Smuzhiyun     for (i = 0; i < numHandlers; i++)
477*4882a593Smuzhiyun         if (handlers[i].BlockHandler == blockHandler &&
478*4882a593Smuzhiyun             handlers[i].WakeupHandler == wakeupHandler &&
479*4882a593Smuzhiyun             handlers[i].blockData == blockData) {
480*4882a593Smuzhiyun             if (inHandler) {
481*4882a593Smuzhiyun                 handlerDeleted = TRUE;
482*4882a593Smuzhiyun                 handlers[i].deleted = TRUE;
483*4882a593Smuzhiyun             }
484*4882a593Smuzhiyun             else {
485*4882a593Smuzhiyun                 for (; i < numHandlers - 1; i++)
486*4882a593Smuzhiyun                     handlers[i] = handlers[i + 1];
487*4882a593Smuzhiyun                 numHandlers--;
488*4882a593Smuzhiyun             }
489*4882a593Smuzhiyun             break;
490*4882a593Smuzhiyun         }
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun void
InitBlockAndWakeupHandlers(void)494*4882a593Smuzhiyun InitBlockAndWakeupHandlers(void)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun     free(handlers);
497*4882a593Smuzhiyun     handlers = (BlockHandlerPtr) 0;
498*4882a593Smuzhiyun     numHandlers = 0;
499*4882a593Smuzhiyun     sizeHandlers = 0;
500*4882a593Smuzhiyun }
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun /*
503*4882a593Smuzhiyun  * A general work queue.  Perform some task before the server
504*4882a593Smuzhiyun  * sleeps for input.
505*4882a593Smuzhiyun  */
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun WorkQueuePtr workQueue;
508*4882a593Smuzhiyun static WorkQueuePtr *workQueueLast = &workQueue;
509*4882a593Smuzhiyun 
510*4882a593Smuzhiyun void
ClearWorkQueue(void)511*4882a593Smuzhiyun ClearWorkQueue(void)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun     WorkQueuePtr q, *p;
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun     p = &workQueue;
516*4882a593Smuzhiyun     while ((q = *p)) {
517*4882a593Smuzhiyun         *p = q->next;
518*4882a593Smuzhiyun         free(q);
519*4882a593Smuzhiyun     }
520*4882a593Smuzhiyun     workQueueLast = p;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun void
ProcessWorkQueue(void)524*4882a593Smuzhiyun ProcessWorkQueue(void)
525*4882a593Smuzhiyun {
526*4882a593Smuzhiyun     WorkQueuePtr q, *p;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun     p = &workQueue;
529*4882a593Smuzhiyun     /*
530*4882a593Smuzhiyun      * Scan the work queue once, calling each function.  Those
531*4882a593Smuzhiyun      * which return TRUE are removed from the queue, otherwise
532*4882a593Smuzhiyun      * they will be called again.  This must be reentrant with
533*4882a593Smuzhiyun      * QueueWorkProc.
534*4882a593Smuzhiyun      */
535*4882a593Smuzhiyun     while ((q = *p)) {
536*4882a593Smuzhiyun         if ((*q->function) (q->client, q->closure)) {
537*4882a593Smuzhiyun             /* remove q from the list */
538*4882a593Smuzhiyun             *p = q->next;       /* don't fetch until after func called */
539*4882a593Smuzhiyun             free(q);
540*4882a593Smuzhiyun         }
541*4882a593Smuzhiyun         else {
542*4882a593Smuzhiyun             p = &q->next;       /* don't fetch until after func called */
543*4882a593Smuzhiyun         }
544*4882a593Smuzhiyun     }
545*4882a593Smuzhiyun     workQueueLast = p;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun void
ProcessWorkQueueZombies(void)549*4882a593Smuzhiyun ProcessWorkQueueZombies(void)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun     WorkQueuePtr q, *p;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun     p = &workQueue;
554*4882a593Smuzhiyun     while ((q = *p)) {
555*4882a593Smuzhiyun         if (q->client && q->client->clientGone) {
556*4882a593Smuzhiyun             (void) (*q->function) (q->client, q->closure);
557*4882a593Smuzhiyun             /* remove q from the list */
558*4882a593Smuzhiyun             *p = q->next;       /* don't fetch until after func called */
559*4882a593Smuzhiyun             free(q);
560*4882a593Smuzhiyun         }
561*4882a593Smuzhiyun         else {
562*4882a593Smuzhiyun             p = &q->next;       /* don't fetch until after func called */
563*4882a593Smuzhiyun         }
564*4882a593Smuzhiyun     }
565*4882a593Smuzhiyun     workQueueLast = p;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun Bool
QueueWorkProc(Bool (* function)(ClientPtr pClient,void * closure),ClientPtr client,void * closure)569*4882a593Smuzhiyun QueueWorkProc(Bool (*function) (ClientPtr pClient, void *closure),
570*4882a593Smuzhiyun               ClientPtr client, void *closure)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun     WorkQueuePtr q;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun     q = malloc(sizeof *q);
575*4882a593Smuzhiyun     if (!q)
576*4882a593Smuzhiyun         return FALSE;
577*4882a593Smuzhiyun     q->function = function;
578*4882a593Smuzhiyun     q->client = client;
579*4882a593Smuzhiyun     q->closure = closure;
580*4882a593Smuzhiyun     q->next = NULL;
581*4882a593Smuzhiyun     *workQueueLast = q;
582*4882a593Smuzhiyun     workQueueLast = &q->next;
583*4882a593Smuzhiyun     return TRUE;
584*4882a593Smuzhiyun }
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun /*
587*4882a593Smuzhiyun  * Manage a queue of sleeping clients, awakening them
588*4882a593Smuzhiyun  * when requested, by using the OS functions IgnoreClient
589*4882a593Smuzhiyun  * and AttendClient.  Note that this *ignores* the troubles
590*4882a593Smuzhiyun  * with request data interleaving itself with events, but
591*4882a593Smuzhiyun  * we'll leave that until a later time.
592*4882a593Smuzhiyun  */
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun typedef struct _SleepQueue {
595*4882a593Smuzhiyun     struct _SleepQueue *next;
596*4882a593Smuzhiyun     ClientPtr client;
597*4882a593Smuzhiyun     ClientSleepProcPtr function;
598*4882a593Smuzhiyun     void *closure;
599*4882a593Smuzhiyun } SleepQueueRec, *SleepQueuePtr;
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun static SleepQueuePtr sleepQueue = NULL;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun Bool
ClientSleep(ClientPtr client,ClientSleepProcPtr function,void * closure)604*4882a593Smuzhiyun ClientSleep(ClientPtr client, ClientSleepProcPtr function, void *closure)
605*4882a593Smuzhiyun {
606*4882a593Smuzhiyun     SleepQueuePtr q;
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun     q = malloc(sizeof *q);
609*4882a593Smuzhiyun     if (!q)
610*4882a593Smuzhiyun         return FALSE;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun     IgnoreClient(client);
613*4882a593Smuzhiyun     q->next = sleepQueue;
614*4882a593Smuzhiyun     q->client = client;
615*4882a593Smuzhiyun     q->function = function;
616*4882a593Smuzhiyun     q->closure = closure;
617*4882a593Smuzhiyun     sleepQueue = q;
618*4882a593Smuzhiyun     return TRUE;
619*4882a593Smuzhiyun }
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun Bool
ClientSignal(ClientPtr client)622*4882a593Smuzhiyun ClientSignal(ClientPtr client)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun     SleepQueuePtr q;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun     for (q = sleepQueue; q; q = q->next)
627*4882a593Smuzhiyun         if (q->client == client) {
628*4882a593Smuzhiyun             return QueueWorkProc(q->function, q->client, q->closure);
629*4882a593Smuzhiyun         }
630*4882a593Smuzhiyun     return FALSE;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun int
ClientSignalAll(ClientPtr client,ClientSleepProcPtr function,void * closure)634*4882a593Smuzhiyun ClientSignalAll(ClientPtr client, ClientSleepProcPtr function, void *closure)
635*4882a593Smuzhiyun {
636*4882a593Smuzhiyun     SleepQueuePtr q;
637*4882a593Smuzhiyun     int count = 0;
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun     for (q = sleepQueue; q; q = q->next) {
640*4882a593Smuzhiyun         if (!(client == CLIENT_SIGNAL_ANY || q->client == client))
641*4882a593Smuzhiyun             continue;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun         if (!(function == CLIENT_SIGNAL_ANY || q->function == function))
644*4882a593Smuzhiyun             continue;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun         if (!(closure == CLIENT_SIGNAL_ANY || q->closure == closure))
647*4882a593Smuzhiyun             continue;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun         count += QueueWorkProc(q->function, q->client, q->closure);
650*4882a593Smuzhiyun     }
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun     return count;
653*4882a593Smuzhiyun }
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun void
ClientWakeup(ClientPtr client)656*4882a593Smuzhiyun ClientWakeup(ClientPtr client)
657*4882a593Smuzhiyun {
658*4882a593Smuzhiyun     SleepQueuePtr q, *prev;
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun     prev = &sleepQueue;
661*4882a593Smuzhiyun     while ((q = *prev)) {
662*4882a593Smuzhiyun         if (q->client == client) {
663*4882a593Smuzhiyun             *prev = q->next;
664*4882a593Smuzhiyun             free(q);
665*4882a593Smuzhiyun             AttendClient(client);
666*4882a593Smuzhiyun             break;
667*4882a593Smuzhiyun         }
668*4882a593Smuzhiyun         prev = &q->next;
669*4882a593Smuzhiyun     }
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun Bool
ClientIsAsleep(ClientPtr client)673*4882a593Smuzhiyun ClientIsAsleep(ClientPtr client)
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun     SleepQueuePtr q;
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun     for (q = sleepQueue; q; q = q->next)
678*4882a593Smuzhiyun         if (q->client == client)
679*4882a593Smuzhiyun             return TRUE;
680*4882a593Smuzhiyun     return FALSE;
681*4882a593Smuzhiyun }
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun /*
684*4882a593Smuzhiyun  *  Generic Callback Manager
685*4882a593Smuzhiyun  */
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun /* ===== Private Procedures ===== */
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun static int numCallbackListsToCleanup = 0;
690*4882a593Smuzhiyun static CallbackListPtr **listsToCleanup = NULL;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun static Bool
_AddCallback(CallbackListPtr * pcbl,CallbackProcPtr callback,void * data)693*4882a593Smuzhiyun _AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun     CallbackPtr cbr;
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun     cbr = malloc(sizeof(CallbackRec));
698*4882a593Smuzhiyun     if (!cbr)
699*4882a593Smuzhiyun         return FALSE;
700*4882a593Smuzhiyun     cbr->proc = callback;
701*4882a593Smuzhiyun     cbr->data = data;
702*4882a593Smuzhiyun     cbr->next = (*pcbl)->list;
703*4882a593Smuzhiyun     cbr->deleted = FALSE;
704*4882a593Smuzhiyun     (*pcbl)->list = cbr;
705*4882a593Smuzhiyun     return TRUE;
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun static Bool
_DeleteCallback(CallbackListPtr * pcbl,CallbackProcPtr callback,void * data)709*4882a593Smuzhiyun _DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data)
710*4882a593Smuzhiyun {
711*4882a593Smuzhiyun     CallbackListPtr cbl = *pcbl;
712*4882a593Smuzhiyun     CallbackPtr cbr, pcbr;
713*4882a593Smuzhiyun 
714*4882a593Smuzhiyun     for (pcbr = NULL, cbr = cbl->list; cbr != NULL; pcbr = cbr, cbr = cbr->next) {
715*4882a593Smuzhiyun         if ((cbr->proc == callback) && (cbr->data == data))
716*4882a593Smuzhiyun             break;
717*4882a593Smuzhiyun     }
718*4882a593Smuzhiyun     if (cbr != NULL) {
719*4882a593Smuzhiyun         if (cbl->inCallback) {
720*4882a593Smuzhiyun             ++(cbl->numDeleted);
721*4882a593Smuzhiyun             cbr->deleted = TRUE;
722*4882a593Smuzhiyun         }
723*4882a593Smuzhiyun         else {
724*4882a593Smuzhiyun             if (pcbr == NULL)
725*4882a593Smuzhiyun                 cbl->list = cbr->next;
726*4882a593Smuzhiyun             else
727*4882a593Smuzhiyun                 pcbr->next = cbr->next;
728*4882a593Smuzhiyun             free(cbr);
729*4882a593Smuzhiyun         }
730*4882a593Smuzhiyun         return TRUE;
731*4882a593Smuzhiyun     }
732*4882a593Smuzhiyun     return FALSE;
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun void
_CallCallbacks(CallbackListPtr * pcbl,void * call_data)736*4882a593Smuzhiyun _CallCallbacks(CallbackListPtr *pcbl, void *call_data)
737*4882a593Smuzhiyun {
738*4882a593Smuzhiyun     CallbackListPtr cbl = *pcbl;
739*4882a593Smuzhiyun     CallbackPtr cbr, pcbr;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun     ++(cbl->inCallback);
742*4882a593Smuzhiyun     for (cbr = cbl->list; cbr != NULL; cbr = cbr->next) {
743*4882a593Smuzhiyun         (*(cbr->proc)) (pcbl, cbr->data, call_data);
744*4882a593Smuzhiyun     }
745*4882a593Smuzhiyun     --(cbl->inCallback);
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun     if (cbl->inCallback)
748*4882a593Smuzhiyun         return;
749*4882a593Smuzhiyun 
750*4882a593Smuzhiyun     /* Was the entire list marked for deletion? */
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun     if (cbl->deleted) {
753*4882a593Smuzhiyun         DeleteCallbackList(pcbl);
754*4882a593Smuzhiyun         return;
755*4882a593Smuzhiyun     }
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun     /* Were some individual callbacks on the list marked for deletion?
758*4882a593Smuzhiyun      * If so, do the deletions.
759*4882a593Smuzhiyun      */
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun     if (cbl->numDeleted) {
762*4882a593Smuzhiyun         for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted;) {
763*4882a593Smuzhiyun             if (cbr->deleted) {
764*4882a593Smuzhiyun                 if (pcbr) {
765*4882a593Smuzhiyun                     cbr = cbr->next;
766*4882a593Smuzhiyun                     free(pcbr->next);
767*4882a593Smuzhiyun                     pcbr->next = cbr;
768*4882a593Smuzhiyun                 }
769*4882a593Smuzhiyun                 else {
770*4882a593Smuzhiyun                     cbr = cbr->next;
771*4882a593Smuzhiyun                     free(cbl->list);
772*4882a593Smuzhiyun                     cbl->list = cbr;
773*4882a593Smuzhiyun                 }
774*4882a593Smuzhiyun                 cbl->numDeleted--;
775*4882a593Smuzhiyun             }
776*4882a593Smuzhiyun             else {              /* this one wasn't deleted */
777*4882a593Smuzhiyun 
778*4882a593Smuzhiyun                 pcbr = cbr;
779*4882a593Smuzhiyun                 cbr = cbr->next;
780*4882a593Smuzhiyun             }
781*4882a593Smuzhiyun         }
782*4882a593Smuzhiyun     }
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun static void
_DeleteCallbackList(CallbackListPtr * pcbl)786*4882a593Smuzhiyun _DeleteCallbackList(CallbackListPtr *pcbl)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun     CallbackListPtr cbl = *pcbl;
789*4882a593Smuzhiyun     CallbackPtr cbr, nextcbr;
790*4882a593Smuzhiyun     int i;
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun     if (cbl->inCallback) {
793*4882a593Smuzhiyun         cbl->deleted = TRUE;
794*4882a593Smuzhiyun         return;
795*4882a593Smuzhiyun     }
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun     for (i = 0; i < numCallbackListsToCleanup; i++) {
798*4882a593Smuzhiyun         if (listsToCleanup[i] == pcbl) {
799*4882a593Smuzhiyun             listsToCleanup[i] = NULL;
800*4882a593Smuzhiyun             break;
801*4882a593Smuzhiyun         }
802*4882a593Smuzhiyun     }
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun     for (cbr = cbl->list; cbr != NULL; cbr = nextcbr) {
805*4882a593Smuzhiyun         nextcbr = cbr->next;
806*4882a593Smuzhiyun         free(cbr);
807*4882a593Smuzhiyun     }
808*4882a593Smuzhiyun     free(cbl);
809*4882a593Smuzhiyun     *pcbl = NULL;
810*4882a593Smuzhiyun }
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun static Bool
CreateCallbackList(CallbackListPtr * pcbl)813*4882a593Smuzhiyun CreateCallbackList(CallbackListPtr *pcbl)
814*4882a593Smuzhiyun {
815*4882a593Smuzhiyun     CallbackListPtr cbl;
816*4882a593Smuzhiyun     int i;
817*4882a593Smuzhiyun 
818*4882a593Smuzhiyun     if (!pcbl)
819*4882a593Smuzhiyun         return FALSE;
820*4882a593Smuzhiyun     cbl = malloc(sizeof(CallbackListRec));
821*4882a593Smuzhiyun     if (!cbl)
822*4882a593Smuzhiyun         return FALSE;
823*4882a593Smuzhiyun     cbl->inCallback = 0;
824*4882a593Smuzhiyun     cbl->deleted = FALSE;
825*4882a593Smuzhiyun     cbl->numDeleted = 0;
826*4882a593Smuzhiyun     cbl->list = NULL;
827*4882a593Smuzhiyun     *pcbl = cbl;
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun     for (i = 0; i < numCallbackListsToCleanup; i++) {
830*4882a593Smuzhiyun         if (!listsToCleanup[i]) {
831*4882a593Smuzhiyun             listsToCleanup[i] = pcbl;
832*4882a593Smuzhiyun             return TRUE;
833*4882a593Smuzhiyun         }
834*4882a593Smuzhiyun     }
835*4882a593Smuzhiyun 
836*4882a593Smuzhiyun     listsToCleanup = (CallbackListPtr **) xnfrealloc(listsToCleanup,
837*4882a593Smuzhiyun                                                      sizeof(CallbackListPtr *) *
838*4882a593Smuzhiyun                                                      (numCallbackListsToCleanup
839*4882a593Smuzhiyun                                                       + 1));
840*4882a593Smuzhiyun     listsToCleanup[numCallbackListsToCleanup] = pcbl;
841*4882a593Smuzhiyun     numCallbackListsToCleanup++;
842*4882a593Smuzhiyun     return TRUE;
843*4882a593Smuzhiyun }
844*4882a593Smuzhiyun 
845*4882a593Smuzhiyun /* ===== Public Procedures ===== */
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun Bool
AddCallback(CallbackListPtr * pcbl,CallbackProcPtr callback,void * data)848*4882a593Smuzhiyun AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data)
849*4882a593Smuzhiyun {
850*4882a593Smuzhiyun     if (!pcbl)
851*4882a593Smuzhiyun         return FALSE;
852*4882a593Smuzhiyun     if (!*pcbl) {               /* list hasn't been created yet; go create it */
853*4882a593Smuzhiyun         if (!CreateCallbackList(pcbl))
854*4882a593Smuzhiyun             return FALSE;
855*4882a593Smuzhiyun     }
856*4882a593Smuzhiyun     return _AddCallback(pcbl, callback, data);
857*4882a593Smuzhiyun }
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun Bool
DeleteCallback(CallbackListPtr * pcbl,CallbackProcPtr callback,void * data)860*4882a593Smuzhiyun DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, void *data)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun     if (!pcbl || !*pcbl)
863*4882a593Smuzhiyun         return FALSE;
864*4882a593Smuzhiyun     return _DeleteCallback(pcbl, callback, data);
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun void
DeleteCallbackList(CallbackListPtr * pcbl)868*4882a593Smuzhiyun DeleteCallbackList(CallbackListPtr *pcbl)
869*4882a593Smuzhiyun {
870*4882a593Smuzhiyun     if (!pcbl || !*pcbl)
871*4882a593Smuzhiyun         return;
872*4882a593Smuzhiyun     _DeleteCallbackList(pcbl);
873*4882a593Smuzhiyun }
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun void
DeleteCallbackManager(void)876*4882a593Smuzhiyun DeleteCallbackManager(void)
877*4882a593Smuzhiyun {
878*4882a593Smuzhiyun     int i;
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun     for (i = 0; i < numCallbackListsToCleanup; i++) {
881*4882a593Smuzhiyun         DeleteCallbackList(listsToCleanup[i]);
882*4882a593Smuzhiyun     }
883*4882a593Smuzhiyun     free(listsToCleanup);
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun     numCallbackListsToCleanup = 0;
886*4882a593Smuzhiyun     listsToCleanup = NULL;
887*4882a593Smuzhiyun }
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun void
InitCallbackManager(void)890*4882a593Smuzhiyun InitCallbackManager(void)
891*4882a593Smuzhiyun {
892*4882a593Smuzhiyun     DeleteCallbackManager();
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun /**
896*4882a593Smuzhiyun  * Coordinates the global GL context used by modules in the X Server
897*4882a593Smuzhiyun  * doing rendering with OpenGL.
898*4882a593Smuzhiyun  *
899*4882a593Smuzhiyun  * When setting a GL context (glXMakeCurrent() or eglMakeCurrent()),
900*4882a593Smuzhiyun  * there is an expensive implied glFlush() required by the GLX and EGL
901*4882a593Smuzhiyun  * APIs, so modules don't want to have to do it on every request.  But
902*4882a593Smuzhiyun  * the individual modules using GL also don't know about each other,
903*4882a593Smuzhiyun  * so they have to coordinate who owns the current context.
904*4882a593Smuzhiyun  *
905*4882a593Smuzhiyun  * When you're about to do a MakeCurrent, you should set this variable
906*4882a593Smuzhiyun  * to your context's address, and you can skip MakeCurrent if it's
907*4882a593Smuzhiyun  * already set to yours.
908*4882a593Smuzhiyun  *
909*4882a593Smuzhiyun  * When you're about to do a DestroyContext, you should set this to
910*4882a593Smuzhiyun  * NULL if it's set to your context.
911*4882a593Smuzhiyun  *
912*4882a593Smuzhiyun  * When you're about to do an unbindContext on a DRI driver, you
913*4882a593Smuzhiyun  * should set this to NULL.  Despite the unbindContext interface
914*4882a593Smuzhiyun  * sounding like it only unbinds the passed in context, it actually
915*4882a593Smuzhiyun  * unconditionally clears the dispatch table even if the given
916*4882a593Smuzhiyun  * context wasn't current.
917*4882a593Smuzhiyun  */
918*4882a593Smuzhiyun void *lastGLContext = NULL;
919