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 librararies 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>
63 #include "SmProtocol.h"
64 #include "SmGlobals.h"
68 * Variables global to this module only
70 static Boolean commandTimeout;
73 * Local Function declarations
76 static WindowInfo GetTopLevelWindowInfo(
78 static void WaitForCommand(
80 static void WaitTimeout( XtPointer , XtIntervalId *) ;
85 /*************************************<->*************************************
87 * GetTopLevelWindowInfo (window)
92 * Given a child of the root - find the top level window for that child.
97 * window = the current window that is being queried about
102 * retInfo = a WindowInfo structure (a window id + state of the window) that
103 * gives the top level window information.
108 *************************************<->***********************************/
110 GetTopLevelWindowInfo(
114 Window parent,root,*children;
118 unsigned long nitems;
119 unsigned long leftover;
120 unsigned int nchildren;
121 WM_STATE *wmState = NULL;
122 XWindowAttributes windowAttr;
124 if ((XGetWindowAttributes(smGD.display, window,&windowAttr)) == 0)
127 retInfo.termState = 0;
132 * If WM_STATE could not be interned at the beginning - the window manager
133 * may have been slow in coming up. Try it again now.
135 if(XaWmState == None)
137 XaWmState = XInternAtom(smGD.display, _XA_WM_STATE, True);
140 XGetWindowProperty(smGD.display,window,XaWmState,
141 0L,(long)BUFSIZ,False,
142 XaWmState,&actualType,&actualFormat,
144 &leftover,(unsigned char **) &wmState);
145 if (actualType==XaWmState)
147 retInfo.wid = window;
148 retInfo.termState = wmState->state;
151 * This data needs to be freed up!
153 SM_FREE((char *) wmState);
159 * Be sure to free the window property each time we get it
160 * if the property exists
162 if(actualType != None)
164 SM_FREE((char *) wmState);
167 if(XQueryTree(smGD.display,window,&root,
168 &parent,&children,&nchildren) != 0)
175 retInfo = GetTopLevelWindowInfo(children[i++]);
178 SM_FREE((char *) children);
182 SM_FREE((char *) children);
186 retInfo.termState = 0;
193 /*************************************<->*************************************
195 * WaitForCommand (window)
200 * This routine waits for an update on the WM_COMMAND property of a top
201 * level window after a WM_SAVE_YOURSELF has been placed on that window.
206 * window = window id for the
215 *************************************<->***********************************/
222 XPropertyEvent *pEvent=(XPropertyEvent *)&event;
223 XtIntervalId comTimerId;
224 Boolean commandUpdated;
227 * Set a configurable timer which stops the block
229 commandUpdated = False;
230 commandTimeout = False;
231 comTimerId = XtAppAddTimeOut(smGD.appCon, smRes.saveYourselfTimeout,
232 WaitTimeout, (XtPointer) window);
234 while((commandUpdated == False) && (commandTimeout == False))
236 if((isThere = XtAppPending(smGD.appCon)) != 0)
238 if(isThere & XtIMXEvent)
240 XtAppPeekEvent(smGD.appCon, &event);
241 if (event.type==PropertyNotify&&pEvent->window==window&&
242 pEvent->atom==XA_WM_COMMAND)
244 commandUpdated = True;
247 if(commandTimeout == False)
249 XtAppProcessEvent(smGD.appCon, XtIMXEvent | XtIMTimer);
254 XtRemoveTimeOut(comTimerId);
255 XSelectInput(smGD.display, window,NoEventMask);
262 /*************************************<->*************************************
264 * SaveYourself (windowInfo)
269 * Places the WM_SAVE_YOURSELF property on each top level window. It then
270 * waits for the window to update its WM_COMMAND property.
275 * windowInfo = window id for the top level wincow and the state of that
285 *************************************<->***********************************/
288 WindowInfo windowInfo )
294 XClientMessageEvent saveYourselfMessage;
297 * Get the WM_PROTOCOLS property on the clients top-level window.
299 if(XGetWMProtocols(smGD.display, windowInfo.wid, &protoRet, &nitems) == 0)
302 * If the client doesn't have a WM_PROTOCOLS property,
303 * it doesn't support any protocols.
308 /* Look for WM_SAVE_YOURSELF atom. */
309 for (i=0;i<nitems;++i)
311 if (protoRet[i]==XaWmSaveYourself)
317 SM_FREE((char *) protoRet);
318 return(-1); /* doesn't participate in WM_SAVE_YOURSELF */
321 /* Construct the ClientMessage. */
322 saveYourselfMessage.type=ClientMessage;
323 saveYourselfMessage.window=windowInfo.wid;
324 saveYourselfMessage.message_type=XaWmProtocols;
325 saveYourselfMessage.format=32;
326 saveYourselfMessage.data.l[0]=XaWmSaveYourself;
327 saveYourselfMessage.data.l[1]=CurrentTime;
330 * look for changes in WM_COMMAND property
332 XSelectInput(smGD.display,windowInfo.wid,PropertyChangeMask);
333 XFlush(smGD.display);
336 * Send the ClientMessage to the client. XSendEvent returns a 1 if it
337 * is successful in converting the event to a wire event.
339 if (XSendEvent(smGD.display,windowInfo.wid,False,NoEventMask,
340 (XEvent *) &saveYourselfMessage) != 1)
342 PrintError(DtError, GETMESSAGE(20, 1, "Client message failed. Client information will not be saved."));
346 /* Wait for client to update WM_COMMAND. */
347 WaitForCommand(windowInfo.wid);
349 SM_FREE((char *) protoRet);
356 /*************************************<->*************************************
358 * GetTopLevelWindows (screen, toplist, toplistlength, containedListLength)
363 * Querys the window tree and constructs a list of all top level windows
368 * screen = pointer to the screen we're currently querying on
373 * toplist = a pointer to the list of top level windows
374 * toplistlength = the length of the list of top level windows
375 * containedListLength = the length of the list of contained windows
380 *************************************<->***********************************/
384 WindowInfo **topList,
385 unsigned int *topListLength,
386 unsigned int *containedListLength )
388 Window rootWindow, parentWindow, *tmpChild;
389 Window *childList, *embeddedList, *tmpList;
390 WindowInfo topLevelWindowInfo;
392 unsigned long numEmbedded;
395 * Get a list of children of the root window
397 if (XQueryTree(smGD.display, RootWindow(smGD.display, screen),&rootWindow,
398 &parentWindow, &childList, topListLength) == 0)
400 PrintError(DtError, GETMESSAGE(20, 2, "Invalid root window. Can not save client information."));
405 * add in the list of top level windows embedded in the front panel
407 if(_DtGetEmbeddedClients(smGD.display, RootWindow(smGD.display, screen),
408 &embeddedList, &numEmbedded) != Success)
414 *topList=(WindowInfo *) SM_MALLOC(sizeof(WindowInfo)*
415 (*topListLength + numEmbedded));
417 tmpChild = childList;
419 for (i=0 ; i<*topListLength; ++i, tmpChild++)
421 topLevelWindowInfo = GetTopLevelWindowInfo(*tmpChild);
422 if (!topLevelWindowInfo.wid)
424 topLevelWindowInfo.wid = (*tmpChild);
426 * Assume if you can't find a state that it is "don't care"
427 * this could be a faulty assumption CHECK IT OUT
429 topLevelWindowInfo.termState = 0;
431 (*topList)[i] = topLevelWindowInfo;
435 * Now add in the extra window id's to check
437 tmpList = embeddedList;
438 for(i = *topListLength;i < (*topListLength + numEmbedded);i++)
440 (*topList)[i].wid = *tmpList;tmpList++;
441 (*topList)[i].termState = NormalState;
446 SM_FREE((char *) embeddedList);
451 SM_FREE((char *) childList);
454 *containedListLength = numEmbedded;
461 /*************************************<->*************************************
468 * Timeout procedure the WaitForCommand routine. It stops a loop waiting
469 * for an update of the WM_COMMAND property from a client.
478 * commandTimeout = (global) flag that stops the loop
483 *************************************<->***********************************/
486 XtPointer client_data,
489 String tmpString, tmpError;
493 success = XFetchName(smGD.display, (Window) client_data, &winName);
494 if (success && winName)
496 tmpString = GETMESSAGE(20, 4, "Session restoration information not updated for client %s. Invalid information may be saved.");
497 tmpError = SM_MALLOC(strlen(winName) + strlen(tmpString) + 5);
500 sprintf(tmpError, tmpString, winName);
501 PrintError(DtError, tmpError);
506 commandTimeout = True;
508 } /* END OF FUNCTION WaitTimeout */