cdesktopenv/cde/programs/dtwm/WmXSMP.c

1141 lines
28 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* (c) Copyright 1996 Digital Equipment Corporation.
* (c) Copyright 1996 Hewlett-Packard Company.
* (c) Copyright 1996 International Business Machines Corp.
* (c) Copyright 1996 Sun Microsystems, Inc.
* (c) Copyright 1996 Novell, Inc.
* (c) Copyright 1996 FUJITSU LIMITED.
* (c) Copyright 1996 Hitachi.
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/param.h>
#include <X11/Intrinsic.h>
#include <X11/Shell.h>
#include <X11/Xatom.h>
#include <X11/SM/SM.h>
#include <Xm/XmP.h>
#include "WmGlobal.h"
#include "WmXSMP.h"
#include "WmWrkspace.h"
#include <Dt/Session.h>
extern XtPointer _XmStringUngenerate(XmString, XmStringTag,
XmTextType, XmTextType);
typedef struct _ProxyClientInfo
{
int screen;
char *wmCommand;
char *wmClientMachine;
char *clientID;
} ProxyClientInfo;
#define RESTORE_RESOURCE(pCD, resFlag) \
((pCD)->ignoreWMSaveHints || !((pCD)->wmSaveHintFlags & (resFlag)))
#define SAVE_RESOURCE(pCD, resFlag) RESTORE_RESOURCE(pCD, resFlag)
#define MAX_RESOURCE_LEN 1024
static char *dtwmFileName = "dtwm.db";
/* Fully-qualified resource names/classes. */
static char *xPositionStr = "%s.position.x";
static char *yPositionStr = "%s.position.y";
static char *widthSizeStr = "%s.size.width";
static char *heightSizeStr = "%s.size.height";
static char *initialStateStr = "%s.initialState";
static char *wmCommandStr = "%s.wmCommand";
static char *wmClientMachineStr = "%s.wmClientMachine";
static char *screenStr = "%s.screen";
static char *workspacesStr = "%s.workspaces";
static char *iconXPosStr = "%s.iconPos.x.%s";
static char *iconYPosStr = "%s.iconPos.y.%s";
static char *instantTitleStr = "%s.instantTitle";
/* Header for private database. */
static char *dbHeader = "\
! %s\n\
!\n\
.version: %s\n\
.dtwmID: %s\n";
/* Format for client entries in database. */
static char *dbClientFormat = "\
!\n\
%s.%s: %s\n\
!\n";
static char *intArg = ": %d\n";
static char *strArg = ": %s\n";
static char *normalStateStr = "NormalState";
static char *iconicStateStr = "IconicState";
static char *XSMPClientStr = "Client";
static char *proxyClientStr = "ProxyClient";
/* Flag to tell us how to treat ProxyClient info. */
static Boolean smClientDBCheckpointed = False;
/*
* Prototypes
*/
/* Session mgmt callbacks. */
static void smSaveYourselfCallback(Widget, XtPointer, XtPointer);
static void smDieCallback(Widget, XtPointer, XtPointer);
/* Build client database file name. */
static void buildDBFileName(char [MAXPATHLEN], Boolean);
/* Get string of client's workspaces. */
static char *getClientWorkspaces(ClientData *);
/* Get string of client's instant title. */
static char *getClientInstantTitle(ClientData *);
/* List-of-clients utilities. */
static Boolean addClientToList(ClientData ***, int *, ClientData *);
static int clientWorkspaceCompare(const void *, const void *);
/* XSMP/Proxy functions to save/restore resources. */
static char *getClientResource(char *, char *);
static char *getXSMPResource(ClientData *, int, char *);
static void getClientGeometry(ClientData *, int *, int *,
unsigned int *, unsigned int *);
static Boolean getProxyClientInfo(ClientData *, ProxyClientInfo *);
static Bool fillClientIDProc(XrmDatabase *, XrmBindingList,
XrmQuarkList, XrmRepresentation *,
XrmValue *, XPointer);
static Bool cmpProxyClient(char *clientID, ProxyClientInfo *proxyClientInfo);
static char *findProxyClientID(ClientData *);
static Boolean findXSMPClientDBMatch(ClientData *, char **);
static Boolean findProxyClientDBMatch(ClientData *, char **);
static Boolean saveXSMPClient(FILE *, ClientData *);
static Boolean saveProxyClient(FILE *, ClientData *, int);
static void dbRemoveProxyClientEntry(char *);
static void
smSaveYourselfCallback(Widget w, XtPointer clientData, XtPointer callData)
{
XtCheckpointToken cpToken = (XtCheckpointToken)callData;
XrmDatabase newClientDB;
int scr;
static Boolean firstTime = True;
/*
* This callback will be called on connection to the Session Manager.
* At that time, we don't want to save any state, and we don't
* want to request the second phase.
*/
if (firstTime)
{
firstTime = False;
return;
}
/* Only respond to Local and Both save requests. */
if ((cpToken->save_type != SmSaveLocal) &&
(cpToken->save_type != SmSaveBoth))
return;
if (cpToken->shutdown &&
(cpToken->cancel_shutdown ||
cpToken->request_cancel ||
!cpToken->save_success))
return; /* Return, maintaining current state */
/* If first phase, request notification when all other clients saved. */
if (cpToken->phase == 1)
{
cpToken->request_next_phase = True;
return;
}
/* Second phase: all other clients saved; now I can save myself. */
/* Copied from WmEvent.c. */
for (scr = 0; scr < wmGD.numScreens; scr++)
{
if (wmGD.Screens[scr].managed)
{
/*
* Write out current workspace, frontpanel
* position and iconbox position and size.
*/
SaveResources(&wmGD.Screens[scr]);
}
}
/*
* NEW FOR SESSION MANAGEMENT: Write private client resource database.
* Destroy old client database and save new one.
*/
if ((newClientDB = SaveClientResourceDB())
!= (XrmDatabase)NULL)
{
if (wmGD.clientResourceDB != (XrmDatabase)NULL)
XrmDestroyDatabase(wmGD.clientResourceDB);
wmGD.clientResourceDB = newClientDB;
smClientDBCheckpointed = True;
}
}
static void
smDieCallback(Widget w, XtPointer clientData, XtPointer callData)
{
/* We assume we've saved our state by the time this is called. */
ExitWM(0);
}
static void
buildDBFileName(char fileNameBuf[MAXPATHLEN], Boolean doingSave)
{
char *savePath = (char *)NULL;
fileNameBuf[0] = '\0';
if (doingSave)
{
char *saveFile = (char *)NULL;
char *ptr;
if (DtSessionSavePath(wmGD.topLevelW, &savePath, &saveFile))
{
XtFree(saveFile);
if ((ptr = strrchr(savePath, '/')) != (char *)NULL)
*ptr = '\0';
if (strlen(savePath) + strlen(dtwmFileName) + 2 < MAXPATHLEN)
sprintf(fileNameBuf, "%s/%s", savePath, dtwmFileName);
XtFree(savePath);
}
}
else
{
if (DtSessionRestorePath(wmGD.topLevelW, &savePath, dtwmFileName))
{
if ((int)strlen(savePath) < MAXPATHLEN)
strcpy(fileNameBuf, savePath);
XtFree(savePath);
}
}
if (fileNameBuf[0] == '\0')
strcpy(fileNameBuf, dtwmFileName);
}
static char *
getClientWorkspaces(ClientData *pCD)
{
WmScreenData *pSD = pCD->pSD;
WmWorkspaceData *pWS;
/* Should we use _DtWmParseMakeQuotedString() when looking at */
/* the name of the workspace, as is done in WmWrkspace.c? */
/* Easy but slow way to do this would be to use XGetAtomName(). */
/* To avoid XServer round trips (and to weed out invalid WS names) */
/* we look through workspaces attached to this screen for ID matches. */
char *cwsP = NULL, *tmpP, *wsNameP;
int pLen = 0;
int i;
for (i = 0; i < pCD->numInhabited; i++)
{
if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
!= (WmWorkspaceData *)NULL)
{
wsNameP = pWS->name;
if (pLen == 0)
{
pLen = strlen(wsNameP) + 1; /* 1 for null termination */
if ((cwsP = (char *)XtMalloc(pLen * sizeof(char)))
== (char *)NULL)
return (char *)NULL;
strcpy(cwsP, wsNameP);
}
else
{
pLen += strlen(wsNameP) + 1; /* 1 for space */
if ((tmpP = (char *)XtRealloc(cwsP, pLen * sizeof(char)))
== (char *)NULL)
{
XtFree((char *)cwsP);
return (char *)NULL;
}
cwsP = tmpP;
strcat(cwsP, " ");
strcat(cwsP, wsNameP);
}
}
}
return cwsP;
}
static char *
getClientInstantTitle(ClientData *pCD)
{
if (!pCD->instantTitle) return NULL;
return _XmStringUngenerate(pCD->instantTitle, NULL, XmCHARSET_TEXT,
XmCHARSET_TEXT);
}
static Boolean
addClientToList(ClientData ***cdList, int *nClients, ClientData *pCD)
{
ClientData **newPtr = (ClientData **)
XtRealloc((char *)*cdList, (*nClients + 1) * sizeof(ClientData *));
if (newPtr == (ClientData **)NULL)
{
if (*cdList != (ClientData **)NULL)
XtFree((char *)*cdList);
return False;
}
*cdList = newPtr;
newPtr[*nClients] = pCD;
(*nClients)++;
return True;
}
static int
clientWorkspaceCompare(const void *ppCD1, const void *ppCD2)
{
ClientData *pCD1 = *(ClientData **)ppCD1;
ClientData *pCD2 = *(ClientData **)ppCD2;
int screenDiff;
/* Sort first by screen. */
if ((screenDiff = pCD1->pSD->screen - pCD2->pSD->screen) != 0)
return screenDiff;
/* If same screen, sort by workspace id. */
/* How do we handle clients that live in more than one workspace? */
/* For now, pick the "current" one - if not in active workspace, */
/* this will simply be the first one in the client's list. */
return (int)(pCD1->pWsList[pCD1->currentWsc].wsID -
pCD2->pWsList[pCD2->currentWsc].wsID);
}
/*
* Assumes: wmGD.clientResourceDB is non-NULL
*/
static char *
getClientResource(char *clientID, char *fmtStr)
{
char resourceBuf[MAX_RESOURCE_LEN];
char *resourceType;
XrmValue resourceValue;
sprintf(resourceBuf, fmtStr, clientID);
if (XrmGetResource(wmGD.clientResourceDB, resourceBuf, resourceBuf,
&resourceType, &resourceValue))
return (char *)resourceValue.addr;
return (char *)NULL;
}
/*
* Assumes: pCD has non-NULL smClientID;
* wmGD.clientResourceDB is non-NULL
*/
static char *
getXSMPResource(ClientData *pCD, int resourceFlag, char *fmtStr)
{
if (RESTORE_RESOURCE(pCD, resourceFlag))
return getClientResource(pCD->smClientID, fmtStr);
return (char *)NULL;
}
/*
* Return True if client is XSMP, False otherwise.
*/
static Boolean
findXSMPClientDBMatch(ClientData *pCD, char **workSpaceNamesP)
{
if (pCD->smClientID != (String)NULL)
{
if (wmGD.clientResourceDB != (XrmDatabase)NULL)
{
char *resourcePtr;
if ((resourcePtr = getXSMPResource(pCD, WMSAVE_X, xPositionStr))
!= (char *)NULL)
{
pCD->clientX = atoi(resourcePtr);
pCD->clientFlags |= SM_X;
}
if ((resourcePtr = getXSMPResource(pCD, WMSAVE_Y, yPositionStr))
!= (char *)NULL)
{
pCD->clientY = atoi(resourcePtr);
pCD->clientFlags |= SM_Y;
}
if ((resourcePtr = getXSMPResource(pCD, WMSAVE_WIDTH,
widthSizeStr))
!= (char *)NULL)
{
pCD->clientWidth = atoi(resourcePtr);
pCD->clientFlags |= SM_WIDTH;
}
if ((resourcePtr = getXSMPResource(pCD, WMSAVE_HEIGHT,
heightSizeStr))
!= (char *)NULL)
{
pCD->clientHeight = atoi(resourcePtr);
pCD->clientFlags |= SM_HEIGHT;
}
if ((resourcePtr = getXSMPResource(pCD, WMSAVE_STATE,
initialStateStr))
!= (char *)NULL)
{
pCD->clientState =
(strcmp(resourcePtr, normalStateStr) == 0) ?
NORMAL_STATE : MINIMIZED_STATE;
pCD->clientFlags |= SM_CLIENT_STATE;
}
if ((workSpaceNamesP != (char **)NULL) &&
((resourcePtr = getXSMPResource(pCD, WMSAVE_WORKSPACES,
workspacesStr))
!= (char *)NULL))
{
*workSpaceNamesP = XtNewString(resourcePtr);
}
if ((resourcePtr = getXSMPResource(pCD, WMSAVE_INSTANT_TITLE,
instantTitleStr))
!= (char *)NULL)
{
pCD->instantTitle = XmStringCreateLocalized(resourcePtr);
}
}
/* Always return True for XSMP clients. */
return True;
}
return False;
}
static Boolean
getProxyClientInfo(ClientData *pCD, ProxyClientInfo *proxyClientInfo)
{
XTextProperty textProperty;
unsigned long i;
/* WM_COMMAND is required; WM_CLIENT_MACHINE is optional. */
if (!XGetTextProperty(wmGD.display, pCD->client, &textProperty,
XA_WM_COMMAND))
return False;
if ((textProperty.encoding != XA_STRING) ||
(textProperty.format != 8) ||
(textProperty.value[0] == '\0'))
{
if (textProperty.value)
free((char *)textProperty.value);
return False;
}
/* Convert embedded NULL characters to space characters. */
/* (If last char is NULL, leave it alone) */
for (i = 0; i < textProperty.nitems - 1; i++)
{
if (textProperty.value[i] == '\0')
textProperty.value[i] = ' ';
}
proxyClientInfo->screen = pCD->pSD->screen;
proxyClientInfo->wmCommand = (char *)textProperty.value;
/* Since WM_CLIENT_MACHINE is optional, don't fail if not found. */
if (XGetWMClientMachine(wmGD.display, pCD->client, &textProperty))
proxyClientInfo->wmClientMachine = (char *)textProperty.value;
else proxyClientInfo->wmClientMachine = (char *)NULL;
proxyClientInfo->clientID = (char *)NULL;
return True;
}
static Bool
fillClientIDProc(XrmDatabase *clientDB, XrmBindingList bindingList,
XrmQuarkList quarkList, XrmRepresentation *reps,
XrmValue *value, XPointer uData)
{
static int i;
int nList;
char *clientID = value->addr;
char ***pClientIDList = (char ***) uData;
char **clientIDList = *pClientIDList;
if (!(clientID && *clientID)) return FALSE;
if (clientIDList) ++i;
else i = 0;
nList = 2 + i;
if (i < 0 || nList < 2) return TRUE;
*pClientIDList = realloc(*pClientIDList, nList * sizeof(char *));
clientIDList = i + *pClientIDList;
clientIDList[0] = clientID;
clientIDList[1] = NULL;
return FALSE;
}
static Bool
cmpProxyClient(char *clientID, ProxyClientInfo *proxyClientInfo)
{
char *clientScreen;
char *wmCommand;
char *wmClientMachine;
if (((wmCommand =
getClientResource(clientID, wmCommandStr)) == (char *)NULL) ||
(strcmp(wmCommand, proxyClientInfo->wmCommand) != 0) ||
((clientScreen =
getClientResource(clientID, screenStr)) == (char *)NULL) ||
(atoi(clientScreen) != proxyClientInfo->screen))
return FALSE;
/* So far so good. If WM_CLIENT_MACHINE missing from either, */
/* or if it is set in both and it's the same, we've got a match! */
if (!proxyClientInfo->wmClientMachine ||
((wmClientMachine =
getClientResource(clientID, wmClientMachineStr)) == (char *)NULL) ||
(strcmp(proxyClientInfo->wmClientMachine, wmClientMachine) == 0))
return TRUE;
return FALSE;
}
static char *
findProxyClientID(ClientData *pCD)
{
ProxyClientInfo proxyClientInfo;
int i;
char *clientID = NULL;
char **clientIDList = NULL;
static XrmName proxyName[2] = {NULLQUARK, NULLQUARK};
static XrmClass proxyClass[2] = {NULLQUARK, NULLQUARK};
if (proxyName[0] == NULLQUARK)
{
proxyName[0] = XrmStringToName(proxyClientStr);
proxyClass[0] = XrmStringToClass(proxyClientStr);
}
/*
* We need to match the screen and
* the WM_COMMAND and WM_CLIENT_MACHINE properties.
*/
if (!getProxyClientInfo(pCD, &proxyClientInfo)) return clientID;
XrmEnumerateDatabase(wmGD.clientResourceDB, proxyName, proxyClass,
XrmEnumOneLevel, fillClientIDProc, (XPointer)&clientIDList);
for (i = 0; clientIDList && clientIDList[i]; ++i)
{
if (cmpProxyClient(clientIDList[i], &proxyClientInfo))
{
clientID = clientIDList[i];
break;
}
}
if (proxyClientInfo.wmCommand) free(proxyClientInfo.wmCommand);
if (proxyClientInfo.wmClientMachine) free(proxyClientInfo.wmClientMachine);
if (clientIDList) free(clientIDList);
return clientID;
}
/*
* Return True if client is *not* XSMP and is listed in the resource DB
* and no checkpoint done yet. Also remove entry from DB if found.
*/
static Boolean
findProxyClientDBMatch(ClientData *pCD, char **workSpaceNamesP)
{
if ((pCD->smClientID == (String)NULL) &&
(wmGD.clientResourceDB != (XrmDatabase)NULL) &&
(!smClientDBCheckpointed))
{
char *proxyClientID;
if ((proxyClientID = findProxyClientID(pCD)) != (char *)NULL)
{
char *resourcePtr;
if ((resourcePtr =
getClientResource(proxyClientID, xPositionStr))
!= (char *)NULL)
{
pCD->clientX = atoi(resourcePtr);
pCD->clientFlags |= SM_X;
}
if ((resourcePtr =
getClientResource(proxyClientID, yPositionStr))
!= (char *)NULL)
{
pCD->clientY = atoi(resourcePtr);
pCD->clientFlags |= SM_Y;
}
if ((resourcePtr =
getClientResource(proxyClientID, widthSizeStr))
!= (char *)NULL)
{
pCD->clientWidth = atoi(resourcePtr);
pCD->clientFlags |= SM_WIDTH;
}
if ((resourcePtr =
getClientResource(proxyClientID, heightSizeStr))
!= (char *)NULL)
{
pCD->clientHeight = atoi(resourcePtr);
pCD->clientFlags |= SM_HEIGHT;
}
if ((resourcePtr =
getClientResource(proxyClientID, initialStateStr))
!= (char *)NULL)
{
pCD->clientState =
(strcmp(resourcePtr, normalStateStr) == 0) ?
NORMAL_STATE : MINIMIZED_STATE;
pCD->clientFlags |= SM_CLIENT_STATE;
}
if ((workSpaceNamesP != (char **)NULL) &&
((resourcePtr =
getClientResource(proxyClientID, workspacesStr))
!= (char *)NULL))
{
*workSpaceNamesP = XtNewString(resourcePtr);
}
if ((resourcePtr =
getClientResource(proxyClientID, instantTitleStr))
!= (char *)NULL)
{
pCD->instantTitle = XmStringCreateLocalized(resourcePtr);
}
return True;
}
}
return False;
}
/*
* Translate the client geometry into what's needed on restore.
*/
static void
getClientGeometry(ClientData *pCD, int *clientX, int *clientY,
unsigned int *clientWd, unsigned int *clientHt)
{
*clientX = pCD->clientX;
*clientY = pCD->clientY;
*clientWd = (pCD->widthInc != 0) ?
(pCD->clientWidth - pCD->baseWidth) / pCD->widthInc :
pCD->clientWidth;
*clientHt = (pCD->heightInc != 0) ?
(pCD->clientHeight - pCD->baseHeight) / pCD->heightInc :
pCD->clientHeight;
}
/*
* Assumes: pCD->smClientID is not NULL
*/
static Boolean
saveXSMPClient(FILE *fp, ClientData *pCD)
{
int clientX, clientY;
unsigned int clientWd, clientHt;
char *clientID = pCD->smClientID;
fprintf(fp, dbClientFormat, XSMPClientStr, clientID, clientID);
getClientGeometry(pCD, &clientX, &clientY, &clientWd, &clientHt);
if (SAVE_RESOURCE(pCD, WMSAVE_X))
{
fprintf(fp, xPositionStr, clientID);
fprintf(fp, intArg, clientX);
}
if (SAVE_RESOURCE(pCD, WMSAVE_Y))
{
fprintf(fp, yPositionStr, clientID);
fprintf(fp, intArg, clientY);
}
if (!pCD->pSD->useIconBox)
{
WmScreenData *pSD = pCD->pSD;
WmWorkspaceData *pWS;
int i;
for (i = 0; i < pCD->numInhabited; i++)
{
if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
!= (WmWorkspaceData *)NULL)
{
if (SAVE_RESOURCE(pCD, WMSAVE_ICON_X))
{
fprintf(fp, iconXPosStr, clientID, pWS->name);
fprintf(fp, intArg, pCD->pWsList[i].iconX);
}
if (SAVE_RESOURCE(pCD, WMSAVE_ICON_Y))
{
fprintf(fp, iconYPosStr, clientID, pWS->name);
fprintf(fp, intArg, pCD->pWsList[i].iconY);
}
}
}
}
if (SAVE_RESOURCE(pCD, WMSAVE_WIDTH))
{
fprintf(fp, widthSizeStr, clientID);
fprintf(fp, intArg, clientWd);
}
if (SAVE_RESOURCE(pCD, WMSAVE_HEIGHT))
{
fprintf(fp, heightSizeStr, clientID);
fprintf(fp, intArg, clientHt);
}
if (SAVE_RESOURCE(pCD, WMSAVE_STATE))
{
int clientState;
clientState = pCD->clientState & ~UNSEEN_STATE;
fprintf(fp, initialStateStr, clientID);
fprintf(fp, strArg, (clientState == NORMAL_STATE) ?
normalStateStr : iconicStateStr);
}
if (SAVE_RESOURCE(pCD, WMSAVE_WORKSPACES))
{
char *clientWorkspaces = getClientWorkspaces(pCD);
if (clientWorkspaces != (char *)NULL)
{
fprintf(fp, workspacesStr, clientID);
fprintf(fp, strArg, clientWorkspaces);
XtFree(clientWorkspaces);
}
}
if (SAVE_RESOURCE(pCD, WMSAVE_INSTANT_TITLE))
{
char *title = getClientInstantTitle(pCD);
if (title)
{
fprintf(fp, instantTitleStr, clientID);
fprintf(fp, strArg, title);
XtFree(title);
}
}
return True;
}
/*
* Assumes: pCD->smClientID is NULL
*/
static Boolean
saveProxyClient(FILE *fp, ClientData *pCD, int clientIDNum)
{
char clientID[50];
int clientState;
ProxyClientInfo proxyClientInfo;
int clientX, clientY;
unsigned int clientWd, clientHt;
char *clientWorkspaces;
char *instantTitle;
if (!getProxyClientInfo(pCD, &proxyClientInfo))
return False;
sprintf(clientID, "%d", clientIDNum);
fprintf(fp, dbClientFormat, proxyClientStr, clientID, clientID);
fprintf(fp, screenStr, clientID);
fprintf(fp, intArg, proxyClientInfo.screen);
fprintf(fp, wmCommandStr, clientID);
fprintf(fp, strArg, proxyClientInfo.wmCommand);
free(proxyClientInfo.wmCommand);
if (proxyClientInfo.wmClientMachine != (char *)NULL)
{
fprintf(fp, wmClientMachineStr, clientID);
fprintf(fp, strArg, proxyClientInfo.wmClientMachine);
free(proxyClientInfo.wmClientMachine);
}
getClientGeometry(pCD, &clientX, &clientY, &clientWd, &clientHt);
fprintf(fp, xPositionStr, clientID);
fprintf(fp, intArg, clientX);
fprintf(fp, yPositionStr, clientID);
fprintf(fp, intArg, clientY);
if (!pCD->pSD->useIconBox)
{
WmScreenData *pSD = pCD->pSD;
WmWorkspaceData *pWS;
int i;
for (i = 0; i < pCD->numInhabited; i++)
{
if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
!= (WmWorkspaceData *)NULL)
{
fprintf(fp, iconXPosStr, clientID, pWS->name);
fprintf(fp, intArg, pCD->pWsList[i].iconX);
fprintf(fp, iconYPosStr, clientID, pWS->name);
fprintf(fp, intArg, pCD->pWsList[i].iconY);
}
}
}
fprintf(fp, widthSizeStr, clientID);
fprintf(fp, intArg, clientWd);
fprintf(fp, heightSizeStr, clientID);
fprintf(fp, intArg, clientHt);
clientState = pCD->clientState & ~UNSEEN_STATE;
fprintf(fp, initialStateStr, clientID);
fprintf(fp, strArg, (clientState == NORMAL_STATE) ?
normalStateStr : iconicStateStr);
clientWorkspaces = getClientWorkspaces(pCD);
if (clientWorkspaces != (char *)NULL)
{
fprintf(fp, workspacesStr, clientID);
fprintf(fp, strArg, clientWorkspaces);
XtFree(clientWorkspaces);
}
instantTitle = getClientInstantTitle(pCD);
if (instantTitle)
{
fprintf(fp, instantTitleStr, clientID);
fprintf(fp, strArg, instantTitle);
XtFree(instantTitle);
}
return True;
}
static void
dbRemoveProxyClientEntry(char *proxyClientID)
{
char resourceBuf[MAX_RESOURCE_LEN];
/* Remove entry from DB. Since Xrm does not provide a means */
/* of removing something from the DB, we blank out key info. */
sprintf(resourceBuf, wmCommandStr, proxyClientID);
strcat(resourceBuf, ":");
XrmPutLineResource(&wmGD.clientResourceDB, resourceBuf);
}
/*
* Add callbacks used in session management.
*/
void
AddSMCallbacks(void)
{
XtAddCallback(wmGD.topLevelW, XtNsaveCallback,
smSaveYourselfCallback, (XtPointer)NULL);
XtAddCallback(wmGD.topLevelW, XtNdieCallback,
smDieCallback, (XtPointer)NULL);
}
/*
* Resign from session management, closing any connections made.
*/
void
ResignFromSM(void)
{
if (wmGD.topLevelW)
{
XtVaSetValues(wmGD.topLevelW,
XtNjoinSession, False,
NULL);
}
}
/*
* Exit the WM, being polite by first resigning from session mgmt.
*/
void
ExitWM(int exitCode)
{
ResignFromSM();
exit(exitCode);
}
/*
* Read our private database of client resources.
*/
XrmDatabase
LoadClientResourceDB(void)
{
char dbFileName[MAXPATHLEN];
buildDBFileName(dbFileName, False);
return XrmGetFileDatabase(dbFileName);
}
/*
* Write our private database of client resources.
*/
XrmDatabase
SaveClientResourceDB(void)
{
String mySessionID;
char dbFileName[MAXPATHLEN];
FILE *fp;
int scr;
WmScreenData *pSD;
ClientData *pCD;
int clientIDNum = 0;
ClientListEntry *pCL;
/* Iterate through client list, saving */
/* appropriate resources for each. */
buildDBFileName(dbFileName, True);
if ((fp = fopen(dbFileName, "w")) == (FILE *)NULL)
return (XrmDatabase)NULL;
XtVaGetValues(wmGD.topLevelW,
XtNsessionID, &mySessionID,
NULL);
fprintf(fp, dbHeader, dtwmFileName, "dtwm Version XSMP1.0",
(mySessionID != (String)NULL) ? mySessionID : "");
for (scr = 0; scr < wmGD.numScreens; scr++)
{
pSD = &(wmGD.Screens[scr]);
for (pCL = pSD->clientList;
pCL != (ClientListEntry *)NULL;
pCL = pCL->nextSibling)
{
/* Each client may be in list twice: normal & icon */
if (pCL->type != NORMAL_STATE)
continue;
pCD = pCL->pCD;
if (pCD->smClientID != (String)NULL)
{
saveXSMPClient(fp, pCD);
}
else
{
if (saveProxyClient(fp, pCD, clientIDNum))
clientIDNum++;
}
}
}
fclose(fp);
/* Retrieve database from file. */
return XrmGetFileDatabase(dbFileName);
}
/*
* As with FindDtSessionMatch(), sets properties and then returns
* an allocated string of workspace names. This string must be
* freed by the caller using XtFree().
*/
Boolean
FindClientDBMatch(ClientData *pCD, char **workSpaceNamesP)
{
return (findXSMPClientDBMatch(pCD, workSpaceNamesP) ||
findProxyClientDBMatch(pCD, workSpaceNamesP));
}
Boolean
GetSmClientIdClientList(ClientData ***clients, int *nClients)
{
int scr;
WmScreenData *pSD;
ClientData *pCD;
ClientListEntry *pCL;
*nClients = 0;
*clients = (ClientData **)NULL;
for (scr = 0; scr < wmGD.numScreens; scr++)
{
pSD = &(wmGD.Screens[scr]);
for (pCL = pSD->clientList;
pCL != (ClientListEntry *)NULL;
pCL = pCL->nextSibling)
{
/* Each client may be in list twice: normal & icon */
if (pCL->type != NORMAL_STATE)
continue;
pCD = pCL->pCD;
if (pCD->smClientID != (String)NULL)
{
/* addClientToList() reclaims memory on failure. */
if (!addClientToList(clients, nClients, pCD))
return False;
}
}
}
return True;
}
void
SortClientListByWorkspace(ClientData **clients, int nClients)
{
if (nClients > 0)
{
qsort((void *)clients, nClients,
sizeof(ClientData *), clientWorkspaceCompare);
}
}
void
LoadClientIconPositions(ClientData *pCD)
{
char resourceBuf[MAX_RESOURCE_LEN];
WmScreenData *pSD = pCD->pSD;
WmWorkspaceData *pWS;
int i;
char *resourcePtr;
if (wmGD.clientResourceDB == (XrmDatabase)NULL)
return;
if (pCD->smClientID != (String)NULL)
{
for (i = 0; i < pCD->numInhabited; i++)
{
if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
!= (WmWorkspaceData *)NULL)
{
sprintf(resourceBuf, iconXPosStr, "%s", pWS->name);
if ((resourcePtr =
getXSMPResource(pCD, WMSAVE_ICON_X, resourceBuf))
!= (char *)NULL)
{
pCD->pWsList[i].iconX = atoi(resourcePtr);
pCD->clientFlags |= SM_ICON_X;
}
sprintf(resourceBuf, iconYPosStr, "%s", pWS->name);
if ((resourcePtr =
getXSMPResource(pCD, WMSAVE_ICON_Y, resourceBuf))
!= (char *)NULL)
{
pCD->pWsList[i].iconY = atoi(resourcePtr);
pCD->clientFlags |= SM_ICON_Y;
}
}
}
return;
}
/* Proxy client */
if (!smClientDBCheckpointed)
{
char *proxyClientID;
if ((proxyClientID = findProxyClientID(pCD)) != (char *)NULL)
{
for (i = 0; i < pCD->numInhabited; i++)
{
if ((pWS = GetWorkspaceData(pSD, pCD->pWsList[i].wsID))
!= (WmWorkspaceData *)NULL)
{
sprintf(resourceBuf, iconXPosStr, "%s", pWS->name);
if ((resourcePtr =
getClientResource(proxyClientID, resourceBuf))
!= (char *)NULL)
{
pCD->pWsList[i].iconX = atoi(resourcePtr);
pCD->clientFlags |= SM_ICON_X;
}
sprintf(resourceBuf, iconYPosStr, "%s", pWS->name);
if ((resourcePtr =
getClientResource(proxyClientID, resourceBuf))
!= (char *)NULL)
{
pCD->pWsList[i].iconY = atoi(resourcePtr);
pCD->clientFlags |= SM_ICON_Y;
}
}
}
dbRemoveProxyClientEntry(proxyClientID);
}
}
}