Remove UXPDS support
[oweals/cde.git] / cde / programs / dtwm / WmFunction.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: WmFunction.c /main/19 1998/04/20 13:00:48 mgreess $"
33 #endif
34 #endif
35 /*
36  * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY 
37  * (c) Copyright 1993, 1994 International Business Machines Corp.
38  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39  * (c) Copyright 1993, 1994 Novell, Inc.
40  */
41
42 /*
43  * Included Files:
44  */
45
46 #include "WmGlobal.h"
47 #ifndef WSM
48 #include <signal.h>
49 #endif
50 #include <stdio.h>
51 #include <X11/Xos.h>
52 #include "WmICCC.h"
53 #ifdef WSM
54 #include "WmWrkspace.h"  /* for ClientInWorkspace() test */
55 #include <Dt/EnvControlP.h>  /* for restoring **environ before an exec() */
56 #include "WmResNames.h"
57 #include <Dt/Message.h>
58 #include <Dt/Help.h>
59 #endif /* WSM */
60 #ifdef PANELIST
61 #include <Dt/DtStrDefs.h>
62 #include "WmPanelP.h"
63 #include "WmSignal.h"
64 #include "WmManage.h"
65 #endif /* PANELIST */
66
67 /*
68  * include extern functions
69  */
70 #include "WmFunction.h"
71 #include "WmCEvent.h"
72 #ifdef WSM
73 #include "WmHelp.h"
74 #endif /* WSM */
75 #include "WmCDInfo.h"
76 #include "WmColormap.h"
77 #include "WmError.h"
78 #include "WmEvent.h"
79 #include "WmFeedback.h"
80 #ifdef WSM
81 #include "WmIPC.h"
82 #endif /* WSM */
83 #include "WmIPlace.h"
84 #include "WmIconBox.h"
85 #include "WmKeyFocus.h"
86 #include "WmMenu.h"
87 #ifdef WSM
88 #include "WmPresence.h"
89 #endif /* WSM */
90 #include "WmProperty.h"
91 #include "WmProtocol.h"
92 #include "WmResParse.h"
93 #include "WmWinConf.h"
94 #include "WmWinInfo.h"
95 #include "WmWinList.h"
96 #include "WmWinState.h"
97 #include "WmXSMP.h"
98
99 #include <Xm/RowColumnP.h> /* for MS_LastManagedMenuTime */
100 extern XmMenuState _XmGetMenuState();
101
102 extern int putenv ();
103 extern char * getenv ();
104 #ifndef PORT_NOVFORK
105 extern pid_t vfork();
106 #endif /* PORT_NOVFORK */
107
108 static unsigned int GetEventInverseMask(XEvent *event);
109
110 #ifdef WSM
111
112 #if (defined(USL) || defined(linux) || \
113      defined(sun) || defined(CSRG_BASED)) && !defined(_NFILE)
114 #define _NFILE FOPEN_MAX
115 #endif
116 #define CLOSE_FILES_ON_EXEC() \
117 {int ifx; for (ifx=3; ifx < _NFILE; ifx++) (void) fcntl (ifx, F_SETFD, 1);}
118
119 #endif /* WSM */
120 /*
121  * Global Variables:
122  */
123
124 /*
125  * The 'dirty' variables are used to keep track of the transient window
126  * that has been lowered via "f.lower freeFamily".
127  */
128 static ClientData *dirtyStackEntry = NULL;
129 static ClientData *dirtyLeader = NULL;
130
131 #ifdef WSM
132 \f
133 /***********************<->*************************************
134  *
135  *  F_Action (args, pCD, event)
136  *
137  *
138  *  Description:
139  *  -----------
140  *  This is the window manager function handler for invoking actions.
141  *
142  *
143  *  Inputs:
144  *  ------
145  *  args = action function and arguments
146  *
147  *  pCD = pointer to the ClientData for the whole front panel
148  *
149  *  event = X event that invoked the function (key, button, or menu/NULL)
150  *
151  *
152  *  Outputs:
153  *  -------
154  *  RETURN = if True then further button binding/function processing can
155  *           be done for the event that caused this function to be called.
156  *
157  *  Comments:
158  *  -------
159  *  The pCD->controlWindow is a temporary area used solely for
160  *  this function invocation--it stores the pCW of the control
161  *  that want the function to happen.
162  ******************************<->***********************************/
163
164 Boolean
165 F_Action (String actionName, ClientData *pCD, XEvent *event)
166 {
167
168     WmActionArg *pAP = (WmActionArg *) actionName;
169
170     /* make sure the command runs on the right display. */
171     if (wmGD.pActiveSD->displayString)
172     {
173         putenv(wmGD.pActiveSD->displayString);
174     }
175
176     if (wmGD.dtSD)
177     {
178         WmFrontPanelSetBusy (True);
179     }
180
181     
182     DtActionInvoke (wmGD.pActiveSD->screenTopLevelW1,
183                     pAP->actionName, pAP->aap, pAP->numArgs,
184                     pAP->szExecParms, NULL, NULL, 1, NULL, NULL);
185     
186     /*
187      * Restore original DISPLAY environment variable 
188      */
189     if(wmGD.pActiveSD->displayString && wmGD.displayString)
190     {
191         putenv(wmGD.displayString);
192     }
193
194     return (True);
195     
196 } /* END OF FUNCTION F_Action */
197 #endif /* WSM */
198
199 \f
200 /******************************<->*************************************
201  *
202  *  F_Beep (args, pCD, event)
203  *
204  *
205  *  Description:
206  *  -----------
207  *  This is the window manager function handler for beeping.
208  *
209  *
210  *  Inputs:
211  *  ------
212  *  args = function arguments (specified in .mwmrc file)
213  *
214  *  pCD = pointer to the client data for the client window to which the
215  *        function is to be applied
216  *
217  *  event = X event that invoked the function (key, button, or menu/NULL)
218  *
219  *
220  *  Outputs:
221  *  -------
222  *  RETURN = if True then further button binding/function processing can
223  *           be done for the event that caused this function to be called.
224  *
225  ******************************<->***********************************/
226
227 Boolean F_Beep (String args, ClientData *pCD, XEvent *event)
228 {
229
230     /* !!! what is a good value for percent (the second arg) !!! */
231     XBell (DISPLAY, 0);
232
233     return (True);
234
235 } /* END OF FUNCTION F_Beep */
236
237
238 \f
239 /*
240  * Handle Special case where the dirty window is the top most
241  * transient window.  When this is the case, raising the window
242  * that was on top (the window just below the dirty window) will
243  * fail because Mwm stack database is out of sync.  So the solution
244  * is to restack the dirty transient relative to the second to the
245  * top transient.  This function is used to support freeFamily stacking.
246  */
247 ClientData * FindSecondToTopTransient (pcd)
248 ClientData *pcd;
249 {
250     ClientData *pcdNext;
251     static ClientData *second;
252
253     pcdNext = pcd->transientChildren;
254     while (pcdNext)
255     {
256         if (pcdNext->transientChildren)
257         {
258             if (!pcdNext->transientChildren->transientChildren)
259             {
260                 second = pcdNext;
261             }
262             FindSecondToTopTransient (pcdNext);
263         }
264         pcdNext = pcdNext->transientSiblings;
265         if (pcdNext && !pcdNext->transientSiblings)
266         {
267             second = pcdNext;
268         }
269     }
270
271     return (second);
272
273 } /* END OF FUNCTION */
274
275
276 \f
277 Boolean ForceLowerWindow (ClientData *pcd)
278 {
279 #if 0
280     Window stackWindow;
281     WmScreenData *pSD = (ACTIVE_WS)->pSD;
282 #endif
283     XWindowChanges changes;
284     Boolean restack = False;
285 #ifdef WSM
286     Window stackWindow;
287     WmScreenData *pSD = (ACTIVE_WS)->pSD;
288     unsigned int mask;
289     ClientListEntry     *pCLE;
290
291     /* 
292      * Find lowest window in this workspace. We'll stack this transient
293      * below it.
294      */
295     pCLE = pSD->lastClient;
296     stackWindow = None;
297     mask = CWStackMode;
298     while (pCLE != NULL)
299     {
300         if ((pCLE->pCD != pcd) &&
301             (ClientInWorkspace (ACTIVE_WS, pCLE->pCD)))
302         {
303             if ((pCLE->type == MINIMIZED_STATE) &&
304                 (pCLE->pCD->clientState == MINIMIZED_STATE))
305             {
306                 stackWindow = ICON_FRAME_WIN(pCLE->pCD);
307             }
308             else if ((pCLE->type == NORMAL_STATE) &&
309                      ((pCLE->pCD->clientState == NORMAL_STATE) ||
310                       (pCLE->pCD->clientState == MAXIMIZED_STATE)))
311             {
312                 stackWindow = pCLE->pCD->clientFrameWin;
313             }
314
315             if (stackWindow != None)
316             {
317                 mask |= CWSibling;
318                 changes.sibling = stackWindow;
319                 break;
320             }
321         }
322         if (stackWindow == None)
323         {
324             pCLE = pCLE->prevSibling;
325         }
326     }
327 #endif /* WSM */
328 #if 0
329     if (pSD->lastClient->type == MINIMIZED_STATE)
330     {
331         stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
332     }
333     else
334     {
335         stackWindow = pSD->lastClient->pCD->clientFrameWin;
336     }
337 #endif
338
339     changes.stack_mode = Below;
340 #ifdef WSM
341     if (mask)
342     {
343         XConfigureWindow (DISPLAY, pcd->clientFrameWin, mask, &changes);
344     }
345 #else /* WSM */
346     XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
347                       &changes);
348 #endif /* WSM */
349
350     return (restack);
351 }
352
353
354 \f
355 /*************************************<->*************************************
356  *
357  *  F_Lower (args, pCD, event)
358  *
359  *
360  *  Description:
361  *  -----------
362  *  This is the window manager function handler for bottoming a client window
363  *  or icon.
364  *
365  *
366  *  Inputs:
367  *  ------
368  *  args = function arguments (specified in .mwmrc file)
369  *
370  *  pCD = pointer to the client data for the client window to which the
371  *        function is to be applied
372  *
373  *  event = X event that invoked the function (key, button, or menu/NULL)
374  *
375  *
376  *  Outputs:
377  *  -------
378  *  RETURN = if True then further button binding/function processing can
379  *           be done for the event that caused this function to be called.
380  *
381  *************************************<->***********************************/
382
383 Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
384 {
385     ClientListEntry *pEntry;
386     ClientListEntry *pNextEntry;
387     ClientListEntry *pStackEntry;
388     String string = args;
389     int flags = STACK_NORMAL;
390 #ifdef WSM
391     WmWorkspaceData *pWS = ACTIVE_WS;
392 #endif /* WSM */
393
394     if (string)
395     {
396         /* process '-client' argument */
397         if (string[0] == '-')
398         {
399             string = &string[1];
400             string = (String) GetString ((unsigned char **) &string);
401
402             pStackEntry = NULL;
403             pNextEntry = ACTIVE_PSD->lastClient;
404             while (pNextEntry &&
405                    (pEntry = FindClientNameMatch (pNextEntry, False,
406                                                         string, F_GROUP_ALL)))
407             {
408                 pNextEntry = pEntry->prevSibling;
409 #ifdef WSM
410                 if (ClientInWorkspace (pWS, pEntry->pCD))
411                 {
412 #endif /* WSM */
413                 Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
414                 pStackEntry = pEntry;
415 #ifdef WSM
416                 }
417 #endif /* WSM */
418             }
419         }
420         /* process family stacking stuff */
421         else if (*string)
422         {
423             unsigned int  slen, len, index;
424
425             slen = strlen(args) - 2;            /* subtract '\n' and NULL */
426             for (index = 0; index < slen; string = &args[index+1])
427             {
428                 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
429                    break;
430                 len = strlen(string);
431                 if (!strcmp(string,"within"))
432                 {
433                     flags |= STACK_WITHIN_FAMILY;
434                 }
435                 else if (!strcmp(string,"freeFamily"))
436                 {
437                     flags |= STACK_FREE_FAMILY;
438                 }
439                 index += len;
440             }
441 #ifdef WSM
442             if (ClientInWorkspace (pWS, pCD))
443             {
444 #endif /* WSM */
445             Do_Lower (pCD, (ClientListEntry *) NULL, flags);
446 #ifdef WSM
447             }
448 #endif /* WSM */
449         }
450     }
451     else if (pCD)
452     {
453 #ifdef WSM
454             if (ClientInWorkspace (pWS, pCD))
455             {
456 #endif /* WSM */
457         Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
458 #ifdef WSM
459             }
460 #endif /* WSM */
461     }
462
463     /*
464      * If caused by button press, event may ALSO cause focus to be
465      * passed to this client - prepare to disable focusAutoRaise.
466      */
467     if (pCD && event && (event->type == ButtonPress))
468       pCD->focusAutoRaiseDisablePending = True;
469
470     wmGD.passButtonsCheck = False;
471     return (True);
472
473 } /* END OF FUNCTION F_Lower */
474
475
476 \f
477 /*************************************<->*************************************
478  *
479  *  Do_Lower (pCD, pStackEntry)
480  *
481  *
482  *  Description:
483  *  -----------
484  *  This is the window manager function handler for lowering the client window
485  *  so that it does not obscure any other window above the stack entry
486  *  window.
487  *
488  *
489  *  Inputs:
490  *  ------
491  *  pCD = pointer to the client data of the window (or icon) to be lowered.
492  * 
493  *  pStackEntry = pointer to client list entry for window that is to be 
494  *      below the lowered window (if NULL, window is lowered to the bottom
495  *      of the  stack).
496  *
497  *************************************<->***********************************/
498
499 void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
500 {
501     Boolean restackTransients;
502     ClientData *pcdLeader;
503     WmWorkspaceData *pWS = ACTIVE_WS;
504 #ifdef WSM
505     Boolean bLeaderRestacked;
506 #endif /* WSM */
507
508 #ifdef PANELIST
509     if (pCD->pECD)
510     {
511         /*
512          * Window has been reparented into the front panel. 
513          * Don't follow through on window stacking change.
514          */
515         return;
516     }
517     else 
518 #else /* PANELIST */
519 #endif /* PANELIST */
520 #ifdef WSM
521     if (ClientInWorkspace(pWS, pCD)  && 
522         (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
523     {
524         /* 
525          * Both clients are in the current workspace. Set
526          * client indices so that the access macros work.
527          */
528         SetClientWsIndex (pCD);
529         if (pStackEntry)
530         {
531             SetClientWsIndex (pStackEntry->pCD);
532         }
533     }
534     else
535     {
536         /*
537          * One or both of the clients are not in the current workspace
538          * Do nothing.
539          */
540         return;
541     }
542 #endif /* WSM */
543
544     pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
545
546     if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
547     {
548         /*
549          * If a dirtyStackEntry exists, return it to its original place 
550          * in the stack (for all stacking types)
551          */
552         if (dirtyStackEntry)
553         {
554             if (dirtyStackEntry->transientChildren ||
555                 dirtyStackEntry->transientLeader)
556                 RestackTransients (dirtyStackEntry);
557             dirtyStackEntry = NULL;
558             dirtyLeader = NULL;
559         }
560
561         /*
562          * Only restack the icon if it is not currently lowered.
563          */
564
565         if (pStackEntry)
566         {
567             if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
568             {
569                 StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
570                     pStackEntry);
571                 MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
572                     pStackEntry);
573             }
574         }
575         else
576         {
577             if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
578             {
579                 StackWindow (pWS, &pcdLeader->iconEntry, 
580                              False /*on bottom*/, (ClientListEntry *) NULL);
581                 MoveEntryInList (pWS, &pcdLeader->iconEntry, 
582                              False /*on bottom*/, (ClientListEntry *) NULL);
583             }
584         }
585     }
586     else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
587     {
588 #ifdef WSM
589         /*
590          * Handle restacking of primary/secondary windows
591          * within the transient window tree.
592          */
593         bLeaderRestacked = False;
594         if ((pcdLeader->transientChildren) &&
595             (!pcdLeader->secondariesOnTop) &&
596             (!wmGD.bSuspendSecondaryRestack))
597         {
598             if (pCD == pcdLeader)
599             {
600                 /*
601                  * Lower requested on the leader itself, insure it's
602                  * at the bottom.
603                  */
604                 bLeaderRestacked = BumpPrimaryToBottom (pcdLeader);
605             }
606             else if (pCD->transientChildren)
607             {
608                 /*
609                  * Lower requested on the leader of a subtree. Insure
610                  * that this subtree leader is at the bottom of the
611                  * subtree.
612                  */
613                 bLeaderRestacked = BumpPrimaryToBottom (pCD);
614             }
615             else if (pCD->transientLeader)
616             {
617                 ClientData *pcdLdr;
618
619                 /*
620                  * Lower requested on a transient. Insure all the
621                  * subtree leaders up to the top are at the bottom
622                  * of their respective transient subtrees.
623                  */
624                 for (pcdLdr = pCD->transientLeader;
625                         pcdLdr; 
626                                 pcdLdr = pcdLdr->transientLeader)
627                 {
628                     bLeaderRestacked |= BumpPrimaryToBottom (pcdLdr);
629                 }
630             }
631
632         }
633 #endif /* WSM */
634         /*
635          * If this is a transient window then put it below its
636          * sibling transient windows.
637          */
638
639         restackTransients = False;
640         if (pCD->transientLeader)
641         {
642
643             /*
644              * If freeFamily stacking, then put dirty transient window
645              * (if any) back in place before force lowering current window
646              * to the bottom of the global window stack.  Then return.
647              */
648
649             if (flags & STACK_FREE_FAMILY)
650             {
651                 /* Restore dirty transient if not current window. */
652                 if ((dirtyStackEntry) &&
653                     (dirtyStackEntry != pCD))
654                 {
655                     RestackTransients (dirtyStackEntry);
656                 }
657
658                 dirtyStackEntry = pCD;
659                 dirtyLeader = pcdLeader;
660
661                 ForceLowerWindow (pCD);
662                 return;
663             }
664
665             /*
666              * Reach here only if NOT doing a f.lower freeFamily (see
667              * return; statement above).  Put current transient below
668              * its sibling transient windows.
669              */
670             restackTransients = PutTransientBelowSiblings (pCD);
671         }
672
673         /*
674          * If doing a regular f.lower and you have a dirty window, then
675          * clean up dirty transient window.
676          */
677
678         if (dirtyStackEntry)
679         {
680             /* 
681              * If lowering a window in the same family as the dirty
682              * transient window, then just restack before lowering.
683              * Else, restore the dirty transient in place before
684              * lowering the current window.  Clear dirtyStack.
685              */
686             if (dirtyLeader == pcdLeader)
687             {
688                 restackTransients = True;
689             }
690             else
691             {
692                 RestackTransients (dirtyStackEntry);
693             }
694
695             dirtyStackEntry = NULL;
696         }
697
698         /*
699          * Only restack the window or transient window tree if it is
700          * not currently lowered and the window is not a system
701          * modal window.
702          */
703
704         if (pStackEntry)
705         {
706             if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
707                 !(wmGD.systemModalActive &&
708                   (pcdLeader == wmGD.systemModalClient)))
709             {
710                 StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
711                     pStackEntry);
712                 MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
713                     pStackEntry);
714             }
715 #ifdef WSM
716             else if ((restackTransients) || (bLeaderRestacked))
717 #else /* WSM */
718             else if (restackTransients)
719 #endif /* WSM */
720             {
721                 RestackTransients (pCD);
722             }
723         }
724         else
725         {
726             if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
727                 !(wmGD.systemModalActive &&
728                   (pcdLeader == wmGD.systemModalClient)) &&
729                 !(flags & STACK_WITHIN_FAMILY))
730             {
731                 StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
732                     (ClientListEntry *) NULL);
733                 MoveEntryInList (pWS, &pcdLeader->clientEntry,
734                     False /*on bottom*/, (ClientListEntry *) NULL);
735             }
736 #ifdef WSM
737             else if ((restackTransients) || (bLeaderRestacked))
738 #else /* WSM */
739             else if (restackTransients)
740 #endif /* WSM */
741             {
742                 RestackTransients (pCD);
743             }
744         }
745     }
746
747 } /* END OF FUNCTION Do_Lower */
748
749
750 \f
751 /*************************************<->*************************************
752  *
753  *  F_CircleDown (args, pCD, event)
754  *
755  *
756  *  Description:
757  *  -----------
758  *  This is the window manager function handler for moving the client window
759  *  on top of stack to the bottom.
760  *
761  *
762  *  Inputs:
763  *  ------
764  *  args = function arguments (specified in .mwmrc file)
765  *
766  *  pCD = pointer to the client data for the client window to which the
767  *        function is to be applied
768  *
769  *  event = X event that invoked the function (key, button, or menu/NULL)
770  *
771  *
772  *  Outputs:
773  *  -------
774  *  RETURN = if True then further button binding/function processing can
775  *           be done for the event that caused this function to be called.
776  *
777  *************************************<->***********************************/
778
779 Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
780 {
781     unsigned long types;
782     unsigned long windowType;
783     ClientListEntry *pNextEntry;
784     ClientData *pcdNext;
785
786
787     /*
788      * Go down through the client list looking for a window of an
789      * appropriate type that is obscuring lower windows.
790      */
791
792     types = (unsigned long)args;
793     pNextEntry = ACTIVE_PSD->clientList;
794     while (pNextEntry)
795     {
796         /*
797          * Only check out the window if it is onscreen.
798          */
799
800         pcdNext = pNextEntry->pCD;
801         if (((pNextEntry->type == NORMAL_STATE) &&
802              (pcdNext->clientState != MINIMIZED_STATE)) ||
803             ((pNextEntry->type == MINIMIZED_STATE) &&
804              (pcdNext->clientState == MINIMIZED_STATE)))
805         {
806             if (pcdNext->clientState == MINIMIZED_STATE)
807             {
808                 windowType = F_GROUP_ICON;
809             }
810             else
811             {
812                 windowType = F_GROUP_WINDOW;
813                 if (pcdNext->transientLeader || pcdNext->transientChildren)
814                 {
815                     windowType |= F_GROUP_TRANSIENT;
816                 }
817             }
818             if (types & windowType)
819             {
820                 if (CheckIfClientObscuringAny (pcdNext))
821                 {
822                     /*
823                      * This window (or window tree) is obscuring another window
824                      * on the screen.  Lower the window.
825                      */
826
827 #ifdef WSM
828                     wmGD.bSuspendSecondaryRestack = True;
829 #endif /* WSM */
830                     F_Lower (NULL, pcdNext, (XEvent *) NULL);
831 #ifdef WSM
832                     wmGD.bSuspendSecondaryRestack = False;
833 #endif /* WSM */
834                     break;
835                 }
836             }
837         }
838         pNextEntry = pNextEntry->nextSibling;
839     }
840
841     return (True);
842
843 } /* END OF FUNCTION F_Circle_Down */
844
845
846 \f
847 /*************************************<->*************************************
848  *
849  *  F_Circle_Up (args, pCD, event)
850  *
851  *
852  *  Description:
853  *  -----------
854  *  This is the window manager function handler for moving the client window
855  *  on the bottom of the stack to the top.
856  *
857  *
858  *  Inputs:
859  *  ------
860  *  args = function arguments (specified in .mwmrc file)
861  *
862  *  pCD = pointer to the client data for the client window to which the
863  *        function is to be applied
864  *
865  *  event = X event that invoked the function (key, button, or menu/NULL)
866  *
867  *
868  *  Outputs:
869  *  -------
870  *  RETURN = if True then further button binding/function processing can
871  *           be done for the event that caused this function to be called.
872  *
873  *************************************<->***********************************/
874
875 Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
876 {
877     unsigned long types;
878     unsigned long windowType;
879     ClientListEntry *pNextEntry;
880     ClientData *pcdNext;
881
882
883     /*
884      * Go up through the client list looking for a window of an
885      * appropriate type that is obscured by higher windows.
886      */
887
888     types = (unsigned long)args;
889     pNextEntry = ACTIVE_PSD->lastClient;
890     while (pNextEntry)
891     {
892         /*
893          * Only check out the window if it is onscreen.
894          */
895
896         pcdNext = pNextEntry->pCD;
897         if (((pNextEntry->type == NORMAL_STATE) &&
898              (pcdNext->clientState != MINIMIZED_STATE)) ||
899             ((pNextEntry->type == MINIMIZED_STATE) &&
900              (pcdNext->clientState == MINIMIZED_STATE)))
901         {
902             if (pcdNext->clientState == MINIMIZED_STATE)
903             {
904                 windowType = F_GROUP_ICON;
905             }
906             else
907             {
908                 windowType = F_GROUP_WINDOW;
909                 if (pcdNext->transientLeader || pcdNext->transientChildren)
910                 {
911                     windowType |= F_GROUP_TRANSIENT;
912                 }
913             }
914             if (types & windowType)
915             {
916                 if (CheckIfClientObscuredByAny (pcdNext))
917                 {
918                     /*
919                      * This window (or window tree) is obscured by another
920                      * window on the screen.  Raise the window.
921                      */
922
923 #ifdef WSM
924                     wmGD.bSuspendSecondaryRestack = True;
925 #endif /* WSM */
926                     F_Raise (NULL, pcdNext, (XEvent *) NULL);
927 #ifdef WSM
928                     wmGD.bSuspendSecondaryRestack = False;
929 #endif /* WSM */
930                     break;
931                 }
932             }
933         }
934         pNextEntry = pNextEntry->prevSibling;
935     }
936
937     return (True);
938
939
940 } /* END OF FUNCTION F_Circle_Up */
941
942
943 \f
944 /*************************************<->*************************************
945  *
946  *  F_Focus_Color (args, pCD, event)
947  *
948  *
949  *  Description:
950  *  -----------
951  *  This is the window manager function handler for setting the colormap
952  *  focus to a client window or reinstalling the default colormap.
953  *
954  *************************************<->***********************************/
955
956 Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
957 {
958
959     if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
960     {
961         if (pCD)
962         {
963             /*
964              * The window selected for the colormap focus is a top-level client
965              * window.  If there are subwindow colormaps then determine if the
966              * selection was in one of the subwindows.
967              */
968
969             if (pCD->clientState == MINIMIZED_STATE)
970             {
971                 /* !!! colormap for client supplied icon window !!! */
972                 pCD = NULL;
973             }
974         }
975
976         SetColormapFocus (ACTIVE_PSD, pCD);
977     }
978
979     return (True);
980
981 } /* END OF FUNCTION F_Focus_Color */
982
983
984 \f
985 /*************************************<->*************************************
986  *
987  *  F_Exec (args, pCD, event)
988  *
989  *
990  *  Description:
991  *  -----------
992  *  This is the window manager function handler for executing a command
993  *  (with /bin/sh).
994  *
995  *************************************<->***********************************/
996
997 Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
998 {
999     int   pid;
1000 #ifndef WSM
1001     int   status;
1002     int   w;
1003     void (*intStat) ();
1004     void (*quitStat) ();
1005 #endif /* WSM */
1006     char *shell;
1007     char *shellname;
1008
1009
1010     /* make sure the f.exec command runs on the right display. */
1011     if (wmGD.pActiveSD->displayString)
1012       {
1013         putenv(wmGD.pActiveSD->displayString);
1014       }
1015     
1016 #ifdef PANELIST
1017     if (wmGD.dtSD)
1018     {
1019         /*
1020          * Start the busy indicator, waiting for a pushbutton window
1021          * for the given duration
1022          */
1023        WmFrontPanelSetBusy (True);
1024     }
1025 #endif /* PANELIST */
1026
1027     /*
1028      * Fork a process to exec a shell to run the specified command:
1029      */
1030
1031 #ifdef PORT_NOVFORK
1032     if ((pid = fork ()) == 0)
1033 #else
1034     if ((pid = vfork ()) == 0)
1035 #endif
1036     {
1037
1038 #ifndef NO_SETPGRP
1039 #if defined(SVR4) || defined(__OSF1__) || defined(__osf__) || defined(linux)
1040         setsid();
1041 #else
1042 #ifdef SYSV
1043         setpgrp();
1044 #else
1045         int tpid;
1046
1047         tpid = getpid();
1048         setpgrp(tpid, tpid);
1049 #endif /* SYSV */
1050 #endif /* SVR4 */
1051 #endif /* NO_SETPGRP */
1052 #ifdef WSM 
1053         /*
1054          * Clean up window manager resources.
1055          * The X file descriptor should be automatically closed.
1056          */
1057
1058         /*
1059          * Fix up signal handling.
1060          */
1061         RestoreDefaultSignalHandlers ();
1062
1063         /*
1064          * Fix up the child application's environment NOT to
1065          * inherit the XFILESEARCHPATH, XBMLANGPATH, NLSPATH, etc.
1066          * used by dtwm.
1067          */
1068          _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
1069
1070          CLOSE_FILES_ON_EXEC();
1071 #endif /* WSM */
1072
1073         /*
1074          * Exec the command using $MWMSHELL if set or 
1075          * $SHELL if set and $MWMSHELL not set or sh.
1076          */
1077
1078         if (((shell = getenv ("MWMSHELL")) != NULL) ||
1079             ((shell = getenv ("SHELL")) != NULL))
1080
1081         {
1082             shellname = strrchr (shell, '/');
1083             if (shellname == NULL)
1084             {
1085                 /*
1086                 If the shell pathname obtained from SHELL or MWMSHELL does not
1087                 have a "/" in the path and if the user expects this shell to be
1088                 obtained using the PATH variable rather than the current
1089                 directory, then we must call execlp and not execl
1090                 */
1091                 shellname = shell;
1092                 execlp (shell, shellname, "-c", args, NULL);
1093             }
1094             else
1095             {
1096                 shellname++;
1097                 execl (shell, shellname, "-c", args, NULL);
1098             }
1099         }
1100
1101         /*
1102          * There is no SHELL environment variable or the first execl failed.
1103          * Try /bin/sh .
1104          */
1105 #ifdef SVR4
1106         execl ("/usr/bin/sh", "sh", "-c", args, NULL);
1107 #else
1108         execl ("/bin/sh", "sh", "-c", args, NULL);
1109 #endif
1110
1111
1112         /*
1113          * Error - command could not be exec'ed.
1114          */
1115
1116         _exit (127);
1117     }
1118
1119     else if (pid == -1)
1120       return(True);
1121
1122     /*
1123      * Have the window manager wait for the shell to complete.
1124      */
1125
1126 #ifndef WSM
1127     intStat = (void (*)())signal (SIGINT, SIG_IGN);
1128     quitStat = (void (*)())signal (SIGQUIT, SIG_IGN);
1129 #endif /* WSM */
1130
1131 #ifdef WSM
1132     /*
1133      * Don't need to wait because WSM sets SIGCLD handler
1134      */
1135 #else /* WSM */
1136     while ((w = wait (&status)) != pid && (w != -1));
1137
1138     if (w == -1)
1139     {
1140         status = -1;
1141     }
1142 #endif /* WSM */
1143
1144 #ifndef WSM
1145     signal (SIGINT, intStat);
1146     signal (SIGQUIT, quitStat);
1147 #endif /* WSM */
1148
1149     /*
1150      * Restore original DISPLAY environment variable value
1151      * so a restart will start on the same screen
1152      */
1153
1154     if(wmGD.pActiveSD->displayString &&
1155        wmGD.displayString)
1156     {
1157         putenv(wmGD.displayString);
1158     }
1159
1160
1161     return (True);
1162
1163
1164 } /* END OF FUNCTION F_Exec */
1165
1166
1167 \f
1168 /*************************************<->*************************************
1169  *
1170  *  F_Quit_Mwm (args, pCD, event)
1171  *
1172  *
1173  *  Description:
1174  *  -----------
1175  *  This is the window manager function handler for terminating the window
1176  *  manager.
1177  *
1178  *************************************<->***********************************/
1179
1180 Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
1181 {
1182     if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
1183     {
1184         ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
1185     }
1186     else
1187     {
1188         Do_Quit_Mwm(False);
1189     }
1190     
1191     return (False);
1192
1193 } /* END OF FUNCTION F_Quit_Mwm */
1194
1195
1196 \f
1197 /*************************************<->*************************************
1198  *
1199  *  Do_Quit_Mwm (diedOnRestart)
1200  *
1201  *
1202  *  Description:
1203  *  -----------
1204  *  Callback to do the f.quit_mwm function.
1205  *
1206  *************************************<->***********************************/
1207
1208 void Do_Quit_Mwm (Boolean diedOnRestart)
1209 {
1210     int scr;
1211     ClientListEntry *pNextEntry;
1212
1213
1214     /*
1215      * Close the X connection to get all the X resources cleaned up.
1216      * !!! maybe windows should be reparented / rebordered  before closing? !!!
1217      * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
1218      */
1219
1220
1221     if (DISPLAY)
1222     {
1223         XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
1224         for (scr = 0; scr < wmGD.numScreens; scr++)
1225         {
1226             if (wmGD.Screens[scr].managed)
1227             {
1228 #ifdef WSM
1229                 SaveResources(&wmGD.Screens[scr]);
1230 #endif /* WSM */
1231                 pNextEntry = wmGD.Screens[scr].lastClient;
1232                 while (pNextEntry)
1233                 {
1234                     if (pNextEntry->type == NORMAL_STATE)
1235                     {
1236                         if (!(pNextEntry->pCD->clientFlags & 
1237                               CLIENT_WM_CLIENTS))
1238                         {
1239                             ReBorderClient (pNextEntry->pCD, diedOnRestart);
1240                         }
1241                     }
1242                     pNextEntry = pNextEntry->prevSibling;
1243                 }
1244 #if defined(PANELIST)
1245                 UnParentControls (&wmGD.Screens[scr], False);
1246 #endif /* PANELIST */
1247
1248 #ifndef WSM
1249                 XDeleteProperty(DISPLAY, wmGD.Screens[scr].rootWindow,
1250                                 wmGD.xa_MWM_INFO);
1251 #endif /* WSM */
1252             }
1253         }
1254 #ifdef WSM
1255         /* shut down the messaging connection */
1256         dtCloseIPC();
1257 #endif /* WSM */
1258         ResignFromSM();
1259         XSync (DISPLAY, False);
1260         XCloseDisplay (DISPLAY);
1261     }
1262     
1263     if(diedOnRestart)
1264     {
1265         exit (WM_ERROR_EXIT_VALUE);
1266     }
1267     else
1268     {
1269         exit (0);
1270     }
1271
1272 } /* END OF FUNCTION Do_Quit_Mwm */
1273
1274 \f
1275 /*************************************<->*************************************
1276  *
1277  *  ReBorderClient (pCD, reMapClient)
1278  *
1279  *
1280  *  Description:
1281  *  -----------
1282  *  Restores X border for client window and reparents the
1283  *  window back to the root.
1284  *
1285  *
1286  *  Inputs:
1287  *  -------
1288  *  pCD = pointer to the client data for the window to be re-bordered.
1289  *
1290  *************************************<->***********************************/
1291
1292 void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1293 {
1294     int x, y;
1295     int xoff, yoff;
1296     XWindowChanges windowChanges;
1297
1298     while (pCD)
1299     {
1300         if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1301             (!(reMapClient)))
1302         {
1303             XUnmapWindow (DISPLAY, pCD->iconWindow);
1304 #ifdef WSM
1305             XReparentWindow (DISPLAY, pCD->iconWindow, 
1306                 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX, 
1307                 pCD->pWsList->iconY);
1308 #else /* WSM */
1309             XReparentWindow (DISPLAY, pCD->iconWindow, 
1310                 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
1311 #endif /* WSM */
1312         }
1313
1314         if (!(reMapClient))
1315         {
1316             if (pCD->maxConfig)
1317             {
1318                 x = pCD->maxX;
1319                 y = pCD->maxY;
1320             }
1321             else
1322             {
1323                 if(wmGD.positionIsFrame)
1324                 {
1325                     CalculateGravityOffset (pCD, &xoff, &yoff);
1326                     x = pCD->clientX - xoff;
1327                     y = pCD->clientY - yoff;
1328                 }
1329                 else
1330                 {
1331                     x = pCD->clientX;
1332                     y = pCD->clientY;
1333                 }
1334             }
1335             XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1336             XReparentWindow (DISPLAY, pCD->client, 
1337                              ROOT_FOR_CLIENT(pCD), x, y);
1338         }
1339         else
1340         {
1341             XMapWindow(wmGD.display, pCD->client);
1342         }
1343
1344         if (pCD->transientChildren)
1345         {
1346             ReBorderClient (pCD->transientChildren, reMapClient);
1347         }
1348
1349         if (!(reMapClient))
1350         {
1351             /*
1352              * restore X border
1353              */
1354             windowChanges.x = x;
1355             windowChanges.y = y;
1356             windowChanges.border_width = pCD->xBorderWidth;
1357             XConfigureWindow (DISPLAY, pCD->client, 
1358                               CWBorderWidth | CWX | CWY, &windowChanges);
1359         }
1360
1361         if (pCD->transientLeader)
1362         {
1363             pCD = pCD->transientSiblings;
1364         }
1365         else
1366         {
1367             pCD = NULL;
1368         }
1369     }
1370
1371 } /* END OF FUNCTION ReBorderClient */
1372
1373
1374 \f
1375 /*************************************<->*************************************
1376  *
1377  *  F_Focus_Key (args, pCD, event)
1378  *
1379  *
1380  *  Description:
1381  *  -----------
1382  *  This is the window manager function handler for setting the keyboard
1383  *  focus to a particular client window.
1384  *
1385  *
1386  *  Inputs:
1387  *  ------
1388  *  args = (immediate value) focus flags
1389  *
1390  *  pCD = pointer to the client data
1391  *
1392  *  event = X event that invoked the function (key, button, or menu/NULL)
1393  *
1394  *************************************<->***********************************/
1395
1396 Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1397 {
1398     long focusFlags = (long)args;
1399
1400
1401     if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1402     {
1403         Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1404             (focusFlags | ALWAYS_SET_FOCUS));
1405     }
1406
1407     return (True);
1408
1409 } /* END OF FUNCTION F_Focus_Key */
1410
1411 \f
1412 /*************************************<->*************************************
1413  *
1414  *  FindSomeReasonableClient
1415  *
1416  *  Description:
1417  *  -----------
1418  *  Find a client, any client to set the focus to, return client or NULL.
1419  *  This code is ripped off from AutoResetKeyFocus(). 
1420  *  
1421  *************************************<->***********************************/
1422
1423 static Window FindSomeReasonableClient(void)
1424 {
1425    ClientData *pcdNoFocus=NULL;
1426
1427     ClientListEntry *pNextEntry;
1428     ClientData *pCD;
1429     ClientData *pcdLastFocus = (ClientData *) NULL;
1430     ClientData *pcdFocus;
1431     Window focusWindow = (Window) NULL;
1432
1433     /*
1434      * Scan through the list of clients to find a window to get the focus.
1435      */
1436
1437     pNextEntry = ACTIVE_PSD->clientList;
1438
1439     while (pNextEntry)
1440     {
1441         pCD = pNextEntry->pCD;
1442         if (!wmGD.systemModalActive ||
1443             (wmGD.systemModalClient == pCD))
1444         {
1445             if ((pNextEntry->type != MINIMIZED_STATE) &&
1446                 (pCD->clientState != MINIMIZED_STATE) &&
1447 #ifdef WSM
1448                 (ClientInWorkspace (ACTIVE_WS, pCD)) &&
1449 #endif /* WSM */
1450                 (pCD != pcdNoFocus))
1451             {
1452                 if (pCD->transientChildren)
1453                 {
1454                     pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1455                 }
1456                 else
1457                 {
1458                     pcdFocus = pCD;
1459                 }
1460                 if (pcdFocus &&
1461                     ((pcdLastFocus == NULL) ||
1462                      (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1463                 {
1464                     pcdLastFocus = pcdFocus;
1465                 }
1466             }
1467         }
1468         pNextEntry = pNextEntry->nextSibling;
1469     }
1470
1471     /*
1472      * Set the focus window if one is found
1473      */
1474
1475 #ifdef WSM
1476     if (pcdLastFocus && 
1477         ClientInWorkspace (ACTIVE_WS, pcdLastFocus))
1478 #else /* WSM */
1479     if (pcdLastFocus)
1480 #endif /* WSM */
1481       focusWindow = pcdLastFocus->client;
1482
1483     /*
1484      * If a client window could not be found, then just put focus
1485      * on any icon.
1486      */
1487
1488     if (focusWindow == (Window) NULL)
1489     {
1490         pNextEntry = ACTIVE_PSD->clientList;
1491
1492         while (pNextEntry)
1493         {
1494             pCD = pNextEntry->pCD;
1495
1496 #ifdef WSM
1497           if (ClientInWorkspace (ACTIVE_WS, pCD))
1498           {
1499 #endif /* WSM */
1500             if ((pNextEntry->type == MINIMIZED_STATE) ||
1501                 (pCD->clientState == MINIMIZED_STATE))
1502             {
1503                 focusWindow = ICON_FRAME_WIN(pCD);
1504                 break;
1505             }
1506 #ifdef WSM
1507           }
1508 #endif /* WSM */
1509             pNextEntry = pNextEntry->nextSibling;
1510         }
1511     }
1512
1513     return (focusWindow);
1514
1515 } /* END OF FUNCTION FindSomeReasonableClient */
1516
1517
1518
1519 \f
1520 /*************************************<->*************************************
1521  *
1522  *  Do_Focus_Key (pCD, focusTime, flags)
1523  *
1524  *
1525  *  Description:
1526  *  -----------
1527  *  This function is used to set the focus to a window.  The focus indication
1528  *  is not changed until the FocusIn event is received.
1529  *
1530  *
1531  *  Inputs:
1532  *  ------
1533  *  pCD = pointer to the client data
1534  *
1535  *  focusTime = focus change time
1536  *
1537  *  flags = wm focus change flags
1538  *
1539  *************************************<->***********************************/
1540
1541 void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1542 {
1543     ClientData *pcdFocus;
1544     Window focusWindow;
1545
1546
1547     /* Clear the replay flag */
1548     wmGD.replayEnterEvent = False;
1549
1550     pcdFocus = pCD;
1551 #ifdef WSM
1552     /* 
1553      * Make sure the client is in the current workspace
1554      */
1555     if ((pCD) &&
1556         (ClientInWorkspace (ACTIVE_WS, pCD)))
1557 #else /* WSM */
1558     if (pCD)
1559 #endif /* WSM */
1560     {
1561         if (pCD->clientState == MINIMIZED_STATE)
1562         {
1563             focusWindow = ICON_FRAME_WIN(pCD);
1564         }
1565         else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1566         {
1567             /*
1568              * Set the keyboard focus to the indicated client window.
1569              * If the window has an application modal subordinate then
1570              * set the input focus to that window if the focus isn't
1571              * already owned by a subordinate.
1572              */
1573
1574             if (IS_APP_MODALIZED(pCD))
1575             {
1576                 ClientData *pcdFocusLeader,*currFocusLeader;
1577
1578                 /*
1579                  * Handle case where a modal window exists when Mwm starts up.
1580                  * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1581                  */
1582
1583                 if (wmGD.keyboardFocus)
1584                 {
1585                     currFocusLeader = wmGD.keyboardFocus->transientLeader;
1586                 }
1587                 else
1588                 {
1589                     currFocusLeader = (ClientData *) NULL;
1590                 }
1591
1592                 /*
1593                  * Find focus leader for pCD
1594                  */
1595
1596                 pcdFocusLeader = pCD;
1597                 while (pcdFocusLeader->transientLeader &&
1598                        (pcdFocusLeader != currFocusLeader))
1599                 {
1600                     pcdFocusLeader = pcdFocusLeader->transientLeader;
1601                 }
1602
1603                 if (pcdFocusLeader == currFocusLeader)
1604                 {
1605                     pcdFocus = wmGD.keyboardFocus;
1606                     flags = 0;
1607                 }
1608                 else
1609                 {
1610                     pcdFocus = FindTransientFocus (pcdFocusLeader);
1611                 }
1612             }
1613
1614             /*
1615              * !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  
1616              * We must look at why FindTransientFocus is
1617              * returning a NULL pcd.  The old code simply set
1618              *  focusWindow = pcdFocus->client;
1619              * !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  !!!  
1620              *
1621              * 11/26/96 rswiston - In tracking down CDExc22816, we
1622              * discovered that pCD could get tricked into thinking
1623              * it had modal transients when in fact all its transients
1624              * had been withdrawn (fixed in WithdrawTransientChildren()).
1625              * As a result, FindTransientFocus() returns wmGD.keyboardFocus;
1626              * if nobody has the focus, FindTransientFocus() returns NULL.
1627              */
1628             if (pcdFocus)
1629             {
1630                 focusWindow = pcdFocus->client;
1631             }
1632             else
1633             {
1634                 focusWindow = (wmGD.keyboardFocus) ?
1635                     wmGD.keyboardFocus->client : ACTIVE_PSD->wmWorkspaceWin;
1636             }
1637         }
1638         else
1639         {
1640             /*
1641              * If the focus policy is "pointer" don't set the focus to a
1642              * window if it has an application modal subordinate.
1643              */
1644
1645             if (IS_APP_MODALIZED(pCD))
1646             {
1647                 pcdFocus = NULL;
1648                 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1649
1650                 /* Replay this later when the modal window is removed. */
1651                 wmGD.replayEnterEvent = True;
1652             }
1653             else
1654             {
1655                 focusWindow = pcdFocus->client;
1656             }
1657         }
1658     }
1659     else
1660     {
1661         /*
1662          * Set up the default (non client specific) keyboard input focus.
1663          */
1664
1665         if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1666         {
1667             focusWindow = PointerRoot;
1668         }
1669         else
1670         {
1671             /*
1672              * The WORKSPACE_IF_NULL flag is used to prevent client
1673              * windows from flashing when deiconifying a client.
1674              */
1675
1676             if (WORKSPACE_IF_NULL & flags)
1677             {
1678                 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1679             }
1680             else
1681             {
1682                 /* find some reasonable client so that focus is not lost */
1683
1684                 focusWindow = FindSomeReasonableClient();
1685                 if (focusWindow == (Window)NULL)
1686                 {
1687                     focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1688                 }
1689             }
1690         }
1691     }
1692
1693     if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1694     {
1695         if (pcdFocus)
1696         {
1697             /*
1698              * Set the focus and/or send a take focus client message.  This
1699              * is not done if a client area button press was done to set
1700              * set the focus and the window is a globally active input
1701              * style window (See ICCCM).
1702              */
1703
1704             if ( (flags & CLIENT_AREA_FOCUS)                           &&
1705                  (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS)    &&
1706                 ! pcdFocus->inputFocusModel                            &&
1707                  (pcdFocus == pCD)                                     &&
1708                  (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
1709                 !(pcdFocus->clientState == MINIMIZED_STATE)
1710                )
1711             {
1712               /*
1713                * We get here if:
1714                * 1. User clicked in the client area   AND
1715                * 2. Input model is Globally Active    AND
1716                * 3. Keyboard focus policy is explicit
1717                */
1718
1719               /* this window has WM_TAKE_FOCUS set and InputField false. */
1720               /* just send a message.                                    */
1721               SendClientMsg (pcdFocus->client, 
1722                              (long) wmGD.xa_WM_PROTOCOLS,
1723                              (long) wmGD.xa_WM_TAKE_FOCUS, 
1724                              focusTime, NULL, 0);
1725             }
1726             else
1727             {
1728                 if ((pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1729                     !(pcdFocus->clientState == MINIMIZED_STATE))
1730                 {
1731                   /*
1732                    * Locally Active Input Model - Send a take focus message to the client.
1733                    */
1734
1735                   SendClientMsg (pcdFocus->client, 
1736                                  (long) wmGD.xa_WM_PROTOCOLS,
1737                                  (long) wmGD.xa_WM_TAKE_FOCUS, 
1738                                  focusTime, NULL, 0);
1739                 }
1740
1741                 /*
1742                  * Don't set the input focus if the window has input_field set
1743                  * to False or has expressed an interest in WM_TAKE_FOCUS
1744                  * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1745                  * and the user click in the client area.  If the user clicks
1746                  * on the titlebar or traverses to this window via f.next_key,
1747                  * set the focus so that the user can access the window menu
1748                  * and accelerators.
1749                  */
1750
1751                 if ( wmGD.enforceKeyFocus       ||  /* res - default == True. */
1752                      (flags & ALWAYS_SET_FOCUS) ||
1753                     !(flags & CLIENT_AREA_FOCUS)||  /* clicked on frame? */
1754                      pcdFocus->inputFocusModel  ||  /* Pass.|Glob. Active */
1755                      (pcdFocus->clientState == MINIMIZED_STATE)
1756                    )
1757                 {
1758                   if ( !(flags & CLIENT_AREA_FOCUS) &&
1759                        !pcdFocus->inputFocusModel &&
1760                        !(pcdFocus->clientState == MINIMIZED_STATE))
1761                   {
1762                    /* the window doesn't want the focus - set it to the frame */
1763                    /* user clicked on the frame but we don't want the focus */
1764                    /* set it to the client's frame */
1765                    XSetInputFocus (DISPLAY, pcdFocus->clientBaseWin,
1766                                 RevertToPointerRoot, focusTime);
1767                   }
1768                   else if ( !(flags & CLIENT_AREA_FOCUS)                   &&
1769                        !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1770                         pcdFocus->inputFocusModel
1771                      )
1772                   {
1773                     XSetInputFocus (DISPLAY, focusWindow,
1774                                     RevertToPointerRoot, focusTime);
1775                   }
1776                   else
1777                   {
1778                     XSetInputFocus (DISPLAY, focusWindow,
1779                                       RevertToParent, focusTime);
1780                   }
1781                 }
1782                 else
1783                 {
1784                   /*
1785                    * We've decided that the window shouldn't get the focus,
1786                    * so don't change the focus.
1787                    */
1788                   pcdFocus = wmGD.nextKeyboardFocus;
1789                 }
1790             }
1791         }
1792         else
1793         {
1794             XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1795                                         focusTime);
1796         }
1797
1798         wmGD.nextKeyboardFocus = pcdFocus;
1799     }
1800
1801
1802 } /* END OF FUNCTION Do_Focus_Key */
1803
1804
1805 #ifdef WSM
1806 \f
1807 /***********************<->*************************************
1808  *
1809  *  F_Goto_Workspace (args, pCD, event)
1810  *
1811  *  Description:
1812  *  -----------
1813  *  This is the window manager function handler for switching
1814  *  to another workspace by name.
1815  *
1816  *  Inputs:
1817  *  ------
1818  *  args = action function and arguments
1819  *
1820  *  pCD = pointer to the ClientData
1821  *
1822  *  event = X event that invoked the function (key, button, or menu/NULL)
1823  *
1824  *  Outputs:
1825  *  -------
1826  *  Always False
1827  *
1828  *  Comments:
1829  *  -------
1830  ******************************<->***********************************/
1831 Boolean
1832 F_Goto_Workspace (String args, ClientData *pCD, XEvent *event)
1833 {
1834     WmScreenData *pSD = ACTIVE_PSD;
1835     int iwsx;
1836     XmString xms;
1837
1838     /* 
1839      * Compare argument against both resource name 
1840      * and workspace title, take the first match.
1841      */
1842     xms = XmStringCreate (args, XmFONTLIST_DEFAULT_TAG);
1843     for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1844     {
1845         if (!strcmp(pSD->pWS[iwsx].name, args) ||
1846             XmStringCompare (xms, pSD->pWS[iwsx].title))
1847         {
1848             break;
1849         }
1850     }
1851
1852     XmStringFree (xms);
1853
1854     /* check bounds */
1855     if (iwsx >= pSD->numWorkspaces)
1856     {
1857         Warning (((char *)GETMESSAGE(26, 4, 
1858                 "Invalid workspace name specified for f.goto_workspace")));
1859     }
1860     else
1861     {
1862         ChangeToWorkspace (&pSD->pWS[iwsx]);
1863
1864     }
1865
1866     return (False);
1867 }  /* END OF FUNCTION F_Goto_Workspace */
1868
1869 #endif /* WSM */
1870
1871 #ifdef WSM
1872 \f
1873 /******************************<->*************************************
1874  *
1875  *  Boolean F_Help (String args, ClientData *pCD, XEvent *event)
1876  *
1877  *  Description:
1878  *  -----------
1879  *  Invoke help on the workspace manager
1880  *
1881  *  Inputs:
1882  *  ------
1883  *  args - incoming values
1884  *  pCD  - associated client data structure
1885  *  event - what triggered this call
1886  * 
1887  *  Outputs:
1888  *  -------
1889  *  Return - True if the call occurs; false otherwise.
1890  *
1891  *  Comments:
1892  *  --------
1893  *
1894  ******************************<->***********************************/
1895 Boolean
1896 F_Help (String args, ClientData *pCD, XEvent *event)
1897 {
1898 #ifdef PANELIST
1899     Boolean rval;
1900
1901     rval = WmDtHelp(args);
1902     return (rval);
1903 #endif /* PANELIST */    
1904     
1905
1906 }  /* END OF FUNCTION F_Help */
1907
1908 \f
1909 /******************************<->*************************************
1910  *
1911  *  Boolean F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1912  *
1913  *  Description:
1914  *  -----------
1915  *  Invoke item help on the frontpanel
1916  *
1917  *  Inputs:
1918  *  ------
1919  *  args - NULL
1920  *  pCD  - associated client data structure ??
1921  *  event - what triggered this call
1922  * 
1923  *  Outputs:
1924  *  -------
1925  *  Return - True if the call occurs; false otherwise.
1926  *
1927  *  Comments:
1928  *  --------
1929  *
1930  ******************************<->***********************************/
1931 Boolean
1932 F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1933 {
1934 #ifdef PANELIST
1935     /*
1936      * Help mode event processing interferes
1937      * with slide up windows. Don't continue
1938      * if windows are sliding.
1939      */
1940     if (wmGD.iSlideUpsInProgress == 0)
1941     {
1942         (void) WmDtHelpMode();
1943     }
1944     return (False);
1945 #endif /* PANELIST */    
1946
1947 }  /* END OF FUNCTION F_Help_Mode */
1948
1949 #endif /* WSM */
1950 \f
1951 /******************************<->*************************************
1952  *
1953  *  F_Next_Key (args, pCD, event)
1954  *
1955  *
1956  *  Description:
1957  *  -----------
1958  *  This is the window manager function handler for setting the keyboard
1959  *  input focus to the next window in the set of managed windows.
1960  *
1961  *
1962  *  Inputs:
1963  *  ------
1964  *  args = (immediate value) window type flags
1965  *
1966  *  pCD = pointer to the client data
1967  *
1968  *  event = X event that invoked the function (key, button, or menu/NULL)
1969  *
1970  *************************************<->***********************************/
1971
1972 Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1973 {
1974 #ifdef ROOT_ICON_MENU
1975     Boolean focused = False;
1976 #endif /*  ROOT_ICON_MENU */
1977     if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1978     {
1979 #ifdef ROOT_ICON_MENU
1980         focused = 
1981 #endif /*  ROOT_ICON_MENU */
1982         FocusNextWindow ((unsigned long)args,
1983                          GetFunctionTimestamp ((XButtonEvent *)event));
1984 #ifdef ROOT_ICON_MENU
1985         if (focused && wmGD.iconClick &&
1986             event && event->type == KeyPress &&
1987             wmGD.nextKeyboardFocus &&
1988             wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1989             !P_ICON_BOX(wmGD.nextKeyboardFocus))
1990         {
1991             /*
1992              * Post system menu from the icon
1993              */
1994             F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1995             return (False);
1996         }
1997 #endif /*  ROOT_ICON_MENU */
1998     }
1999
2000     return (True);
2001
2002 } /* END OF FUNCTION F_Next_Key */
2003
2004
2005 \f
2006 /*************************************<->*************************************
2007  *
2008  *  F_Prev_Cmap (args, pCD, event)
2009  *
2010  *
2011  *  Description:
2012  *  -----------
2013  *  This is the window manager function handler installing the previous
2014  *  colormap in the list of client window colormaps.
2015  *
2016  *************************************<->***********************************/
2017
2018 Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
2019 {
2020     if (pCD == NULL)
2021     {
2022         pCD = ACTIVE_PSD->colormapFocus;
2023     }
2024
2025     if (pCD && (pCD->clientCmapCount > 0) &&
2026         ((pCD->clientState == NORMAL_STATE) ||
2027          (pCD->clientState == MAXIMIZED_STATE)))
2028     {
2029         if (--(pCD->clientCmapIndex) < 0)
2030         {
2031             pCD->clientCmapIndex = pCD->clientCmapCount - 1;
2032         }
2033         pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2034         if (ACTIVE_PSD->colormapFocus == pCD)
2035         {
2036 #ifndef OLD_COLORMAP /* colormap */
2037             /*
2038              * We just re-ordered the colormaps list,
2039              * so we need to re-run the whole thing.
2040              */
2041             pCD->clientCmapFlagsInitialized = 0;
2042             ProcessColormapList (ACTIVE_PSD, pCD);
2043 #else /* OSF original */
2044             WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2045 #endif
2046         }
2047     }
2048
2049     return (True);
2050
2051 } /* END OF FUNCTION F_Prev_Cmap */
2052
2053
2054 \f
2055 /*************************************<->*************************************
2056  *
2057  *  F_Prev_Key (args, pCD, event)
2058  *
2059  *
2060  *  Description:
2061  *  -----------
2062  *  This is the window manager function handler for setting the keyboard
2063  *  input focus to the previous window in the set of managed windows.
2064  *
2065  *
2066  *  Inputs:
2067  *  ------
2068  *  args = (immediate value) window type flags
2069  *
2070  *  pCD = pointer to the client data
2071  *
2072  *  event = X event that invoked the function (key, button, or menu/NULL)
2073  *
2074  *************************************<->***********************************/
2075
2076 Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
2077 {
2078 #ifdef ROOT_ICON_MENU
2079     Boolean focused = False;
2080 #endif /*  ROOT_ICON_MENU */
2081     if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
2082     {
2083 #ifdef ROOT_ICON_MENU
2084         focused = 
2085 #endif /*  ROOT_ICON_MENU */
2086         FocusPrevWindow ((unsigned long)args,
2087                             GetFunctionTimestamp ((XButtonEvent *)event));
2088 #ifdef ROOT_ICON_MENU
2089         if (focused && wmGD.iconClick &&
2090             event && event->type == KeyPress &&
2091             wmGD.nextKeyboardFocus &&
2092             wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
2093             !P_ICON_BOX(wmGD.nextKeyboardFocus))
2094         {
2095             /*
2096              * Post system menu from the icon
2097              */
2098             F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
2099             return (False);
2100         }
2101 #endif /*  ROOT_ICON_MENU */
2102
2103     }
2104
2105     return (True);
2106
2107 } /* END OF FUNCTION F_Prev_Key */
2108
2109 #ifdef PANELIST
2110 \f
2111 /***********************<->*************************************
2112  *
2113  *  F_Post_FpMenu (args, pCD, event)
2114  *
2115  *
2116  *  Description:
2117  *  -----------
2118  *  This is the window manager function handler for posting
2119  *  the Front Panel window menu.
2120  *
2121  *  Inputs:
2122  *  ------
2123  *  args = arguments (none)
2124  *
2125  *  pCD = pointer to the FP ClientData
2126  *
2127  *  event = X button press that invoked the function
2128  *
2129  ******************************<->***********************************/
2130
2131 Boolean
2132 F_Post_FpMenu (String args, ClientData *pCD, XEvent *event)
2133 {
2134     static MenuSpec *fpMenuSpec = (MenuSpec *)NULL;
2135
2136     if (event->type != ButtonPress)
2137         return False;
2138
2139     if (!fpMenuSpec)
2140     {
2141         WmScreenData *pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2142         MenuSpec *oldSpec;
2143         Widget tmpWidget;
2144         char *newMenuName;
2145
2146         newMenuName = pCD ? pCD->systemMenu : "DtPanelMenu";
2147
2148         for (oldSpec = pSD->menuSpecs;
2149              oldSpec != (MenuSpec *)NULL;
2150              oldSpec = oldSpec->nextMenuSpec)
2151         {
2152             if (oldSpec->name && (strcmp(oldSpec->name, newMenuName) == 0))
2153                 break;
2154         }
2155         if (!oldSpec)
2156             return False;
2157
2158         fpMenuSpec = DuplicateMenuSpec(oldSpec);
2159
2160         /*
2161          * TEMPORARILY modify pSD so the new menu will be
2162          * created on DISPLAY1 instead of DISPLAY.
2163          */
2164         fpMenuSpec->nextMenuSpec = pSD->menuSpecs;
2165         pSD->menuSpecs = fpMenuSpec;
2166         tmpWidget = pSD->screenTopLevelW;
2167         pSD->screenTopLevelW = pSD->screenTopLevelW1;
2168
2169         (void)MAKE_MENU (pSD, pCD, newMenuName,
2170                          F_CONTEXT_NORMAL, F_CONTEXT_NORMAL,
2171                          (MenuItem *) NULL, FALSE);
2172
2173         /* Restore pSD */
2174         pSD->screenTopLevelW = tmpWidget;
2175         pSD->menuSpecs = fpMenuSpec->nextMenuSpec;
2176     }
2177
2178     PostMenu (fpMenuSpec, pCD, event->xbutton.x_root, event->xbutton.y_root,
2179               event->xbutton.button, F_CONTEXT_NORMAL, POST_AT_XY, event);
2180
2181     _XmGetMenuState(XtParent(fpMenuSpec->menuWidget))
2182         ->MS_LastManagedMenuTime = event->xbutton.time;
2183
2184     return False;
2185 }
2186
2187 \f
2188 /***********************<->*************************************
2189  *
2190  *  F_Push_Recall (args, pCD, event)
2191  *
2192  *
2193  *  Description:
2194  *  -----------
2195  *  This is the window manager function handler for invoking/topping
2196  *  push_recall clients.
2197  *
2198  *
2199  *  Inputs:
2200  *  ------
2201  *  args = arguments
2202  *
2203  *  pCD = pointer to the ClientData 
2204  *
2205  *  event = X event that invoked the function (key, button, or menu/NULL)
2206  *
2207  *
2208  *  Outputs:
2209  *  -------
2210  *  RETURN = if True then further button binding/function processing can
2211  *           be done for the event that caused this function to be called.
2212  *
2213  *  Comments:
2214  *  -------
2215  ******************************<->***********************************/
2216
2217 Boolean
2218 F_Push_Recall (String args, ClientData *pCD, XEvent *event)
2219 {
2220     WmPushRecallArg *pPRP;
2221     WmScreenData *pSD;
2222     WmFpPushRecallClientData *pPRCD;
2223
2224     pPRP = (WmPushRecallArg *) args;
2225     pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2226
2227     if (pPRP->ixReg  < pSD->numPushRecallClients)
2228     {
2229         /* get slot for this client */
2230         pPRCD = &(pSD->pPRCD[pPRP->ixReg]);
2231
2232         /*
2233          * If the client is already running, then top it in this workspace,
2234          * else invoke the function to start it.
2235          */
2236         if (pPRCD->pCD)
2237         {
2238             /* Client is managed already. */ 
2239             if (!(ClientInWorkspace (pSD->pActiveWS, pPRCD->pCD)))
2240             {
2241                 WorkspaceID *wsRemoveList;
2242                 int sizeRemoveList;
2243
2244                 /* 
2245                  * Move client to current workspace 
2246                  */
2247                 wsRemoveList = GetListOfOccupiedWorkspaces (pPRCD->pCD, 
2248                                         &sizeRemoveList);
2249                 RemoveClientFromWorkspaces (pPRCD->pCD, wsRemoveList,
2250                                         sizeRemoveList);
2251                 XtFree ((char *)wsRemoveList);
2252                 AddClientToWorkspaces (pPRCD->pCD, &(pSD->pActiveWS->id), 1);
2253                 SetClientWsIndex(pPRCD->pCD);
2254                 SetClientState(pPRCD->pCD, 
2255                     pPRCD->pCD->clientState & ~UNSEEN_STATE, CurrentTime);
2256             }
2257
2258             /* Make this client visible */
2259 #ifdef WSM
2260                     wmGD.bSuspendSecondaryRestack = True;
2261 #endif /* WSM */
2262             F_Normalize_And_Raise (NULL, pPRCD->pCD, event);
2263 #ifdef WSM
2264                     wmGD.bSuspendSecondaryRestack = False;
2265 #endif /* WSM */
2266         }
2267         else 
2268         {
2269             struct timeval tvNow;
2270             struct timezone tz;
2271             Boolean bWaiting = False;
2272
2273             if (pPRCD->tvTimeout.tv_sec != 0)
2274             {
2275                 gettimeofday (&tvNow, &tz);
2276
2277                 if ((pPRCD->tvTimeout.tv_sec > tvNow.tv_sec) ||
2278                     ((pPRCD->tvTimeout.tv_sec == tvNow.tv_sec) &&
2279                      (pPRCD->tvTimeout.tv_usec > tvNow.tv_usec)))
2280                 {
2281                     /* still waiting for client to start */
2282                     bWaiting = True;
2283                 }
2284             }
2285
2286             if (!bWaiting)
2287             {
2288                 long clientTimeout = 0;
2289                 Arg al[5];
2290                 int ac;
2291                 WmPanelistObject  pPanelist;
2292
2293                 pPanelist = (WmPanelistObject) pSD->wPanelist;
2294
2295                 /* invoke the function to start the client */
2296                 pPRP->wmFunc ( pPRP->pArgs, pCD, event);
2297
2298                 if (pPanelist && panel.busy_light_data)
2299                 {
2300                     /* set timeout value */
2301                     ac = 0;
2302                     XtSetArg (al[ac], 
2303                         XmNclientTimeoutInterval, &clientTimeout);      ac++; 
2304                     XtGetValues (panel.busy_light_data->icon, (ArgList)al, ac);
2305                 }
2306
2307                 /*
2308                  * ClientTimeout is in milliseconds, timeval values
2309                  * are in seconds and microseconds.
2310                  */
2311                 gettimeofday (&(pPRCD->tvTimeout), &tz);
2312
2313                 pPRCD->tvTimeout.tv_sec += clientTimeout / 1000;
2314                 pPRCD->tvTimeout.tv_usec += 
2315                     (clientTimeout % 1000) * 1000;
2316
2317                 pPRCD->tvTimeout.tv_sec += pPRCD->tvTimeout.tv_usec / 1000000;
2318                 pPRCD->tvTimeout.tv_usec %= 1000000;
2319             }
2320         }
2321     }
2322
2323     return (True);
2324
2325 } /* END OF FUNCTION F_Push_Recall */
2326 #endif /* PANELIST */
2327
2328 \f
2329 /*************************************<->*************************************
2330  *
2331  *  F_Pass_Key (args, pCD, event)
2332  *
2333  *
2334  *  Description:
2335  *  -----------
2336  *  This is a function stub for the f.pass_key window manager function.
2337  *
2338  *
2339  *  Inputs:
2340  *  ------
2341  *  args = (immediate value) window type flags
2342  *
2343  *  pCD = pointer to the client data
2344  *
2345  *  event = X event that invoked the function (key, button, or menu/NULL)
2346  *
2347  *************************************<->***********************************/
2348
2349 Boolean F_Pass_Key (args, pCD, event)
2350     String args;
2351     ClientData *pCD;
2352     XEvent *event;
2353
2354 {
2355     if (wmGD.passKeysActive)
2356     {
2357         /*
2358          * Get out of pass keys mode.
2359          */
2360
2361         wmGD.passKeysActive = False;
2362         wmGD.passKeysKeySpec = NULL;
2363     }
2364     else
2365     {
2366         /*
2367          * Get into pass keys mode.
2368          */
2369
2370         wmGD.passKeysActive = True;
2371     }
2372
2373     return (False);
2374
2375 } /* END OF FUNCTION F_Pass_Key */
2376
2377
2378 \f
2379 /*************************************<->*************************************
2380  *
2381  *  F_Maximize (args, pCD, event)
2382  *
2383  *
2384  *  Description:
2385  *  -----------
2386  *  This is the window manager function handler for maximizing a client
2387  *  window.
2388  *
2389  *************************************<->***********************************/
2390
2391 Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
2392 {
2393     if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
2394     {
2395         SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
2396             GetFunctionTimestamp ((XButtonEvent *)event),
2397                 GetEventInverseMask(event));
2398     }
2399
2400     return (False);
2401
2402 } /* END OF FUNCTION F_Maximize */
2403
2404
2405 \f
2406 /*************************************<->*************************************
2407  *
2408  *  F_Menu (args, pCD, event)
2409  *
2410  *
2411  *  Description:
2412  *  -----------
2413  *  This is the window manager function handler for posting a menu.
2414  *  This function can only be invoked by a key or button event.
2415  *   wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2416  *     NULL when the menu is unposted.
2417  *
2418  *************************************<->***********************************/
2419
2420 Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
2421 {
2422     MenuSpec    *menuSpec;
2423     Context      menuContext;
2424     unsigned int button;
2425     int          x;
2426     int          y;
2427     long         flags = POST_AT_XY;
2428     WmScreenData *pSD;
2429
2430
2431     if (event && 
2432         ((event->type == ButtonPress) || (event->type == ButtonRelease)))
2433     {
2434         button = event->xbutton.button;
2435         x = event->xbutton.x_root;
2436         y = event->xbutton.y_root;
2437         if (event->type == ButtonRelease)
2438         {
2439             flags |= POST_TRAVERSAL_ON;
2440         }
2441 #ifdef WSM
2442         /*
2443          * Root menu, if posted with button press, then 
2444          * set up to handle root menu click to make the menu
2445          * sticky.
2446          */
2447         else if (wmGD.rootButtonClick && (event->type == ButtonPress))
2448         {
2449             if (wmGD.bReplayedButton)
2450             {
2451                 /* This button was replayed, it most likely dismissed
2452                    a previous sticky menu, don't post a menu here */
2453                 return (False);
2454             }
2455             wmGD.checkHotspot = True;
2456             wmGD.hotspotRectangle.x = x - wmGD.moveThreshold/2;
2457             wmGD.hotspotRectangle.y = y - wmGD.moveThreshold/2;
2458             wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2459             wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2460         }
2461 #endif /* WSM */
2462     }
2463     else if (event && 
2464         ((event->type == KeyPress) || (event->type == KeyRelease)))
2465     {
2466         button = NoButton;
2467         x = event->xkey.x_root;
2468         y = event->xkey.y_root;
2469     }
2470     else
2471     {
2472         /*
2473          * A button or key event must be used to post a menu using this 
2474          * function.
2475          */
2476
2477         return (False);
2478     }
2479
2480     if (pCD)
2481     {
2482         if (pCD->clientState == NORMAL_STATE)
2483         {
2484             menuContext = F_CONTEXT_NORMAL;
2485         }
2486         else if (pCD->clientState == MAXIMIZED_STATE)
2487         {
2488             menuContext = F_CONTEXT_MAXIMIZE;
2489         }
2490         else 
2491         {
2492             menuContext = F_CONTEXT_ICON;
2493         }
2494         if (P_ICON_BOX(pCD) &&
2495             event->xany.window == ICON_FRAME_WIN(pCD))
2496         {
2497             if (pCD->clientState == MINIMIZED_STATE)
2498             {
2499                 menuContext = F_SUBCONTEXT_IB_IICON;
2500             }
2501             else
2502             {
2503                 menuContext = F_SUBCONTEXT_IB_WICON;
2504             }
2505         }
2506     }
2507     else
2508     {
2509         menuContext = F_CONTEXT_ROOT;
2510     }
2511
2512
2513     /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
2514      * This should have been done in MakeWmFunctionResources().
2515      */
2516
2517     pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2518     if ((menuSpec = MAKE_MENU (pSD, pCD, args, menuContext, 
2519                               menuContext, (MenuItem *) NULL, FALSE)) != NULL)
2520     {
2521         PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
2522     }
2523
2524     return (False);
2525
2526 } /* END OF FUNCTION F_Menu */
2527
2528 \f
2529 /*************************************<->*************************************
2530  *
2531  *  F_Minimize (args, pCD, event)
2532  *
2533  *
2534  *  Description:
2535  *  -----------
2536  *  This is the window manager function handler for minimizing a client
2537  *  window.
2538  *
2539  *************************************<->***********************************/
2540
2541 Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
2542 {
2543     ClientData *pcdLeader;
2544
2545
2546     if (pCD)
2547     {
2548         /*
2549          * If the window is a transient then minimize the entire transient
2550          * tree including the transient leader.
2551          */
2552         
2553         pcdLeader = (pCD->transientLeader) ?
2554                                         FindTransientTreeLeader (pCD) : pCD;
2555         if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
2556         {
2557             SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
2558                 GetFunctionTimestamp ((XButtonEvent *)event),
2559                 GetEventInverseMask(event));
2560         }
2561     }
2562
2563     return (False);
2564
2565 } /* END OF FUNCTION F_Minimize */
2566
2567
2568 \f
2569 /*************************************<->*************************************
2570  *
2571  *  F_Move (args, pCD, event)
2572  *
2573  *
2574  *  Description:
2575  *  -----------
2576  *  This is the window manager function handler for moving a client window
2577  *  or icon.
2578  *
2579  *************************************<->***********************************/
2580
2581 Boolean F_Move (String args, ClientData *pCD, XEvent *event)
2582 {
2583     if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
2584     {
2585         StartClientMove (pCD, event);
2586         HandleClientFrameMove (pCD, event);
2587     }
2588
2589     return (False);
2590
2591 } /* END OF FUNCTION F_Move */
2592
2593
2594 \f
2595 /*************************************<->*************************************
2596  *
2597  *  F_Next_Cmap (args, pCD, event)
2598  *
2599  *
2600  *  Description:
2601  *  -----------
2602  *  This is the window manager function handler installing the next
2603  *  colormap in the list of client window colormaps.
2604  *
2605  *************************************<->***********************************/
2606
2607 Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
2608 {
2609     if (pCD == NULL)
2610     {
2611         pCD = ACTIVE_PSD->colormapFocus;
2612     }
2613
2614     if (pCD && (pCD->clientCmapCount > 0) &&
2615         ((pCD->clientState == NORMAL_STATE) ||
2616          (pCD->clientState == MAXIMIZED_STATE)))
2617     {
2618         if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
2619         {
2620             pCD->clientCmapIndex = 0;
2621         }
2622         pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2623         if (ACTIVE_PSD->colormapFocus == pCD)
2624         {
2625 #ifndef OLD_COLORMAP /* colormap */
2626             /*
2627              * We just re-ordered the colormaps list,
2628              * so we need to re-run the whole thing.
2629              */
2630             pCD->clientCmapFlagsInitialized = 0;
2631             ProcessColormapList (ACTIVE_PSD, pCD);
2632 #else /* OSF original */
2633             WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2634 #endif
2635         }
2636     }
2637
2638     return (True);
2639
2640 } /* END OF FUNCTION F_Next_Cmap */
2641
2642
2643 \f
2644 /*************************************<->*************************************
2645  *
2646  *  F_Nop (args, pCD, event)
2647  *
2648  *
2649  *  Description:
2650  *  -----------
2651  *  This is the window manager function handler for doing nothing.
2652  *
2653  *************************************<->***********************************/
2654
2655 Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2656 {
2657
2658     return (True);
2659
2660 } /* END OF FUNCTION F_Nop */
2661
2662
2663 \f
2664 /*************************************<->*************************************
2665  *
2666  *  F_Normalize (args, pCD, event)
2667  *
2668  *
2669  *  Description:
2670  *  -----------
2671  *  This is the window manager function handler for putting a client window
2672  *  in the normal state.
2673  *
2674  *************************************<->***********************************/
2675
2676 Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2677 {
2678
2679     if (pCD)
2680     {
2681         SetClientStateWithEventMask (pCD, NORMAL_STATE,
2682             GetFunctionTimestamp ((XButtonEvent *)event),
2683                 GetEventInverseMask(event));
2684     }
2685
2686     return (False);
2687
2688 } /* END OF FUNCTION F_Normalize */
2689
2690
2691 \f
2692 /*************************************<->*************************************
2693  *
2694  *  F_Normalize_And_Raise (args, pCD, event)
2695  *
2696  *
2697  *  Description:
2698  *  -----------
2699  *  This is the window manager function handler for putting a client window
2700  *  in the normal state and raising it from and icon.
2701  *
2702  *************************************<->***********************************/
2703
2704 Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2705 {
2706 #ifdef PANELIST
2707     WmScreenData        *pSD;
2708     WmWorkspaceData     *pWS;
2709
2710     if (args)
2711     {
2712         if (pCD) 
2713             pSD = PSD_FOR_CLIENT (pCD);
2714         else
2715             pSD = ACTIVE_PSD;
2716
2717         pWS =  pSD->pActiveWS;
2718
2719         if (pSD->useIconBox && 
2720             wmGD.useFrontPanel && 
2721             pSD->iconBoxControl &&
2722             (!strcmp(args, WmNiconBox)))
2723         {
2724             /* 
2725              * There's an icon box in the front panel and this is a 
2726              * request to pop up the icon box.
2727              */
2728             IconBoxPopUp (pWS, True);
2729             return (False);
2730         }
2731     }
2732 #endif /* PANELIST */
2733     if (pCD)
2734     {
2735         if (pCD->clientState == MINIMIZED_STATE)
2736         {
2737             /* normalize window  */
2738             SetClientStateWithEventMask (pCD, NORMAL_STATE,
2739                           (Time)
2740                           (event
2741                            ? GetFunctionTimestamp ((XButtonEvent *)event)
2742                            : GetTimestamp ()),
2743                         GetEventInverseMask(event));
2744         }
2745         else
2746         {
2747             /* Make sure we are in NORMAL_STATE */
2748             SetClientStateWithEventMask (pCD, NORMAL_STATE,
2749                             GetFunctionTimestamp ((XButtonEvent *)event),
2750                                 GetEventInverseMask(event));
2751
2752             /* Raise the window and set the keyboard focus to the window */
2753 #ifdef WSM
2754             wmGD.bSuspendSecondaryRestack = True;
2755 #endif /* WSM */
2756             F_Raise (NULL, pCD, (XEvent *)NULL);
2757 #ifdef WSM
2758             wmGD.bSuspendSecondaryRestack = False;
2759 #endif /* WSM */
2760             if (wmGD.raiseKeyFocus)
2761             {
2762                 F_Focus_Key (NULL, pCD,
2763                              (event 
2764                               ? ((XEvent *)event)
2765                               : ((XEvent *)NULL)));
2766             }
2767         }
2768         wmGD.clickData.clickPending = False;
2769         wmGD.clickData.doubleClickPending = False;
2770     }
2771
2772     return (False);
2773
2774 } /* END OF FUNCTION F_Normalize_And_Raise */
2775
2776
2777 \f
2778 /*************************************<->*************************************
2779  *
2780  *  F_Restore (args, pCD, event)
2781  *
2782  *
2783  *  Description:
2784  *  -----------
2785  *  This is the window manager function handler for putting a client window
2786  *  in the normal state.
2787  *
2788  *************************************<->***********************************/
2789
2790 Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2791 {
2792     int newState;
2793
2794     if (pCD)
2795     {
2796         /*
2797          * If current state is MAXIMIZED state then just go to NORMAL state,
2798          * otherwise (you are in MINIMIZED state) return to previous state.
2799          */
2800
2801         if (pCD->clientState == MAXIMIZED_STATE)
2802         {
2803             SetClientStateWithEventMask (pCD, NORMAL_STATE,
2804                             GetFunctionTimestamp ((XButtonEvent *)event),
2805                                 GetEventInverseMask(event));
2806         }
2807         else
2808         {
2809             if (pCD->maxConfig)
2810             {
2811                 newState = MAXIMIZED_STATE;
2812             }
2813             else
2814             {
2815                 newState = NORMAL_STATE;
2816             }
2817
2818             SetClientStateWithEventMask (pCD, newState,
2819                             GetFunctionTimestamp ((XButtonEvent *)event),
2820                                 GetEventInverseMask(event));
2821         }
2822     }
2823
2824     return (False);
2825
2826 } /* END OF FUNCTION F_Restore */
2827
2828
2829 \f
2830 /*************************************<->*************************************
2831  *
2832  *  F_Restore_And_Raise (args, pCD, event)
2833  *
2834  *
2835  *  Description:
2836  *  -----------
2837  *  This is the window manager function handler for putting a client window
2838  *  in the normal state and raising it from and icon.
2839  *
2840  *************************************<->***********************************/
2841
2842 Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2843 {
2844     int newState;
2845     
2846     if (pCD)
2847     {
2848         if (pCD->clientState == MINIMIZED_STATE)
2849         {
2850             /* Restore window  */
2851             if (pCD->maxConfig)
2852             {
2853                 newState = MAXIMIZED_STATE;
2854             }
2855             else
2856             {
2857                 newState = NORMAL_STATE;
2858             }
2859
2860             SetClientStateWithEventMask (pCD, newState,
2861                           (Time)
2862                           (event
2863                            ? GetFunctionTimestamp ((XButtonEvent *)event)
2864                            : GetTimestamp ()),
2865                         GetEventInverseMask(event));
2866         }
2867         else
2868         {
2869             /* Make sure we restore the window first */
2870             F_Restore (NULL, pCD, event);
2871
2872             /* Raise the window and set the keyboard focus to the window */
2873 #ifdef WSM
2874             wmGD.bSuspendSecondaryRestack = True;
2875 #endif /* WSM */
2876             F_Raise (NULL, pCD, (XEvent *)NULL);
2877 #ifdef WSM
2878             wmGD.bSuspendSecondaryRestack = False;
2879 #endif /* WSM */
2880             if (wmGD.raiseKeyFocus)
2881             {
2882                 F_Focus_Key (NULL, pCD,
2883                              (event 
2884                               ? ((XEvent *)event)
2885                               : ((XEvent *)NULL)));
2886             }
2887         }
2888         wmGD.clickData.clickPending = False;
2889         wmGD.clickData.doubleClickPending = False;
2890     }
2891
2892     return (False);
2893
2894 } /* END OF FUNCTION F_Restore_And_Raise */
2895
2896
2897 \f
2898 /*************************************<->*************************************
2899  *
2900  *  F_Pack_Icons (args, pCD, event)
2901  *
2902  *
2903  *  Description:
2904  *  -----------
2905  *  This is the window manager function handler for packing icons in the
2906  *  icon box or on the desktop.
2907  *
2908  *************************************<->***********************************/
2909
2910 Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2911 {
2912     
2913     IconBoxData *pIBD;
2914
2915     if (ACTIVE_PSD->useIconBox)
2916     {
2917         pIBD = ACTIVE_WS->pIconBox;
2918         if (pCD)
2919         {
2920             while (pCD != pIBD->pCD_iconBox)
2921             {
2922                 if (pIBD->pNextIconBox)
2923                 {
2924                     pIBD = pIBD->pNextIconBox;
2925                 }
2926                 else
2927                 {
2928                     pIBD = NULL;
2929                     break;
2930                 }
2931             }
2932         }
2933         if (pIBD)
2934         {
2935             PackIconBox (pIBD, False, False, 0, 0);
2936         }
2937         else
2938         {
2939            PackRootIcons ();
2940         }
2941     }
2942     else
2943     {
2944         PackRootIcons ();
2945     }
2946
2947     return (True);
2948
2949
2950 } /* END OF FUNCTION F_Pack_Icons */
2951
2952 \f
2953 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2954 /*************************************<->*************************************
2955  *
2956  *  F_Post_RMenu (args, pCD, event)
2957  *
2958  *
2959  *  Description:
2960  *  -----------
2961  *  This is the window manager function handler for posting the
2962  *  root window menu.
2963  *  This function can only be invoked by a key event.
2964  *
2965  *************************************<->***********************************/
2966
2967 Boolean F_Post_RMenu (String args, ClientData *pCD, XEvent *event)
2968 {
2969     MenuSpec    *rootMenu;
2970     unsigned int button = NoButton;
2971     int          x, y;
2972     long         flags = POST_AT_XY;
2973     Window       rwin, cwin;
2974     int          winx, winy;
2975     unsigned int mask;
2976
2977
2978     if ((event->type == KeyPress) || (event->type == KeyRelease))
2979       {
2980
2981         /* Find the root menu spec */
2982         for (rootMenu = ACTIVE_PSD->menuSpecs;
2983              rootMenu != (MenuSpec *) NULL;
2984              rootMenu = rootMenu->nextMenuSpec)
2985           {
2986             if (strcmp(rootMenu->name, ACTIVE_PSD->rootMenu) == 0)
2987               break;
2988           }
2989     
2990         /* If we couldn't find the root menu, then do nothing. */
2991         if (rootMenu == (MenuSpec *) NULL)
2992           return (False);
2993
2994         else
2995           {
2996             XQueryPointer(DISPLAY, ACTIVE_ROOT,
2997                           &rwin, &cwin, &x, &y, &winx, &winy, &mask);
2998
2999             PostMenu (rootMenu, NULL, x, y, NoButton, F_CONTEXT_ROOT,
3000                       flags, event);
3001           }
3002       }
3003
3004     return (False);
3005
3006 } /* END OF FUNCTION F_Post_RMenu */
3007 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
3008
3009 \f
3010 /*************************************<->*************************************
3011  *
3012  *  F_Post_SMenu (args, pCD, event)
3013  *
3014  *
3015  *  Description:
3016  *  -----------
3017  *  This is the window manager function handler for posting the system menu
3018  *  for the specified client.
3019  *  This function can only be invoked by a key or button event.
3020  *  wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
3021  *    NULL when the menu is unposted.
3022  *
3023  *************************************<->***********************************/
3024
3025 Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
3026 {
3027     Context menuContext;
3028
3029
3030     /*
3031      * An event must be used to post the system menu using this function.
3032      */
3033
3034     if (event && pCD && pCD->systemMenuSpec)
3035     {
3036         /*
3037          * Determine whether the keyboard is posting the menu and post
3038          * the menu at an appropriate place.
3039          */
3040
3041         if (pCD->clientState == NORMAL_STATE)
3042         {
3043             menuContext = F_CONTEXT_NORMAL;
3044         }
3045         else if (pCD->clientState == MAXIMIZED_STATE)
3046         {
3047             menuContext = F_CONTEXT_MAXIMIZE;
3048         }
3049         else 
3050         {
3051             menuContext = F_CONTEXT_ICON;
3052         }
3053         if (P_ICON_BOX(pCD) &&
3054             event->xany.window == ICON_FRAME_WIN(pCD))
3055         {
3056             if (pCD->clientState == MINIMIZED_STATE)
3057             {
3058                 menuContext = F_SUBCONTEXT_IB_IICON;
3059             }
3060             else
3061             {
3062                 menuContext = F_SUBCONTEXT_IB_WICON;
3063             }
3064         }
3065
3066         if ((event->type == KeyPress) || (event->type == KeyRelease))
3067         {
3068             /*
3069              * Set up for "sticky" menu processing if specified.
3070              */
3071
3072             if (pCD->clientState == MINIMIZED_STATE ||
3073                 menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
3074             {
3075                 if (wmGD.iconClick)
3076                 {
3077                     wmGD.checkHotspot = True;
3078                 }
3079             }
3080             else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
3081             {
3082                 wmGD.checkHotspot = True;
3083             }
3084
3085             PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
3086                       0, event);
3087         }
3088         else if (event->type == ButtonPress)
3089         {
3090 #ifdef WSM
3091             /*
3092              * Root menu, if posted with button press, then 
3093              * set up to handle root menu click to make the menu
3094              * sticky.
3095              */
3096             if (wmGD.rootButtonClick && (!wmGD.checkHotspot))
3097             {
3098                 wmGD.checkHotspot = True;
3099                 wmGD.hotspotRectangle.x = 
3100                             event->xbutton.x_root - wmGD.moveThreshold/2;
3101                 wmGD.hotspotRectangle.y = 
3102                             event->xbutton.y_root - wmGD.moveThreshold/2;
3103                 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
3104                 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
3105             }
3106 #endif /* WSM */
3107             PostMenu (pCD->systemMenuSpec, pCD, 
3108                 event->xbutton.x_root, event->xbutton.y_root,
3109                 event->xbutton.button, menuContext, POST_AT_XY, event);
3110         }
3111         else if (event->type == ButtonRelease)
3112         {
3113             PostMenu (pCD->systemMenuSpec, pCD, 
3114                 event->xbutton.x_root, event->xbutton.y_root,
3115                 event->xbutton.button, menuContext,
3116                 POST_AT_XY | POST_TRAVERSAL_ON, event);
3117         }
3118     }
3119
3120     return (False);
3121
3122 } /* END OF FUNCTION F_PostSMenu */
3123
3124
3125 \f
3126 /*************************************<->*************************************
3127  *
3128  *  F_Kill (args, pCD, event)
3129  *
3130  *
3131  *  Description:
3132  *  -----------
3133  *  This is the window manager function handler for terminating a client.
3134  *  Essentially the client connection is shut down.
3135  *
3136  *************************************<->***********************************/
3137
3138 Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
3139 {
3140     if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
3141     {
3142         Boolean do_delete_window =
3143                 pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
3144         Boolean do_save_yourself =
3145                 pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
3146
3147 #ifdef PANELIST
3148         if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3149         {
3150             Widget              wPanel;
3151             
3152             /*
3153              * Get the widget for the subpanel
3154              * (Should be only child of the shell!)
3155              */
3156             wPanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
3157             if (wPanel)
3158             {
3159                 SlideSubpanelBackIn (pCD, wPanel);
3160             }
3161             return (False);
3162         }
3163         if (pCD->clientFlags & ICON_BOX)
3164         {
3165             /*
3166              * When the front panel is used with the icon box,
3167              * "Close" hides the icon box into the front panel.
3168              */
3169             if ((wmGD.useFrontPanel) &&
3170                 (pCD->pSD->iconBoxControl) &&
3171                 (IconBoxShowing(pCD->pSD->pActiveWS)))
3172             {
3173                 IconBoxPopUp (pCD->pSD->pActiveWS, False);
3174             }
3175         }
3176         else
3177 #endif /* PANELIST */
3178         if (!do_delete_window && !do_save_yourself)
3179         {
3180             XKillClient (DISPLAY, pCD->client);
3181         }
3182         else
3183         {
3184             if (do_delete_window)
3185             {
3186                 /*
3187                  * The client wants to be notified, not killed.
3188                  */
3189
3190                 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3191                     (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
3192             }
3193 #ifdef WSM
3194             /*
3195              * HP does not want to send a client message for both
3196              * delete_window AND save_yourself.  The current OSF
3197              * patch did just that.  This "else if" returns dtwm
3198              * to the behavior of dt 2.01
3199              */
3200             else if (do_save_yourself)
3201 #else /* WSM */
3202             if (do_save_yourself)
3203 #endif /* WSM */
3204             {
3205                 /*
3206                  * Send a WM_SAVE_YOURSELF message and wait for a change to
3207                  * the WM_COMMAND property.
3208                  * !!! button and key input should be kept from the window !!!
3209                  */
3210
3211                 if (AddWmTimer (TIMER_QUIT, 
3212                     (unsigned long) wmGD.quitTimeout, pCD))
3213                 {
3214                     SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3215                         (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
3216
3217                     pCD->clientFlags |= CLIENT_TERMINATING;
3218                 }
3219                 else
3220                 {
3221                     XKillClient (DISPLAY, pCD->client);
3222                 }
3223             }
3224         }
3225     }
3226
3227     return (False);
3228
3229 } /* END OF FUNCTION F_Kill */
3230
3231 #ifdef WSM
3232 \f
3233 /*************************************<->*************************************
3234  *
3235  *  F_Marquee_Selection (args, pCD, event)
3236  *
3237  *
3238  *  Description:
3239  *  -----------
3240  *  This is the window manager function handler for selecting 
3241  *  non-window manager objects on the root window.
3242  *
3243  *************************************<->***********************************/
3244
3245 Boolean F_Marquee_Selection (String args, ClientData *pCD, XEvent *event)
3246 {
3247     if (!pCD)
3248     {
3249         /*
3250          * This function only valid in root context
3251          */
3252         StartMarqueeSelect (ACTIVE_PSD, event);
3253         HandleMarqueeSelect (ACTIVE_PSD, event);
3254     }
3255
3256     return (False);
3257
3258 } /* END OF FUNCTION F_Marquee_Selection */
3259
3260 /*************************************<->*************************************
3261  *
3262  *  RefreshByClearing (win)
3263  *
3264  *
3265  *  Description:
3266  *  -----------
3267  *  Recursively refresh this window and its children by doing
3268  *  XClearAreas
3269  *
3270  *************************************<->***********************************/
3271 static void
3272 RefreshByClearing (Window win)
3273 {
3274     Status status;
3275     int i;
3276     Window root, parent;
3277     unsigned int nchildren;
3278     Window *winChildren;
3279
3280     /* clear this window */
3281     XClearArea(DISPLAY, win, 0, 0, 0, 0, True);
3282
3283     /* find any children and clear them, too */
3284     status = XQueryTree(DISPLAY, win, &root, &parent, &winChildren,
3285                     &nchildren);
3286     if (status != 0)
3287     {
3288         /* recurse for each child window */
3289         for (i=0; i<nchildren; ++i) 
3290         {
3291             RefreshByClearing(winChildren[i]);
3292         }
3293
3294         /* clean up */
3295         if (nchildren > 0) 
3296             XFree((char *)winChildren);
3297     }
3298 }
3299 #endif /* WSM */
3300
3301 \f
3302 /*************************************<->*************************************
3303  *
3304  *  F_Refresh (args, pCD, event)
3305  *
3306  *
3307  *  Description:
3308  *  -----------
3309  *  This is the window manager function handler for causing all windows
3310  *  in the workspace to be redrawn.
3311  *
3312  *************************************<->***********************************/
3313
3314 Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
3315 {
3316     Window win;
3317
3318 #ifdef WSM
3319     if (wmGD.refreshByClearing)
3320     {
3321         RefreshByClearing (ACTIVE_ROOT);
3322     }
3323     else
3324     {
3325 #endif /* WSM */
3326                          /* default background_pixmap is None */
3327     win = XCreateWindow (DISPLAY,
3328                          ACTIVE_ROOT, 0, 0,
3329                          (unsigned int) DisplayWidth (DISPLAY, 
3330                              ACTIVE_SCREEN),
3331                          (unsigned int) DisplayHeight (DISPLAY, 
3332                              ACTIVE_SCREEN),
3333                          0, 
3334                          0,
3335                          InputOutput,
3336                          CopyFromParent,
3337                          0, 
3338                          (XSetWindowAttributes *)NULL);   
3339
3340     XMapWindow (DISPLAY, win);
3341     XDestroyWindow (DISPLAY, win);
3342 #ifdef WSM 
3343     }
3344 #endif /* WSM */
3345     XFlush (DISPLAY);
3346
3347     return (True);
3348
3349 } /* END OF FUNCTION F_Refresh */
3350
3351
3352 \f
3353 /*************************************<->*************************************
3354  *
3355  *  F_Resize (args, pCD, event)
3356  *
3357  *
3358  *  Description:
3359  *  -----------
3360  *  This is the window manager function handler for resizing a client window.
3361  *
3362  *************************************<->***********************************/
3363
3364 Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
3365 {
3366     if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
3367         ((pCD->clientState == NORMAL_STATE) ||
3368                                         (pCD->clientState == MAXIMIZED_STATE)))
3369     {
3370         StartClientResize (pCD, event);
3371         HandleClientFrameResize (pCD, event);
3372     }
3373
3374     return (False);
3375
3376 } /* END OF FUNCTION F_Resize */
3377
3378
3379 \f
3380 /*************************************<->*************************************
3381  *
3382  *  F_Restart (args, pCD, event)
3383  *
3384  *
3385  *  Description:
3386  *  -----------
3387  *  This is the window manager function handler for restarting the window
3388  *  manager.
3389  *
3390  *************************************<->***********************************/
3391
3392 Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
3393 {
3394 #ifdef WSM
3395     if (args && *args && !strcmp (args, DTWM_REQP_NO_CONFIRM))
3396     {
3397         RestartWm (MWM_INFO_STARTUP_CUSTOM);
3398     }
3399     else
3400 #endif /* WSM */
3401     if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
3402     {
3403         ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
3404     }
3405     else
3406     {
3407         RestartWm (MWM_INFO_STARTUP_CUSTOM);
3408     }
3409     return (False);
3410
3411 } /* END OF FUNCTION F_Restart */
3412
3413
3414 \f
3415 /*************************************<->*************************************
3416  *
3417  *  Do_Restart (dummy)
3418  *
3419  *
3420  *  Description:
3421  *  -----------
3422  *  Callback function for restarting the window manager.
3423  *
3424  *************************************<->***********************************/
3425
3426 void Do_Restart (Boolean dummy)
3427 {
3428     RestartWm (MWM_INFO_STARTUP_CUSTOM);
3429
3430 } /* END OF FUNCTION Do_Restart */
3431
3432
3433 \f
3434 /*************************************<->*************************************
3435  *
3436  *  RestartWm (startupFlags)
3437  *
3438  *
3439  *  Description:
3440  *  -----------
3441  *  Actually restarts the window manager.
3442  *
3443  *
3444  *  Inputs:
3445  *  ------
3446  *  startupFlags = flags to be put into the Wm_INFO property for restart.
3447  *
3448  *************************************<->***********************************/
3449
3450 void RestartWm (long startupFlags)
3451 {
3452     ClientListEntry *pNextEntry;
3453     int scr;
3454
3455
3456     for (scr=0; scr<wmGD.numScreens; scr++)
3457     {
3458         if(wmGD.Screens[scr].managed)
3459         {
3460             
3461             /*
3462              * Set up the _MOTIF_WM_INFO property on the root window 
3463              * to indicate a restart.
3464              */
3465             
3466             SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
3467 #ifdef WSM
3468             SaveResources(&wmGD.Screens[scr]);
3469 #endif /* WSM */
3470             /*
3471              * Unmap client windows and reparent them to the root window.
3472              */
3473             
3474             pNextEntry = wmGD.Screens[scr].lastClient;
3475             while (pNextEntry)
3476             {
3477                 if (pNextEntry->type == NORMAL_STATE)
3478                 {
3479                     if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
3480                     {
3481                         if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
3482                         {
3483                             XUnmapWindow (DISPLAY, 
3484                                           pNextEntry->pCD->clientFrameWin);
3485                         }
3486                     }
3487                     else
3488                     {
3489                         DeFrameClient (pNextEntry->pCD);
3490                     }
3491                 }
3492                 pNextEntry = pNextEntry->prevSibling;
3493             }
3494 #if defined(PANELIST)
3495             UnParentControls (&wmGD.Screens[scr], True);
3496 #endif /* PANELIST */
3497         }
3498         
3499     }
3500     
3501 #ifdef WSM
3502     /* shut down the messaging connection */
3503     dtCloseIPC();
3504 #endif /* WSM */
3505     ResignFromSM();
3506
3507     /*
3508      * This fixes restart problem when going from explicit focus to
3509      * pointer focus.  Window under pointer was not getting focus indication
3510      * until pointer was moved to new window, or out of and into the
3511      * window.
3512      */
3513
3514     XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
3515     XSync (DISPLAY, False);
3516
3517 #ifdef WSM
3518     CLOSE_FILES_ON_EXEC();
3519     _DtEnvControl(DT_ENV_RESTORE_PRE_DT); 
3520 #endif /* WSM */
3521     /*
3522      * Restart the window manager with the initial arguments plus
3523      * the restart settings.
3524      */
3525
3526     execvp (*(wmGD.argv), wmGD.argv);
3527
3528 #ifdef WSM
3529     Warning (((char *)GETMESSAGE(26, 1, 
3530 "The window manager restart failed. The window manager program could not \
3531 be found or could not be executed.")));
3532 #else /* WSM */
3533     Warning ("Cannot restart the window manager");
3534 #endif /* WSM */
3535     Do_Quit_Mwm (True);
3536
3537
3538
3539 } /* END OF FUNCTION RestartWm */
3540
3541 \f
3542 /*************************************<->*************************************
3543  *
3544  *  DeFrameClient (pCD)
3545  *
3546  *
3547  *  Description:
3548  *  -----------
3549  *  Unmaps a client window (and client icon window) and reparents the
3550  *  window back to the root.
3551  *
3552  *
3553  *  Inputs:
3554  *  -------
3555  *  pCD = pointer to the client data for the window to be de-framed.
3556  *
3557  *************************************<->***********************************/
3558
3559 void DeFrameClient (ClientData *pCD)
3560 {
3561     int x, y;
3562     int xoff, yoff;
3563     XWindowChanges windowChanges;
3564
3565     while (pCD)
3566     {
3567         if (pCD->clientState != MINIMIZED_STATE)
3568         {
3569             XUnmapWindow (DISPLAY, pCD->clientFrameWin);
3570         }
3571
3572         if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
3573         {
3574             XUnmapWindow (DISPLAY, pCD->iconWindow);
3575             XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
3576 #ifdef WSM
3577             XReparentWindow (DISPLAY, pCD->iconWindow, 
3578                 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX, 
3579                 pCD->pWsList->iconY);
3580 #else /* WSM */
3581             XReparentWindow (DISPLAY, pCD->iconWindow, 
3582                 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
3583 #endif /* WSM */
3584         }
3585
3586         if (pCD->maxConfig)
3587         {
3588             x = pCD->maxX;
3589             y = pCD->maxY;
3590         }
3591         else
3592         {
3593             if(wmGD.positionIsFrame)
3594             {
3595                 CalculateGravityOffset (pCD, &xoff, &yoff);
3596                 x = pCD->clientX - xoff;
3597                 y = pCD->clientY - yoff;
3598             }
3599             else
3600             {
3601                 x = pCD->clientX;
3602                 y = pCD->clientY;
3603             }
3604         }
3605
3606 #ifndef UNMAP_ON_RESTART
3607         if (pCD->clientState == MINIMIZED_STATE)
3608         {
3609             XUnmapWindow (DISPLAY, pCD->client);
3610         }
3611 #else
3612         XUnmapWindow (DISPLAY, pCD->client);
3613 #endif
3614         XRemoveFromSaveSet (DISPLAY, pCD->client);
3615         XReparentWindow (DISPLAY, pCD->client, 
3616             ROOT_FOR_CLIENT(pCD), x, y);
3617
3618         if (pCD->transientChildren)
3619         {
3620             DeFrameClient (pCD->transientChildren);
3621         }
3622
3623         /*
3624          * restore X border
3625          */
3626         windowChanges.x = x;
3627         windowChanges.y = y;
3628         windowChanges.border_width = pCD->xBorderWidth;
3629         XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
3630                           &windowChanges);
3631
3632         if (pCD->transientLeader)
3633         {
3634             pCD = pCD->transientSiblings;
3635         }
3636         else
3637         {
3638             pCD = NULL;
3639         }
3640     }
3641
3642 } /* END OF FUNCTION DeFrameClient */
3643
3644 #if defined(PANELIST)
3645 \f
3646 /******************************<->*************************************
3647  *
3648  *  F_Toggle_Front_Panel (args, pCD, event)
3649  *
3650  *
3651  *  Description:
3652  *  -----------
3653  *  This is the window manager function handler for toggling the
3654  *  front panel off and on.
3655  ******************************<->***********************************/
3656
3657 Boolean
3658 F_Toggle_Front_Panel (String args, ClientData *pCD, XEvent *event)
3659 {
3660
3661     WmPanelistObject  pPanelist;
3662
3663     if (pCD)
3664     {
3665         pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3666     }
3667     else
3668     {
3669         pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3670     }
3671
3672     pCD = NULL;
3673     if (pPanelist)
3674     {
3675         (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3676                             wmGD.windowContextType, (caddr_t *)&pCD);
3677     }
3678
3679
3680     if (pCD)
3681     {
3682         if (pCD->clientState & MINIMIZED_STATE)
3683         {
3684             SetClientState (pCD, NORMAL_STATE, 
3685                     GetFunctionTimestamp ((XButtonEvent *)event));
3686         }
3687         else
3688         {
3689             SetClientState (pCD, MINIMIZED_STATE, 
3690                     GetFunctionTimestamp ((XButtonEvent *)event));
3691         }
3692     }
3693
3694     return(True);
3695 } /* END OF FUNCTION F_Toggle_Front_Panel */
3696
3697 \f
3698 /******************************<->*************************************
3699  *
3700  *  Boolean F_Version (String args, ClientData *pCD, XEvent *event)
3701  *
3702  *  Description:
3703  *  -----------
3704  *  Invoke the help on version dialogue.
3705  *
3706  *  Inputs:
3707  *  ------
3708  *  args - incoming values
3709  *  pCD  - associated client data structure
3710  *  event - what triggered this call
3711  * 
3712  *  Outputs:
3713  *  -------
3714  *  Return - True if the call occurs; false otherwise.
3715  *
3716  *  Comments:
3717  *  --------
3718  *
3719  ******************************<->***********************************/
3720 Boolean
3721 F_Version (String args, ClientData *pCD, XEvent *event)
3722 {
3723
3724     WmPanelistObject  pPanelist;
3725
3726     if (pCD)
3727     {
3728         pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3729     }
3730     else
3731     {
3732         pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3733     }
3734
3735     if (pPanelist)
3736     {
3737         WmDtHelpOnVersion (O_Shell (pPanelist));
3738     }
3739
3740     return (True);
3741
3742 }  /* END OF FUNCTION F_Version */
3743 #endif /* PANELIST */
3744
3745 \f
3746 /******************************<->*************************************
3747  *
3748  *  F_Send_Msg (args, pCD, event)
3749  *
3750  *
3751  *  Description:
3752  *  -----------
3753  *  This is the window manager function handler for sending a client
3754  *  message event to a client window.
3755  *
3756  *
3757  *  Inputs:
3758  *  ------
3759  *  args = (immediate value) message id
3760  *
3761  *  pCD = pointer to the client data
3762  *
3763  *  event = X event that invoked the function (key, button, or menu/NULL)
3764  *
3765  *
3766  ******************************<->***********************************/
3767
3768 Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
3769 {
3770     register int i;
3771
3772
3773     if (pCD && pCD->mwmMessagesCount)
3774     {
3775         /*
3776          * A message id must be made "active" by being included in the
3777          * _MWM_MESSAGES property before the associated message can be sent.
3778          */
3779
3780         for (i = 0; i < pCD->mwmMessagesCount; i++)
3781         {
3782             if (pCD->mwmMessages[i] == (long)args)
3783             {
3784                 SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES, 
3785                     (long)args, CurrentTime, NULL, 0);
3786                 return (True);
3787             }
3788         }
3789     }
3790
3791     return (True);
3792
3793 } /* END OF FUNCTION F_Send_Msg */
3794
3795
3796 \f
3797 /*************************************<->*************************************
3798  *
3799  *  F_Separator (args, pCD, event)
3800  *
3801  *
3802  *  Description:
3803  *  -----------
3804  *  This is a placeholder function; it should never be called.
3805  *
3806  *************************************<->***********************************/
3807
3808 Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
3809 {
3810
3811     return (True);
3812
3813 } /* END OF FUNCTION F_Separator */
3814
3815
3816 Boolean ForceRaiseWindow (ClientData *pcd)
3817 {
3818 #if 0
3819     Window stackWindow;
3820     WmScreenData *pSD = (ACTIVE_WS)->pSD;
3821 #endif
3822     XWindowChanges changes;
3823     Boolean restack = False;
3824
3825 #if 0
3826     if (pSD->clientList->type == MINIMIZED_STATE)
3827     {
3828         stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
3829     }
3830     else
3831     {
3832         stackWindow = pSD->clientList->pCD->clientFrameWin;
3833     }
3834 #endif
3835
3836     /*
3837      * Windows did not raise on regular f.raise because the raise was
3838      * not relative to another window (methinks).
3839      */
3840     changes.stack_mode = Above;
3841     XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
3842                       &changes);
3843
3844     return (restack);
3845 }
3846
3847
3848 \f
3849 /*************************************<->*************************************
3850  *
3851  *  F_Raise (args, pCD, event)
3852  *
3853  *
3854  *  Description:
3855  *  -----------
3856  *  This is the window manager function handler for topping the client window
3857  *  so that it is unobscured.
3858  *
3859  *************************************<->***********************************/
3860
3861 Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
3862 {
3863     ClientListEntry *pEntry;
3864     ClientListEntry *pNextEntry;
3865     ClientListEntry *pStackEntry;
3866     String string = args;
3867     int flags = STACK_NORMAL;
3868 #ifdef WSM
3869         WmWorkspaceData *pWS = ACTIVE_WS;
3870 #endif /* WSM */
3871
3872     if (string)
3873     {
3874         /* process '-client' argument */
3875         if (string[0] == '-')
3876         {
3877             string = &string[1];
3878             string = (String) GetString ((unsigned char **) &string);
3879
3880             pStackEntry = NULL;
3881             pNextEntry = ACTIVE_PSD->clientList;
3882             while (pNextEntry &&
3883                    (pEntry = FindClientNameMatch (pNextEntry, True, string,
3884                                                   F_GROUP_ALL)))
3885             {
3886                 pNextEntry = pEntry->nextSibling;
3887 #ifdef WSM
3888                 if (ClientInWorkspace (pWS, pEntry->pCD))
3889                 {
3890 #endif /* WSM */
3891                 Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3892                 pStackEntry = pEntry;
3893 #ifdef WSM
3894                 }
3895 #endif /* WSM */
3896             }
3897         }
3898         /* process family stacking stuff */
3899         else if (*string)
3900         {
3901             unsigned int  slen, len, index;
3902
3903             slen = strlen(args) - 2;            /* subtract '\n' and NULL */
3904             for (index = 0; index < slen; string = &args[index+1])
3905             {
3906                 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3907                    break;
3908                 len = strlen(string);
3909                 if (!strcmp(string,"within"))
3910                 {
3911                     flags |= STACK_WITHIN_FAMILY;
3912                 }
3913                 else if (!strcmp(string,"freeFamily"))
3914                 {
3915                     flags |= STACK_FREE_FAMILY;
3916                 }
3917                 index += len;
3918             }
3919 #ifdef WSM
3920             if (ClientInWorkspace (pWS, pCD))
3921             {
3922 #endif /* WSM */
3923             Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3924 #ifdef WSM
3925             }
3926 #endif /* WSM */
3927         }
3928     }
3929     else if (pCD)
3930     {
3931 #ifdef WSM
3932         if (ClientInWorkspace (pWS, pCD))
3933         {
3934 #endif /* WSM */
3935         Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3936 #ifdef WSM
3937         }
3938 #endif /* WSM */
3939     }
3940
3941     return (True);
3942
3943 } /* END OF FUNCTION F_Raise */
3944
3945
3946 \f
3947 /*************************************<->*************************************
3948  *
3949  *  Do_Raise (pCD, pStackEntry)
3950  *
3951  *
3952  *  Description:
3953  *  -----------
3954  *  This is the window manager function handler for topping the client window
3955  *  so that it is unobscured.
3956  *
3957  *
3958  *  Inputs:
3959  *  ------
3960  *  pCD = pointer to the client data of the window (or icon) to be raised.
3961  * 
3962  *  pStackEntry = pointer to client list entry for window that is to be 
3963  *      above the raised window (if NULL window is raised to the top of the
3964  *      stack).
3965  *
3966  *************************************<->***********************************/
3967
3968 void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3969 {
3970     Boolean restackTransients;
3971     ClientData *pcdLeader;
3972     WmWorkspaceData *pWS = ACTIVE_WS;
3973 #ifdef WSM
3974     Boolean bLeaderRestacked;
3975 #endif /* WSM */
3976
3977 #ifdef PANELIST
3978     if (pCD->pECD)
3979     {
3980         /*
3981          * Window has been reparented into the front panel. 
3982          * Don't follow through on window stacking change.
3983          */
3984         return;
3985     }
3986     else 
3987 #else /* PANELIST */
3988 #endif /* PANELIST */
3989 #ifdef WSM
3990     if (ClientInWorkspace(pWS, pCD)  && 
3991         (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
3992     {
3993         /* 
3994          * Both clients are in the current workspace. Set
3995          * client indices so that the access macros work.
3996          */
3997         SetClientWsIndex (pCD);
3998         if (pStackEntry)
3999         {
4000             SetClientWsIndex (pStackEntry->pCD);
4001         }
4002     }
4003     else
4004     {
4005         /*
4006          * One or both of the clients are not in the current workspace
4007          * Do nothing.
4008          */
4009         return;
4010     }
4011 #endif /* WSM */
4012
4013     pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
4014
4015     if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
4016     {
4017         /*
4018          * Don't raise the window above the system modal window.
4019          */
4020     }
4021     else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
4022              !P_ICON_BOX(pcdLeader))
4023     {
4024         /*
4025          * If a dirtyStackEntry exists, return it to its original place 
4026          * in the stack (for all stacking types)
4027          */
4028         if (dirtyStackEntry)
4029         {
4030             if (dirtyStackEntry->transientChildren ||
4031                 dirtyStackEntry->transientLeader)
4032                 RestackTransients (dirtyStackEntry);
4033             dirtyStackEntry = NULL;
4034             dirtyLeader = NULL;
4035         }
4036
4037         /*
4038          * Only restack the icon if it is not currently raised.
4039          */
4040
4041         if (pStackEntry)
4042         {
4043             if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
4044             {
4045                 StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
4046                              pStackEntry);
4047                 MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
4048                                  pStackEntry);
4049             }
4050         }
4051         else
4052         {
4053             if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
4054             {
4055                 StackWindow (pWS, &pcdLeader->iconEntry, 
4056                     True /*on top*/, (ClientListEntry *) NULL);
4057                 MoveEntryInList (pWS, &pcdLeader->iconEntry, 
4058                     True /*on top*/, (ClientListEntry *) NULL);
4059             }
4060         }
4061     }
4062     else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
4063     {
4064 #ifdef WSM
4065         /*
4066          * Handle restacking of primary/secondary windows
4067          * within the transient window tree. Don't raise this
4068          * window above any modal transients.
4069          */
4070         bLeaderRestacked = False;
4071         if ((pcdLeader->transientChildren) &&
4072             (!pCD->secondariesOnTop) &&
4073             (!wmGD.bSuspendSecondaryRestack) &&
4074             (!IS_APP_MODALIZED(pCD)))
4075         {
4076             if (pCD != pcdLeader)
4077             {
4078                 /* 
4079                  * This is not the transient leader, make sure
4080                  * the transient leader isn't on top.
4081                  * (Brute force solution)
4082                  */
4083                 bLeaderRestacked = NormalizeTransientTreeStacking (pcdLeader);
4084
4085                 if (pCD->transientChildren)
4086                 {
4087                     /*
4088                      * This isn't the overall leader of the transient 
4089                      * tree, but it does have transient's of its own.
4090                      * Move it to the top of its own transient sub-tree.
4091                      */
4092                     bLeaderRestacked |= BumpPrimaryToTop (pCD);
4093                 }
4094             }
4095             else 
4096             {
4097                 /*
4098                  * This is the transient leader, move it to the
4099                  * top.
4100                  */
4101                 bLeaderRestacked = BumpPrimaryToTop (pcdLeader);
4102             }
4103
4104         }
4105 #endif /* WSM */
4106         /*
4107          * If this is a transient window then put it on top of its
4108          * sibling transient windows.
4109          */
4110
4111         restackTransients = False;
4112
4113
4114 /*
4115  * Fix for 5325 - The following code has been reorganized to cause the
4116  *                action of F_Raise to match the current documentation.
4117  *                The new algorithm is as follows:
4118  *
4119  *                if (dirtyStackEntry)
4120  *                  restore dirty tree
4121  *                if (not withinFamily)
4122  *                  bring window group to the top of global stack
4123  *                if (freeFamily)
4124  *                  raise the requested window to top of family
4125  *                else
4126  *                  raise requested window to top of siblings
4127  *                if (need to restack windows)
4128  *                  restack windows
4129  *                return
4130  */
4131         /*
4132          * If a dirtyStackEntry exists, return it to its original place 
4133          * in the stack (for all stacking types)
4134          */
4135         if (dirtyStackEntry)
4136         {
4137             /*
4138              * Check to make sure that the dirty pCD has either transient
4139              * children or a transient leader.  If not, do not restore
4140              * the transients.
4141              */
4142             if (dirtyStackEntry->transientChildren ||
4143                 dirtyStackEntry->transientLeader)
4144                 RestackTransients (dirtyStackEntry);
4145             dirtyStackEntry = NULL;
4146             dirtyLeader = NULL;
4147         }
4148
4149         /*
4150          * If the flags do not indicate "within", raise the window family
4151          * to the top of the window stack. If the window is the primary,
4152          * raise it to the top regardless of the flags.
4153          */
4154         if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
4155         {
4156             if (pStackEntry)
4157             {
4158                 if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
4159                 {
4160                     StackWindow (pWS, &pcdLeader->clientEntry, 
4161                         False /*below*/, pStackEntry);
4162                     MoveEntryInList (pWS, &pcdLeader->clientEntry, 
4163                         False /*below*/, pStackEntry);
4164                 }
4165             }
4166             else
4167             {
4168                 if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
4169                 {
4170                     StackWindow (pWS, &pcdLeader->clientEntry,
4171                         True /*on top*/, (ClientListEntry *) NULL);
4172                     MoveEntryInList (pWS, &pcdLeader->clientEntry,
4173                         True /*on top*/, (ClientListEntry *) NULL);
4174                 }
4175             }
4176         }
4177   
4178         /*
4179          * If freeFamily stacking is requested, check to make sure that
4180          * the window has either a transientChild or Leader.  This will
4181          * guarantee that windows that form their own family are not
4182          * labelled as dirty (what's to dirty it up?).  If it has either,
4183          * raise the window to the top of the family stack.
4184          */
4185         if ((flags & STACK_FREE_FAMILY) &&
4186             (pCD->transientLeader || pCD->transientChildren))
4187         {
4188             dirtyStackEntry = pCD;
4189             dirtyLeader = pcdLeader;
4190   
4191             restackTransients = ForceRaiseWindow (pCD);
4192         }
4193   
4194         /*
4195          * If withinFamily stacking is requested, put the current transient
4196          * on top of its sibling transient windows.
4197          */
4198         else
4199         {
4200             restackTransients = PutTransientOnTop (pCD);
4201         }
4202   
4203         /* At this point, if doing a regular f.raise the window family has
4204          * already been brought to the top of the stack, so nothing further
4205          * needs to be done for it.
4206          */
4207   
4208         /* Restack the transients if needed */
4209   
4210 #ifdef WSM
4211         if ((restackTransients) || (bLeaderRestacked))
4212 #else /* WSM */
4213         if (restackTransients)
4214 #endif /* WSM */
4215         {
4216             RestackTransients (pCD);
4217         }
4218     }
4219
4220 } /* END OF FUNCTION Do_Raise */
4221
4222
4223 \f
4224 /*************************************<->*************************************
4225  *
4226  *  F_Raise_Lower (args, pCD, event)
4227  *
4228  *
4229  *  Description:
4230  *  -----------
4231  *  This window manager function tops an obscured window or icon and bottoms 
4232  *  a window or icon that is on top of the window stack.
4233  *
4234  *************************************<->***********************************/
4235
4236 Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
4237 {
4238     ClientData *pcdLeader;
4239
4240     if (pCD)
4241     {
4242         pcdLeader = (pCD->transientLeader) ?
4243                                         FindTransientTreeLeader (pCD) : pCD;
4244
4245         /*
4246          * Treat a raise/lower on a window in a transient tree as if it is
4247          * a raise/lower for the whole tree.
4248          */
4249
4250         if (CheckIfClientObscuredByAny (pcdLeader))
4251         {
4252             /*
4253              * The window is obscured by another window, raise the window.
4254              */
4255
4256 #ifdef WSM
4257             F_Raise (NULL, pCD, (XEvent *)NULL);
4258 #else /* WSM */
4259             F_Raise (NULL, pcdLeader, (XEvent *)NULL);
4260 #endif /* WSM */
4261         }
4262         else if (CheckIfClientObscuringAny (pcdLeader) &&
4263                 !(wmGD.systemModalActive &&
4264                  (pcdLeader == wmGD.systemModalClient)))
4265         {
4266             /*
4267              * The window is obscuring another window and is
4268              * not system modal, lower the window.
4269              */
4270
4271             F_Lower (NULL, pcdLeader, (XEvent *)NULL);
4272 #ifdef WSM
4273             if ((pcdLeader->secondariesOnTop == False) &&
4274                 (pCD->transientLeader != NULL) &&
4275                 (!IS_APP_MODALIZED(pcdLeader)))
4276             {
4277                 /* Push transient below primary */
4278                 (void) BumpPrimaryToTop (pcdLeader);
4279                 RestackTransients (pcdLeader);
4280             }
4281 #endif /* WSM */
4282         }
4283 #ifdef WSM
4284         else if ((pcdLeader->secondariesOnTop == False) &&
4285                  (pcdLeader->transientChildren != NULL) &&
4286                  (!wmGD.systemModalActive) &&
4287                  (!IS_APP_MODALIZED(pcdLeader)))
4288         {
4289             if (LeaderOnTop(pcdLeader))
4290             {
4291                 /* Push primary below transient */
4292                 (void) BumpPrimaryToBottom (pcdLeader);
4293                 RestackTransients (pcdLeader);
4294             }
4295             else
4296             {
4297                 F_Raise (NULL, pCD, (XEvent *)NULL);
4298                 /* Push transient below primary */
4299                 (void) BumpPrimaryToTop (pcdLeader);
4300                 RestackTransients (pcdLeader);
4301             }
4302         }
4303 #endif /* WSM */
4304     }
4305
4306     return (True);
4307
4308 } /* END OF FUNCTION F_Raise_Lower */
4309
4310
4311 \f
4312 /*************************************<->*************************************
4313  *
4314  *  F_Refresh_Win (args, pCD, event)
4315  *
4316  *
4317  *  Description:
4318  *  -----------
4319  *  This is the window manager function handler for causing a client window
4320  *  to redisplay itself.
4321  *
4322  *************************************<->***********************************/
4323
4324 Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
4325 {
4326     Window win;
4327     unsigned int w, h;
4328
4329     if (pCD && ((pCD->clientState == NORMAL_STATE) ||
4330                 (pCD->clientState == MAXIMIZED_STATE)))
4331     {
4332         if (pCD->clientState == NORMAL_STATE)
4333         {
4334             w = (unsigned int) pCD->clientWidth;
4335             h = (unsigned int) pCD->clientHeight;
4336         }
4337         else
4338         {
4339             w = (unsigned int) pCD->maxWidth;
4340             h = (unsigned int) pCD->maxHeight;
4341         }
4342
4343 #ifdef WSM
4344         if (wmGD.refreshByClearing)
4345         {
4346             RefreshByClearing (pCD->clientFrameWin);
4347         }
4348         else
4349         {
4350 #endif /* WSM */
4351                          /* default background_pixmap is None */
4352         win = XCreateWindow (DISPLAY,
4353                          pCD->clientBaseWin,
4354                          pCD->matteWidth,
4355                          pCD->matteWidth,
4356                          w, h,
4357                          0, 
4358                          0,
4359                          InputOutput,
4360                          CopyFromParent,
4361                          0, 
4362                          (XSetWindowAttributes *)NULL);  
4363
4364         XMapWindow (DISPLAY, win);
4365         XDestroyWindow (DISPLAY, win);
4366 #ifdef WSM
4367         }
4368 #endif /* WSM */
4369         XFlush (DISPLAY);
4370     }
4371
4372     return (True);
4373
4374 } /* END OF FUNCTION F_Refresh_Win */
4375
4376
4377 \f
4378 /*************************************<->*************************************
4379  *
4380  *  F_Set_Behavior (args, pCD, event)
4381  *
4382  *
4383  *  Description:
4384  *  -----------
4385  *  This function is used to switch the window manager configuration between
4386  *  the built-in configuration (for CXI behavior) and the user's custom
4387  *  configuration.
4388  *
4389  *************************************<->***********************************/
4390
4391 Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
4392 {
4393     /*
4394      * Go system modal in starting to do the set behavior.
4395      */
4396
4397     /* !!! grab the server and the pointer !!! */
4398
4399
4400     /*
4401      * Confirm that a set_behavior should be done.
4402      * Execute restart if so.
4403      */
4404
4405     if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
4406     {
4407         ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
4408                        CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
4409     }
4410     else
4411     {
4412         RestartWm ((long) ((wmGD.useStandardBehavior) ?
4413                         MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4414     }
4415     return (False);
4416
4417 } /* END OF FUNCTION F_Set_Behavior */
4418
4419
4420 \f
4421 /*************************************<->*************************************
4422  *
4423  *  Do_Set_Behavior (dummy)
4424  *
4425  *
4426  *  Description:
4427  *  -----------
4428  *  Callback to do the f.set_behavior function.
4429  *
4430  *************************************<->***********************************/
4431
4432 void Do_Set_Behavior (Boolean dummy)
4433 {
4434     RestartWm ((long) ((wmGD.useStandardBehavior) ?
4435                         MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4436
4437 } /* END OF FUNCTION Do_Set_Behavior */
4438
4439 #ifdef WSM
4440 \f
4441 /*************************************<->*************************************
4442  *
4443  *  F_Set_Context (args, pCD, event)
4444  *
4445  *
4446  *  Description:
4447  *  -----------
4448  *  This function is used to set a client context for subsequent
4449  *  WM_REQUESTs
4450  *
4451  *************************************<->***********************************/
4452
4453 Boolean F_Set_Context (String args, ClientData *pCD, XEvent *event)
4454 {
4455  
4456     wmGD.requestContextWin = (Window) args;
4457     return (True);
4458
4459 } /* END OF FUNCTION F_Set_Context */
4460 #endif /* WSM */
4461
4462 \f
4463 /*************************************<->*************************************
4464  *
4465  *  F_Title (args, pCD, event)
4466  *
4467  *
4468  *  Description:
4469  *  -----------
4470  *  This is a placeholder function; it should never be called.
4471  *
4472  *************************************<->***********************************/
4473
4474 Boolean F_Title (String args, ClientData *pCD, XEvent *event)
4475 {
4476
4477     return (True);
4478
4479 } /* END OF FUNCTION F_Title */
4480
4481
4482 \f
4483 /******************************<->*************************************
4484  *
4485  *  F_Screen (args, pCD, event)
4486  *
4487  *
4488  *  Description:
4489  *  -----------
4490  *  This is the window manager function handler for warping to screens
4491  *
4492  *
4493  *  Inputs:
4494  *  ------
4495  *  args = (immediate value) window type flags
4496  *
4497  *  pCD = pointer to the client data
4498  *
4499  *  event = X event that invoked the function (key, button, or menu/NULL)
4500  *
4501  *  NOTE: May want to consider tracking changes in screen because in
4502  *        managing a new window (ie. in ManageWindow()).
4503  *
4504  *  Outputs:
4505  *  -------
4506  *  RETURN = if True then further button binding/function processing can
4507  *           be done for the event that caused this function to be called.
4508  *
4509  *************************************<->***********************************/
4510
4511 Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
4512 {
4513     Window dumwin;
4514     int x, y, dumint;
4515     unsigned int dummask;
4516     WmScreenData *newscr = NULL;
4517     int scr, inc;
4518     static int PreviousScreen = -1;
4519     char pch[80];
4520     
4521
4522     if (PreviousScreen == -1)
4523     {
4524         PreviousScreen = DefaultScreen(DISPLAY);
4525     }
4526
4527     if (strcmp (args, "next") == 0)
4528     {
4529         scr = ACTIVE_PSD->screen + 1;
4530         inc = 1;
4531     }
4532     else if (strcmp (args, "prev") == 0)
4533     {
4534         scr = ACTIVE_PSD->screen - 1;
4535         inc = -1;
4536     }
4537     else if (strcmp (args, "back") == 0)
4538     {
4539         scr = PreviousScreen;
4540         inc = 0;
4541     }
4542     else
4543     {
4544         scr = atoi (args);
4545         inc = 0;
4546     }
4547
4548     while (!newscr) {
4549                                         /* wrap around */
4550         if (scr < 0) 
4551           scr = wmGD.numScreens - 1;
4552         else if (scr >= wmGD.numScreens)
4553           scr = 0;
4554
4555         newscr = &(wmGD.Screens[scr]);
4556         if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
4557             if (inc) {                  /* walk around the list */
4558                 scr += inc;
4559                 continue;
4560             }
4561             sprintf(pch, 
4562                     "Unable to warp to unmanaged screen %d\n", scr);
4563             Warning (&pch[0]);
4564             XBell (DISPLAY, 0);
4565             return (False);
4566         }
4567     }
4568
4569     if (ACTIVE_PSD->screen == scr) return (False);  /* already on that screen */
4570
4571     PreviousScreen = ACTIVE_PSD->screen;
4572     XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
4573                    &dumint, &dumint, &dummask);
4574
4575     XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
4576
4577     if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
4578     {
4579         /*
4580          * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can 
4581          * uses the new screen instead of the old screen.  Then call
4582          * Do_Focus_Key with a NULL pCD to find a reasonable client to
4583          * set focus to.
4584          */
4585         SetActiveScreen (newscr);
4586         Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
4587                       ALWAYS_SET_FOCUS);
4588     }
4589
4590     return (False);
4591 }
4592
4593
4594 \f
4595 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
4596 /*************************************<->*************************************
4597  *
4598  *  F_InvokeCommand (args, pCD, event)
4599  *
4600  *
4601  *  Description:
4602  *  -----------
4603  *  This is the window manager function for invoking client inserted menu
4604  *  commands.
4605  *
4606  *************************************<->***********************************/
4607
4608 Boolean F_InvokeCommand (String args, ClientData *pCD, XEvent *event)
4609 {
4610     CARD32 commandID, clientWindow;
4611     Atom notifySelection;
4612
4613     if (args == (String) NULL) return(FALSE);
4614
4615     if (sscanf(args, "%d %d %ld", &commandID, &clientWindow,
4616                &notifySelection) != 3)
4617       return(FALSE);
4618
4619     SendInvokeMessage(commandID,
4620                       (pCD == (ClientData *) NULL ? 0 : pCD->client),
4621                       notifySelection,
4622                       LastTime());
4623
4624     return (True);
4625 } /* END OF FUNCTION F_InvokeCommand */
4626 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
4627
4628 \f
4629 /*************************************<->*************************************
4630  *
4631  *  GetFunctionTimestamp (pEvent)
4632  *
4633  *
4634  *  Description:
4635  *  -----------
4636  *  This function is used to extract a timestamp from a key or button event.
4637  *  If the event passed in is not a key or button event then a timestamp
4638  *  is generated.
4639  *
4640  *
4641  *  Inputs:
4642  *  ------
4643  *  event = pointer to an X event
4644  *
4645  *
4646  *  Outputs:
4647  *  -------
4648  *  RETURN = a timestamp
4649  *
4650  *************************************<->***********************************/
4651
4652 Time GetFunctionTimestamp (XButtonEvent *pEvent)
4653 {
4654     Time time;
4655
4656     if (pEvent &&
4657         (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
4658          ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
4659     {
4660         time = pEvent->time;
4661     }
4662     else
4663     {
4664         time = GetTimestamp ();
4665     }
4666
4667     return (time);
4668
4669 } /* END OF FUNCTION GetFunctionTimestamp */
4670
4671
4672 /*
4673 ** name the event mask we need for a grab in order to find the matching 
4674 ** event for an event; right now handle only button-presses
4675 */
4676 static unsigned int GetEventInverseMask(XEvent *event)
4677 {
4678         if ((XEvent*)NULL == event)
4679                 return 0;
4680         if (ButtonPress == event->type)
4681                 return ButtonReleaseMask;       /* detail ? */
4682         /*
4683         expansion further here
4684         */
4685         else 
4686                 return 0;
4687 }
4688
4689
4690
4691 /*************************************<->*************************************
4692  *
4693  *  ClearDirtyStackEntry (pCD)
4694  *
4695  *
4696  *  Description:
4697  *  -----------
4698  *  This function is used to clear the static dirtyStackEntry structure and
4699  *  the dirtyLeader static variable when a pCD is destroyed.  This 
4700  *  guarantees that freed memory will not be accessed.
4701  *
4702  *
4703  *  Inputs:
4704  *  ------
4705  *  pCD = pointer to clientData being freed
4706  *
4707  *
4708  *  Outputs:
4709  *  -------
4710  *  RETURN = void
4711  *
4712  *************************************<->***********************************/
4713
4714 void ClearDirtyStackEntry (ClientData *pCD)
4715 {
4716   if (pCD == dirtyStackEntry)
4717     {
4718       dirtyStackEntry = NULL;
4719       dirtyLeader = NULL;
4720     }
4721 }
4722 #if defined(DEBUG) && defined(WSM)
4723 \f
4724 /***********************<->*************************************
4725  *
4726  *  F_ZZ_Debug (args, pCD, event)
4727  *
4728  *
4729  *  Description:
4730  *  -----------
4731  *  This is the window manager debug (multi) function
4732  *
4733  *
4734  *  Inputs:
4735  *  ------
4736  *  args = arguments
4737  *
4738  *  pCD = pointer to the ClientData for the whole front panel
4739  *
4740  *  event = X event that invoked the function (key, button, or menu/NULL)
4741  *
4742  *
4743  *  Outputs:
4744  *  -------
4745  *  RETURN = if True then further button binding/function processing can
4746  *           be done for the event that caused this function to be called.
4747  *
4748  *  Comments:
4749  *  -------
4750  *  Argument 1 determines the debug function to execute:
4751  *
4752  *  Valid arguments:
4753  *
4754  *      "color_server_info"  - dump out color server info
4755  *
4756  ******************************<->***********************************/
4757
4758 Boolean
4759 F_ZZ_Debug (String subFcn, ClientData *pCD, XEvent *event)
4760 {
4761     /* Only do something is sub function is specified */
4762
4763     if (subFcn)
4764     {
4765         if (!(strcmp(subFcn, "dump_resources")))
4766         {
4767             int scr;
4768             char szRes[80];
4769
4770             for (scr=0; scr<wmGD.numScreens; scr++)
4771             {
4772                 sprintf (szRes, "/tmp/dtwm.resources.%d", scr);
4773
4774                 XrmPutFileDatabase(XtScreenDatabase(
4775                                        XScreenOfDisplay(DISPLAY, scr)), 
4776                                    szRes);
4777             }
4778         }
4779     }
4780     return (True);
4781 }
4782 #endif /* DEBUG */
4783
4784 #ifdef WSM
4785 \f
4786 /*************************************<->*************************************
4787  *
4788  *  F_Next_Workspace (args, pCD, event)
4789  *
4790  *
4791  *  Description:
4792  *  -----------
4793  *  This function switches to the next workspace in the list
4794  *
4795  *************************************<->***********************************/
4796
4797 Boolean F_Next_Workspace (String args, ClientData *pCD, XEvent *event)
4798 {
4799     WmScreenData *pSD = ACTIVE_PSD;
4800     int iwsx;
4801
4802     for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4803     {
4804         if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4805         {
4806             iwsx++;
4807             break;
4808         }
4809     }
4810
4811     /* check bounds and wrap */
4812     if (iwsx >= pSD->numWorkspaces)
4813         iwsx = 0;
4814
4815     ChangeToWorkspace (&pSD->pWS[iwsx]);
4816
4817
4818     return (False);
4819
4820 } /* END OF FUNCTION F_Next_Workspace */
4821
4822 \f
4823 /*************************************<->*************************************
4824  *
4825  *  F_Prev_Workspace (args, pCD, event)
4826  *
4827  *
4828  *  Description:
4829  *  -----------
4830  *  This function switches to the previous workspace in the list
4831  *
4832  *************************************<->***********************************/
4833
4834 Boolean F_Prev_Workspace (String args, ClientData *pCD, XEvent *event)
4835 {
4836     WmScreenData *pSD = ACTIVE_PSD;
4837     int iwsx;
4838
4839     for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4840     {
4841         if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4842         {
4843             iwsx--;
4844             break;
4845         }
4846     }
4847
4848     /* check bounds and wrap */
4849     if (iwsx < 0)
4850         iwsx = pSD->numWorkspaces - 1;
4851
4852     ChangeToWorkspace (&pSD->pWS[iwsx]);
4853
4854
4855     return (False);
4856
4857 } /* END OF FUNCTION F_Prev_Workspace */
4858
4859
4860 \f
4861 /*************************************<->*************************************
4862  *
4863  *  F_Workspace_Presence (args, pCD, event)
4864  *
4865  *
4866  *  Description:
4867  *  -----------
4868  *  This function pops up the workspace presence dialog box
4869  *
4870  *************************************<->***********************************/
4871
4872 Boolean F_Workspace_Presence (String args, ClientData *pCD, XEvent *event)
4873 {
4874     Context wsContext = (Context)NULL;
4875
4876     if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4877     {
4878         if (pCD->clientState == NORMAL_STATE)
4879         {
4880             wsContext = F_CONTEXT_NORMAL;
4881         }
4882         else if (pCD->clientState == MAXIMIZED_STATE)
4883         {
4884             wsContext = F_CONTEXT_MAXIMIZE;
4885         }
4886         else 
4887         {
4888             wsContext = F_CONTEXT_ICON;
4889 /*          return (False); */
4890         }
4891         ShowPresenceBox (pCD, wsContext);
4892     }
4893     return (False);
4894
4895 } /* END OF FUNCTION F_Workspace_Presence */
4896
4897 #ifdef DEBUG
4898 void
4899 DumpWindowList ()
4900 {
4901     WmScreenData *pSD = (ACTIVE_WS)->pSD;
4902     ClientListEntry     *pCLE;
4903
4904     fprintf (stdout, "Window stacking (bottom to top)\n");
4905     pCLE = pSD->lastClient;
4906     while (pCLE)
4907     {
4908         if (ClientInWorkspace (ACTIVE_WS, pCLE->pCD))
4909             fprintf (stdout, "* ");
4910         else
4911             fprintf (stdout, "  ");
4912
4913         fprintf (stdout, "%08lx\t%s\n", 
4914             pCLE->pCD->client,
4915             pCLE->pCD->clientName);
4916
4917         pCLE = pCLE->prevSibling;
4918     }
4919 }
4920 #endif /* DEBUG */
4921
4922 #endif /* WSM */
4923
4924
4925