cdesktopenv/cde/programs/dtwm/WmWrkspace.c

3891 lines
81 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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 1987,1988,1989,1990,1992,1993,1994 HEWLETT-PACKARD COMPANY
* (c) Copyright 1993, 1994 International Business Machines Corp.
* (c) Copyright 1993, 1994 Sun Microsystems, Inc.
* (c) Copyright 1993, 1994 Novell, Inc.
* ALL RIGHTS RESERVED
*/
/*
* Included Files:
*/
#include "WmGlobal.h"
#include "WmHelp.h"
#include "WmResNames.h"
#include "WmIPlace.h"
#include "WmInitWs.h"
#include <X11/Xutil.h>
#include "WmICCC.h"
#include <Xm/Xm.h>
#include <Xm/AtomMgr.h>
#include <Dt/DtP.h>
#include <Dt/WsmM.h>
#include <stdio.h>
#include "WmPanelP.h"
#include "WmIPC.h" /* must be after DtP.h */
#include "WmPresence.h"
/* local macros */
#ifndef MIN
#define MIN(a,b) ((a)<=(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>=(b)?(a):(b))
#endif
/* internally defined functions */
#include "WmWrkspace.h"
/******** Static Function Declarations ********/
static void InsureUniqueWorkspaceHints(
ClientData *pCD) ;
/******** End Static Function Declarations ********/
/* FindDtSessionMatch () put in WmResParse.h */
/* external functions */
#include "WmBackdrop.h"
#include "WmError.h"
#include "WmFunction.h"
#include "WmIDecor.h"
#include "WmIconBox.h"
#include "WmMenu.h"
#include "WmProperty.h"
#include "WmResParse.h"
#include "WmWinInfo.h"
#include "WmWinList.h"
#include "WmWinState.h"
#include "WmXSMP.h"
/*
* Global Variables:
*/
/* a dynamically allocated list of workspaces used
* by F_AddToAllWorkspaces
*/
static int numResIDs = 0;
static WorkspaceID *pResIDs = NULL;
/*************************************<->*************************************
*
* ChangeToWorkspace (pNewWS)
*
*
* Description:
* -----------
* This function changes to a new workspace.
*
* Inputs:
* ------
* pNewWS = pointer to workspace data
*
*
*************************************<->***********************************/
void
ChangeToWorkspace(
WmWorkspaceData *pNewWS )
{
ClientData *pCD;
int i;
WmScreenData *pSD = pNewWS->pSD;
ClientData *pWsPCD;
Context wsContext = F_CONTEXT_NONE;
if (pNewWS == pSD->pActiveWS)
return; /* already there */
pSD->pLastWS = pSD->pActiveWS;
/*
* Go through client list of old workspace and hide windows
* that shouldn't appear in new workspace.
*/
if (pSD->presence.shellW &&
pSD->presence.onScreen &&
pSD->presence.contextForClient == F_CONTEXT_ICON)
{
pWsPCD = pSD->presence.pCDforClient;
wsContext = pSD->presence.contextForClient;
HidePresenceBox (pSD, False);
}
for (i = 0; i < pSD->pActiveWS->numClients; i++)
{
pCD = pSD->pActiveWS->ppClients[i];
if (!ClientInWorkspace (pNewWS, pCD))
{
SetClientWsIndex(pCD);
SetClientState (pCD, pCD->clientState | UNSEEN_STATE,
CurrentTime);
}
}
/*
* Hide active icon text label
*/
if ((pSD->iconDecoration & ICON_ACTIVE_LABEL_PART) &&
wmGD.activeIconTextDisplayed)
{
HideActiveIconText(pSD);
}
/*
* Unmap old icon box
*/
if (pSD->useIconBox)
{
UnmapIconBoxes (pSD->pLastWS);
}
/*
* Set new active workspace
*/
pSD->pActiveWS = pNewWS;
ChangeBackdrop (pNewWS);
/*
* Go through client list of new workspace and show windows
* that should appear.
*/
for (i = 0; i < pNewWS->numClients; i++)
{
pCD = pNewWS->ppClients[i];
SetClientWsIndex(pCD);
if (pCD->clientState & UNSEEN_STATE)
{
SetClientState (pCD,
(pCD->clientState & ~UNSEEN_STATE), CurrentTime);
}
if ((pCD->clientState == MINIMIZED_STATE) &&
((!pCD->pSD->useIconBox) ||
(!P_ICON_BOX(pCD))))
{
XMoveWindow (DISPLAY, ICON_FRAME_WIN(pCD),
ICON_X(pCD), ICON_Y(pCD));
}
if (pCD->iconWindow)
{
unsigned int xOffset, yOffset;
/*
* Adjust for icons in the box
*/
if (pNewWS->pIconBox)
{
xOffset = IB_MARGIN_WIDTH;
yOffset = IB_MARGIN_HEIGHT;
}
else
{
xOffset = 0;
yOffset = 0;
}
/*
* reparent icon window to frame in this workspace
*/
if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) &&
(pCD->iconWindow))
{
ReparentIconWindow (pCD, xOffset, yOffset);
}
}
}
if ( (wsContext == F_CONTEXT_ICON &&
ClientInWorkspace (ACTIVE_WS, pWsPCD)) ||
(pSD->presence.shellW &&
! pSD->presence.userDismissed &&
ClientInWorkspace (ACTIVE_WS, pSD->presence.pCDforClient) &&
pSD->presence.contextForClient == F_CONTEXT_ICON))
{
ShowPresenceBox(pSD->presence.pCDforClient, F_CONTEXT_ICON);
}
SetCurrentWorkspaceProperty (pSD);
/* send workspace change broadcast message */
dtSendWorkspaceModifyNotification(pSD, (Atom) pNewWS->id,
DtWSM_REASON_CURRENT);
} /* END OF FUNCTION ChangeToWorkspace */
/******************************<->*************************************
*
* ChangeWorkspaceTitle (pWS, pchTitle)
*
* Description:
* -----------
* Set the title for a workspace.
*
* Inputs:
* ------
* pWS = pointer to workspace data
* pchTitle = new title to assign to this workspace
*
* Outputs:
* -------
* none
*
* Comments:
* --------
*
******************************<->***********************************/
void
ChangeWorkspaceTitle(
WmWorkspaceData *pWS,
char * pchTitle)
{
XmString xmstr;
/*
* Convert string to XmString
*/
xmstr = XmStringCreateLocalized (pchTitle);
/*
* Validate title ?
*/
/*
* Replace title in workspace data
*/
XmStringFree (pWS->title);
pWS->title = xmstr;
/*
* Save changes to resource database
*/
SaveWorkspaceResources (pWS, (WM_RES_WORKSPACE_TITLE));
/*
* Replace old workspace in info property
*/
SetWorkspaceInfoProperty (pWS);
XFlush (DISPLAY);
/*
* Inform the world of the new workspace title
*/
dtSendWorkspaceModifyNotification(pWS->pSD, pWS->id, DtWSM_REASON_TITLE);
} /* END OF FUNCTION ChangeWorkspaceTitle */
/*************************************<->*************************************
*
* UpdateWorkspacePresenceProperty (pCD)
*
*
* Description:
* -----------
* This function updates the _DT_WORKSPACE_PRESENCE property for a
* client window
*
* Inputs:
* ------
* pCD = pointer to client data
*
*
*************************************<->***********************************/
void
UpdateWorkspacePresenceProperty(
ClientData *pCD )
{
static Atom *pPresence = NULL;
static unsigned long cPresence = 0;
unsigned long i;
if (wmGD.useStandardBehavior)
{
/*
* Don't change any workspace properties in standard behavior
* mode.
*/
return;
}
if (!pPresence)
{
/* allocate initial list */
if (!(pPresence = (Atom *)
XtMalloc (pCD->pSD->numWorkspaces * sizeof(Atom))))
{
Warning (((char *)GETMESSAGE(76, 1, "Insufficient memory for workspace presence property")));
}
else
{
cPresence = pCD->pSD->numWorkspaces;
}
}
if (cPresence < pCD->numInhabited)
{
/* allocate bigger list */
if (!(pPresence = (Atom *)
XtRealloc ((char *)pPresence, pCD->numInhabited * sizeof(Atom))))
{
Warning (((char *)GETMESSAGE(76, 2, "Insufficient memory for workspace presence property")));
}
else
{
cPresence = pCD->numInhabited;
}
}
for (i = 0; (i < pCD->numInhabited) && (i < cPresence) ; i++)
{
pPresence[i] = pCD->pWsList[i].wsID;
}
SetWorkspacePresence (pCD->client, pPresence,
MIN(pCD->numInhabited, cPresence));
} /* END OF FUNCTION UpdateWorkspacePresenceProperty */
/*************************************<->*************************************
*
* AddPersistentWindow (pWS)
*
*
* Description:
* -----------
* This function adds windows that want to be in all workspaces to
* the workspace passed in.
*
* Inputs:
* ------
* pWS = pointer to workspace data
*
* Outputs:
* --------
*
*************************************<->***********************************/
void
AddPersistentWindows(
WmWorkspaceData *pWS)
{
WmScreenData *pSD = pWS->pSD;
int i;
ClientListEntry *pCLE;
/*
* For all the windows managed for this screen, see if they
* want to be in all workspaces and add them to this workspace.
*/
pCLE = pSD->clientList;
while (1)
{
/*
* Process all the non-icon client list entries
*/
if ((pCLE->type == NORMAL_STATE) &&
(pCLE->pCD->putInAll))
{
AddClientToWorkspaces( pCLE->pCD, &(pWS->id), 1 );
}
/*
* Test for exit condition and advance client list pointer
*/
if (pCLE == pSD->lastClient)
break;
else
pCLE = pCLE->nextSibling;
}
} /* END OF FUNCTION AddPersistentWindows */
/*************************************<->*************************************
*
* CreateWorkspace (pSD, pchTitle)
*
*
* Description:
* -----------
* This function creates a new workspace.
*
* Inputs:
* ------
* pSD = pointer to screen data
* pchTitle = user-visible title for the workspace (may be NULL)
*
* Outputs:
* --------
* Returns pointer to workspace data if successful.
*
*************************************<->***********************************/
WmWorkspaceData *
CreateWorkspace(
WmScreenData *pSD,
unsigned char *pchTitle )
{
WmWorkspaceData *pWS = NULL;
String string;
int iActiveWS;
/*
* Allocate more workspace datas if we have no spares
*/
if (pSD->numWsDataAllocated <= pSD->numWorkspaces)
{
iActiveWS = (pSD->pActiveWS - pSD->pWS) / sizeof (WmWorkspaceData);
pSD->numWsDataAllocated += WS_ALLOC_AMOUNT;
pSD->pWS = (WmWorkspaceData *) XtRealloc ((char *)pSD->pWS,
pSD->numWsDataAllocated * sizeof(WmWorkspaceData));
pSD->pActiveWS = &(pSD->pWS[iActiveWS]);
}
/*
* Give this workspace a name
*/
pWS = &pSD->pWS[pSD->numWorkspaces];
string = (String) GenerateWorkspaceName (pSD, pSD->numWorkspaces);
pWS->name = XtNewString (string);
/*
* Initialize the workspace data structure
*/
InitWmWorkspace (pWS, pSD);
if (pchTitle)
{
if (pWS->title)
XmStringFree (pWS->title);
pWS->title = XmStringCreateLocalized ((char *)pchTitle);
}
/*
* bump workspace count
*/
pSD->numWorkspaces++;
/*
* update the properties that announce workspace info
*/
SetWorkspaceInfoProperty (pWS);
SetWorkspaceListProperty (pSD);
SaveWorkspaceResources(pWS, (WM_RES_WORKSPACE_LIST |
WM_RES_WORKSPACE_COUNT |
WM_RES_WORKSPACE_TITLE));
dtSendWorkspaceModifyNotification(pSD, pWS->id, DtWSM_REASON_ADD);
/*
* Insure there's an iconbox for this workspace
*/
if (pSD->useIconBox)
{
AddIconBoxForWorkspace (pWS);
}
/*
* Add windows to this workspaces that want to be in "all"
* workspaces.
*/
AddPersistentWindows (pWS);
/*
* Update workspace presence dialog data
*/
UpdatePresenceWorkspaces(pSD);
return (pWS);
} /* END OF FUNCTION CreateWorkspace */
/*************************************<->*************************************
*
* DeleteWorkspace (pWS)
*
*
* Description:
* -----------
* This function deletes a workspace.
*
* Inputs:
* ------
* pWS = pointer to screen data
*
* Outputs:
* --------
* Returns pointer to workspace data if successful.
*
*************************************<->***********************************/
void
DeleteWorkspace(
WmWorkspaceData *pWS )
{
WmWorkspaceData *pWSdest; /* destination WS */
int i, iNextWs;
ClientData *pCD;
WmScreenData *pSD = pWS->pSD;
Atom aOldId;
if (pSD->numWorkspaces > 1)
{
/*
* Find index for "next" workspace
*/
for (iNextWs = 0; iNextWs < pSD->numWorkspaces; iNextWs++)
{
if (pSD->pWS[iNextWs].id == pWS->id)
{
iNextWs++;
break;
}
}
/* check bounds and wrap */
if (iNextWs >= pSD->numWorkspaces)
iNextWs = 0;
/*
* Determine default destination for clients that exist
* only in the workspace being deleted.
*/
if (pWS == ACTIVE_WS)
{
pWSdest = &(pSD->pWS[iNextWs]);
}
else
{
/*
* Use the "current" workspace as the default destination
*/
pWSdest = ACTIVE_WS;
}
/*
* Move all clients out of this workspace
*/
while (pWS->numClients > 0)
{
/* repeatedly remove the first one until all are gone */
pCD = pWS->ppClients[0];
if (pCD->numInhabited == 1)
{
if (!(pCD->clientFlags & (ICON_BOX)))
{
AddClientToWorkspaces (pCD, &(pWSdest->id), 1);
}
}
RemoveClientFromWorkspaces (pCD, &(pWS->id), 1);
}
/*
* If we're deleting the current workspace,
* then change to another workspace.
*/
if (pWS == ACTIVE_WS)
{
ChangeToWorkspace (pWSdest);
}
/*
* Save the workspace ID for the notification message.
*/
aOldId = pWS->id;
/*
* Destroy the icon box for the workspace if one was used
*/
if (pSD->useIconBox)
{
DestroyIconBox (pWS);
}
/*
* Delete the property containing information on this workspace
*/
DeleteWorkspaceInfoProperty (pWS);
/*
* Delete the workspace data structures
*/
if (pWS->backdrop.imagePixmap)
{
if (!XmDestroyPixmap (XtScreen(pWS->workspaceTopLevelW),
pWS->backdrop.imagePixmap))
{
/* not in Xm pixmap cache */
}
}
/* free pWS->backdrop.image */
if ((pWS->backdrop.flags & BACKDROP_IMAGE_ALLOCED) &&
(pWS->backdrop.image))
{
free (pWS->backdrop.image);
}
/*
* Free up icon placement data
*/
if (wmGD.iconAutoPlace)
{
if (pWS->IPData.placeList != NULL)
XtFree ((char *) pWS->IPData.placeList);
if (pWS->IPData.placementRowY != NULL)
XtFree ((char *) pWS->IPData.placementRowY);
if (pWS->IPData.placementColX != NULL)
XtFree ((char *) pWS->IPData.placementColX);
}
XtFree ((char *) pWS->name);
XmStringFree (pWS->title);
XtFree ((char *) pWS->ppClients);
if (pWS->iconBoxGeometry) XtFree ((char *) pWS->iconBoxGeometry);
XtDestroyWidget (pWS->workspaceTopLevelW);
/*
* Compress the list of workspaces if we're not deleting
* the last one. (Do piece-wise to avoid overlapping copy
* problems).
*/
if (iNextWs > 0)
{
WmWorkspaceData *pWSdest;
WmWorkspaceData *pWSsrc;
int j;
pWSdest = pWS;
pWSsrc = &(pSD->pWS[iNextWs]);
for (j=iNextWs; j < pSD->numWorkspaces; j++)
{
memcpy (pWSdest, pWSsrc, sizeof(WmWorkspaceData));
if (pSD->pActiveWS == pWSsrc)
{
pSD->pActiveWS = pWSdest;
}
pWSdest++;
pWSsrc++;
}
}
/*
* We now have one less workspace.
*/
pSD->numWorkspaces--;
/*
* Update the properties that announce workspace info.
*/
SetWorkspaceListProperty (pSD);
SaveWorkspaceResources(pWSdest,
(WM_RES_WORKSPACE_LIST | WM_RES_WORKSPACE_COUNT));
dtSendWorkspaceModifyNotification(pSD, aOldId, DtWSM_REASON_DELETE);
/*
* Update workspace presence dialog data
*/
UpdatePresenceWorkspaces(pSD);
}
} /* END OF FUNCTION DeleteWorkspace */
/*************************************<->*************************************
*
* ProcessDtWmHints (pCD)
*
*
* Description:
* -----------
* Process the _DT_WM_HINTS property on the window (if any).
*
*
* Inputs:
* ------
* pCD = pointer to client data
*
*
* Outputs:
* -------
* pCD = may be changed.
*
*************************************<->***********************************/
void
ProcessDtWmHints (ClientData *pCD)
{
DtWmHints *pHints;
Atom property;
long saveFunctions;
/*
* Retrieve the _DT_WM_HINTS property if it exists.
*/
property = XmInternAtom(DISPLAY, _XA_DT_WM_HINTS, False);
if (
(HasProperty (pCD, property))
&& (_DtWsmGetDtWmHints (DISPLAY, pCD->client, &pHints) == Success))
{
pCD->clientFlags |= GOT_DT_WM_HINTS;
if (pHints->flags & DtWM_HINTS_FUNCTIONS)
{
if (pHints->functions & DtWM_FUNCTION_ALL)
{
/* client indicating inapplicable functions */
pCD->dtwmFunctions &= ~(pHints->functions);
}
else
{
/* client indicating applicable functions */
pCD->dtwmFunctions &= pHints->functions;
}
}
if (pHints->flags & DtWM_HINTS_BEHAVIORS)
{
/* set applicable behaviors */
pCD->dtwmBehaviors = pHints->behaviors;
if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUB_RESTORED)
{
/*
* if this is a restored subpanel, remove the
* DtWM_BEHAVIOR_SUB_RESTORED bit so the next
* time through the subpanel will behave as an
* existing subpanel
*/
pHints->behaviors &= ~DtWM_BEHAVIOR_SUB_RESTORED;
_DtWsmSetDtWmHints (DISPLAY, pCD->client, pHints);
}
}
XFree ((char*)pHints);
}
if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_PANEL)
{
/* put it in all workspaces */
saveFunctions = pCD->dtwmFunctions;
pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
F_AddToAllWorkspaces (NULL, pCD, NULL);
pCD->dtwmFunctions = saveFunctions;
pCD->clientFlags |= FRONT_PANEL_BOX ;
}
} /* END OF ProcessDtWmHints */
/*************************************<->*************************************
*
* GetClientWorkspaceInfo (pCD, manageFlags);
*
*
* Description:
* -----------
* This function sets up the portion of client data that has to
* do with workspaces
*
* Inputs:
* ------
* pCD = pointer to client data (only partly initialized!!)
* manageFlags = tells us, in particular, if we're restarting.
*
* Outputs:
* --------
* pCD = updated client data
*
*************************************<->***********************************/
Boolean
GetClientWorkspaceInfo(
ClientData *pCD,
long manageFlags )
{
Atom *pIDs;
int i;
unsigned int numIDs = 0;
Boolean bAll;
/*
* Allocate initial workspace ID list
* fill with NULL IDs
*/
if ((pCD->pWsList = (WsClientData *)
XtMalloc(pCD->pSD->numWorkspaces * sizeof(WsClientData))) == NULL)
{
Warning (((char *)GETMESSAGE(76, 4, "Insufficient memory for client data")));
return (False);
}
pCD->currentWsc = 0;
pCD->pWorkspaceHints = NULL;
pCD->sizeWsList = pCD->pSD->numWorkspaces;
pCD->numInhabited = 0; /* no valid ones yet */
for (i = 0; i < pCD->pSD->numWorkspaces; i++)
{
pCD->pWsList[i].wsID = None;
pCD->pWsList[i].iconPlace = NO_ICON_PLACE;
pCD->pWsList[i].iconX = 0;
pCD->pWsList[i].iconY = 0;
pCD->pWsList[i].iconFrameWin = None;
pCD->pWsList[i].pIconBox = NULL;
}
pCD->putInAll = bAll = False;
/*
* Determine initial workspace set.
*
* If this is a secondary window, use the hints from the
* transient tree leader.
*
* Else if we're restarting, then use our own workspace presence.
*
* Else if a command line option is specified, use that.
*
* Else, if workspace hints are on the window, then use them.
*
* If none of the above work out, the window will be put into
* the current workspace.
*/
if (pCD->client &&
((pCD->transientLeader && GetLeaderPresence(pCD, &pIDs, &numIDs)) ||
((manageFlags & MANAGEW_WM_RESTART) &&
GetMyOwnPresence (pCD, &pIDs, &numIDs)) ||
(WorkspaceIsInCommand (DISPLAY, pCD, &pIDs, &numIDs)) ||
(
HasProperty (pCD, wmGD.xa_DT_WORKSPACE_HINTS)
&& (GetWorkspaceHints (DISPLAY, pCD->client, &pIDs, &numIDs, &bAll) ==
Success))) &&
numIDs)
{
/*
* Got some workspace hints!
*/
pCD->putInAll = bAll;
ProcessWorkspaceHintList (pCD, pIDs, numIDs);
}
if (pCD->numInhabited == 0)
{
/*
* If not in any workspaces, then put the client into
* the current one.
*/
PutClientIntoWorkspace (pCD->pSD->pActiveWS, pCD);
}
return (True);
} /* END OF FUNCTION GetClientWorkspaceInfo */
/*************************************<->*************************************
*
* WorkspaceIsInCommand (dpy, pCD, ppIDs, pNumIDs)
*
*
* Description:
* -----------
* Determine if workspace specification is in command line for client
*
*
* Inputs:
* ------
* dpy - pointer to display structure
* pCD - ptr to client data
* ppIDs - pointer for returning list of IDs
* pNumIDs - number of IDs being returned
*
* Outputs:
* -------
* ppIDs - returned list of IDs
* pNumIDs - number of IDs being returned
*
* Return - True if workspace option found, false otherwise
*
*
* Comments:
* --------
* Malloc's memory that must be freed
*
*************************************<->***********************************/
Boolean
WorkspaceIsInCommand(
Display *dpy,
ClientData *pCD,
WorkspaceID **ppIDs,
unsigned int *pNumIDs )
{
int wmcArgc;
char **wmcArgv = NULL;
Boolean rval = False;
unsigned char *pch = NULL;
XTextProperty clientMachineProp;
if (FindClientDBMatch(pCD, (char **)&pch))
{
if (pch)
{
if (ConvertNamesToIDs (pCD->pSD, pch, ppIDs, pNumIDs))
{
rval = True;
}
XtFree((char *)pch);
}
}
else if (HasProperty (pCD, XA_WM_COMMAND) &&
XGetCommand (dpy, pCD->client, &wmcArgv, &wmcArgc) &&
(wmcArgv != NULL))
{
if (pCD->pSD->remainingSessionItems)
{
if(!(XGetWMClientMachine(dpy, pCD->client, &clientMachineProp)))
{
clientMachineProp.value = NULL;
}
if (FindDtSessionMatch(wmcArgc, wmcArgv, pCD, pCD->pSD,
(char **)&pch,
(char *)clientMachineProp.value))
{
/*
* If we found a match to a client description
* in the DtSessionHints, use the information from
* the Hints instead of the command line
*/
if (pch)
{
if (ConvertNamesToIDs (pCD->pSD, pch, ppIDs, pNumIDs))
{
rval = True;
}
/*
* free malloced memory containing workspace list
*/
XtFree ((char *)pch);
}
}
if (clientMachineProp.value)
{
XFree ((char*)clientMachineProp.value);
}
}
if (!rval && FindWsNameInCommand (wmcArgc, wmcArgv, &pch))
{
if (ConvertNamesToIDs (pCD->pSD, pch, ppIDs, pNumIDs))
{
rval = True;
}
}
if (wmcArgv != NULL)
{
XFreeStringList (wmcArgv);
}
}
return (rval);
} /* END OF FUNCTION WorkspaceIsInCommand */
/*************************************<->*************************************
*
* ConvertNamesToIDs (pSD, pch, ppAtoms, pNumAtoms)
*
*
* Description:
* -----------
* Takes a string containing a list of names separated by white space
* and converts it to a list of workspace IDs.
*
* Inputs:
* ------
* pSD - pointer to screen data
* pchIn - pointer to original string
* ppAtoms - pointer to an atom pointer (for returning list pointer)
* pNumAtoms - pointer to the number of atoms being returned.
*
* Outputs:
* -------
* *ppAtoms - points to a list of atoms returned.
* *pNumAtoms - the number of atoms being returned.
*
* Return - True if some Atoms are being returned
*
* Comments:
* --------
* Processes local copy of string so that pch is not modified.
*
* The list of atoms returned has been dynamically allocated.
* Please XtFree() it when you're done.
*
*************************************<->***********************************/
Boolean
ConvertNamesToIDs(
WmScreenData *pSD,
unsigned char *pchIn,
WorkspaceID **ppAtoms,
unsigned int *pNumAtoms )
{
unsigned char *pchLocal, *pch, *pchName;
int num = 0;
int numLocalIDs;
WorkspaceID *pLocalIDs;
if ((pLocalIDs = (WorkspaceID *) XtMalloc (WS_ALLOC_AMOUNT *
sizeof(WorkspaceID))) == NULL)
{
Warning (((char *)GETMESSAGE(76, 5, "Insufficient Memory (ConvertNamesToIDs)")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
numLocalIDs = WS_ALLOC_AMOUNT;
if (pchIn && (pchLocal = (unsigned char *) XtMalloc(1+strlen((char *)pchIn))))
{
strcpy ((char *)pchLocal, (char *)pchIn);
pch = pchLocal;
while ((pchName = GetSmartString (&pch)))
{
int iwsx;
XmString xms;
/*
* Check workspace for workspace titles; map to
* workspace names.
*/
xms = XmStringCreateLocalized ((char *)pchName);
for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
{
if (XmStringCompare (xms, pSD->pWS[iwsx].title))
{
break;
}
}
XmStringFree (xms);
if (iwsx < pSD->numWorkspaces)
{
/*
* Found a workspace title we've got,
* use id for workspace name
*/
pLocalIDs[num] = pSD->pWS[iwsx].id;
num++;
}
else
{
/*
* Try for match on workspace name
*/
pLocalIDs[num] = (WorkspaceID)
XInternAtom (DISPLAY, (char *)pchName, False);
num++;
}
if (num >= numLocalIDs)
{
/* list too small */
numLocalIDs += WS_ALLOC_AMOUNT;
if ((pLocalIDs = (WorkspaceID *) XtRealloc ((char *)pLocalIDs,
numLocalIDs * sizeof(WorkspaceID))) == NULL)
{
Warning (((char *)GETMESSAGE(76, 6, "Insufficient Memory (ConvertNamesToIDs)")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
}
}
XtFree ((char *)pchLocal);
}
*ppAtoms = pLocalIDs;
*pNumAtoms = num;
return (num != 0);
} /* END OF FUNCTION ConvertNamesToIDs */
/*************************************<->*************************************
*
* CheckForPutInAllRequest (pCD, pIDs, numIDs)
*
*
* Description:
* -----------
* Tests for the presence of the "all" atom in the atom list
* and sets the "putInAll" flag on the client.
*
* Inputs:
* ------
* pCD - pointer to client data
* pIDs - pointer to ID list
* numIDs - number of IDs in list
*
* Outputs:
* -------
* pCD - putInAll member may be set
*
*************************************<->***********************************/
void
CheckForPutInAllRequest(
ClientData *pCD,
Atom *pIDs,
unsigned int numIDs )
{
unsigned int i;
for (i = 0; (i < numIDs) && !(pCD->putInAll); i++)
{
if (pIDs[i] == wmGD.xa_ALL_WORKSPACES)
{
pCD->putInAll = True;
break;
}
}
} /* END OF FUNCTION CheckForPutInAllRequest */
/*************************************<->*************************************
*
* FindWsNameInCommand (argc, argv, ppch)
*
*
* Description:
* -----------
* Finds and returns the workspace name option in the command line
* (if any)
*
* Inputs:
* ------
* argc - argument count
* argv - argument list
* ppch - string pointer to return
*
*
* Outputs:
* -------
* *ppch - points to ws name (if found)
*
* Return - True if wsname found
*
*
* Comments:
* --------
*************************************<->***********************************/
Boolean
FindWsNameInCommand(
int argc,
char *argv[],
unsigned char **ppch )
{
#define XRM_OPT "-xrm"
#define WSLIST "*workspaceList:"
#define WSLIST_LEN 14
int i = 1;
Boolean rval = False;
unsigned char *pch, *pchTmp, *pch0;
unsigned char *pchRes, *pchValue;
if (argc > 0)
{
while (--argc && !rval)
{
if (!strcmp(argv[i], XRM_OPT) && (argc > 1))
{
/*
* found "-xrm", now look at resource spec
*/
pch0 = (unsigned char *) strdup (argv[i+1]);
if (!pch0)
{
Warning (((char *)GETMESSAGE(76, 7, "Insufficient memory")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
pch = pch0;
/* strip off quotes ,
* separate two halve of resource spec
*/
pchRes = GetSmartString (&pch);
pchValue = pch;
if ((*pchRes) && (*pch))
{
/* Erase colon at end of resource name */
pch = (unsigned char *) strrchr((char *)pchRes, ':');
if (pch)
{
*pch = '\0';
}
/* find beginning of last component of resource
* spec
*/
pch = (unsigned char *) strrchr ((char *)pchRes, '*');
pchTmp = (unsigned char *) strrchr ((char *)pchRes, '.');
if (pchTmp > pch)
{
pch = pchTmp;
}
if (pch && *pch && *(pch+1))
{
pch += 1;
}
/* compare resource with our resource */
if ( (!strcmp ((char *)pch, WmNworkspaceList)) ||
(!strcmp ((char *)pch, WmCWorkspaceList)))
{
/* match, compute return position in
passed in string */
*ppch = (unsigned char *)
(argv[i+1] + (pchValue - pch0));
rval = True;
XtFree ((char *)pch0);
pch0 = NULL;
}
}
i++; /* skip next arg */
argc--;
if (pch0)
{
XtFree ((char *)pch0);
}
}
i++;
}
}
return (rval);
} /* END OF FUNCTION FindWsNameInCommand */
/*************************************<->*************************************
*
* PutClientIntoWorkspace (pWS, pCD)
*
*
* Description:
* -----------
* This function updates the data for the client and workspace to
* reflect the presence of the client in the workspace.
*
* Inputs:
* ------
* pWS = pointer to workspace data
* pCD = pointer to client data
*
* Outputs:
* --------
*
*************************************<->***********************************/
void
PutClientIntoWorkspace(
WmWorkspaceData *pWS,
ClientData *pCD )
{
int i = pCD->numInhabited;
int iAdded, j, k;
/* insure the client's got enough workspace data */
if (pCD->sizeWsList < pCD->pSD->numWorkspaces)
{
iAdded = pCD->pSD->numWorkspaces - pCD->sizeWsList;
pCD->sizeWsList = pCD->pSD->numWorkspaces;
pCD->pWsList = (WsClientData *)
XtRealloc((char *)pCD->pWsList,
(pCD->pSD->numWorkspaces * sizeof(WsClientData)));
/* intialized new data */
j = pCD->sizeWsList - 1;
for (j=1; j <= iAdded; j++)
{
k = pCD->sizeWsList - j;
pCD->pWsList[k].iconPlace = NO_ICON_PLACE;
pCD->pWsList[k].iconX = 0;
pCD->pWsList[k].iconY = 0;
pCD->pWsList[k].iconFrameWin = (Window) 0;
pCD->pWsList[k].pIconBox = NULL;
}
}
/* update the client's list of workspace data */
pCD->pWsList[i].wsID = pWS->id;
pCD->numInhabited++;
if (!(pCD->clientFlags & WM_INITIALIZATION))
{
/*
* Make sure there's an icon
* (Don't do this during initialization, the pCD not
* ready for icon making yet).
*/
InsureIconForWorkspace (pWS, pCD);
}
/* update the workspace list of clients */
AddClientToWsList (pWS, pCD);
} /* END OF FUNCTION PutClientIntoWorkspace */
/*************************************<->*************************************
*
* TakeClientOutOfWorkspace (pWS, pCD)
*
*
* Description:
* -----------
* This function updates the data for the client and the workspace
* to reflect the removal of the client from the workspace.
*
* Inputs:
* ------
* pWS = pointer to workspace data
* pCD = pointer to client data
*
* Outputs:
* --------
*
*************************************<->***********************************/
void
TakeClientOutOfWorkspace(
WmWorkspaceData *pWS,
ClientData *pCD )
{
int ixA;
Boolean Copying = False;
WsClientData *pWsc;
if (pWS && pCD && ClientInWorkspace(pWS, pCD))
{
/*
* Clean up icon
*/
if (!pCD->transientLeader)
{
pWsc = GetWsClientData (pWS, pCD);
if ((pCD->pSD->useIconBox) &&
(pWsc->pIconBox) &&
(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
{
DeleteIconFromBox (pWS->pIconBox, pCD);
}
else if (wmGD.iconAutoPlace)
{
/*
* Free up root icon spot
*/
if ((pWsc->iconPlace != NO_ICON_PLACE) &&
(pWS->IPData.placeList[pWsc->iconPlace].pCD == pCD))
{
pWS->IPData.placeList[pWsc->iconPlace].pCD = NULL;
pWsc->iconPlace = NO_ICON_PLACE;
}
}
}
/*
* Remove the selected workspace and copy the remaining ones
* up. (Do piece-wise to avoid overlapping copy.)
*/
for (ixA = 0; ixA < pCD->numInhabited; ixA++)
{
if (Copying)
{
memcpy (&pCD->pWsList[ixA-1], &pCD->pWsList[ixA],
sizeof(WsClientData));
}
else if (pCD->pWsList[ixA].wsID == pWS->id)
{
/*
* This is the one we're removing, start copying here.
*/
Copying = True;
}
}
/*
* Decrement the number of workspaces inhabited.
*/
pCD->numInhabited--;
/* update the workspaces list of clients */
RemoveClientFromWsList (pWS, pCD);
}
#ifdef DEBUG
else
{
Warning("TakeClientOutOfWorkspace: null workspace passed in.");
}
#endif /* DEBUG */
} /* END OF FUNCTION TakeClientOutOfWorkspace */
/*************************************<->*************************************
*
* GetWorkspaceData (pSD, wsID)
*
*
* Description:
* -----------
* This function finds the data that is associated with a workspace ID.
*
* Inputs:
* ------
* pSD = pointer to screen data
* wsID = workspace ID
*
* Outputs:
* --------
* Function returns a pointer to the workspace data if successful,
* or NULL if unsuccessful.
*
*************************************<->***********************************/
WmWorkspaceData *
GetWorkspaceData(
WmScreenData *pSD,
WorkspaceID wsID )
{
WmWorkspaceData *pWS = NULL;
int i;
for (i=0; i < pSD->numWorkspaces; i++)
{
if (pSD->pWS[i].id == wsID)
{
pWS = &pSD->pWS[i];
break;
}
}
#ifdef DEBUG
if (!pWS)
{
/* failed to find one */
Warning ("Failed to find workspace data");
}
#endif
return (pWS);
} /* END OF FUNCTION GetWorkspaceData */
/*************************************<->*************************************
*
* GenerateWorkspaceName (pSD, wsnum)
*
*
* Description:
* -----------
* This function generates and returns a workspace string name from
* a small number passed in.
*
* Inputs:
* ------
* pSD = pointer to screen data
* wsNum = number for workspace
*
*
* Outputs:
* -------
* returns pointer to statically allocated data. You must copy it
* to your local buffer.
*
* Comments:
* ---------
* Name is of the form ws<n> where <n> is a number.
*
*************************************<->***********************************/
unsigned char *
GenerateWorkspaceName(
WmScreenData *pSD,
int wsnum )
{
static unsigned char nameReturned[13];
int i, j;
/*
* Nice n-squared algorithm...
* (This should be OK for small number of workspaces)
*/
for (i=0; i <= pSD->numWorkspaces; i++)
{
/* generate a name */
sprintf ((char *)nameReturned, "ws%d", i);
if (!DuplicateWorkspaceName (pSD, nameReturned, wsnum))
break;
}
return (nameReturned);
} /* END OF FUNCTION GenerateWorkspaceName */
/*************************************<->*************************************
*
* InWindowList (w, wl, num)
*
*
* Description:
* -----------
* This function determines if a window is in a list of windows
*
* Inputs:
* ------
* w = window of interest
* wl = list of windows
* num = number of windows in wl
*
*
* Outputs:
* -------
* The function returns "True" if "w" appears in "wl"
*
*************************************<->***********************************/
Boolean
InWindowList(
Window w,
Window wl[],
int num )
{
int i;
Boolean rval = False;
for (i = 0; (i < num) && !rval; i++)
{
if (w == wl[i])
{
rval = True;
}
}
return (rval);
} /* END OF FUNCTION InWindowList */
/*************************************<->*************************************
*
* ClientInWorkspace (pWS, pCD)
*
*
* Description:
* -----------
* This function determines if a client is in a workspace
*
* Inputs:
* ------
* pWS = pointer to workspace data
* pCD = pointer to client data
*
* Outputs:
* -------
* The function returns "True" if client pCD is in workspace pWS
*
*************************************<->***********************************/
Boolean
ClientInWorkspace(
WmWorkspaceData *pWS,
ClientData *pCD )
{
int i;
Boolean rval = False;
for (i = 0; (i < pCD->numInhabited) && !rval; i++)
{
if (pWS->id == pCD->pWsList[i].wsID)
{
rval = True;
}
}
return (rval);
} /* END OF FUNCTION ClientInWorkspace */
/*************************************<->*************************************
*
* GetWsClientData (pWS, pCD)
*
*
* Description:
* -----------
* This function returns a pointer to the client's specific data for
* this workspace
*
* Inputs:
* ------
* pWS = pointer to workspace data
* pCD = pointer to client data
*
* Outputs:
* -------
* The function returns a pointer to the client's data for this
* workspace. If the client isn't in the workspace, an error is
* printed and the first datum in the workspace list is returned.
*
*************************************<->***********************************/
WsClientData *
GetWsClientData(
WmWorkspaceData *pWS,
ClientData *pCD )
{
int i;
WsClientData *pWsc = NULL;
for (i = 0; (i < pCD->numInhabited) && !pWsc; i++)
{
if (pWS->id == pCD->pWsList[i].wsID)
{
pWsc = &pCD->pWsList[i];
}
}
if (!pWsc)
{
pWsc = &pCD->pWsList[0];
}
return (pWsc);
} /* END OF FUNCTION GetWsClientData */
/*************************************<->*************************************
*
* SetClientWsIndex (pCD)
*
*
* Description:
* -----------
* This function sets the index into the client's array of workspace
* specific data. This index points to the data to be used for the
* currently active workspace.
*
* Inputs:
* ------
* pCD = pointer to client data
*
* Outputs:
* -------
* The function returns an index as described above. If the client is
* not in the currently active workspace, then the index returned is 0.
*
*************************************<->***********************************/
void
SetClientWsIndex(
ClientData *pCD )
{
int i;
WmWorkspaceData *pWS = pCD->pSD->pActiveWS;
for (i = 0; (i < pCD->numInhabited); i++)
{
if (pWS->id == pCD->pWsList[i].wsID)
{
break;
}
}
if (i >= pCD->numInhabited)
{
i = 0;
}
pCD->currentWsc = i;
} /* END OF FUNCTION SetClientWsIndex */
/*************************************<->*************************************
*
* ProcessWmWorkspaceHints (pCD)
*
*
* Description:
* -----------
* This function processes a change to the _DT_WORKSPACE_HINTS property
* on a window that we manage.
*
* Inputs:
* ------
* pCD = pointer to client data
*
* Outputs:
* -------
* Returns False if we ran out of memory or no hints.
* Returns True on success.
*
*************************************<->***********************************/
Boolean
ProcessWorkspaceHints(
ClientData *pCD )
{
Atom *pIDs;
int i, j;
unsigned int numIDs;
WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
Boolean rval = False;
Boolean InBoth;
Boolean bAll;
int numOld;
WorkspaceID *pDiff = NULL;
int numDiff;
numOld = pCD->numInhabited;
ReserveIdListSpace (numOld);
for (i = 0; i < numOld; i++)
{
pResIDs[i] = pCD->pWsList[i].wsID;
}
if ((pCD->client) &&
(GetWorkspaceHints (DISPLAY, pCD->client,
&pIDs, &numIDs, &bAll) == Success) &&
(bAll || (numIDs && (pDiff = (WorkspaceID *)
XtMalloc (sizeof(WorkspaceID) * MAX(numIDs, numOld))))))
{
/*
* Process request to put window in all workspaces
*/
pCD->putInAll = bAll;
CheckForPutInAllRequest (pCD, pIDs, numIDs);
if (!pCD->putInAll)
{
/*
* Compute the ids to be removed.
*/
numDiff = 0;
for (i=0; i < numOld; i++)
{
InBoth = False;
for (j=0; j < numIDs; j++)
{
if (pIDs[j] == pResIDs[i])
{
InBoth = True;
break;
}
}
if (!InBoth)
{
pDiff[numDiff++] = pResIDs[i];
}
}
/*
* Remove the client from the set of workspaces
*/
if (numDiff)
{
RemoveClientFromWorkspaces (pCD, pDiff, numDiff);
}
}
/*
* Process request to put window in all workspaces
*/
if (pCD->putInAll)
{
for (i=0; i<pCD->pSD->numWorkspaces; i++)
{
if (!ClientInWorkspace(&pCD->pSD->pWS[i], pCD))
{
AddClientToWorkspaces (pCD, &pCD->pSD->pWS[i].id, 1);
}
}
}
else
{
/*
* Compute the ids to be added.
*/
numDiff = 0;
for (i=0; i < numIDs; i++)
{
InBoth = False;
for (j=0; j < numOld; j++)
{
if (pResIDs[j] == pIDs[i])
{
InBoth = True;
break;
}
}
if (!InBoth)
{
pDiff[numDiff++] = pIDs[i];
}
}
/*
* Add the client to the set of workspaces
*/
if (numDiff)
{
AddClientToWorkspaces (pCD, pDiff, numDiff);
}
}
/*
* If the client is not in any workspaces, then
* put it in the current one
*
* !!! Is this right? !!!
*/
if (pCD->numInhabited == 0)
{
AddClientToWorkspaces (pCD, &pSD->pActiveWS->id, 1);
}
/*
* Free up the old list of hints
*/
if (pCD->pWorkspaceHints)
{
XFree ((char *)pCD->pWorkspaceHints);
}
if (pDiff)
{
XtFree ((char *)pDiff);
}
/*
* Save the new hints
*/
pCD->pWorkspaceHints = pIDs;
pCD->numWorkspaceHints = numIDs;
/*
* Update the presence property
*/
UpdateWorkspacePresenceProperty (pCD);
rval = True;
}
return (rval);
} /* END OF FUNCTION ProcessWorkspaceHints */
/*************************************<->*************************************
*
* InsureUniqueWorkspaceHints (pCD)
*
*
* Description:
* -----------
* This function processes the workspace hints and removes duplicates.
*
* Inputs:
* ------
* pCD = pointer to client data
*
* Outputs:
* -------
* May modify *pWorkspaceHints and numWorkspaceHints
*
*************************************<->***********************************/
static void
InsureUniqueWorkspaceHints(
ClientData *pCD )
{
int next, trail, i;
WorkspaceID *pID;
Boolean duplicate;
if (pCD->numWorkspaceHints < 2) return;
pID = pCD->pWorkspaceHints;
trail = 0;
next = 1;
while (next < pCD->numWorkspaceHints)
{
duplicate = False;
for (i = 0; i < next; i++)
{
if (pID [next] == pID [i])
{
/* duplicate found! */
duplicate = True;
break;
}
}
if (duplicate)
{
/* skip duplicates */
next++;
}
else
{
/* not a duplicate */
trail++;
if (next > trail)
{
/*
* We need to copy up over an old duplicate
*/
pID [trail] = pID [next];
}
}
next++;
}
pCD->numWorkspaceHints = trail+1;
} /* END OF FUNCTION InsureUniqueWorkspaceHints */
/*************************************<->*************************************
*
* ProcessWorkspaceHintList (pCD, pIDs, numIDs)
*
*
* Description:
* -----------
* This function processes a list of workspace hints for a client.
*
* Inputs:
* ------
* pCD = pointer to client data
* pIDs = pointer to a list of workspace IDs
* numIDs = number of IDs in the list
*
* Outputs:
* -------
*
*************************************<->***********************************/
void
ProcessWorkspaceHintList(
ClientData *pCD,
WorkspaceID *pIDs,
unsigned int numIDs )
{
int i;
WmWorkspaceData *pWS;
if (numIDs > 0)
{
/*
* Keep these hints; make sure there are no duplicate
* workspace requests.
*/
pCD->pWorkspaceHints = pIDs;
pCD->numWorkspaceHints = numIDs;
InsureUniqueWorkspaceHints (pCD);
numIDs = pCD->numWorkspaceHints;
if (pCD->pWorkspaceHints)
{
/*
* Process request to put window in all workspaces
*/
CheckForPutInAllRequest (pCD, pIDs, numIDs);
if (pCD->putInAll)
{
for (i=0; i<pCD->pSD->numWorkspaces; i++)
{
PutClientIntoWorkspace (&pCD->pSD->pWS[i], pCD);
}
}
else
{
for (i=0; i<numIDs; i++)
{
/*
* Put the client into requested workspaces that
* exist.
*/
if ((pWS = GetWorkspaceData (pCD->pSD,
pCD->pWorkspaceHints[i])))
{
PutClientIntoWorkspace (pWS, pCD);
}
}
}
}
}
} /* END OF FUNCTION ProcessWorkspaceHintList */
/*************************************<->*************************************
*
* RemoveSingleClientFromWorkspaces (pCD, pIDs, numIDs)
*
*
* Description:
* -----------
* This function removes a single client from a list of workspaces
*
* Inputs:
* ------
* pCD = pointer to client data
* pIDs = pointer to a list of workspace IDs
* numIDs = number of workspace IDs
*
* Outputs:
* -------
*
*************************************<->***********************************/
void
RemoveSingleClientFromWorkspaces(
ClientData *pCD,
WorkspaceID *pIDs,
unsigned int numIDs )
{
int i;
WmWorkspaceData *pWS;
for (i=0; i < numIDs; i++)
{
/*
* Remove the client from the specified workspaces
*/
if ((pWS = GetWorkspaceData (pCD->pSD, pIDs[i])) &&
(ClientInWorkspace (pWS, pCD)))
{
/*
* If this workspace is active, then make the
* window unseen. We only need to call
* SetClientState on the main window, the
* transients will get taken care of in there.
*/
if ((pWS == pCD->pSD->pActiveWS) &&
(pCD->transientLeader == NULL) &&
!(pCD->clientState & UNSEEN_STATE))
{
SetClientState (pCD,
(pCD->clientState | UNSEEN_STATE), CurrentTime);
}
TakeClientOutOfWorkspace (pWS, pCD);
/*
* Update the presence property
*/
UpdateWorkspacePresenceProperty (pCD);
}
}
} /* END OF FUNCTION RemoveSingleClientFromWorkspaces */
/*************************************<->*************************************
*
* RemoveSubtreeFromWorkspaces (pCD, pIDs, numIDs)
*
*
* Description:
* -----------
* This function removes a transient subtree from a list of workspaces
*
* Inputs:
* ------
* pCD = pointer to client data
* pIDs = pointer to a list of workspace IDs
* numIDs = number of workspace IDs
*
* Outputs:
* -------
*
*************************************<->***********************************/
void
RemoveSubtreeFromWorkspaces(
ClientData *pCD,
WorkspaceID *pIDs,
unsigned int numIDs )
{
ClientData *pNext;
pNext = pCD->transientChildren;
while (pNext)
{
/* process all children first */
if (pNext->transientChildren)
{
RemoveSubtreeFromWorkspaces (pNext, pIDs, numIDs);
}
else
{
RemoveSingleClientFromWorkspaces (pNext, pIDs, numIDs);
}
pNext = pNext->transientSiblings;
}
/* process the primary window */
RemoveSingleClientFromWorkspaces (pCD, pIDs, numIDs);
} /* END OF FUNCTION RemoveSubtreeFromWorkspaces */
/******************************<->*************************************
*
* pIDs = GetListOfOccupiedWorkspaces (pCD, numIDs)
*
*
* Description:
* -----------
* This function creates a list of occupied workspaces of a particular
* client, EXCLUDING the current workspace.
*
* Inputs:
* ------
* pCD = pointer to client data
*
* Outputs:
* -------
* pIDs = pointer to a list of workspace IDs
* numIDs = number of workspace IDs
*
* Comment
* -------
* memory for pIDs is allocated with XtMalloc and should be
* freed with XtFree.
*
*
******************************<->***********************************/
WorkspaceID *
GetListOfOccupiedWorkspaces(
ClientData *pCD,
int *numIDs )
{
int i;
WorkspaceID *pLocalIDs = NULL;
WorkspaceID activeWsID = pCD->pSD->pActiveWS->id;
*numIDs = 0;
if ((pLocalIDs = (WorkspaceID *) XtMalloc (pCD->numInhabited *
sizeof(WorkspaceID))) == NULL)
{
Warning (((char *)GETMESSAGE(76, 7, "Insufficient memory")));
return (NULL);
}
for (i = 0; i < pCD->numInhabited; i++)
{
if (activeWsID != pCD->pWsList[i].wsID)
{
pLocalIDs[(*numIDs)++] = pCD->pWsList[i].wsID;
}
}
return(pLocalIDs);
} /* END OF FUNCTION GetListOfOccupiedWorkspaces */
/******************************<->*************************************
*
* HonorAbsentMapBehavior(pCD)
*
*
* Description:
* -----------
* This function adds a client to the current workspace and
* if (pCD->absentMapBehavior == AMAP_BEHAVIOR_MOVE)
* removes the client from the other workspaces
*
*
* Inputs:
* ------
* pCD = pointer to client data
*
* Outputs:
* -------
*
******************************<->***********************************/
void
HonorAbsentMapBehavior(
ClientData *pCD)
{
int inWorkspace = 0;
if (pCD->absentMapBehavior == AMAP_BEHAVIOR_MOVE)
{
int wsCnt;
/*
* Remove from other workspaces
*/
for (wsCnt = 0; wsCnt < pCD->numInhabited; wsCnt = inWorkspace)
{
if (pCD->pWsList[wsCnt].wsID != pCD->pSD->pActiveWS->id)
{
RemoveClientFromWorkspaces (pCD,
&pCD->pWsList[wsCnt].wsID, 1);
}
else inWorkspace++;
}
}
if (inWorkspace == 0)
AddClientToWorkspaces (pCD, &ACTIVE_WS->id, 1);
} /* END OF FUNCTION HonorAbsentMapBehavior */
/******************************<->*************************************
*
* RemoveClientFromWorkspaces (pCD, pIDs, numIDs)
*
*
* Description:
* -----------
* This function removes a client from a list of workspaces
*
* Inputs:
* ------
* pCD = pointer to client data
* pIDs = pointer to a list of workspace IDs
* numIDs = number of workspace IDs
*
* Outputs:
* -------
*
******************************<->***********************************/
void
RemoveClientFromWorkspaces(
ClientData *pCD,
WorkspaceID *pIDs,
unsigned int numIDs )
{
ClientData *pcdLeader;
pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
RemoveSubtreeFromWorkspaces (pcdLeader, pIDs, numIDs);
} /* END OF FUNCTION RemoveClientFromWorkspaces */
/*************************************<->*************************************
*
* AddSingleClientToWorkspaces (pCD, pIDs, numIDs)
*
*
* Description:
* -----------
* This function adds a single client to a list of workspaces
*
* Inputs:
* ------
* pCD = pointer to client data
* pIDs = pointer to a list of workspace IDs
* numIDs = number of workspace IDs
*
* Outputs:
* -------
*
*************************************<->***********************************/
void
AddSingleClientToWorkspaces(
ClientData *pCD,
WorkspaceID *pIDs,
unsigned int numIDs )
{
int i;
WmWorkspaceData *pWS;
for (i=0; i < numIDs; i++)
{
/*
* Add the client to the specified workspaces if
* it is not already there.
*/
if ((pWS = GetWorkspaceData (pCD->pSD, pIDs[i])) &&
(!ClientInWorkspace (pWS, pCD)))
{
PutClientIntoWorkspace (pWS, pCD);
if ((pWS == PSD_FOR_CLIENT(pCD)->pActiveWS) &&
(pCD->transientLeader == NULL) &&
(pCD->clientState & UNSEEN_STATE))
{
SetClientState (pCD,
(pCD->clientState & ~UNSEEN_STATE), CurrentTime);
}
/*
* Update the presence property (only on transient leader)
*/
UpdateWorkspacePresenceProperty (pCD);
}
}
} /* END OF FUNCTION AddSingleClientToWorkspace */
/*************************************<->*************************************
*
* AddSubtreeToWorkspaces (pCD, pIDs, numIDs)
*
*
* Description:
* -----------
* This function adds a client subtree to a list of workspaces
*
* Inputs:
* ------
* pCD = pointer to client data (head of subtree)
* pIDs = pointer to a list of workspace IDs
* numIDs = number of workspace IDs
*
* Outputs:
* -------
*
*************************************<->***********************************/
void
AddSubtreeToWorkspaces(
ClientData *pCD,
WorkspaceID *pIDs,
unsigned int numIDs )
{
ClientData *pNext;
pNext = pCD->transientChildren;
while (pNext)
{
/* process all children first */
if (pNext->transientChildren)
{
AddSubtreeToWorkspaces (pNext, pIDs, numIDs);
}
else
{
AddSingleClientToWorkspaces (pNext, pIDs, numIDs);
}
pNext = pNext->transientSiblings;
}
/* process the primary window */
AddSingleClientToWorkspaces (pCD, pIDs, numIDs);
} /* END OF FUNCTION AddSubtreeToWorkspaces */
/*************************************<->*************************************
*
* AddClientToWorkspaces (pCD, pIDs, numIDs)
*
*
* Description:
* -----------
* This function adds a transient tree to a list of workspaces
*
* Inputs:
* ------
* pCD = pointer to client data
* pIDs = pointer to a list of workspace IDs
* numIDs = number of workspace IDs
*
* Outputs:
* -------
*
*************************************<->***********************************/
void
AddClientToWorkspaces(
ClientData *pCD,
WorkspaceID *pIDs,
unsigned int numIDs )
{
ClientData *pcdLeader;
pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
AddSubtreeToWorkspaces (pcdLeader, pIDs, numIDs);
} /* END OF FUNCTION AddClientToWorkspaces */
/*************************************<->*************************************
*
* AddClientToWsList (pWS, pCD)
*
*
* Description:
* -----------
* This function adds a client to a list of clients in a workspace
*
* Inputs:
* ------
* pCD = pointer to client data
* pWS = pointer to workspace data
*
* Outputs:
* -------
* none
*
*************************************<->***********************************/
void
AddClientToWsList(
WmWorkspaceData *pWS,
ClientData *pCD )
{
if (pWS->numClients >= pWS->sizeClientList)
{
if (pWS->sizeClientList == 0)
{
pWS->ppClients = (ClientData **)
XtMalloc (WINDOW_ALLOC_AMOUNT * sizeof(ClientData *));
}
else
{
pWS->ppClients = (ClientData **)
XtRealloc ((char *)pWS->ppClients,
(pWS->sizeClientList + WINDOW_ALLOC_AMOUNT) *
sizeof(ClientData *));
}
if (!pWS->ppClients)
{
Warning (((char *)GETMESSAGE(76, 9, "Insufficient memory to add window to workspace")));
ExitWM(WM_ERROR_EXIT_VALUE);
}
pWS->sizeClientList += WINDOW_ALLOC_AMOUNT;
}
if (pWS->numClients < pWS->sizeClientList)
{
pWS->ppClients[pWS->numClients] = pCD;
pWS->numClients++;
}
} /* END OF FUNCTION AddClientToWsList */
/*************************************<->*************************************
*
* RemoveClientFromWsList (pWS, pCD)
*
*
* Description:
* -----------
* This function removes a client from a list of clients in a workspace
*
* Inputs:
* ------
* pCD = pointer to client data
* pWS = pointer to workspace data
*
* Outputs:
* -------
* none
*
*************************************<->***********************************/
void
RemoveClientFromWsList(
WmWorkspaceData *pWS,
ClientData *pCD )
{
int src, dest;
for (dest = 0; dest < pWS->numClients; dest++)
{
if (pWS->ppClients[dest] == pCD)
{
break;
}
}
for (src = dest+1; src < pWS->numClients; src++, dest++)
{
pWS->ppClients[dest] = pWS->ppClients[src];
}
pWS->numClients--;
} /* END OF FUNCTION RemoveClientFromWsList */
/*************************************<->*************************************
*
* Boolean
* F_CreateWorkspace (args, pCD, event)
*
* Description:
* -----------
*
* Inputs:
* ------
* args = ...
* pCD = ...
* event = ...
*
* Outputs:
* -------
* Return = ...
*
* Comments:
* --------
*
*************************************<->***********************************/
Boolean
F_CreateWorkspace(
String args,
ClientData *pCD,
XEvent *event )
{
WmScreenData *pSD = ACTIVE_PSD;
if (pSD->numWorkspaces >= MAX_WORKSPACE_COUNT)
{
char buffer[MAXWMPATH];
/*
* At the maximum number of allowed workspaces.
*/
sprintf (buffer,
((char *)GETMESSAGE(76, 14, "Maximum number of workspaces is %d. New workspace was not created.")), MAX_WORKSPACE_COUNT);
Warning (buffer);
}
else
{
CreateWorkspace (ACTIVE_PSD, (unsigned char *)args);
}
return (TRUE);
} /* END OF FUNCTION F_CreateWorkspace */
/*************************************<->*************************************
*
* Boolean
* F_DeleteWorkspace (args, pCD, event)
*
* Description:
* -----------
*
* Inputs:
* ------
* args = ...
* pCD = ...
* event = ...
*
* Outputs:
* -------
* Return = ...
*
* Comments:
* --------
*
*************************************<->***********************************/
Boolean
F_DeleteWorkspace(
String args,
ClientData *pCD,
XEvent *event )
{
WmScreenData *pSD = ACTIVE_PSD;
WmWorkspaceData *pWS = NULL;
int i;
if (args == NULL)
{
pWS= ACTIVE_WS;
}
else
{
for (i=0; i<pSD->numWorkspaces; i++)
{
if (!strcmp(pSD->pWS[i].name, args))
{
pWS = &(pSD->pWS[i]);
break;
}
}
}
if (pWS)
DeleteWorkspace (pWS);
return (TRUE);
} /* END OF FUNCTION F_DeleteWorkspace */
/*************************************<->*************************************
*
* Boolean
* F_GotoWorkspace (args, pCD, event)
*
* Description:
* -----------
*
* Inputs:
* ------
* args = ...
* pCD = ...
* event = ...
*
* Outputs:
* -------
* Return = ...
*
* Comments:
* --------
*
*************************************<->***********************************/
Boolean
F_GotoWorkspace(
String args,
ClientData *pCD,
XEvent *event )
{
WorkspaceID wsID;
WmWorkspaceData *pWS;
wsID = XInternAtom (DISPLAY, args, False);
pWS = GetWorkspaceData (ACTIVE_PSD, wsID);
if (pWS)
{
ChangeToWorkspace (pWS);
}
return (TRUE);
} /* END OF FUNCTION F_GotoWorkspace */
/*************************************<->*************************************
*
* Boolean
* F_AddToAllWorkspaces (args, pCD, event)
*
*
* Description:
* -----------
* Puts a client into all workspaces
*
*
* Inputs:
* ------
* args = ...
* pCD = pointer to client data
* event = ...
*
*
* Outputs:
* -------
* Return = True
*
*
* Comments:
* --------
* The list of Ids returned has been privately allocated. Copy
* if you want to save or do anything with it.
*
*************************************<->***********************************/
Boolean
F_AddToAllWorkspaces(
String args,
ClientData *pCD,
XEvent *event )
{
WmScreenData *pSD;
int i;
if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
{
pSD = pCD->pSD;
ReserveIdListSpace (pSD->numWorkspaces);
for (i = 0; i < pSD->numWorkspaces; i++)
{
pResIDs[i] = pSD->pWS[i].id;
}
AddClientToWorkspaces (pCD, pResIDs, pSD->numWorkspaces);
pCD->putInAll = True;
}
return (True);
} /* END OF FUNCTION F_AddToAllWorkspaces */
/*************************************<->*************************************
*
* Boolean
* F_Remove (args, pCD, event)
*
*
* Description:
* -----------
* Removes a client from the current workspace
*
*
* Inputs:
* ------
* args = ...
* pCD = pointer to client data
* event = ...
*
*
* Outputs:
* -------
* Return = True
*
*
* Comments:
* --------
*
*************************************<->***********************************/
Boolean
F_Remove(
String args,
ClientData *pCD,
XEvent *event )
{
Boolean rval = False;
/*
* Only remove if in more than one workspace.
*/
if ((pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS)) &&
(pCD->numInhabited > 1))
{
if (ClientInWorkspace (ACTIVE_WS, pCD))
{
RemoveClientFromWorkspaces (pCD, &ACTIVE_WS->id, 1);
pCD->putInAll = False;
}
}
return (rval);
} /* END OF FUNCTION F_Remove */
/*************************************<->*************************************
*
* GetCurrentWorkspaceIndex (pSD)
*
*
* Description:
* -----------
* Returns an index into the screens array of workspace structures
* for the current workspace.
*
*
* Inputs:
* ------
*
*
* Outputs:
* -------
*
*
* Comments:
* --------
*************************************<->***********************************/
int
GetCurrentWorkspaceIndex(
WmScreenData *pSD )
{
int i;
for (i = 0 ; i < pSD->numWorkspaces; i++)
{
if (pSD->pWS[i].id == pSD->pActiveWS->id)
break;
}
if (i >= pSD->numWorkspaces)
{
/* failed to find workspace!!! How did that happen??? */
i = 0;
#ifdef DEBUG
Warning ("Failed to find workspace index");
#endif /* DEBUG */
}
return(i);
} /* END OF FUNCTION GetCurrentWorkspaceIndex */
/*************************************<->*************************************
*
* void
* InsureIconForWorkspace (pWS, pCD)
*
*
* Description:
* -----------
* Makes sure an icon exists for the workspace
*
*
* Inputs:
* ------
*
*
* Outputs:
* -------
*
* Comments:
* --------
*
*************************************<->***********************************/
void
InsureIconForWorkspace(
WmWorkspaceData *pWS,
ClientData *pCD )
{
WsClientData *pWsc;
if (pCD->clientFunctions & MWM_FUNC_MINIMIZE)
{
pWsc = GetWsClientData (pWS, pCD);
if ((pCD->pSD->useIconBox) &&
(!(pCD->clientFlags & (CLIENT_WM_CLIENTS | FRONT_PANEL_BOX))))
{
/*
* Create a new widget for the icon box
*/
if (MakeIcon (pWS, pCD))
{
XSaveContext (DISPLAY, pWsc->iconFrameWin,
wmGD.windowContextType, (caddr_t)pCD);
if (pCD->iconWindow && pWsc->iconFrameWin)
{
XGrabButton (DISPLAY, AnyButton, AnyModifier,
pWsc->iconFrameWin, True,
ButtonPressMask|ButtonReleaseMask|
ButtonMotionMask,
GrabModeAsync, GrabModeAsync, None,
wmGD.workspaceCursor);
}
ShowClientIconState (pCD, (pCD->clientState & ~UNSEEN_STATE));
}
}
else
{
/*
* Reuse existing icon in new workspaces. Suggest
* icon position in current WS as position of icon
* in new WS.
*/
pWsc->iconFrameWin = pCD->pWsList[0].iconFrameWin;
pWsc->iconX = ICON_X(pCD);
pWsc->iconY = ICON_Y(pCD);
if ((pCD->clientState & ~UNSEEN_STATE) != MINIMIZED_STATE)
{
pWsc->iconPlace = NO_ICON_PLACE;
}
else if (!wmGD.iconAutoPlace)
{
if (wmGD.positionIsFrame)
{
pWsc->iconX -= pCD->clientOffset.x;
pWsc->iconY -= pCD->clientOffset.y;
}
PlaceIconOnScreen (pCD, &pWsc->iconX, &pWsc->iconY);
}
else /* icon auto placement */
{
pWsc->iconPlace =
CvtIconPositionToPlace (&pWS->IPData,
pWsc->iconX, pWsc->iconY);
if (pWS->IPData.placeList[pWsc->iconPlace].pCD)
{
/* The spot is already occupied! Find a
spot nearby. */
pWsc->iconPlace =
FindIconPlace (pCD, &pWS->IPData, pWsc->iconX,
pWsc->iconY);
if (pWsc->iconPlace == NO_ICON_PLACE)
{
/* Can't find a spot close by. Use the
next available slot */
pWsc->iconPlace = GetNextIconPlace (&pWS->IPData);
if (pWsc->iconPlace == NO_ICON_PLACE)
{
pWsc->iconPlace =
CvtIconPositionToPlace (&pWS->IPData,
pCD->clientX,
pCD->clientY);
}
}
}
CvtIconPlaceToPosition (&pWS->IPData, pWsc->iconPlace,
&pWsc->iconX, &pWsc->iconY);
if (!(pWS->IPData.placeList[pWsc->iconPlace].pCD))
{
pWS->IPData.placeList[pWsc->iconPlace].pCD = pCD;
}
}
}
}
} /* END OF FUNCTION InsureIconForWorkspace */
/*************************************<->*************************************
*
* Boolean
* GetLeaderPresence (pCD, pIDs, pnumIDs)
*
*
* Description:
* -----------
* Gets the workspace presence of the transient tree leader for a
* client.
*
*
* Inputs:
* ------
* pCD = pointer to client data
* ppIDs = pointer to pointer to list of workspace ids
* pnumIDs = pointer to number of workspace ids
*
*
* Outputs:
* -------
* *ppIDS = list of workspace IDs
* *pnumIDs = number of workspace IDs in list
*
* Return = true on success
*
*
* Comments:
* --------
* ID list is dynamically allocated, please XtFree() it when you're
* done.
*
*************************************<->***********************************/
Boolean
GetLeaderPresence(
ClientData *pCD,
WorkspaceID **ppIDs,
unsigned int *pnumIDs )
{
ClientData *pcdLeader;
int i;
Boolean rval = False;
WorkspaceID *pLocalIDs;
if ((pLocalIDs = (WorkspaceID *) XtMalloc (pCD->pSD->numWorkspaces *
sizeof(WorkspaceID))) == NULL)
{
Warning (((char *)GETMESSAGE(76, 10, "Insufficient Memory (GetLeaderPresence)")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
/*
* Make up list of workspaces for primary window
*/
if (pCD->transientLeader)
{
pcdLeader = FindTransientTreeLeader (pCD);
for (i = 0; i < pcdLeader->numInhabited; i++)
{
pLocalIDs[i] = pcdLeader->pWsList[i].wsID;
}
*ppIDs = pLocalIDs;
*pnumIDs = pcdLeader->numInhabited;
rval = True;
}
return (rval);
} /* END OF FUNCTION GetLeaderPresence */
/*************************************<->*************************************
*
* Boolean
* GetMyOwnPresence (pCD, pIDs, pnumIDs)
*
*
* Description:
* -----------
* Returns the current workspace presence for the client
*
*
* Inputs:
* ------
* pCD = pointer to client data
* ppIDs = pointer to pointer to list of workspace ids
* pnumIDs = pointer to number of workspace ids
*
*
* Outputs:
* -------
* *ppIDS = list of workspace IDs
* *pnumIDs = number of workspace IDs in list
*
* Return = true on success
*
*
* Comments:
* --------
* ID list is dynamically allocated (by DtWsmGetWorkspacesOccupied).
* Please XtFree() it when you're done.
*
*************************************<->***********************************/
Boolean
GetMyOwnPresence(
ClientData *pCD,
WorkspaceID **ppIDs,
unsigned int *pnumIDs )
{
Boolean rval = False;
unsigned long nIDs = (unsigned long)*pnumIDs;
/*
* Get the workspace presence property
*/
if (
HasProperty (pCD, wmGD.xa_DT_WORKSPACE_PRESENCE)
&& (DtWsmGetWorkspacesOccupied (DISPLAY, pCD->client, ppIDs,
&nIDs) == Success))
{
if (nIDs)
{
rval = True;
}
}
*pnumIDs = (unsigned int)nIDs;
return (rval);
} /* END OF FUNCTION GetMyOwnPresence */
/*************************************<->*************************************
*
* void
* ReserveIdListSpace (numIDs)
*
*
* Description:
* -----------
* Insures that there is enough room in our privately allocated
* list of workspace IDs
*
*
* Inputs:
* ------
* numIDs = number of workspace ids
*
* Outputs:
* -------
*
* Comments:
* --------
*************************************<->***********************************/
void
ReserveIdListSpace(
int numIDs )
{
if (numResIDs == 0)
{
pResIDs = (WorkspaceID *)
XtMalloc (numIDs * sizeof (WorkspaceID));
if (pResIDs)
{
numResIDs = numIDs;
}
}
else if (numResIDs < numIDs)
{
pResIDs = (WorkspaceID *) XtRealloc ((char *)pResIDs,
numIDs * sizeof (WorkspaceID));
numResIDs = (pResIDs)? numIDs : 0;
}
if (pResIDs == NULL)
{
Warning (((char *)GETMESSAGE(76, 11, "Insufficient memory")));
ExitWM (WM_ERROR_EXIT_VALUE);
}
} /* END OF FUNCTION ReserveIdListSpace */
/******************************<->*************************************
*
* SaveResources (pSD)
*
* Description:
* -----------
* Saves dtwm resources to restore session
*
* Inputs:
* ------
* pSD = pointer to screen data
*
* Outputs:
* -------
* None
*
* Comments:
* ---------
*
*************************************<->***********************************/
void
SaveResources( WmScreenData *pSD)
{
int wsCnt;
WmPanelistObject pPanelist;
if(pSD)
{
if (pSD->pActiveWS)
{
SaveWorkspaceResources(pSD->pActiveWS,
(WM_RES_INITIAL_WORKSPACE |
WM_RES_WORKSPACE_COUNT));
}
pPanelist = (WmPanelistObject) pSD->wPanelist;
if (pPanelist && O_Shell(pPanelist))
{
/* This is the front panel for the screen */
SaveWorkspaceResources(pSD->pActiveWS,
WM_RES_FP_POSITION);
/* Call the fronto panel function to save its resources */
WmFrontPanelSessionSaveData();
}
for (wsCnt = 0; wsCnt < pSD->numWorkspaces; wsCnt++)
{
if(pSD->useIconBox)
{
SaveWorkspaceResources(&pSD->pWS[wsCnt],
WM_RES_ICONBOX_GEOMETRY);
}
} /* for wsCnt */
SaveHelpResources(pSD);
} /* if pSD */
} /* END OF FUNCTION SaveResources */
/******************************<->*************************************
*
* SaveWorkspaceResource (pWS, flags)
*
* Description:
* -----------
* Modifies the RESOURCE_MANAGER property to add update versions
* of the requested resources.
*
* Inputs:
* ------
* pWS = pointer to workspace data
*
* Outputs:
* -------
* None
*
* Comments:
* ---------
*
*************************************<->***********************************/
void
SaveWorkspaceResources(
WmWorkspaceData *pWS,
unsigned long flags)
{
char *buffer = NULL;
int bufferLength = 0;
char *res_class;
char *data;
int cum_len;
char screenName[1024];
char tmpScreenName[10];
Position clientX;
Position clientY;
Dimension clientWidth;
Dimension clientHeight;
int xoff, yoff;
WmPanelistObject pPanelist = (WmPanelistObject) pWS->pSD->wPanelist;
ClientData *pCD_Panel ;
char tmpBuffer[MAXWMPATH+1];
int iLen;
/* allocate initial data space */
if ((data = (char *) XtMalloc (MAXWMPATH+1)) == NULL)
{
Warning (((char *)
GETMESSAGE(76,12,"Insufficient memory to save resources")));
Do_Quit_Mwm (False);
}
cum_len = 1;
*data = '\0';
if (bufferLength == 0)
{
buffer = (char *) XtMalloc (MAXWMPATH+1);
bufferLength = MAXWMPATH;
}
*buffer = '\0';
/* Get our current resource class */
if (MwmBehavior)
{
res_class = WM_RESOURCE_CLASS;
}
else
{
res_class = DT_WM_RESOURCE_CLASS;
}
strcpy(screenName, "*");
strcat(screenName,XtName (pWS->pSD->screenTopLevelW));
/* construct and write out the resources specification */
if (flags & WM_RES_BACKDROP_IMAGE)
{
iLen = (strlen (res_class) + strlen (screenName) +
strlen (pWS->name) + strlen (WmNbackdrop) +
strlen (WmNimage) + strlen (pWS->backdrop.image) + 20);
if (iLen > bufferLength)
{
bufferLength += iLen;
buffer = (char *)
XtRealloc (buffer, bufferLength * sizeof(char));
}
sprintf (buffer, "%s%s*%s*%s*%s: %s\n", res_class,
screenName, pWS->name,
WmNbackdrop, WmNimage, pWS->backdrop.image);
AddStringToResourceData (buffer, &data, &cum_len);
}
if (flags & WM_RES_BACKDROP_IMAGETYPE)
{
iLen = (strlen (res_class) + strlen (screenName) +
strlen (pWS->name) + strlen (WmNbackdrop) +
strlen (WmNimageType) + 22);
if (iLen > bufferLength)
{
bufferLength += iLen;
buffer = (char *)
XtRealloc (buffer, bufferLength * sizeof(char));
}
sprintf (buffer, "%s%s*%s*%s*%s: %d\n", res_class,
screenName, pWS->name,
WmNbackdrop, WmNimageType, pWS->backdrop.imageType);
AddStringToResourceData (buffer, &data, &cum_len);
}
if (flags & WM_RES_WORKSPACE_TITLE)
{
String asciiName;
asciiName = WmXmStringToString (pWS->title);
iLen = strlen (res_class) + strlen (screenName) +
strlen (pWS->name) + strlen (WmNtitle) +
strlen (asciiName) + 16;
if (iLen > bufferLength)
{
bufferLength += iLen;
buffer = (char *)
XtRealloc (buffer, bufferLength * sizeof(char));
}
sprintf (buffer, "%s%s*%s*%s: %s\n", res_class,
screenName, pWS->name,
WmNtitle, asciiName);
AddStringToResourceData (buffer, &data, &cum_len);
XtFree (asciiName);
}
if ((flags & WM_RES_INITIAL_WORKSPACE) &&
(!wmGD.useStandardBehavior))
{
iLen = strlen (res_class) + strlen (screenName) +
strlen (WmNinitialWorkspace) + strlen (pWS->name) + 14;
if (iLen > bufferLength)
{
bufferLength += iLen;
buffer = (char *)
XtRealloc (buffer, bufferLength * sizeof(char));
}
sprintf (buffer, "%s%s*%s: %s\n", res_class,
screenName,
WmNinitialWorkspace, pWS->name);
AddStringToResourceData (buffer, &data, &cum_len);
}
if ((flags & WM_RES_WORKSPACE_LIST) &&
(!wmGD.useStandardBehavior))
{
WmWorkspaceData *pWSi;
char *pchQname;
int i;
pWSi = pWS->pSD->pWS;
pchQname = (char *) _DtWmParseMakeQuotedString (
(unsigned char *)pWSi->name);
strcpy ((char *)wmGD.tmpBuffer, pchQname);
XtFree (pchQname);
pWSi++;
for (i=1; i<pWS->pSD->numWorkspaces; i++, pWSi++)
{
strcat ((char *)wmGD.tmpBuffer, " ");
pchQname = (char *) _DtWmParseMakeQuotedString (
(unsigned char *)pWSi->name);
strcat ((char *)wmGD.tmpBuffer, pchQname);
XtFree (pchQname);
}
sprintf (buffer, "%s%s*%s: %s\n", res_class,
screenName,
WmNworkspaceList, wmGD.tmpBuffer);
AddStringToResourceData (buffer, &data, &cum_len);
}
if ((flags & WM_RES_WORKSPACE_COUNT) &&
(!wmGD.useStandardBehavior))
{
char pchNumWs[20];
sprintf (pchNumWs, "%d", pWS->pSD->numWorkspaces);
iLen = strlen (res_class) + strlen (screenName) +
strlen (WmNworkspaceCount) + strlen (pchNumWs) + 14;
if (iLen > bufferLength)
{
bufferLength += iLen;
buffer = (char *)
XtRealloc (buffer, bufferLength * sizeof(char));
}
sprintf (buffer, "%s%s*%s: %s\n", res_class,
screenName,
WmNworkspaceCount, pchNumWs);
AddStringToResourceData (buffer, &data, &cum_len);
}
if ((flags & WM_RES_FP_POSITION) &&
(O_Shell(pPanelist)) &&
(!wmGD.useStandardBehavior) &&
(!XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
wmGD.windowContextType,
(XtPointer)&pCD_Panel)))
{
Position midX, midY, tmpX, tmpY;
Dimension screenWidth, screenHeight;
clientX = pCD_Panel->clientX;
clientY = pCD_Panel->clientY;
/*
* Determine quadrant that the front panel midpoint is
* in and save front panel with appropriate gravity.
*/
/* find panel midpoint */
midX = clientX+(pCD_Panel->clientWidth >> 1);
midY = clientY+(pCD_Panel->clientHeight >> 1);
/* get screen dimensions */
screenWidth = XDisplayWidth (DISPLAY, pCD_Panel->pSD->screen);
screenHeight = XDisplayHeight (DISPLAY, pCD_Panel->pSD->screen);
/*
* Determine midpoint quadrant and set up client geometry
* relative to that corner. Adjust if positionIsFrame
* is being used.
*/
if (midX <= (Position) screenWidth/2)
{
if(wmGD.positionIsFrame)
{
clientX -= pCD_Panel->frameInfo.upperBorderWidth;
}
/* West */
if (midY <= (Position) screenHeight/2)
{
/* NorthWest */
if(wmGD.positionIsFrame)
{
clientY -= (pCD_Panel->frameInfo.upperBorderWidth +
pCD_Panel->frameInfo.titleBarHeight);
}
sprintf (tmpBuffer, "+%d+%d", clientX, clientY);
}
else
{
/* SouthWest */
clientY = screenHeight - clientY - pCD_Panel->clientHeight;
if(wmGD.positionIsFrame)
{
clientY -= pCD_Panel->frameInfo.lowerBorderWidth;
}
sprintf (tmpBuffer, "+%d-%d", clientX, clientY);
}
}
else
{
clientX = screenWidth - clientX - pCD_Panel->clientWidth;
if (wmGD.positionIsFrame)
{
clientX -= pCD_Panel->frameInfo.lowerBorderWidth;
}
/* East */
if (midY <= (Position) screenHeight/2)
{
/* NorthEast */
if(wmGD.positionIsFrame)
{
clientY -= (pCD_Panel->frameInfo.upperBorderWidth +
pCD_Panel->frameInfo.titleBarHeight);
}
sprintf (tmpBuffer, "-%d+%d", clientX, clientY);
}
else
{
/* SouthEast */
clientY = screenHeight - clientY - pCD_Panel->clientHeight;
if(wmGD.positionIsFrame)
{
clientY -= pCD_Panel->frameInfo.lowerBorderWidth;
}
sprintf (tmpBuffer, "-%d-%d", clientX, clientY);
}
}
iLen = strlen (res_class) + strlen (screenName) +
strlen (XtName(O_Shell(pPanelist))) +
strlen (WmNgeometry) + strlen (tmpBuffer) + 18;
if (iLen > bufferLength)
{
bufferLength += iLen;
buffer = (char *)
XtRealloc (buffer, bufferLength * sizeof(char));
}
sprintf (buffer, "%s%s*%s*%s: %s\n", res_class,
screenName,
XtName (O_Shell(pPanelist)),
WmNgeometry, tmpBuffer);
AddStringToResourceData (buffer, &data, &cum_len);
}
if ((flags & WM_RES_ICONBOX_GEOMETRY) &&
(!wmGD.useStandardBehavior))
{
/* update iconbox geometry string */
if (pWS->iconBoxGeometry)
{
XtFree((char *) (pWS->iconBoxGeometry));
pWS->iconBoxGeometry = NULL;
}
clientWidth = (pWS->pIconBox->pCD_iconBox->clientWidth -
pWS->pIconBox->pCD_iconBox->baseWidth) /
pWS->pIconBox->pCD_iconBox->widthInc;
clientHeight = (pWS->pIconBox->pCD_iconBox->clientHeight -
pWS->pIconBox->pCD_iconBox->baseHeight) /
pWS->pIconBox->pCD_iconBox->heightInc ;
if(wmGD.positionIsFrame)
{
CalculateGravityOffset (pWS->pIconBox->pCD_iconBox, &xoff, &yoff);
clientX = pWS->pIconBox->pCD_iconBox->clientX - xoff;
clientY = pWS->pIconBox->pCD_iconBox->clientY - yoff;
}
else
{
clientX = pWS->pIconBox->pCD_iconBox->clientX;
clientY = pWS->pIconBox->pCD_iconBox->clientY;
}
sprintf (buffer, "%dx%d+%d+%d", clientWidth, clientHeight,
clientX, clientY);
pWS->iconBoxGeometry = strdup( buffer);
iLen = strlen (res_class) + strlen (screenName) +
strlen (pWS->name) + strlen (WmNiconBoxGeometry) +
strlen (pWS->iconBoxGeometry) + 18;
if (iLen > bufferLength)
{
bufferLength += iLen;
buffer = (char *)
XtRealloc (buffer, bufferLength * sizeof(char));
}
sprintf (buffer, "%s%s*%s*%s: %s\n", res_class,
screenName, pWS->name,
WmNiconBoxGeometry, pWS->iconBoxGeometry);
AddStringToResourceData (buffer, &data, &cum_len);
}
if (data)
{
/*
* Merge in the resource(s)
*/
_DtAddToResource (DISPLAY, data);
XtFree(data);
}
XtFree(buffer);
} /* END OF FUNCTION SaveWorkspaceResources */
/******************************<->*************************************
*
* AddStringToResourceData (string, pdata, plen)
*
* Description:
* -----------
* Adds a string to a growing buffer of strings.
*
* Inputs:
* ------
* string - string to add
* pdata - pointer to data pointer
* plen - number of bytes used in *pdata already
*
* Outputs:
* -------
* *pdata - data pointer (may be changed by XtRealloc)
* *plen - number of bytes used in *pdata (old value plus length
* of string
*
* Comments:
* ---------
*
*************************************<->***********************************/
void
AddStringToResourceData(
char *string,
char **pdata,
int *plen )
{
if ((*pdata = (char *) XtRealloc(*pdata, *plen+strlen(string)+1)) == NULL)
{
Warning (((char *)GETMESSAGE(76, 13, "Insufficient memory to save resources.")));
Do_Quit_Mwm (False);
}
strcat (*pdata, string);
*plen += strlen(string);
} /* END OF FUNCTION AddStringToResourceData */
/*************************************<->*************************************
*
* DuplicateWorkspaceName (pSD, name, num)
*
*
* Description:
* -----------
* This function searches the first "num" workspace names to see if the
* passed "name" duplicates any workspace name defined so far.
*
*
* Inputs:
* ------
* pSD = pointer to screen data
* name = potential string name for workspace
* num = number of workspaces to check against
*
* Outputs:
* -------
* Return = True if a dupicate was found
*
* Comments:
* --------
*
*************************************<->***********************************/
Boolean
DuplicateWorkspaceName (WmScreenData *pSD, unsigned char *name, int num)
{
int i;
Boolean duplicate = False;
if (pSD && pSD->pWS)
{
for (i = 0; (i < num) && !duplicate; i++)
{
if (!strcmp (pSD->pWS[i].name, (char *)name))
{
duplicate = True;
}
}
}
return (duplicate);
}
#ifdef DEBUG
int PrintWorkspaceList (pSD)
WmScreenData *pSD;
{
int i, j, k;
WmWorkspaceData *pWS;
ClientData *pCD;
ClientData *pClients[500];
int numSaved = 0;
Boolean Saved;
fprintf (stderr, "Screen: %d\n", pSD->screen);
for (i =0; i < pSD->numWorkspaces; i++)
{
pWS = &pSD->pWS[i];
fprintf (stderr, "\nWorkspace %s contains: \n", pWS->name);
for (j = 0; j < pWS->numClients; j++)
{
pCD = pWS->ppClients[j];
fprintf (stderr, "\t%s\n", pCD->clientName);
Saved = False;
for (k = 0; k < numSaved; k++)
{
if (pCD == pClients[k])
{
Saved = True;
break;
}
}
if (!Saved)
{
pClients[numSaved++] = pCD;
}
}
}
for (i = 0; i < numSaved; i++)
{
pCD = pClients[i];
fprintf (stderr, "\nClient %s is in: \n", pCD->clientName);
for (j = 0; j < pCD->numInhabited; j++)
{
pWS = GetWorkspaceData (pCD->pSD, pCD->pWsList[j].wsID);
fprintf (stderr, "\t%s\n", pWS->name);
}
}
} /* END OF FUNCTION PrintWorkspaceList */
#endif /* DEBUG */