]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/Xext/appgroup.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / Xext / appgroup.c
1 /*
2 Copyright (c) 1996  X Consortium
3
4 Permission is hereby granted, free of charge, to any person obtaining
5 a copy of this software and associated documentation files (the
6 "Software"), to deal in the Software without restriction, including
7 without limitation the rights to use, copy, modify, merge, publish,
8 distribute, sublicense, and sell copies of the Software, and to
9 permit persons to whom the Software is furnished to do so, subject to
10 the following conditions:
11
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
22
23 Except as contained in this notice, the name of the X Consortium shall
24 not be used in advertising or otherwise to promote the sale, use or
25 other dealings in this Software without prior written authorization
26 from the X Consortium.
27 */
28 /* $XConsortium: appgroup.c /main/20 1996/12/08 16:14:27 kaleb $ */
29
30 #define NEED_REPLIES
31 #define NEED_EVENTS
32 #include "X.h"
33 #include "Xproto.h"
34 #include "misc.h"
35 #include "dixstruct.h"
36 #include "extnsionst.h"
37 #include "scrnintstr.h"
38 #include "windowstr.h"
39 #include "colormapst.h"
40 #include "servermd.h"
41 #define _XAG_SERVER_
42 #include "Xagstr.h"
43 #define _SECURITY_SERVER
44 #include "security.h"
45 #include "Xfuncproto.h"
46
47 #define XSERV_t
48 #include <X11/Xtrans.h>
49 #include "../os/osdep.h"
50
51 #include <stdio.h>
52
53 typedef struct _AppGroupRec {
54     struct _AppGroupRec* next;
55     XID                 appgroupId;
56     ClientPtr*          clients;
57     int                 nclients;
58     ClientPtr           leader;
59     Bool                single_screen;
60     Window              default_root;
61     VisualID            root_visual;
62     Colormap            default_colormap;    
63     Pixel               black_pixel;
64     Pixel               white_pixel;
65     xConnSetupPrefix    connSetupPrefix;
66     char*               ConnectionInfo;
67 } AppGroupRec, *AppGroupPtr;
68
69 static int              ProcXagDispatch (), SProcXagDispatch ();
70 static void             XagResetProc ();
71
72 static unsigned char    XagReqCode = 0;
73 static int              XagErrorBase;
74 static int              XagCallbackRefCount = 0;
75
76 static RESTYPE          RT_APPGROUP;
77 static AppGroupPtr      appGrpList = NULL;
78
79 extern WindowPtr* WindowTable;
80 extern xConnSetupPrefix connSetupPrefix;
81 extern char* ConnectionInfo;
82
83 static 
84 int XagAppGroupFree (what, id)
85     pointer what;
86     XID id; /* unused */
87 {
88     int i;
89     AppGroupPtr pAppGrp = (AppGroupPtr) what;
90
91     if (pAppGrp->leader)
92         for (i = 0; i < pAppGrp->nclients; i++) {
93             pAppGrp->clients[i]->appgroup = NULL;
94             CloseDownClient (pAppGrp->clients[i]);
95         }
96
97     if (pAppGrp == appGrpList)
98         appGrpList = appGrpList->next;
99     else {
100         AppGroupPtr tpAppGrp;
101         for (tpAppGrp = appGrpList; 
102             tpAppGrp->next != NULL; 
103             tpAppGrp = tpAppGrp->next) {
104             if (tpAppGrp->next == pAppGrp) {
105                 tpAppGrp->next = tpAppGrp->next->next;
106                 break;
107             }
108         }
109     }
110     (void) xfree (pAppGrp->clients);
111     (void) xfree (pAppGrp->ConnectionInfo);
112     (void) xfree (what);
113     return Success;
114 }
115
116 /* static */
117 void XagClientStateChange (pcbl, nulldata, calldata)
118     CallbackListPtr* pcbl;
119     pointer nulldata;
120     pointer calldata;
121 {
122     SecurityAuthorizationPtr pAuth;
123     NewClientInfoRec* pci = (NewClientInfoRec*) calldata;
124     ClientPtr pClient = pci->client;
125     AppGroupPtr pAppGrp;
126     XID authId;
127
128     if (!pClient->appgroup) {
129         switch (pClient->clientState) {
130
131         case ClientStateAuthenticating:
132         case ClientStateRunning: 
133         case ClientStateCheckingSecurity:
134             return;
135
136         case ClientStateInitial: 
137         case ClientStateCheckedSecurity:
138             /* 
139              * If the client is connecting via a firewall proxy (which
140              * uses XC-QUERY-SECURITY-1, then the authId is available
141              * during ClientStateCheckedSecurity, otherwise it's
142              * available during ClientStateInitial.
143              *
144              * Don't get it from pClient because can't guarantee the order
145              * of the callbacks and the security extension might not have
146              * plugged it in yet.
147              */
148             authId = AuthorizationIDOfClient(pClient);
149             break;
150
151         case ClientStateGone:
152         case ClientStateRetained:
153             /*
154              * Don't get if from AuthorizationIDOfClient because can't
155              * guarantee the order of the callbacks and the security
156              * extension may have torn down the client's private data
157              */
158             authId = pClient->authId;
159             break;
160         }
161
162         if (authId == None)
163             return;
164
165         pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(pClient,
166                 authId, SecurityAuthorizationResType, SecurityReadAccess);
167
168         if (pAuth == NULL)
169             return;
170
171         for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next)
172             if (pAppGrp->appgroupId == pAuth->group) break;
173     } else {
174         pAppGrp = pClient->appgroup;
175     }
176
177     if (!pAppGrp)
178         return;
179
180     switch (pClient->clientState) {
181     case ClientStateAuthenticating:
182     case ClientStateRunning: 
183     case ClientStateCheckingSecurity:
184         break;
185
186     case ClientStateInitial: 
187     case ClientStateCheckedSecurity:
188         /* see the comment above about Initial vs. CheckedSecurity */
189         {
190             /* if this client already in AppGroup, don't add it again */
191             int i;
192             for (i = 0; i < pAppGrp->nclients; i++)
193                 if (pClient == pAppGrp->clients[i]) return;
194         }
195         pAppGrp->clients = (ClientPtr*) xrealloc (pAppGrp->clients, 
196                                 ++pAppGrp->nclients * sizeof (ClientPtr));
197         pAppGrp->clients[pAppGrp->nclients - 1] = pClient;
198         pClient->appgroup = pAppGrp;
199         break;
200
201     case ClientStateGone:
202     case ClientStateRetained: /* client disconnected, dump it */
203         {
204             int i;
205             for (i = 0; i < pAppGrp->nclients; i++)
206                 if (pAppGrp->clients[i] == pClient) {
207                     pAppGrp->clients[i] = NULL;
208                     break;
209                 }
210             for (i = 0; i < pAppGrp->nclients; i++)
211                 if (pAppGrp->clients[i] == NULL && i + 1 < pAppGrp->nclients)
212                     pAppGrp->clients[i] = pAppGrp->clients[i + 1];
213             pAppGrp->nclients--;
214         }
215         pClient->appgroup = NULL; /* redundant, pClient will be freed */
216         break;
217     }
218 }
219
220 void
221 XagExtensionInit ()
222 {
223     ExtensionEntry* extEntry;
224
225     if (extEntry = AddExtension (XAGNAME,
226                                 0,
227                                 XagNumberErrors,
228                                 ProcXagDispatch,
229                                 SProcXagDispatch,
230                                 XagResetProc,
231                                 StandardMinorOpcode)) {
232         XagReqCode = (unsigned char)extEntry->base;
233         XagErrorBase = extEntry->errorBase;
234         RT_APPGROUP = CreateNewResourceType (XagAppGroupFree);
235     }
236 }
237
238 /*ARGSUSED*/
239 static 
240 void XagResetProc (extEntry)
241     ExtensionEntry* extEntry;
242 {
243     DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL);
244     XagCallbackRefCount = 0;
245     while (appGrpList) XagAppGroupFree ((pointer) appGrpList, 0);
246 }
247
248 static 
249 int ProcXagQueryVersion (client)
250     register ClientPtr client;
251 {
252     REQUEST (xXagQueryVersionReq);
253     xXagQueryVersionReply rep;
254     register int n;
255
256     REQUEST_SIZE_MATCH (xXagQueryVersionReq);
257     rep.type = X_Reply;
258     rep.length = 0;
259     rep.sequence_number = client->sequence;
260     rep.server_major_version = XAG_MAJOR_VERSION;
261     rep.server_minor_version = XAG_MINOR_VERSION;
262     if (client->swapped) {
263         swaps (&rep.sequence_number, n);
264         swapl (&rep.length, n);
265         swaps (&rep.server_major_version, n);
266         swaps (&rep.server_minor_version, n);
267     }
268     WriteToClient (client, sizeof (xXagQueryVersionReply), (char *)&rep);
269     return client->noClientException;
270 }
271
272 static 
273 void ProcessAttr (pAppGrp, client, attrib_mask, attribs)
274     AppGroupPtr pAppGrp;
275     ClientPtr client;
276     unsigned int attrib_mask;
277     CARD32* attribs;
278 {
279     int i;
280
281     for (i = XagNsingleScreen; i <= XagNappGroupLeader; i++) {
282         switch (attrib_mask & (1 << i)) {
283         case XagSingleScreenMask:
284             pAppGrp->single_screen = *attribs;
285             break;
286         case XagDefaultRootMask:
287             pAppGrp->default_root = *attribs;
288             break;
289         case XagRootVisualMask:
290             pAppGrp->root_visual = *attribs;
291             break;
292         case XagDefaultColormapMask:
293             pAppGrp->default_colormap = *attribs;
294             break;
295         case XagBlackPixelMask:
296             pAppGrp->black_pixel = *attribs;
297             break;
298         case XagWhitePixelMask:
299             pAppGrp->white_pixel = *attribs;
300             break;
301         case XagAppGroupLeaderMask:
302             pAppGrp->leader = client;
303             break;
304         default: continue;
305         }
306         attribs++;
307     }
308 }
309
310 static 
311 void CreateConnectionInfo (pAppGrp)
312     AppGroupPtr pAppGrp;
313 {
314     extern int connBlockScreenStart;
315     xConnSetup *setup = (xConnSetup*) ConnectionInfo;
316     xWindowRoot* rootp;
317     xWindowRoot* roots[MAXSCREENS];
318     unsigned int rootlens[MAXSCREENS];
319     xDepth* depth;
320     int olen;
321     int snum, i;
322
323     rootp = (xWindowRoot*) (ConnectionInfo + connBlockScreenStart);
324     for (snum = 0; snum < screenInfo.numScreens; snum++) {
325
326         rootlens[snum] = sizeof (xWindowRoot);
327         roots[snum] = rootp;
328
329         depth = (xDepth*) (rootp + 1);
330         for (i = 0; i < rootp->nDepths; i++) {
331             rootlens[snum] += sizeof (xDepth) + 
332                               depth->nVisuals * sizeof (xVisualType);
333             depth = (xDepth *)(((char*)(depth + 1)) +
334                 depth->nVisuals * sizeof (xVisualType));
335         }
336         rootp = (xWindowRoot*) depth;
337     }
338     snum = 0;
339     if (pAppGrp->default_root) {
340         for (; snum < screenInfo.numVideoScreens; snum++) {
341             if (roots[snum]->windowId == pAppGrp->default_root)
342                 break;
343         }
344     }
345     olen = connBlockScreenStart + rootlens[snum];
346     for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++)
347         olen += rootlens[i];
348     pAppGrp->ConnectionInfo = (char*) xalloc (olen);
349     if (!pAppGrp->ConnectionInfo)
350         return;
351     memmove (pAppGrp->ConnectionInfo, ConnectionInfo, connBlockScreenStart);
352     ((xConnSetup*) (pAppGrp->ConnectionInfo))->numRoots = 
353         1 + screenInfo.numScreens - screenInfo.numVideoScreens;
354     memmove (pAppGrp->ConnectionInfo + connBlockScreenStart,
355              (void*) roots[snum], rootlens[snum]);
356     rootp = (xWindowRoot*) (pAppGrp->ConnectionInfo + connBlockScreenStart);
357     if (pAppGrp->default_colormap) {
358         rootp->defaultColormap = pAppGrp->default_colormap;
359         rootp->whitePixel = pAppGrp->white_pixel;
360         rootp->blackPixel = pAppGrp->black_pixel;
361     }
362     if (pAppGrp->root_visual)
363         rootp->rootVisualID = pAppGrp->root_visual;
364     rootp = (xWindowRoot*) (((char*)rootp) + rootlens[snum]);
365     for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++) {
366         memmove ((void*) rootp, (void*) roots[i], rootlens[i]);
367         rootp = (xWindowRoot*) (((char*) rootp) + rootlens[i]);
368     }
369     pAppGrp->connSetupPrefix = connSetupPrefix;
370     pAppGrp->connSetupPrefix.length = olen >> 2;
371 }
372
373 static 
374 AppGroupPtr CreateAppGroup (client, appgroupId, attrib_mask, attribs)
375     ClientPtr client;
376     XID appgroupId;
377     unsigned int attrib_mask;
378     CARD32* attribs;
379 {
380     AppGroupPtr pAppGrp;
381     int i;
382
383     pAppGrp = (AppGroupPtr) xalloc (sizeof(AppGroupRec));
384     if (pAppGrp) {
385         pAppGrp->next = appGrpList;
386         appGrpList = pAppGrp;
387         pAppGrp->appgroupId = appgroupId;
388         pAppGrp->clients = (ClientPtr*) xalloc (0);
389         pAppGrp->nclients = 0;
390         pAppGrp->leader = NULL;
391         pAppGrp->default_root = 0;
392         pAppGrp->root_visual = 0;
393         pAppGrp->default_colormap = 0;
394         pAppGrp->black_pixel = -1;
395         pAppGrp->white_pixel = -1;
396         pAppGrp->ConnectionInfo = NULL;
397         ProcessAttr (pAppGrp, client, attrib_mask, attribs);
398     }
399     return pAppGrp;
400 }
401
402 static 
403 int AttrValidate (client, attrib_mask, pAppGrp)
404     ClientPtr client;
405     int attrib_mask;
406     AppGroupPtr pAppGrp;
407 {
408     WindowPtr pWin;
409     int idepth, ivids, found;
410     ScreenPtr pScreen;
411     DepthPtr pDepth;
412     ColormapPtr pColormap;
413
414     pWin = LookupWindow (pAppGrp->default_root, client);
415     /* XXX check that pWin is not NULL */
416     pScreen = pWin->drawable.pScreen;
417     if (WindowTable[pScreen->myNum]->drawable.id != pAppGrp->default_root)
418         return BadWindow;
419     pDepth = pScreen->allowedDepths;
420     if (pAppGrp->root_visual) {
421         found = FALSE;
422         for (idepth = 0; idepth < pScreen->numDepths; idepth++, pDepth++) {
423             for (ivids = 0; ivids < pDepth->numVids; ivids++) {
424                 if (pAppGrp->root_visual == pDepth->vids[ivids]) {
425                     found = TRUE;
426                     break;
427                 }
428             }
429         }
430         if (!found)
431             return BadMatch;
432     }
433     if (pAppGrp->default_colormap) {
434
435         pColormap = (ColormapPtr)LookupIDByType (pAppGrp->default_colormap, RT_COLORMAP);
436         /* XXX check that pColormap is not NULL */
437         if (pColormap->pScreen != pScreen)
438             return BadColor;
439         if (pColormap->pVisual->vid != (pAppGrp->root_visual ? pAppGrp->root_visual : pScreen->rootVisual))
440             return BadMatch;
441     }
442     return client->noClientException;
443 }
444
445 /* static */
446 int ProcXagCreate (client)
447     register ClientPtr client;
448 {
449     REQUEST (xXagCreateReq);
450     AppGroupPtr pAppGrp;
451     int ret;
452
453     REQUEST_AT_LEAST_SIZE (xXagCreateReq);
454
455     LEGAL_NEW_RESOURCE (stuff->app_group, client);
456     pAppGrp = CreateAppGroup (client, stuff->app_group, 
457                 stuff->attrib_mask, (CARD32*) &stuff[1]);
458     if (!pAppGrp)
459         return BadAlloc;
460     ret = AttrValidate (client, stuff->attrib_mask, pAppGrp);
461     if (ret != Success) {
462         XagAppGroupFree ((pointer)pAppGrp, (XID)0);
463         return ret;
464     }
465     if (pAppGrp->single_screen) {
466         CreateConnectionInfo (pAppGrp);
467         if (!pAppGrp->ConnectionInfo)
468             return BadAlloc;
469     }
470     if (!AddResource (stuff->app_group, RT_APPGROUP, (pointer)pAppGrp))
471         return BadAlloc;
472     if (XagCallbackRefCount++ == 0)
473         (void) AddCallback (&ClientStateCallback, XagClientStateChange, NULL);
474     return client->noClientException;
475 }
476
477 /* static */
478 int ProcXagDestroy (client)
479     register ClientPtr client;
480 {
481     AppGroupPtr pAppGrp;
482     REQUEST (xXagDestroyReq);
483
484     REQUEST_SIZE_MATCH (xXagDestroyReq);
485     pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client, 
486                 (XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess);
487     if (!pAppGrp) return XagBadAppGroup;
488     FreeResource ((XID)stuff->app_group, RT_NONE);
489     if (--XagCallbackRefCount == 0)
490         (void) DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL);
491     return client->noClientException;
492 }
493
494 static 
495 int ProcXagGetAttr (client)
496     register ClientPtr client;
497 {
498     AppGroupPtr pAppGrp;
499     REQUEST (xXagGetAttrReq);
500     xXagGetAttrReply rep;
501     int n;
502
503     REQUEST_SIZE_MATCH (xXagGetAttrReq);
504     pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client, 
505                 (XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess);
506     if (!pAppGrp) return XagBadAppGroup;
507     rep.default_root = pAppGrp->default_root;
508     rep.root_visual = pAppGrp->root_visual;
509     rep.default_colormap = pAppGrp->default_colormap;
510     rep.single_screen = pAppGrp->single_screen;
511     rep.app_group_leader = (pAppGrp->leader) ? 1 : 0;
512     if (client->swapped) {
513         swaps (&rep.sequence_number, n);
514         swapl (&rep.length, n);
515         swapl (&rep.default_root, n);
516         swapl (&rep.root_visual, n);
517         swapl (&rep.default_colormap, n);
518     }
519     WriteToClient (client, sizeof (xXagGetAttrReply), (char *)&rep);
520     return client->noClientException;
521 }
522
523 static 
524 int ProcXagQuery (client)
525     register ClientPtr client;
526 {
527     ClientPtr pClient;
528     AppGroupPtr pAppGrp;
529     REQUEST (xXagQueryReq);
530     int n;
531
532     REQUEST_SIZE_MATCH (xXagQueryReq);
533     pClient = LookupClient (stuff->resource, client);
534     for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next)
535         for (n = 0; n < pAppGrp->nclients; n++)
536             if (pAppGrp->clients[n] == pClient) {
537                 xXagQueryReply rep;
538
539                 rep.type = X_Reply;
540                 rep.length = 0;
541                 rep.sequence_number = client->sequence;
542                 rep.app_group = pAppGrp->appgroupId;
543                 if (client->swapped) {
544                     swaps (&rep.sequence_number, n);
545                     swapl (&rep.length, n);
546                     swapl (&rep.app_group, n);
547                 }
548                 WriteToClient (client, sizeof (xXagQueryReply), (char *)&rep);
549                 return client->noClientException;
550             }
551
552     return BadMatch;
553 }
554
555 static 
556 int ProcXagCreateAssoc (client)
557     register ClientPtr client;
558 {
559     REQUEST (xXagCreateAssocReq);
560
561     REQUEST_SIZE_MATCH (xXagCreateAssocReq);
562 #ifdef WIN32
563     if (stuff->window_type != XagWindowTypeWin32)
564 #else
565     if (stuff->window_type != XagWindowTypeX11)
566 #endif
567         return BadMatch;
568 #ifdef WIN32 /* and Mac, etc */
569     if (!LocalClient (client))
570         return BadAccess;
571 #endif
572
573 /* Macintosh, OS/2, and MS-Windows servers have some work to do here */
574
575     return client->noClientException;
576 }
577
578 static 
579 int ProcXagDestroyAssoc (client)
580     register ClientPtr client;
581 {
582     REQUEST (xXagDestroyAssocReq);
583
584     REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
585 /* Macintosh, OS/2, and MS-Windows servers have some work to do here */
586     return client->noClientException;
587 }
588
589 static 
590 int ProcXagDispatch (client)
591     register ClientPtr  client;
592 {
593     REQUEST (xReq);
594     switch (stuff->data)
595     {
596     case X_XagQueryVersion:
597         return ProcXagQueryVersion (client);
598     case X_XagCreate:
599         return ProcXagCreate (client);
600     case X_XagDestroy:
601         return ProcXagDestroy (client);
602     case X_XagGetAttr:
603         return ProcXagGetAttr (client);
604     case X_XagQuery:
605         return ProcXagQuery (client);
606     case X_XagCreateAssoc:
607         return ProcXagCreateAssoc (client);
608     case X_XagDestroyAssoc:
609         return ProcXagDestroyAssoc (client);
610     default:
611         return BadRequest;
612     }
613 }
614
615 static 
616 int SProcXagQueryVersion (client)
617     register ClientPtr  client;
618 {
619     register int n;
620     REQUEST(xXagQueryVersionReq);
621     swaps(&stuff->length, n);
622     return ProcXagQueryVersion(client);
623 }
624
625 static 
626 int SProcXagCreate (client)
627     ClientPtr client;
628 {
629     register int n;
630     REQUEST (xXagCreateReq);
631     swaps (&stuff->length, n);
632     REQUEST_AT_LEAST_SIZE (xXagCreateReq);
633     swapl (&stuff->app_group, n);
634     swapl (&stuff->attrib_mask, n);
635     SwapRestL (stuff);
636     return ProcXagCreate (client);
637 }
638
639 static 
640 int SProcXagDestroy (client)
641     ClientPtr client;
642 {
643     register int n;
644     REQUEST (xXagDestroyReq);
645     swaps (&stuff->length, n);
646     REQUEST_SIZE_MATCH (xXagDestroyReq);
647     swapl (&stuff->app_group, n);
648     return ProcXagDestroy (client);
649 }
650
651 static 
652 int SProcXagGetAttr (client)
653     ClientPtr client;
654 {
655     register int n;
656     REQUEST (xXagGetAttrReq);
657     swaps (&stuff->length, n);
658     REQUEST_SIZE_MATCH (xXagGetAttrReq);
659     swapl (&stuff->app_group, n);
660     return ProcXagGetAttr (client);
661 }
662
663 static 
664 int SProcXagQuery (client)
665     ClientPtr client;
666 {
667     register int n;
668     REQUEST (xXagQueryReq);
669     swaps (&stuff->length, n);
670     REQUEST_SIZE_MATCH (xXagQueryReq);
671     swapl (&stuff->resource, n);
672     return ProcXagQuery (client);
673 }
674
675 static 
676 int SProcXagCreateAssoc (client)
677     ClientPtr client;
678 {
679     register int n;
680     REQUEST (xXagCreateAssocReq);
681     swaps (&stuff->length, n);
682     REQUEST_SIZE_MATCH (xXagCreateAssocReq);
683     swapl (&stuff->window, n);
684     swapl (&stuff->window_type, n);
685     swaps (&stuff->system_window_len, n);
686     return ProcXagCreateAssoc (client);
687 }
688
689 static 
690 int SProcXagDestroyAssoc (client)
691     ClientPtr client;
692 {
693     register int n;
694     REQUEST (xXagDestroyAssocReq);
695     swaps (&stuff->length, n);
696     REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
697     swapl (&stuff->window, n);
698     return ProcXagDestroyAssoc (client);
699 }
700
701 static 
702 int SProcXagDispatch (client)
703     register ClientPtr  client;
704 {
705     REQUEST(xReq);
706     switch (stuff->data)
707     {
708     case X_XagQueryVersion:
709         return SProcXagQueryVersion (client);
710     case X_XagCreate:
711         return SProcXagCreate (client);
712     case X_XagDestroy:
713         return SProcXagDestroy (client);
714     case X_XagGetAttr:
715         return SProcXagGetAttr (client);
716     case X_XagQuery:
717         return SProcXagQuery (client);
718     case X_XagCreateAssoc:
719         return SProcXagCreateAssoc (client);
720     case X_XagDestroyAssoc:
721         return SProcXagDestroyAssoc (client);
722     default:
723         return BadRequest;
724     }
725 }
726
727 Colormap XagDefaultColormap (client)
728     ClientPtr client;
729 {
730     return (client->appgroup ? client->appgroup->default_colormap : None);
731 }
732
733 VisualID XagRootVisual (client)
734     ClientPtr client;
735 {
736     return (client->appgroup ? client->appgroup->root_visual : 0);
737 }
738
739 ClientPtr XagLeader (client)
740     ClientPtr client;
741 {
742     return (client->appgroup ? client->appgroup->leader : NULL);
743 }
744
745 /*
746  * Return whether the Map request event should be sent to the appgroup leader.
747  * We don't want to send it to the leader when the window is on a different
748  * screen, e.g. a print screen.
749  */
750 Bool XagIsControlledRoot (client, pParent)
751     ClientPtr client;
752     WindowPtr pParent;
753 {
754     if (client->appgroup) {
755         if (client->appgroup->single_screen && 
756             pParent->drawable.id == client->appgroup->default_root)
757             return TRUE;
758         else if (!pParent->parent)
759             return TRUE;
760         else
761             return FALSE;
762     }
763     return FALSE; 
764 }
765
766 void XagConnectionInfo (client, conn_prefix, conn_info, num_screen)
767     ClientPtr client;
768     xConnSetupPrefix** conn_prefix;
769     char** conn_info;
770     int* num_screen;
771 {
772     if (client->appgroup && client->appgroup->ConnectionInfo) {
773         *conn_prefix = &client->appgroup->connSetupPrefix;
774         *conn_info = client->appgroup->ConnectionInfo;
775         *num_screen = ((xConnSetup*)(client->appgroup->ConnectionInfo))->numRoots;
776     } 
777 }
778
779 XID XagId (client)
780     ClientPtr client;
781 {
782     return (client->appgroup ? client->appgroup->appgroupId : 0);
783 }
784
785 void XagGetDeltaInfo (client, buf)
786     ClientPtr client;
787     CARD32* buf;
788 {
789     *buf++ = (CARD32) client->appgroup->default_root;
790     *buf++ = (CARD32) client->appgroup->root_visual;
791     *buf++ = (CARD32) client->appgroup->default_colormap;
792     *buf++ = (CARD32) client->appgroup->black_pixel;
793     *buf = (CARD32) client->appgroup->white_pixel;
794 }
795
796 void XagCallClientStateChange (client)
797     ClientPtr client;
798 {
799     if (appGrpList) {
800         NewClientInfoRec clientinfo;
801
802         clientinfo.client = client;
803         XagClientStateChange (NULL, NULL, (pointer)&clientinfo);
804     }
805 }