Spelling fixes
[oweals/cde.git] / cde / programs / dtwm / WmManage.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /* 
24  * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC. 
25  * ALL RIGHTS RESERVED 
26 */ 
27 /* 
28  * Motif Release 1.2.4
29 */ 
30 #ifdef REV_INFO
31 #ifndef lint
32 static char rcsid[] = "$TOG: WmManage.c /main/11 1998/01/12 16:45:48 cshi $"
33 #endif
34 #endif
35 /*
36  * (c) Copyright 1987, 1988, 1989, 1990, 1992, 1993 HEWLETT-PACKARD COMPANY 
37  */
38
39 /*
40  * Included Files:
41  */
42
43 #include "WmGlobal.h"
44 #include "WmICCC.h"
45 /*
46  * include extern functions
47  */
48 #include "WmCDecor.h"
49 #include "WmCEvent.h"
50 #include "WmColormap.h"
51 #include "WmError.h"
52 #include "WmEvent.h"
53 #include "WmFunction.h"
54 #include "WmGraphics.h"
55 #include "WmIDecor.h"
56 #include "WmIconBox.h"
57 #include "WmImage.h"
58 #include "WmKeyFocus.h"
59 #ifdef PANELIST
60 #include "WmPanelP.h"   /* typedef needed in WmManage.h */
61 #include <Dt/Message.h>
62 #include "WmIPC.h"
63 #endif /* PANELIST */
64 #include "WmManage.h"
65 #include "WmMenu.h"
66 #include "WmProperty.h"
67 #include "WmProtocol.h"
68 #include "WmWinInfo.h"
69 #include "WmWinList.h"
70 #include "WmWinState.h"
71 #ifdef WSM
72 #include "WmPresence.h"
73 #include "WmWrkspace.h"
74 #endif /* WSM */
75 #include "WmXSMP.h"
76
77
78
79 /*
80  * Function Declarations:
81  */
82
83 #ifdef PANELIST
84
85 Boolean IsEmbeddedClient (
86     ClientData *pCD, 
87     WmFpEmbeddedClientData **ppECD);
88 Boolean ManageEmbeddedClient ( 
89     ClientData *pCD, 
90     WmFpEmbeddedClientData *pECD,
91     long manageFlags);
92 Boolean IsPushRecallClient (
93     ClientData *pCD, 
94     WmFpPushRecallClientData **ppPRCD);
95 static void HandleSubstructEvents(
96         Widget w,
97         caddr_t ptr,
98         XEvent *event );
99 Boolean UpdateEmbeddedClientsProperty(
100         WmScreenData *pSD );
101 static void ForceSubpanelWMState(Window win);
102 static void ReManageWindow (ClientData *pCD);
103 static void CheckPushRecallClient (ClientData *pCD);
104
105 #endif /* PANELIST */
106
107
108 /*
109  * Global Variables:
110  */
111
112
113 \f
114 /*************************************<->*************************************
115  *
116  *  AdoptInitialClients (pSD)
117  *
118  *  Inputs:
119  *  -------
120  *  pSD = pointer to screen data
121  *
122  *
123  *  Description:
124  *  -----------
125  *  This function is called to find client windows that were mapped prior to 
126  *  starting (or restarting) the window manager.  These windows are included
127  *  in the set of windows managed by the window manager.
128  *
129  *************************************<->***********************************/
130
131 void AdoptInitialClients (WmScreenData *pSD)
132 {
133     Window  root;
134     Window  parent;
135     Window *clients;
136 #ifdef WSM
137     int nAncillaries, iAnc;
138     Window *pAncillaryWindows, *pWin1;
139     WmWorkspaceData *pWS0;
140 #endif /* WSM */
141     unsigned int     nclients;
142     ClientData *pcd = NULL;
143     PropWMState *wmStateProp;
144     Boolean manageOnRestart;
145     int i,j;
146     long manageFlags;
147
148 #ifdef WSM
149     /* 
150      * Generate list of ancillary windows (not to be managed)
151      */
152     nAncillaries = 2 + pSD->numWorkspaces;
153     pAncillaryWindows = (Window *) XtMalloc (sizeof(Window)*(nAncillaries));
154     if (!pAncillaryWindows)
155     {
156         Warning (((char *)GETMESSAGE(46, 1, "Insufficient memory to adopt initial clients")));
157         ExitWM (WM_ERROR_EXIT_VALUE);
158     }
159     pWS0 = pSD->pWS;
160     pWin1 = pAncillaryWindows;
161     for (iAnc = 0; iAnc < pSD->numWorkspaces; iAnc++)
162     {
163         *pWin1 = XtWindow((pWS0)->workspaceTopLevelW);
164         pWin1++;
165         pWS0++;
166     }
167     *pWin1++ = XtWindow (pSD->screenTopLevelW);
168     *pWin1 = pSD->activeIconTextWin;
169
170 #endif /* WSM */
171
172     /*
173      * Look for mapped top-level windows and start managing them:
174      */
175
176     if (XQueryTree (DISPLAY, pSD->rootWindow, &root, &parent, &clients,
177             &nclients))
178     {
179 #ifndef DONT_FILTER_ICON_WINDOWS
180         /*
181          * Filter out icon windows so they don't get managed as a client
182          * window.  Icon windows will be process in SetupClientIconWindow().
183          */
184         XWMHints *tmphint;
185
186         for (i = 0; i < nclients; i++) {
187             if (clients[i]) {
188                 if ((tmphint = XGetWMHints (DISPLAY, clients[i])) != NULL) {
189                     if (tmphint->flags & IconWindowHint) {
190                         for (j = 0; j < nclients; j++) {
191                             if (clients[j] == tmphint->icon_window) {
192                                 clients[j] = None;
193                                 break;
194                             }
195                         }
196                     }
197                     XFree ((char *) tmphint);
198                 }
199             }
200         }
201 #endif
202
203         for (i = 0; i < nclients; i++)
204         {
205             /* determine if the client window should be managed by wm */
206 #ifdef WSM
207             if (InWindowList (clients[i], pAncillaryWindows, nAncillaries))
208             {
209                 /* don't manage ancillary window manager windows */
210                 continue;
211             }
212 #else /* WSM */
213             if ((clients[i] == XtWindow (pSD->screenTopLevelW)) ||
214                 (clients[i] == XtWindow (pSD->pActiveWS->workspaceTopLevelW)) ||
215                 (clients[i] == pSD->activeIconTextWin))
216             {
217                 /* don't manage ancillary window manager windows */
218                 continue;
219             }
220 #endif /* WSM */
221             if (!XFindContext (DISPLAY, clients[i], wmGD.windowContextType,
222                 (caddr_t *)&pcd)) 
223             {
224                 /* don't manage a window we've already established a 
225                    context for (e.g. icon windows) */
226                 continue;
227             }
228             if (!WmGetWindowAttributes (clients[i]))
229             {
230                 /* can't access the window; ignore it */
231                 continue;
232             }
233             /* window attributes are put into the global cache */
234
235             /*
236              * Get the window WM_STATE property value to determine the
237              * initial window state if the wm is being restarted.
238              */
239
240             manageFlags = MANAGEW_WM_STARTUP;
241             manageOnRestart = True;
242
243             if (wmGD.wmRestarted)
244             {
245                 manageFlags |= MANAGEW_WM_RESTART;
246                 if ((wmStateProp = GetWMState (clients[i])) != NULL)
247                 {
248                     if (wmStateProp->state == IconicState)
249                     {
250                         manageFlags |= MANAGEW_WM_RESTART_ICON;
251                     }
252                     else if (wmStateProp->state != NormalState)
253                     {
254                         manageOnRestart = False;
255                     }
256                     XFree ((char *)wmStateProp);
257                 }
258                 else 
259                 {
260                     manageOnRestart = False;
261                 }
262             }
263
264             /*
265              * Don't manage any override_redirect windows (mapped or not).
266              * Manage an unmapped window if it has a WM_STATE property
267              *   and it is not Withdrawn.
268              * Manage any window that is mapped.
269              */
270
271             if ((wmGD.windowAttributes.override_redirect != True) &&
272                 ((wmGD.wmRestarted && manageOnRestart) ||
273                  (wmGD.windowAttributes.map_state != IsUnmapped)))
274             {
275                 ManageWindow (pSD, clients[i], manageFlags);
276             }
277         }
278
279         if (nclients)
280         {
281             XFree ((char *)clients);
282         }
283     }
284
285 #ifdef WSM
286     if (pAncillaryWindows)
287     {
288         XtFree ((char *) pAncillaryWindows);
289     }
290 #endif /* WSM  */
291
292 } /* END OF FUNCTION AdoptInitialClients */
293
294
295 \f
296 /*************************************<->*************************************
297  *
298  *  ManageWindow (pSD, clientWindow, manageFlags)
299  *
300  *
301  *  Description:
302  *  -----------
303  *  This is the highlevel function that is used to include a window in
304  *  the set of windows that are managed by the window manager.  The window
305  *  gets reparented and decorated, gets an icon, is setup for window
306  *  management event handling, etc.  Client windows that are controlled
307  *  by the window manager (e.g., the icon box) are also managed with
308  *  this function.
309  *
310  *
311  *  Inputs:
312  *  ------
313  *  clientWindow = window of the client that we should manage
314  *
315  *  manageFlags = additional control information 
316  *
317  * 
318  *  Outputs:
319  *  -------
320  *  pCD = initialized client data
321  *
322  *************************************<->***********************************/
323
324 void 
325 ManageWindow (WmScreenData *pSD, Window clientWindow, long manageFlags)
326 {
327     ClientData *pCD;
328     int initialState;
329     int i;
330     Boolean sendConfigNotify;
331 #ifdef WSM
332     WmWorkspaceData *pwsi;
333 #endif /* WSM */
334 #ifdef PANELIST 
335     WmFpEmbeddedClientData *pECD;
336 #endif /* PANELIST */
337
338     /*
339      * Get client information including window attributes and window
340      * property values.  Use this information to determine how the window
341      * is to be managed.
342      */
343
344     if (!(pCD = GetClientInfo (pSD, clientWindow, manageFlags)))
345     {
346         /* error getting client info; do not manage the client window */
347         return;
348     }
349
350
351 #ifdef PANELIST
352     /*
353      *  Handle case of transients that derive from embedded clients.
354      */
355     if (wmGD.dtSD && (wmGD.dtSD == pCD->pSD))
356     {
357         if (pCD->transientLeader && pCD->transientLeader->pECD)
358         {
359             WmPanelistObject  pPanelist;
360             ClientData *pCDfp = NULL;
361
362             pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
363             (void) XFindContext (DISPLAY, XtWindow(O_Shell (pPanelist)),
364                       wmGD.windowContextType, (caddr_t *)&pCDfp);
365
366             pCD->transientLeader = pCDfp;
367         }
368     }
369
370     if (IsEmbeddedClient (pCD, &pECD))
371     {
372         /*
373          * This client is embedded in the front panel 
374          */
375         
376         if (ManageEmbeddedClient(pCD, pECD, manageFlags))
377         {
378             /*
379              *   ...then we've embedded it in the front
380              *   panel--no further processing required.
381              */
382 #ifdef WSM
383             if (smAckState == SM_START_ACK)
384             {
385                 SendClientMsg( wmGD.dtSmWindow, 
386                               (long) wmGD.xa_DT_SM_WM_PROTOCOL,
387                               (long) wmGD.xa_DT_WM_WINDOW_ACK,
388                               CurrentTime, NULL, 0);
389             }
390 #endif /* WSM */
391             return;
392         }
393     }
394     
395     /*
396      *  Handle case of transients that derive from embedded clients.
397      *  !!!!
398      */
399 #if 0
400     if (pCD->transientLeader && pCD->transientLeader->pAccessPanel)
401     {
402         pCD->transientLeader = 
403             pCD->transientLeader->pAccessPanel->pCD_accessPanel;
404     }
405 #endif 
406 #endif /* PANELIST */
407 #ifdef WSM
408     if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
409     {
410         /*
411          * Put system modal windows in all workspaces to
412          * avoid the race condition of the window coming up
413          * just as the user switches workspaces.
414          */
415         pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
416         F_AddToAllWorkspaces(0, pCD, 0);
417         pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
418     }
419 #endif /* WSM */
420     if (manageFlags & MANAGEW_WM_RESTART)
421     {
422         if (manageFlags & MANAGEW_WM_RESTART_ICON)
423         {
424             pCD->clientState = MINIMIZED_STATE;
425         }
426         else
427         {
428             pCD->clientState = NORMAL_STATE;
429         }
430     }
431
432
433     /*
434      * Setup the initial placement of the client window.  Do interactive
435      * placement if configured.
436      */
437
438     sendConfigNotify = InitClientPlacement (pCD, manageFlags);
439
440
441     /*
442      * Make a window frame for the client window and reparent the client
443      * window.
444      */
445
446     if (!FrameWindow (pCD))
447     {
448         /*
449          * Error in framing the window; clean up the wm resources made
450          * up to this point for the client window. Do not manage the
451          * client window.
452          */
453
454         UnManageWindow (pCD);
455         return;
456     }
457
458     /*
459      * Send config notify if the client's been moved/resized
460      */
461     if (sendConfigNotify)
462     {
463         SendConfigureNotify (pCD);
464     }
465
466     /*
467      * Send client offset message if:
468      *
469      *   1. The client is interested.
470      *   2. The position we report to the user is not the client's real
471      *      position.
472      *   3. There is a client offset to report.
473      */
474     if ((pCD->protocolFlags & PROTOCOL_MWM_OFFSET) &&
475         (wmGD.positionIsFrame) && 
476         ((pCD->clientOffset.x != 0) ||
477          (pCD->clientOffset.y != 0)))
478     { 
479         SendClientOffsetMessage (pCD);
480     }
481
482     /*
483      * Make an icon for the client window if it is not a valid transient
484      * window.
485      */
486
487 #ifdef WSM
488     if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
489         (pCD->transientLeader == NULL))
490     {
491         /* 
492          * Make icons frames 
493          * Only make one icon frame for root icons.
494          * Make one per workspace for icon box icons.
495          */
496         for (i = 0; i < pCD->numInhabited; i++)
497         {
498             if ((pwsi = GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID)))
499             {
500
501                 if ((pCD->pSD->useIconBox && 
502                      !(manageFlags & MANAGEW_WM_CLIENTS) &&
503                      !(pCD->clientFlags & FRONT_PANEL_BOX)) || (i == 0))
504                 {
505                     /*
506                      *   Make icon inside an icon box for non-root case
507                      */
508                     if (!MakeIcon (pwsi, pCD)) 
509                     { 
510                         /*
511                          * Error in making an icon for the client window; 
512                          * clean up the wm resources; do not manage the 
513                          * client window.
514                          */
515
516                         UnManageWindow (pCD);
517                         return;
518                     }
519                     else 
520                     {
521                         XSaveContext (DISPLAY, pCD->pWsList[i].iconFrameWin, 
522                                 wmGD.windowContextType, (caddr_t)pCD);
523
524                         if (pCD->iconWindow && pCD->pWsList[i].iconFrameWin)
525                         {
526                             XGrabButton (DISPLAY, AnyButton, AnyModifier, 
527                                 pCD->pWsList[i].iconFrameWin, True,
528                                 ButtonPressMask|ButtonReleaseMask|
529                                     ButtonMotionMask,
530                                 GrabModeAsync, GrabModeAsync, None, 
531                                 wmGD.workspaceCursor);
532                         }
533                     }
534                 }
535                 else 
536                 {
537                     /* 
538                      *  Make root icons for a client
539                      */
540                     if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
541                         (pCD->transientLeader == NULL))
542                     {
543                         if ((i == 0) &&
544                             (!MakeIcon (pwsi, pCD)))
545                         {
546                             /*
547                              * Error in making an icon for the client 
548                              * window; clean up the wm resources; do 
549                              * not manage the client window.
550                              */
551  
552                             UnManageWindow (pCD);
553                             return;
554                         }
555                         else
556                         {
557                             /* copy root icon frame reference to other 
558                              * workspaces
559                              */
560                             pCD->pWsList[i].iconFrameWin = 
561                                     pCD->pWsList[0].iconFrameWin;
562                         }
563                     }
564                 }
565             }
566         }
567     }
568 #else /* WSM */
569     if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
570         (pCD->transientLeader == NULL) && 
571           !MakeIcon (pCD->pSD->pActiveWS, pCD))
572     {
573         /*
574          * Error in making an icon for the client window; clean up the wm
575          * resources; do not manage the client window.
576          */
577
578         UnManageWindow (pCD);
579         return;
580     }
581 #endif /* WSM */
582
583
584     /*
585      * Register window contexts to facilitate event handling:
586      */
587
588     XSaveContext (DISPLAY, pCD->clientFrameWin, wmGD.windowContextType,
589         (caddr_t)pCD);
590
591     XSaveContext (DISPLAY, pCD->clientBaseWin, wmGD.windowContextType,
592         (caddr_t)pCD);
593
594     if (DECOUPLE_TITLE_APPEARANCE(pCD) && pCD->clientTitleWin)
595     {
596         /* 
597          * handle exposures on title bar if it has its own appearance
598          */
599         XSaveContext (DISPLAY, pCD->clientTitleWin, wmGD.windowContextType,
600             (caddr_t)pCD);
601     }
602 #ifndef WSM
603     if (pCD->iconFrameWin)
604     {
605         XSaveContext (DISPLAY, pCD->iconFrameWin, wmGD.windowContextType,
606             (caddr_t)pCD);
607     }
608 #endif /* WSM */
609
610     if (pCD->clientCmapCount > 0)
611     {
612         for (i = 0; i < pCD->clientCmapCount; i++)
613         {
614             if (pCD->cmapWindows[i] != pCD->client)
615             {
616 #ifndef IBM_169380
617                 AddColormapWindowReference(pCD, pCD->cmapWindows[i]);
618 #else
619                 XSaveContext (DISPLAY, pCD->cmapWindows[i],
620                     wmGD.windowContextType, (caddr_t)pCD);
621 #endif
622             }
623         }
624     }
625
626     pCD->clientFlags |= CLIENT_CONTEXT_SAVED;
627
628
629     /*
630      * Setup button binding handling for actions that apply to the client
631      * window.
632      */
633
634     if (BUTTON_SPECS(pCD))
635     {
636         SetupCButtonBindings (pCD->clientBaseWin, BUTTON_SPECS(pCD));
637     }
638
639 #ifndef WSM
640     if (pCD->iconWindow && pCD->iconFrameWin)
641     {
642         XGrabButton (DISPLAY, AnyButton, AnyModifier, pCD->iconFrameWin, True,
643             ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
644             GrabModeAsync, GrabModeAsync, None, wmGD.workspaceCursor);
645     }
646 #endif /* WSM */
647
648     /*
649      * Setup key binding handling for system menu accelerators.
650      */
651
652     if (pCD->systemMenuSpec &&
653         (pCD->systemMenuSpec->accelKeySpecs))
654     {
655         SetupKeyBindings (pCD->systemMenuSpec->accelKeySpecs,
656                           pCD->clientFrameWin, GrabModeSync, F_CONTEXT_ALL);
657 #ifdef WSM
658         for (i = 0; i < pCD->numInhabited; i++)
659         {
660             if (!pCD->pWsList[i].pIconBox && pCD->pWsList[i].iconFrameWin)
661             {
662                 SetupKeyBindings (pCD->systemMenuSpec->accelKeySpecs,
663                               pCD->pWsList[i].iconFrameWin, GrabModeSync, 
664                               F_CONTEXT_ALL);
665             }
666         }
667 #else /* WSM */
668         if (!pCD->pIconBox && pCD->iconFrameWin)
669         {
670             SetupKeyBindings (pCD->systemMenuSpec->accelKeySpecs,
671                               pCD->iconFrameWin, GrabModeSync, F_CONTEXT_ALL);
672         }
673 #endif /* WSM */
674     }
675
676 #ifdef WSM
677   for (i = 0; i < pCD->numInhabited; i++)
678   {
679     if (!pCD->pWsList[i].pIconBox && pCD->pWsList[i].iconFrameWin)
680 #else /* WSM */
681     if (!pCD->pIconBox && pCD->iconFrameWin)
682 #endif /* WSM */
683     {
684         static int iconKeySpec = 1;
685         static int iconAccelSpec = 1;
686
687         if ((iconKeySpec != 0) && KEY_SPECS(pCD))
688         {
689 #ifdef WSM
690             iconKeySpec = SetupKeyBindings (KEY_SPECS(pCD), 
691                                 pCD->pWsList[i].iconFrameWin,
692                                 GrabModeSync, F_CONTEXT_ICON);
693 #else /* WSM */
694             iconKeySpec = SetupKeyBindings (KEY_SPECS(pCD), pCD->iconFrameWin,
695                                 GrabModeSync, F_CONTEXT_ICON);
696 #endif /* WSM */
697         }
698
699         if ((iconAccelSpec != 0) && ACCELERATOR_MENU_COUNT(pCD))
700         {
701             int n;
702
703             iconAccelSpec = 0;
704             for (n= 0; n < pSD->acceleratorMenuCount; n++)
705             {
706 #ifdef WSM
707                 iconAccelSpec += SetupKeyBindings (
708                             ACCELERATOR_MENU_SPECS(pCD)[n]->accelKeySpecs,
709                             pCD->pWsList[i].iconFrameWin, GrabModeSync,
710                             F_CONTEXT_ICON);
711 #else /* WSM */
712                 iconAccelSpec += SetupKeyBindings (
713                             ACCELERATOR_MENU_SPECS(pCD)[n]->accelKeySpecs,
714                             pCD->iconFrameWin, GrabModeSync,
715                             F_CONTEXT_ICON);
716 #endif /* WSM */
717             }
718         }
719     }
720 #ifdef WSM
721   }
722 #endif /* WSM */
723
724
725     /*
726      * Setup keyboard focus handling if policy is "explicit".
727      */
728
729     if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
730     {
731         DoExplicitSelectGrab (pCD->clientBaseWin);
732     }
733
734 #ifdef WSM
735     UpdateWorkspacePresenceProperty(pCD);
736 #endif /* WSM */
737
738
739     /*
740      * Make sure the client window has been reparented ...
741      */
742
743     if (!(manageFlags & MANAGEW_WM_CLIENTS))
744     {
745         XSync (DISPLAY, False);
746
747         if (pCD->clientFlags & CLIENT_DESTROYED)
748         {
749             UnManageWindow (pCD);
750             return;
751         }
752     }
753
754     /*
755      * Setup the initial display state for the client window:
756      */
757
758     initialState = pCD->clientState;
759 #ifdef WSM
760     if (!ClientInWorkspace (pSD->pActiveWS, pCD))
761     {
762         initialState |= UNSEEN_STATE;
763     }
764 #endif /* WSM */
765     pCD->clientState = WITHDRAWN_STATE;
766     pCD->clientFlags &= ~WM_INITIALIZATION;
767
768 #ifdef WSM
769     /* 
770      * Add to stacking list using the client's zero'th workspace
771      * instead of the current one because it may not be in 
772      * the current one.
773      */
774     AddClientToList (GetWorkspaceData (pSD, pCD->pWsList[0].wsID),
775         pCD, True /*on top*/);
776 #else /* WSM */
777     AddClientToList (pSD->pActiveWS, pCD, True /*on top*/);
778 #endif /* WSM */
779     SetClientState (pCD, initialState, GetTimestamp());
780
781     /*
782      * Set the keyboard input focus to the newly managed window if appropriate:
783      * - focus is automatically set only if the focus policy is explicit
784      * - if there is a system modal window active then set the focus only
785      *   if the new window is in the system modal hierarchy
786      * - focus is automatically set if startupKeyFocus is selected or
787      *   the new window is a system modal window or the current focus window
788      *   has the new window as an application modal subordinate
789      * - don't automatically set the focus if the window is minimized or
790      *   is a window that generally doesn't take input
791      */
792
793     if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
794         ((pCD->inputMode == MWM_INPUT_SYSTEM_MODAL) ||
795          ((!wmGD.systemModalActive ||
796            (wmGD.systemModalClient == FindTransientTreeLeader (pCD))) &&
797           (wmGD.startupKeyFocus ||
798            (wmGD.keyboardFocus && (IS_APP_MODALIZED(wmGD.keyboardFocus)))) &&
799           !(manageFlags &
800             (MANAGEW_WM_STARTUP | MANAGEW_WM_RESTART | MANAGEW_WM_CLIENTS)) &&
801           (pCD->clientState != MINIMIZED_STATE) &&
802 #ifdef WSM
803           !(pCD->clientState & UNSEEN_STATE) &&
804 #endif /* WSM */
805           (pCD->inputFocusModel ||
806            (pCD->protocolFlags & PROTOCOL_WM_TAKE_FOCUS)))))
807     {
808         Do_Focus_Key (pCD, GetTimestamp() , ALWAYS_SET_FOCUS);
809     }
810     else if ((pCD->inputMode == MWM_INPUT_SYSTEM_MODAL) ||
811              (wmGD.keyboardFocus && IS_APP_MODALIZED(wmGD.keyboardFocus)))
812     {
813         Do_Focus_Key ((ClientData *)NULL, GetTimestamp() , ALWAYS_SET_FOCUS);
814     }
815
816 #ifdef WSM
817     if (smAckState == SM_START_ACK)
818     {
819         SendClientMsg( wmGD.dtSmWindow, (long) wmGD.xa_DT_SM_WM_PROTOCOL,
820                       (long) wmGD.xa_DT_WM_WINDOW_ACK,
821                       CurrentTime, NULL, 0);
822     }
823
824     /*
825      * Free the initial property list. This will force
826      * reads of properties that change after the initial
827      * management (see HasProperty() function.)
828      */
829     DiscardInitialPropertyList (pCD);
830
831 #endif /* WSM */
832 #ifdef PANELIST
833     CheckPushRecallClient (pCD);
834 #endif /* PANELIST */
835
836 } /* END OF FUNCTION ManageWindow */
837
838
839 \f
840 /*************************************<->*************************************
841  *
842  *  UnManageWindow (pCD)
843  *
844  *
845  *  Description:
846  *  -----------
847  *  This function removes a top-level client window and it's transients
848  *  from the set of windows that is managed by the window manager.  
849  *
850  *
851  *  Inputs:
852  *  ------
853  *  pCD         - pointer to client data of window to unmanage
854  *
855  *************************************<->***********************************/
856
857 void UnManageWindow (ClientData *pCD)
858 {
859 #ifdef PANELIST
860     if (pCD->pECD)
861     {
862         WmFpEmbeddedClientData *pECD;
863
864         pECD = (WmFpEmbeddedClientData *) pCD->pECD;
865
866         XtRemoveEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
867                 (SubstructureRedirectMask | SubstructureNotifyMask),
868                 False,
869                 (XtEventHandler)HandleSubstructEvents,
870                 (XtPointer)(pCD));
871
872         pECD->pCD = NULL;
873         UpdateEmbeddedClientsProperty (pCD->pSD);
874     }
875
876     if (pCD->pPRCD)
877     {
878         WmFpPushRecallClientData *pPRCD;
879         int j;
880
881         pPRCD = (WmFpPushRecallClientData *) pCD->pSD->pPRCD;
882
883         for (j = 0; 
884                  j < pCD->pSD->numPushRecallClients; 
885                          j++, pPRCD++)
886         {
887             /*
888              * Clean out all slots used by this client.
889              */
890             if ((!strcmp ((char *)pCD->clientName, 
891                          (char *)(pPRCD->pchResName))) &&
892                 (pPRCD->pCD == pCD))
893             {
894                 pPRCD->pCD = NULL;
895             }
896         }
897         pCD->pPRCD = NULL;
898     }
899 #endif /* PANELIST */
900     /*
901      * Withdraw all the transient children of this window.
902      */
903
904     if (pCD->transientChildren != NULL) 
905     {
906         WithdrawTransientChildren (pCD);
907     }
908
909
910     /*
911      * If this is a transient window, then delete it from the leader's
912      * list of transients.
913      */
914
915     if (pCD->transientLeader)
916     {
917         DeleteTransient (pCD);
918
919         /* If this was a modal dialog box, then replay the event. */
920         if ( wmGD.replayEnterEvent )
921           {
922             XPutBackEvent( DISPLAY, (XEvent*)&wmGD.savedEnterEvent );
923             /* Reset event flag to false */
924             wmGD.replayEnterEvent = False;
925           }
926     }
927
928
929     /*
930      * Withdraw this window
931      */
932
933     WithdrawWindow (pCD);
934
935 } /* END OF FUNCTION UnManageWindow */
936
937
938 \f
939 /*************************************<->*************************************
940  *
941  *  WithdrawTransientChildren (pCD)
942  *
943  *
944  *  Description:
945  *  -----------
946  *  This function withdraws all transient children of the specified window.
947  *
948  *
949  *  Inputs:
950  *  ------
951  *  pCD = pointer to client data of the leader of the transient tree.
952  * 
953  *************************************<->***********************************/
954
955 void WithdrawTransientChildren (ClientData *pCD)
956 {
957     ClientData *pcdNext;
958     ClientData *pcdThis;
959
960
961     pcdNext = pCD->transientChildren;
962     while (pcdNext)
963     {
964         if (pcdNext->transientChildren)
965         {
966             WithdrawTransientChildren (pcdNext);
967         }
968         pcdThis = pcdNext;
969         pcdNext = pcdThis->transientSiblings;
970         DeleteTransient(pcdThis);
971         WithdrawWindow (pcdThis);
972     }
973
974 } /* END OF FUNCTION WithdrawTransientChildren */
975
976
977 \f
978 /*************************************<->*************************************
979  *
980  *  WithdrawWindow (pCD)
981  *
982  *
983  *  Description:
984  *  -----------
985  *  This function removes a top-level client window from the set of windows
986  *  that is managed by the window manager.  All window manager resources
987  *  associtated with the client window are freed up (possibly cached for
988  *  reuse).  Any custom system menu is destroyed.
989  *
990  *
991  *  Inputs:
992  *  ------
993  *  pCD         - pointer to client data of window to withdraw
994  * 
995  *************************************<->***********************************/
996
997 void WithdrawWindow (ClientData *pCD)
998 {
999     int x;
1000     int y;
1001     int i;
1002     XWindowChanges xwc;
1003
1004
1005     /*
1006      * Put the client window into a withdrawn state:
1007      *
1008      * - remove the icon/client window from the screen
1009      * - make sure the input focus no longer is associted with the window
1010      * - free the icon placement (if necessary)
1011      */
1012 #ifdef WSM
1013     SetClientWsIndex (pCD);
1014 #endif /* WSM */
1015
1016     if (!(pCD->clientFlags & WM_INITIALIZATION))
1017     {
1018         if (!pCD->transientLeader)
1019         {
1020             DeleteClientFromList (pCD->pSD->pActiveWS, pCD);
1021         }
1022         ResetWithdrawnFocii (pCD);
1023         if (pCD->clientState & MINIMIZED_STATE)
1024         {
1025 #ifdef WSM
1026             if (wmGD.iconAutoPlace && (!(P_ICON_BOX(pCD))))
1027             {
1028                 WmWorkspaceData *pWsTmp;
1029                 WsClientData *pWsc;
1030                 int j;
1031
1032                 /* 
1033                  * Clean up icon placement data in all inhabited
1034                  * workspaces
1035                  */
1036                 for (j = 0; j< pCD->numInhabited; j++)
1037                 {
1038                     pWsc = &(pCD->pWsList[j]);
1039
1040                     if (pWsc->iconPlace != NO_ICON_PLACE)
1041                     {
1042                         if ((pWsTmp=GetWorkspaceData(pCD->pSD, pWsc->wsID)))
1043                         {
1044                           pWsTmp->IPData.placeList[pWsc->iconPlace].pCD 
1045                               = NULL;
1046                         }
1047                     }
1048                 }
1049             }
1050 #else /* WSM */
1051             if (wmGD.iconAutoPlace && (!(P_ICON_BOX(pCD))))
1052             {
1053                 if (ICON_PLACE(pCD) != NO_ICON_PLACE)
1054                 {
1055                 pCD->pSD->pActiveWS->IPData.placeList[ICON_PLACE(pCD)].pCD 
1056                     = NULL;
1057                 }
1058             }
1059 #endif /* WSM */
1060             if (ICON_FRAME_WIN(pCD))
1061             {
1062                 XUnmapWindow (DISPLAY, ICON_FRAME_WIN(pCD));
1063             }
1064             XFlush (DISPLAY);
1065         }
1066         else if ((pCD->clientState == NORMAL_STATE) ||
1067                  (pCD->clientState == MAXIMIZED_STATE))
1068         {
1069             XUnmapWindow (DISPLAY, pCD->clientFrameWin);
1070             XFlush (DISPLAY);
1071         }
1072     }
1073 #ifdef WSM
1074     /* 
1075      * Clean up the workspace presence dialog if it's
1076      * connected to this client.
1077      */
1078     if ((pCD->pSD->presence.shellW) &&
1079         (pCD->pSD->presence.pCDforClient == pCD))
1080     {
1081         if (pCD->pSD->presence.onScreen)
1082         {
1083             HidePresenceBox (pCD->pSD, True);
1084         }
1085         pCD->pSD->presence.pCDforClient = NULL;
1086     }
1087 #endif /* WSM */
1088
1089     /*
1090      * Check to see if the window is being unmanaged because the window
1091      * was destroyed.
1092      */
1093
1094     if (!(pCD->clientFlags & CLIENT_DESTROYED))
1095     {
1096         XEvent eventReturn;
1097
1098         if (XCheckTypedWindowEvent (DISPLAY, pCD->clientBaseWin, DestroyNotify,
1099                 &eventReturn))
1100         {
1101             pCD->clientFlags |= CLIENT_DESTROYED;
1102         }
1103     }
1104
1105
1106     /*
1107      * Reparent the client window back to root if the window has been
1108      * reparented by the window manager.  Remove the window from the
1109      * window managers save-set if necessary.
1110      */
1111
1112     if ((pCD->clientFlags & CLIENT_REPARENTED) &&
1113         !(pCD->clientFlags & CLIENT_DESTROYED))
1114     {
1115 #ifdef WSM
1116         SetWMState (pCD->client, WithdrawnSTATE, 
1117                 pCD->pWsList[0].iconFrameWin);
1118 #else /* WSM */
1119         SetWMState (pCD->client, WithdrawnSTATE, ICON_FRAME_WIN(pCD));
1120 #endif /* WSM */
1121
1122         if (pCD->maxConfig)
1123         {
1124             x = pCD->maxX;
1125             y = pCD->maxY;
1126         }
1127         else
1128         {
1129             int xoff, yoff;
1130             
1131             if(wmGD.positionIsFrame)
1132             {
1133               CalculateGravityOffset (pCD, &xoff, &yoff);
1134               x = pCD->clientX - xoff;
1135               y = pCD->clientY - yoff;
1136             }
1137             else
1138               {
1139             x = pCD->clientX;
1140             y = pCD->clientY;
1141             }
1142         }
1143
1144         XUnmapWindow (DISPLAY, pCD->client);
1145         XReparentWindow (DISPLAY, pCD->client, ROOT_FOR_CLIENT(pCD), x, y);
1146
1147         /* give the window back it's X border */
1148         xwc.border_width = pCD->xBorderWidth;
1149         XConfigureWindow(DISPLAY, pCD->client, CWBorderWidth, &xwc);
1150
1151         if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
1152         {
1153             XUnmapWindow (DISPLAY, pCD->iconWindow);
1154 #ifdef WSM
1155             XReparentWindow (DISPLAY, pCD->iconWindow, ROOT_FOR_CLIENT(pCD), 
1156                              pCD->pWsList[0].iconX, pCD->pWsList[0].iconY);
1157 #else /* WSM */
1158             XReparentWindow (DISPLAY, pCD->iconWindow, ROOT_FOR_CLIENT(pCD), 
1159                              ICON_X(pCD), ICON_Y(pCD));
1160 #endif /* WSM */
1161         }
1162     }
1163
1164
1165     if ((pCD->clientFlags & CLIENT_IN_SAVE_SET) &&
1166         !(pCD->clientFlags & CLIENT_DESTROYED))
1167     {
1168         XRemoveFromSaveSet (DISPLAY, pCD->client);
1169
1170         if (pCD->iconWindow && (pCD->clientFlags & ICON_IN_SAVE_SET))
1171         {
1172             XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
1173         }
1174     }
1175
1176     /*
1177      * Free a custom system menu if one was created.
1178      */
1179
1180     FreeCustomMenuSpec (pCD->systemMenuSpec);
1181
1182     /*
1183      * Free the client window frame:
1184      */
1185
1186     if (pCD->clientFrameWin)
1187     {
1188         FreeClientFrame (pCD);
1189     }
1190
1191
1192     /*
1193      * Free the icon associated with the client window:
1194      */
1195
1196     if ((pCD->iconFlags & ICON_HINTS_PIXMAP) && pCD->iconPixmap)
1197     {
1198         XFreePixmap (DISPLAY, pCD->iconPixmap);
1199     }
1200
1201 #ifdef WSM
1202     if ((pCD->numInhabited > 0) && ICON_FRAME_WIN(pCD))
1203 #else /* WSM */
1204     if (ICON_FRAME_WIN(pCD))
1205 #endif /* WSM */
1206     {
1207         FreeIcon (pCD);
1208     }
1209
1210
1211     /*
1212      * Free up the client protocol list:
1213      */
1214
1215     if (pCD->clientProtocols)
1216     {
1217         XtFree ((char *)pCD->clientProtocols);
1218     }
1219
1220
1221     /*
1222      * Free up the mwm messages list:
1223      */
1224
1225     if (pCD->mwmMessages)
1226     {
1227         XtFree ((char *)pCD->mwmMessages);
1228     }
1229
1230
1231     /*
1232      * Delete client window manager timers:
1233      */
1234
1235     DeleteClientWmTimers (pCD);
1236
1237
1238     /*
1239      * Free up window context associations.  
1240      */
1241     DeleteClientContext (pCD);
1242
1243
1244 #ifdef WSM
1245     /* 
1246      * Count backward for efficiency  --  
1247      *     removes from end of list.
1248      */
1249     for (i = pCD->numInhabited - 1; i >= 0; i--)
1250     {
1251         TakeClientOutOfWorkspace (
1252             GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID),
1253             pCD);
1254     }
1255 #endif /* WSM */
1256
1257     /*
1258      * Free up window manager resources:
1259      */
1260
1261     if (!(pCD->clientFlags & CLIENT_WM_CLIENTS))
1262     {
1263         if (pCD->clientName)
1264         {
1265             XFree ((char *) (pCD->clientName));
1266         }
1267         if (pCD->clientClass)
1268         {
1269             XFree ((char *) (pCD->clientClass));
1270         }
1271     }
1272
1273     if ((pCD->clientFlags & CLIENT_HINTS_TITLE) && pCD->clientTitle)
1274     {
1275         XmStringFree (pCD->clientTitle);
1276     }
1277
1278     if ((pCD->iconFlags & ICON_HINTS_TITLE) && pCD->iconTitle)
1279     {
1280         XmStringFree (pCD->iconTitle);
1281     }
1282
1283     if (pCD->clientCmapCount > 0)
1284     {
1285         for (i = 0; i < pCD->clientCmapCount; i++)
1286         {
1287             if (pCD->cmapWindows[i] != pCD->client)
1288             {
1289 #ifndef IBM_169380
1290                 RemoveColormapWindowReference(pCD, pCD->cmapWindows[i]);
1291 #else
1292                 XDeleteContext (DISPLAY, pCD->cmapWindows[i],
1293                     wmGD.windowContextType);
1294 #endif
1295             }
1296         }
1297         XtFree ((char *) (pCD->cmapWindows));
1298         XtFree ((char *) (pCD->clientCmapList));
1299 #ifndef OLD_COLORMAP /* colormap */
1300         XtFree ((char  *) (pCD->clientCmapFlags));
1301 #endif
1302     }
1303
1304 #ifdef WSM
1305     /*
1306      * Insure list of initial properties has been freed.
1307      */
1308     DiscardInitialPropertyList (pCD);
1309
1310     /* 
1311      * free up list of workspace specific data
1312      */
1313     if ((pCD)->pWsList)
1314     {
1315         XtFree ((char *) (pCD->pWsList));
1316     }
1317
1318     /*
1319      * free up workspace hints
1320      */
1321     if (pCD->pWorkspaceHints)
1322     {
1323         XtFree ((char *)pCD->pWorkspaceHints);
1324     }
1325 #endif /* WSM */
1326
1327     if (pCD->smClientID)
1328         XFree (pCD->smClientID);
1329
1330     /*
1331      * Clean up references to this data before we free it.
1332      */
1333     if (wmGD.menuClient == pCD) {
1334         wmGD.menuClient = NULL;
1335     }
1336
1337     if (wmGD.gadgetClient == pCD) {
1338         wmGD.gadgetClient = NULL;
1339         wmGD.gadgetDepressed = 0;
1340     }
1341
1342     if (wmGD.clickData.pCD == pCD) {
1343         wmGD.clickData.pCD = NULL;
1344     }
1345
1346     if (wmGD.nextKeyboardFocus == pCD)
1347         wmGD.nextKeyboardFocus = NULL;
1348     if (wmGD.keyboardFocus == pCD)
1349         wmGD.keyboardFocus = NULL;
1350
1351 /*
1352  * Fix for 5325 - Delete reference by dirty stack 
1353  */
1354     ClearDirtyStackEntry(pCD);
1355
1356     XtFree ((char *)pCD);
1357
1358
1359 } /* END OF FUNCTION WithdrawWindow */
1360
1361
1362 \f
1363 /*************************************<->*************************************
1364  *
1365  *  DeleteClientContext (pCD)
1366  *
1367  *
1368  *  Description:
1369  *  -----------
1370  *  This function deletes the client from the X context manager
1371  *  
1372  *
1373  *  Inputs:
1374  *  ------
1375  *  pCD         - pointer to client data 
1376  * 
1377  *  Outputs:
1378  *  -------
1379  *
1380  *  Comments:
1381  *  --------
1382  * 
1383  *************************************<->***********************************/
1384
1385 void DeleteClientContext (ClientData *pCD)
1386 {
1387     /*
1388      * Free up window context associations.  The context for the client
1389      * window is always set if there is a client data structure.
1390      */
1391
1392     XDeleteContext (DISPLAY, pCD->client, wmGD.windowContextType);
1393     if (pCD->clientFlags & CLIENT_CONTEXT_SAVED)
1394     {
1395         XDeleteContext (DISPLAY, pCD->clientFrameWin, wmGD.windowContextType);
1396         XDeleteContext (DISPLAY, pCD->clientBaseWin, wmGD.windowContextType);
1397         if (DECOUPLE_TITLE_APPEARANCE(pCD))
1398         {
1399             XDeleteContext (DISPLAY, pCD->clientTitleWin,
1400                 wmGD.windowContextType);
1401         }
1402         if (ICON_FRAME_WIN(pCD)) 
1403         {
1404 #ifdef WSM
1405             int k;
1406
1407             for (k=0; k < pCD->numInhabited; k++)
1408             {
1409                 XDeleteContext (DISPLAY, pCD->pWsList[k].iconFrameWin, 
1410                                  wmGD.windowContextType);
1411             }
1412 #else /* WSM */
1413             XDeleteContext (DISPLAY, pCD->iconFrameWin, 
1414                              wmGD.windowContextType);
1415 #endif /* WSM */
1416         }
1417         pCD->clientFlags &= ~CLIENT_CONTEXT_SAVED;
1418     }
1419
1420 } /* END OF FUNCTION DeleteClientContext */
1421
1422
1423 \f
1424 /*************************************<->*************************************
1425  *
1426  *  ResetWitdrawnFocii (pCD)
1427  *
1428  *
1429  *  Description:
1430  *  -----------
1431  *  This function resets the various types of focus if they are set to a
1432  *  window being withdrawn.
1433  *  
1434  *
1435  *
1436  *  Inputs:
1437  *  ------
1438  *  pCD         - pointer to client data 
1439  * 
1440  *  Outputs:
1441  *  -------
1442  *
1443  *  Comments:
1444  *  --------
1445  * 
1446  *************************************<->***********************************/
1447
1448 void ResetWithdrawnFocii (ClientData *pCD)
1449 {
1450     if ((wmGD.keyboardFocus == pCD) ||
1451         /* BEGIN fix for CDExc21090 */
1452         ((wmGD.keyboardFocus == (ClientData *)NULL) &&
1453          (wmGD.nextKeyboardFocus == pCD) &&
1454          (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)))
1455         /* END fix for CDExc21090 */
1456     {
1457         if (wmGD.autoKeyFocus &&
1458             (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1459         {
1460             /* local hack: if we've already received a map for a new
1461             ** focus window, be sure to use wmGD.nextKeyboardFocus; otherwise 
1462             ** AutoResetKeyFocus chooses an essentially arbitrary window to 
1463             ** set focus to. 
1464             */
1465             if (wmGD.nextKeyboardFocus == pCD)
1466                     AutoResetKeyFocus (pCD, GetTimestamp());
1467             else
1468                 Do_Focus_Key ((ClientData *)wmGD.nextKeyboardFocus, 
1469                                 GetTimestamp(), ALWAYS_SET_FOCUS);
1470         }
1471         else
1472         {
1473             /*
1474              * Set the focus to the default state if the focus is not in
1475              * the process of being set (i.e. a FocusIn event will be 
1476              * coming along shortly.
1477              */
1478
1479             if (wmGD.nextKeyboardFocus == wmGD.keyboardFocus)
1480             {
1481                 Do_Focus_Key ((ClientData *)NULL, GetTimestamp(),
1482                     ALWAYS_SET_FOCUS | WORKSPACE_IF_NULL);
1483             }
1484         }
1485         SetKeyboardFocus ((ClientData *)NULL, 0);
1486     }
1487
1488     if (((pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL) ||
1489          (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)) &&
1490         (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER))
1491     {
1492         /*
1493          * Repair the focus if an application modal dialog went 
1494          * away. We may not see an enter event and have the focus
1495          * set to the wrong place.
1496          */
1497         RepairFocus ();
1498     }
1499
1500     if (wmGD.nextKeyboardFocus == pCD)
1501     {
1502         wmGD.nextKeyboardFocus = NULL;
1503     }
1504
1505     if (ACTIVE_PSD->colormapFocus == pCD)
1506     {
1507         SetColormapFocus (ACTIVE_PSD, (ClientData *)NULL);
1508     }
1509
1510 } /* END OF FUNCTION ResetWithdrawnFocii */
1511
1512
1513 \f
1514 /*************************************<->*************************************
1515  *
1516  *  FreeClientFrame (pCD)
1517  *
1518  *
1519  *  Description:
1520  *  -----------
1521  *  This function frees up frame windows and associated resources.
1522  *
1523  *
1524  *  Inputs:
1525  *  ------
1526  *  pCD         - pointer to client data
1527  *
1528  *************************************<->***********************************/
1529
1530 void FreeClientFrame (ClientData *pCD)
1531 {
1532     if (pCD->pclientTopShadows) {
1533         FreeRList (pCD->pclientTopShadows);
1534         pCD->pclientTopShadows = NULL;
1535     }
1536     if (pCD->pclientBottomShadows) {
1537         FreeRList (pCD->pclientBottomShadows);
1538         pCD->pclientBottomShadows = NULL;
1539     }
1540     if (pCD->pclientTitleTopShadows) {
1541         FreeRList (pCD->pclientTitleTopShadows);
1542         pCD->pclientTitleTopShadows = NULL;
1543     }
1544     if (pCD->pclientTitleBottomShadows) {
1545         FreeRList (pCD->pclientTitleBottomShadows);
1546         pCD->pclientTitleBottomShadows = NULL;
1547     }
1548     if (pCD->pclientMatteTopShadows) {
1549         FreeRList (pCD->pclientMatteTopShadows);
1550         pCD->pclientMatteTopShadows = NULL;
1551     }
1552     if (pCD->pclientMatteBottomShadows) {
1553         FreeRList (pCD->pclientMatteBottomShadows);
1554         pCD->pclientMatteBottomShadows = NULL;
1555     }
1556     if (pCD->pTitleGadgets) {
1557         XtFree ((char *)pCD->pTitleGadgets);
1558         pCD->pTitleGadgets = NULL;
1559         pCD->cTitleGadgets = 0;
1560     }
1561     if (pCD->pResizeGadgets) {
1562         XtFree ((char *)pCD->pResizeGadgets);
1563         pCD->pResizeGadgets = NULL;
1564     }
1565
1566     /* destroy frame window & all children */
1567     XDestroyWindow (DISPLAY, pCD->clientFrameWin);
1568
1569 } /* END OF FUNCTION FreeClientFrame */
1570
1571
1572 \f
1573 /*************************************<->*************************************
1574  *
1575  *  FreeIcon (pCD)
1576  *
1577  *
1578  *  Description:
1579  *  -----------
1580  *  This function frees up icon windows and associated resources.
1581  *
1582  *
1583  *  Inputs:
1584  *  ------
1585  *  pCD         - pointer to client data
1586  * 
1587  *************************************<->***********************************/
1588
1589 void FreeIcon (ClientData *pCD)
1590 {
1591 #ifdef WSM
1592     WmWorkspaceData *pWsTmp;
1593     int i;
1594 #endif /* WSM */
1595
1596     if (pCD->piconTopShadows) {
1597         FreeRList (pCD->piconTopShadows);
1598         pCD->piconTopShadows = NULL;
1599     }
1600     if (pCD->piconBottomShadows) {
1601         FreeRList (pCD->piconBottomShadows);
1602         pCD->piconBottomShadows = NULL;
1603     }
1604
1605     /* 
1606      * destroy frame window & all children 
1607      */
1608
1609 #ifdef WSM
1610     if ((pCD->pSD->useIconBox) && pCD->pWsList[0].pIconBox)
1611     {
1612         /* 
1613          * We're using icon boxes and it's in at least one ...
1614          * Delete from all workspaces we live in
1615          */
1616         for (i = 0; i< pCD->numInhabited; i++)
1617         {
1618             if ((pWsTmp = GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID)))
1619             {
1620                 DeleteIconFromBox (pWsTmp->pIconBox, pCD);
1621             }
1622         }
1623     }
1624     else
1625     {
1626         /* only one window, so destroying its first reference will
1627          * clean it up adequately
1628          */
1629         if (pCD->pWsList[0].iconFrameWin)
1630         {
1631             XDestroyWindow (DISPLAY, pCD->pWsList[0].iconFrameWin);
1632         }
1633     }
1634 #else /* WSM */
1635     if (pCD->pSD->useIconBox && P_ICON_BOX(pCD))
1636     {
1637         DeleteIconFromBox (pCD->pSD->pActiveWS->pIconBox, pCD);
1638     }
1639     else
1640     {
1641         XDestroyWindow (DISPLAY, pCD->iconFrameWin);
1642     }
1643 #endif /* WSM */
1644
1645 } /* END OF FUNCTION FreeIcon */
1646
1647
1648
1649 \f
1650 /*************************************<->*************************************
1651  *
1652  *  WithdrawDialog (dialogboxW)
1653  *
1654  *
1655  *  Description:
1656  *  -----------
1657  *  This function removes a DialogBox widget "client" from the set of windows 
1658  *  that are managed by the window manager.
1659  *
1660  *
1661  *  Inputs:
1662  *  ------
1663  *  dialogboxW = DialogBox widget to withdraw.
1664  * 
1665  *  Comments:
1666  *  --------
1667  *  Does not maintain the WM_STATE property on the dialog "client".
1668  * 
1669  *************************************<->***********************************/
1670
1671 void WithdrawDialog (Widget dialogboxW)
1672 {
1673 #ifdef WSM
1674     int i;
1675 #endif /* WSM */
1676     ClientData *pCD = NULL;
1677
1678     /*
1679      * Get the dialog shell window client data.
1680      */
1681
1682     if (XFindContext (DISPLAY, XtWindow (XtParent (dialogboxW)),
1683                       wmGD.windowContextType, (caddr_t *)&pCD))
1684       return;
1685
1686     XtUnmanageChild (dialogboxW);
1687     DeleteClientFromList (ACTIVE_WS, pCD);
1688 #ifdef WSM
1689     /* TakeClientOutOfWorkspace (ACTIVE_WS, pCD); */
1690
1691     /* 
1692      * Count backward for efficiency  --  
1693      *     removes from end of list.
1694      */
1695     for (i = pCD->numInhabited - 1; i >= 0; i--)
1696     {
1697         TakeClientOutOfWorkspace (
1698             GetWorkspaceData(pCD->pSD, pCD->pWsList[i].wsID),
1699             pCD);
1700     }
1701 #endif /* WSM */
1702     ResetWithdrawnFocii (pCD);
1703     XUnmapWindow (DISPLAY, pCD->clientFrameWin);
1704
1705 } /* END OF FUNCTION WithdrawDialog */
1706
1707
1708 \f
1709 /*************************************<->*************************************
1710  *
1711  *  ReManageDialog (pSD, dialogboxW)
1712  *
1713  *
1714  *  Description:
1715  *  -----------
1716  *  This function remanages a DialogBox "client" that was unmanaged via 
1717  *  WithdrawDialog ().
1718  *
1719  *
1720  *  Inputs:
1721  *  ------
1722  *  pSD = pointer to screen data
1723  *  dialogboxW = DialogBox widget to remanage.
1724  *
1725  * 
1726  *  Outputs:
1727  *  -------
1728  *  Does not maintain the WM_STATE property on the dialog "client".
1729  *
1730  *************************************<->***********************************/
1731
1732 void ReManageDialog (WmScreenData *pSD, Widget dialogboxW)
1733 {
1734     ClientData *pCD = NULL;
1735
1736     /*
1737      * Get the dialog shell window client data.
1738      */
1739
1740     if (XFindContext (DISPLAY, XtWindow (XtParent (dialogboxW)),
1741                       wmGD.windowContextType, (caddr_t *)&pCD))
1742       return;
1743
1744     /*
1745      * The order is important here:
1746      */
1747
1748 #ifdef WSM
1749     /*
1750      * Put system modal windows in all workspaces to
1751      * avoid the race condition of the window coming up
1752      * just as the user switches workspaces OR when
1753      * the window is up and a user switces workspaces
1754      * with a key binding.  We may want to eventually short 
1755      * circuit F_Functions any time there is a modal
1756      * window up, but for now, we will just make sure
1757      * the modal window appears in all workspaces 
1758      */
1759
1760     pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
1761     F_AddToAllWorkspaces(0, pCD, 0);
1762     pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
1763 #endif /* WSM */
1764
1765     if (pSD->clientList)
1766     {
1767       StackWindow (pSD->pActiveWS, &pCD->clientEntry,
1768                     TRUE, (ClientListEntry *) NULL);
1769     }
1770     AddClientToList (pSD->pActiveWS, pCD, True /*on top*/);
1771     XMapWindow (DISPLAY, pCD->clientFrameWin);
1772     XtManageChild (dialogboxW);
1773
1774     if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1775     {
1776         Do_Focus_Key (pCD, GetTimestamp() , ALWAYS_SET_FOCUS);
1777     }
1778
1779
1780 } /* END OF FUNCTION ReManageDialog */
1781
1782 #ifdef PANELIST
1783 \f
1784 /*************************************<->*************************************
1785  *
1786  *  RegisterEmbeddedClients (wPanelist, pECD, count)
1787  *
1788  *
1789  *  Description:
1790  *  -----------
1791  *  This function registers a list of clients to be embedded in the
1792  *  front panel subsystem.
1793  *
1794  *
1795  *  Inputs:
1796  *  ------
1797  *  wPanelist = front panel object (widget)
1798  *  pECD = pointer to list of data for clients to embed
1799  *  count = number of elements in the list
1800  *
1801  * 
1802  *  Outputs:
1803  *  -------
1804  *
1805  *************************************<->***********************************/
1806
1807 void
1808 RegisterEmbeddedClients (
1809         Widget wPanelist, 
1810         WmFpEmbeddedClientList pECD, 
1811         int count)
1812 {
1813     WmScreenData *pSD;
1814     int i;
1815
1816     for (i= 0; i < wmGD.numScreens; i++)
1817     {
1818         pSD = &(wmGD.Screens[i]);
1819
1820         if (pSD->managed)
1821         {
1822            if (pSD->wPanelist == wPanelist)
1823                break;
1824         }
1825     }
1826
1827     if (i < wmGD.numScreens)
1828     {
1829         pSD->pECD = (struct _WmFpEmbeddedClientData *) pECD;
1830         pSD->numEmbeddedClients = count;
1831     }
1832 #ifdef DEBUG
1833     else
1834     {
1835         fprintf (stderr, "Couldn't match wPanelist to screen data\n");
1836     }
1837 #endif /* DEBUG */
1838
1839 } /* END OF FUNCTION RegisterEmbeddedClients */
1840
1841 \f
1842 #define LTT_INCREMENT  16
1843 /*************************************<->*************************************
1844  *
1845  *  ListTransientSubtree (pCD, ppWins, pSize, pCount)
1846  *
1847  *
1848  *  Description:
1849  *  -----------
1850  *  This function returns the list of windows in a transient window
1851  *  tree.
1852  *
1853  *
1854  *  Inputs:
1855  *  ------
1856  *  pCD         - pointer to client data of a window.
1857  *  ppWins      - address of a pointer to a list of windows 
1858  *                (this must be in the heap -- XtMalloc).
1859  *  pSize       - address of variable with size of list
1860  *  pCount      - address of variable with number of windows in list
1861  * 
1862  *  Outputs:
1863  *  -------
1864  *  *ppWins     - may point to a new area of memory if list grows
1865  *  *pSize      - if list has to grow, this may be bigger
1866  *  *pCount     - number of windows in the list
1867  *
1868  *  Comments
1869  *  --------
1870  *  The list should be freed when done with XtFree().
1871  *
1872  *************************************<->***********************************/
1873
1874 static void
1875 ListTransientSubtree (
1876         ClientData *pCD,
1877         Window **ppWins,
1878         int *pSize,
1879         int *pCount)
1880 {
1881     /*
1882      * Check size
1883      */
1884     if (*pCount == *pSize) 
1885     {
1886         *pSize += LTT_INCREMENT;
1887         *ppWins = (Window *) 
1888                 XtRealloc ((char *) *ppWins, (*pSize * sizeof(Window)));
1889     }
1890     /*
1891      * Add this window to the list
1892      */
1893     (*ppWins)[*pCount] = pCD->client;
1894     *pCount += 1;
1895
1896     /*
1897      * Add siblings
1898      */
1899     if (pCD->transientSiblings)
1900         ListTransientSubtree (pCD->transientSiblings, ppWins, pSize, pCount);
1901
1902     /*
1903      * Add children
1904      */
1905     if (pCD->transientChildren)
1906         ListTransientSubtree (pCD->transientChildren, ppWins, pSize, pCount);
1907
1908     
1909 } /* END OF FUNCTION ListTransientSubtree */
1910
1911
1912 \f
1913 /*************************************<->*************************************
1914  *
1915  *  ListTransientTree (pCD)
1916  *
1917  *
1918  *  Description:
1919  *  -----------
1920  *  This function returns the list of windows in a transient window
1921  *  tree.
1922  *
1923  *
1924  *  Inputs:
1925  *  ------
1926  *  pCD         - pointer to client data of a primary window.
1927  * 
1928  *  Outputs:
1929  *  -------
1930  *  none
1931  *
1932  *  Comments
1933  *  --------
1934  *  The list should be freed when done with XtFree().
1935  *
1936  *************************************<->***********************************/
1937
1938 static Window *
1939 ListTransientTree (
1940         ClientData *pCD)
1941 {
1942     Window *pWins;
1943     int count;
1944     int iSize;
1945
1946     /*
1947      * Initial allocation
1948      */
1949     iSize = LTT_INCREMENT;
1950     pWins = (Window *) XtMalloc (iSize * sizeof(Window));
1951     count = 0;
1952
1953     /*
1954      * Add this window to the list
1955      */
1956     ListTransientSubtree (pCD, &pWins, &iSize, &count);
1957
1958     /*
1959      * Add terminator to end of window list
1960      */
1961     if (count == iSize) 
1962     {
1963         iSize += LTT_INCREMENT;
1964         pWins = (Window *) 
1965                 XtRealloc ((char *)pWins, (iSize * sizeof(Window)));
1966     }
1967     pWins[count++] = None;
1968
1969     /*
1970      * Return the list of windows found
1971      */
1972     return (pWins);
1973     
1974 } /* END OF FUNCTION ListTransientTree */
1975
1976 \f
1977 /*************************************<->*************************************
1978  *
1979  *  ReManageWindow (pCD)
1980  *
1981  *
1982  *  Description:
1983  *  -----------
1984  *  This function unmanages and remanages a window and it's associated
1985  *  transients.
1986  *
1987  *
1988  *  Inputs:
1989  *  ------
1990  *  pCD         - pointer to client data of a primary window.
1991  * 
1992  *  Outputs:
1993  *  -------
1994  *  none
1995  *
1996  *  Comments
1997  *  --------
1998  *  The pointer pCD is invalid after calling this function -- a
1999  *  side-effect of unmanaging the client before remanaging it.
2000  *
2001  *************************************<->***********************************/
2002
2003 static void
2004 ReManageWindow (
2005         ClientData *pCD)
2006 {
2007     long manageFlags = MANAGEW_NORMAL;
2008     Window *pWins, *pW;
2009     WmScreenData *pSD;
2010
2011     /*
2012      * Get the list of windows in the transient window tree.
2013      */
2014     pWins = ListTransientTree (pCD);
2015
2016     pSD = pCD->pSD;
2017
2018     /*
2019      * Unmanage this window and associated transients
2020      */
2021     UnManageWindow (pCD);
2022
2023     /*** pCD is no longer a valid pointer!!! ***/
2024     
2025     /*
2026      * Remanage this window and its secondaries
2027      */
2028     pW = pWins;
2029     while (*pW != None)
2030     {
2031         ManageWindow (pSD, *pW, manageFlags);
2032         pW++;
2033     }
2034
2035     XtFree ((char *) pWins);
2036
2037 } /* END OF FUNCTION ReManageWindow */
2038
2039
2040 \f
2041 /*************************************<->*************************************
2042  *
2043  *  ScanForEmbeddedClients (pSD)
2044  *
2045  *
2046  *  Description:
2047  *  -----------
2048  *  This function scans the managed windows and identifies those that
2049  *  should be embedded clients in the front panel
2050  *
2051  *
2052  *  Inputs:
2053  *  ------
2054  *  pSD         - pointer to screen data.
2055  * 
2056  *  Outputs:
2057  *  -------
2058  *
2059  *************************************<->***********************************/
2060
2061 void
2062 ScanForEmbeddedClients (
2063         WmScreenData *pSD)
2064 {
2065     ClientData *pCD;
2066     ClientListEntry *pCLE;
2067     WmFpEmbeddedClientData *pECD;
2068     Boolean bReset;
2069
2070     /*
2071      *  Search through all the windows we're managing right now to
2072      *  see if any should be embedded in a front/sub panel.
2073      */
2074     pCLE = pSD->clientList;
2075     bReset = False;
2076
2077     while (pCLE != NULL)
2078     {
2079         /*
2080          * See if this is an previously unrecognized embedded client
2081          */
2082         pCD = pCLE->pCD;
2083
2084         if ((pCD->pECD == NULL ) && IsEmbeddedClient (pCD, &pECD))
2085         {
2086             /*
2087              * Remanage this window and associated transients
2088              */
2089             ReManageWindow (pCD);
2090             /*
2091              * At this point pCD is no longer valid and the
2092              * pSD->clientList has been changed.
2093              */
2094             bReset = True;
2095         }
2096         
2097         /*
2098          * Test for exit condition 
2099          */
2100         if (pCLE == pSD->lastClient) 
2101         {
2102             /*
2103              * Gone all the way through the list without finding
2104              * anything -- time to quit
2105              */
2106             break;
2107         }
2108         else if (bReset)
2109         {
2110             /*
2111              * Remanaging a client restructures the client list.
2112              * Start over at the beginning.
2113              */
2114             bReset = False;
2115             pCLE = pSD->clientList;
2116         }
2117         else
2118         {
2119             /*
2120              * Move to next client.
2121              */
2122             pCLE = pCLE->nextSibling;
2123         }
2124     }
2125
2126 } /* END OF FUNCTION ScanForEmbeddedClients */
2127
2128 \f
2129 /*************************************<->*************************************
2130  *
2131  *  IsEmbeddedClient (pCD, ppECD)
2132  *
2133  *
2134  *  Description:
2135  *  -----------
2136  *  This function tests a a client to see if it should be embedded
2137  *  in the front panel.
2138  *
2139  *
2140  *  Inputs:
2141  *  ------
2142  *  pCD = ptr to Client Data
2143  *  ppECD = ptr to returned embedded client data ptr
2144  *
2145  * 
2146  *  Outputs:
2147  *  -------
2148  *  *ppECD = ptr to embedded client data
2149  *
2150  *************************************<->***********************************/
2151
2152 Boolean
2153
2154 IsEmbeddedClient (ClientData *pCD, WmFpEmbeddedClientData **ppECD)
2155
2156 {
2157     WmScreenData *pSD;
2158     int i;
2159     Boolean bFoundMatch = False;
2160     WmFpEmbeddedClientData *pECD;
2161
2162     pSD = pCD->pSD;
2163     pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2164
2165     for (i = 0; i < pSD->numEmbeddedClients && !bFoundMatch; i++, pECD++)
2166     {
2167         /*
2168          * It's an embedded client if 
2169          *     the resource name matches a slot and 
2170          *     it's not a subpanel and
2171          *     the slot isn't already filled.
2172          */
2173         if ((!strcmp ((char *)pCD->clientName, 
2174                       (char *)(pECD->pchResName))) &&
2175             (!(pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)) &&
2176             (!pECD->pCD))
2177         {
2178             *ppECD = pECD;
2179             bFoundMatch = True;
2180         }
2181     }
2182     return (bFoundMatch);
2183
2184 } /* END OF FUNCTION IsEmbeddedClient */
2185
2186 \f
2187 /******************************<->*************************************
2188  *
2189  *  ManageEmbeddedClient (pCD, pECD, manageFlags)
2190  *
2191  *
2192  *  Description:
2193  *  -----------
2194  *  This is the function that is used to setup a client window
2195  *  in the front panel.
2196  *
2197  *  Inputs:
2198  *  ------
2199  *  pCD = initialized client data, including window of client that
2200  *        we want to manage.
2201  *  pECD = ptr to embedded client entry for this client
2202  *
2203  *  manageFlags = additional control information 
2204  * 
2205  *  Outputs:
2206  *  -------
2207  *  Returns False if normal client processing needs to be done.
2208  *
2209  *  Returns True if this client has been embedded directly in the
2210  *  front panel and is NOT to be managed as a normal top level
2211  *  window--no further processing required.
2212  ******************************<->***********************************/
2213 Boolean
2214
2215 ManageEmbeddedClient (
2216     ClientData *pCD, 
2217     WmFpEmbeddedClientData *pECD,
2218     long manageFlags)
2219
2220 {
2221     XWindowChanges windowChanges;
2222     unsigned int mask;
2223     WmFpPushRecallClientData *pPRCD;
2224
2225     if (!pECD || !pCD)
2226     {
2227         return (False);
2228     }
2229    
2230     /*
2231      * Add to all workspaces
2232      */
2233     pCD->dtwmFunctions |= DtWM_FUNCTION_OCCUPY_WS;
2234
2235     F_AddToAllWorkspaces(0, pCD, 0);
2236
2237     pCD->dtwmFunctions &= ~DtWM_FUNCTION_OCCUPY_WS;
2238
2239     /*
2240      * Set client list entries 
2241      * (in a list by itself)
2242      */
2243     pCD->clientEntry.type = NORMAL_STATE;
2244     pCD->clientEntry.pCD = pCD;
2245     pCD->clientEntry.nextSibling = NULL;
2246     pCD->clientEntry.prevSibling = NULL;
2247
2248     pCD->iconEntry.type = MINIMIZED_STATE;
2249     pCD->iconEntry.pCD = pCD;
2250     pCD->iconEntry.nextSibling = NULL;
2251     pCD->iconEntry.prevSibling = NULL;
2252
2253     /*
2254      *  Save context for event processing.
2255      *
2256      */
2257
2258     XSaveContext (DISPLAY, pCD->client, wmGD.windowContextType, 
2259                     (caddr_t)pCD);
2260
2261     if (!(pCD->clientFlags & CLIENT_WM_CLIENTS))
2262     {
2263         XChangeSaveSet (DISPLAY, pCD->client, SetModeInsert);
2264         XChangeSaveSet (DISPLAY1, pCD->client, SetModeInsert);
2265         pCD->clientFlags |= CLIENT_IN_SAVE_SET;
2266     }
2267     if (!(manageFlags & MANAGEW_WM_CLIENTS))
2268     {
2269         XSync (DISPLAY1, False);
2270
2271         if (pCD->clientFlags & CLIENT_DESTROYED)
2272         {
2273             UnManageWindow (pCD);
2274             return (True); 
2275         }
2276     }
2277
2278     XtAddEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
2279                 (SubstructureRedirectMask | SubstructureNotifyMask),
2280                 False,
2281                 (XtEventHandler)HandleSubstructEvents,
2282                 (XtPointer)(pCD));
2283
2284     /* 
2285      * Fill in more client data
2286      */
2287     pCD->clientX = pECD->x;
2288     pCD->clientY = pECD->y;
2289     pCD->clientWidth = pECD->width;
2290     pCD->clientHeight = pECD->height;
2291
2292     pCD->clientFrameWin = 0;
2293     pCD->clientBaseWin = pECD->winParent;
2294
2295     pECD->pCD = pCD;
2296     pCD->pECD = (void *) pECD;
2297
2298 #ifdef WSM
2299     SetClientWsIndex(pCD);
2300 #endif
2301     SetClientWMState (pCD, NormalState, NORMAL_STATE);
2302
2303     /*
2304      * Set state on subpanel in case it never gets mapped
2305      * to prevent session manager from finding an embedded
2306      * client on its own.
2307      */
2308     ForceSubpanelWMState (pECD->winParent);
2309
2310     XReparentWindow (DISPLAY1, pCD->client, 
2311                      pECD->winParent,
2312                      pECD->x, pECD->y);
2313     pCD->clientFlags |= CLIENT_REPARENTED;
2314
2315     windowChanges.width = pECD->width;
2316     windowChanges.height = pECD->height;
2317     windowChanges.border_width = 0;
2318     mask = (CWWidth | CWHeight | CWBorderWidth);
2319
2320     XConfigureWindow (DISPLAY1, pCD->client, mask, &windowChanges);
2321
2322     XMapWindow (DISPLAY1, pCD->client);
2323     if (pCD->iconWindow)
2324     {
2325         XUnmapWindow (DISPLAY, pCD->iconWindow);
2326     }
2327
2328     UpdateEmbeddedClientsProperty (pCD->pSD);
2329
2330     SendConfigureNotify (pCD);
2331
2332     if (IsPushRecallClient (pCD, &pPRCD))
2333     {
2334         /*
2335          * There should only be one instance of this
2336          * client started from a front panel button.
2337          */
2338         pPRCD->pCD = pCD;
2339         pCD->pPRCD = (void *) pPRCD;
2340     }
2341
2342     WmStopWaiting(); 
2343
2344     return(True); /* successful embedation */
2345
2346 } /* END OF FUNCTION ManageEmbeddedClient */
2347
2348 \f
2349 /******************************<->*************************************
2350  *
2351  *  ReparentEmbeddedClient (pECD, newControl, newWin, x, y, width, height)
2352  *
2353  *
2354  *  Description:
2355  *  -----------
2356  *
2357  *  Inputs:
2358  *  ------
2359  *  pECD = ptr to embedded client entry for this client
2360  *  newControl = widget for new "parent" widget
2361  *  newWin = window ID of window that this embedded client will be
2362  *           a parent of. This is needed in case the control is a
2363  *           gadget.
2364  *  x = x-coord position within newWin where UL corner of the embedded
2365  *      client will go.
2366  *  y = y-coord as described above.
2367  *  width = desired width of embedded client in this new location
2368  *  height = desired height as above.
2369  *
2370  * 
2371  *  Outputs:
2372  *  -------
2373  *  Returns False if embedded client was is not moved to the new
2374  *  location.
2375  *
2376  *  Returns True if this client has been reparented to the new
2377  *  control.
2378  ******************************<->***********************************/
2379 Boolean
2380
2381 ReparentEmbeddedClient (
2382     WmFpEmbeddedClientData *pECD,
2383     Widget newControl,
2384     Window newWin,
2385     int x, 
2386     int y,
2387     unsigned int width, 
2388     unsigned int height
2389     )
2390
2391 {
2392     XWindowChanges windowChanges;
2393     unsigned int mask;
2394     ClientData *pCD;
2395
2396     /*
2397      * If we have bogus data or if we're asked
2398      * to reparent to our current parent, then just
2399      * say no.
2400      */
2401     if ((pECD == NULL) || 
2402         (pECD->pCD == NULL) ||
2403         (pECD->winParent == newWin))
2404     {
2405         return (False);
2406     }
2407     pCD=pECD->pCD;
2408
2409     /*
2410      * Need event handler on new parent window?
2411      */
2412     if (newWin != pECD->winParent)
2413     {
2414         XtRemoveEventHandler(XtWindowToWidget (DISPLAY1, pECD->winParent),
2415                 (SubstructureRedirectMask | SubstructureNotifyMask),
2416                 False,
2417                 (XtEventHandler)HandleSubstructEvents,
2418                 (XtPointer)(pCD));
2419
2420         XtAddEventHandler(XtWindowToWidget (DISPLAY1, newWin),
2421                 (SubstructureRedirectMask | SubstructureNotifyMask),
2422                 False,
2423                 (XtEventHandler)HandleSubstructEvents,
2424                 (XtPointer)(pCD));
2425     }
2426
2427     /* 
2428      * Update embedding and client data
2429      */
2430     pECD->wControl = newControl;
2431     pECD->winParent = newWin;
2432     pCD->clientX = pECD->x = x;
2433     pCD->clientY = pECD->y = y;
2434     pCD->clientWidth = pECD->width = width;
2435     pCD->clientHeight = pECD->height = height;
2436     pCD->clientBaseWin = pECD->winParent;
2437
2438     /*
2439      * Set state on subpanel in case it never gets mapped
2440      * to prevent session manager from finding an embedded
2441      * client on its own.
2442      */
2443     ForceSubpanelWMState (pECD->winParent);
2444
2445     /*
2446      * Do the actual reparent
2447      */
2448     XReparentWindow (DISPLAY1, pCD->client, 
2449                      pECD->winParent,
2450                      pECD->x, pECD->y);
2451
2452     /*
2453      * Configure the embedded client
2454      */
2455     windowChanges.width = pECD->width;
2456     windowChanges.height = pECD->height;
2457     windowChanges.border_width = 0;
2458     mask = (CWWidth | CWHeight | CWBorderWidth);
2459
2460     XConfigureWindow (DISPLAY1, pCD->client, mask, &windowChanges);
2461
2462     XMapWindow (DISPLAY1, pCD->client);
2463
2464     UpdateEmbeddedClientsProperty (pCD->pSD);
2465
2466     SendConfigureNotify (pCD);
2467
2468     return(True); /* successful reparent */
2469
2470 } /* END OF FUNCTION ReparentEmbeddedClient */
2471
2472 \f
2473 /*************************************<->*************************************
2474  *
2475  *  ForceSubpanelWMState (win)
2476  *
2477  *
2478  *  Description:
2479  *  -----------
2480  *  This function forces a WM_STATE property on a subpanel window
2481  *  so that the session manager doesn't save multiple copies
2482  *  of embedded clients for subpanels that never get mapped.
2483  *
2484  *
2485  *  Inputs:
2486  *  ------
2487  *  win = window ID of a subpanel window (not necessarily the top level!)
2488  *
2489  * 
2490  *  Outputs:
2491  *  -------
2492  *
2493  *************************************<->***********************************/
2494
2495 static void
2496 ForceSubpanelWMState (Window win)
2497 {
2498     ClientData *pCD = NULL;
2499     Window root, parent;
2500     Window *children = NULL;
2501     unsigned int numChildren;
2502     PropWMState *wmStateProp;
2503     Boolean bDone = False;
2504
2505     while (!bDone)
2506     {
2507         if (!XQueryTree (DISPLAY, win, &root, &parent, 
2508                 &children, &numChildren))
2509         {
2510             break;
2511         }
2512
2513         if (!XFindContext(DISPLAY, win, wmGD.windowContextType, 
2514             (caddr_t *)&pCD))
2515         {
2516             /*
2517              * Only continue if we're not already managing this subpanel.
2518              */
2519             bDone = True;
2520         }
2521         else if (parent == root)
2522         {
2523             if ((wmStateProp = GetWMState (win)))
2524             {
2525                 /*
2526                  * Already has a WM_STATE.
2527                  */
2528                 XFree ((char *)wmStateProp);
2529             }
2530             else
2531             {
2532                 /*
2533                  * Add a dummy WM_STATE to foil the session manager
2534                  * search.
2535                  */
2536                 SetWMState (win, WITHDRAWN_STATE, 0);
2537             }
2538             bDone = True;
2539         }
2540         else 
2541         {
2542             /* continue ascent up to root */
2543             win = parent;
2544         }
2545
2546         XFree ((char *) children);
2547     }
2548
2549 } /* END OF FUNCTION ForceSubpanelWMState */
2550
2551 \f
2552 /*************************************<->*************************************
2553  *
2554  *  RegisterPushRecallClients (wPanelist, pPRCD, count)
2555  *
2556  *
2557  *  Description:
2558  *  -----------
2559  *  This function registers a list of push_recallclients for the 
2560  *  front panel subsystem. 
2561  *
2562  *
2563  *  Inputs:
2564  *  ------
2565  *  wPanelist = front panel object (widget)
2566  *  pPRCD = pointer to list of data for clients
2567  *  count = number of elements in the list
2568  *
2569  * 
2570  *  Outputs:
2571  *  -------
2572  *
2573  *************************************<->***********************************/
2574
2575 void
2576 RegisterPushRecallClients (
2577         Widget wPanelist, 
2578         WmFpPushRecallClientList pPRCD, 
2579         int count)
2580 {
2581     WmScreenData *pSD;
2582     int i;
2583
2584     for (i= 0; i < wmGD.numScreens; i++)
2585     {
2586         pSD = &(wmGD.Screens[i]);
2587
2588         if (pSD->managed)
2589         {
2590            if (pSD->wPanelist == wPanelist)
2591                break;
2592         }
2593     }
2594
2595     if (i < wmGD.numScreens)
2596     {
2597         pSD->pPRCD = (struct _WmFpPushRecallClientData *) pPRCD;
2598         pSD->numPushRecallClients = count;
2599     }
2600 #ifdef DEBUG
2601     else
2602     {
2603         fprintf (stderr, "Couldn't match wPanelist to screen data\n");
2604     }
2605 #endif /* DEBUG */
2606
2607     for (i = 0; i < pSD->numPushRecallClients ; i++, pPRCD++)
2608     {
2609         /*
2610          * Initialize data in each slot
2611          */
2612         pPRCD->tvTimeout.tv_sec = 0;
2613     }
2614
2615 } /* END OF FUNCTION RegisterPushRecallClients */
2616
2617 \f
2618 /*************************************<->*************************************
2619  *
2620  *  IsPushRecallClient (pCD, ppPRCD)
2621  *
2622  *
2623  *  Description:
2624  *  -----------
2625  *  This function tests a a client to see if it should be embedded
2626  *  in the front panel.
2627  *
2628  *
2629  *  Inputs:
2630  *  ------
2631  *  pCD = ptr to Client Data
2632  *  ppPRCD = ptr to returned embedded client data ptr
2633  *
2634  * 
2635  *  Outputs:
2636  *  -------
2637  *  *ppPRCD = ptr to embedded client data
2638  *
2639  *************************************<->***********************************/
2640
2641 Boolean
2642
2643 IsPushRecallClient (ClientData *pCD, WmFpPushRecallClientData **ppPRCD)
2644
2645 {
2646     WmScreenData *pSD;
2647     int i;
2648     Boolean bFoundMatch = False;
2649     WmFpPushRecallClientData *pPRCD;
2650
2651     pSD = pCD->pSD;
2652     pPRCD = (WmFpPushRecallClientData *) pSD->pPRCD;
2653
2654     for (i = 0; i < pSD->numPushRecallClients && !bFoundMatch; i++, pPRCD++)
2655     {
2656         /*
2657          * It's a push_recall client if the resource name matches
2658          * a slot and the slot isn't already filled.
2659          */
2660         if ((!strcmp ((char *)pCD->clientName, 
2661                      (char *)(pPRCD->pchResName))) &&
2662             (!pPRCD->pCD))
2663         {
2664             *ppPRCD = pPRCD;
2665             bFoundMatch = True;
2666         }
2667     }
2668     return (bFoundMatch);
2669
2670 } /* END OF FUNCTION IsPushRecallClient */
2671
2672 \f
2673 /*************************************<->*************************************
2674  *
2675  *  ScanForPushRecallClients (pSD)
2676  *
2677  *
2678  *  Description:
2679  *  -----------
2680  *  This function scans the managed windows and identifies those that
2681  *  should be push recall clients of the front panel
2682  *
2683  *
2684  *  Inputs:
2685  *  ------
2686  *  pSD         - pointer to screen data.
2687  * 
2688  *  Outputs:
2689  *  -------
2690  *
2691  *************************************<->***********************************/
2692
2693 void
2694 ScanForPushRecallClients (
2695         WmScreenData *pSD)
2696 {
2697     ClientData *pCD;
2698     ClientListEntry *pCLE;
2699     WmFpPushRecallClientData *pPRCD;
2700
2701     /*
2702      *  Search through all the windows we're managing right now 
2703      */
2704     pCLE = pSD->clientList;
2705
2706     while (pCLE != NULL)
2707     {
2708         /*
2709          * See if this is an previously unrecognized push recall client
2710          */
2711         pCD = pCLE->pCD;
2712
2713         if ((pCD->pPRCD == NULL ) && IsPushRecallClient (pCD, &pPRCD))
2714         {
2715             CheckPushRecallClient (pCD);
2716         }
2717         
2718         /*
2719          * Test for exit condition 
2720          */
2721         if (pCLE == pSD->lastClient) 
2722         {
2723             /*
2724              * Gone all the way through the list without finding
2725              * anything -- time to quit
2726              */
2727             break;
2728         }
2729         else
2730         {
2731             /*
2732              * Move to next client.
2733              */
2734             pCLE = pCLE->nextSibling;
2735         }
2736     }
2737
2738 } /* END OF FUNCTION ScanForPushRecallClients */
2739
2740 \f
2741 /******************************<->*************************************
2742  *
2743  *  static void CheckPushRecallClient (pCD)
2744  *
2745  *
2746  *  Description:
2747  *  -----------
2748  *  Checks a client against the list of push recall clients to see
2749  *  if there are any matches. All matches are marked.
2750  *
2751  *  Inputs:
2752  *  ------
2753  *  pCD - pointer to the Client Data structure
2754  * 
2755  *  Outputs:
2756  *  -------
2757  *
2758  *  Comments:
2759  *  --------
2760  *
2761  ******************************<->***********************************/
2762 static void 
2763 CheckPushRecallClient(
2764         ClientData *pCD)
2765 {
2766     WmFpPushRecallClientData *pPRCD;
2767
2768     while (IsPushRecallClient (pCD, &pPRCD))
2769     {
2770         /*
2771          * There should only be one instance of this
2772          * client started from a front panel button.
2773          */
2774         pPRCD->pCD = pCD;
2775         pPRCD->tvTimeout.tv_sec = 0;
2776         if (!pCD->pPRCD)
2777             pCD->pPRCD = (void *) pPRCD;
2778     }
2779 }
2780
2781 \f
2782 /******************************<->*************************************
2783  *
2784  *  static void HandleSubstructEvents (Widget w, caddr_t pCD, XEvent *event)
2785  *
2786  *
2787  *  Description:
2788  *  -----------
2789  *  Causes death of embedded clients to run through UnManageWindow()
2790  *  for proper cleanup.
2791  *
2792  *  Note there is one of these event handlers instantiated for
2793  *  each live client window in the front panel.  Hence, for each
2794  *  live client window death, each of the event handlers gets called
2795  *  once.  We need to ensure that we've got the right pCD before
2796  *  calling UnManageWindow() on it.
2797  *
2798  *
2799  *  Inputs:
2800  *  ------
2801  *  w   - not used
2802  *  pCD - pointer to the Client Data structure
2803  *  event - we only care about UnMapNotify
2804  * 
2805  *  Outputs:
2806  *  -------
2807  *
2808  *  Comments:
2809  *  --------
2810  *  This routine is called LOTS of times, for all types of events.
2811  *
2812  ******************************<->***********************************/
2813 static void 
2814 HandleSubstructEvents(
2815         Widget w,
2816         caddr_t ptr,
2817         XEvent *event )
2818 {
2819         struct _ClientData *pCD = (struct _ClientData *)ptr;
2820
2821         switch (event->type)
2822         {
2823             case UnmapNotify:
2824             {
2825                 if (pCD->client == event->xunmap.window)
2826                 {
2827                     UnManageWindow (pCD);
2828                 }
2829                 break;
2830             }
2831         }
2832 } /* END OF FUNCTION HandleSubstructEvents */
2833
2834 \f
2835 /*******************************<->*************************************
2836  *
2837  *  UpdateEmbeddedClientsProperty (pSD)
2838  *
2839  *  Description:
2840  *  -----------
2841  *
2842  *  Inputs:
2843  *  ------
2844  *  pSD - pointer to the screen data
2845  * 
2846  *  Outputs:
2847  *  -------
2848  *  True if successful, False otherwise.
2849  *
2850  *  Comments:
2851  *  --------
2852  *  The _DT_WORKSPACE_EMBEDDED_CLIENTS property on the 
2853  *  root window for the screen will be updated to reflect the
2854  *  current contents of the front panel
2855  *
2856  * 
2857  ******************************<->***********************************/
2858 Boolean 
2859 UpdateEmbeddedClientsProperty(
2860         WmScreenData *pSD )
2861 {
2862     unsigned int numClients = 0;
2863     Window *pClients = NULL;
2864     Boolean rval = True;
2865     int i;
2866     WmFpEmbeddedClientData *pECD;
2867
2868     pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2869
2870     for (i = 0; i < pSD->numEmbeddedClients; i++, pECD++)
2871     {
2872         if (pECD->pCD)
2873         {
2874             numClients += 1;
2875
2876             if (!pClients) 
2877             {
2878                 pClients = (Window *) XtMalloc (sizeof(Window));
2879             }
2880             else
2881             {
2882                 pClients = (Window *) XtRealloc ((char *)pClients,
2883                     (numClients * (sizeof(Window))));
2884             }
2885
2886             if (!pClients)
2887             {
2888                 Warning (
2889 ((char *)GETMESSAGE(4, 17, "Insufficient memory to write _DT_WORKSPACE_EMBEDDED_CLIENTS."))
2890                         );
2891                 rval = False;
2892                 break;
2893             }
2894             else
2895             {
2896                 pClients[numClients-1] = pECD->pCD->client;
2897             }
2898         }
2899     }
2900
2901     SetEmbeddedClientsProperty (pSD->rootWindow, pClients,
2902         numClients);
2903
2904     if (pClients != NULL)
2905     {
2906         XtFree ((char *)pClients);
2907     }
2908
2909     return (rval);
2910 } /* END OF FUNCTION UpdateEmbeddedClientsProperty */
2911
2912
2913 \f
2914 /*******************************<->*************************************
2915  *
2916  *  UnParentControls (pSD, unmap)
2917  *
2918  *  Description:
2919  *  -----------
2920  *
2921  *  Inputs:
2922  *  ------
2923  *  pSD - pointer to the screen data
2924  *  unmap - if True, then unmap the windows after reparenting to root
2925  * 
2926  *  Outputs:
2927  *  -------
2928  *  none
2929  *
2930  *  Comments:
2931  *  --------
2932  *  Reparents clients embedded in the front panel back to the 
2933  *  root window
2934  * 
2935  ******************************<->***********************************/
2936 void 
2937 UnParentControls(
2938         WmScreenData *pSD,
2939         Boolean unmap )
2940 {
2941     int i;
2942     ClientData *pCD;
2943     WmFpEmbeddedClientData *pECD;
2944     
2945     if (pSD && pSD->managed)
2946     {
2947         pECD = (WmFpEmbeddedClientData *) pSD->pECD;
2948         for (i = 0; i < pSD->numEmbeddedClients; i++, pECD++)
2949         {
2950             pCD = pECD->pCD;
2951
2952             if (pCD)
2953             {
2954                 if ((pCD->clientFlags & CLIENT_IN_SAVE_SET) &&
2955                     !(pCD->clientFlags & CLIENT_DESTROYED))
2956                 {
2957                     XRemoveFromSaveSet (DISPLAY, pCD->client);
2958                     XRemoveFromSaveSet (DISPLAY1, pCD->client);
2959                 }
2960                 
2961                 XReparentWindow (DISPLAY,
2962                                  pCD->client,
2963                                  pSD->rootWindow,
2964                                  pCD->clientX,
2965                                  pCD->clientY);
2966                 if (unmap)
2967                 {
2968                     XUnmapWindow (DISPLAY, pCD->client);
2969                     if (pCD->iconWindow)
2970                     {
2971                         if (pCD->clientFlags & ICON_IN_SAVE_SET)
2972                         {
2973                             XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
2974                             pCD->clientFlags &= ~ICON_IN_SAVE_SET;
2975                         }
2976                         XUnmapWindow (DISPLAY, pCD->iconWindow);
2977                     }
2978                 }
2979             }
2980         }
2981     }
2982     
2983 } /* END OF FUNCTION UnParentControl */
2984
2985
2986 \f
2987 /*************************************<->*************************************
2988  *
2989  *  RegisterIconBoxControl (wPanelist)
2990  *
2991  *
2992  *  Description:
2993  *  -----------
2994  *  This function registers the icon box control in a front panel
2995  *
2996  *
2997  *  Inputs:
2998  *  ------
2999  *  wPanelist = front panel object (widget)
3000  *
3001  *  Outputs:
3002  *  -------
3003  *
3004  *************************************<->***********************************/
3005
3006 void
3007 RegisterIconBoxControl (Widget wPanelist)
3008 {
3009     WmScreenData *pSD;
3010     int i;
3011
3012     for (i= 0; i < wmGD.numScreens; i++)
3013     {
3014         pSD = &(wmGD.Screens[i]);
3015
3016         if (pSD->managed)
3017         {
3018            if (pSD->wPanelist == wPanelist)
3019                break;
3020         }
3021     }
3022
3023     if (i < wmGD.numScreens)
3024     {
3025         pSD->iconBoxControl = True;
3026         pSD->useIconBox = True;
3027     }
3028 #ifdef DEBUG
3029     else
3030     {
3031         fprintf (stderr, "Couldn't match wPanelist to screen data\n");
3032     }
3033 #endif /* DEBUG */
3034
3035 } /* END OF FUNCTION RegisterIconBoxControl */
3036
3037 #endif /* PANELIST */