2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$TOG: WmFunction.c /main/19 1998/04/20 13:00:48 mgreess $"
36 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY
37 * (c) Copyright 1993, 1994 International Business Machines Corp.
38 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39 * (c) Copyright 1993, 1994 Novell, Inc.
54 #include "WmWrkspace.h" /* for ClientInWorkspace() test */
55 #include <Dt/EnvControlP.h> /* for restoring **environ before an exec() */
56 #include "WmResNames.h"
57 #include <Dt/Message.h>
60 #include <Dt/DtStrDefs.h>
66 * include extern functions
68 #include "WmFunction.h"
74 #include "WmColormap.h"
77 #include "WmFeedback.h"
82 #include "WmIconBox.h"
83 #include "WmKeyFocus.h"
86 #include "WmPresence.h"
88 #include "WmProperty.h"
89 #include "WmProtocol.h"
90 #include "WmResParse.h"
91 #include "WmWinConf.h"
92 #include "WmWinInfo.h"
93 #include "WmWinList.h"
94 #include "WmWinState.h"
97 #include <Xm/RowColumnP.h> /* for MS_LastManagedMenuTime */
98 extern XmMenuState _XmGetMenuState();
100 extern int putenv ();
101 extern char * getenv ();
103 extern pid_t vfork();
104 #endif /* PORT_NOVFORK */
106 static unsigned int GetEventInverseMask(XEvent *event);
110 #if (defined(__linux__) || defined(sun) || defined(CSRG_BASED)) && !defined(_NFILE)
111 #define _NFILE FOPEN_MAX
113 #define CLOSE_FILES_ON_EXEC() \
114 {int ifx; for (ifx=3; ifx < _NFILE; ifx++) (void) fcntl (ifx, F_SETFD, 1);}
122 * The 'dirty' variables are used to keep track of the transient window
123 * that has been lowered via "f.lower freeFamily".
125 static ClientData *dirtyStackEntry = NULL;
126 static ClientData *dirtyLeader = NULL;
130 /***********************<->*************************************
132 * F_Action (args, pCD, event)
137 * This is the window manager function handler for invoking actions.
142 * args = action function and arguments
144 * pCD = pointer to the ClientData for the whole front panel
146 * event = X event that invoked the function (key, button, or menu/NULL)
151 * RETURN = if True then further button binding/function processing can
152 * be done for the event that caused this function to be called.
156 * The pCD->controlWindow is a temporary area used solely for
157 * this function invocation--it stores the pCW of the control
158 * that want the function to happen.
159 ******************************<->***********************************/
162 F_Action (String actionName, ClientData *pCD, XEvent *event)
165 WmActionArg *pAP = (WmActionArg *) actionName;
167 /* make sure the command runs on the right display. */
168 if (wmGD.pActiveSD->displayString)
170 putenv(wmGD.pActiveSD->displayString);
175 WmFrontPanelSetBusy (True);
179 DtActionInvoke (wmGD.pActiveSD->screenTopLevelW1,
180 pAP->actionName, pAP->aap, pAP->numArgs,
181 pAP->szExecParms, NULL, NULL, 1, NULL, NULL);
184 * Restore original DISPLAY environment variable
186 if(wmGD.pActiveSD->displayString && wmGD.displayString)
188 putenv(wmGD.displayString);
193 } /* END OF FUNCTION F_Action */
197 /******************************<->*************************************
199 * F_Beep (args, pCD, event)
204 * This is the window manager function handler for beeping.
209 * args = function arguments (specified in .mwmrc file)
211 * pCD = pointer to the client data for the client window to which the
212 * function is to be applied
214 * event = X event that invoked the function (key, button, or menu/NULL)
219 * RETURN = if True then further button binding/function processing can
220 * be done for the event that caused this function to be called.
222 ******************************<->***********************************/
224 Boolean F_Beep (String args, ClientData *pCD, XEvent *event)
227 /* !!! what is a good value for percent (the second arg) !!! */
232 } /* END OF FUNCTION F_Beep */
237 * Handle Special case where the dirty window is the top most
238 * transient window. When this is the case, raising the window
239 * that was on top (the window just below the dirty window) will
240 * fail because Mwm stack database is out of sync. So the solution
241 * is to restack the dirty transient relative to the second to the
242 * top transient. This function is used to support freeFamily stacking.
244 ClientData * FindSecondToTopTransient (pcd)
248 static ClientData *second;
250 pcdNext = pcd->transientChildren;
253 if (pcdNext->transientChildren)
255 if (!pcdNext->transientChildren->transientChildren)
259 FindSecondToTopTransient (pcdNext);
261 pcdNext = pcdNext->transientSiblings;
262 if (pcdNext && !pcdNext->transientSiblings)
270 } /* END OF FUNCTION */
274 Boolean ForceLowerWindow (ClientData *pcd)
278 WmScreenData *pSD = (ACTIVE_WS)->pSD;
280 XWindowChanges changes;
281 Boolean restack = False;
284 WmScreenData *pSD = (ACTIVE_WS)->pSD;
286 ClientListEntry *pCLE;
289 * Find lowest window in this workspace. We'll stack this transient
292 pCLE = pSD->lastClient;
297 if ((pCLE->pCD != pcd) &&
298 (ClientInWorkspace (ACTIVE_WS, pCLE->pCD)))
300 if ((pCLE->type == MINIMIZED_STATE) &&
301 (pCLE->pCD->clientState == MINIMIZED_STATE))
303 stackWindow = ICON_FRAME_WIN(pCLE->pCD);
305 else if ((pCLE->type == NORMAL_STATE) &&
306 ((pCLE->pCD->clientState == NORMAL_STATE) ||
307 (pCLE->pCD->clientState == MAXIMIZED_STATE)))
309 stackWindow = pCLE->pCD->clientFrameWin;
312 if (stackWindow != None)
315 changes.sibling = stackWindow;
319 if (stackWindow == None)
321 pCLE = pCLE->prevSibling;
326 if (pSD->lastClient->type == MINIMIZED_STATE)
328 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
332 stackWindow = pSD->lastClient->pCD->clientFrameWin;
336 changes.stack_mode = Below;
340 XConfigureWindow (DISPLAY, pcd->clientFrameWin, mask, &changes);
343 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
352 /*************************************<->*************************************
354 * F_Lower (args, pCD, event)
359 * This is the window manager function handler for bottoming a client window
365 * args = function arguments (specified in .mwmrc file)
367 * pCD = pointer to the client data for the client window to which the
368 * function is to be applied
370 * event = X event that invoked the function (key, button, or menu/NULL)
375 * RETURN = if True then further button binding/function processing can
376 * be done for the event that caused this function to be called.
378 *************************************<->***********************************/
380 Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
382 ClientListEntry *pEntry;
383 ClientListEntry *pNextEntry;
384 ClientListEntry *pStackEntry;
385 String string = args;
386 int flags = STACK_NORMAL;
388 WmWorkspaceData *pWS = ACTIVE_WS;
393 /* process '-client' argument */
394 if (string[0] == '-')
397 string = (String) GetString ((unsigned char **) &string);
400 pNextEntry = ACTIVE_PSD->lastClient;
402 (pEntry = FindClientNameMatch (pNextEntry, False,
403 string, F_GROUP_ALL)))
405 pNextEntry = pEntry->prevSibling;
407 if (ClientInWorkspace (pWS, pEntry->pCD))
410 Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
411 pStackEntry = pEntry;
417 /* process family stacking stuff */
420 unsigned int slen, len, index;
422 slen = strlen(args) - 2; /* subtract '\n' and NULL */
423 for (index = 0; index < slen; string = &args[index+1])
425 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
427 len = strlen(string);
428 if (!strcmp(string,"within"))
430 flags |= STACK_WITHIN_FAMILY;
432 else if (!strcmp(string,"freeFamily"))
434 flags |= STACK_FREE_FAMILY;
439 if (ClientInWorkspace (pWS, pCD))
442 Do_Lower (pCD, (ClientListEntry *) NULL, flags);
451 if (ClientInWorkspace (pWS, pCD))
454 Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
461 * If caused by button press, event may ALSO cause focus to be
462 * passed to this client - prepare to disable focusAutoRaise.
464 if (pCD && event && (event->type == ButtonPress))
465 pCD->focusAutoRaiseDisablePending = True;
467 wmGD.passButtonsCheck = False;
470 } /* END OF FUNCTION F_Lower */
474 /*************************************<->*************************************
476 * Do_Lower (pCD, pStackEntry)
481 * This is the window manager function handler for lowering the client window
482 * so that it does not obscure any other window above the stack entry
488 * pCD = pointer to the client data of the window (or icon) to be lowered.
490 * pStackEntry = pointer to client list entry for window that is to be
491 * below the lowered window (if NULL, window is lowered to the bottom
494 *************************************<->***********************************/
496 void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
498 Boolean restackTransients;
499 ClientData *pcdLeader;
500 WmWorkspaceData *pWS = ACTIVE_WS;
502 Boolean bLeaderRestacked;
508 * Window has been reparented into the front panel.
509 * Don't follow through on window stacking change.
515 if (ClientInWorkspace(pWS, pCD) &&
516 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
519 * Both clients are in the current workspace. Set
520 * client indices so that the access macros work.
522 SetClientWsIndex (pCD);
525 SetClientWsIndex (pStackEntry->pCD);
531 * One or both of the clients are not in the current workspace
538 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
540 if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
543 * If a dirtyStackEntry exists, return it to its original place
544 * in the stack (for all stacking types)
548 if (dirtyStackEntry->transientChildren ||
549 dirtyStackEntry->transientLeader)
550 RestackTransients (dirtyStackEntry);
551 dirtyStackEntry = NULL;
556 * Only restack the icon if it is not currently lowered.
561 if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
563 StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
565 MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
571 if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
573 StackWindow (pWS, &pcdLeader->iconEntry,
574 False /*on bottom*/, (ClientListEntry *) NULL);
575 MoveEntryInList (pWS, &pcdLeader->iconEntry,
576 False /*on bottom*/, (ClientListEntry *) NULL);
580 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
584 * Handle restacking of primary/secondary windows
585 * within the transient window tree.
587 bLeaderRestacked = False;
588 if ((pcdLeader->transientChildren) &&
589 (!pcdLeader->secondariesOnTop) &&
590 (!wmGD.bSuspendSecondaryRestack))
592 if (pCD == pcdLeader)
595 * Lower requested on the leader itself, insure it's
598 bLeaderRestacked = BumpPrimaryToBottom (pcdLeader);
600 else if (pCD->transientChildren)
603 * Lower requested on the leader of a subtree. Insure
604 * that this subtree leader is at the bottom of the
607 bLeaderRestacked = BumpPrimaryToBottom (pCD);
609 else if (pCD->transientLeader)
614 * Lower requested on a transient. Insure all the
615 * subtree leaders up to the top are at the bottom
616 * of their respective transient subtrees.
618 for (pcdLdr = pCD->transientLeader;
620 pcdLdr = pcdLdr->transientLeader)
622 bLeaderRestacked |= BumpPrimaryToBottom (pcdLdr);
629 * If this is a transient window then put it below its
630 * sibling transient windows.
633 restackTransients = False;
634 if (pCD->transientLeader)
638 * If freeFamily stacking, then put dirty transient window
639 * (if any) back in place before force lowering current window
640 * to the bottom of the global window stack. Then return.
643 if (flags & STACK_FREE_FAMILY)
645 /* Restore dirty transient if not current window. */
646 if ((dirtyStackEntry) &&
647 (dirtyStackEntry != pCD))
649 RestackTransients (dirtyStackEntry);
652 dirtyStackEntry = pCD;
653 dirtyLeader = pcdLeader;
655 ForceLowerWindow (pCD);
660 * Reach here only if NOT doing a f.lower freeFamily (see
661 * return; statement above). Put current transient below
662 * its sibling transient windows.
664 restackTransients = PutTransientBelowSiblings (pCD);
668 * If doing a regular f.lower and you have a dirty window, then
669 * clean up dirty transient window.
675 * If lowering a window in the same family as the dirty
676 * transient window, then just restack before lowering.
677 * Else, restore the dirty transient in place before
678 * lowering the current window. Clear dirtyStack.
680 if (dirtyLeader == pcdLeader)
682 restackTransients = True;
686 RestackTransients (dirtyStackEntry);
689 dirtyStackEntry = NULL;
693 * Only restack the window or transient window tree if it is
694 * not currently lowered and the window is not a system
700 if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
701 !(wmGD.systemModalActive &&
702 (pcdLeader == wmGD.systemModalClient)))
704 StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
706 MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
710 else if ((restackTransients) || (bLeaderRestacked))
712 else if (restackTransients)
715 RestackTransients (pCD);
720 if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
721 !(wmGD.systemModalActive &&
722 (pcdLeader == wmGD.systemModalClient)) &&
723 !(flags & STACK_WITHIN_FAMILY))
725 StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
726 (ClientListEntry *) NULL);
727 MoveEntryInList (pWS, &pcdLeader->clientEntry,
728 False /*on bottom*/, (ClientListEntry *) NULL);
731 else if ((restackTransients) || (bLeaderRestacked))
733 else if (restackTransients)
736 RestackTransients (pCD);
741 } /* END OF FUNCTION Do_Lower */
745 /*************************************<->*************************************
747 * F_CircleDown (args, pCD, event)
752 * This is the window manager function handler for moving the client window
753 * on top of stack to the bottom.
758 * args = function arguments (specified in .mwmrc file)
760 * pCD = pointer to the client data for the client window to which the
761 * function is to be applied
763 * event = X event that invoked the function (key, button, or menu/NULL)
768 * RETURN = if True then further button binding/function processing can
769 * be done for the event that caused this function to be called.
771 *************************************<->***********************************/
773 Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
776 unsigned long windowType;
777 ClientListEntry *pNextEntry;
782 * Go down through the client list looking for a window of an
783 * appropriate type that is obscuring lower windows.
786 types = (unsigned long)args;
787 pNextEntry = ACTIVE_PSD->clientList;
791 * Only check out the window if it is onscreen.
794 pcdNext = pNextEntry->pCD;
795 if (((pNextEntry->type == NORMAL_STATE) &&
796 (pcdNext->clientState != MINIMIZED_STATE)) ||
797 ((pNextEntry->type == MINIMIZED_STATE) &&
798 (pcdNext->clientState == MINIMIZED_STATE)))
800 if (pcdNext->clientState == MINIMIZED_STATE)
802 windowType = F_GROUP_ICON;
806 windowType = F_GROUP_WINDOW;
807 if (pcdNext->transientLeader || pcdNext->transientChildren)
809 windowType |= F_GROUP_TRANSIENT;
812 if (types & windowType)
814 if (CheckIfClientObscuringAny (pcdNext))
817 * This window (or window tree) is obscuring another window
818 * on the screen. Lower the window.
822 wmGD.bSuspendSecondaryRestack = True;
824 F_Lower (NULL, pcdNext, (XEvent *) NULL);
826 wmGD.bSuspendSecondaryRestack = False;
832 pNextEntry = pNextEntry->nextSibling;
837 } /* END OF FUNCTION F_Circle_Down */
841 /*************************************<->*************************************
843 * F_Circle_Up (args, pCD, event)
848 * This is the window manager function handler for moving the client window
849 * on the bottom of the stack to the top.
854 * args = function arguments (specified in .mwmrc file)
856 * pCD = pointer to the client data for the client window to which the
857 * function is to be applied
859 * event = X event that invoked the function (key, button, or menu/NULL)
864 * RETURN = if True then further button binding/function processing can
865 * be done for the event that caused this function to be called.
867 *************************************<->***********************************/
869 Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
872 unsigned long windowType;
873 ClientListEntry *pNextEntry;
878 * Go up through the client list looking for a window of an
879 * appropriate type that is obscured by higher windows.
882 types = (unsigned long)args;
883 pNextEntry = ACTIVE_PSD->lastClient;
887 * Only check out the window if it is onscreen.
890 pcdNext = pNextEntry->pCD;
891 if (((pNextEntry->type == NORMAL_STATE) &&
892 (pcdNext->clientState != MINIMIZED_STATE)) ||
893 ((pNextEntry->type == MINIMIZED_STATE) &&
894 (pcdNext->clientState == MINIMIZED_STATE)))
896 if (pcdNext->clientState == MINIMIZED_STATE)
898 windowType = F_GROUP_ICON;
902 windowType = F_GROUP_WINDOW;
903 if (pcdNext->transientLeader || pcdNext->transientChildren)
905 windowType |= F_GROUP_TRANSIENT;
908 if (types & windowType)
910 if (CheckIfClientObscuredByAny (pcdNext))
913 * This window (or window tree) is obscured by another
914 * window on the screen. Raise the window.
918 wmGD.bSuspendSecondaryRestack = True;
920 F_Raise (NULL, pcdNext, (XEvent *) NULL);
922 wmGD.bSuspendSecondaryRestack = False;
928 pNextEntry = pNextEntry->prevSibling;
934 } /* END OF FUNCTION F_Circle_Up */
938 /*************************************<->*************************************
940 * F_Focus_Color (args, pCD, event)
945 * This is the window manager function handler for setting the colormap
946 * focus to a client window or reinstalling the default colormap.
948 *************************************<->***********************************/
950 Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
953 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
958 * The window selected for the colormap focus is a top-level client
959 * window. If there are subwindow colormaps then determine if the
960 * selection was in one of the subwindows.
963 if (pCD->clientState == MINIMIZED_STATE)
965 /* !!! colormap for client supplied icon window !!! */
970 SetColormapFocus (ACTIVE_PSD, pCD);
975 } /* END OF FUNCTION F_Focus_Color */
979 /*************************************<->*************************************
981 * F_Exec (args, pCD, event)
986 * This is the window manager function handler for executing a command
989 *************************************<->***********************************/
991 Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
1004 /* make sure the f.exec command runs on the right display. */
1005 if (wmGD.pActiveSD->displayString)
1007 putenv(wmGD.pActiveSD->displayString);
1013 * Start the busy indicator, waiting for a pushbutton window
1014 * for the given duration
1016 WmFrontPanelSetBusy (True);
1020 * Fork a process to exec a shell to run the specified command:
1024 if ((pid = fork ()) == 0)
1026 if ((pid = vfork ()) == 0)
1031 #if defined(SVR4) || defined(__linux__)
1040 setpgrp(tpid, tpid);
1043 #endif /* NO_SETPGRP */
1046 * Clean up window manager resources.
1047 * The X file descriptor should be automatically closed.
1051 * Fix up signal handling.
1053 RestoreDefaultSignalHandlers ();
1056 * Fix up the child application's environment NOT to
1057 * inherit the XFILESEARCHPATH, XBMLANGPATH, NLSPATH, etc.
1060 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
1062 CLOSE_FILES_ON_EXEC();
1066 * Exec the command using $MWMSHELL if set or
1067 * $SHELL if set and $MWMSHELL not set or sh.
1070 if (((shell = getenv ("MWMSHELL")) != NULL) ||
1071 ((shell = getenv ("SHELL")) != NULL))
1074 shellname = strrchr (shell, '/');
1075 if (shellname == NULL)
1078 If the shell pathname obtained from SHELL or MWMSHELL does not
1079 have a "/" in the path and if the user expects this shell to be
1080 obtained using the PATH variable rather than the current
1081 directory, then we must call execlp and not execl
1084 execlp (shell, shellname, "-c", args, NULL);
1089 execl (shell, shellname, "-c", args, NULL);
1094 * There is no SHELL environment variable or the first execl failed.
1098 execl ("/usr/bin/sh", "sh", "-c", args, NULL);
1100 execl ("/bin/sh", "sh", "-c", args, NULL);
1105 * Error - command could not be exec'ed.
1115 * Have the window manager wait for the shell to complete.
1119 intStat = (void (*)())signal (SIGINT, SIG_IGN);
1120 quitStat = (void (*)())signal (SIGQUIT, SIG_IGN);
1125 * Don't need to wait because WSM sets SIGCLD handler
1128 while ((w = wait (&status)) != pid && (w != -1));
1137 signal (SIGINT, intStat);
1138 signal (SIGQUIT, quitStat);
1142 * Restore original DISPLAY environment variable value
1143 * so a restart will start on the same screen
1146 if(wmGD.pActiveSD->displayString &&
1149 putenv(wmGD.displayString);
1156 } /* END OF FUNCTION F_Exec */
1160 /*************************************<->*************************************
1162 * F_Quit_Mwm (args, pCD, event)
1167 * This is the window manager function handler for terminating the window
1170 *************************************<->***********************************/
1172 Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
1174 if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
1176 ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
1185 } /* END OF FUNCTION F_Quit_Mwm */
1189 /*************************************<->*************************************
1191 * Do_Quit_Mwm (diedOnRestart)
1196 * Callback to do the f.quit_mwm function.
1198 *************************************<->***********************************/
1200 void Do_Quit_Mwm (Boolean diedOnRestart)
1203 ClientListEntry *pNextEntry;
1207 * Close the X connection to get all the X resources cleaned up.
1208 * !!! maybe windows should be reparented / rebordered before closing? !!!
1209 * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
1215 XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
1216 for (scr = 0; scr < wmGD.numScreens; scr++)
1218 if (wmGD.Screens[scr].managed)
1221 SaveResources(&wmGD.Screens[scr]);
1223 pNextEntry = wmGD.Screens[scr].lastClient;
1226 if (pNextEntry->type == NORMAL_STATE)
1228 if (!(pNextEntry->pCD->clientFlags &
1231 ReBorderClient (pNextEntry->pCD, diedOnRestart);
1234 pNextEntry = pNextEntry->prevSibling;
1236 UnParentControls (&wmGD.Screens[scr], False);
1239 XDeleteProperty(DISPLAY, wmGD.Screens[scr].rootWindow,
1245 /* shut down the messaging connection */
1249 XSync (DISPLAY, False);
1250 XCloseDisplay (DISPLAY);
1255 exit (WM_ERROR_EXIT_VALUE);
1262 } /* END OF FUNCTION Do_Quit_Mwm */
1265 /*************************************<->*************************************
1267 * ReBorderClient (pCD, reMapClient)
1272 * Restores X border for client window and reparents the
1273 * window back to the root.
1278 * pCD = pointer to the client data for the window to be re-bordered.
1280 *************************************<->***********************************/
1282 void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1286 XWindowChanges windowChanges;
1290 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1293 XUnmapWindow (DISPLAY, pCD->iconWindow);
1295 XReparentWindow (DISPLAY, pCD->iconWindow,
1296 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
1297 pCD->pWsList->iconY);
1299 XReparentWindow (DISPLAY, pCD->iconWindow,
1300 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
1313 if(wmGD.positionIsFrame)
1315 CalculateGravityOffset (pCD, &xoff, &yoff);
1316 x = pCD->clientX - xoff;
1317 y = pCD->clientY - yoff;
1325 XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1326 XReparentWindow (DISPLAY, pCD->client,
1327 ROOT_FOR_CLIENT(pCD), x, y);
1331 XMapWindow(wmGD.display, pCD->client);
1334 if (pCD->transientChildren)
1336 ReBorderClient (pCD->transientChildren, reMapClient);
1344 windowChanges.x = x;
1345 windowChanges.y = y;
1346 windowChanges.border_width = pCD->xBorderWidth;
1347 XConfigureWindow (DISPLAY, pCD->client,
1348 CWBorderWidth | CWX | CWY, &windowChanges);
1351 if (pCD->transientLeader)
1353 pCD = pCD->transientSiblings;
1361 } /* END OF FUNCTION ReBorderClient */
1365 /*************************************<->*************************************
1367 * F_Focus_Key (args, pCD, event)
1372 * This is the window manager function handler for setting the keyboard
1373 * focus to a particular client window.
1378 * args = (immediate value) focus flags
1380 * pCD = pointer to the client data
1382 * event = X event that invoked the function (key, button, or menu/NULL)
1384 *************************************<->***********************************/
1386 Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1388 long focusFlags = (long)args;
1391 if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1393 Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1394 (focusFlags | ALWAYS_SET_FOCUS));
1399 } /* END OF FUNCTION F_Focus_Key */
1402 /*************************************<->*************************************
1404 * FindSomeReasonableClient
1408 * Find a client, any client to set the focus to, return client or NULL.
1409 * This code is ripped off from AutoResetKeyFocus().
1411 *************************************<->***********************************/
1413 static Window FindSomeReasonableClient(void)
1415 ClientData *pcdNoFocus=NULL;
1417 ClientListEntry *pNextEntry;
1419 ClientData *pcdLastFocus = (ClientData *) NULL;
1420 ClientData *pcdFocus;
1421 Window focusWindow = (Window) NULL;
1424 * Scan through the list of clients to find a window to get the focus.
1427 pNextEntry = ACTIVE_PSD->clientList;
1431 pCD = pNextEntry->pCD;
1432 if (!wmGD.systemModalActive ||
1433 (wmGD.systemModalClient == pCD))
1435 if ((pNextEntry->type != MINIMIZED_STATE) &&
1436 (pCD->clientState != MINIMIZED_STATE) &&
1438 (ClientInWorkspace (ACTIVE_WS, pCD)) &&
1440 (pCD != pcdNoFocus))
1442 if (pCD->transientChildren)
1444 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1451 ((pcdLastFocus == NULL) ||
1452 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1454 pcdLastFocus = pcdFocus;
1458 pNextEntry = pNextEntry->nextSibling;
1462 * Set the focus window if one is found
1467 ClientInWorkspace (ACTIVE_WS, pcdLastFocus))
1471 focusWindow = pcdLastFocus->client;
1474 * If a client window could not be found, then just put focus
1478 if (focusWindow == (Window) NULL)
1480 pNextEntry = ACTIVE_PSD->clientList;
1484 pCD = pNextEntry->pCD;
1487 if (ClientInWorkspace (ACTIVE_WS, pCD))
1490 if ((pNextEntry->type == MINIMIZED_STATE) ||
1491 (pCD->clientState == MINIMIZED_STATE))
1493 focusWindow = ICON_FRAME_WIN(pCD);
1499 pNextEntry = pNextEntry->nextSibling;
1503 return (focusWindow);
1505 } /* END OF FUNCTION FindSomeReasonableClient */
1510 /*************************************<->*************************************
1512 * Do_Focus_Key (pCD, focusTime, flags)
1517 * This function is used to set the focus to a window. The focus indication
1518 * is not changed until the FocusIn event is received.
1523 * pCD = pointer to the client data
1525 * focusTime = focus change time
1527 * flags = wm focus change flags
1529 *************************************<->***********************************/
1531 void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1533 ClientData *pcdFocus;
1537 /* Clear the replay flag */
1538 wmGD.replayEnterEvent = False;
1543 * Make sure the client is in the current workspace
1546 (ClientInWorkspace (ACTIVE_WS, pCD)))
1551 if (pCD->clientState == MINIMIZED_STATE)
1553 focusWindow = ICON_FRAME_WIN(pCD);
1555 else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1558 * Set the keyboard focus to the indicated client window.
1559 * If the window has an application modal subordinate then
1560 * set the input focus to that window if the focus isn't
1561 * already owned by a subordinate.
1564 if (IS_APP_MODALIZED(pCD))
1566 ClientData *pcdFocusLeader,*currFocusLeader;
1569 * Handle case where a modal window exists when Mwm starts up.
1570 * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1573 if (wmGD.keyboardFocus)
1575 currFocusLeader = wmGD.keyboardFocus->transientLeader;
1579 currFocusLeader = (ClientData *) NULL;
1583 * Find focus leader for pCD
1586 pcdFocusLeader = pCD;
1587 while (pcdFocusLeader->transientLeader &&
1588 (pcdFocusLeader != currFocusLeader))
1590 pcdFocusLeader = pcdFocusLeader->transientLeader;
1593 if (pcdFocusLeader == currFocusLeader)
1595 pcdFocus = wmGD.keyboardFocus;
1600 pcdFocus = FindTransientFocus (pcdFocusLeader);
1605 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1606 * We must look at why FindTransientFocus is
1607 * returning a NULL pcd. The old code simply set
1608 * focusWindow = pcdFocus->client;
1609 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1611 * 11/26/96 rswiston - In tracking down CDExc22816, we
1612 * discovered that pCD could get tricked into thinking
1613 * it had modal transients when in fact all its transients
1614 * had been withdrawn (fixed in WithdrawTransientChildren()).
1615 * As a result, FindTransientFocus() returns wmGD.keyboardFocus;
1616 * if nobody has the focus, FindTransientFocus() returns NULL.
1620 focusWindow = pcdFocus->client;
1624 focusWindow = (wmGD.keyboardFocus) ?
1625 wmGD.keyboardFocus->client : ACTIVE_PSD->wmWorkspaceWin;
1631 * If the focus policy is "pointer" don't set the focus to a
1632 * window if it has an application modal subordinate.
1635 if (IS_APP_MODALIZED(pCD))
1638 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1640 /* Replay this later when the modal window is removed. */
1641 wmGD.replayEnterEvent = True;
1645 focusWindow = pcdFocus->client;
1652 * Set up the default (non client specific) keyboard input focus.
1655 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1657 focusWindow = PointerRoot;
1662 * The WORKSPACE_IF_NULL flag is used to prevent client
1663 * windows from flashing when deiconifying a client.
1666 if (WORKSPACE_IF_NULL & flags)
1668 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1672 /* find some reasonable client so that focus is not lost */
1674 focusWindow = FindSomeReasonableClient();
1675 if (focusWindow == (Window)NULL)
1677 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1683 if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1688 * Set the focus and/or send a take focus client message. This
1689 * is not done if a client area button press was done to set
1690 * set the focus and the window is a globally active input
1691 * style window (See ICCCM).
1694 if ( (flags & CLIENT_AREA_FOCUS) &&
1695 (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1696 ! pcdFocus->inputFocusModel &&
1697 (pcdFocus == pCD) &&
1698 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
1699 !(pcdFocus->clientState == MINIMIZED_STATE)
1704 * 1. User clicked in the client area AND
1705 * 2. Input model is Globally Active AND
1706 * 3. Keyboard focus policy is explicit
1709 /* this window has WM_TAKE_FOCUS set and InputField false. */
1710 /* just send a message. */
1711 SendClientMsg (pcdFocus->client,
1712 (long) wmGD.xa_WM_PROTOCOLS,
1713 (long) wmGD.xa_WM_TAKE_FOCUS,
1714 focusTime, NULL, 0);
1718 if ((pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1719 !(pcdFocus->clientState == MINIMIZED_STATE))
1722 * Locally Active Input Model - Send a take focus message to the client.
1725 SendClientMsg (pcdFocus->client,
1726 (long) wmGD.xa_WM_PROTOCOLS,
1727 (long) wmGD.xa_WM_TAKE_FOCUS,
1728 focusTime, NULL, 0);
1732 * Don't set the input focus if the window has input_field set
1733 * to False or has expressed an interest in WM_TAKE_FOCUS
1734 * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1735 * and the user click in the client area. If the user clicks
1736 * on the titlebar or traverses to this window via f.next_key,
1737 * set the focus so that the user can access the window menu
1741 if ( wmGD.enforceKeyFocus || /* res - default == True. */
1742 (flags & ALWAYS_SET_FOCUS) ||
1743 !(flags & CLIENT_AREA_FOCUS)|| /* clicked on frame? */
1744 pcdFocus->inputFocusModel || /* Pass.|Glob. Active */
1745 (pcdFocus->clientState == MINIMIZED_STATE)
1748 if ( !(flags & CLIENT_AREA_FOCUS) &&
1749 !pcdFocus->inputFocusModel &&
1750 !(pcdFocus->clientState == MINIMIZED_STATE))
1752 /* the window doesn't want the focus - set it to the frame */
1753 /* user clicked on the frame but we don't want the focus */
1754 /* set it to the client's frame */
1755 XSetInputFocus (DISPLAY, pcdFocus->clientBaseWin,
1756 RevertToPointerRoot, focusTime);
1758 else if ( !(flags & CLIENT_AREA_FOCUS) &&
1759 !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1760 pcdFocus->inputFocusModel
1763 XSetInputFocus (DISPLAY, focusWindow,
1764 RevertToPointerRoot, focusTime);
1768 XSetInputFocus (DISPLAY, focusWindow,
1769 RevertToParent, focusTime);
1775 * We've decided that the window shouldn't get the focus,
1776 * so don't change the focus.
1778 pcdFocus = wmGD.nextKeyboardFocus;
1784 XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1788 wmGD.nextKeyboardFocus = pcdFocus;
1792 } /* END OF FUNCTION Do_Focus_Key */
1797 /***********************<->*************************************
1799 * F_Goto_Workspace (args, pCD, event)
1803 * This is the window manager function handler for switching
1804 * to another workspace by name.
1808 * args = action function and arguments
1810 * pCD = pointer to the ClientData
1812 * event = X event that invoked the function (key, button, or menu/NULL)
1820 ******************************<->***********************************/
1822 F_Goto_Workspace (String args, ClientData *pCD, XEvent *event)
1824 WmScreenData *pSD = ACTIVE_PSD;
1829 * Compare argument against both resource name
1830 * and workspace title, take the first match.
1832 xms = XmStringCreate (args, XmFONTLIST_DEFAULT_TAG);
1833 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1835 if (!strcmp(pSD->pWS[iwsx].name, args) ||
1836 XmStringCompare (xms, pSD->pWS[iwsx].title))
1845 if (iwsx >= pSD->numWorkspaces)
1847 Warning (((char *)GETMESSAGE(26, 4,
1848 "Invalid workspace name specified for f.goto_workspace")));
1852 ChangeToWorkspace (&pSD->pWS[iwsx]);
1857 } /* END OF FUNCTION F_Goto_Workspace */
1863 /******************************<->*************************************
1865 * Boolean F_Help (String args, ClientData *pCD, XEvent *event)
1869 * Invoke help on the workspace manager
1873 * args - incoming values
1874 * pCD - associated client data structure
1875 * event - what triggered this call
1879 * Return - True if the call occurs; false otherwise.
1884 ******************************<->***********************************/
1886 F_Help (String args, ClientData *pCD, XEvent *event)
1890 rval = WmDtHelp(args);
1892 } /* END OF FUNCTION F_Help */
1895 /******************************<->*************************************
1897 * Boolean F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1901 * Invoke item help on the frontpanel
1906 * pCD - associated client data structure ??
1907 * event - what triggered this call
1911 * Return - True if the call occurs; false otherwise.
1916 ******************************<->***********************************/
1918 F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1921 * Help mode event processing interferes
1922 * with slide up windows. Don't continue
1923 * if windows are sliding.
1925 if (wmGD.iSlideUpsInProgress == 0)
1927 (void) WmDtHelpMode();
1930 } /* END OF FUNCTION F_Help_Mode */
1934 /******************************<->*************************************
1936 * F_Next_Key (args, pCD, event)
1941 * This is the window manager function handler for setting the keyboard
1942 * input focus to the next window in the set of managed windows.
1947 * args = (immediate value) window type flags
1949 * pCD = pointer to the client data
1951 * event = X event that invoked the function (key, button, or menu/NULL)
1953 *************************************<->***********************************/
1955 Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1957 #ifdef ROOT_ICON_MENU
1958 Boolean focused = False;
1959 #endif /* ROOT_ICON_MENU */
1960 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1962 #ifdef ROOT_ICON_MENU
1964 #endif /* ROOT_ICON_MENU */
1965 FocusNextWindow ((unsigned long)args,
1966 GetFunctionTimestamp ((XButtonEvent *)event));
1967 #ifdef ROOT_ICON_MENU
1968 if (focused && wmGD.iconClick &&
1969 event && event->type == KeyPress &&
1970 wmGD.nextKeyboardFocus &&
1971 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1972 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1975 * Post system menu from the icon
1977 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1980 #endif /* ROOT_ICON_MENU */
1985 } /* END OF FUNCTION F_Next_Key */
1989 /*************************************<->*************************************
1991 * F_Prev_Cmap (args, pCD, event)
1996 * This is the window manager function handler installing the previous
1997 * colormap in the list of client window colormaps.
1999 *************************************<->***********************************/
2001 Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
2005 pCD = ACTIVE_PSD->colormapFocus;
2008 if (pCD && (pCD->clientCmapCount > 0) &&
2009 ((pCD->clientState == NORMAL_STATE) ||
2010 (pCD->clientState == MAXIMIZED_STATE)))
2012 if (--(pCD->clientCmapIndex) < 0)
2014 pCD->clientCmapIndex = pCD->clientCmapCount - 1;
2016 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2017 if (ACTIVE_PSD->colormapFocus == pCD)
2019 #ifndef OLD_COLORMAP /* colormap */
2021 * We just re-ordered the colormaps list,
2022 * so we need to re-run the whole thing.
2024 pCD->clientCmapFlagsInitialized = 0;
2025 ProcessColormapList (ACTIVE_PSD, pCD);
2026 #else /* OSF original */
2027 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2034 } /* END OF FUNCTION F_Prev_Cmap */
2038 /*************************************<->*************************************
2040 * F_Prev_Key (args, pCD, event)
2045 * This is the window manager function handler for setting the keyboard
2046 * input focus to the previous window in the set of managed windows.
2051 * args = (immediate value) window type flags
2053 * pCD = pointer to the client data
2055 * event = X event that invoked the function (key, button, or menu/NULL)
2057 *************************************<->***********************************/
2059 Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
2061 #ifdef ROOT_ICON_MENU
2062 Boolean focused = False;
2063 #endif /* ROOT_ICON_MENU */
2064 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
2066 #ifdef ROOT_ICON_MENU
2068 #endif /* ROOT_ICON_MENU */
2069 FocusPrevWindow ((unsigned long)args,
2070 GetFunctionTimestamp ((XButtonEvent *)event));
2071 #ifdef ROOT_ICON_MENU
2072 if (focused && wmGD.iconClick &&
2073 event && event->type == KeyPress &&
2074 wmGD.nextKeyboardFocus &&
2075 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
2076 !P_ICON_BOX(wmGD.nextKeyboardFocus))
2079 * Post system menu from the icon
2081 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
2084 #endif /* ROOT_ICON_MENU */
2090 } /* END OF FUNCTION F_Prev_Key */
2092 /***********************<->*************************************
2094 * F_Post_FpMenu (args, pCD, event)
2099 * This is the window manager function handler for posting
2100 * the Front Panel window menu.
2104 * args = arguments (none)
2106 * pCD = pointer to the FP ClientData
2108 * event = X button press that invoked the function
2110 ******************************<->***********************************/
2113 F_Post_FpMenu (String args, ClientData *pCD, XEvent *event)
2115 static MenuSpec *fpMenuSpec = (MenuSpec *)NULL;
2117 if (event->type != ButtonPress)
2122 WmScreenData *pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2127 newMenuName = pCD ? pCD->systemMenu : "DtPanelMenu";
2129 for (oldSpec = pSD->menuSpecs;
2130 oldSpec != (MenuSpec *)NULL;
2131 oldSpec = oldSpec->nextMenuSpec)
2133 if (oldSpec->name && (strcmp(oldSpec->name, newMenuName) == 0))
2139 fpMenuSpec = DuplicateMenuSpec(oldSpec);
2142 * TEMPORARILY modify pSD so the new menu will be
2143 * created on DISPLAY1 instead of DISPLAY.
2145 fpMenuSpec->nextMenuSpec = pSD->menuSpecs;
2146 pSD->menuSpecs = fpMenuSpec;
2147 tmpWidget = pSD->screenTopLevelW;
2148 pSD->screenTopLevelW = pSD->screenTopLevelW1;
2150 (void)MAKE_MENU (pSD, pCD, newMenuName,
2151 F_CONTEXT_NORMAL, F_CONTEXT_NORMAL,
2152 (MenuItem *) NULL, FALSE);
2155 pSD->screenTopLevelW = tmpWidget;
2156 pSD->menuSpecs = fpMenuSpec->nextMenuSpec;
2159 PostMenu (fpMenuSpec, pCD, event->xbutton.x_root, event->xbutton.y_root,
2160 event->xbutton.button, F_CONTEXT_NORMAL, POST_AT_XY, event);
2162 _XmGetMenuState(XtParent(fpMenuSpec->menuWidget))
2163 ->MS_LastManagedMenuTime = event->xbutton.time;
2169 /***********************<->*************************************
2171 * F_Push_Recall (args, pCD, event)
2176 * This is the window manager function handler for invoking/topping
2177 * push_recall clients.
2184 * pCD = pointer to the ClientData
2186 * event = X event that invoked the function (key, button, or menu/NULL)
2191 * RETURN = if True then further button binding/function processing can
2192 * be done for the event that caused this function to be called.
2196 ******************************<->***********************************/
2199 F_Push_Recall (String args, ClientData *pCD, XEvent *event)
2201 WmPushRecallArg *pPRP;
2203 WmFpPushRecallClientData *pPRCD;
2205 pPRP = (WmPushRecallArg *) args;
2206 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2208 if (pPRP->ixReg < pSD->numPushRecallClients)
2210 /* get slot for this client */
2211 pPRCD = &(pSD->pPRCD[pPRP->ixReg]);
2214 * If the client is already running, then top it in this workspace,
2215 * else invoke the function to start it.
2219 /* Client is managed already. */
2220 if (!(ClientInWorkspace (pSD->pActiveWS, pPRCD->pCD)))
2222 WorkspaceID *wsRemoveList;
2226 * Move client to current workspace
2228 wsRemoveList = GetListOfOccupiedWorkspaces (pPRCD->pCD,
2230 RemoveClientFromWorkspaces (pPRCD->pCD, wsRemoveList,
2232 XtFree ((char *)wsRemoveList);
2233 AddClientToWorkspaces (pPRCD->pCD, &(pSD->pActiveWS->id), 1);
2234 SetClientWsIndex(pPRCD->pCD);
2235 SetClientState(pPRCD->pCD,
2236 pPRCD->pCD->clientState & ~UNSEEN_STATE, CurrentTime);
2239 /* Make this client visible */
2241 wmGD.bSuspendSecondaryRestack = True;
2243 F_Normalize_And_Raise (NULL, pPRCD->pCD, event);
2245 wmGD.bSuspendSecondaryRestack = False;
2250 struct timeval tvNow;
2252 Boolean bWaiting = False;
2254 if (pPRCD->tvTimeout.tv_sec != 0)
2256 gettimeofday (&tvNow, &tz);
2258 if ((pPRCD->tvTimeout.tv_sec > tvNow.tv_sec) ||
2259 ((pPRCD->tvTimeout.tv_sec == tvNow.tv_sec) &&
2260 (pPRCD->tvTimeout.tv_usec > tvNow.tv_usec)))
2262 /* still waiting for client to start */
2269 long clientTimeout = 0;
2272 WmPanelistObject pPanelist;
2274 pPanelist = (WmPanelistObject) pSD->wPanelist;
2276 /* invoke the function to start the client */
2277 pPRP->wmFunc ( pPRP->pArgs, pCD, event);
2279 if (pPanelist && panel.busy_light_data)
2281 /* set timeout value */
2284 XmNclientTimeoutInterval, &clientTimeout); ac++;
2285 XtGetValues (panel.busy_light_data->icon, (ArgList)al, ac);
2289 * ClientTimeout is in milliseconds, timeval values
2290 * are in seconds and microseconds.
2292 gettimeofday (&(pPRCD->tvTimeout), &tz);
2294 pPRCD->tvTimeout.tv_sec += clientTimeout / 1000;
2295 pPRCD->tvTimeout.tv_usec +=
2296 (clientTimeout % 1000) * 1000;
2298 pPRCD->tvTimeout.tv_sec += pPRCD->tvTimeout.tv_usec / 1000000;
2299 pPRCD->tvTimeout.tv_usec %= 1000000;
2306 } /* END OF FUNCTION F_Push_Recall */
2309 /*************************************<->*************************************
2311 * F_Pass_Key (args, pCD, event)
2316 * This is a function stub for the f.pass_key window manager function.
2321 * args = (immediate value) window type flags
2323 * pCD = pointer to the client data
2325 * event = X event that invoked the function (key, button, or menu/NULL)
2327 *************************************<->***********************************/
2329 Boolean F_Pass_Key (args, pCD, event)
2335 if (wmGD.passKeysActive)
2338 * Get out of pass keys mode.
2341 wmGD.passKeysActive = False;
2342 wmGD.passKeysKeySpec = NULL;
2347 * Get into pass keys mode.
2350 wmGD.passKeysActive = True;
2355 } /* END OF FUNCTION F_Pass_Key */
2359 /*************************************<->*************************************
2361 * F_Maximize (args, pCD, event)
2366 * This is the window manager function handler for maximizing a client
2369 *************************************<->***********************************/
2371 Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
2373 if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
2375 SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
2376 GetFunctionTimestamp ((XButtonEvent *)event),
2377 GetEventInverseMask(event));
2382 } /* END OF FUNCTION F_Maximize */
2386 /*************************************<->*************************************
2388 * F_Menu (args, pCD, event)
2393 * This is the window manager function handler for posting a menu.
2394 * This function can only be invoked by a key or button event.
2395 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2396 * NULL when the menu is unposted.
2398 *************************************<->***********************************/
2400 Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
2403 Context menuContext;
2404 unsigned int button;
2407 long flags = POST_AT_XY;
2412 ((event->type == ButtonPress) || (event->type == ButtonRelease)))
2414 button = event->xbutton.button;
2415 x = event->xbutton.x_root;
2416 y = event->xbutton.y_root;
2417 if (event->type == ButtonRelease)
2419 flags |= POST_TRAVERSAL_ON;
2423 * Root menu, if posted with button press, then
2424 * set up to handle root menu click to make the menu
2427 else if (wmGD.rootButtonClick && (event->type == ButtonPress))
2429 if (wmGD.bReplayedButton)
2431 /* This button was replayed, it most likely dismissed
2432 a previous sticky menu, don't post a menu here */
2435 wmGD.checkHotspot = True;
2436 wmGD.hotspotRectangle.x = x - wmGD.moveThreshold/2;
2437 wmGD.hotspotRectangle.y = y - wmGD.moveThreshold/2;
2438 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2439 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2444 ((event->type == KeyPress) || (event->type == KeyRelease)))
2447 x = event->xkey.x_root;
2448 y = event->xkey.y_root;
2453 * A button or key event must be used to post a menu using this
2462 if (pCD->clientState == NORMAL_STATE)
2464 menuContext = F_CONTEXT_NORMAL;
2466 else if (pCD->clientState == MAXIMIZED_STATE)
2468 menuContext = F_CONTEXT_MAXIMIZE;
2472 menuContext = F_CONTEXT_ICON;
2474 if (P_ICON_BOX(pCD) &&
2475 event->xany.window == ICON_FRAME_WIN(pCD))
2477 if (pCD->clientState == MINIMIZED_STATE)
2479 menuContext = F_SUBCONTEXT_IB_IICON;
2483 menuContext = F_SUBCONTEXT_IB_WICON;
2489 menuContext = F_CONTEXT_ROOT;
2493 /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
2494 * This should have been done in MakeWmFunctionResources().
2497 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2498 if ((menuSpec = MAKE_MENU (pSD, pCD, args, menuContext,
2499 menuContext, (MenuItem *) NULL, FALSE)) != NULL)
2501 PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
2506 } /* END OF FUNCTION F_Menu */
2509 /*************************************<->*************************************
2511 * F_Minimize (args, pCD, event)
2516 * This is the window manager function handler for minimizing a client
2519 *************************************<->***********************************/
2521 Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
2523 ClientData *pcdLeader;
2529 * If the window is a transient then minimize the entire transient
2530 * tree including the transient leader.
2533 pcdLeader = (pCD->transientLeader) ?
2534 FindTransientTreeLeader (pCD) : pCD;
2535 if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
2537 SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
2538 GetFunctionTimestamp ((XButtonEvent *)event),
2539 GetEventInverseMask(event));
2545 } /* END OF FUNCTION F_Minimize */
2549 /*************************************<->*************************************
2551 * F_Move (args, pCD, event)
2556 * This is the window manager function handler for moving a client window
2559 *************************************<->***********************************/
2561 Boolean F_Move (String args, ClientData *pCD, XEvent *event)
2563 if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
2565 StartClientMove (pCD, event);
2566 HandleClientFrameMove (pCD, event);
2571 } /* END OF FUNCTION F_Move */
2575 /*************************************<->*************************************
2577 * F_Next_Cmap (args, pCD, event)
2582 * This is the window manager function handler installing the next
2583 * colormap in the list of client window colormaps.
2585 *************************************<->***********************************/
2587 Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
2591 pCD = ACTIVE_PSD->colormapFocus;
2594 if (pCD && (pCD->clientCmapCount > 0) &&
2595 ((pCD->clientState == NORMAL_STATE) ||
2596 (pCD->clientState == MAXIMIZED_STATE)))
2598 if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
2600 pCD->clientCmapIndex = 0;
2602 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2603 if (ACTIVE_PSD->colormapFocus == pCD)
2605 #ifndef OLD_COLORMAP /* colormap */
2607 * We just re-ordered the colormaps list,
2608 * so we need to re-run the whole thing.
2610 pCD->clientCmapFlagsInitialized = 0;
2611 ProcessColormapList (ACTIVE_PSD, pCD);
2612 #else /* OSF original */
2613 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2620 } /* END OF FUNCTION F_Next_Cmap */
2624 /*************************************<->*************************************
2626 * F_Nop (args, pCD, event)
2631 * This is the window manager function handler for doing nothing.
2633 *************************************<->***********************************/
2635 Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2640 } /* END OF FUNCTION F_Nop */
2644 /*************************************<->*************************************
2646 * F_Normalize (args, pCD, event)
2651 * This is the window manager function handler for putting a client window
2652 * in the normal state.
2654 *************************************<->***********************************/
2656 Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2661 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2662 GetFunctionTimestamp ((XButtonEvent *)event),
2663 GetEventInverseMask(event));
2668 } /* END OF FUNCTION F_Normalize */
2672 /*************************************<->*************************************
2674 * F_Normalize_And_Raise (args, pCD, event)
2679 * This is the window manager function handler for putting a client window
2680 * in the normal state and raising it from and icon.
2682 *************************************<->***********************************/
2684 Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2687 WmWorkspaceData *pWS;
2692 pSD = PSD_FOR_CLIENT (pCD);
2696 pWS = pSD->pActiveWS;
2698 if (pSD->useIconBox &&
2699 wmGD.useFrontPanel &&
2700 pSD->iconBoxControl &&
2701 (!strcmp(args, WmNiconBox)))
2704 * There's an icon box in the front panel and this is a
2705 * request to pop up the icon box.
2707 IconBoxPopUp (pWS, True);
2714 if (pCD->clientState == MINIMIZED_STATE)
2716 /* normalize window */
2717 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2720 ? GetFunctionTimestamp ((XButtonEvent *)event)
2722 GetEventInverseMask(event));
2726 /* Make sure we are in NORMAL_STATE */
2727 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2728 GetFunctionTimestamp ((XButtonEvent *)event),
2729 GetEventInverseMask(event));
2731 /* Raise the window and set the keyboard focus to the window */
2733 wmGD.bSuspendSecondaryRestack = True;
2735 F_Raise (NULL, pCD, (XEvent *)NULL);
2737 wmGD.bSuspendSecondaryRestack = False;
2739 if (wmGD.raiseKeyFocus)
2741 F_Focus_Key (NULL, pCD,
2744 : ((XEvent *)NULL)));
2747 wmGD.clickData.clickPending = False;
2748 wmGD.clickData.doubleClickPending = False;
2753 } /* END OF FUNCTION F_Normalize_And_Raise */
2757 /*************************************<->*************************************
2759 * F_Restore (args, pCD, event)
2764 * This is the window manager function handler for putting a client window
2765 * in the normal state.
2767 *************************************<->***********************************/
2769 Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2776 * If current state is MAXIMIZED state then just go to NORMAL state,
2777 * otherwise (you are in MINIMIZED state) return to previous state.
2780 if (pCD->clientState == MAXIMIZED_STATE)
2782 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2783 GetFunctionTimestamp ((XButtonEvent *)event),
2784 GetEventInverseMask(event));
2790 newState = MAXIMIZED_STATE;
2794 newState = NORMAL_STATE;
2797 SetClientStateWithEventMask (pCD, newState,
2798 GetFunctionTimestamp ((XButtonEvent *)event),
2799 GetEventInverseMask(event));
2805 } /* END OF FUNCTION F_Restore */
2809 /*************************************<->*************************************
2811 * F_Restore_And_Raise (args, pCD, event)
2816 * This is the window manager function handler for putting a client window
2817 * in the normal state and raising it from and icon.
2819 *************************************<->***********************************/
2821 Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2827 if (pCD->clientState == MINIMIZED_STATE)
2829 /* Restore window */
2832 newState = MAXIMIZED_STATE;
2836 newState = NORMAL_STATE;
2839 SetClientStateWithEventMask (pCD, newState,
2842 ? GetFunctionTimestamp ((XButtonEvent *)event)
2844 GetEventInverseMask(event));
2848 /* Make sure we restore the window first */
2849 F_Restore (NULL, pCD, event);
2851 /* Raise the window and set the keyboard focus to the window */
2853 wmGD.bSuspendSecondaryRestack = True;
2855 F_Raise (NULL, pCD, (XEvent *)NULL);
2857 wmGD.bSuspendSecondaryRestack = False;
2859 if (wmGD.raiseKeyFocus)
2861 F_Focus_Key (NULL, pCD,
2864 : ((XEvent *)NULL)));
2867 wmGD.clickData.clickPending = False;
2868 wmGD.clickData.doubleClickPending = False;
2873 } /* END OF FUNCTION F_Restore_And_Raise */
2877 /*************************************<->*************************************
2879 * F_Pack_Icons (args, pCD, event)
2884 * This is the window manager function handler for packing icons in the
2885 * icon box or on the desktop.
2887 *************************************<->***********************************/
2889 Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2894 if (ACTIVE_PSD->useIconBox)
2896 pIBD = ACTIVE_WS->pIconBox;
2899 while (pCD != pIBD->pCD_iconBox)
2901 if (pIBD->pNextIconBox)
2903 pIBD = pIBD->pNextIconBox;
2914 PackIconBox (pIBD, False, False, 0, 0);
2929 } /* END OF FUNCTION F_Pack_Icons */
2932 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2933 /*************************************<->*************************************
2935 * F_Post_RMenu (args, pCD, event)
2940 * This is the window manager function handler for posting the
2942 * This function can only be invoked by a key event.
2944 *************************************<->***********************************/
2946 Boolean F_Post_RMenu (String args, ClientData *pCD, XEvent *event)
2949 unsigned int button = NoButton;
2951 long flags = POST_AT_XY;
2957 if ((event->type == KeyPress) || (event->type == KeyRelease))
2960 /* Find the root menu spec */
2961 for (rootMenu = ACTIVE_PSD->menuSpecs;
2962 rootMenu != (MenuSpec *) NULL;
2963 rootMenu = rootMenu->nextMenuSpec)
2965 if (strcmp(rootMenu->name, ACTIVE_PSD->rootMenu) == 0)
2969 /* If we couldn't find the root menu, then do nothing. */
2970 if (rootMenu == (MenuSpec *) NULL)
2975 XQueryPointer(DISPLAY, ACTIVE_ROOT,
2976 &rwin, &cwin, &x, &y, &winx, &winy, &mask);
2978 PostMenu (rootMenu, NULL, x, y, NoButton, F_CONTEXT_ROOT,
2985 } /* END OF FUNCTION F_Post_RMenu */
2986 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2989 /*************************************<->*************************************
2991 * F_Post_SMenu (args, pCD, event)
2996 * This is the window manager function handler for posting the system menu
2997 * for the specified client.
2998 * This function can only be invoked by a key or button event.
2999 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
3000 * NULL when the menu is unposted.
3002 *************************************<->***********************************/
3004 Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
3006 Context menuContext;
3010 * An event must be used to post the system menu using this function.
3013 if (event && pCD && pCD->systemMenuSpec)
3016 * Determine whether the keyboard is posting the menu and post
3017 * the menu at an appropriate place.
3020 if (pCD->clientState == NORMAL_STATE)
3022 menuContext = F_CONTEXT_NORMAL;
3024 else if (pCD->clientState == MAXIMIZED_STATE)
3026 menuContext = F_CONTEXT_MAXIMIZE;
3030 menuContext = F_CONTEXT_ICON;
3032 if (P_ICON_BOX(pCD) &&
3033 event->xany.window == ICON_FRAME_WIN(pCD))
3035 if (pCD->clientState == MINIMIZED_STATE)
3037 menuContext = F_SUBCONTEXT_IB_IICON;
3041 menuContext = F_SUBCONTEXT_IB_WICON;
3045 if ((event->type == KeyPress) || (event->type == KeyRelease))
3048 * Set up for "sticky" menu processing if specified.
3051 if (pCD->clientState == MINIMIZED_STATE ||
3052 menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
3056 wmGD.checkHotspot = True;
3059 else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
3061 wmGD.checkHotspot = True;
3064 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
3067 else if (event->type == ButtonPress)
3071 * Root menu, if posted with button press, then
3072 * set up to handle root menu click to make the menu
3075 if (wmGD.rootButtonClick && (!wmGD.checkHotspot))
3077 wmGD.checkHotspot = True;
3078 wmGD.hotspotRectangle.x =
3079 event->xbutton.x_root - wmGD.moveThreshold/2;
3080 wmGD.hotspotRectangle.y =
3081 event->xbutton.y_root - wmGD.moveThreshold/2;
3082 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
3083 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
3086 PostMenu (pCD->systemMenuSpec, pCD,
3087 event->xbutton.x_root, event->xbutton.y_root,
3088 event->xbutton.button, menuContext, POST_AT_XY, event);
3090 else if (event->type == ButtonRelease)
3092 PostMenu (pCD->systemMenuSpec, pCD,
3093 event->xbutton.x_root, event->xbutton.y_root,
3094 event->xbutton.button, menuContext,
3095 POST_AT_XY | POST_TRAVERSAL_ON, event);
3101 } /* END OF FUNCTION F_PostSMenu */
3105 /*************************************<->*************************************
3107 * F_Kill (args, pCD, event)
3112 * This is the window manager function handler for terminating a client.
3113 * Essentially the client connection is shut down.
3115 *************************************<->***********************************/
3117 Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
3119 if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
3121 Boolean do_delete_window =
3122 pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
3123 Boolean do_save_yourself =
3124 pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
3126 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3131 * Get the widget for the subpanel
3132 * (Should be only child of the shell!)
3134 wPanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
3137 SlideSubpanelBackIn (pCD, wPanel);
3141 if (pCD->clientFlags & ICON_BOX)
3144 * When the front panel is used with the icon box,
3145 * "Close" hides the icon box into the front panel.
3147 if ((wmGD.useFrontPanel) &&
3148 (pCD->pSD->iconBoxControl) &&
3149 (IconBoxShowing(pCD->pSD->pActiveWS)))
3151 IconBoxPopUp (pCD->pSD->pActiveWS, False);
3154 else if (!do_delete_window && !do_save_yourself)
3156 XKillClient (DISPLAY, pCD->client);
3160 if (do_delete_window)
3163 * The client wants to be notified, not killed.
3166 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3167 (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
3171 * HP does not want to send a client message for both
3172 * delete_window AND save_yourself. The current OSF
3173 * patch did just that. This "else if" returns dtwm
3174 * to the behavior of dt 2.01
3176 else if (do_save_yourself)
3178 if (do_save_yourself)
3182 * Send a WM_SAVE_YOURSELF message and wait for a change to
3183 * the WM_COMMAND property.
3184 * !!! button and key input should be kept from the window !!!
3187 if (AddWmTimer (TIMER_QUIT,
3188 (unsigned long) wmGD.quitTimeout, pCD))
3190 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3191 (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
3193 pCD->clientFlags |= CLIENT_TERMINATING;
3197 XKillClient (DISPLAY, pCD->client);
3205 } /* END OF FUNCTION F_Kill */
3209 /*************************************<->*************************************
3211 * F_Marquee_Selection (args, pCD, event)
3216 * This is the window manager function handler for selecting
3217 * non-window manager objects on the root window.
3219 *************************************<->***********************************/
3221 Boolean F_Marquee_Selection (String args, ClientData *pCD, XEvent *event)
3226 * This function only valid in root context
3228 StartMarqueeSelect (ACTIVE_PSD, event);
3229 HandleMarqueeSelect (ACTIVE_PSD, event);
3234 } /* END OF FUNCTION F_Marquee_Selection */
3236 /*************************************<->*************************************
3238 * RefreshByClearing (win)
3243 * Recursively refresh this window and its children by doing
3246 *************************************<->***********************************/
3248 RefreshByClearing (Window win)
3252 Window root, parent;
3253 unsigned int nchildren;
3254 Window *winChildren;
3256 /* clear this window */
3257 XClearArea(DISPLAY, win, 0, 0, 0, 0, True);
3259 /* find any children and clear them, too */
3260 status = XQueryTree(DISPLAY, win, &root, &parent, &winChildren,
3264 /* recurse for each child window */
3265 for (i=0; i<nchildren; ++i)
3267 RefreshByClearing(winChildren[i]);
3272 XFree((char *)winChildren);
3278 /*************************************<->*************************************
3280 * F_Refresh (args, pCD, event)
3285 * This is the window manager function handler for causing all windows
3286 * in the workspace to be redrawn.
3288 *************************************<->***********************************/
3290 Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
3295 if (wmGD.refreshByClearing)
3297 RefreshByClearing (ACTIVE_ROOT);
3302 /* default background_pixmap is None */
3303 win = XCreateWindow (DISPLAY,
3305 (unsigned int) DisplayWidth (DISPLAY,
3307 (unsigned int) DisplayHeight (DISPLAY,
3314 (XSetWindowAttributes *)NULL);
3316 XMapWindow (DISPLAY, win);
3317 XDestroyWindow (DISPLAY, win);
3325 } /* END OF FUNCTION F_Refresh */
3329 /*************************************<->*************************************
3331 * F_Resize (args, pCD, event)
3336 * This is the window manager function handler for resizing a client window.
3338 *************************************<->***********************************/
3340 Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
3342 if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
3343 ((pCD->clientState == NORMAL_STATE) ||
3344 (pCD->clientState == MAXIMIZED_STATE)))
3346 StartClientResize (pCD, event);
3347 HandleClientFrameResize (pCD, event);
3352 } /* END OF FUNCTION F_Resize */
3356 /*************************************<->*************************************
3358 * F_Restart (args, pCD, event)
3363 * This is the window manager function handler for restarting the window
3366 *************************************<->***********************************/
3368 Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
3371 if (args && *args && !strcmp (args, DTWM_REQP_NO_CONFIRM))
3373 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3377 if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
3379 ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
3383 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3387 } /* END OF FUNCTION F_Restart */
3391 /*************************************<->*************************************
3393 * Do_Restart (dummy)
3398 * Callback function for restarting the window manager.
3400 *************************************<->***********************************/
3402 void Do_Restart (Boolean dummy)
3404 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3406 } /* END OF FUNCTION Do_Restart */
3410 /*************************************<->*************************************
3412 * RestartWm (startupFlags)
3417 * Actually restarts the window manager.
3422 * startupFlags = flags to be put into the Wm_INFO property for restart.
3424 *************************************<->***********************************/
3426 void RestartWm (long startupFlags)
3428 ClientListEntry *pNextEntry;
3432 for (scr=0; scr<wmGD.numScreens; scr++)
3434 if(wmGD.Screens[scr].managed)
3438 * Set up the _MOTIF_WM_INFO property on the root window
3439 * to indicate a restart.
3442 SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
3444 SaveResources(&wmGD.Screens[scr]);
3447 * Unmap client windows and reparent them to the root window.
3450 pNextEntry = wmGD.Screens[scr].lastClient;
3453 if (pNextEntry->type == NORMAL_STATE)
3455 if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
3457 if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
3459 XUnmapWindow (DISPLAY,
3460 pNextEntry->pCD->clientFrameWin);
3465 DeFrameClient (pNextEntry->pCD);
3468 pNextEntry = pNextEntry->prevSibling;
3470 UnParentControls (&wmGD.Screens[scr], True);
3476 /* shut down the messaging connection */
3482 * This fixes restart problem when going from explicit focus to
3483 * pointer focus. Window under pointer was not getting focus indication
3484 * until pointer was moved to new window, or out of and into the
3488 XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
3489 XSync (DISPLAY, False);
3492 CLOSE_FILES_ON_EXEC();
3493 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3496 * Restart the window manager with the initial arguments plus
3497 * the restart settings.
3500 execvp (*(wmGD.argv), wmGD.argv);
3503 Warning (((char *)GETMESSAGE(26, 1,
3504 "The window manager restart failed. The window manager program could not \
3505 be found or could not be executed.")));
3507 Warning ("Cannot restart the window manager");
3513 } /* END OF FUNCTION RestartWm */
3516 /*************************************<->*************************************
3518 * DeFrameClient (pCD)
3523 * Unmaps a client window (and client icon window) and reparents the
3524 * window back to the root.
3529 * pCD = pointer to the client data for the window to be de-framed.
3531 *************************************<->***********************************/
3533 void DeFrameClient (ClientData *pCD)
3537 XWindowChanges windowChanges;
3541 if (pCD->clientState != MINIMIZED_STATE)
3543 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
3546 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
3548 XUnmapWindow (DISPLAY, pCD->iconWindow);
3549 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
3551 XReparentWindow (DISPLAY, pCD->iconWindow,
3552 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
3553 pCD->pWsList->iconY);
3555 XReparentWindow (DISPLAY, pCD->iconWindow,
3556 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
3567 if(wmGD.positionIsFrame)
3569 CalculateGravityOffset (pCD, &xoff, &yoff);
3570 x = pCD->clientX - xoff;
3571 y = pCD->clientY - yoff;
3580 #ifndef UNMAP_ON_RESTART
3581 if (pCD->clientState == MINIMIZED_STATE)
3583 XUnmapWindow (DISPLAY, pCD->client);
3586 XUnmapWindow (DISPLAY, pCD->client);
3588 XRemoveFromSaveSet (DISPLAY, pCD->client);
3589 XReparentWindow (DISPLAY, pCD->client,
3590 ROOT_FOR_CLIENT(pCD), x, y);
3592 if (pCD->transientChildren)
3594 DeFrameClient (pCD->transientChildren);
3600 windowChanges.x = x;
3601 windowChanges.y = y;
3602 windowChanges.border_width = pCD->xBorderWidth;
3603 XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
3606 if (pCD->transientLeader)
3608 pCD = pCD->transientSiblings;
3616 } /* END OF FUNCTION DeFrameClient */
3618 /******************************<->*************************************
3620 * F_Toggle_Front_Panel (args, pCD, event)
3625 * This is the window manager function handler for toggling the
3626 * front panel off and on.
3627 ******************************<->***********************************/
3630 F_Toggle_Front_Panel (String args, ClientData *pCD, XEvent *event)
3633 WmPanelistObject pPanelist;
3637 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3641 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3647 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3648 wmGD.windowContextType, (caddr_t *)&pCD);
3654 if (pCD->clientState & MINIMIZED_STATE)
3656 SetClientState (pCD, NORMAL_STATE,
3657 GetFunctionTimestamp ((XButtonEvent *)event));
3661 SetClientState (pCD, MINIMIZED_STATE,
3662 GetFunctionTimestamp ((XButtonEvent *)event));
3667 } /* END OF FUNCTION F_Toggle_Front_Panel */
3670 /******************************<->*************************************
3672 * Boolean F_Version (String args, ClientData *pCD, XEvent *event)
3676 * Invoke the help on version dialogue.
3680 * args - incoming values
3681 * pCD - associated client data structure
3682 * event - what triggered this call
3686 * Return - True if the call occurs; false otherwise.
3691 ******************************<->***********************************/
3693 F_Version (String args, ClientData *pCD, XEvent *event)
3696 WmPanelistObject pPanelist;
3700 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3704 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3709 WmDtHelpOnVersion (O_Shell (pPanelist));
3714 } /* END OF FUNCTION F_Version */
3717 /******************************<->*************************************
3719 * F_Send_Msg (args, pCD, event)
3724 * This is the window manager function handler for sending a client
3725 * message event to a client window.
3730 * args = (immediate value) message id
3732 * pCD = pointer to the client data
3734 * event = X event that invoked the function (key, button, or menu/NULL)
3737 ******************************<->***********************************/
3739 Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
3744 if (pCD && pCD->mwmMessagesCount)
3747 * A message id must be made "active" by being included in the
3748 * _MWM_MESSAGES property before the associated message can be sent.
3751 for (i = 0; i < pCD->mwmMessagesCount; i++)
3753 if (pCD->mwmMessages[i] == (long)args)
3755 SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES,
3756 (long)args, CurrentTime, NULL, 0);
3764 } /* END OF FUNCTION F_Send_Msg */
3768 /*************************************<->*************************************
3770 * F_Separator (args, pCD, event)
3775 * This is a placeholder function; it should never be called.
3777 *************************************<->***********************************/
3779 Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
3784 } /* END OF FUNCTION F_Separator */
3787 Boolean ForceRaiseWindow (ClientData *pcd)
3791 WmScreenData *pSD = (ACTIVE_WS)->pSD;
3793 XWindowChanges changes;
3794 Boolean restack = False;
3797 if (pSD->clientList->type == MINIMIZED_STATE)
3799 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
3803 stackWindow = pSD->clientList->pCD->clientFrameWin;
3808 * Windows did not raise on regular f.raise because the raise was
3809 * not relative to another window (methinks).
3811 changes.stack_mode = Above;
3812 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
3820 /*************************************<->*************************************
3822 * F_Raise (args, pCD, event)
3827 * This is the window manager function handler for topping the client window
3828 * so that it is unobscured.
3830 *************************************<->***********************************/
3832 Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
3834 ClientListEntry *pEntry;
3835 ClientListEntry *pNextEntry;
3836 ClientListEntry *pStackEntry;
3837 String string = args;
3838 int flags = STACK_NORMAL;
3840 WmWorkspaceData *pWS = ACTIVE_WS;
3845 /* process '-client' argument */
3846 if (string[0] == '-')
3848 string = &string[1];
3849 string = (String) GetString ((unsigned char **) &string);
3852 pNextEntry = ACTIVE_PSD->clientList;
3853 while (pNextEntry &&
3854 (pEntry = FindClientNameMatch (pNextEntry, True, string,
3857 pNextEntry = pEntry->nextSibling;
3859 if (ClientInWorkspace (pWS, pEntry->pCD))
3862 Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3863 pStackEntry = pEntry;
3869 /* process family stacking stuff */
3872 unsigned int slen, len, index;
3874 slen = strlen(args) - 2; /* subtract '\n' and NULL */
3875 for (index = 0; index < slen; string = &args[index+1])
3877 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3879 len = strlen(string);
3880 if (!strcmp(string,"within"))
3882 flags |= STACK_WITHIN_FAMILY;
3884 else if (!strcmp(string,"freeFamily"))
3886 flags |= STACK_FREE_FAMILY;
3891 if (ClientInWorkspace (pWS, pCD))
3894 Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3903 if (ClientInWorkspace (pWS, pCD))
3906 Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3914 } /* END OF FUNCTION F_Raise */
3918 /*************************************<->*************************************
3920 * Do_Raise (pCD, pStackEntry)
3925 * This is the window manager function handler for topping the client window
3926 * so that it is unobscured.
3931 * pCD = pointer to the client data of the window (or icon) to be raised.
3933 * pStackEntry = pointer to client list entry for window that is to be
3934 * above the raised window (if NULL window is raised to the top of the
3937 *************************************<->***********************************/
3939 void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3941 Boolean restackTransients;
3942 ClientData *pcdLeader;
3943 WmWorkspaceData *pWS = ACTIVE_WS;
3945 Boolean bLeaderRestacked;
3951 * Window has been reparented into the front panel.
3952 * Don't follow through on window stacking change.
3958 if (ClientInWorkspace(pWS, pCD) &&
3959 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
3962 * Both clients are in the current workspace. Set
3963 * client indices so that the access macros work.
3965 SetClientWsIndex (pCD);
3968 SetClientWsIndex (pStackEntry->pCD);
3974 * One or both of the clients are not in the current workspace
3981 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
3983 if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
3986 * Don't raise the window above the system modal window.
3989 else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
3990 !P_ICON_BOX(pcdLeader))
3993 * If a dirtyStackEntry exists, return it to its original place
3994 * in the stack (for all stacking types)
3996 if (dirtyStackEntry)
3998 if (dirtyStackEntry->transientChildren ||
3999 dirtyStackEntry->transientLeader)
4000 RestackTransients (dirtyStackEntry);
4001 dirtyStackEntry = NULL;
4006 * Only restack the icon if it is not currently raised.
4011 if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
4013 StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
4015 MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
4021 if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
4023 StackWindow (pWS, &pcdLeader->iconEntry,
4024 True /*on top*/, (ClientListEntry *) NULL);
4025 MoveEntryInList (pWS, &pcdLeader->iconEntry,
4026 True /*on top*/, (ClientListEntry *) NULL);
4030 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
4034 * Handle restacking of primary/secondary windows
4035 * within the transient window tree. Don't raise this
4036 * window above any modal transients.
4038 bLeaderRestacked = False;
4039 if ((pcdLeader->transientChildren) &&
4040 (!pCD->secondariesOnTop) &&
4041 (!wmGD.bSuspendSecondaryRestack) &&
4042 (!IS_APP_MODALIZED(pCD)))
4044 if (pCD != pcdLeader)
4047 * This is not the transient leader, make sure
4048 * the transient leader isn't on top.
4049 * (Brute force solution)
4051 bLeaderRestacked = NormalizeTransientTreeStacking (pcdLeader);
4053 if (pCD->transientChildren)
4056 * This isn't the overall leader of the transient
4057 * tree, but it does have transient's of its own.
4058 * Move it to the top of its own transient sub-tree.
4060 bLeaderRestacked |= BumpPrimaryToTop (pCD);
4066 * This is the transient leader, move it to the
4069 bLeaderRestacked = BumpPrimaryToTop (pcdLeader);
4075 * If this is a transient window then put it on top of its
4076 * sibling transient windows.
4079 restackTransients = False;
4083 * Fix for 5325 - The following code has been reorganized to cause the
4084 * action of F_Raise to match the current documentation.
4085 * The new algorithm is as follows:
4087 * if (dirtyStackEntry)
4088 * restore dirty tree
4089 * if (not withinFamily)
4090 * bring window group to the top of global stack
4092 * raise the requested window to top of family
4094 * raise requested window to top of siblings
4095 * if (need to restack windows)
4100 * If a dirtyStackEntry exists, return it to its original place
4101 * in the stack (for all stacking types)
4103 if (dirtyStackEntry)
4106 * Check to make sure that the dirty pCD has either transient
4107 * children or a transient leader. If not, do not restore
4110 if (dirtyStackEntry->transientChildren ||
4111 dirtyStackEntry->transientLeader)
4112 RestackTransients (dirtyStackEntry);
4113 dirtyStackEntry = NULL;
4118 * If the flags do not indicate "within", raise the window family
4119 * to the top of the window stack. If the window is the primary,
4120 * raise it to the top regardless of the flags.
4122 if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
4126 if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
4128 StackWindow (pWS, &pcdLeader->clientEntry,
4129 False /*below*/, pStackEntry);
4130 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4131 False /*below*/, pStackEntry);
4136 if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
4138 StackWindow (pWS, &pcdLeader->clientEntry,
4139 True /*on top*/, (ClientListEntry *) NULL);
4140 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4141 True /*on top*/, (ClientListEntry *) NULL);
4147 * If freeFamily stacking is requested, check to make sure that
4148 * the window has either a transientChild or Leader. This will
4149 * guarantee that windows that form their own family are not
4150 * labelled as dirty (what's to dirty it up?). If it has either,
4151 * raise the window to the top of the family stack.
4153 if ((flags & STACK_FREE_FAMILY) &&
4154 (pCD->transientLeader || pCD->transientChildren))
4156 dirtyStackEntry = pCD;
4157 dirtyLeader = pcdLeader;
4159 restackTransients = ForceRaiseWindow (pCD);
4163 * If withinFamily stacking is requested, put the current transient
4164 * on top of its sibling transient windows.
4168 restackTransients = PutTransientOnTop (pCD);
4171 /* At this point, if doing a regular f.raise the window family has
4172 * already been brought to the top of the stack, so nothing further
4173 * needs to be done for it.
4176 /* Restack the transients if needed */
4179 if ((restackTransients) || (bLeaderRestacked))
4181 if (restackTransients)
4184 RestackTransients (pCD);
4188 } /* END OF FUNCTION Do_Raise */
4192 /*************************************<->*************************************
4194 * F_Raise_Lower (args, pCD, event)
4199 * This window manager function tops an obscured window or icon and bottoms
4200 * a window or icon that is on top of the window stack.
4202 *************************************<->***********************************/
4204 Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
4206 ClientData *pcdLeader;
4210 pcdLeader = (pCD->transientLeader) ?
4211 FindTransientTreeLeader (pCD) : pCD;
4214 * Treat a raise/lower on a window in a transient tree as if it is
4215 * a raise/lower for the whole tree.
4218 if (CheckIfClientObscuredByAny (pcdLeader))
4221 * The window is obscured by another window, raise the window.
4225 F_Raise (NULL, pCD, (XEvent *)NULL);
4227 F_Raise (NULL, pcdLeader, (XEvent *)NULL);
4230 else if (CheckIfClientObscuringAny (pcdLeader) &&
4231 !(wmGD.systemModalActive &&
4232 (pcdLeader == wmGD.systemModalClient)))
4235 * The window is obscuring another window and is
4236 * not system modal, lower the window.
4239 F_Lower (NULL, pcdLeader, (XEvent *)NULL);
4241 if ((pcdLeader->secondariesOnTop == False) &&
4242 (pCD->transientLeader != NULL) &&
4243 (!IS_APP_MODALIZED(pcdLeader)))
4245 /* Push transient below primary */
4246 (void) BumpPrimaryToTop (pcdLeader);
4247 RestackTransients (pcdLeader);
4252 else if ((pcdLeader->secondariesOnTop == False) &&
4253 (pcdLeader->transientChildren != NULL) &&
4254 (!wmGD.systemModalActive) &&
4255 (!IS_APP_MODALIZED(pcdLeader)))
4257 if (LeaderOnTop(pcdLeader))
4259 /* Push primary below transient */
4260 (void) BumpPrimaryToBottom (pcdLeader);
4261 RestackTransients (pcdLeader);
4265 F_Raise (NULL, pCD, (XEvent *)NULL);
4266 /* Push transient below primary */
4267 (void) BumpPrimaryToTop (pcdLeader);
4268 RestackTransients (pcdLeader);
4276 } /* END OF FUNCTION F_Raise_Lower */
4280 /*************************************<->*************************************
4282 * F_Refresh_Win (args, pCD, event)
4287 * This is the window manager function handler for causing a client window
4288 * to redisplay itself.
4290 *************************************<->***********************************/
4292 Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
4297 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
4298 (pCD->clientState == MAXIMIZED_STATE)))
4300 if (pCD->clientState == NORMAL_STATE)
4302 w = (unsigned int) pCD->clientWidth;
4303 h = (unsigned int) pCD->clientHeight;
4307 w = (unsigned int) pCD->maxWidth;
4308 h = (unsigned int) pCD->maxHeight;
4312 if (wmGD.refreshByClearing)
4314 RefreshByClearing (pCD->clientFrameWin);
4319 /* default background_pixmap is None */
4320 win = XCreateWindow (DISPLAY,
4330 (XSetWindowAttributes *)NULL);
4332 XMapWindow (DISPLAY, win);
4333 XDestroyWindow (DISPLAY, win);
4342 } /* END OF FUNCTION F_Refresh_Win */
4346 /*************************************<->*************************************
4348 * F_Set_Behavior (args, pCD, event)
4353 * This function is used to switch the window manager configuration between
4354 * the built-in configuration (for CXI behavior) and the user's custom
4357 *************************************<->***********************************/
4359 Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
4362 * Go system modal in starting to do the set behavior.
4365 /* !!! grab the server and the pointer !!! */
4369 * Confirm that a set_behavior should be done.
4370 * Execute restart if so.
4373 if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
4375 ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
4376 CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
4380 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4381 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4385 } /* END OF FUNCTION F_Set_Behavior */
4389 /*************************************<->*************************************
4391 * Do_Set_Behavior (dummy)
4396 * Callback to do the f.set_behavior function.
4398 *************************************<->***********************************/
4400 void Do_Set_Behavior (Boolean dummy)
4402 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4403 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4405 } /* END OF FUNCTION Do_Set_Behavior */
4409 /*************************************<->*************************************
4411 * F_Set_Context (args, pCD, event)
4416 * This function is used to set a client context for subsequent
4419 *************************************<->***********************************/
4421 Boolean F_Set_Context (String args, ClientData *pCD, XEvent *event)
4424 wmGD.requestContextWin = (Window) args;
4427 } /* END OF FUNCTION F_Set_Context */
4431 /*************************************<->*************************************
4433 * F_Title (args, pCD, event)
4438 * This is a placeholder function; it should never be called.
4440 *************************************<->***********************************/
4442 Boolean F_Title (String args, ClientData *pCD, XEvent *event)
4447 } /* END OF FUNCTION F_Title */
4451 /******************************<->*************************************
4453 * F_Screen (args, pCD, event)
4458 * This is the window manager function handler for warping to screens
4463 * args = (immediate value) window type flags
4465 * pCD = pointer to the client data
4467 * event = X event that invoked the function (key, button, or menu/NULL)
4469 * NOTE: May want to consider tracking changes in screen because in
4470 * managing a new window (ie. in ManageWindow()).
4474 * RETURN = if True then further button binding/function processing can
4475 * be done for the event that caused this function to be called.
4477 *************************************<->***********************************/
4479 Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
4483 unsigned int dummask;
4484 WmScreenData *newscr = NULL;
4486 static int PreviousScreen = -1;
4490 if (PreviousScreen == -1)
4492 PreviousScreen = DefaultScreen(DISPLAY);
4495 if (strcmp (args, "next") == 0)
4497 scr = ACTIVE_PSD->screen + 1;
4500 else if (strcmp (args, "prev") == 0)
4502 scr = ACTIVE_PSD->screen - 1;
4505 else if (strcmp (args, "back") == 0)
4507 scr = PreviousScreen;
4519 scr = wmGD.numScreens - 1;
4520 else if (scr >= wmGD.numScreens)
4523 newscr = &(wmGD.Screens[scr]);
4524 if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
4525 if (inc) { /* walk around the list */
4530 "Unable to warp to unmanaged screen %d\n", scr);
4537 if (ACTIVE_PSD->screen == scr) return (False); /* already on that screen */
4539 PreviousScreen = ACTIVE_PSD->screen;
4540 XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
4541 &dumint, &dumint, &dummask);
4543 XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
4545 if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
4548 * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can
4549 * uses the new screen instead of the old screen. Then call
4550 * Do_Focus_Key with a NULL pCD to find a reasonable client to
4553 SetActiveScreen (newscr);
4554 Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
4563 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
4564 /*************************************<->*************************************
4566 * F_InvokeCommand (args, pCD, event)
4571 * This is the window manager function for invoking client inserted menu
4574 *************************************<->***********************************/
4576 Boolean F_InvokeCommand (String args, ClientData *pCD, XEvent *event)
4578 CARD32 commandID, clientWindow;
4579 Atom notifySelection;
4581 if (args == (String) NULL) return(FALSE);
4583 if (sscanf(args, "%d %d %ld", &commandID, &clientWindow,
4584 ¬ifySelection) != 3)
4587 SendInvokeMessage(commandID,
4588 (pCD == (ClientData *) NULL ? 0 : pCD->client),
4593 } /* END OF FUNCTION F_InvokeCommand */
4594 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
4597 /*************************************<->*************************************
4599 * GetFunctionTimestamp (pEvent)
4604 * This function is used to extract a timestamp from a key or button event.
4605 * If the event passed in is not a key or button event then a timestamp
4611 * event = pointer to an X event
4616 * RETURN = a timestamp
4618 *************************************<->***********************************/
4620 Time GetFunctionTimestamp (XButtonEvent *pEvent)
4625 (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
4626 ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
4628 time = pEvent->time;
4632 time = GetTimestamp ();
4637 } /* END OF FUNCTION GetFunctionTimestamp */
4641 ** name the event mask we need for a grab in order to find the matching
4642 ** event for an event; right now handle only button-presses
4644 static unsigned int GetEventInverseMask(XEvent *event)
4646 if ((XEvent*)NULL == event)
4648 if (ButtonPress == event->type)
4649 return ButtonReleaseMask; /* detail ? */
4651 expansion further here
4659 /*************************************<->*************************************
4661 * ClearDirtyStackEntry (pCD)
4666 * This function is used to clear the static dirtyStackEntry structure and
4667 * the dirtyLeader static variable when a pCD is destroyed. This
4668 * guarantees that freed memory will not be accessed.
4673 * pCD = pointer to clientData being freed
4680 *************************************<->***********************************/
4682 void ClearDirtyStackEntry (ClientData *pCD)
4684 if (pCD == dirtyStackEntry)
4686 dirtyStackEntry = NULL;
4690 #if defined(DEBUG) && defined(WSM)
4692 /***********************<->*************************************
4694 * F_ZZ_Debug (args, pCD, event)
4699 * This is the window manager debug (multi) function
4706 * pCD = pointer to the ClientData for the whole front panel
4708 * event = X event that invoked the function (key, button, or menu/NULL)
4713 * RETURN = if True then further button binding/function processing can
4714 * be done for the event that caused this function to be called.
4718 * Argument 1 determines the debug function to execute:
4722 * "color_server_info" - dump out color server info
4724 ******************************<->***********************************/
4727 F_ZZ_Debug (String subFcn, ClientData *pCD, XEvent *event)
4729 /* Only do something is sub function is specified */
4733 if (!(strcmp(subFcn, "dump_resources")))
4738 for (scr=0; scr<wmGD.numScreens; scr++)
4740 sprintf (szRes, "/tmp/dtwm.resources.%d", scr);
4742 XrmPutFileDatabase(XtScreenDatabase(
4743 XScreenOfDisplay(DISPLAY, scr)),
4754 /*************************************<->*************************************
4756 * F_Next_Workspace (args, pCD, event)
4761 * This function switches to the next workspace in the list
4763 *************************************<->***********************************/
4765 Boolean F_Next_Workspace (String args, ClientData *pCD, XEvent *event)
4767 WmScreenData *pSD = ACTIVE_PSD;
4770 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4772 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4779 /* check bounds and wrap */
4780 if (iwsx >= pSD->numWorkspaces)
4783 ChangeToWorkspace (&pSD->pWS[iwsx]);
4788 } /* END OF FUNCTION F_Next_Workspace */
4791 /*************************************<->*************************************
4793 * F_Prev_Workspace (args, pCD, event)
4798 * This function switches to the previous workspace in the list
4800 *************************************<->***********************************/
4802 Boolean F_Prev_Workspace (String args, ClientData *pCD, XEvent *event)
4804 WmScreenData *pSD = ACTIVE_PSD;
4807 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4809 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4816 /* check bounds and wrap */
4818 iwsx = pSD->numWorkspaces - 1;
4820 ChangeToWorkspace (&pSD->pWS[iwsx]);
4825 } /* END OF FUNCTION F_Prev_Workspace */
4829 /*************************************<->*************************************
4831 * F_Workspace_Presence (args, pCD, event)
4836 * This function pops up the workspace presence dialog box
4838 *************************************<->***********************************/
4840 Boolean F_Workspace_Presence (String args, ClientData *pCD, XEvent *event)
4842 Context wsContext = (Context)NULL;
4844 if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4846 if (pCD->clientState == NORMAL_STATE)
4848 wsContext = F_CONTEXT_NORMAL;
4850 else if (pCD->clientState == MAXIMIZED_STATE)
4852 wsContext = F_CONTEXT_MAXIMIZE;
4856 wsContext = F_CONTEXT_ICON;
4857 /* return (False); */
4859 ShowPresenceBox (pCD, wsContext);
4863 } /* END OF FUNCTION F_Workspace_Presence */
4869 WmScreenData *pSD = (ACTIVE_WS)->pSD;
4870 ClientListEntry *pCLE;
4872 fprintf (stdout, "Window stacking (bottom to top)\n");
4873 pCLE = pSD->lastClient;
4876 if (ClientInWorkspace (ACTIVE_WS, pCLE->pCD))
4877 fprintf (stdout, "* ");
4879 fprintf (stdout, " ");
4881 fprintf (stdout, "%08lx\t%s\n",
4883 pCLE->pCD->clientName);
4885 pCLE = pCLE->prevSibling;