2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1996 Digital Equipment Corporation.
25 * (c) Copyright 1996 Hewlett-Packard Company.
26 * (c) Copyright 1996 International Business Machines Corp.
27 * (c) Copyright 1996 Sun Microsystems, Inc.
28 * (c) Copyright 1996 Novell, Inc.
29 * (c) Copyright 1996 FUJITSU LIMITED.
30 * (c) Copyright 1996 Hitachi.
36 #include <sys/param.h>
37 #include <X11/Intrinsic.h>
38 #include <X11/Shell.h>
39 #include <X11/Xatom.h>
40 #include <X11/SM/SM.h>
44 #include "WmWrkspace.h"
45 #include <Dt/Session.h>
47 typedef struct _ProxyClientInfo
51 char *wmClientMachine;
55 #define RESTORE_RESOURCE(pCD, resFlag) \
56 ((pCD)->ignoreWMSaveHints || !((pCD)->wmSaveHintFlags & (resFlag)))
57 #define SAVE_RESOURCE(pCD, resFlag) RESTORE_RESOURCE(pCD, resFlag)
59 #define MAX_RESOURCE_LEN 1024
61 static char *dtwmFileName = "dtwm.db";
63 /* Fully-qualified resource names/classes. */
64 static char *xPositionStr = "%s.position.x";
65 static char *yPositionStr = "%s.position.y";
66 static char *widthSizeStr = "%s.size.width";
67 static char *heightSizeStr = "%s.size.height";
68 static char *initialStateStr = "%s.initialState";
69 static char *wmCommandStr = "%s.wmCommand";
70 static char *wmClientMachineStr = "%s.wmClientMachine";
71 static char *screenStr = "%s.screen";
72 static char *workspacesStr = "%s.workspaces";
73 static char *iconXPosStr = "%s.iconPos.x.%s";
74 static char *iconYPosStr = "%s.iconPos.y.%s";
76 /* Header for private database. */
77 static char *dbHeader = "\
83 /* Format for client entries in database. */
84 static char *dbClientFormat = "\
88 static char *intArg = ": %d\n";
89 static char *strArg = ": %s\n";
90 static char *normalStateStr = "NormalState";
91 static char *iconicStateStr = "IconicState";
93 static char *XSMPClientStr = "Client";
94 static char *proxyClientStr = "ProxyClient";
96 /* Flag to tell us how to treat ProxyClient info. */
97 static Boolean smClientDBCheckpointed = False;
102 /* Session mgmt callbacks. */
103 static void smSaveYourselfCallback(Widget, XtPointer, XtPointer);
104 static void smDieCallback(Widget, XtPointer, XtPointer);
106 /* Build client database file name. */
107 static void buildDBFileName(char [MAXPATHLEN], Boolean);
109 /* Get string of client's workspaces. */
110 static char *getClientWorkspaces(ClientData *);
112 /* List-of-clients utilities. */
113 static Boolean addClientToList(ClientData ***, int *, ClientData *);
114 static int clientWorkspaceCompare(const void *, const void *);
116 /* XSMP/Proxy functions to save/restore resources. */
117 static char *getClientResource(char *, char *);
118 static char *getXSMPResource(ClientData *, int, char *);
119 static void getClientGeometry(ClientData *, int *, int *,
120 unsigned int *, unsigned int *);
121 static Boolean getProxyClientInfo(ClientData *, ProxyClientInfo *);
122 static Bool cmpProxyClientProc(XrmDatabase *, XrmBindingList,
123 XrmQuarkList, XrmRepresentation *,
124 XrmValue *, XPointer);
125 static char *findProxyClientID(ClientData *);
126 static Boolean findXSMPClientDBMatch(ClientData *, char **);
127 static Boolean findProxyClientDBMatch(ClientData *, char **);
128 static Boolean saveXSMPClient(FILE *, ClientData *);
129 static Boolean saveProxyClient(FILE *, ClientData *, int);
130 static void dbRemoveProxyClientEntry(char *);
133 smSaveYourselfCallback(Widget w, XtPointer clientData, XtPointer callData)
135 XtCheckpointToken cpToken = (XtCheckpointToken)callData;
136 XrmDatabase newClientDB;
138 static Boolean firstTime = True;
141 * This callback will be called on connection to the Session Manager.
142 * At that time, we don't want to save any state, and we don't
143 * want to request the second phase.
151 /* Only respond to Local and Both save requests. */
152 if ((cpToken->save_type != SmSaveLocal) &&
153 (cpToken->save_type != SmSaveBoth))
156 if (cpToken->shutdown &&
157 (cpToken->cancel_shutdown ||
158 cpToken->request_cancel ||
159 !cpToken->save_success))
160 return; /* Return, maintaining current state */
162 /* If first phase, request notification when all other clients saved. */
163 if (cpToken->phase == 1)
165 cpToken->request_next_phase = True;
169 /* Second phase: all other clients saved; now I can save myself. */
170 /* Copied from WmEvent.c. */
171 for (scr = 0; scr < wmGD.numScreens; scr++)
173 if (wmGD.Screens[scr].managed)
176 * Write out current workspace, frontpanel
177 * position and iconbox position and size.
179 SaveResources(&wmGD.Screens[scr]);
184 * NEW FOR SESSION MANAGEMENT: Write private client resource database.
185 * Destroy old client database and save new one.
187 if ((newClientDB = SaveClientResourceDB())
188 != (XrmDatabase)NULL)
190 if (wmGD.clientResourceDB != (XrmDatabase)NULL)
191 XrmDestroyDatabase(wmGD.clientResourceDB);
192 wmGD.clientResourceDB = newClientDB;
193 smClientDBCheckpointed = True;
199 smDieCallback(Widget w, XtPointer clientData, XtPointer callData)
201 /* We assume we've saved our state by the time this is called. */
206 buildDBFileName(char fileNameBuf[MAXPATHLEN], Boolean doingSave)
208 char *savePath = (char *)NULL;
210 fileNameBuf[0] = '\0';
213 char *saveFile = (char *)NULL;
216 if (DtSessionSavePath(wmGD.topLevelW, &savePath, &saveFile))
220 if ((ptr = strrchr(savePath, '/')) != (char *)NULL)
223 if (strlen(savePath) + strlen(dtwmFileName) + 2 < MAXPATHLEN)
224 sprintf(fileNameBuf, "%s/%s", savePath, dtwmFileName);
231 if (DtSessionRestorePath(wmGD.topLevelW, &savePath, dtwmFileName))
233 if ((int)strlen(savePath) < MAXPATHLEN)
234 strcpy(fileNameBuf, savePath);
240 if (fileNameBuf[0] == '\0')
241 strcpy(fileNameBuf, dtwmFileName);
246 getClientWorkspaces(ClientData *pCD)
248 WmScreenData *pSD = pCD->pSD;
249 WmWorkspaceData *pWS;
251 /* Should we use _DtWmParseMakeQuotedString() when looking at */
252 /* the name of the workspace, as is done in WmWrkspace.c? */
254 /* Easy but slow way to do this would be to use XGetAtomName(). */
255 /* To avoid XServer round trips (and to weed out invalid WS names) */
256 /* we look through workspaces attached to this screen for ID matches. */
257 char *cwsP = NULL, *tmpP, *wsNameP;
261 for (i = 0; i < pCD->numInhabited; i++)
263 if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
264 != (WmWorkspaceData *)NULL)
269 pLen = strlen(wsNameP) + 1; /* 1 for null termination */
270 if ((cwsP = (char *)XtMalloc(pLen * sizeof(char)))
274 strcpy(cwsP, wsNameP);
278 pLen += strlen(wsNameP) + 1; /* 1 for space */
279 if ((tmpP = (char *)XtRealloc(cwsP, pLen * sizeof(char)))
282 XtFree((char *)cwsP);
287 strcat(cwsP, wsNameP);
296 addClientToList(ClientData ***cdList, int *nClients, ClientData *pCD)
298 ClientData **newPtr = (ClientData **)
299 XtRealloc((char *)*cdList, (*nClients + 1) * sizeof(ClientData *));
301 if (newPtr == (ClientData **)NULL)
303 if (*cdList != (ClientData **)NULL)
304 XtFree((char *)*cdList);
309 newPtr[*nClients] = pCD;
316 clientWorkspaceCompare(const void *ppCD1, const void *ppCD2)
318 ClientData *pCD1 = *(ClientData **)ppCD1;
319 ClientData *pCD2 = *(ClientData **)ppCD2;
322 /* Sort first by screen. */
323 if ((screenDiff = pCD1->pSD->screen - pCD2->pSD->screen) != 0)
326 /* If same screen, sort by workspace id. */
327 /* How do we handle clients that live in more than one workspace? */
328 /* For now, pick the "current" one - if not in active workspace, */
329 /* this will simply be the first one in the client's list. */
330 return (int)(pCD1->pWsList[pCD1->currentWsc].wsID -
331 pCD2->pWsList[pCD2->currentWsc].wsID);
335 * Assumes: wmGD.clientResourceDB is non-NULL
338 getClientResource(char *clientID, char *fmtStr)
340 char resourceBuf[MAX_RESOURCE_LEN];
342 XrmValue resourceValue;
344 sprintf(resourceBuf, fmtStr, clientID);
345 if (XrmGetResource(wmGD.clientResourceDB, resourceBuf, resourceBuf,
346 &resourceType, &resourceValue))
347 return (char *)resourceValue.addr;
353 * Assumes: pCD has non-NULL smClientID;
354 * wmGD.clientResourceDB is non-NULL
357 getXSMPResource(ClientData *pCD, int resourceFlag, char *fmtStr)
359 if (RESTORE_RESOURCE(pCD, resourceFlag))
360 return getClientResource(pCD->smClientID, fmtStr);
366 * Return True if client is XSMP, False otherwise.
369 findXSMPClientDBMatch(ClientData *pCD, char **workSpaceNamesP)
371 if (pCD->smClientID != (String)NULL)
373 if (wmGD.clientResourceDB != (XrmDatabase)NULL)
377 if ((resourcePtr = getXSMPResource(pCD, WMSAVE_X, xPositionStr))
380 pCD->clientX = atoi(resourcePtr);
381 pCD->clientFlags |= SM_X;
384 if ((resourcePtr = getXSMPResource(pCD, WMSAVE_Y, yPositionStr))
387 pCD->clientY = atoi(resourcePtr);
388 pCD->clientFlags |= SM_Y;
391 if ((resourcePtr = getXSMPResource(pCD, WMSAVE_WIDTH,
395 pCD->clientWidth = atoi(resourcePtr);
396 pCD->clientFlags |= SM_WIDTH;
399 if ((resourcePtr = getXSMPResource(pCD, WMSAVE_HEIGHT,
403 pCD->clientHeight = atoi(resourcePtr);
404 pCD->clientFlags |= SM_HEIGHT;
407 if ((resourcePtr = getXSMPResource(pCD, WMSAVE_STATE,
412 (strcmp(resourcePtr, normalStateStr) == 0) ?
413 NORMAL_STATE : MINIMIZED_STATE;
414 pCD->clientFlags |= SM_CLIENT_STATE;
417 if ((workSpaceNamesP != (char **)NULL) &&
418 ((resourcePtr = getXSMPResource(pCD, WMSAVE_WORKSPACES,
422 *workSpaceNamesP = XtNewString(resourcePtr);
426 /* Always return True for XSMP clients. */
434 getProxyClientInfo(ClientData *pCD, ProxyClientInfo *proxyClientInfo)
436 XTextProperty textProperty;
439 /* WM_COMMAND is required; WM_CLIENT_MACHINE is optional. */
440 if (!XGetTextProperty(wmGD.display, pCD->client, &textProperty,
444 if ((textProperty.encoding != XA_STRING) ||
445 (textProperty.format != 8) ||
446 (textProperty.value[0] == '\0'))
448 if (textProperty.value)
449 free((char *)textProperty.value);
454 /* Convert embedded NULL characters to space characters. */
455 /* (If last char is NULL, leave it alone) */
456 for (i = 0; i < textProperty.nitems - 1; i++)
458 if (textProperty.value[i] == '\0')
459 textProperty.value[i] = ' ';
462 proxyClientInfo->screen = pCD->pSD->screen;
463 proxyClientInfo->wmCommand = (char *)textProperty.value;
465 /* Since WM_CLIENT_MACHINE is optional, don't fail if not found. */
466 if (XGetWMClientMachine(wmGD.display, pCD->client, &textProperty))
467 proxyClientInfo->wmClientMachine = (char *)textProperty.value;
468 else proxyClientInfo->wmClientMachine = (char *)NULL;
470 proxyClientInfo->clientID = (char *)NULL;
476 * IMPORTANT: This function is called by XrmEnumerateDatabase().
477 * It calls other Xrm*() functions - if dtwm is threaded, THIS
478 * WILL HANG. For now, dtwm is NOT threaded, so no problem.
481 cmpProxyClientProc(XrmDatabase *clientDB, XrmBindingList bindingList,
482 XrmQuarkList quarkList, XrmRepresentation *reps,
483 XrmValue *value, XPointer uData)
487 char *wmClientMachine;
488 char *clientID = (char *)value->addr;
489 ProxyClientInfo *proxyClientInfo = (ProxyClientInfo *)uData;
492 getClientResource(clientID, wmCommandStr)) == (char *)NULL) ||
493 (strcmp(wmCommand, proxyClientInfo->wmCommand) != 0) ||
495 getClientResource(clientID, screenStr)) == (char *)NULL) ||
496 (atoi(clientScreen) != proxyClientInfo->screen))
499 /* So far so good. If WM_CLIENT_MACHINE missing from either, */
500 /* or if it is set in both and it's the same, we've got a match! */
501 if (!proxyClientInfo->wmClientMachine ||
503 getClientResource(clientID, wmClientMachineStr)) == (char *)NULL) ||
504 (strcmp(proxyClientInfo->wmClientMachine, wmClientMachine) == 0))
506 proxyClientInfo->clientID = clientID;
514 findProxyClientID(ClientData *pCD)
516 ProxyClientInfo proxyClientInfo;
517 char *clientID = (char *)NULL;
518 static XrmName proxyName[2] = {NULLQUARK, NULLQUARK};
519 static XrmClass proxyClass[2] = {NULLQUARK, NULLQUARK};
521 if (proxyName[0] == NULLQUARK)
523 proxyName[0] = XrmStringToName(proxyClientStr);
524 proxyClass[0] = XrmStringToClass(proxyClientStr);
528 * We need to match the screen and
529 * the WM_COMMAND and WM_CLIENT_MACHINE properties.
531 if (!getProxyClientInfo(pCD, &proxyClientInfo))
534 if (XrmEnumerateDatabase(wmGD.clientResourceDB, proxyName, proxyClass,
535 XrmEnumOneLevel, cmpProxyClientProc,
536 (XPointer)&proxyClientInfo))
537 clientID = proxyClientInfo.clientID;
539 if (proxyClientInfo.wmCommand)
540 free(proxyClientInfo.wmCommand);
541 if (proxyClientInfo.wmClientMachine)
542 free(proxyClientInfo.wmClientMachine);
548 * Return True if client is *not* XSMP and is listed in the resource DB
549 * and no checkpoint done yet. Also remove entry from DB if found.
552 findProxyClientDBMatch(ClientData *pCD, char **workSpaceNamesP)
554 if ((pCD->smClientID == (String)NULL) &&
555 (wmGD.clientResourceDB != (XrmDatabase)NULL) &&
556 (!smClientDBCheckpointed))
560 if ((proxyClientID = findProxyClientID(pCD)) != (char *)NULL)
565 getClientResource(proxyClientID, xPositionStr))
568 pCD->clientX = atoi(resourcePtr);
569 pCD->clientFlags |= SM_X;
573 getClientResource(proxyClientID, yPositionStr))
576 pCD->clientY = atoi(resourcePtr);
577 pCD->clientFlags |= SM_Y;
581 getClientResource(proxyClientID, widthSizeStr))
584 pCD->clientWidth = atoi(resourcePtr);
585 pCD->clientFlags |= SM_WIDTH;
589 getClientResource(proxyClientID, heightSizeStr))
592 pCD->clientHeight = atoi(resourcePtr);
593 pCD->clientFlags |= SM_HEIGHT;
597 getClientResource(proxyClientID, initialStateStr))
601 (strcmp(resourcePtr, normalStateStr) == 0) ?
602 NORMAL_STATE : MINIMIZED_STATE;
603 pCD->clientFlags |= SM_CLIENT_STATE;
606 if ((workSpaceNamesP != (char **)NULL) &&
608 getClientResource(proxyClientID, workspacesStr))
611 *workSpaceNamesP = XtNewString(resourcePtr);
622 * Translate the client geometry into what's needed on restore.
625 getClientGeometry(ClientData *pCD, int *clientX, int *clientY,
626 unsigned int *clientWd, unsigned int *clientHt)
628 *clientX = pCD->clientX;
629 *clientY = pCD->clientY;
630 *clientWd = (pCD->widthInc != 0) ?
631 (pCD->clientWidth - pCD->baseWidth) / pCD->widthInc :
633 *clientHt = (pCD->heightInc != 0) ?
634 (pCD->clientHeight - pCD->baseHeight) / pCD->heightInc :
639 * Assumes: pCD->smClientID is not NULL
642 saveXSMPClient(FILE *fp, ClientData *pCD)
644 int clientX, clientY;
645 unsigned int clientWd, clientHt;
646 char *clientID = pCD->smClientID;
648 fprintf(fp, dbClientFormat, XSMPClientStr, clientID, clientID);
650 getClientGeometry(pCD, &clientX, &clientY, &clientWd, &clientHt);
652 if (SAVE_RESOURCE(pCD, WMSAVE_X))
654 fprintf(fp, xPositionStr, clientID);
655 fprintf(fp, intArg, clientX);
658 if (SAVE_RESOURCE(pCD, WMSAVE_Y))
660 fprintf(fp, yPositionStr, clientID);
661 fprintf(fp, intArg, clientY);
664 if (!pCD->pSD->useIconBox)
666 WmScreenData *pSD = pCD->pSD;
667 WmWorkspaceData *pWS;
670 for (i = 0; i < pCD->numInhabited; i++)
672 if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
673 != (WmWorkspaceData *)NULL)
675 if (SAVE_RESOURCE(pCD, WMSAVE_ICON_X))
677 fprintf(fp, iconXPosStr, clientID, pWS->name);
678 fprintf(fp, intArg, pCD->pWsList[i].iconX);
681 if (SAVE_RESOURCE(pCD, WMSAVE_ICON_Y))
683 fprintf(fp, iconYPosStr, clientID, pWS->name);
684 fprintf(fp, intArg, pCD->pWsList[i].iconY);
690 if (SAVE_RESOURCE(pCD, WMSAVE_WIDTH))
692 fprintf(fp, widthSizeStr, clientID);
693 fprintf(fp, intArg, clientWd);
696 if (SAVE_RESOURCE(pCD, WMSAVE_HEIGHT))
698 fprintf(fp, heightSizeStr, clientID);
699 fprintf(fp, intArg, clientHt);
702 if (SAVE_RESOURCE(pCD, WMSAVE_STATE))
706 clientState = pCD->clientState & ~UNSEEN_STATE;
708 fprintf(fp, initialStateStr, clientID);
709 fprintf(fp, strArg, (clientState == NORMAL_STATE) ?
710 normalStateStr : iconicStateStr);
713 if (SAVE_RESOURCE(pCD, WMSAVE_WORKSPACES))
715 char *clientWorkspaces = getClientWorkspaces(pCD);
717 if (clientWorkspaces != (char *)NULL)
719 fprintf(fp, workspacesStr, clientID);
720 fprintf(fp, strArg, clientWorkspaces);
721 XtFree(clientWorkspaces);
729 * Assumes: pCD->smClientID is NULL
732 saveProxyClient(FILE *fp, ClientData *pCD, int clientIDNum)
736 ProxyClientInfo proxyClientInfo;
737 int clientX, clientY;
738 unsigned int clientWd, clientHt;
739 char *clientWorkspaces;
741 if (!getProxyClientInfo(pCD, &proxyClientInfo))
744 sprintf(clientID, "%d", clientIDNum);
745 fprintf(fp, dbClientFormat, proxyClientStr, clientID, clientID);
747 fprintf(fp, screenStr, clientID);
748 fprintf(fp, intArg, proxyClientInfo.screen);
750 fprintf(fp, wmCommandStr, clientID);
751 fprintf(fp, strArg, proxyClientInfo.wmCommand);
752 free(proxyClientInfo.wmCommand);
754 if (proxyClientInfo.wmClientMachine != (char *)NULL)
756 fprintf(fp, wmClientMachineStr, clientID);
757 fprintf(fp, strArg, proxyClientInfo.wmClientMachine);
758 free(proxyClientInfo.wmClientMachine);
761 getClientGeometry(pCD, &clientX, &clientY, &clientWd, &clientHt);
763 fprintf(fp, xPositionStr, clientID);
764 fprintf(fp, intArg, clientX);
766 fprintf(fp, yPositionStr, clientID);
767 fprintf(fp, intArg, clientY);
769 if (!pCD->pSD->useIconBox)
771 WmScreenData *pSD = pCD->pSD;
772 WmWorkspaceData *pWS;
775 for (i = 0; i < pCD->numInhabited; i++)
777 if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
778 != (WmWorkspaceData *)NULL)
780 fprintf(fp, iconXPosStr, clientID, pWS->name);
781 fprintf(fp, intArg, pCD->pWsList[i].iconX);
783 fprintf(fp, iconYPosStr, clientID, pWS->name);
784 fprintf(fp, intArg, pCD->pWsList[i].iconY);
789 fprintf(fp, widthSizeStr, clientID);
790 fprintf(fp, intArg, clientWd);
792 fprintf(fp, heightSizeStr, clientID);
793 fprintf(fp, intArg, clientHt);
795 clientState = pCD->clientState & ~UNSEEN_STATE;
797 fprintf(fp, initialStateStr, clientID);
798 fprintf(fp, strArg, (clientState == NORMAL_STATE) ?
799 normalStateStr : iconicStateStr);
801 clientWorkspaces = getClientWorkspaces(pCD);
802 if (clientWorkspaces != (char *)NULL)
804 fprintf(fp, workspacesStr, clientID);
805 fprintf(fp, strArg, clientWorkspaces);
806 XtFree(clientWorkspaces);
813 dbRemoveProxyClientEntry(char *proxyClientID)
815 char resourceBuf[MAX_RESOURCE_LEN];
817 /* Remove entry from DB. Since Xrm does not provide a means */
818 /* of removing something from the DB, we blank out key info. */
819 sprintf(resourceBuf, wmCommandStr, proxyClientID);
820 strcat(resourceBuf, ":");
821 XrmPutLineResource(&wmGD.clientResourceDB, resourceBuf);
825 * Add callbacks used in session management.
830 XtAddCallback(wmGD.topLevelW, XtNsaveCallback,
831 smSaveYourselfCallback, (XtPointer)NULL);
832 XtAddCallback(wmGD.topLevelW, XtNdieCallback,
833 smDieCallback, (XtPointer)NULL);
837 * Resign from session management, closing any connections made.
844 XtVaSetValues(wmGD.topLevelW,
845 XtNjoinSession, False,
851 * Exit the WM, being polite by first resigning from session mgmt.
861 * Read our private database of client resources.
864 LoadClientResourceDB(void)
866 char dbFileName[MAXPATHLEN];
868 buildDBFileName(dbFileName, False);
870 return XrmGetFileDatabase(dbFileName);
874 * Write our private database of client resources.
877 SaveClientResourceDB(void)
880 char dbFileName[MAXPATHLEN];
886 ClientListEntry *pCL;
888 /* Iterate through client list, saving */
889 /* appropriate resources for each. */
890 buildDBFileName(dbFileName, True);
891 if ((fp = fopen(dbFileName, "w")) == (FILE *)NULL)
892 return (XrmDatabase)NULL;
894 XtVaGetValues(wmGD.topLevelW,
895 XtNsessionID, &mySessionID,
897 fprintf(fp, dbHeader, dtwmFileName, "dtwm Version XSMP1.0",
898 (mySessionID != (String)NULL) ? mySessionID : "");
900 for (scr = 0; scr < wmGD.numScreens; scr++)
902 pSD = &(wmGD.Screens[scr]);
904 for (pCL = pSD->clientList;
905 pCL != (ClientListEntry *)NULL;
906 pCL = pCL->nextSibling)
908 /* Each client may be in list twice: normal & icon */
909 if (pCL->type != NORMAL_STATE)
914 if (pCD->smClientID != (String)NULL)
916 saveXSMPClient(fp, pCD);
920 if (saveProxyClient(fp, pCD, clientIDNum))
928 /* Retrieve database from file. */
929 return XrmGetFileDatabase(dbFileName);
933 * As with FindDtSessionMatch(), sets properties and then returns
934 * an allocated string of workspace names. This string must be
935 * freed by the caller using XtFree().
938 FindClientDBMatch(ClientData *pCD, char **workSpaceNamesP)
940 return (findXSMPClientDBMatch(pCD, workSpaceNamesP) ||
941 findProxyClientDBMatch(pCD, workSpaceNamesP));
945 GetSmClientIdClientList(ClientData ***clients, int *nClients)
950 ClientListEntry *pCL;
953 *clients = (ClientData **)NULL;
954 for (scr = 0; scr < wmGD.numScreens; scr++)
956 pSD = &(wmGD.Screens[scr]);
958 for (pCL = pSD->clientList;
959 pCL != (ClientListEntry *)NULL;
960 pCL = pCL->nextSibling)
962 /* Each client may be in list twice: normal & icon */
963 if (pCL->type != NORMAL_STATE)
968 if (pCD->smClientID != (String)NULL)
970 /* addClientToList() reclaims memory on failure. */
971 if (!addClientToList(clients, nClients, pCD))
981 SortClientListByWorkspace(ClientData **clients, int nClients)
985 qsort((void *)clients, nClients,
986 sizeof(ClientData *), clientWorkspaceCompare);
991 LoadClientIconPositions(ClientData *pCD)
993 char resourceBuf[MAX_RESOURCE_LEN];
994 WmScreenData *pSD = pCD->pSD;
995 WmWorkspaceData *pWS;
999 if (wmGD.clientResourceDB == (XrmDatabase)NULL)
1002 if (pCD->smClientID != (String)NULL)
1004 for (i = 0; i < pCD->numInhabited; i++)
1006 if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
1007 != (WmWorkspaceData *)NULL)
1009 sprintf(resourceBuf, iconXPosStr, "%s", pWS->name);
1011 getXSMPResource(pCD, WMSAVE_ICON_X, resourceBuf))
1014 pCD->pWsList[i].iconX = atoi(resourcePtr);
1015 pCD->clientFlags |= SM_ICON_X;
1018 sprintf(resourceBuf, iconYPosStr, "%s", pWS->name);
1020 getXSMPResource(pCD, WMSAVE_ICON_Y, resourceBuf))
1023 pCD->pWsList[i].iconY = atoi(resourcePtr);
1024 pCD->clientFlags |= SM_ICON_Y;
1032 if (!smClientDBCheckpointed)
1034 char *proxyClientID;
1036 if ((proxyClientID = findProxyClientID(pCD)) != (char *)NULL)
1038 for (i = 0; i < pCD->numInhabited; i++)
1040 if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
1041 != (WmWorkspaceData *)NULL)
1043 sprintf(resourceBuf, iconXPosStr, "%s", pWS->name);
1045 getClientResource(proxyClientID, resourceBuf))
1048 pCD->pWsList[i].iconX = atoi(resourcePtr);
1049 pCD->clientFlags |= SM_ICON_X;
1052 sprintf(resourceBuf, iconYPosStr, "%s", pWS->name);
1054 getClientResource(proxyClientID, resourceBuf))
1057 pCD->pWsList[i].iconY = atoi(resourcePtr);
1058 pCD->clientFlags |= SM_ICON_Y;
1062 dbRemoveProxyClientEntry(proxyClientID);