2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: SmWindow.c /main/6 1997/03/07 10:25:30 barstow $ */
25 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
26 * (c) Copyright 1993, 1994 International Business Machines Corp. *
27 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
28 * (c) Copyright 1993, 1994 Novell, Inc. *
30 /*************************************<+>*************************************
31 *****************************************************************************
35 ** Project: HP DT Session Manager (dtsession)
39 ** This file contains all routines needed to query the window tree.
40 ** The window tree needs to be queried to find all top level windows.
43 *******************************************************************
44 ** (c) Copyright Hewlett-Packard Company, 1990. All rights are
45 ** reserved. Copying or other reproduction of this program
46 ** except for archival purposes is prohibited without prior
47 ** written consent of Hewlett-Packard Company.
48 ********************************************************************
52 *****************************************************************************
53 *************************************<+>*************************************/
56 #include <X11/Intrinsic.h>
57 #include <X11/Xutil.h>
58 #include <X11/Xatom.h>
59 #include <Dt/UserMsg.h>
64 #include "SmProtocol.h"
65 #include "SmGlobals.h"
69 * Variables global to this module only
71 static Boolean commandTimeout;
74 * Local Function declarations
77 static WindowInfo GetTopLevelWindowInfo(
79 static void WaitForCommand(
81 static void WaitTimeout( XtPointer , XtIntervalId *) ;
86 /*************************************<->*************************************
88 * GetTopLevelWindowInfo (window)
93 * Given a child of the root - find the top level window for that child.
98 * window = the current window that is being queried about
103 * retInfo = a WindowInfo structure (a window id + state of the window) that
104 * gives the top level window information.
109 *************************************<->***********************************/
111 GetTopLevelWindowInfo(
115 Window parent,root,*children;
119 unsigned long nitems;
120 unsigned long leftover;
121 unsigned int nchildren;
122 WM_STATE *wmState = NULL;
123 XWindowAttributes windowAttr;
125 if ((XGetWindowAttributes(smGD.display, window,&windowAttr)) == 0)
128 retInfo.termState = 0;
133 * If WM_STATE could not be interned at the beginning - the window manager
134 * may have been slow in coming up. Try it again now.
136 if(XaWmState == None)
138 XaWmState = XInternAtom(smGD.display, _XA_WM_STATE, True);
141 XGetWindowProperty(smGD.display,window,XaWmState,
142 0L,(long)BUFSIZ,False,
143 XaWmState,&actualType,&actualFormat,
145 &leftover,(unsigned char **) &wmState);
146 if (actualType==XaWmState)
148 retInfo.wid = window;
149 retInfo.termState = wmState->state;
152 * This data needs to be freed up!
154 SM_FREE((char *) wmState);
160 * Be sure to free the window property each time we get it
161 * if the property exists
163 if(actualType != None)
165 SM_FREE((char *) wmState);
168 if(XQueryTree(smGD.display,window,&root,
169 &parent,&children,&nchildren) != 0)
176 retInfo = GetTopLevelWindowInfo(children[i++]);
179 SM_FREE((char *) children);
183 SM_FREE((char *) children);
187 retInfo.termState = 0;
194 /*************************************<->*************************************
196 * WaitForCommand (window)
201 * This routine waits for an update on the WM_COMMAND property of a top
202 * level window after a WM_SAVE_YOURSELF has been placed on that window.
207 * window = window id for the
216 *************************************<->***********************************/
223 XPropertyEvent *pEvent=(XPropertyEvent *)&event;
224 XtIntervalId comTimerId;
225 Boolean commandUpdated;
228 * Set a configurable timer which stops the block
230 commandUpdated = False;
231 commandTimeout = False;
232 comTimerId = XtAppAddTimeOut(smGD.appCon, smRes.saveYourselfTimeout,
233 WaitTimeout, (XtPointer) window);
235 while((commandUpdated == False) && (commandTimeout == False))
237 if((isThere = XtAppPending(smGD.appCon)) != 0)
239 if(isThere & XtIMXEvent)
241 XtAppPeekEvent(smGD.appCon, &event);
242 if (event.type==PropertyNotify&&pEvent->window==window&&
243 pEvent->atom==XA_WM_COMMAND)
245 commandUpdated = True;
248 if(commandTimeout == False)
250 XtAppProcessEvent(smGD.appCon, XtIMXEvent | XtIMTimer);
255 XtRemoveTimeOut(comTimerId);
256 XSelectInput(smGD.display, window,NoEventMask);
263 /*************************************<->*************************************
265 * SaveYourself (windowInfo)
270 * Places the WM_SAVE_YOURSELF property on each top level window. It then
271 * waits for the window to update its WM_COMMAND property.
276 * windowInfo = window id for the top level wincow and the state of that
286 *************************************<->***********************************/
289 WindowInfo windowInfo )
295 XClientMessageEvent saveYourselfMessage;
298 * Get the WM_PROTOCOLS property on the clients top-level window.
300 if(XGetWMProtocols(smGD.display, windowInfo.wid, &protoRet, &nitems) == 0)
303 * If the client doesn't have a WM_PROTOCOLS property,
304 * it doesn't support any protocols.
309 /* Look for WM_SAVE_YOURSELF atom. */
310 for (i=0;i<nitems;++i)
312 if (protoRet[i]==XaWmSaveYourself)
318 SM_FREE((char *) protoRet);
319 return(-1); /* doesn't participate in WM_SAVE_YOURSELF */
322 /* Construct the ClientMessage. */
323 saveYourselfMessage.type=ClientMessage;
324 saveYourselfMessage.window=windowInfo.wid;
325 saveYourselfMessage.message_type=XaWmProtocols;
326 saveYourselfMessage.format=32;
327 saveYourselfMessage.data.l[0]=XaWmSaveYourself;
328 saveYourselfMessage.data.l[1]=CurrentTime;
331 * look for changes in WM_COMMAND property
333 XSelectInput(smGD.display,windowInfo.wid,PropertyChangeMask);
334 XFlush(smGD.display);
337 * Send the ClientMessage to the client. XSendEvent returns a 1 if it
338 * is successful in converting the event to a wire event.
340 if (XSendEvent(smGD.display,windowInfo.wid,False,NoEventMask,
341 (XEvent *) &saveYourselfMessage) != 1)
343 PrintError(DtError, GETMESSAGE(20, 1, "Client message failed. Client information will not be saved."));
347 /* Wait for client to update WM_COMMAND. */
348 WaitForCommand(windowInfo.wid);
350 SM_FREE((char *) protoRet);
357 /*************************************<->*************************************
359 * GetTopLevelWindows (screen, toplist, toplistlength, containedListLength)
364 * Querys the window tree and constructs a list of all top level windows
369 * screen = pointer to the screen we're currently querying on
374 * toplist = a pointer to the list of top level windows
375 * toplistlength = the length of the list of top level windows
376 * containedListLength = the length of the list of contained windows
381 *************************************<->***********************************/
385 WindowInfo **topList,
386 unsigned int *topListLength,
387 unsigned int *containedListLength )
389 Window rootWindow, parentWindow, *tmpChild;
390 Window *childList, *embeddedList, *tmpList;
391 WindowInfo topLevelWindowInfo;
393 unsigned long numEmbedded;
396 * Get a list of children of the root window
398 if (XQueryTree(smGD.display, RootWindow(smGD.display, screen),&rootWindow,
399 &parentWindow, &childList, topListLength) == 0)
401 PrintError(DtError, GETMESSAGE(20, 2, "Invalid root window. Can not save client information."));
406 * add in the list of top level windows embedded in the front panel
408 if(_DtGetEmbeddedClients(smGD.display, RootWindow(smGD.display, screen),
409 &embeddedList, &numEmbedded) != Success)
415 *topList=(WindowInfo *) SM_MALLOC(sizeof(WindowInfo)*
416 (*topListLength + numEmbedded));
418 tmpChild = childList;
420 for (i=0 ; i<*topListLength; ++i, tmpChild++)
422 topLevelWindowInfo = GetTopLevelWindowInfo(*tmpChild);
423 if (!topLevelWindowInfo.wid)
425 topLevelWindowInfo.wid = (*tmpChild);
427 * Assume if you can't find a state that it is "don't care"
428 * this could be a faulty assumption CHECK IT OUT
430 topLevelWindowInfo.termState = 0;
432 (*topList)[i] = topLevelWindowInfo;
436 * Now add in the extra window id's to check
438 tmpList = embeddedList;
439 for(i = *topListLength;i < (*topListLength + numEmbedded);i++)
441 (*topList)[i].wid = *tmpList;tmpList++;
442 (*topList)[i].termState = NormalState;
447 SM_FREE((char *) embeddedList);
452 SM_FREE((char *) childList);
455 *containedListLength = numEmbedded;
462 /*************************************<->*************************************
469 * Timeout procedure the WaitForCommand routine. It stops a loop waiting
470 * for an update of the WM_COMMAND property from a client.
479 * commandTimeout = (global) flag that stops the loop
484 *************************************<->***********************************/
487 XtPointer client_data,
490 String tmpString, tmpError;
494 success = XFetchName(smGD.display, (Window) client_data, &winName);
495 if (success && winName)
497 tmpString = GETMESSAGE(20, 4, "Session restoration information not updated for client %s. Invalid information may be saved.");
498 tmpError = SM_MALLOC(strlen(winName) + strlen(tmpString) + 5);
501 sprintf(tmpError, tmpString, winName);
502 PrintError(DtError, tmpError);
507 commandTimeout = True;
509 } /* END OF FUNCTION WaitTimeout */