source: trunk/third/mwm/WmFunction.c @ 9757

Revision 9757, 84.0 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9756, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
3 * ALL RIGHTS RESERVED
4*/
5/*
6 * Motif Release 1.2.3
7*/
8#ifdef REV_INFO
9#ifndef lint
10static char rcsid[] = "$RCSfile: WmFunction.c,v $ $Revision: 1.1.1.1 $ $Date: 1997-03-25 09:12:18 $"
11#endif
12#endif
13/*
14 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
15
16/*
17 * Included Files:
18 */
19
20#include <signal.h>
21#include <stdio.h>
22#include <sys/wait.h>           /* for wait() */
23#include <X11/Xos.h>
24#include "WmGlobal.h"
25#include "WmICCC.h"
26
27/*
28 * include extern functions
29 */
30#include "WmFunction.h"
31#include "WmCEvent.h"
32#include "WmCDInfo.h"
33#include "WmColormap.h"
34#include "WmError.h"
35#include "WmEvent.h"
36#include "WmFeedback.h"
37#include "WmIPlace.h"
38#include "WmIconBox.h"
39#include "WmKeyFocus.h"
40#include "WmMenu.h"
41#include "WmProperty.h"
42#include "WmProtocol.h"
43#include "WmResParse.h"
44#include "WmWinConf.h"
45#include "WmWinInfo.h"
46#include "WmWinList.h"
47#include "WmWinState.h"
48
49#include <Xm/XmosP.h>           /* for _XmOSPutenv */
50
51extern char * getenv ();
52#ifndef PORT_NOVFORK
53extern pid_t vfork();
54#endif /* PORT_NOVFORK */
55
56#ifdef _NO_PROTO
57static unsigned int GetEventInverseMask();
58#else   /* _NO_PROTO */
59static unsigned int GetEventInverseMask(XEvent *event);
60#endif  /* _NO_PROTO */
61
62/*
63 * Global Variables:
64 */
65
66/*
67 * The 'dirty' variables are used to keep track of the transient window
68 * that has been lowered via "f.lower freeFamily".
69 */
70static ClientListEntry dirtyStackEntry = { NULL, NULL, NORMAL_STATE, NULL };
71static ClientData *dirtyLeader = NULL;
72
73
74
75/******************************<->*************************************
76 *
77 *  F_Beep (args, pCD, event)
78 *
79 *
80 *  Description:
81 *  -----------
82 *  This is the window manager function handler for beeping.
83 *
84 *
85 *  Inputs:
86 *  ------
87 *  args = function arguments (specified in .mwmrc file)
88 *
89 *  pCD = pointer to the client data for the client window to which the
90 *        function is to be applied
91 *
92 *  event = X event that invoked the function (key, button, or menu/NULL)
93 *
94 *
95 *  Outputs:
96 *  -------
97 *  RETURN = if True then further button binding/function processing can
98 *           be done for the event that caused this function to be called.
99 *
100 ******************************<->***********************************/
101
102#ifdef _NO_PROTO
103Boolean F_Beep (args, pCD, event)
104    String args;
105    ClientData *pCD;
106    XEvent *event;
107
108#else /* _NO_PROTO */
109Boolean F_Beep (String args, ClientData *pCD, XEvent *event)
110#endif /* _NO_PROTO */
111{
112
113    /* !!! what is a good value for percent (the second arg) !!! */
114    XBell (DISPLAY, 0);
115
116    return (True);
117
118} /* END OF FUNCTION F_Beep */
119
120
121
122/*
123 * Handle Special case where the dirty window is the top most
124 * transient window.  When this is the case, raising the window
125 * that was on top (the window just below the dirty window) will
126 * fail because Mwm stack database is out of sync.  So the solution
127 * is to restack the dirty transient relative to the second to the
128 * top transient.  This function is used to support freeFamily stacking.
129 */
130ClientData * FindSecondToTopTransient (pcd)
131ClientData *pcd;
132{
133    ClientData *pcdNext;
134    static ClientData *second;
135
136    pcdNext = pcd->transientChildren;
137    while (pcdNext)
138    {
139        if (pcdNext->transientChildren)
140        {
141            if (!pcdNext->transientChildren->transientChildren)
142            {
143                second = pcdNext;
144            }
145            FindSecondToTopTransient (pcdNext);
146        }
147        pcdNext = pcdNext->transientSiblings;
148        if (pcdNext && !pcdNext->transientSiblings)
149        {
150            second = pcdNext;
151        }
152    }
153
154    return (second);
155
156} /* END OF FUNCTION */
157
158
159
160/*************************************<->*************************************
161 *
162 *  RestoreTransients (pcd, stack_mode)
163 *
164 *
165 *  Description:
166 *  -----------
167 *  A function to restore dirty transient windows to their original position
168 *  before changing the stack again.  This function is used to support
169 *  freeFamily stacking.
170 *
171 *************************************<->***********************************/
172#ifdef _NO_PROTO
173void RestoreTransients (pcd, stack_mode)
174     ClientData *pcd;
175     int stack_mode;
176#else /* _NO_PROTO */
177void RestoreTransients (ClientData *pcd, int stack_mode)
178#endif /* _NO_PROTO */
179{
180    ClientData *pcdLeader, *pcd_temp;
181    XWindowChanges changes;
182    Window win;
183
184    if (dirtyStackEntry.pCD)
185    {
186        pcdLeader = FindTransientTreeLeader (dirtyStackEntry.pCD);
187
188        /*
189         * Handle Special case where the dirty window is the top most
190         * transient window.  When this is the case, raising the window
191         * that was on top (the window just below the dirty window) will
192         * fail because Mwm stack database is out of sync.  So the solution
193         * is to restack the dirty transient relative to the second to the
194         * top transient.
195         */
196
197        if (dirtyStackEntry.pCD == FindTransientOnTop(pcdLeader))
198        {
199            pcd_temp = FindSecondToTopTransient (pcdLeader);
200            win = pcd_temp->clientFrameWin;
201        }
202        else
203        {
204            win = pcd->clientFrameWin;
205        }
206        changes.sibling = win;
207        changes.stack_mode = stack_mode;
208        XConfigureWindow (DISPLAY, dirtyStackEntry.pCD->clientFrameWin,
209                          (CWSibling | CWStackMode), &changes);
210
211        RestackTransients (dirtyStackEntry.pCD, False);
212    }
213}
214
215#ifdef _NO_PROTO
216Boolean ForceLowerWindow (pcd)
217        ClientData *pcd;
218#else /* _NO_PROTO */
219Boolean ForceLowerWindow (ClientData *pcd)
220#endif /* _NO_PROTO */
221{
222#if 0
223    Window stackWindow;
224    WmScreenData *pSD = (ACTIVE_WS)->pSD;
225#endif
226    XWindowChanges changes;
227    Boolean restack = False;
228
229#if 0
230    if (pSD->lastClient->type == MINIMIZED_STATE)
231    {
232        stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
233    }
234    else
235    {
236        stackWindow = pSD->lastClient->pCD->clientFrameWin;
237    }
238#endif
239
240    changes.stack_mode = Below;
241    XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
242                      &changes);
243
244    return (restack);
245}
246
247
248
249/*************************************<->*************************************
250 *
251 *  F_Lower (args, pCD, event)
252 *
253 *
254 *  Description:
255 *  -----------
256 *  This is the window manager function handler for bottoming a client window
257 *  or icon.
258 *
259 *
260 *  Inputs:
261 *  ------
262 *  args = function arguments (specified in .mwmrc file)
263 *
264 *  pCD = pointer to the client data for the client window to which the
265 *        function is to be applied
266 *
267 *  event = X event that invoked the function (key, button, or menu/NULL)
268 *
269 *
270 *  Outputs:
271 *  -------
272 *  RETURN = if True then further button binding/function processing can
273 *           be done for the event that caused this function to be called.
274 *
275 *************************************<->***********************************/
276
277#ifdef _NO_PROTO
278Boolean F_Lower (args, pCD, event)
279    String args;
280    ClientData *pCD;
281    XEvent *event;
282
283#else /* _NO_PROTO */
284Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
285#endif /* _NO_PROTO */
286{
287    ClientListEntry *pEntry;
288    ClientListEntry *pNextEntry;
289    ClientListEntry *pStackEntry;
290    String string = args;
291    int flags = STACK_NORMAL;
292
293    if (string)
294    {
295        /* process '-client' argument */
296        if (string[0] == '-')
297        {
298            string = &string[1];
299            string = (String) GetString ((unsigned char **) &string);
300
301            pStackEntry = NULL;
302            pNextEntry = ACTIVE_PSD->lastClient;
303            while (pNextEntry &&
304                   (pEntry = FindClientNameMatch (pNextEntry, False,
305                                                        string, F_GROUP_ALL)))
306            {
307                pNextEntry = pEntry->prevSibling;
308                Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
309                pStackEntry = pEntry;
310            }
311        }
312        /* process family stacking stuff */
313        else if (*string)
314        {
315            unsigned int  slen, len, index;
316
317            slen = strlen(args) - 2;            /* subtract '\n' and NULL */
318            for (index = 0; index < slen; string = &args[index+1])
319            {
320                if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
321                   break;
322                len = strlen(string);
323                if (!strcmp(string,"within"))
324                {
325                    flags |= STACK_WITHIN_FAMILY;
326                }
327                else if (!strcmp(string,"freeFamily"))
328                {
329                    flags |= STACK_FREE_FAMILY;
330                }
331                index += len;
332            }
333            Do_Lower (pCD, (ClientListEntry *) NULL, flags);
334        }
335    }
336    else if (pCD)
337    {
338        Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
339    }
340
341    wmGD.passButtonsCheck = False;
342    return (True);
343
344} /* END OF FUNCTION F_Lower */
345
346
347
348/*************************************<->*************************************
349 *
350 *  Do_Lower (pCD, pStackEntry)
351 *
352 *
353 *  Description:
354 *  -----------
355 *  This is the window manager function handler for lowering the client window
356 *  so that it does not obscure any other window above the stack entry
357 *  window.
358 *
359 *
360 *  Inputs:
361 *  ------
362 *  pCD = pointer to the client data of the window (or icon) to be lowered.
363 *
364 *  pStackEntry = pointer to client list entry for window that is to be
365 *      below the lowered window (if NULL, window is lowered to the bottom
366 *      of the  stack).
367 *
368 *************************************<->***********************************/
369
370#ifdef _NO_PROTO
371void Do_Lower (pCD, pStackEntry, flags)
372    ClientData *pCD;
373    ClientListEntry *pStackEntry;
374    int flags;
375#else /* _NO_PROTO */
376void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
377#endif /* _NO_PROTO */
378{
379    Boolean restackTransients;
380    ClientData *pcdLeader;
381    WmWorkspaceData *pWS = ACTIVE_WS;
382
383
384    pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
385
386    if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
387    {
388        /*
389         * Only restack the icon if it is not currently lowered.
390         */
391
392        if (pStackEntry)
393        {
394            if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
395            {
396                StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
397                    pStackEntry);
398                MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
399                    pStackEntry);
400            }
401        }
402        else
403        {
404            if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
405            {
406                StackWindow (pWS, &pcdLeader->iconEntry,
407                             False /*on bottom*/, (ClientListEntry *) NULL);
408                MoveEntryInList (pWS, &pcdLeader->iconEntry,
409                             False /*on bottom*/, (ClientListEntry *) NULL);
410            }
411        }
412    }
413    else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
414    {
415        /*
416         * If this is a transient window then put it below its
417         * sibling transient windows.
418         */
419
420        restackTransients = False;
421        if (pCD->transientLeader)
422        {
423
424            /*
425             * If freeFamily stacking, then put dirty transient window
426             * (if any) back in place before force lowering current window
427             * to the bottom of the global window stack.  Then return.
428             */
429
430            if (flags & STACK_FREE_FAMILY)
431            {
432                if (dirtyStackEntry.pCD)
433                {
434                    RestoreTransients (pCD, Below);
435                }
436
437                dirtyStackEntry.pCD = pCD;
438
439                if (dirtyStackEntry.pCD->transientLeader)
440                  dirtyLeader = FindTransientTreeLeader (pCD);
441                else
442                  dirtyLeader = dirtyStackEntry.pCD;
443
444                restackTransients = ForceLowerWindow (pCD);
445                return;
446            }
447
448            /*
449             * Reach here only if NOT doing a f.lower freeFamily (see
450             * return; statement above).  Put current transient below
451             * its sibling transient windows.
452             */
453            restackTransients = PutTransientBelowSiblings (pCD);
454        }
455
456        /*
457         * If doing a regular f.lower and you have a dirty window, then
458         * clean up dirty transient window.
459         */
460
461        if (dirtyStackEntry.pCD)
462        {
463            /*
464             * If lowering a window in the same family as the dirty
465             * transient window, then just restack before lowering.
466             * Else, restore the dirty transient in place before
467             * lowering the current window.  Clear dirtyStack.
468             */
469            if (dirtyLeader == pcdLeader)
470            {
471                if (dirtyStackEntry.pCD == FindTransientOnTop(pCD))
472                {
473                    RestackTransients (dirtyStackEntry.pCD, True);
474                }
475                else
476                {
477                    RestackTransients (dirtyStackEntry.pCD, False);
478                }       
479            }
480            else
481            {
482                RestoreTransients (pCD, Above);
483            }
484            dirtyStackEntry.pCD = NULL;
485        }
486
487        /*
488         * Only restack the window or transient window tree if it is
489         * not currently lowered and the window is not a system
490         * modal window.
491         */
492
493        if (pStackEntry)
494        {
495            if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
496                !(wmGD.systemModalActive &&
497                  (pcdLeader == wmGD.systemModalClient)))
498            {
499                StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
500                    pStackEntry);
501                MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
502                    pStackEntry);
503            }
504            else if (restackTransients)
505            {
506                RestackTransients (pCD, False);
507            }
508        }
509        else
510        {
511            if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
512                !(wmGD.systemModalActive &&
513                  (pcdLeader == wmGD.systemModalClient)) &&
514                !(flags & STACK_WITHIN_FAMILY))
515            {
516                StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
517                    (ClientListEntry *) NULL);
518                MoveEntryInList (pWS, &pcdLeader->clientEntry,
519                    False /*on bottom*/, (ClientListEntry *) NULL);
520            }
521            else if (restackTransients)
522            {
523                RestackTransients (pCD, False);
524            }
525        }
526    }
527
528} /* END OF FUNCTION Do_Lower */
529
530
531
532/*************************************<->*************************************
533 *
534 *  F_CircleDown (args, pCD, event)
535 *
536 *
537 *  Description:
538 *  -----------
539 *  This is the window manager function handler for moving the client window
540 *  on top of stack to the bottom.
541 *
542 *
543 *  Inputs:
544 *  ------
545 *  args = function arguments (specified in .mwmrc file)
546 *
547 *  pCD = pointer to the client data for the client window to which the
548 *        function is to be applied
549 *
550 *  event = X event that invoked the function (key, button, or menu/NULL)
551 *
552 *
553 *  Outputs:
554 *  -------
555 *  RETURN = if True then further button binding/function processing can
556 *           be done for the event that caused this function to be called.
557 *
558 *************************************<->***********************************/
559
560#ifdef _NO_PROTO
561Boolean F_Circle_Down (args, pCD, event)
562    String args;
563    ClientData *pCD;
564    XEvent *event;
565
566#else /* _NO_PROTO */
567Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
568#endif /* _NO_PROTO */
569{
570    unsigned long types;
571    unsigned long windowType;
572    ClientListEntry *pNextEntry;
573    ClientData *pcdNext;
574
575
576    /*
577     * Go down through the client list looking for a window of an
578     * appropriate type that is obscuring lower windows.
579     */
580
581    types = (unsigned long)args;
582    pNextEntry = ACTIVE_PSD->clientList;
583    while (pNextEntry)
584    {
585        /*
586         * Only check out the window if it is onscreen.
587         */
588
589        pcdNext = pNextEntry->pCD;
590        if (((pNextEntry->type == NORMAL_STATE) &&
591             (pcdNext->clientState != MINIMIZED_STATE)) ||
592            ((pNextEntry->type == MINIMIZED_STATE) &&
593             (pcdNext->clientState == MINIMIZED_STATE)))
594        {
595            if (pcdNext->clientState == MINIMIZED_STATE)
596            {
597                windowType = F_GROUP_ICON;
598            }
599            else
600            {
601                windowType = F_GROUP_WINDOW;
602                if (pcdNext->transientLeader || pcdNext->transientChildren)
603                {
604                    windowType |= F_GROUP_TRANSIENT;
605                }
606            }
607            if (types & windowType)
608            {
609                if (CheckIfClientObscuringAny (pcdNext))
610                {
611                    /*
612                     * This window (or window tree) is obscuring another window
613                     * on the screen.  Lower the window.
614                     */
615
616                    F_Lower (NULL, pcdNext, (XEvent *) NULL);
617                    break;
618                }
619            }
620        }
621        pNextEntry = pNextEntry->nextSibling;
622    }
623
624    return (True);
625
626} /* END OF FUNCTION F_Circle_Down */
627
628
629
630/*************************************<->*************************************
631 *
632 *  F_Circle_Up (args, pCD, event)
633 *
634 *
635 *  Description:
636 *  -----------
637 *  This is the window manager function handler for moving the client window
638 *  on the bottom of the stack to the top.
639 *
640 *
641 *  Inputs:
642 *  ------
643 *  args = function arguments (specified in .mwmrc file)
644 *
645 *  pCD = pointer to the client data for the client window to which the
646 *        function is to be applied
647 *
648 *  event = X event that invoked the function (key, button, or menu/NULL)
649 *
650 *
651 *  Outputs:
652 *  -------
653 *  RETURN = if True then further button binding/function processing can
654 *           be done for the event that caused this function to be called.
655 *
656 *************************************<->***********************************/
657
658#ifdef _NO_PROTO
659Boolean F_Circle_Up (args, pCD, event)
660    String args;
661    ClientData *pCD;
662    XEvent *event;
663
664#else /* _NO_PROTO */
665Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
666#endif /* _NO_PROTO */
667{
668    unsigned long types;
669    unsigned long windowType;
670    ClientListEntry *pNextEntry;
671    ClientData *pcdNext;
672
673
674    /*
675     * Go up through the client list looking for a window of an
676     * appropriate type that is obscured by higher windows.
677     */
678
679    types = (unsigned long)args;
680    pNextEntry = ACTIVE_PSD->lastClient;
681    while (pNextEntry)
682    {
683        /*
684         * Only check out the window if it is onscreen.
685         */
686
687        pcdNext = pNextEntry->pCD;
688        if (((pNextEntry->type == NORMAL_STATE) &&
689             (pcdNext->clientState != MINIMIZED_STATE)) ||
690            ((pNextEntry->type == MINIMIZED_STATE) &&
691             (pcdNext->clientState == MINIMIZED_STATE)))
692        {
693            if (pcdNext->clientState == MINIMIZED_STATE)
694            {
695                windowType = F_GROUP_ICON;
696            }
697            else
698            {
699                windowType = F_GROUP_WINDOW;
700                if (pcdNext->transientLeader || pcdNext->transientChildren)
701                {
702                    windowType |= F_GROUP_TRANSIENT;
703                }
704            }
705            if (types & windowType)
706            {
707                if (CheckIfClientObscuredByAny (pcdNext))
708                {
709                    /*
710                     * This window (or window tree) is obscured by another
711                     * window on the screen.  Raise the window.
712                     */
713
714                    F_Raise (NULL, pcdNext, (XEvent *) NULL);
715                    break;
716                }
717            }
718        }
719        pNextEntry = pNextEntry->prevSibling;
720    }
721
722    return (True);
723
724
725} /* END OF FUNCTION F_Circle_Up */
726
727
728
729/*************************************<->*************************************
730 *
731 *  F_Focus_Color (args, pCD, event)
732 *
733 *
734 *  Description:
735 *  -----------
736 *  This is the window manager function handler for setting the colormap
737 *  focus to a client window or reinstalling the default colormap.
738 *
739 *************************************<->***********************************/
740
741#ifdef _NO_PROTO
742Boolean F_Focus_Color (args, pCD, event)
743    String args;
744    ClientData *pCD;
745    XEvent *event;
746
747#else /* _NO_PROTO */
748Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
749#endif /* _NO_PROTO */
750{
751
752    if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
753    {
754        if (pCD)
755        {
756            /*
757             * The window selected for the colormap focus is a top-level client
758             * window.  If there are subwindow colormaps then determine if the
759             * selection was in one of the subwindows.
760             */
761
762            if (pCD->clientState == MINIMIZED_STATE)
763            {
764                /* !!! colormap for client supplied icon window !!! */
765                pCD = NULL;
766            }
767        }
768
769        SetColormapFocus (ACTIVE_PSD, pCD);
770    }
771
772    return (True);
773
774} /* END OF FUNCTION F_Focus_Color */
775
776
777
778/*************************************<->*************************************
779 *
780 *  F_Exec (args, pCD, event)
781 *
782 *
783 *  Description:
784 *  -----------
785 *  This is the window manager function handler for executing a command
786 *  (with /bin/sh).
787 *
788 *************************************<->***********************************/
789
790#ifdef _NO_PROTO
791Boolean F_Exec (args, pCD, event)
792    String args;
793    ClientData *pCD;
794    XEvent *event;
795
796#else /* _NO_PROTO */
797Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
798#endif /* _NO_PROTO */
799{
800    int   status;
801    int   pid;
802    int   w;
803    void (*intStat) ();
804    void (*quitStat) ();
805    char *shell;
806    char *shellname;
807
808
809    /* make sure the f.exec command runs on the right display. */
810    if (wmGD.pActiveSD->displayString)
811      {
812        _XmOSPutenv(wmGD.pActiveSD->displayString);
813      }
814   
815
816    /*
817     * Fork a process to exec a shell to run the specified command:
818     */
819
820#ifdef PORT_NOVFORK
821    if ((pid = fork ()) == 0)
822#else
823    if ((pid = vfork ()) == 0)
824#endif
825    {
826
827#ifndef NO_SETPGRP
828#if defined(SVR4) || defined(__OSF1__)
829        setsid();
830#else
831#ifdef SYSV
832        setpgrp();
833#else
834        int tpid;
835
836        tpid = getpid();
837        setpgrp(tpid, tpid);
838#endif /* SYSV */
839#endif /* SVR4 */
840#endif /* NO_SETPGRP */
841
842        /*
843         * Exec the command using $MWMSHELL if set or
844         * $SHELL if set and $MWMSHELL not set or sh.
845         */
846
847        if (((shell = getenv ("MWMSHELL")) != NULL) ||
848            ((shell = getenv ("SHELL")) != NULL))
849
850        {
851            shellname = rindex(shell, '/');
852            if (shellname == NULL)
853            {
854                shellname = shell;
855            }
856            else
857            {
858                shellname++;
859            }
860            execl (shell, shellname, "-c", args, 0);
861        }
862
863        /*
864         * There is no SHELL environment variable or the first execl failed.
865         * Try /bin/sh .
866         */
867        execl ("/bin/sh", "sh", "-c", args, 0);
868
869
870        /*
871         * Error - command could not be exec'ed.
872         */
873
874        _exit (127);
875    }
876
877    else if (pid == -1)
878      return(True);
879
880    /*
881     * Have the window manager wait for the shell to complete.
882     */
883
884    intStat = (void (*)())signal (SIGINT, SIG_IGN);
885    quitStat = (void (*)())signal (SIGQUIT, SIG_IGN);
886
887    while ((w = wait (&status)) != pid && (w != -1));
888
889    if (w == -1)
890    {
891        status = -1;
892    }
893
894    signal (SIGINT, intStat);
895    signal (SIGQUIT, quitStat);
896
897    /*
898     * Restore original DISPLAY environment variable value
899     * so a restart will start on the same screen
900     */
901
902    if(wmGD.pActiveSD->displayString &&
903       wmGD.displayString)
904    {
905        _XmOSPutenv(wmGD.displayString);
906    }
907
908    return (True);
909
910
911} /* END OF FUNCTION F_Exec */
912
913
914
915/*************************************<->*************************************
916 *
917 *  F_Quit_Mwm (args, pCD, event)
918 *
919 *
920 *  Description:
921 *  -----------
922 *  This is the window manager function handler for terminating the window
923 *  manager.
924 *
925 *************************************<->***********************************/
926
927#ifdef _NO_PROTO
928Boolean F_Quit_Mwm (args, pCD, event)
929    String args;
930    ClientData *pCD;
931    XEvent *event;
932
933#else /* _NO_PROTO */
934Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
935#endif /* _NO_PROTO */
936{
937    if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
938    {
939        ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
940    }
941    else
942    {
943        Do_Quit_Mwm(False);
944    }
945   
946    return (False);
947
948} /* END OF FUNCTION F_Quit_Mwm */
949
950
951
952/*************************************<->*************************************
953 *
954 *  Do_Quit_Mwm (diedOnRestart)
955 *
956 *
957 *  Description:
958 *  -----------
959 *  Callback to do the f.quit_mwm function.
960 *
961 *************************************<->***********************************/
962
963#ifdef _NO_PROTO
964void Do_Quit_Mwm (diedOnRestart)
965    Boolean diedOnRestart;
966#else /* _NO_PROTO */
967void Do_Quit_Mwm (Boolean diedOnRestart)
968#endif /* _NO_PROTO */
969{
970    int scr;
971    ClientListEntry *pNextEntry;
972
973
974    /*
975     * Close the X connection to get all the X resources cleaned up.
976     * !!! maybe windows should be reparented / rebordered  before closing? !!!
977     * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
978     */
979
980
981    if (DISPLAY)
982    {
983        XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
984        for (scr = 0; scr < wmGD.numScreens; scr++)
985        {
986            if (wmGD.Screens[scr].managed)
987            {
988                pNextEntry = wmGD.Screens[scr].lastClient;
989                while (pNextEntry)
990                {
991                    if (pNextEntry->type == NORMAL_STATE)
992                    {
993                        if (!(pNextEntry->pCD->clientFlags &
994                              CLIENT_WM_CLIENTS))
995                        {
996                            ReBorderClient (pNextEntry->pCD, diedOnRestart);
997                        }
998                    }
999                    pNextEntry = pNextEntry->prevSibling;
1000                }
1001
1002                XDeleteProperty(DISPLAY, wmGD.Screens[scr].rootWindow,
1003                                wmGD.xa_MWM_INFO);
1004            }
1005        }
1006        XSync (DISPLAY, False);
1007        XCloseDisplay (DISPLAY);
1008    }
1009   
1010    if(diedOnRestart)
1011    {
1012        exit (WM_ERROR_EXIT_VALUE);
1013    }
1014    else
1015    {
1016        exit (0);
1017    }
1018
1019} /* END OF FUNCTION Do_Quit_Mwm */
1020
1021
1022/*************************************<->*************************************
1023 *
1024 *  ReBorderClient (pCD, reMapClient)
1025 *
1026 *
1027 *  Description:
1028 *  -----------
1029 *  Restores X border for client window and reparents the
1030 *  window back to the root.
1031 *
1032 *
1033 *  Inputs:
1034 *  -------
1035 *  pCD = pointer to the client data for the window to be re-bordered.
1036 *
1037 *************************************<->***********************************/
1038
1039#ifdef _NO_PROTO
1040void ReBorderClient (pCD, reMapClient)
1041    ClientData *pCD;
1042    Boolean  reMapClient;
1043#else /* _NO_PROTO */
1044void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1045#endif /* _NO_PROTO */
1046{
1047    int x, y;
1048    int xoff, yoff;
1049    XWindowChanges windowChanges;
1050
1051    while (pCD)
1052    {
1053        if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1054            (!(reMapClient)))
1055        {
1056            XUnmapWindow (DISPLAY, pCD->iconWindow);
1057            XReparentWindow (DISPLAY, pCD->iconWindow,
1058                ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
1059        }
1060
1061        if (!(reMapClient))
1062        {
1063            if (pCD->maxConfig)
1064            {
1065                x = pCD->maxX;
1066                y = pCD->maxY;
1067            }
1068            else
1069            {
1070                if(wmGD.positionIsFrame)
1071                {
1072                    CalculateGravityOffset (pCD, &xoff, &yoff);
1073                    x = pCD->clientX - xoff;
1074                    y = pCD->clientY - yoff;
1075                }
1076                else
1077                {
1078                    x = pCD->clientX;
1079                    y = pCD->clientY;
1080                }
1081            }
1082            XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1083            XReparentWindow (DISPLAY, pCD->client,
1084                             ROOT_FOR_CLIENT(pCD), x, y);
1085        }
1086        else
1087        {
1088            XMapWindow(wmGD.display, pCD->client);
1089        }
1090
1091        if (pCD->transientChildren)
1092        {
1093            ReBorderClient (pCD->transientChildren, reMapClient);
1094        }
1095
1096        if (!(reMapClient))
1097        {
1098            /*
1099             * restore X border
1100             */
1101            windowChanges.x = x;
1102            windowChanges.y = y;
1103            windowChanges.border_width = pCD->xBorderWidth;
1104            XConfigureWindow (DISPLAY, pCD->client,
1105                              CWBorderWidth | CWX | CWY, &windowChanges);
1106        }
1107
1108        if (pCD->transientLeader)
1109        {
1110            pCD = pCD->transientSiblings;
1111        }
1112        else
1113        {
1114            pCD = NULL;
1115        }
1116    }
1117
1118} /* END OF FUNCTION ReBorderClient */
1119
1120
1121
1122/*************************************<->*************************************
1123 *
1124 *  F_Focus_Key (args, pCD, event)
1125 *
1126 *
1127 *  Description:
1128 *  -----------
1129 *  This is the window manager function handler for setting the keyboard
1130 *  focus to a particular client window.
1131 *
1132 *
1133 *  Inputs:
1134 *  ------
1135 *  args = (immediate value) focus flags
1136 *
1137 *  pCD = pointer to the client data
1138 *
1139 *  event = X event that invoked the function (key, button, or menu/NULL)
1140 *
1141 *************************************<->***********************************/
1142
1143#ifdef _NO_PROTO
1144Boolean F_Focus_Key (args, pCD, event)
1145    String args;
1146    ClientData *pCD;
1147    XEvent *event;
1148
1149#else /* _NO_PROTO */
1150Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1151#endif /* _NO_PROTO */
1152{
1153    long focusFlags = (long)args;
1154
1155
1156    if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1157    {
1158        Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1159            (focusFlags | ALWAYS_SET_FOCUS));
1160    }
1161
1162    return (True);
1163
1164} /* END OF FUNCTION F_Focus_Key */
1165
1166
1167/*************************************<->*************************************
1168 *
1169 *  FindSomeReasonableClient
1170 *
1171 *  Description:
1172 *  -----------
1173 *  Find a client, any client to set the focus to, return client or NULL.
1174 *  This code is ripped off from AutoResetKeyFocus().
1175 * 
1176 *************************************<->***********************************/
1177
1178#ifdef _NO_PROTO
1179static Window FindSomeReasonableClient()
1180#else /* _NO_PROTO */
1181static Window FindSomeReasonableClient(void)
1182#endif /* _NO_PROTO */
1183{
1184   ClientData *pcdNoFocus=NULL;
1185
1186    ClientListEntry *pNextEntry;
1187    ClientData *pCD;
1188    ClientData *pcdLastFocus = (ClientData *) NULL;
1189    ClientData *pcdFocus;
1190    Window focusWindow = (Window) NULL;
1191
1192    /*
1193     * Scan through the list of clients to find a window to get the focus.
1194     */
1195
1196    pNextEntry = ACTIVE_PSD->clientList;
1197
1198    while (pNextEntry)
1199    {
1200        pCD = pNextEntry->pCD;
1201        if (!wmGD.systemModalActive ||
1202            (wmGD.systemModalClient == pCD))
1203        {
1204            if ((pNextEntry->type != MINIMIZED_STATE) &&
1205                (pCD->clientState != MINIMIZED_STATE) &&
1206                (pCD != pcdNoFocus))
1207            {
1208                if (pCD->transientChildren)
1209                {
1210                    pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1211                }
1212                else
1213                {
1214                    pcdFocus = pCD;
1215                }
1216                if (pcdFocus &&
1217                    ((pcdLastFocus == NULL) ||
1218                     (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1219                {
1220                    pcdLastFocus = pcdFocus;
1221                }
1222            }
1223        }
1224        pNextEntry = pNextEntry->nextSibling;
1225    }
1226
1227    /*
1228     * Set the focus window if one is found
1229     */
1230
1231    if (pcdLastFocus)
1232      focusWindow = pcdLastFocus->client;
1233
1234    /*
1235     * If a client window could not be found, then just put focus
1236     * on any icon.
1237     */
1238
1239    if (focusWindow == (Window) NULL)
1240    {
1241        pNextEntry = ACTIVE_PSD->clientList;
1242
1243        while (pNextEntry)
1244        {
1245            pCD = pNextEntry->pCD;
1246
1247            if ((pNextEntry->type == MINIMIZED_STATE) ||
1248                (pCD->clientState == MINIMIZED_STATE))
1249            {
1250                focusWindow = ICON_FRAME_WIN(pCD);
1251                break;
1252            }
1253            pNextEntry = pNextEntry->nextSibling;
1254        }
1255    }
1256
1257    return (focusWindow);
1258
1259} /* END OF FUNCTION FindSomeReasonableClient */
1260
1261
1262
1263
1264/*************************************<->*************************************
1265 *
1266 *  Do_Focus_Key (pCD, focusTime, flags)
1267 *
1268 *
1269 *  Description:
1270 *  -----------
1271 *  This function is used to set the focus to a window.  The focus indication
1272 *  is not changed until the FocusIn event is received.
1273 *
1274 *
1275 *  Inputs:
1276 *  ------
1277 *  pCD = pointer to the client data
1278 *
1279 *  focusTime = focus change time
1280 *
1281 *  flags = wm focus change flags
1282 *
1283 *************************************<->***********************************/
1284
1285#ifdef _NO_PROTO
1286void Do_Focus_Key (pCD, focusTime, flags)
1287    ClientData *pCD;
1288    Time focusTime;
1289    long flags;
1290
1291#else /* _NO_PROTO */
1292void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1293#endif /* _NO_PROTO */
1294{
1295    ClientData *pcdFocus;
1296    Window focusWindow;
1297
1298
1299    pcdFocus = pCD;
1300    if (pCD)
1301    {
1302        if (pCD->clientState == MINIMIZED_STATE)
1303        {
1304            focusWindow = ICON_FRAME_WIN(pCD);
1305        }
1306        else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1307        {
1308            /*
1309             * Set the keyboard focus to the indicated client window.
1310             * If the window has an application modal subordinate then
1311             * set the input focus to that window if the focus isn't
1312             * already owned by a subordinate.
1313             */
1314
1315            if (IS_APP_MODALIZED(pCD))
1316            {
1317                ClientData *pcdFocusLeader,*currFocusLeader;
1318
1319                /*
1320                 * Handle case where a modal window exists when Mwm starts up.
1321                 * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1322                 */
1323
1324                if (wmGD.keyboardFocus)
1325                {
1326                    currFocusLeader = wmGD.keyboardFocus->transientLeader;
1327                }
1328                else
1329                {
1330                    currFocusLeader = (ClientData *) NULL;
1331                }
1332
1333                /*
1334                 * Find focus leader for pCD
1335                 */
1336
1337                pcdFocusLeader = pCD;
1338                while (pcdFocusLeader->transientLeader &&
1339                       (pcdFocusLeader != currFocusLeader))
1340                {
1341                    pcdFocusLeader = pcdFocusLeader->transientLeader;
1342                }
1343
1344                if (pcdFocusLeader == currFocusLeader)
1345                {
1346                    pcdFocus = wmGD.keyboardFocus;
1347                    flags = 0;
1348                }
1349                else
1350                {
1351                    pcdFocus = FindTransientFocus (pcdFocusLeader);
1352                }
1353            }
1354
1355            focusWindow = pcdFocus->client;
1356        }
1357        else
1358        {
1359            /*
1360             * If the focus policy is "pointer" don't set the focus to a
1361             * window is it has an application modal subordinate.
1362             */
1363
1364            if (IS_APP_MODALIZED(pCD))
1365            {
1366                pcdFocus = NULL;
1367                focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1368            }
1369            else
1370            {
1371                focusWindow = pcdFocus->client;
1372            }
1373        }
1374    }
1375    else
1376    {
1377        /*
1378         * Set up the default (non client specific) keyboard input focus.
1379         */
1380
1381        if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1382        {
1383            focusWindow = PointerRoot;
1384        }
1385        else
1386        {
1387            /*
1388             * The WORKSPACE_IF_NULL flag is used to prevent client
1389             * windows from flashing when deiconifying a client.
1390             */
1391
1392            if (WORKSPACE_IF_NULL & flags)
1393            {
1394                focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1395            }
1396            else
1397            {
1398                /* find some reasonable client so that focus is not lost */
1399
1400                focusWindow = FindSomeReasonableClient();
1401                if (focusWindow == (Window)NULL)
1402                {
1403                    focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1404                }
1405            }
1406        }
1407    }
1408
1409
1410    if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1411    {
1412        if (pcdFocus)
1413        {
1414            /*
1415             * Set the focus and/or send a take focus client message.  This
1416             * is not done if a client area button press was done to set
1417             * set the focus and the window is a globally active input
1418             * style window (See ICCCM).
1419             */
1420
1421            if (!((flags & CLIENT_AREA_FOCUS) &&
1422                  (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1423                  !pcdFocus->inputFocusModel &&
1424                  (pcdFocus == pCD) &&
1425                  (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)))
1426            {
1427                if (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS)
1428                {
1429                    SendClientMsg (pcdFocus->client,
1430                        (long) wmGD.xa_WM_PROTOCOLS,
1431                        (long) wmGD.xa_WM_TAKE_FOCUS,
1432                        focusTime, NULL, 0);
1433                }
1434
1435#ifdef OLD_TAKE_FOCUS
1436                if (wmGD.enforceKeyFocus || pcdFocus->inputFocusModel ||
1437                    (pcdFocus->clientState == MINIMIZED_STATE) ||
1438                    !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS))
1439                {
1440                    XSetInputFocus (DISPLAY, focusWindow, RevertToParent,
1441                        CurrentTime);
1442                }
1443#else
1444                /*
1445                 * Don't set the input focus if the window has input_field set
1446                 * to False or has expressed an interest in WM_TAKE_FOCUS
1447                 * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1448                 * and the user click in the client area.  If the user clicks
1449                 * on the titlebar or traverses to this window via f.next_key,
1450                 * set the focus so that the user can access the window menu
1451                 * and accelerators.
1452                 *
1453                 * The following section was modified for CR 5652
1454                 * to correct input focus problem with windows that
1455                 * don't want the focus.  A more complete solution should
1456                 * be addressed at a later time.
1457                 */
1458                if (wmGD.enforceKeyFocus ||
1459                    (flags & ALWAYS_SET_FOCUS) ||
1460                    !(flags & CLIENT_AREA_FOCUS) ||
1461                    pcdFocus->inputFocusModel ||
1462                    (pcdFocus->clientState == MINIMIZED_STATE) ||
1463                    ((!(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS))
1464                     && pcdFocus->inputFocusModel))
1465                {
1466                  if (!(flags & CLIENT_AREA_FOCUS) &&
1467                      (!(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS))
1468                      && pcdFocus->inputFocusModel)
1469                    XSetInputFocus (DISPLAY, focusWindow,
1470                                    RevertToPointerRoot, CurrentTime);
1471
1472                  /* According to ICCCM the client area should not get
1473                   * focus, so don't change it. This needs to be fixed
1474                   * to be the client frame to get input focus, but
1475                   * mwm can't handle this right now.
1476                   */
1477                  if (!(flags & CLIENT_AREA_FOCUS) &&
1478                      !pcdFocus->inputFocusModel) {
1479                    /* Do Nothing for now
1480                     * This means there is no way to get
1481                     * at the system menu using the keyboard
1482                     * although it is possible with the mouse.
1483                     */
1484                  }
1485                  else
1486                    XSetInputFocus (DISPLAY, focusWindow, RevertToParent,
1487                        CurrentTime);
1488                }
1489                else
1490                {
1491                    /*
1492                     * We've decided that the window shouldn't get the focus,
1493                     * so don't change the focus.
1494                     */
1495                    pcdFocus = wmGD.nextKeyboardFocus;
1496                }
1497#endif
1498            }
1499        }
1500        else
1501        {
1502            /* !!! used timestamp based on SCREEN_SWITCH_FOCUS !!! */
1503            XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1504                ((flags & SCREEN_SWITCH_FOCUS) ? focusTime : CurrentTime));
1505        }
1506
1507        wmGD.nextKeyboardFocus = pcdFocus;
1508    }
1509
1510
1511} /* END OF FUNCTION Do_Focus_Key */
1512
1513
1514
1515
1516/******************************<->*************************************
1517 *
1518 *  F_Next_Key (args, pCD, event)
1519 *
1520 *
1521 *  Description:
1522 *  -----------
1523 *  This is the window manager function handler for setting the keyboard
1524 *  input focus to the next window in the set of managed windows.
1525 *
1526 *
1527 *  Inputs:
1528 *  ------
1529 *  args = (immediate value) window type flags
1530 *
1531 *  pCD = pointer to the client data
1532 *
1533 *  event = X event that invoked the function (key, button, or menu/NULL)
1534 *
1535 *************************************<->***********************************/
1536
1537#ifdef _NO_PROTO
1538Boolean F_Next_Key (args, pCD, event)
1539    String args;
1540    ClientData *pCD;
1541    XEvent *event;
1542
1543#else /* _NO_PROTO */
1544Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1545#endif /* _NO_PROTO */
1546{
1547    if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1548    {
1549        FocusNextWindow ((unsigned long)args,
1550                         GetFunctionTimestamp ((XButtonEvent *)event));
1551    }
1552
1553    return (True);
1554
1555} /* END OF FUNCTION F_Next_Key */
1556
1557
1558
1559/*************************************<->*************************************
1560 *
1561 *  F_Prev_Cmap (args, pCD, event)
1562 *
1563 *
1564 *  Description:
1565 *  -----------
1566 *  This is the window manager function handler installing the previous
1567 *  colormap in the list of client window colormaps.
1568 *
1569 *************************************<->***********************************/
1570
1571#ifdef _NO_PROTO
1572Boolean F_Prev_Cmap (args, pCD, event)
1573    String args;
1574    ClientData *pCD;
1575    XEvent *event;
1576
1577#else /* _NO_PROTO */
1578Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
1579#endif /* _NO_PROTO */
1580{
1581    if (pCD == NULL)
1582    {
1583        pCD = ACTIVE_PSD->colormapFocus;
1584    }
1585
1586    if (pCD && (pCD->clientCmapCount > 0) &&
1587        ((pCD->clientState == NORMAL_STATE) ||
1588         (pCD->clientState == MAXIMIZED_STATE)))
1589    {
1590        if (--(pCD->clientCmapIndex) < 0)
1591        {
1592            pCD->clientCmapIndex = pCD->clientCmapCount - 1;
1593        }
1594        pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
1595        if (ACTIVE_PSD->colormapFocus == pCD)
1596        {
1597#ifndef OLD_COLORMAP /* colormap */
1598            /*
1599             * We just re-ordered the colormaps list,
1600             * so we need to re-run the whole thing.
1601             */
1602            pCD->clientCmapFlagsInitialized = 0;
1603            ProcessColormapList (ACTIVE_PSD, pCD);
1604#else /* OSF original */
1605            WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
1606#endif
1607        }
1608    }
1609
1610    return (True);
1611
1612} /* END OF FUNCTION F_Prev_Cmap */
1613
1614
1615
1616/*************************************<->*************************************
1617 *
1618 *  F_Prev_Key (args, pCD, event)
1619 *
1620 *
1621 *  Description:
1622 *  -----------
1623 *  This is the window manager function handler for setting the keyboard
1624 *  input focus to the previous window in the set of managed windows.
1625 *
1626 *
1627 *  Inputs:
1628 *  ------
1629 *  args = (immediate value) window type flags
1630 *
1631 *  pCD = pointer to the client data
1632 *
1633 *  event = X event that invoked the function (key, button, or menu/NULL)
1634 *
1635 *************************************<->***********************************/
1636
1637#ifdef _NO_PROTO
1638Boolean F_Prev_Key (args, pCD, event)
1639    String args;
1640    ClientData *pCD;
1641    XEvent *event;
1642
1643#else /* _NO_PROTO */
1644Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
1645#endif /* _NO_PROTO */
1646{
1647    if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1648    {
1649        FocusPrevWindow ((unsigned long)args,
1650                            GetFunctionTimestamp ((XButtonEvent *)event));
1651
1652    }
1653
1654    return (True);
1655
1656} /* END OF FUNCTION F_Prev_Key */
1657
1658
1659
1660/*************************************<->*************************************
1661 *
1662 *  F_Pass_Key (args, pCD, event)
1663 *
1664 *
1665 *  Description:
1666 *  -----------
1667 *  This is a function stub for the f.pass_key window manager function.
1668 *
1669 *
1670 *  Inputs:
1671 *  ------
1672 *  args = (immediate value) window type flags
1673 *
1674 *  pCD = pointer to the client data
1675 *
1676 *  event = X event that invoked the function (key, button, or menu/NULL)
1677 *
1678 *************************************<->***********************************/
1679
1680Boolean F_Pass_Key (args, pCD, event)
1681    String args;
1682    ClientData *pCD;
1683    XEvent *event;
1684
1685{
1686    if (wmGD.passKeysActive)
1687    {
1688        /*
1689         * Get out of pass keys mode.
1690         */
1691
1692        wmGD.passKeysActive = False;
1693        wmGD.passKeysKeySpec = NULL;
1694    }
1695    else
1696    {
1697        /*
1698         * Get into pass keys mode.
1699         */
1700
1701        wmGD.passKeysActive = True;
1702    }
1703
1704    return (False);
1705
1706} /* END OF FUNCTION F_Pass_Key */
1707
1708
1709
1710/*************************************<->*************************************
1711 *
1712 *  F_Maximize (args, pCD, event)
1713 *
1714 *
1715 *  Description:
1716 *  -----------
1717 *  This is the window manager function handler for maximizing a client
1718 *  window.
1719 *
1720 *************************************<->***********************************/
1721
1722#ifdef _NO_PROTO
1723Boolean F_Maximize (args, pCD, event)
1724    String args;
1725    ClientData *pCD;
1726    XEvent *event;
1727
1728#else /* _NO_PROTO */
1729Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
1730#endif /* _NO_PROTO */
1731{
1732    if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
1733    {
1734        SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
1735            GetFunctionTimestamp ((XButtonEvent *)event),
1736                GetEventInverseMask(event));
1737    }
1738
1739    return (False);
1740
1741} /* END OF FUNCTION F_Maximize */
1742
1743
1744
1745/*************************************<->*************************************
1746 *
1747 *  F_Menu (args, pCD, event)
1748 *
1749 *
1750 *  Description:
1751 *  -----------
1752 *  This is the window manager function handler for posting a menu.
1753 *  This function can only be invoked by a key or button event.
1754 *   wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
1755 *     NULL when the menu is unposted.
1756 *
1757 *************************************<->***********************************/
1758
1759#ifdef _NO_PROTO
1760Boolean F_Menu (args, pCD, event)
1761    String args;
1762    ClientData *pCD;
1763    XEvent *event;
1764
1765#else /* _NO_PROTO */
1766Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
1767#endif /* _NO_PROTO */
1768{
1769    MenuSpec    *menuSpec;
1770    Context      menuContext;
1771    unsigned int button;
1772    int          x;
1773    int          y;
1774    long         flags = POST_AT_XY;
1775    WmScreenData *pSD;
1776
1777
1778    if (event &&
1779        ((event->type == ButtonPress) || (event->type == ButtonRelease)))
1780    {
1781        button = event->xbutton.button;
1782        x = event->xbutton.x_root;
1783        y = event->xbutton.y_root;
1784        if (event->type == ButtonRelease)
1785        {
1786            flags |= POST_TRAVERSAL_ON;
1787        }
1788    }
1789    else if (event &&
1790        ((event->type == KeyPress) || (event->type == KeyRelease)))
1791    {
1792        button = NoButton;
1793        x = event->xkey.x_root;
1794        y = event->xkey.y_root;
1795    }
1796    else
1797    {
1798        /*
1799         * A button or key event must be used to post a menu using this
1800         * function.
1801         */
1802
1803        return (False);
1804    }
1805
1806    if (pCD)
1807    {
1808        if (pCD->clientState == NORMAL_STATE)
1809        {
1810            menuContext = F_CONTEXT_NORMAL;
1811        }
1812        else if (pCD->clientState == MAXIMIZED_STATE)
1813        {
1814            menuContext = F_CONTEXT_MAXIMIZE;
1815        }
1816        else
1817        {
1818            menuContext = F_CONTEXT_ICON;
1819        }
1820        if (P_ICON_BOX(pCD) &&
1821            event->xany.window == ICON_FRAME_WIN(pCD))
1822        {
1823            if (pCD->clientState == MINIMIZED_STATE)
1824            {
1825                menuContext = F_SUBCONTEXT_IB_IICON;
1826            }
1827            else
1828            {
1829                menuContext = F_SUBCONTEXT_IB_WICON;
1830            }
1831        }
1832    }
1833    else
1834    {
1835        menuContext = F_CONTEXT_ROOT;
1836    }
1837
1838
1839    /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
1840     * This should have been done in MakeWmFunctionResources().
1841     */
1842
1843    pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
1844    if ((menuSpec = MakeMenu (pSD, args, menuContext,
1845                              menuContext, (MenuItem *) NULL, FALSE)) != NULL)
1846    {
1847        PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
1848    }
1849
1850    return (False);
1851
1852} /* END OF FUNCTION F_Menu */
1853
1854
1855/*************************************<->*************************************
1856 *
1857 *  F_Minimize (args, pCD, event)
1858 *
1859 *
1860 *  Description:
1861 *  -----------
1862 *  This is the window manager function handler for minimizing a client
1863 *  window.
1864 *
1865 *************************************<->***********************************/
1866
1867#ifdef _NO_PROTO
1868Boolean F_Minimize (args, pCD, event)
1869    String args;
1870    ClientData *pCD;
1871    XEvent *event;
1872
1873#else /* _NO_PROTO */
1874Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
1875#endif /* _NO_PROTO */
1876{
1877    ClientData *pcdLeader;
1878
1879
1880    if (pCD)
1881    {
1882        /*
1883         * If the window is a transient then minimize the entire transient
1884         * tree including the transient leader.
1885         */
1886       
1887        pcdLeader = (pCD->transientLeader) ?
1888                                        FindTransientTreeLeader (pCD) : pCD;
1889        if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
1890        {
1891            SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
1892                GetFunctionTimestamp ((XButtonEvent *)event),
1893                GetEventInverseMask(event));
1894        }
1895    }
1896
1897    return (False);
1898
1899} /* END OF FUNCTION F_Minimize */
1900
1901
1902
1903/*************************************<->*************************************
1904 *
1905 *  F_Move (args, pCD, event)
1906 *
1907 *
1908 *  Description:
1909 *  -----------
1910 *  This is the window manager function handler for moving a client window
1911 *  or icon.
1912 *
1913 *************************************<->***********************************/
1914
1915#ifdef _NO_PROTO
1916Boolean F_Move (args, pCD, event)
1917    String args;
1918    ClientData *pCD;
1919    XEvent *event;
1920
1921#else /* _NO_PROTO */
1922Boolean F_Move (String args, ClientData *pCD, XEvent *event)
1923#endif /* _NO_PROTO */
1924{
1925    if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
1926    {
1927        StartClientMove (pCD, event);
1928        HandleClientFrameMove (pCD, event);
1929    }
1930
1931    return (False);
1932
1933} /* END OF FUNCTION F_Move */
1934
1935
1936
1937/*************************************<->*************************************
1938 *
1939 *  F_Next_Cmap (args, pCD, event)
1940 *
1941 *
1942 *  Description:
1943 *  -----------
1944 *  This is the window manager function handler installing the next
1945 *  colormap in the list of client window colormaps.
1946 *
1947 *************************************<->***********************************/
1948
1949#ifdef _NO_PROTO
1950Boolean F_Next_Cmap (args, pCD, event)
1951    String args;
1952    ClientData *pCD;
1953    XEvent *event;
1954
1955#else /* _NO_PROTO */
1956Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
1957#endif /* _NO_PROTO */
1958{
1959    if (pCD == NULL)
1960    {
1961        pCD = ACTIVE_PSD->colormapFocus;
1962    }
1963
1964    if (pCD && (pCD->clientCmapCount > 0) &&
1965        ((pCD->clientState == NORMAL_STATE) ||
1966         (pCD->clientState == MAXIMIZED_STATE)))
1967    {
1968        if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
1969        {
1970            pCD->clientCmapIndex = 0;
1971        }
1972        pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
1973        if (ACTIVE_PSD->colormapFocus == pCD)
1974        {
1975#ifndef OLD_COLORMAP /* colormap */
1976            /*
1977             * We just re-ordered the colormaps list,
1978             * so we need to re-run the whole thing.
1979             */
1980            pCD->clientCmapFlagsInitialized = 0;
1981            ProcessColormapList (ACTIVE_PSD, pCD);
1982#else /* OSF original */
1983            WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
1984#endif
1985        }
1986    }
1987
1988    return (True);
1989
1990} /* END OF FUNCTION F_Next_Cmap */
1991
1992
1993
1994/*************************************<->*************************************
1995 *
1996 *  F_Nop (args, pCD, event)
1997 *
1998 *
1999 *  Description:
2000 *  -----------
2001 *  This is the window manager function handler for doing nothing.
2002 *
2003 *************************************<->***********************************/
2004
2005#ifdef _NO_PROTO
2006Boolean F_Nop (args, pCD, event)
2007    String args;
2008    ClientData *pCD;
2009    XEvent *event;
2010
2011#else /* _NO_PROTO */
2012Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2013#endif /* _NO_PROTO */
2014{
2015
2016    return (True);
2017
2018} /* END OF FUNCTION F_Nop */
2019
2020
2021
2022/*************************************<->*************************************
2023 *
2024 *  F_Normalize (args, pCD, event)
2025 *
2026 *
2027 *  Description:
2028 *  -----------
2029 *  This is the window manager function handler for putting a client window
2030 *  in the normal state.
2031 *
2032 *************************************<->***********************************/
2033
2034#ifdef _NO_PROTO
2035Boolean F_Normalize (args, pCD, event)
2036    String args;
2037    ClientData *pCD;
2038    XEvent *event;
2039
2040#else /* _NO_PROTO */
2041Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2042#endif /* _NO_PROTO */
2043{
2044
2045    if (pCD)
2046    {
2047        SetClientStateWithEventMask (pCD, NORMAL_STATE,
2048            GetFunctionTimestamp ((XButtonEvent *)event),
2049                GetEventInverseMask(event));
2050    }
2051
2052    return (False);
2053
2054} /* END OF FUNCTION F_Normalize */
2055
2056
2057
2058/*************************************<->*************************************
2059 *
2060 *  F_Normalize_And_Raise (args, pCD, event)
2061 *
2062 *
2063 *  Description:
2064 *  -----------
2065 *  This is the window manager function handler for putting a client window
2066 *  in the normal state and raising it from and icon.
2067 *
2068 *************************************<->***********************************/
2069
2070#ifdef _NO_PROTO
2071Boolean F_Normalize_And_Raise (args, pCD, event)
2072    String args;
2073    ClientData *pCD;
2074    XEvent *event;
2075
2076#else /* _NO_PROTO */
2077Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2078#endif /* _NO_PROTO */
2079{
2080   
2081    if (pCD)
2082    {
2083        if (pCD->clientState == MINIMIZED_STATE)
2084        {
2085            /* normalize window  */
2086            SetClientStateWithEventMask (pCD, NORMAL_STATE,
2087                          (Time)
2088                          (event
2089                           ? GetFunctionTimestamp ((XButtonEvent *)event)
2090                           : GetTimestamp ()),
2091                        GetEventInverseMask(event));
2092        }
2093        else
2094        {
2095            /* Make sure we are in NORMAL_STATE */
2096            SetClientStateWithEventMask (pCD, NORMAL_STATE,
2097                            GetFunctionTimestamp ((XButtonEvent *)event),
2098                                GetEventInverseMask(event));
2099
2100            /* Raise the window and set the keyboard focus to the window */
2101            F_Raise (NULL, pCD, (XEvent *)NULL);
2102            if (wmGD.raiseKeyFocus)
2103            {
2104                F_Focus_Key (NULL, pCD,
2105                             (event
2106                              ? ((XEvent *)event)
2107                              : ((XEvent *)NULL)));
2108            }
2109        }
2110        wmGD.clickData.clickPending = False;
2111        wmGD.clickData.doubleClickPending = False;
2112    }
2113
2114    return (False);
2115
2116} /* END OF FUNCTION F_Normalize_And_Raise */
2117
2118
2119
2120/*************************************<->*************************************
2121 *
2122 *  F_Restore (args, pCD, event)
2123 *
2124 *
2125 *  Description:
2126 *  -----------
2127 *  This is the window manager function handler for putting a client window
2128 *  in the normal state.
2129 *
2130 *************************************<->***********************************/
2131
2132#ifdef _NO_PROTO
2133Boolean F_Restore (args, pCD, event)
2134    String args;
2135    ClientData *pCD;
2136    XEvent *event;
2137
2138#else /* _NO_PROTO */
2139Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2140#endif /* _NO_PROTO */
2141{
2142    int newState;
2143
2144    if (pCD)
2145    {
2146        /*
2147         * If current state is MAXIMIZED state then just go to NORMAL state,
2148         * otherwise (you are in MINIMIZED state) return to previous state.
2149         */
2150
2151        if (pCD->clientState == MAXIMIZED_STATE)
2152        {
2153            SetClientStateWithEventMask (pCD, NORMAL_STATE,
2154                            GetFunctionTimestamp ((XButtonEvent *)event),
2155                                GetEventInverseMask(event));
2156        }
2157        else
2158        {
2159            if (pCD->maxConfig)
2160            {
2161                newState = MAXIMIZED_STATE;
2162            }
2163            else
2164            {
2165                newState = NORMAL_STATE;
2166            }
2167
2168            SetClientStateWithEventMask (pCD, newState,
2169                            GetFunctionTimestamp ((XButtonEvent *)event),
2170                                GetEventInverseMask(event));
2171        }
2172    }
2173
2174    return (False);
2175
2176} /* END OF FUNCTION F_Restore */
2177
2178
2179
2180/*************************************<->*************************************
2181 *
2182 *  F_Restore_And_Raise (args, pCD, event)
2183 *
2184 *
2185 *  Description:
2186 *  -----------
2187 *  This is the window manager function handler for putting a client window
2188 *  in the normal state and raising it from and icon.
2189 *
2190 *************************************<->***********************************/
2191
2192#ifdef _NO_PROTO
2193Boolean F_Restore_And_Raise (args, pCD, event)
2194    String args;
2195    ClientData *pCD;
2196    XEvent *event;
2197
2198#else /* _NO_PROTO */
2199Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2200#endif /* _NO_PROTO */
2201{
2202    int newState;
2203   
2204    if (pCD)
2205    {
2206        if (pCD->clientState == MINIMIZED_STATE)
2207        {
2208            /* Restore window  */
2209            if (pCD->maxConfig)
2210            {
2211                newState = MAXIMIZED_STATE;
2212            }
2213            else
2214            {
2215                newState = NORMAL_STATE;
2216            }
2217
2218            SetClientStateWithEventMask (pCD, newState,
2219                          (Time)
2220                          (event
2221                           ? GetFunctionTimestamp ((XButtonEvent *)event)
2222                           : GetTimestamp ()),
2223                        GetEventInverseMask(event));
2224        }
2225        else
2226        {
2227            /* Make sure we restore the window first */
2228            F_Restore (NULL, pCD, event);
2229
2230            /* Raise the window and set the keyboard focus to the window */
2231            F_Raise (NULL, pCD, (XEvent *)NULL);
2232            if (wmGD.raiseKeyFocus)
2233            {
2234                F_Focus_Key (NULL, pCD,
2235                             (event
2236                              ? ((XEvent *)event)
2237                              : ((XEvent *)NULL)));
2238            }
2239        }
2240        wmGD.clickData.clickPending = False;
2241        wmGD.clickData.doubleClickPending = False;
2242    }
2243
2244    return (False);
2245
2246} /* END OF FUNCTION F_Restore_And_Raise */
2247
2248
2249
2250/*************************************<->*************************************
2251 *
2252 *  F_Pack_Icons (args, pCD, event)
2253 *
2254 *
2255 *  Description:
2256 *  -----------
2257 *  This is the window manager function handler for packing icons in the
2258 *  icon box or on the desktop.
2259 *
2260 *************************************<->***********************************/
2261
2262#ifdef _NO_PROTO
2263Boolean F_Pack_Icons (args, pCD, event)
2264    String args;
2265    ClientData *pCD;
2266    XEvent *event;
2267
2268#else /* _NO_PROTO */
2269Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2270#endif /* _NO_PROTO */
2271{
2272   
2273    IconBoxData *pIBD;
2274
2275    if (ACTIVE_PSD->useIconBox)
2276    {
2277        pIBD = ACTIVE_WS->pIconBox;
2278        if (pCD)
2279        {
2280            while (pCD != pIBD->pCD_iconBox)
2281            {
2282                if (pIBD->pNextIconBox)
2283                {
2284                    pIBD = pIBD->pNextIconBox;
2285                }
2286                else
2287                {
2288                    pIBD = NULL;
2289                    break;
2290                }
2291            }
2292        }
2293        if (pIBD)
2294        {
2295            PackIconBox (pIBD, False, False, 0, 0);
2296        }
2297        else
2298        {
2299           PackRootIcons ();
2300        }
2301    }
2302    else
2303    {
2304        PackRootIcons ();
2305    }
2306
2307    return (True);
2308
2309
2310} /* END OF FUNCTION F_Pack_Icons */
2311
2312
2313
2314/*************************************<->*************************************
2315 *
2316 *  F_Post_SMenu (args, pCD, event)
2317 *
2318 *
2319 *  Description:
2320 *  -----------
2321 *  This is the window manager function handler for posting the system menu
2322 *  for the specified client.
2323 *  This function can only be invoked by a key or button event.
2324 *  wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2325 *    NULL when the menu is unposted.
2326 *
2327 *************************************<->***********************************/
2328
2329#ifdef _NO_PROTO
2330Boolean F_Post_SMenu (args, pCD, event)
2331    String args;
2332    ClientData *pCD;
2333    XEvent *event;
2334
2335#else /* _NO_PROTO */
2336Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
2337#endif /* _NO_PROTO */
2338{
2339    Context menuContext;
2340
2341
2342    /*
2343     * An event must be used to post the system menu using this function.
2344     */
2345
2346    if (event && pCD && pCD->systemMenuSpec)
2347    {
2348        /*
2349         * Determine whether the keyboard is posting the menu and post
2350         * the menu at an appropriate place.
2351         */
2352
2353        if (pCD->clientState == NORMAL_STATE)
2354        {
2355            menuContext = F_CONTEXT_NORMAL;
2356        }
2357        else if (pCD->clientState == MAXIMIZED_STATE)
2358        {
2359            menuContext = F_CONTEXT_MAXIMIZE;
2360        }
2361        else
2362        {
2363            menuContext = F_CONTEXT_ICON;
2364        }
2365        if (P_ICON_BOX(pCD) &&
2366            event->xany.window == ICON_FRAME_WIN(pCD))
2367        {
2368            if (pCD->clientState == MINIMIZED_STATE)
2369            {
2370                menuContext = F_SUBCONTEXT_IB_IICON;
2371            }
2372            else
2373            {
2374                menuContext = F_SUBCONTEXT_IB_WICON;
2375            }
2376        }
2377
2378        if ((event->type == KeyPress) || (event->type == KeyRelease))
2379        {
2380            /*
2381             * Set up for "sticky" menu processing if specified.
2382             */
2383
2384            if (pCD->clientState == MINIMIZED_STATE ||
2385                menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
2386            {
2387                if (wmGD.iconClick)
2388                {
2389                    wmGD.checkHotspot = True;
2390                }
2391            }
2392            else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
2393            {
2394                wmGD.checkHotspot = True;
2395            }
2396
2397            PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
2398                      0, event);
2399        }
2400        else if (event->type == ButtonPress)
2401        {
2402            PostMenu (pCD->systemMenuSpec, pCD,
2403                event->xbutton.x_root, event->xbutton.y_root,
2404                event->xbutton.button, menuContext, POST_AT_XY, event);
2405        }
2406        else if (event->type == ButtonRelease)
2407        {
2408            PostMenu (pCD->systemMenuSpec, pCD,
2409                event->xbutton.x_root, event->xbutton.y_root,
2410                event->xbutton.button, menuContext,
2411                POST_AT_XY | POST_TRAVERSAL_ON, event);
2412        }
2413    }
2414
2415    return (False);
2416
2417} /* END OF FUNCTION F_PostSMenu */
2418
2419
2420
2421/*************************************<->*************************************
2422 *
2423 *  F_Kill (args, pCD, event)
2424 *
2425 *
2426 *  Description:
2427 *  -----------
2428 *  This is the window manager function handler for terminating a client.
2429 *  Essentially the client connection is shut down.
2430 *
2431 *************************************<->***********************************/
2432
2433#ifdef _NO_PROTO
2434Boolean F_Kill (args, pCD, event)
2435    String args;
2436    ClientData *pCD;
2437    XEvent *event;
2438
2439#else /* _NO_PROTO */
2440Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
2441#endif /* _NO_PROTO */
2442{
2443    if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
2444    {
2445        Boolean do_delete_window =
2446                pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
2447        Boolean do_save_yourself =
2448                pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
2449
2450        if (!do_delete_window && !do_save_yourself)
2451          {
2452            XKillClient (DISPLAY, pCD->client);
2453          }
2454
2455        else if (do_delete_window)
2456          {
2457            /*
2458             * The client wants to be notified, not killed.
2459             */
2460
2461            SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
2462                   (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
2463
2464            if (do_save_yourself)
2465              {
2466                SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
2467                       (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
2468              }
2469          }
2470        else /* do_save_yourself */
2471          {
2472            /*
2473             * Send a WM_SAVE_YOURSELF message and wait for a change to
2474             * the WM_COMMAND property.
2475             * !!! button and key input should be kept from the window !!!
2476             */
2477
2478            if (AddWmTimer (TIMER_QUIT, (unsigned long) wmGD.quitTimeout, pCD))
2479              {
2480                SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
2481                       (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
2482
2483                pCD->clientFlags |= CLIENT_TERMINATING;
2484              }
2485            else
2486              {
2487                XKillClient (DISPLAY, pCD->client);
2488              }
2489          }
2490      }
2491
2492    return (False);
2493
2494} /* END OF FUNCTION F_Kill */
2495
2496
2497
2498/*************************************<->*************************************
2499 *
2500 *  F_Refresh (args, pCD, event)
2501 *
2502 *
2503 *  Description:
2504 *  -----------
2505 *  This is the window manager function handler for causing all windows
2506 *  in the workspace to be redrawn.
2507 *
2508 *************************************<->***********************************/
2509
2510#ifdef _NO_PROTO
2511Boolean F_Refresh (args, pCD, event)
2512    String args;
2513    ClientData *pCD;
2514    XEvent *event;
2515
2516#else /* _NO_PROTO */
2517Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
2518#endif /* _NO_PROTO */
2519{
2520    Window win;
2521
2522                         /* default background_pixmap is None */
2523    win = XCreateWindow (DISPLAY,
2524                         ACTIVE_ROOT, 0, 0,
2525                         (unsigned int) DisplayWidth (DISPLAY,
2526                             ACTIVE_SCREEN),
2527                         (unsigned int) DisplayHeight (DISPLAY,
2528                             ACTIVE_SCREEN),
2529                         0,
2530                         0,
2531                         InputOutput,
2532                         CopyFromParent,
2533                         0,
2534                         (XSetWindowAttributes *)NULL);   
2535
2536    XMapWindow (DISPLAY, win);
2537    XDestroyWindow (DISPLAY, win);
2538    XFlush (DISPLAY);
2539
2540    return (True);
2541
2542} /* END OF FUNCTION F_Refresh */
2543
2544
2545
2546/*************************************<->*************************************
2547 *
2548 *  F_Resize (args, pCD, event)
2549 *
2550 *
2551 *  Description:
2552 *  -----------
2553 *  This is the window manager function handler for resizing a client window.
2554 *
2555 *************************************<->***********************************/
2556
2557#ifdef _NO_PROTO
2558Boolean F_Resize (args, pCD, event)
2559    String args;
2560    ClientData *pCD;
2561    XEvent *event;
2562
2563#else /* _NO_PROTO */
2564Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
2565#endif /* _NO_PROTO */
2566{
2567    if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
2568        ((pCD->clientState == NORMAL_STATE) ||
2569                                        (pCD->clientState == MAXIMIZED_STATE)))
2570    {
2571        StartClientResize (pCD, event);
2572        HandleClientFrameResize (pCD, event);
2573    }
2574
2575    return (False);
2576
2577} /* END OF FUNCTION F_Resize */
2578
2579
2580
2581/*************************************<->*************************************
2582 *
2583 *  F_Restart (args, pCD, event)
2584 *
2585 *
2586 *  Description:
2587 *  -----------
2588 *  This is the window manager function handler for restarting the window
2589 *  manager.
2590 *
2591 *************************************<->***********************************/
2592
2593#ifdef _NO_PROTO
2594Boolean F_Restart (args, pCD, event)
2595    String args;
2596    ClientData *pCD;
2597    XEvent *event;
2598
2599#else /* _NO_PROTO */
2600Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
2601#endif /* _NO_PROTO */
2602{
2603    if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
2604    {
2605        ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
2606    }
2607    else
2608    {
2609        RestartWm (MWM_INFO_STARTUP_CUSTOM);
2610    }
2611    return (False);
2612
2613} /* END OF FUNCTION F_Restart */
2614
2615
2616
2617/*************************************<->*************************************
2618 *
2619 *  Do_Restart (dummy)
2620 *
2621 *
2622 *  Description:
2623 *  -----------
2624 *  Callback function for restarting the window manager.
2625 *
2626 *************************************<->***********************************/
2627
2628#ifdef _NO_PROTO
2629void Do_Restart (dummy)
2630Boolean dummy;
2631#else /* _NO_PROTO */
2632void Do_Restart (Boolean dummy)
2633#endif /* _NO_PROTO */
2634{
2635    RestartWm (MWM_INFO_STARTUP_CUSTOM);
2636
2637} /* END OF FUNCTION Do_Restart */
2638
2639
2640
2641/*************************************<->*************************************
2642 *
2643 *  RestartWm (startupFlags)
2644 *
2645 *
2646 *  Description:
2647 *  -----------
2648 *  Actually restarts the window manager.
2649 *
2650 *
2651 *  Inputs:
2652 *  ------
2653 *  startupFlags = flags to be put into the Wm_INFO property for restart.
2654 *
2655 *************************************<->***********************************/
2656
2657#ifdef _NO_PROTO
2658void RestartWm (startupFlags)
2659    long startupFlags;
2660
2661#else /* _NO_PROTO */
2662void RestartWm (long startupFlags)
2663#endif /* _NO_PROTO */
2664{
2665    ClientListEntry *pNextEntry;
2666    int scr;
2667
2668
2669    for (scr=0; scr<wmGD.numScreens; scr++)
2670    {
2671        if(wmGD.Screens[scr].managed)
2672        {
2673           
2674            /*
2675             * Set up the _MOTIF_WM_INFO property on the root window
2676             * to indicate a restart.
2677             */
2678           
2679            SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
2680           
2681           
2682            /*
2683             * Unmap client windows and reparent them to the root window.
2684             */
2685           
2686            pNextEntry = wmGD.Screens[scr].lastClient;
2687            while (pNextEntry)
2688            {
2689                if (pNextEntry->type == NORMAL_STATE)
2690                {
2691                    if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
2692                    {
2693                        if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
2694                        {
2695                            XUnmapWindow (DISPLAY,
2696                                          pNextEntry->pCD->clientFrameWin);
2697                        }
2698                    }
2699                    else
2700                    {
2701                        DeFrameClient (pNextEntry->pCD);
2702                    }
2703                }
2704                pNextEntry = pNextEntry->prevSibling;
2705            }
2706        }
2707       
2708    }
2709   
2710
2711    /*
2712     * This fixes restart problem when going from explicit focus to
2713     * pointer focus.  Window under pointer was not getting focus indication
2714     * until pointer was moved to new window, or out of and into the
2715     * window.
2716     */
2717
2718    XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
2719    XSync (DISPLAY, False);
2720
2721
2722
2723    /*
2724     * Restart the window manager with the initial arguments plus
2725     * the restart settings.
2726     */
2727
2728    execvp (*(wmGD.argv), wmGD.argv);
2729
2730    Warning ("Cannot restart the window manager");
2731    Do_Quit_Mwm (True);
2732
2733
2734
2735} /* END OF FUNCTION RestartWm */
2736
2737
2738
2739/*************************************<->*************************************
2740 *
2741 *  DeFrameClient (pCD)
2742 *
2743 *
2744 *  Description:
2745 *  -----------
2746 *  Unmaps a client window (and client icon window) and reparents the
2747 *  window back to the root.
2748 *
2749 *
2750 *  Inputs:
2751 *  -------
2752 *  pCD = pointer to the client data for the window to be de-framed.
2753 *
2754 *************************************<->***********************************/
2755
2756#ifdef _NO_PROTO
2757void DeFrameClient (pCD)
2758    ClientData *pCD;
2759
2760#else /* _NO_PROTO */
2761void DeFrameClient (ClientData *pCD)
2762#endif /* _NO_PROTO */
2763{
2764    int x, y;
2765    int xoff, yoff;
2766    XWindowChanges windowChanges;
2767
2768    while (pCD)
2769    {
2770        if (pCD->clientState != MINIMIZED_STATE)
2771        {
2772            XUnmapWindow (DISPLAY, pCD->clientFrameWin);
2773        }
2774
2775        if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
2776        {
2777            XUnmapWindow (DISPLAY, pCD->iconWindow);
2778            XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
2779            XReparentWindow (DISPLAY, pCD->iconWindow,
2780                ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
2781        }
2782
2783        if (pCD->maxConfig)
2784        {
2785            x = pCD->maxX;
2786            y = pCD->maxY;
2787        }
2788        else
2789        {
2790            if(wmGD.positionIsFrame)
2791            {
2792                CalculateGravityOffset (pCD, &xoff, &yoff);
2793                x = pCD->clientX - xoff;
2794                y = pCD->clientY - yoff;
2795            }
2796            else
2797            {
2798                x = pCD->clientX;
2799                y = pCD->clientY;
2800            }
2801        }
2802
2803#ifndef UNMAP_ON_RESTART
2804        if (pCD->clientState == MINIMIZED_STATE)
2805        {
2806            XUnmapWindow (DISPLAY, pCD->client);
2807        }
2808#else
2809        XUnmapWindow (DISPLAY, pCD->client);
2810#endif
2811        XRemoveFromSaveSet (DISPLAY, pCD->client);
2812        XReparentWindow (DISPLAY, pCD->client,
2813            ROOT_FOR_CLIENT(pCD), x, y);
2814
2815        if (pCD->transientChildren)
2816        {
2817            DeFrameClient (pCD->transientChildren);
2818        }
2819
2820        /*
2821         * restore X border
2822         */
2823        windowChanges.x = x;
2824        windowChanges.y = y;
2825        windowChanges.border_width = pCD->xBorderWidth;
2826        XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
2827                          &windowChanges);
2828
2829        if (pCD->transientLeader)
2830        {
2831            pCD = pCD->transientSiblings;
2832        }
2833        else
2834        {
2835            pCD = NULL;
2836        }
2837    }
2838
2839} /* END OF FUNCTION DeFrameClient */
2840
2841
2842
2843/******************************<->*************************************
2844 *
2845 *  F_Send_Msg (args, pCD, event)
2846 *
2847 *
2848 *  Description:
2849 *  -----------
2850 *  This is the window manager function handler for sending a client
2851 *  message event to a client window.
2852 *
2853 *
2854 *  Inputs:
2855 *  ------
2856 *  args = (immediate value) message id
2857 *
2858 *  pCD = pointer to the client data
2859 *
2860 *  event = X event that invoked the function (key, button, or menu/NULL)
2861 *
2862 *
2863 ******************************<->***********************************/
2864
2865#ifdef _NO_PROTO
2866Boolean F_Send_Msg (args, pCD, event)
2867    String args;
2868    ClientData *pCD;
2869    XEvent *event;
2870
2871#else /* _NO_PROTO */
2872Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
2873#endif /* _NO_PROTO */
2874{
2875    register int i;
2876
2877
2878    if (pCD && pCD->mwmMessagesCount)
2879    {
2880        /*
2881         * A message id must be made "active" by being included in the
2882         * _MWM_MESSAGES property before the associated message can be sent.
2883         */
2884
2885        for (i = 0; i < pCD->mwmMessagesCount; i++)
2886        {
2887            if (pCD->mwmMessages[i] == (long)args)
2888            {
2889                SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES,
2890                    (long)args, CurrentTime, NULL, 0);
2891                return (True);
2892            }
2893        }
2894    }
2895
2896    return (True);
2897
2898} /* END OF FUNCTION F_Send_Msg */
2899
2900
2901
2902/*************************************<->*************************************
2903 *
2904 *  F_Separator (args, pCD, event)
2905 *
2906 *
2907 *  Description:
2908 *  -----------
2909 *  This is a placeholder function; it should never be called.
2910 *
2911 *************************************<->***********************************/
2912
2913#ifdef _NO_PROTO
2914Boolean F_Separator (args, pCD, event)
2915    String args;
2916    ClientData *pCD;
2917    XEvent *event;
2918
2919#else /* _NO_PROTO */
2920Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
2921#endif /* _NO_PROTO */
2922{
2923
2924    return (True);
2925
2926} /* END OF FUNCTION F_Separator */
2927
2928
2929#ifdef _NO_PROTO
2930Boolean ForceRaiseWindow (pcd)
2931        ClientData *pcd;
2932#else /* _NO_PROTO */
2933Boolean ForceRaiseWindow (ClientData *pcd)
2934#endif /* _NO_PROTO */
2935{
2936#if 0
2937    Window stackWindow;
2938    WmScreenData *pSD = (ACTIVE_WS)->pSD;
2939#endif
2940    XWindowChanges changes;
2941    Boolean restack = False;
2942
2943#if 0
2944    if (pSD->clientList->type == MINIMIZED_STATE)
2945    {
2946        stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
2947    }
2948    else
2949    {
2950        stackWindow = pSD->clientList->pCD->clientFrameWin;
2951    }
2952#endif
2953
2954    /*
2955     * Windows did not raise on regular f.raise because the raise was
2956     * not relative to another window (methinks).
2957     */
2958    changes.stack_mode = Above;
2959    XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
2960                      &changes);
2961
2962    return (restack);
2963}
2964
2965
2966
2967/*************************************<->*************************************
2968 *
2969 *  F_Raise (args, pCD, event)
2970 *
2971 *
2972 *  Description:
2973 *  -----------
2974 *  This is the window manager function handler for topping the client window
2975 *  so that it is unobscured.
2976 *
2977 *************************************<->***********************************/
2978
2979#ifdef _NO_PROTO
2980Boolean F_Raise (args, pCD, event)
2981    String args;
2982    ClientData *pCD;
2983    XEvent *event;
2984
2985#else /* _NO_PROTO */
2986Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
2987#endif /* _NO_PROTO */
2988{
2989    ClientListEntry *pEntry;
2990    ClientListEntry *pNextEntry;
2991    ClientListEntry *pStackEntry;
2992    String string = args;
2993    int flags = STACK_NORMAL;
2994
2995    if (string)
2996    {
2997        /* process '-client' argument */
2998        if (string[0] == '-')
2999        {
3000            string = &string[1];
3001            string = (String) GetString ((unsigned char **) &string);
3002
3003            pStackEntry = NULL;
3004            pNextEntry = ACTIVE_PSD->clientList;
3005            while (pNextEntry &&
3006                   (pEntry = FindClientNameMatch (pNextEntry, True, string,
3007                                                  F_GROUP_ALL)))
3008            {
3009                pNextEntry = pEntry->nextSibling;
3010                Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3011                pStackEntry = pEntry;
3012            }
3013        }
3014        /* process family stacking stuff */
3015        else if (*string)
3016        {
3017            unsigned int  slen, len, index;
3018
3019            slen = strlen(args) - 2;            /* subtract '\n' and NULL */
3020            for (index = 0; index < slen; string = &args[index+1])
3021            {
3022                if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3023                   break;
3024                len = strlen(string);
3025                if (!strcmp(string,"within"))
3026                {
3027                    flags |= STACK_WITHIN_FAMILY;
3028                }
3029                else if (!strcmp(string,"freeFamily"))
3030                {
3031                    flags |= STACK_FREE_FAMILY;
3032                }
3033                index += len;
3034            }
3035            Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3036        }
3037
3038    }
3039    else if (pCD)
3040    {
3041        Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3042    }
3043
3044    return (True);
3045
3046} /* END OF FUNCTION F_Raise */
3047
3048
3049
3050/*************************************<->*************************************
3051 *
3052 *  Do_Raise (pCD, pStackEntry)
3053 *
3054 *
3055 *  Description:
3056 *  -----------
3057 *  This is the window manager function handler for topping the client window
3058 *  so that it is unobscured.
3059 *
3060 *
3061 *  Inputs:
3062 *  ------
3063 *  pCD = pointer to the client data of the window (or icon) to be raised.
3064 *
3065 *  pStackEntry = pointer to client list entry for window that is to be
3066 *      above the raised window (if NULL window is raised to the top of the
3067 *      stack).
3068 *
3069 *************************************<->***********************************/
3070
3071#ifdef _NO_PROTO
3072void Do_Raise (pCD, pStackEntry, flags)
3073    ClientData *pCD;
3074    ClientListEntry *pStackEntry;
3075    int flags;
3076
3077#else /* _NO_PROTO */
3078void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3079#endif /* _NO_PROTO */
3080{
3081    Boolean restackTransients;
3082    ClientData *pcdLeader;
3083    WmWorkspaceData *pWS = ACTIVE_WS;
3084
3085
3086    pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
3087
3088    if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
3089    {
3090        /*
3091         * Don't raise the window above the system modal window.
3092         */
3093    }
3094    else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
3095             !P_ICON_BOX(pcdLeader))
3096    {
3097        /*
3098         * Only restack the icon if it is not currently raised.
3099         */
3100
3101        if (pStackEntry)
3102        {
3103            if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
3104            {
3105                StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
3106                             pStackEntry);
3107                MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
3108                                 pStackEntry);
3109            }
3110        }
3111        else
3112        {
3113            if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
3114            {
3115                StackWindow (pWS, &pcdLeader->iconEntry,
3116                    True /*on top*/, (ClientListEntry *) NULL);
3117                MoveEntryInList (pWS, &pcdLeader->iconEntry,
3118                    True /*on top*/, (ClientListEntry *) NULL);
3119            }
3120        }
3121    }
3122    else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
3123    {
3124        /*
3125         * If this is a transient window then put it on top of its
3126         * sibling transient windows.
3127         */
3128
3129        restackTransients = False;
3130
3131
3132
3133/*
3134 * Fix for 5325 - The following code has been reorganized to cause the
3135 *                action of F_Raise to match the current documentation.
3136 *                The new algorithm is as follows:
3137 *
3138 *                if (dirtyStackEntry.pCD)
3139 *                  restore dirty tree
3140 *                if (not withinFamily)
3141 *                  bring window group to the top of global stack
3142 *                if (freeFamily)
3143 *                  raise the requested window to top of family
3144 *                else
3145 *                  raise requested window to top of siblings
3146 *                if (need to restack windows)
3147 *                  restack windows
3148 *                return
3149 */
3150        /*
3151         * If a dirtyStackEntry exists, return it to its original place
3152         * in the stack (for all stacking types)
3153         */
3154        if (dirtyStackEntry.pCD)
3155        {
3156            /*
3157             * Check to make sure that the dirty pCD has either transient
3158             * children or a transient leader.  If not, do not restore
3159             * the transients.
3160             */
3161            if (dirtyStackEntry.pCD->transientChildren ||
3162                dirtyStackEntry.pCD->transientLeader)
3163                RestoreTransients (dirtyStackEntry.pCD, Above);
3164            dirtyStackEntry.pCD = NULL;
3165            dirtyLeader = NULL;
3166        }
3167 
3168        /*
3169         * If the flags do not indicate "within", raise the window family
3170         * to the top of the window stack. If the window is the primary,
3171         * raise it to the top regardless of the flags.
3172         */
3173        if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
3174        {
3175            if (pStackEntry)
3176            {
3177                if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
3178                {
3179                    StackWindow (pWS, &pcdLeader->clientEntry,
3180                        False /*below*/, pStackEntry);
3181                    MoveEntryInList (pWS, &pcdLeader->clientEntry,
3182                        False /*below*/, pStackEntry);
3183                }
3184            }
3185            else
3186            {
3187                if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
3188                {
3189                    StackWindow (pWS, &pcdLeader->clientEntry,
3190                        True /*on top*/, (ClientListEntry *) NULL);
3191                    MoveEntryInList (pWS, &pcdLeader->clientEntry,
3192                        True /*on top*/, (ClientListEntry *) NULL);
3193                }
3194            }
3195        }
3196 
3197        /*
3198         * If freeFamily stacking is requested, check to make sure that
3199         * the window has either a transientChild or Leader.  This will
3200         * guarantee that windows that form their own family are not
3201         * labelled as dirty (what's to dirty it up?).  If it has either,
3202         * raise the window to the top of the family stack.
3203         */
3204        if ((flags & STACK_FREE_FAMILY) &&
3205            (pCD->transientLeader || pCD->transientChildren))
3206        {
3207            dirtyStackEntry.pCD = pCD;
3208 
3209            if (dirtyStackEntry.pCD->transientLeader)
3210                dirtyLeader = FindTransientTreeLeader (pCD);
3211            else
3212                dirtyLeader = dirtyStackEntry.pCD;
3213 
3214            restackTransients = ForceRaiseWindow (pCD);
3215        }
3216 
3217        /*
3218         * If withinFamily stacking is requested, put the current transient
3219         * on top of its sibling transient windows.
3220         */
3221        else
3222        {
3223            restackTransients = PutTransientOnTop (pCD);
3224        }
3225 
3226        /* At this point, if doing a regular f.raise the window family has
3227         * already been brought to the top of the stack, so nothing further
3228         * needs to be done for it.
3229         */
3230 
3231        /* Restack the transients if needed */
3232 
3233        if (restackTransients)
3234        {
3235            if (pStackEntry)
3236            {
3237                RestackTransients (pCD, False);
3238            }
3239            else
3240            {
3241                RestackTransients (pCD, True);
3242            }
3243        }
3244
3245
3246
3247
3248    }
3249
3250} /* END OF FUNCTION Do_Raise */
3251
3252
3253
3254/*************************************<->*************************************
3255 *
3256 *  F_Raise_Lower (args, pCD, event)
3257 *
3258 *
3259 *  Description:
3260 *  -----------
3261 *  This window manager function tops an obscured window or icon and bottoms
3262 *  a window or icon that is on top of the window stack.
3263 *
3264 *************************************<->***********************************/
3265
3266#ifdef _NO_PROTO
3267Boolean F_Raise_Lower (args, pCD, event)
3268    String args;
3269    ClientData *pCD;
3270    XEvent *event;
3271
3272#else /* _NO_PROTO */
3273Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
3274#endif /* _NO_PROTO */
3275{
3276    ClientData *pcdLeader;
3277
3278    if (pCD)
3279    {
3280        pcdLeader = (pCD->transientLeader) ?
3281                                        FindTransientTreeLeader (pCD) : pCD;
3282
3283        /*
3284         * Treat a raise/lower on a window in a transient tree as if it is
3285         * a raise/lower for the whole tree.
3286         */
3287
3288        if (CheckIfClientObscuredByAny (pcdLeader))
3289        {
3290            /*
3291             * The window is obscured by another window, raise the window.
3292             */
3293
3294            F_Raise (NULL, pcdLeader, (XEvent *)NULL);
3295        }
3296        else if (CheckIfClientObscuringAny (pcdLeader) &&
3297                !(wmGD.systemModalActive &&
3298                 (pcdLeader == wmGD.systemModalClient)))
3299        {
3300            /*
3301             * The window is obscuring another window and is
3302             * not system modal, lower the window.
3303             */
3304
3305            F_Lower (NULL, pcdLeader, (XEvent *)NULL);
3306        }
3307    }
3308
3309    return (True);
3310
3311} /* END OF FUNCTION F_Raise_Lower */
3312
3313
3314
3315/*************************************<->*************************************
3316 *
3317 *  F_Refresh_Win (args, pCD, event)
3318 *
3319 *
3320 *  Description:
3321 *  -----------
3322 *  This is the window manager function handler for causing a client window
3323 *  to redisplay itself.
3324 *
3325 *************************************<->***********************************/
3326
3327#ifdef _NO_PROTO
3328Boolean F_Refresh_Win (args, pCD, event)
3329    String args;
3330    ClientData *pCD;
3331    XEvent *event;
3332
3333#else /* _NO_PROTO */
3334Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
3335#endif /* _NO_PROTO */
3336{
3337    Window win;
3338    unsigned int w, h;
3339
3340    if (pCD && ((pCD->clientState == NORMAL_STATE) ||
3341                (pCD->clientState == MAXIMIZED_STATE)))
3342    {
3343        if (pCD->clientState == NORMAL_STATE)
3344        {
3345            w = (unsigned int) pCD->clientWidth;
3346            h = (unsigned int) pCD->clientHeight;
3347        }
3348        else
3349        {
3350            w = (unsigned int) pCD->maxWidth;
3351            h = (unsigned int) pCD->maxHeight;
3352        }
3353
3354                         /* default background_pixmap is None */
3355        win = XCreateWindow (DISPLAY,
3356                         pCD->clientBaseWin,
3357                         pCD->matteWidth,
3358                         pCD->matteWidth,
3359                         w, h,
3360                         0,
3361                         0,
3362                         InputOutput,
3363                         CopyFromParent,
3364                         0,
3365                         (XSetWindowAttributes *)NULL); 
3366
3367        XMapWindow (DISPLAY, win);
3368        XDestroyWindow (DISPLAY, win);
3369        XFlush (DISPLAY);
3370    }
3371
3372    return (True);
3373
3374} /* END OF FUNCTION F_Refresh_Win */
3375
3376
3377
3378/*************************************<->*************************************
3379 *
3380 *  F_Set_Behavior (args, pCD, event)
3381 *
3382 *
3383 *  Description:
3384 *  -----------
3385 *  This function is used to switch the window manager configuration between
3386 *  the built-in configuration (for CXI behavior) and the user's custom
3387 *  configuration.
3388 *
3389 *************************************<->***********************************/
3390
3391#ifdef _NO_PROTO
3392Boolean F_Set_Behavior (args, pCD, event)
3393    String args;
3394    ClientData *pCD;
3395    XEvent *event;
3396
3397#else /* _NO_PROTO */
3398Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
3399#endif /* _NO_PROTO */
3400{
3401    /*
3402     * Go system modal in starting to do the set behavior.
3403     */
3404
3405    /* !!! grab the server and the pointer !!! */
3406
3407
3408    /*
3409     * Confirm that a set_behavior should be done.
3410     * Execute restart if so.
3411     */
3412
3413    if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
3414    {
3415        ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
3416                       CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
3417    }
3418    else
3419    {
3420        RestartWm ((long) ((wmGD.useStandardBehavior) ?
3421                        MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
3422    }
3423    return (False);
3424
3425} /* END OF FUNCTION F_Set_Behavior */
3426
3427
3428
3429/*************************************<->*************************************
3430 *
3431 *  Do_Set_Behavior (dummy)
3432 *
3433 *
3434 *  Description:
3435 *  -----------
3436 *  Callback to do the f.set_behavior function.
3437 *
3438 *************************************<->***********************************/
3439
3440#ifdef _NO_PROTO
3441void Do_Set_Behavior (dummy)
3442Boolean dummy;
3443#else /* _NO_PROTO */
3444void Do_Set_Behavior (Boolean dummy)
3445#endif /* _NO_PROTO */
3446{
3447    RestartWm ((long) ((wmGD.useStandardBehavior) ?
3448                        MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
3449
3450} /* END OF FUNCTION Do_Set_Behavior */
3451
3452
3453
3454/*************************************<->*************************************
3455 *
3456 *  F_Title (args, pCD, event)
3457 *
3458 *
3459 *  Description:
3460 *  -----------
3461 *  This is a placeholder function; it should never be called.
3462 *
3463 *************************************<->***********************************/
3464
3465#ifdef _NO_PROTO
3466Boolean F_Title (args, pCD, event)
3467    String args;
3468    ClientData *pCD;
3469    XEvent *event;
3470
3471#else /* _NO_PROTO */
3472Boolean F_Title (String args, ClientData *pCD, XEvent *event)
3473#endif /* _NO_PROTO */
3474{
3475
3476    return (True);
3477
3478} /* END OF FUNCTION F_Title */
3479
3480
3481
3482/******************************<->*************************************
3483 *
3484 *  F_Screen (args, pCD, event)
3485 *
3486 *
3487 *  Description:
3488 *  -----------
3489 *  This is the window manager function handler for warping to screens
3490 *
3491 *
3492 *  Inputs:
3493 *  ------
3494 *  args = (immediate value) window type flags
3495 *
3496 *  pCD = pointer to the client data
3497 *
3498 *  event = X event that invoked the function (key, button, or menu/NULL)
3499 *
3500 *  NOTE: May want to consider tracking changes in screen because in
3501 *        managing a new window (ie. in ManageWindow()).
3502 *
3503 *  Outputs:
3504 *  -------
3505 *  RETURN = if True then further button binding/function processing can
3506 *           be done for the event that caused this function to be called.
3507 *
3508 *************************************<->***********************************/
3509
3510#ifdef _NO_PROTO
3511Boolean F_Screen (args, pCD, event)
3512    String args;
3513    ClientData *pCD;
3514    XEvent *event;
3515
3516#else /* _NO_PROTO */
3517Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
3518#endif /* _NO_PROTO */
3519{
3520    Window dumwin;
3521    int x, y, dumint;
3522    unsigned int dummask;
3523    WmScreenData *newscr = NULL;
3524    int scr, inc;
3525    static int PreviousScreen = -1;
3526    char pch[80];
3527   
3528
3529    if (PreviousScreen == -1)
3530    {
3531        PreviousScreen = DefaultScreen(DISPLAY);
3532    }
3533
3534    if (strcmp (args, "next") == 0)
3535    {
3536        scr = ACTIVE_PSD->screen + 1;
3537        inc = 1;
3538    }
3539    else if (strcmp (args, "prev") == 0)
3540    {
3541        scr = ACTIVE_PSD->screen - 1;
3542        inc = -1;
3543    }
3544    else if (strcmp (args, "back") == 0)
3545    {
3546        scr = PreviousScreen;
3547        inc = 0;
3548    }
3549    else
3550    {
3551        scr = atoi (args);
3552        inc = 0;
3553    }
3554
3555    while (!newscr) {
3556                                        /* wrap around */
3557        if (scr < 0)
3558          scr = wmGD.numScreens - 1;
3559        else if (scr >= wmGD.numScreens)
3560          scr = 0;
3561
3562        newscr = &(wmGD.Screens[scr]);
3563        if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
3564            if (inc) {                  /* walk around the list */
3565                scr += inc;
3566                continue;
3567            }
3568            sprintf(pch,
3569                    "Unable to warp to unmanaged screen %d\n", scr);
3570            Warning (&pch[0]);
3571            XBell (DISPLAY, 0);
3572            return (False);
3573        }
3574    }
3575
3576    if (ACTIVE_PSD->screen == scr) return (False);  /* already on that screen */
3577
3578    PreviousScreen = ACTIVE_PSD->screen;
3579    XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
3580                   &dumint, &dumint, &dummask);
3581
3582    XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
3583
3584    if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
3585    {
3586        /*
3587         * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can
3588         * uses the new screen instead of the old screen.  Then call
3589         * Do_Focus_Key with a NULL pCD to find a reasonable client to
3590         * set focus to.
3591         */
3592        SetActiveScreen (newscr);
3593        Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
3594                      ALWAYS_SET_FOCUS);
3595    }
3596
3597    return (False);
3598}
3599
3600
3601
3602/*************************************<->*************************************
3603 *
3604 *  GetFunctionTimestamp (pEvent)
3605 *
3606 *
3607 *  Description:
3608 *  -----------
3609 *  This function is used to extract a timestamp from a key or button event.
3610 *  If the event passed in is not a key or button event then a timestamp
3611 *  is generated.
3612 *
3613 *
3614 *  Inputs:
3615 *  ------
3616 *  event = pointer to an X event
3617 *
3618 *
3619 *  Outputs:
3620 *  -------
3621 *  RETURN = a timestamp
3622 *
3623 *************************************<->***********************************/
3624
3625#ifdef _NO_PROTO
3626Time GetFunctionTimestamp (pEvent)
3627    XButtonEvent *pEvent;
3628
3629#else /* _NO_PROTO */
3630Time GetFunctionTimestamp (XButtonEvent *pEvent)
3631#endif /* _NO_PROTO */
3632{
3633    Time time;
3634
3635    if (pEvent &&
3636        (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
3637         ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
3638    {
3639        time = pEvent->time;
3640    }
3641    else
3642    {
3643        time = GetTimestamp ();
3644    }
3645
3646    return (time);
3647
3648} /* END OF FUNCTION GetFunctionTimestamp */
3649
3650
3651/*
3652** name the event mask we need for a grab in order to find the matching
3653** event for an event; right now handle only button-presses
3654*/
3655#ifdef _NO_PROTO
3656static unsigned int GetEventInverseMask(event)
3657        XEvent *event;
3658#else   /* _NO_PROTO */
3659static unsigned int GetEventInverseMask(XEvent *event)
3660#endif  /* _NO_PROTO */
3661{
3662        if ((XEvent*)NULL == event)
3663                return 0;
3664        if (ButtonPress == event->type)
3665                return ButtonReleaseMask;       /* detail ? */
3666        /*
3667        expansion further here
3668        */
3669        else
3670                return 0;
3671}
3672
3673
3674
3675/*************************************<->*************************************
3676 *
3677 *  ClearDirtyStackEntry (pCD)
3678 *
3679 *
3680 *  Description:
3681 *  -----------
3682 *  This function is used to clear the static dirtyStackEntry structure and
3683 *  the dirtyLeader static variable when a pCD is destroyed.  This
3684 *  guarantees that freed memory will not be accessed.
3685 *
3686 *
3687 *  Inputs:
3688 *  ------
3689 *  pCD = pointer to clientData being freed
3690 *
3691 *
3692 *  Outputs:
3693 *  -------
3694 *  RETURN = void
3695 *
3696 *************************************<->***********************************/
3697
3698#ifdef _NO_PROTO
3699void ClearDirtyStackEntry (pCD)
3700    ClientData *pCD;
3701
3702#else /* _NO_PROTO */
3703void ClearDirtyStackEntry (ClientData *pCD)
3704#endif /* _NO_PROTO */
3705{
3706  if (pCD == dirtyStackEntry.pCD)
3707    {
3708      dirtyStackEntry.pCD = NULL;
3709      dirtyLeader = NULL;
3710    }
3711}
Note: See TracBrowser for help on using the repository browser.