2 Copyright (c) 1996 X Consortium
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:
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
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.
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.
28 /* $XConsortium: appgroup.c /main/20 1996/12/08 16:14:27 kaleb $ */
35 #include "dixstruct.h"
36 #include "extnsionst.h"
37 #include "scrnintstr.h"
38 #include "windowstr.h"
39 #include "colormapst.h"
43 #define _SECURITY_SERVER
45 #include "Xfuncproto.h"
48 #include <X11/Xtrans.h>
49 #include "../os/osdep.h"
53 typedef struct _AppGroupRec {
54 struct _AppGroupRec* next;
62 Colormap default_colormap;
65 xConnSetupPrefix connSetupPrefix;
67 } AppGroupRec, *AppGroupPtr;
69 static int ProcXagDispatch (), SProcXagDispatch ();
70 static void XagResetProc ();
72 static unsigned char XagReqCode = 0;
73 static int XagErrorBase;
74 static int XagCallbackRefCount = 0;
76 static RESTYPE RT_APPGROUP;
77 static AppGroupPtr appGrpList = NULL;
79 extern WindowPtr* WindowTable;
80 extern xConnSetupPrefix connSetupPrefix;
81 extern char* ConnectionInfo;
84 int XagAppGroupFree (what, id)
89 AppGroupPtr pAppGrp = (AppGroupPtr) what;
92 for (i = 0; i < pAppGrp->nclients; i++) {
93 pAppGrp->clients[i]->appgroup = NULL;
94 CloseDownClient (pAppGrp->clients[i]);
97 if (pAppGrp == appGrpList)
98 appGrpList = appGrpList->next;
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;
110 (void) xfree (pAppGrp->clients);
111 (void) xfree (pAppGrp->ConnectionInfo);
117 void XagClientStateChange (pcbl, nulldata, calldata)
118 CallbackListPtr* pcbl;
122 SecurityAuthorizationPtr pAuth;
123 NewClientInfoRec* pci = (NewClientInfoRec*) calldata;
124 ClientPtr pClient = pci->client;
128 if (!pClient->appgroup) {
129 switch (pClient->clientState) {
131 case ClientStateAuthenticating:
132 case ClientStateRunning:
133 case ClientStateCheckingSecurity:
136 case ClientStateInitial:
137 case ClientStateCheckedSecurity:
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.
144 * Don't get it from pClient because can't guarantee the order
145 * of the callbacks and the security extension might not have
148 authId = AuthorizationIDOfClient(pClient);
151 case ClientStateGone:
152 case ClientStateRetained:
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
158 authId = pClient->authId;
165 pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(pClient,
166 authId, SecurityAuthorizationResType, SecurityReadAccess);
171 for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next)
172 if (pAppGrp->appgroupId == pAuth->group) break;
174 pAppGrp = pClient->appgroup;
180 switch (pClient->clientState) {
181 case ClientStateAuthenticating:
182 case ClientStateRunning:
183 case ClientStateCheckingSecurity:
186 case ClientStateInitial:
187 case ClientStateCheckedSecurity:
188 /* see the comment above about Initial vs. CheckedSecurity */
190 /* if this client already in AppGroup, don't add it again */
192 for (i = 0; i < pAppGrp->nclients; i++)
193 if (pClient == pAppGrp->clients[i]) return;
195 pAppGrp->clients = (ClientPtr*) xrealloc (pAppGrp->clients,
196 ++pAppGrp->nclients * sizeof (ClientPtr));
197 pAppGrp->clients[pAppGrp->nclients - 1] = pClient;
198 pClient->appgroup = pAppGrp;
201 case ClientStateGone:
202 case ClientStateRetained: /* client disconnected, dump it */
205 for (i = 0; i < pAppGrp->nclients; i++)
206 if (pAppGrp->clients[i] == pClient) {
207 pAppGrp->clients[i] = NULL;
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];
215 pClient->appgroup = NULL; /* redundant, pClient will be freed */
223 ExtensionEntry* extEntry;
225 if (extEntry = AddExtension (XAGNAME,
231 StandardMinorOpcode)) {
232 XagReqCode = (unsigned char)extEntry->base;
233 XagErrorBase = extEntry->errorBase;
234 RT_APPGROUP = CreateNewResourceType (XagAppGroupFree);
240 void XagResetProc (extEntry)
241 ExtensionEntry* extEntry;
243 DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL);
244 XagCallbackRefCount = 0;
245 while (appGrpList) XagAppGroupFree ((pointer) appGrpList, 0);
249 int ProcXagQueryVersion (client)
250 register ClientPtr client;
252 REQUEST (xXagQueryVersionReq);
253 xXagQueryVersionReply rep;
256 REQUEST_SIZE_MATCH (xXagQueryVersionReq);
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);
268 WriteToClient (client, sizeof (xXagQueryVersionReply), (char *)&rep);
269 return client->noClientException;
273 void ProcessAttr (pAppGrp, client, attrib_mask, attribs)
276 unsigned int attrib_mask;
281 for (i = XagNsingleScreen; i <= XagNappGroupLeader; i++) {
282 switch (attrib_mask & (1 << i)) {
283 case XagSingleScreenMask:
284 pAppGrp->single_screen = *attribs;
286 case XagDefaultRootMask:
287 pAppGrp->default_root = *attribs;
289 case XagRootVisualMask:
290 pAppGrp->root_visual = *attribs;
292 case XagDefaultColormapMask:
293 pAppGrp->default_colormap = *attribs;
295 case XagBlackPixelMask:
296 pAppGrp->black_pixel = *attribs;
298 case XagWhitePixelMask:
299 pAppGrp->white_pixel = *attribs;
301 case XagAppGroupLeaderMask:
302 pAppGrp->leader = client;
311 void CreateConnectionInfo (pAppGrp)
314 extern int connBlockScreenStart;
315 xConnSetup *setup = (xConnSetup*) ConnectionInfo;
317 xWindowRoot* roots[MAXSCREENS];
318 unsigned int rootlens[MAXSCREENS];
323 rootp = (xWindowRoot*) (ConnectionInfo + connBlockScreenStart);
324 for (snum = 0; snum < screenInfo.numScreens; snum++) {
326 rootlens[snum] = sizeof (xWindowRoot);
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));
336 rootp = (xWindowRoot*) depth;
339 if (pAppGrp->default_root) {
340 for (; snum < screenInfo.numVideoScreens; snum++) {
341 if (roots[snum]->windowId == pAppGrp->default_root)
345 olen = connBlockScreenStart + rootlens[snum];
346 for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++)
348 pAppGrp->ConnectionInfo = (char*) xalloc (olen);
349 if (!pAppGrp->ConnectionInfo)
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;
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]);
369 pAppGrp->connSetupPrefix = connSetupPrefix;
370 pAppGrp->connSetupPrefix.length = olen >> 2;
374 AppGroupPtr CreateAppGroup (client, appgroupId, attrib_mask, attribs)
377 unsigned int attrib_mask;
383 pAppGrp = (AppGroupPtr) xalloc (sizeof(AppGroupRec));
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);
403 int AttrValidate (client, attrib_mask, pAppGrp)
409 int idepth, ivids, found;
412 ColormapPtr pColormap;
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)
419 pDepth = pScreen->allowedDepths;
420 if (pAppGrp->root_visual) {
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]) {
433 if (pAppGrp->default_colormap) {
435 pColormap = (ColormapPtr)LookupIDByType (pAppGrp->default_colormap, RT_COLORMAP);
436 /* XXX check that pColormap is not NULL */
437 if (pColormap->pScreen != pScreen)
439 if (pColormap->pVisual->vid != (pAppGrp->root_visual ? pAppGrp->root_visual : pScreen->rootVisual))
442 return client->noClientException;
446 int ProcXagCreate (client)
447 register ClientPtr client;
449 REQUEST (xXagCreateReq);
453 REQUEST_AT_LEAST_SIZE (xXagCreateReq);
455 LEGAL_NEW_RESOURCE (stuff->app_group, client);
456 pAppGrp = CreateAppGroup (client, stuff->app_group,
457 stuff->attrib_mask, (CARD32*) &stuff[1]);
460 ret = AttrValidate (client, stuff->attrib_mask, pAppGrp);
461 if (ret != Success) {
462 XagAppGroupFree ((pointer)pAppGrp, (XID)0);
465 if (pAppGrp->single_screen) {
466 CreateConnectionInfo (pAppGrp);
467 if (!pAppGrp->ConnectionInfo)
470 if (!AddResource (stuff->app_group, RT_APPGROUP, (pointer)pAppGrp))
472 if (XagCallbackRefCount++ == 0)
473 (void) AddCallback (&ClientStateCallback, XagClientStateChange, NULL);
474 return client->noClientException;
478 int ProcXagDestroy (client)
479 register ClientPtr client;
482 REQUEST (xXagDestroyReq);
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;
495 int ProcXagGetAttr (client)
496 register ClientPtr client;
499 REQUEST (xXagGetAttrReq);
500 xXagGetAttrReply rep;
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);
519 WriteToClient (client, sizeof (xXagGetAttrReply), (char *)&rep);
520 return client->noClientException;
524 int ProcXagQuery (client)
525 register ClientPtr client;
529 REQUEST (xXagQueryReq);
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) {
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);
548 WriteToClient (client, sizeof (xXagQueryReply), (char *)&rep);
549 return client->noClientException;
556 int ProcXagCreateAssoc (client)
557 register ClientPtr client;
559 REQUEST (xXagCreateAssocReq);
561 REQUEST_SIZE_MATCH (xXagCreateAssocReq);
563 if (stuff->window_type != XagWindowTypeWin32)
565 if (stuff->window_type != XagWindowTypeX11)
568 #ifdef WIN32 /* and Mac, etc */
569 if (!LocalClient (client))
573 /* Macintosh, OS/2, and MS-Windows servers have some work to do here */
575 return client->noClientException;
579 int ProcXagDestroyAssoc (client)
580 register ClientPtr client;
582 REQUEST (xXagDestroyAssocReq);
584 REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
585 /* Macintosh, OS/2, and MS-Windows servers have some work to do here */
586 return client->noClientException;
590 int ProcXagDispatch (client)
591 register ClientPtr client;
596 case X_XagQueryVersion:
597 return ProcXagQueryVersion (client);
599 return ProcXagCreate (client);
601 return ProcXagDestroy (client);
603 return ProcXagGetAttr (client);
605 return ProcXagQuery (client);
606 case X_XagCreateAssoc:
607 return ProcXagCreateAssoc (client);
608 case X_XagDestroyAssoc:
609 return ProcXagDestroyAssoc (client);
616 int SProcXagQueryVersion (client)
617 register ClientPtr client;
620 REQUEST(xXagQueryVersionReq);
621 swaps(&stuff->length, n);
622 return ProcXagQueryVersion(client);
626 int SProcXagCreate (client)
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);
636 return ProcXagCreate (client);
640 int SProcXagDestroy (client)
644 REQUEST (xXagDestroyReq);
645 swaps (&stuff->length, n);
646 REQUEST_SIZE_MATCH (xXagDestroyReq);
647 swapl (&stuff->app_group, n);
648 return ProcXagDestroy (client);
652 int SProcXagGetAttr (client)
656 REQUEST (xXagGetAttrReq);
657 swaps (&stuff->length, n);
658 REQUEST_SIZE_MATCH (xXagGetAttrReq);
659 swapl (&stuff->app_group, n);
660 return ProcXagGetAttr (client);
664 int SProcXagQuery (client)
668 REQUEST (xXagQueryReq);
669 swaps (&stuff->length, n);
670 REQUEST_SIZE_MATCH (xXagQueryReq);
671 swapl (&stuff->resource, n);
672 return ProcXagQuery (client);
676 int SProcXagCreateAssoc (client)
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);
690 int SProcXagDestroyAssoc (client)
694 REQUEST (xXagDestroyAssocReq);
695 swaps (&stuff->length, n);
696 REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
697 swapl (&stuff->window, n);
698 return ProcXagDestroyAssoc (client);
702 int SProcXagDispatch (client)
703 register ClientPtr client;
708 case X_XagQueryVersion:
709 return SProcXagQueryVersion (client);
711 return SProcXagCreate (client);
713 return SProcXagDestroy (client);
715 return SProcXagGetAttr (client);
717 return SProcXagQuery (client);
718 case X_XagCreateAssoc:
719 return SProcXagCreateAssoc (client);
720 case X_XagDestroyAssoc:
721 return SProcXagDestroyAssoc (client);
727 Colormap XagDefaultColormap (client)
730 return (client->appgroup ? client->appgroup->default_colormap : None);
733 VisualID XagRootVisual (client)
736 return (client->appgroup ? client->appgroup->root_visual : 0);
739 ClientPtr XagLeader (client)
742 return (client->appgroup ? client->appgroup->leader : NULL);
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.
750 Bool XagIsControlledRoot (client, pParent)
754 if (client->appgroup) {
755 if (client->appgroup->single_screen &&
756 pParent->drawable.id == client->appgroup->default_root)
758 else if (!pParent->parent)
766 void XagConnectionInfo (client, conn_prefix, conn_info, num_screen)
768 xConnSetupPrefix** conn_prefix;
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;
782 return (client->appgroup ? client->appgroup->appgroupId : 0);
785 void XagGetDeltaInfo (client, buf)
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;
796 void XagCallClientStateChange (client)
800 NewClientInfoRec clientinfo;
802 clientinfo.client = client;
803 XagClientStateChange (NULL, NULL, (pointer)&clientinfo);