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