2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
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>
61 #include <Dt/DtStrDefs.h>
68 * include extern functions
70 #include "WmFunction.h"
76 #include "WmColormap.h"
79 #include "WmFeedback.h"
84 #include "WmIconBox.h"
85 #include "WmKeyFocus.h"
88 #include "WmPresence.h"
90 #include "WmProperty.h"
91 #include "WmProtocol.h"
92 #include "WmResParse.h"
93 #include "WmWinConf.h"
94 #include "WmWinInfo.h"
95 #include "WmWinList.h"
96 #include "WmWinState.h"
99 #include <Xm/RowColumnP.h> /* for MS_LastManagedMenuTime */
100 extern XmMenuState _XmGetMenuState();
102 extern int putenv ();
103 extern char * getenv ();
105 extern pid_t vfork();
106 #endif /* PORT_NOVFORK */
108 static unsigned int GetEventInverseMask(XEvent *event);
112 #if (defined(USL) || defined(__uxp__) || defined(linux) || defined(CSRG_BASED)) && !defined(_NFILE)
113 #define _NFILE FOPEN_MAX
115 #define CLOSE_FILES_ON_EXEC() \
116 {int ifx; for (ifx=3; ifx < _NFILE; ifx++) (void) fcntl (ifx, F_SETFD, 1);}
124 * The 'dirty' variables are used to keep track of the transient window
125 * that has been lowered via "f.lower freeFamily".
127 static ClientData *dirtyStackEntry = NULL;
128 static ClientData *dirtyLeader = NULL;
132 /***********************<->*************************************
134 * F_Action (args, pCD, event)
139 * This is the window manager function handler for invoking actions.
144 * args = action function and arguments
146 * pCD = pointer to the ClientData for the whole front panel
148 * event = X event that invoked the function (key, button, or menu/NULL)
153 * RETURN = if True then further button binding/function processing can
154 * be done for the event that caused this function to be called.
158 * The pCD->controlWindow is a temporary area used solely for
159 * this function invocation--it stores the pCW of the control
160 * that want the function to happen.
161 ******************************<->***********************************/
164 F_Action (String actionName, ClientData *pCD, XEvent *event)
167 WmActionArg *pAP = (WmActionArg *) actionName;
169 /* make sure the command runs on the right display. */
170 if (wmGD.pActiveSD->displayString)
172 putenv(wmGD.pActiveSD->displayString);
177 WmFrontPanelSetBusy (True);
181 DtActionInvoke (wmGD.pActiveSD->screenTopLevelW1,
182 pAP->actionName, pAP->aap, pAP->numArgs,
183 pAP->szExecParms, NULL, NULL, 1, NULL, NULL);
186 * Restore original DISPLAY environment variable
188 if(wmGD.pActiveSD->displayString && wmGD.displayString)
190 putenv(wmGD.displayString);
195 } /* END OF FUNCTION F_Action */
199 /******************************<->*************************************
201 * F_Beep (args, pCD, event)
206 * This is the window manager function handler for beeping.
211 * args = function arguments (specified in .mwmrc file)
213 * pCD = pointer to the client data for the client window to which the
214 * function is to be applied
216 * event = X event that invoked the function (key, button, or menu/NULL)
221 * RETURN = if True then further button binding/function processing can
222 * be done for the event that caused this function to be called.
224 ******************************<->***********************************/
226 Boolean F_Beep (String args, ClientData *pCD, XEvent *event)
229 /* !!! what is a good value for percent (the second arg) !!! */
234 } /* END OF FUNCTION F_Beep */
239 * Handle Special case where the dirty window is the top most
240 * transient window. When this is the case, raising the window
241 * that was on top (the window just below the dirty window) will
242 * fail because Mwm stack database is out of sync. So the solution
243 * is to restack the dirty transient relative to the second to the
244 * top transient. This function is used to support freeFamily stacking.
246 ClientData * FindSecondToTopTransient (pcd)
250 static ClientData *second;
252 pcdNext = pcd->transientChildren;
255 if (pcdNext->transientChildren)
257 if (!pcdNext->transientChildren->transientChildren)
261 FindSecondToTopTransient (pcdNext);
263 pcdNext = pcdNext->transientSiblings;
264 if (pcdNext && !pcdNext->transientSiblings)
272 } /* END OF FUNCTION */
276 Boolean ForceLowerWindow (ClientData *pcd)
280 WmScreenData *pSD = (ACTIVE_WS)->pSD;
282 XWindowChanges changes;
283 Boolean restack = False;
286 WmScreenData *pSD = (ACTIVE_WS)->pSD;
288 ClientListEntry *pCLE;
291 * Find lowest window in this workspace. We'll stack this transient
294 pCLE = pSD->lastClient;
299 if ((pCLE->pCD != pcd) &&
300 (ClientInWorkspace (ACTIVE_WS, pCLE->pCD)))
302 if ((pCLE->type == MINIMIZED_STATE) &&
303 (pCLE->pCD->clientState == MINIMIZED_STATE))
305 stackWindow = ICON_FRAME_WIN(pCLE->pCD);
307 else if ((pCLE->type == NORMAL_STATE) &&
308 ((pCLE->pCD->clientState == NORMAL_STATE) ||
309 (pCLE->pCD->clientState == MAXIMIZED_STATE)))
311 stackWindow = pCLE->pCD->clientFrameWin;
314 if (stackWindow != None)
317 changes.sibling = stackWindow;
321 if (stackWindow == None)
323 pCLE = pCLE->prevSibling;
328 if (pSD->lastClient->type == MINIMIZED_STATE)
330 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
334 stackWindow = pSD->lastClient->pCD->clientFrameWin;
338 changes.stack_mode = Below;
342 XConfigureWindow (DISPLAY, pcd->clientFrameWin, mask, &changes);
345 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
354 /*************************************<->*************************************
356 * F_Lower (args, pCD, event)
361 * This is the window manager function handler for bottoming a client window
367 * args = function arguments (specified in .mwmrc file)
369 * pCD = pointer to the client data for the client window to which the
370 * function is to be applied
372 * event = X event that invoked the function (key, button, or menu/NULL)
377 * RETURN = if True then further button binding/function processing can
378 * be done for the event that caused this function to be called.
380 *************************************<->***********************************/
382 Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
384 ClientListEntry *pEntry;
385 ClientListEntry *pNextEntry;
386 ClientListEntry *pStackEntry;
387 String string = args;
388 int flags = STACK_NORMAL;
390 WmWorkspaceData *pWS = ACTIVE_WS;
395 /* process '-client' argument */
396 if (string[0] == '-')
399 string = (String) GetString ((unsigned char **) &string);
402 pNextEntry = ACTIVE_PSD->lastClient;
404 (pEntry = FindClientNameMatch (pNextEntry, False,
405 string, F_GROUP_ALL)))
407 pNextEntry = pEntry->prevSibling;
409 if (ClientInWorkspace (pWS, pEntry->pCD))
412 Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
413 pStackEntry = pEntry;
419 /* process family stacking stuff */
422 unsigned int slen, len, index;
424 slen = strlen(args) - 2; /* subtract '\n' and NULL */
425 for (index = 0; index < slen; string = &args[index+1])
427 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
429 len = strlen(string);
430 if (!strcmp(string,"within"))
432 flags |= STACK_WITHIN_FAMILY;
434 else if (!strcmp(string,"freeFamily"))
436 flags |= STACK_FREE_FAMILY;
441 if (ClientInWorkspace (pWS, pCD))
444 Do_Lower (pCD, (ClientListEntry *) NULL, flags);
453 if (ClientInWorkspace (pWS, pCD))
456 Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
463 * If caused by button press, event may ALSO cause focus to be
464 * passed to this client - prepare to disable focusAutoRaise.
466 if (pCD && event && (event->type == ButtonPress))
467 pCD->focusAutoRaiseDisablePending = True;
469 wmGD.passButtonsCheck = False;
472 } /* END OF FUNCTION F_Lower */
476 /*************************************<->*************************************
478 * Do_Lower (pCD, pStackEntry)
483 * This is the window manager function handler for lowering the client window
484 * so that it does not obscure any other window above the stack entry
490 * pCD = pointer to the client data of the window (or icon) to be lowered.
492 * pStackEntry = pointer to client list entry for window that is to be
493 * below the lowered window (if NULL, window is lowered to the bottom
496 *************************************<->***********************************/
498 void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
500 Boolean restackTransients;
501 ClientData *pcdLeader;
502 WmWorkspaceData *pWS = ACTIVE_WS;
504 Boolean bLeaderRestacked;
511 * Window has been reparented into the front panel.
512 * Don't follow through on window stacking change.
518 #endif /* PANELIST */
520 if (ClientInWorkspace(pWS, pCD) &&
521 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
524 * Both clients are in the current workspace. Set
525 * client indices so that the access macros work.
527 SetClientWsIndex (pCD);
530 SetClientWsIndex (pStackEntry->pCD);
536 * One or both of the clients are not in the current workspace
543 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
545 if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
548 * If a dirtyStackEntry exists, return it to its original place
549 * in the stack (for all stacking types)
553 if (dirtyStackEntry->transientChildren ||
554 dirtyStackEntry->transientLeader)
555 RestackTransients (dirtyStackEntry);
556 dirtyStackEntry = NULL;
561 * Only restack the icon if it is not currently lowered.
566 if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
568 StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
570 MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
576 if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
578 StackWindow (pWS, &pcdLeader->iconEntry,
579 False /*on bottom*/, (ClientListEntry *) NULL);
580 MoveEntryInList (pWS, &pcdLeader->iconEntry,
581 False /*on bottom*/, (ClientListEntry *) NULL);
585 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
589 * Handle restacking of primary/secondary windows
590 * within the transient window tree.
592 bLeaderRestacked = False;
593 if ((pcdLeader->transientChildren) &&
594 (!pcdLeader->secondariesOnTop) &&
595 (!wmGD.bSuspendSecondaryRestack))
597 if (pCD == pcdLeader)
600 * Lower requested on the leader itself, insure it's
603 bLeaderRestacked = BumpPrimaryToBottom (pcdLeader);
605 else if (pCD->transientChildren)
608 * Lower requested on the leader of a subtree. Insure
609 * that this subtree leader is at the bottom of the
612 bLeaderRestacked = BumpPrimaryToBottom (pCD);
614 else if (pCD->transientLeader)
619 * Lower requested on a transient. Insure all the
620 * subtree leaders up to the top are at the bottom
621 * of their respective transient subtrees.
623 for (pcdLdr = pCD->transientLeader;
625 pcdLdr = pcdLdr->transientLeader)
627 bLeaderRestacked |= BumpPrimaryToBottom (pcdLdr);
634 * If this is a transient window then put it below its
635 * sibling transient windows.
638 restackTransients = False;
639 if (pCD->transientLeader)
643 * If freeFamily stacking, then put dirty transient window
644 * (if any) back in place before force lowering current window
645 * to the bottom of the global window stack. Then return.
648 if (flags & STACK_FREE_FAMILY)
650 /* Restore dirty transient if not current window. */
651 if ((dirtyStackEntry) &&
652 (dirtyStackEntry != pCD))
654 RestackTransients (dirtyStackEntry);
657 dirtyStackEntry = pCD;
658 dirtyLeader = pcdLeader;
660 ForceLowerWindow (pCD);
665 * Reach here only if NOT doing a f.lower freeFamily (see
666 * return; statement above). Put current transient below
667 * its sibling transient windows.
669 restackTransients = PutTransientBelowSiblings (pCD);
673 * If doing a regular f.lower and you have a dirty window, then
674 * clean up dirty transient window.
680 * If lowering a window in the same family as the dirty
681 * transient window, then just restack before lowering.
682 * Else, restore the dirty transient in place before
683 * lowering the current window. Clear dirtyStack.
685 if (dirtyLeader == pcdLeader)
687 restackTransients = True;
691 RestackTransients (dirtyStackEntry);
694 dirtyStackEntry = NULL;
698 * Only restack the window or transient window tree if it is
699 * not currently lowered and the window is not a system
705 if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
706 !(wmGD.systemModalActive &&
707 (pcdLeader == wmGD.systemModalClient)))
709 StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
711 MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
715 else if ((restackTransients) || (bLeaderRestacked))
717 else if (restackTransients)
720 RestackTransients (pCD);
725 if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
726 !(wmGD.systemModalActive &&
727 (pcdLeader == wmGD.systemModalClient)) &&
728 !(flags & STACK_WITHIN_FAMILY))
730 StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
731 (ClientListEntry *) NULL);
732 MoveEntryInList (pWS, &pcdLeader->clientEntry,
733 False /*on bottom*/, (ClientListEntry *) NULL);
736 else if ((restackTransients) || (bLeaderRestacked))
738 else if (restackTransients)
741 RestackTransients (pCD);
746 } /* END OF FUNCTION Do_Lower */
750 /*************************************<->*************************************
752 * F_CircleDown (args, pCD, event)
757 * This is the window manager function handler for moving the client window
758 * on top of stack to the bottom.
763 * args = function arguments (specified in .mwmrc file)
765 * pCD = pointer to the client data for the client window to which the
766 * function is to be applied
768 * event = X event that invoked the function (key, button, or menu/NULL)
773 * RETURN = if True then further button binding/function processing can
774 * be done for the event that caused this function to be called.
776 *************************************<->***********************************/
778 Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
781 unsigned long windowType;
782 ClientListEntry *pNextEntry;
787 * Go down through the client list looking for a window of an
788 * appropriate type that is obscuring lower windows.
791 types = (unsigned long)args;
792 pNextEntry = ACTIVE_PSD->clientList;
796 * Only check out the window if it is onscreen.
799 pcdNext = pNextEntry->pCD;
800 if (((pNextEntry->type == NORMAL_STATE) &&
801 (pcdNext->clientState != MINIMIZED_STATE)) ||
802 ((pNextEntry->type == MINIMIZED_STATE) &&
803 (pcdNext->clientState == MINIMIZED_STATE)))
805 if (pcdNext->clientState == MINIMIZED_STATE)
807 windowType = F_GROUP_ICON;
811 windowType = F_GROUP_WINDOW;
812 if (pcdNext->transientLeader || pcdNext->transientChildren)
814 windowType |= F_GROUP_TRANSIENT;
817 if (types & windowType)
819 if (CheckIfClientObscuringAny (pcdNext))
822 * This window (or window tree) is obscuring another window
823 * on the screen. Lower the window.
827 wmGD.bSuspendSecondaryRestack = True;
829 F_Lower (NULL, pcdNext, (XEvent *) NULL);
831 wmGD.bSuspendSecondaryRestack = False;
837 pNextEntry = pNextEntry->nextSibling;
842 } /* END OF FUNCTION F_Circle_Down */
846 /*************************************<->*************************************
848 * F_Circle_Up (args, pCD, event)
853 * This is the window manager function handler for moving the client window
854 * on the bottom of the stack to the top.
859 * args = function arguments (specified in .mwmrc file)
861 * pCD = pointer to the client data for the client window to which the
862 * function is to be applied
864 * event = X event that invoked the function (key, button, or menu/NULL)
869 * RETURN = if True then further button binding/function processing can
870 * be done for the event that caused this function to be called.
872 *************************************<->***********************************/
874 Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
877 unsigned long windowType;
878 ClientListEntry *pNextEntry;
883 * Go up through the client list looking for a window of an
884 * appropriate type that is obscured by higher windows.
887 types = (unsigned long)args;
888 pNextEntry = ACTIVE_PSD->lastClient;
892 * Only check out the window if it is onscreen.
895 pcdNext = pNextEntry->pCD;
896 if (((pNextEntry->type == NORMAL_STATE) &&
897 (pcdNext->clientState != MINIMIZED_STATE)) ||
898 ((pNextEntry->type == MINIMIZED_STATE) &&
899 (pcdNext->clientState == MINIMIZED_STATE)))
901 if (pcdNext->clientState == MINIMIZED_STATE)
903 windowType = F_GROUP_ICON;
907 windowType = F_GROUP_WINDOW;
908 if (pcdNext->transientLeader || pcdNext->transientChildren)
910 windowType |= F_GROUP_TRANSIENT;
913 if (types & windowType)
915 if (CheckIfClientObscuredByAny (pcdNext))
918 * This window (or window tree) is obscured by another
919 * window on the screen. Raise the window.
923 wmGD.bSuspendSecondaryRestack = True;
925 F_Raise (NULL, pcdNext, (XEvent *) NULL);
927 wmGD.bSuspendSecondaryRestack = False;
933 pNextEntry = pNextEntry->prevSibling;
939 } /* END OF FUNCTION F_Circle_Up */
943 /*************************************<->*************************************
945 * F_Focus_Color (args, pCD, event)
950 * This is the window manager function handler for setting the colormap
951 * focus to a client window or reinstalling the default colormap.
953 *************************************<->***********************************/
955 Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
958 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
963 * The window selected for the colormap focus is a top-level client
964 * window. If there are subwindow colormaps then determine if the
965 * selection was in one of the subwindows.
968 if (pCD->clientState == MINIMIZED_STATE)
970 /* !!! colormap for client supplied icon window !!! */
975 SetColormapFocus (ACTIVE_PSD, pCD);
980 } /* END OF FUNCTION F_Focus_Color */
984 /*************************************<->*************************************
986 * F_Exec (args, pCD, event)
991 * This is the window manager function handler for executing a command
994 *************************************<->***********************************/
996 Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
1003 void (*quitStat) ();
1009 /* make sure the f.exec command runs on the right display. */
1010 if (wmGD.pActiveSD->displayString)
1012 putenv(wmGD.pActiveSD->displayString);
1019 * Start the busy indicator, waiting for a pushbutton window
1020 * for the given duration
1022 WmFrontPanelSetBusy (True);
1024 #endif /* PANELIST */
1027 * Fork a process to exec a shell to run the specified command:
1031 if ((pid = fork ()) == 0)
1033 if ((pid = vfork ()) == 0)
1038 #if defined(SVR4) || defined(__OSF1__) || defined(__osf__) || defined(linux)
1047 setpgrp(tpid, tpid);
1050 #endif /* NO_SETPGRP */
1053 * Clean up window manager resources.
1054 * The X file descriptor should be automatically closed.
1058 * Fix up signal handling.
1060 RestoreDefaultSignalHandlers ();
1063 * Fix up the child application's environment NOT to
1064 * inherit the XFILESEARCHPATH, XBMLANGPATH, NLSPATH, etc.
1067 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
1069 CLOSE_FILES_ON_EXEC();
1073 * Exec the command using $MWMSHELL if set or
1074 * $SHELL if set and $MWMSHELL not set or sh.
1077 if (((shell = getenv ("MWMSHELL")) != NULL) ||
1078 ((shell = getenv ("SHELL")) != NULL))
1081 shellname = strrchr (shell, '/');
1082 if (shellname == NULL)
1085 If the shell pathname obtained from SHELL or MWMSHELL does not
1086 have a "/" in the path and if the user expects this shell to be
1087 obtained using the PATH variable rather than the current
1088 directory, then we must call execlp and not execl
1091 execlp (shell, shellname, "-c", args, 0);
1096 execl (shell, shellname, "-c", args, 0);
1101 * There is no SHELL environment variable or the first execl failed.
1105 execl ("/usr/bin/sh", "sh", "-c", args, 0);
1107 execl ("/bin/sh", "sh", "-c", args, 0);
1112 * Error - command could not be exec'ed.
1122 * Have the window manager wait for the shell to complete.
1126 intStat = (void (*)())signal (SIGINT, SIG_IGN);
1127 quitStat = (void (*)())signal (SIGQUIT, SIG_IGN);
1132 * Don't need to wait because WSM sets SIGCLD handler
1135 while ((w = wait (&status)) != pid && (w != -1));
1144 signal (SIGINT, intStat);
1145 signal (SIGQUIT, quitStat);
1149 * Restore original DISPLAY environment variable value
1150 * so a restart will start on the same screen
1153 if(wmGD.pActiveSD->displayString &&
1156 putenv(wmGD.displayString);
1163 } /* END OF FUNCTION F_Exec */
1167 /*************************************<->*************************************
1169 * F_Quit_Mwm (args, pCD, event)
1174 * This is the window manager function handler for terminating the window
1177 *************************************<->***********************************/
1179 Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
1181 if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
1183 ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
1192 } /* END OF FUNCTION F_Quit_Mwm */
1196 /*************************************<->*************************************
1198 * Do_Quit_Mwm (diedOnRestart)
1203 * Callback to do the f.quit_mwm function.
1205 *************************************<->***********************************/
1207 void Do_Quit_Mwm (Boolean diedOnRestart)
1210 ClientListEntry *pNextEntry;
1214 * Close the X connection to get all the X resources cleaned up.
1215 * !!! maybe windows should be reparented / rebordered before closing? !!!
1216 * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
1222 XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
1223 for (scr = 0; scr < wmGD.numScreens; scr++)
1225 if (wmGD.Screens[scr].managed)
1228 SaveResources(&wmGD.Screens[scr]);
1230 pNextEntry = wmGD.Screens[scr].lastClient;
1233 if (pNextEntry->type == NORMAL_STATE)
1235 if (!(pNextEntry->pCD->clientFlags &
1238 ReBorderClient (pNextEntry->pCD, diedOnRestart);
1241 pNextEntry = pNextEntry->prevSibling;
1243 #if defined(PANELIST)
1244 UnParentControls (&wmGD.Screens[scr], False);
1245 #endif /* PANELIST */
1248 XDeleteProperty(DISPLAY, wmGD.Screens[scr].rootWindow,
1254 /* shut down the messaging connection */
1258 XSync (DISPLAY, False);
1259 XCloseDisplay (DISPLAY);
1264 exit (WM_ERROR_EXIT_VALUE);
1271 } /* END OF FUNCTION Do_Quit_Mwm */
1274 /*************************************<->*************************************
1276 * ReBorderClient (pCD, reMapClient)
1281 * Restores X border for client window and reparents the
1282 * window back to the root.
1287 * pCD = pointer to the client data for the window to be re-bordered.
1289 *************************************<->***********************************/
1291 void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1295 XWindowChanges windowChanges;
1299 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1302 XUnmapWindow (DISPLAY, pCD->iconWindow);
1304 XReparentWindow (DISPLAY, pCD->iconWindow,
1305 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
1306 pCD->pWsList->iconY);
1308 XReparentWindow (DISPLAY, pCD->iconWindow,
1309 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
1322 if(wmGD.positionIsFrame)
1324 CalculateGravityOffset (pCD, &xoff, &yoff);
1325 x = pCD->clientX - xoff;
1326 y = pCD->clientY - yoff;
1334 XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1335 XReparentWindow (DISPLAY, pCD->client,
1336 ROOT_FOR_CLIENT(pCD), x, y);
1340 XMapWindow(wmGD.display, pCD->client);
1343 if (pCD->transientChildren)
1345 ReBorderClient (pCD->transientChildren, reMapClient);
1353 windowChanges.x = x;
1354 windowChanges.y = y;
1355 windowChanges.border_width = pCD->xBorderWidth;
1356 XConfigureWindow (DISPLAY, pCD->client,
1357 CWBorderWidth | CWX | CWY, &windowChanges);
1360 if (pCD->transientLeader)
1362 pCD = pCD->transientSiblings;
1370 } /* END OF FUNCTION ReBorderClient */
1374 /*************************************<->*************************************
1376 * F_Focus_Key (args, pCD, event)
1381 * This is the window manager function handler for setting the keyboard
1382 * focus to a particular client window.
1387 * args = (immediate value) focus flags
1389 * pCD = pointer to the client data
1391 * event = X event that invoked the function (key, button, or menu/NULL)
1393 *************************************<->***********************************/
1395 Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1397 long focusFlags = (long)args;
1400 if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1402 Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1403 (focusFlags | ALWAYS_SET_FOCUS));
1408 } /* END OF FUNCTION F_Focus_Key */
1411 /*************************************<->*************************************
1413 * FindSomeReasonableClient
1417 * Find a client, any client to set the focus to, return client or NULL.
1418 * This code is ripped off from AutoResetKeyFocus().
1420 *************************************<->***********************************/
1422 static Window FindSomeReasonableClient(void)
1424 ClientData *pcdNoFocus=NULL;
1426 ClientListEntry *pNextEntry;
1428 ClientData *pcdLastFocus = (ClientData *) NULL;
1429 ClientData *pcdFocus;
1430 Window focusWindow = (Window) NULL;
1433 * Scan through the list of clients to find a window to get the focus.
1436 pNextEntry = ACTIVE_PSD->clientList;
1440 pCD = pNextEntry->pCD;
1441 if (!wmGD.systemModalActive ||
1442 (wmGD.systemModalClient == pCD))
1444 if ((pNextEntry->type != MINIMIZED_STATE) &&
1445 (pCD->clientState != MINIMIZED_STATE) &&
1447 (ClientInWorkspace (ACTIVE_WS, pCD)) &&
1449 (pCD != pcdNoFocus))
1451 if (pCD->transientChildren)
1453 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1460 ((pcdLastFocus == NULL) ||
1461 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1463 pcdLastFocus = pcdFocus;
1467 pNextEntry = pNextEntry->nextSibling;
1471 * Set the focus window if one is found
1476 ClientInWorkspace (ACTIVE_WS, pcdLastFocus))
1480 focusWindow = pcdLastFocus->client;
1483 * If a client window could not be found, then just put focus
1487 if (focusWindow == (Window) NULL)
1489 pNextEntry = ACTIVE_PSD->clientList;
1493 pCD = pNextEntry->pCD;
1496 if (ClientInWorkspace (ACTIVE_WS, pCD))
1499 if ((pNextEntry->type == MINIMIZED_STATE) ||
1500 (pCD->clientState == MINIMIZED_STATE))
1502 focusWindow = ICON_FRAME_WIN(pCD);
1508 pNextEntry = pNextEntry->nextSibling;
1512 return (focusWindow);
1514 } /* END OF FUNCTION FindSomeReasonableClient */
1519 /*************************************<->*************************************
1521 * Do_Focus_Key (pCD, focusTime, flags)
1526 * This function is used to set the focus to a window. The focus indication
1527 * is not changed until the FocusIn event is received.
1532 * pCD = pointer to the client data
1534 * focusTime = focus change time
1536 * flags = wm focus change flags
1538 *************************************<->***********************************/
1540 void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1542 ClientData *pcdFocus;
1546 /* Clear the replay flag */
1547 wmGD.replayEnterEvent = False;
1552 * Make sure the client is in the current workspace
1555 (ClientInWorkspace (ACTIVE_WS, pCD)))
1560 if (pCD->clientState == MINIMIZED_STATE)
1562 focusWindow = ICON_FRAME_WIN(pCD);
1564 else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1567 * Set the keyboard focus to the indicated client window.
1568 * If the window has an application modal subordinate then
1569 * set the input focus to that window if the focus isn't
1570 * already owned by a subordinate.
1573 if (IS_APP_MODALIZED(pCD))
1575 ClientData *pcdFocusLeader,*currFocusLeader;
1578 * Handle case where a modal window exists when Mwm starts up.
1579 * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1582 if (wmGD.keyboardFocus)
1584 currFocusLeader = wmGD.keyboardFocus->transientLeader;
1588 currFocusLeader = (ClientData *) NULL;
1592 * Find focus leader for pCD
1595 pcdFocusLeader = pCD;
1596 while (pcdFocusLeader->transientLeader &&
1597 (pcdFocusLeader != currFocusLeader))
1599 pcdFocusLeader = pcdFocusLeader->transientLeader;
1602 if (pcdFocusLeader == currFocusLeader)
1604 pcdFocus = wmGD.keyboardFocus;
1609 pcdFocus = FindTransientFocus (pcdFocusLeader);
1614 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1615 * We must look at why FindTransientFocus is
1616 * returning a NULL pcd. The old code simply set
1617 * focusWindow = pcdFocus->client;
1618 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1620 * 11/26/96 rswiston - In tracking down CDExc22816, we
1621 * discovered that pCD could get tricked into thinking
1622 * it had modal transients when in fact all its transients
1623 * had been withdrawn (fixed in WithdrawTransientChildren()).
1624 * As a result, FindTransientFocus() returns wmGD.keyboardFocus;
1625 * if nobody has the focus, FindTransientFocus() returns NULL.
1629 focusWindow = pcdFocus->client;
1633 focusWindow = (wmGD.keyboardFocus) ?
1634 wmGD.keyboardFocus->client : ACTIVE_PSD->wmWorkspaceWin;
1640 * If the focus policy is "pointer" don't set the focus to a
1641 * window if it has an application modal subordinate.
1644 if (IS_APP_MODALIZED(pCD))
1647 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1649 /* Replay this later when the modal window is removed. */
1650 wmGD.replayEnterEvent = True;
1654 focusWindow = pcdFocus->client;
1661 * Set up the default (non client specific) keyboard input focus.
1664 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1666 focusWindow = PointerRoot;
1671 * The WORKSPACE_IF_NULL flag is used to prevent client
1672 * windows from flashing when deiconifying a client.
1675 if (WORKSPACE_IF_NULL & flags)
1677 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1681 /* find some reasonable client so that focus is not lost */
1683 focusWindow = FindSomeReasonableClient();
1684 if (focusWindow == (Window)NULL)
1686 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1692 if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1697 * Set the focus and/or send a take focus client message. This
1698 * is not done if a client area button press was done to set
1699 * set the focus and the window is a globally active input
1700 * style window (See ICCCM).
1703 if ( (flags & CLIENT_AREA_FOCUS) &&
1704 (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1705 ! pcdFocus->inputFocusModel &&
1706 (pcdFocus == pCD) &&
1707 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
1708 !(pcdFocus->clientState == MINIMIZED_STATE)
1713 * 1. User clicked in the client area AND
1714 * 2. Input model is Globally Active AND
1715 * 3. Keyboard focus policy is explicit
1718 /* this window has WM_TAKE_FOCUS set and InputField false. */
1719 /* just send a message. */
1720 SendClientMsg (pcdFocus->client,
1721 (long) wmGD.xa_WM_PROTOCOLS,
1722 (long) wmGD.xa_WM_TAKE_FOCUS,
1723 focusTime, NULL, 0);
1727 if ((pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1728 !(pcdFocus->clientState == MINIMIZED_STATE))
1731 * Locally Active Input Model - Send a take focus message to the client.
1734 SendClientMsg (pcdFocus->client,
1735 (long) wmGD.xa_WM_PROTOCOLS,
1736 (long) wmGD.xa_WM_TAKE_FOCUS,
1737 focusTime, NULL, 0);
1741 * Don't set the input focus if the window has input_field set
1742 * to False or has expressed an interest in WM_TAKE_FOCUS
1743 * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1744 * and the user click in the client area. If the user clicks
1745 * on the titlebar or traverses to this window via f.next_key,
1746 * set the focus so that the user can access the window menu
1750 if ( wmGD.enforceKeyFocus || /* res - default == True. */
1751 (flags & ALWAYS_SET_FOCUS) ||
1752 !(flags & CLIENT_AREA_FOCUS)|| /* clicked on frame? */
1753 pcdFocus->inputFocusModel || /* Pass.|Glob. Active */
1754 (pcdFocus->clientState == MINIMIZED_STATE)
1757 if ( !(flags & CLIENT_AREA_FOCUS) &&
1758 !pcdFocus->inputFocusModel &&
1759 !(pcdFocus->clientState == MINIMIZED_STATE))
1761 /* the window doesn't want the focus - set it to the frame */
1762 /* user clicked on the frame but we don't want the focus */
1763 /* set it to the client's frame */
1764 XSetInputFocus (DISPLAY, pcdFocus->clientBaseWin,
1765 RevertToPointerRoot, focusTime);
1767 else if ( !(flags & CLIENT_AREA_FOCUS) &&
1768 !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1769 pcdFocus->inputFocusModel
1772 XSetInputFocus (DISPLAY, focusWindow,
1773 RevertToPointerRoot, focusTime);
1777 XSetInputFocus (DISPLAY, focusWindow,
1778 RevertToParent, focusTime);
1784 * We've decided that the window shouldn't get the focus,
1785 * so don't change the focus.
1787 pcdFocus = wmGD.nextKeyboardFocus;
1793 XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1797 wmGD.nextKeyboardFocus = pcdFocus;
1801 } /* END OF FUNCTION Do_Focus_Key */
1806 /***********************<->*************************************
1808 * F_Goto_Workspace (args, pCD, event)
1812 * This is the window manager function handler for switching
1813 * to another workspace by name.
1817 * args = action function and arguments
1819 * pCD = pointer to the ClientData
1821 * event = X event that invoked the function (key, button, or menu/NULL)
1829 ******************************<->***********************************/
1831 F_Goto_Workspace (String args, ClientData *pCD, XEvent *event)
1833 WmScreenData *pSD = ACTIVE_PSD;
1838 * Compare argument against both resource name
1839 * and workspace title, take the first match.
1841 xms = XmStringCreate (args, XmFONTLIST_DEFAULT_TAG);
1842 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1844 if (!strcmp(pSD->pWS[iwsx].name, args) ||
1845 XmStringCompare (xms, pSD->pWS[iwsx].title))
1854 if (iwsx >= pSD->numWorkspaces)
1856 Warning (((char *)GETMESSAGE(26, 4,
1857 "Invalid workspace name specified for f.goto_workspace")));
1861 ChangeToWorkspace (&pSD->pWS[iwsx]);
1866 } /* END OF FUNCTION F_Goto_Workspace */
1872 /******************************<->*************************************
1874 * Boolean F_Help (String args, ClientData *pCD, XEvent *event)
1878 * Invoke help on the workspace manager
1882 * args - incoming values
1883 * pCD - associated client data structure
1884 * event - what triggered this call
1888 * Return - True if the call occurs; false otherwise.
1893 ******************************<->***********************************/
1895 F_Help (String args, ClientData *pCD, XEvent *event)
1900 rval = WmDtHelp(args);
1902 #endif /* PANELIST */
1905 } /* END OF FUNCTION F_Help */
1908 /******************************<->*************************************
1910 * Boolean F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1914 * Invoke item help on the frontpanel
1919 * pCD - associated client data structure ??
1920 * event - what triggered this call
1924 * Return - True if the call occurs; false otherwise.
1929 ******************************<->***********************************/
1931 F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1935 * Help mode event processing interferes
1936 * with slide up windows. Don't continue
1937 * if windows are sliding.
1939 if (wmGD.iSlideUpsInProgress == 0)
1941 (void) WmDtHelpMode();
1944 #endif /* PANELIST */
1946 } /* END OF FUNCTION F_Help_Mode */
1950 /******************************<->*************************************
1952 * F_Next_Key (args, pCD, event)
1957 * This is the window manager function handler for setting the keyboard
1958 * input focus to the next window in the set of managed windows.
1963 * args = (immediate value) window type flags
1965 * pCD = pointer to the client data
1967 * event = X event that invoked the function (key, button, or menu/NULL)
1969 *************************************<->***********************************/
1971 Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1973 #ifdef ROOT_ICON_MENU
1974 Boolean focused = False;
1975 #endif /* ROOT_ICON_MENU */
1976 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1978 #ifdef ROOT_ICON_MENU
1980 #endif /* ROOT_ICON_MENU */
1981 FocusNextWindow ((unsigned long)args,
1982 GetFunctionTimestamp ((XButtonEvent *)event));
1983 #ifdef ROOT_ICON_MENU
1984 if (focused && wmGD.iconClick &&
1985 event && event->type == KeyPress &&
1986 wmGD.nextKeyboardFocus &&
1987 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1988 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1991 * Post system menu from the icon
1993 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1996 #endif /* ROOT_ICON_MENU */
2001 } /* END OF FUNCTION F_Next_Key */
2005 /*************************************<->*************************************
2007 * F_Prev_Cmap (args, pCD, event)
2012 * This is the window manager function handler installing the previous
2013 * colormap in the list of client window colormaps.
2015 *************************************<->***********************************/
2017 Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
2021 pCD = ACTIVE_PSD->colormapFocus;
2024 if (pCD && (pCD->clientCmapCount > 0) &&
2025 ((pCD->clientState == NORMAL_STATE) ||
2026 (pCD->clientState == MAXIMIZED_STATE)))
2028 if (--(pCD->clientCmapIndex) < 0)
2030 pCD->clientCmapIndex = pCD->clientCmapCount - 1;
2032 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2033 if (ACTIVE_PSD->colormapFocus == pCD)
2035 #ifndef OLD_COLORMAP /* colormap */
2037 * We just re-ordered the colormaps list,
2038 * so we need to re-run the whole thing.
2040 pCD->clientCmapFlagsInitialized = 0;
2041 ProcessColormapList (ACTIVE_PSD, pCD);
2042 #else /* OSF original */
2043 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2050 } /* END OF FUNCTION F_Prev_Cmap */
2054 /*************************************<->*************************************
2056 * F_Prev_Key (args, pCD, event)
2061 * This is the window manager function handler for setting the keyboard
2062 * input focus to the previous window in the set of managed windows.
2067 * args = (immediate value) window type flags
2069 * pCD = pointer to the client data
2071 * event = X event that invoked the function (key, button, or menu/NULL)
2073 *************************************<->***********************************/
2075 Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
2077 #ifdef ROOT_ICON_MENU
2078 Boolean focused = False;
2079 #endif /* ROOT_ICON_MENU */
2080 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
2082 #ifdef ROOT_ICON_MENU
2084 #endif /* ROOT_ICON_MENU */
2085 FocusPrevWindow ((unsigned long)args,
2086 GetFunctionTimestamp ((XButtonEvent *)event));
2087 #ifdef ROOT_ICON_MENU
2088 if (focused && wmGD.iconClick &&
2089 event && event->type == KeyPress &&
2090 wmGD.nextKeyboardFocus &&
2091 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
2092 !P_ICON_BOX(wmGD.nextKeyboardFocus))
2095 * Post system menu from the icon
2097 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
2100 #endif /* ROOT_ICON_MENU */
2106 } /* END OF FUNCTION F_Prev_Key */
2110 /***********************<->*************************************
2112 * F_Post_FpMenu (args, pCD, event)
2117 * This is the window manager function handler for posting
2118 * the Front Panel window menu.
2122 * args = arguments (none)
2124 * pCD = pointer to the FP ClientData
2126 * event = X button press that invoked the function
2128 ******************************<->***********************************/
2131 F_Post_FpMenu (String args, ClientData *pCD, XEvent *event)
2133 static MenuSpec *fpMenuSpec = (MenuSpec *)NULL;
2135 if (event->type != ButtonPress)
2140 WmScreenData *pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2145 newMenuName = pCD ? pCD->systemMenu : "DtPanelMenu";
2147 for (oldSpec = pSD->menuSpecs;
2148 oldSpec != (MenuSpec *)NULL;
2149 oldSpec = oldSpec->nextMenuSpec)
2151 if (oldSpec->name && (strcmp(oldSpec->name, newMenuName) == 0))
2157 fpMenuSpec = DuplicateMenuSpec(oldSpec);
2160 * TEMPORARILY modify pSD so the new menu will be
2161 * created on DISPLAY1 instead of DISPLAY.
2163 fpMenuSpec->nextMenuSpec = pSD->menuSpecs;
2164 pSD->menuSpecs = fpMenuSpec;
2165 tmpWidget = pSD->screenTopLevelW;
2166 pSD->screenTopLevelW = pSD->screenTopLevelW1;
2168 (void)MAKE_MENU (pSD, pCD, newMenuName,
2169 F_CONTEXT_NORMAL, F_CONTEXT_NORMAL,
2170 (MenuItem *) NULL, FALSE);
2173 pSD->screenTopLevelW = tmpWidget;
2174 pSD->menuSpecs = fpMenuSpec->nextMenuSpec;
2177 PostMenu (fpMenuSpec, pCD, event->xbutton.x_root, event->xbutton.y_root,
2178 event->xbutton.button, F_CONTEXT_NORMAL, POST_AT_XY, event);
2180 _XmGetMenuState(XtParent(fpMenuSpec->menuWidget))
2181 ->MS_LastManagedMenuTime = event->xbutton.time;
2187 /***********************<->*************************************
2189 * F_Push_Recall (args, pCD, event)
2194 * This is the window manager function handler for invoking/topping
2195 * push_recall clients.
2202 * pCD = pointer to the ClientData
2204 * event = X event that invoked the function (key, button, or menu/NULL)
2209 * RETURN = if True then further button binding/function processing can
2210 * be done for the event that caused this function to be called.
2214 ******************************<->***********************************/
2217 F_Push_Recall (String args, ClientData *pCD, XEvent *event)
2219 WmPushRecallArg *pPRP;
2221 WmFpPushRecallClientData *pPRCD;
2223 pPRP = (WmPushRecallArg *) args;
2224 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2226 if (pPRP->ixReg < pSD->numPushRecallClients)
2228 /* get slot for this client */
2229 pPRCD = &(pSD->pPRCD[pPRP->ixReg]);
2232 * If the client is already running, then top it in this workspace,
2233 * else invoke the function to start it.
2237 /* Client is managed already. */
2238 if (!(ClientInWorkspace (pSD->pActiveWS, pPRCD->pCD)))
2240 WorkspaceID *wsRemoveList;
2244 * Move client to current workspace
2246 wsRemoveList = GetListOfOccupiedWorkspaces (pPRCD->pCD,
2248 RemoveClientFromWorkspaces (pPRCD->pCD, wsRemoveList,
2250 XtFree ((char *)wsRemoveList);
2251 AddClientToWorkspaces (pPRCD->pCD, &(pSD->pActiveWS->id), 1);
2252 SetClientWsIndex(pPRCD->pCD);
2253 SetClientState(pPRCD->pCD,
2254 pPRCD->pCD->clientState & ~UNSEEN_STATE, CurrentTime);
2257 /* Make this client visible */
2259 wmGD.bSuspendSecondaryRestack = True;
2261 F_Normalize_And_Raise (NULL, pPRCD->pCD, event);
2263 wmGD.bSuspendSecondaryRestack = False;
2268 struct timeval tvNow;
2270 Boolean bWaiting = False;
2272 if (pPRCD->tvTimeout.tv_sec != 0)
2274 gettimeofday (&tvNow, &tz);
2276 if ((pPRCD->tvTimeout.tv_sec > tvNow.tv_sec) ||
2277 ((pPRCD->tvTimeout.tv_sec == tvNow.tv_sec) &&
2278 (pPRCD->tvTimeout.tv_usec > tvNow.tv_usec)))
2280 /* still waiting for client to start */
2290 WmPanelistObject pPanelist;
2292 pPanelist = (WmPanelistObject) pSD->wPanelist;
2294 /* invoke the function to start the client */
2295 pPRP->wmFunc ( pPRP->pArgs, pCD, event);
2297 if (pPanelist && panel.busy_light_data)
2299 /* set timeout value */
2302 XmNclientTimeoutInterval, &clientTimeout); ac++;
2303 XtGetValues (panel.busy_light_data->icon, (ArgList)al, ac);
2307 * ClientTimeout is in milliseconds, timeval values
2308 * are in seconds and microseconds.
2310 gettimeofday (&(pPRCD->tvTimeout), &tz);
2312 pPRCD->tvTimeout.tv_sec += clientTimeout / 1000;
2313 pPRCD->tvTimeout.tv_usec +=
2314 (clientTimeout % 1000) * 1000;
2316 pPRCD->tvTimeout.tv_sec += pPRCD->tvTimeout.tv_usec / 1000000;
2317 pPRCD->tvTimeout.tv_usec %= 1000000;
2324 } /* END OF FUNCTION F_Push_Recall */
2325 #endif /* PANELIST */
2328 /*************************************<->*************************************
2330 * F_Pass_Key (args, pCD, event)
2335 * This is a function stub for the f.pass_key window manager function.
2340 * args = (immediate value) window type flags
2342 * pCD = pointer to the client data
2344 * event = X event that invoked the function (key, button, or menu/NULL)
2346 *************************************<->***********************************/
2348 Boolean F_Pass_Key (args, pCD, event)
2354 if (wmGD.passKeysActive)
2357 * Get out of pass keys mode.
2360 wmGD.passKeysActive = False;
2361 wmGD.passKeysKeySpec = NULL;
2366 * Get into pass keys mode.
2369 wmGD.passKeysActive = True;
2374 } /* END OF FUNCTION F_Pass_Key */
2378 /*************************************<->*************************************
2380 * F_Maximize (args, pCD, event)
2385 * This is the window manager function handler for maximizing a client
2388 *************************************<->***********************************/
2390 Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
2392 if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
2394 SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
2395 GetFunctionTimestamp ((XButtonEvent *)event),
2396 GetEventInverseMask(event));
2401 } /* END OF FUNCTION F_Maximize */
2405 /*************************************<->*************************************
2407 * F_Menu (args, pCD, event)
2412 * This is the window manager function handler for posting a menu.
2413 * This function can only be invoked by a key or button event.
2414 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2415 * NULL when the menu is unposted.
2417 *************************************<->***********************************/
2419 Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
2422 Context menuContext;
2423 unsigned int button;
2426 long flags = POST_AT_XY;
2431 ((event->type == ButtonPress) || (event->type == ButtonRelease)))
2433 button = event->xbutton.button;
2434 x = event->xbutton.x_root;
2435 y = event->xbutton.y_root;
2436 if (event->type == ButtonRelease)
2438 flags |= POST_TRAVERSAL_ON;
2442 * Root menu, if posted with button press, then
2443 * set up to handle root menu click to make the menu
2446 else if (wmGD.rootButtonClick && (event->type == ButtonPress))
2448 if (wmGD.bReplayedButton)
2450 /* This button was replayed, it most likely dismissed
2451 a previous sticky menu, don't post a menu here */
2454 wmGD.checkHotspot = True;
2455 wmGD.hotspotRectangle.x = x - wmGD.moveThreshold/2;
2456 wmGD.hotspotRectangle.y = y - wmGD.moveThreshold/2;
2457 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2458 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2463 ((event->type == KeyPress) || (event->type == KeyRelease)))
2466 x = event->xkey.x_root;
2467 y = event->xkey.y_root;
2472 * A button or key event must be used to post a menu using this
2481 if (pCD->clientState == NORMAL_STATE)
2483 menuContext = F_CONTEXT_NORMAL;
2485 else if (pCD->clientState == MAXIMIZED_STATE)
2487 menuContext = F_CONTEXT_MAXIMIZE;
2491 menuContext = F_CONTEXT_ICON;
2493 if (P_ICON_BOX(pCD) &&
2494 event->xany.window == ICON_FRAME_WIN(pCD))
2496 if (pCD->clientState == MINIMIZED_STATE)
2498 menuContext = F_SUBCONTEXT_IB_IICON;
2502 menuContext = F_SUBCONTEXT_IB_WICON;
2508 menuContext = F_CONTEXT_ROOT;
2512 /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
2513 * This should have been done in MakeWmFunctionResources().
2516 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2517 if ((menuSpec = MAKE_MENU (pSD, pCD, args, menuContext,
2518 menuContext, (MenuItem *) NULL, FALSE)) != NULL)
2520 PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
2525 } /* END OF FUNCTION F_Menu */
2528 /*************************************<->*************************************
2530 * F_Minimize (args, pCD, event)
2535 * This is the window manager function handler for minimizing a client
2538 *************************************<->***********************************/
2540 Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
2542 ClientData *pcdLeader;
2548 * If the window is a transient then minimize the entire transient
2549 * tree including the transient leader.
2552 pcdLeader = (pCD->transientLeader) ?
2553 FindTransientTreeLeader (pCD) : pCD;
2554 if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
2556 SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
2557 GetFunctionTimestamp ((XButtonEvent *)event),
2558 GetEventInverseMask(event));
2564 } /* END OF FUNCTION F_Minimize */
2568 /*************************************<->*************************************
2570 * F_Move (args, pCD, event)
2575 * This is the window manager function handler for moving a client window
2578 *************************************<->***********************************/
2580 Boolean F_Move (String args, ClientData *pCD, XEvent *event)
2582 if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
2584 StartClientMove (pCD, event);
2585 HandleClientFrameMove (pCD, event);
2590 } /* END OF FUNCTION F_Move */
2594 /*************************************<->*************************************
2596 * F_Next_Cmap (args, pCD, event)
2601 * This is the window manager function handler installing the next
2602 * colormap in the list of client window colormaps.
2604 *************************************<->***********************************/
2606 Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
2610 pCD = ACTIVE_PSD->colormapFocus;
2613 if (pCD && (pCD->clientCmapCount > 0) &&
2614 ((pCD->clientState == NORMAL_STATE) ||
2615 (pCD->clientState == MAXIMIZED_STATE)))
2617 if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
2619 pCD->clientCmapIndex = 0;
2621 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2622 if (ACTIVE_PSD->colormapFocus == pCD)
2624 #ifndef OLD_COLORMAP /* colormap */
2626 * We just re-ordered the colormaps list,
2627 * so we need to re-run the whole thing.
2629 pCD->clientCmapFlagsInitialized = 0;
2630 ProcessColormapList (ACTIVE_PSD, pCD);
2631 #else /* OSF original */
2632 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2639 } /* END OF FUNCTION F_Next_Cmap */
2643 /*************************************<->*************************************
2645 * F_Nop (args, pCD, event)
2650 * This is the window manager function handler for doing nothing.
2652 *************************************<->***********************************/
2654 Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2659 } /* END OF FUNCTION F_Nop */
2663 /*************************************<->*************************************
2665 * F_Normalize (args, pCD, event)
2670 * This is the window manager function handler for putting a client window
2671 * in the normal state.
2673 *************************************<->***********************************/
2675 Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2680 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2681 GetFunctionTimestamp ((XButtonEvent *)event),
2682 GetEventInverseMask(event));
2687 } /* END OF FUNCTION F_Normalize */
2691 /*************************************<->*************************************
2693 * F_Normalize_And_Raise (args, pCD, event)
2698 * This is the window manager function handler for putting a client window
2699 * in the normal state and raising it from and icon.
2701 *************************************<->***********************************/
2703 Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2707 WmWorkspaceData *pWS;
2712 pSD = PSD_FOR_CLIENT (pCD);
2716 pWS = pSD->pActiveWS;
2718 if (pSD->useIconBox &&
2719 wmGD.useFrontPanel &&
2720 pSD->iconBoxControl &&
2721 (!strcmp(args, WmNiconBox)))
2724 * There's an icon box in the front panel and this is a
2725 * request to pop up the icon box.
2727 IconBoxPopUp (pWS, True);
2731 #endif /* PANELIST */
2734 if (pCD->clientState == MINIMIZED_STATE)
2736 /* normalize window */
2737 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2740 ? GetFunctionTimestamp ((XButtonEvent *)event)
2742 GetEventInverseMask(event));
2746 /* Make sure we are in NORMAL_STATE */
2747 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2748 GetFunctionTimestamp ((XButtonEvent *)event),
2749 GetEventInverseMask(event));
2751 /* Raise the window and set the keyboard focus to the window */
2753 wmGD.bSuspendSecondaryRestack = True;
2755 F_Raise (NULL, pCD, (XEvent *)NULL);
2757 wmGD.bSuspendSecondaryRestack = False;
2759 if (wmGD.raiseKeyFocus)
2761 F_Focus_Key (NULL, pCD,
2764 : ((XEvent *)NULL)));
2767 wmGD.clickData.clickPending = False;
2768 wmGD.clickData.doubleClickPending = False;
2773 } /* END OF FUNCTION F_Normalize_And_Raise */
2777 /*************************************<->*************************************
2779 * F_Restore (args, pCD, event)
2784 * This is the window manager function handler for putting a client window
2785 * in the normal state.
2787 *************************************<->***********************************/
2789 Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2796 * If current state is MAXIMIZED state then just go to NORMAL state,
2797 * otherwise (you are in MINIMIZED state) return to previous state.
2800 if (pCD->clientState == MAXIMIZED_STATE)
2802 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2803 GetFunctionTimestamp ((XButtonEvent *)event),
2804 GetEventInverseMask(event));
2810 newState = MAXIMIZED_STATE;
2814 newState = NORMAL_STATE;
2817 SetClientStateWithEventMask (pCD, newState,
2818 GetFunctionTimestamp ((XButtonEvent *)event),
2819 GetEventInverseMask(event));
2825 } /* END OF FUNCTION F_Restore */
2829 /*************************************<->*************************************
2831 * F_Restore_And_Raise (args, pCD, event)
2836 * This is the window manager function handler for putting a client window
2837 * in the normal state and raising it from and icon.
2839 *************************************<->***********************************/
2841 Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2847 if (pCD->clientState == MINIMIZED_STATE)
2849 /* Restore window */
2852 newState = MAXIMIZED_STATE;
2856 newState = NORMAL_STATE;
2859 SetClientStateWithEventMask (pCD, newState,
2862 ? GetFunctionTimestamp ((XButtonEvent *)event)
2864 GetEventInverseMask(event));
2868 /* Make sure we restore the window first */
2869 F_Restore (NULL, pCD, event);
2871 /* Raise the window and set the keyboard focus to the window */
2873 wmGD.bSuspendSecondaryRestack = True;
2875 F_Raise (NULL, pCD, (XEvent *)NULL);
2877 wmGD.bSuspendSecondaryRestack = False;
2879 if (wmGD.raiseKeyFocus)
2881 F_Focus_Key (NULL, pCD,
2884 : ((XEvent *)NULL)));
2887 wmGD.clickData.clickPending = False;
2888 wmGD.clickData.doubleClickPending = False;
2893 } /* END OF FUNCTION F_Restore_And_Raise */
2897 /*************************************<->*************************************
2899 * F_Pack_Icons (args, pCD, event)
2904 * This is the window manager function handler for packing icons in the
2905 * icon box or on the desktop.
2907 *************************************<->***********************************/
2909 Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2914 if (ACTIVE_PSD->useIconBox)
2916 pIBD = ACTIVE_WS->pIconBox;
2919 while (pCD != pIBD->pCD_iconBox)
2921 if (pIBD->pNextIconBox)
2923 pIBD = pIBD->pNextIconBox;
2934 PackIconBox (pIBD, False, False, 0, 0);
2949 } /* END OF FUNCTION F_Pack_Icons */
2952 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2953 /*************************************<->*************************************
2955 * F_Post_RMenu (args, pCD, event)
2960 * This is the window manager function handler for posting the
2962 * This function can only be invoked by a key event.
2964 *************************************<->***********************************/
2966 Boolean F_Post_RMenu (String args, ClientData *pCD, XEvent *event)
2969 unsigned int button = NoButton;
2971 long flags = POST_AT_XY;
2977 if ((event->type == KeyPress) || (event->type == KeyRelease))
2980 /* Find the root menu spec */
2981 for (rootMenu = ACTIVE_PSD->menuSpecs;
2982 rootMenu != (MenuSpec *) NULL;
2983 rootMenu = rootMenu->nextMenuSpec)
2985 if (strcmp(rootMenu->name, ACTIVE_PSD->rootMenu) == 0)
2989 /* If we couldn't find the root menu, then do nothing. */
2990 if (rootMenu == (MenuSpec *) NULL)
2995 XQueryPointer(DISPLAY, ACTIVE_ROOT,
2996 &rwin, &cwin, &x, &y, &winx, &winy, &mask);
2998 PostMenu (rootMenu, NULL, x, y, NoButton, F_CONTEXT_ROOT,
3005 } /* END OF FUNCTION F_Post_RMenu */
3006 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
3009 /*************************************<->*************************************
3011 * F_Post_SMenu (args, pCD, event)
3016 * This is the window manager function handler for posting the system menu
3017 * for the specified client.
3018 * This function can only be invoked by a key or button event.
3019 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
3020 * NULL when the menu is unposted.
3022 *************************************<->***********************************/
3024 Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
3026 Context menuContext;
3030 * An event must be used to post the system menu using this function.
3033 if (event && pCD && pCD->systemMenuSpec)
3036 * Determine whether the keyboard is posting the menu and post
3037 * the menu at an appropriate place.
3040 if (pCD->clientState == NORMAL_STATE)
3042 menuContext = F_CONTEXT_NORMAL;
3044 else if (pCD->clientState == MAXIMIZED_STATE)
3046 menuContext = F_CONTEXT_MAXIMIZE;
3050 menuContext = F_CONTEXT_ICON;
3052 if (P_ICON_BOX(pCD) &&
3053 event->xany.window == ICON_FRAME_WIN(pCD))
3055 if (pCD->clientState == MINIMIZED_STATE)
3057 menuContext = F_SUBCONTEXT_IB_IICON;
3061 menuContext = F_SUBCONTEXT_IB_WICON;
3065 if ((event->type == KeyPress) || (event->type == KeyRelease))
3068 * Set up for "sticky" menu processing if specified.
3071 if (pCD->clientState == MINIMIZED_STATE ||
3072 menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
3076 wmGD.checkHotspot = True;
3079 else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
3081 wmGD.checkHotspot = True;
3084 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
3087 else if (event->type == ButtonPress)
3091 * Root menu, if posted with button press, then
3092 * set up to handle root menu click to make the menu
3095 if (wmGD.rootButtonClick && (!wmGD.checkHotspot))
3097 wmGD.checkHotspot = True;
3098 wmGD.hotspotRectangle.x =
3099 event->xbutton.x_root - wmGD.moveThreshold/2;
3100 wmGD.hotspotRectangle.y =
3101 event->xbutton.y_root - wmGD.moveThreshold/2;
3102 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
3103 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
3106 PostMenu (pCD->systemMenuSpec, pCD,
3107 event->xbutton.x_root, event->xbutton.y_root,
3108 event->xbutton.button, menuContext, POST_AT_XY, event);
3110 else if (event->type == ButtonRelease)
3112 PostMenu (pCD->systemMenuSpec, pCD,
3113 event->xbutton.x_root, event->xbutton.y_root,
3114 event->xbutton.button, menuContext,
3115 POST_AT_XY | POST_TRAVERSAL_ON, event);
3121 } /* END OF FUNCTION F_PostSMenu */
3125 /*************************************<->*************************************
3127 * F_Kill (args, pCD, event)
3132 * This is the window manager function handler for terminating a client.
3133 * Essentially the client connection is shut down.
3135 *************************************<->***********************************/
3137 Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
3139 if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
3141 Boolean do_delete_window =
3142 pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
3143 Boolean do_save_yourself =
3144 pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
3147 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3152 * Get the widget for the subpanel
3153 * (Should be only child of the shell!)
3155 wPanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
3158 SlideSubpanelBackIn (pCD, wPanel);
3162 if (pCD->clientFlags & ICON_BOX)
3165 * When the front panel is used with the icon box,
3166 * "Close" hides the icon box into the front panel.
3168 if ((wmGD.useFrontPanel) &&
3169 (pCD->pSD->iconBoxControl) &&
3170 (IconBoxShowing(pCD->pSD->pActiveWS)))
3172 IconBoxPopUp (pCD->pSD->pActiveWS, False);
3176 #endif /* PANELIST */
3177 if (!do_delete_window && !do_save_yourself)
3179 XKillClient (DISPLAY, pCD->client);
3183 if (do_delete_window)
3186 * The client wants to be notified, not killed.
3189 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3190 (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
3194 * HP does not want to send a client message for both
3195 * delete_window AND save_yourself. The current OSF
3196 * patch did just that. This "else if" returns dtwm
3197 * to the behavior of dt 2.01
3199 else if (do_save_yourself)
3201 if (do_save_yourself)
3205 * Send a WM_SAVE_YOURSELF message and wait for a change to
3206 * the WM_COMMAND property.
3207 * !!! button and key input should be kept from the window !!!
3210 if (AddWmTimer (TIMER_QUIT,
3211 (unsigned long) wmGD.quitTimeout, pCD))
3213 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3214 (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
3216 pCD->clientFlags |= CLIENT_TERMINATING;
3220 XKillClient (DISPLAY, pCD->client);
3228 } /* END OF FUNCTION F_Kill */
3232 /*************************************<->*************************************
3234 * F_Marquee_Selection (args, pCD, event)
3239 * This is the window manager function handler for selecting
3240 * non-window manager objects on the root window.
3242 *************************************<->***********************************/
3244 Boolean F_Marquee_Selection (String args, ClientData *pCD, XEvent *event)
3249 * This function only valid in root context
3251 StartMarqueeSelect (ACTIVE_PSD, event);
3252 HandleMarqueeSelect (ACTIVE_PSD, event);
3257 } /* END OF FUNCTION F_Marquee_Selection */
3259 /*************************************<->*************************************
3261 * RefreshByClearing (win)
3266 * Recursively refresh this window and its children by doing
3269 *************************************<->***********************************/
3271 RefreshByClearing (Window win)
3275 Window root, parent;
3276 unsigned int nchildren;
3277 Window *winChildren;
3279 /* clear this window */
3280 XClearArea(DISPLAY, win, 0, 0, 0, 0, True);
3282 /* find any children and clear them, too */
3283 status = XQueryTree(DISPLAY, win, &root, &parent, &winChildren,
3287 /* recurse for each child window */
3288 for (i=0; i<nchildren; ++i)
3290 RefreshByClearing(winChildren[i]);
3295 XFree((char *)winChildren);
3301 /*************************************<->*************************************
3303 * F_Refresh (args, pCD, event)
3308 * This is the window manager function handler for causing all windows
3309 * in the workspace to be redrawn.
3311 *************************************<->***********************************/
3313 Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
3318 if (wmGD.refreshByClearing)
3320 RefreshByClearing (ACTIVE_ROOT);
3325 /* default background_pixmap is None */
3326 win = XCreateWindow (DISPLAY,
3328 (unsigned int) DisplayWidth (DISPLAY,
3330 (unsigned int) DisplayHeight (DISPLAY,
3337 (XSetWindowAttributes *)NULL);
3339 XMapWindow (DISPLAY, win);
3340 XDestroyWindow (DISPLAY, win);
3348 } /* END OF FUNCTION F_Refresh */
3352 /*************************************<->*************************************
3354 * F_Resize (args, pCD, event)
3359 * This is the window manager function handler for resizing a client window.
3361 *************************************<->***********************************/
3363 Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
3365 if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
3366 ((pCD->clientState == NORMAL_STATE) ||
3367 (pCD->clientState == MAXIMIZED_STATE)))
3369 StartClientResize (pCD, event);
3370 HandleClientFrameResize (pCD, event);
3375 } /* END OF FUNCTION F_Resize */
3379 /*************************************<->*************************************
3381 * F_Restart (args, pCD, event)
3386 * This is the window manager function handler for restarting the window
3389 *************************************<->***********************************/
3391 Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
3394 if (args && *args && !strcmp (args, DTWM_REQP_NO_CONFIRM))
3396 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3400 if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
3402 ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
3406 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3410 } /* END OF FUNCTION F_Restart */
3414 /*************************************<->*************************************
3416 * Do_Restart (dummy)
3421 * Callback function for restarting the window manager.
3423 *************************************<->***********************************/
3425 void Do_Restart (Boolean dummy)
3427 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3429 } /* END OF FUNCTION Do_Restart */
3433 /*************************************<->*************************************
3435 * RestartWm (startupFlags)
3440 * Actually restarts the window manager.
3445 * startupFlags = flags to be put into the Wm_INFO property for restart.
3447 *************************************<->***********************************/
3449 void RestartWm (long startupFlags)
3451 ClientListEntry *pNextEntry;
3455 for (scr=0; scr<wmGD.numScreens; scr++)
3457 if(wmGD.Screens[scr].managed)
3461 * Set up the _MOTIF_WM_INFO property on the root window
3462 * to indicate a restart.
3465 SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
3467 SaveResources(&wmGD.Screens[scr]);
3470 * Unmap client windows and reparent them to the root window.
3473 pNextEntry = wmGD.Screens[scr].lastClient;
3476 if (pNextEntry->type == NORMAL_STATE)
3478 if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
3480 if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
3482 XUnmapWindow (DISPLAY,
3483 pNextEntry->pCD->clientFrameWin);
3488 DeFrameClient (pNextEntry->pCD);
3491 pNextEntry = pNextEntry->prevSibling;
3493 #if defined(PANELIST)
3494 UnParentControls (&wmGD.Screens[scr], True);
3495 #endif /* PANELIST */
3501 /* shut down the messaging connection */
3507 * This fixes restart problem when going from explicit focus to
3508 * pointer focus. Window under pointer was not getting focus indication
3509 * until pointer was moved to new window, or out of and into the
3513 XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
3514 XSync (DISPLAY, False);
3517 CLOSE_FILES_ON_EXEC();
3518 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3521 * Restart the window manager with the initial arguments plus
3522 * the restart settings.
3525 execvp (*(wmGD.argv), wmGD.argv);
3528 Warning (((char *)GETMESSAGE(26, 1,
3529 "The window manager restart failed. The window manager program could not \
3530 be found or could not be executed.")));
3532 Warning ("Cannot restart the window manager");
3538 } /* END OF FUNCTION RestartWm */
3541 /*************************************<->*************************************
3543 * DeFrameClient (pCD)
3548 * Unmaps a client window (and client icon window) and reparents the
3549 * window back to the root.
3554 * pCD = pointer to the client data for the window to be de-framed.
3556 *************************************<->***********************************/
3558 void DeFrameClient (ClientData *pCD)
3562 XWindowChanges windowChanges;
3566 if (pCD->clientState != MINIMIZED_STATE)
3568 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
3571 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
3573 XUnmapWindow (DISPLAY, pCD->iconWindow);
3574 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
3576 XReparentWindow (DISPLAY, pCD->iconWindow,
3577 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
3578 pCD->pWsList->iconY);
3580 XReparentWindow (DISPLAY, pCD->iconWindow,
3581 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
3592 if(wmGD.positionIsFrame)
3594 CalculateGravityOffset (pCD, &xoff, &yoff);
3595 x = pCD->clientX - xoff;
3596 y = pCD->clientY - yoff;
3605 #ifndef UNMAP_ON_RESTART
3606 if (pCD->clientState == MINIMIZED_STATE)
3608 XUnmapWindow (DISPLAY, pCD->client);
3611 XUnmapWindow (DISPLAY, pCD->client);
3613 XRemoveFromSaveSet (DISPLAY, pCD->client);
3614 XReparentWindow (DISPLAY, pCD->client,
3615 ROOT_FOR_CLIENT(pCD), x, y);
3617 if (pCD->transientChildren)
3619 DeFrameClient (pCD->transientChildren);
3625 windowChanges.x = x;
3626 windowChanges.y = y;
3627 windowChanges.border_width = pCD->xBorderWidth;
3628 XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
3631 if (pCD->transientLeader)
3633 pCD = pCD->transientSiblings;
3641 } /* END OF FUNCTION DeFrameClient */
3643 #if defined(PANELIST)
3645 /******************************<->*************************************
3647 * F_Toggle_Front_Panel (args, pCD, event)
3652 * This is the window manager function handler for toggling the
3653 * front panel off and on.
3654 ******************************<->***********************************/
3657 F_Toggle_Front_Panel (String args, ClientData *pCD, XEvent *event)
3660 WmPanelistObject pPanelist;
3664 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3668 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3674 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3675 wmGD.windowContextType, (caddr_t *)&pCD);
3681 if (pCD->clientState & MINIMIZED_STATE)
3683 SetClientState (pCD, NORMAL_STATE,
3684 GetFunctionTimestamp ((XButtonEvent *)event));
3688 SetClientState (pCD, MINIMIZED_STATE,
3689 GetFunctionTimestamp ((XButtonEvent *)event));
3694 } /* END OF FUNCTION F_Toggle_Front_Panel */
3697 /******************************<->*************************************
3699 * Boolean F_Version (String args, ClientData *pCD, XEvent *event)
3703 * Invoke the help on version dialogue.
3707 * args - incoming values
3708 * pCD - associated client data structure
3709 * event - what triggered this call
3713 * Return - True if the call occurs; false otherwise.
3718 ******************************<->***********************************/
3720 F_Version (String args, ClientData *pCD, XEvent *event)
3723 WmPanelistObject pPanelist;
3727 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3731 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3736 WmDtHelpOnVersion (O_Shell (pPanelist));
3741 } /* END OF FUNCTION F_Version */
3742 #endif /* PANELIST */
3745 /******************************<->*************************************
3747 * F_Send_Msg (args, pCD, event)
3752 * This is the window manager function handler for sending a client
3753 * message event to a client window.
3758 * args = (immediate value) message id
3760 * pCD = pointer to the client data
3762 * event = X event that invoked the function (key, button, or menu/NULL)
3765 ******************************<->***********************************/
3767 Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
3772 if (pCD && pCD->mwmMessagesCount)
3775 * A message id must be made "active" by being included in the
3776 * _MWM_MESSAGES property before the associated message can be sent.
3779 for (i = 0; i < pCD->mwmMessagesCount; i++)
3781 if (pCD->mwmMessages[i] == (long)args)
3783 SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES,
3784 (long)args, CurrentTime, NULL, 0);
3792 } /* END OF FUNCTION F_Send_Msg */
3796 /*************************************<->*************************************
3798 * F_Separator (args, pCD, event)
3803 * This is a placeholder function; it should never be called.
3805 *************************************<->***********************************/
3807 Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
3812 } /* END OF FUNCTION F_Separator */
3815 Boolean ForceRaiseWindow (ClientData *pcd)
3819 WmScreenData *pSD = (ACTIVE_WS)->pSD;
3821 XWindowChanges changes;
3822 Boolean restack = False;
3825 if (pSD->clientList->type == MINIMIZED_STATE)
3827 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
3831 stackWindow = pSD->clientList->pCD->clientFrameWin;
3836 * Windows did not raise on regular f.raise because the raise was
3837 * not relative to another window (methinks).
3839 changes.stack_mode = Above;
3840 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
3848 /*************************************<->*************************************
3850 * F_Raise (args, pCD, event)
3855 * This is the window manager function handler for topping the client window
3856 * so that it is unobscured.
3858 *************************************<->***********************************/
3860 Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
3862 ClientListEntry *pEntry;
3863 ClientListEntry *pNextEntry;
3864 ClientListEntry *pStackEntry;
3865 String string = args;
3866 int flags = STACK_NORMAL;
3868 WmWorkspaceData *pWS = ACTIVE_WS;
3873 /* process '-client' argument */
3874 if (string[0] == '-')
3876 string = &string[1];
3877 string = (String) GetString ((unsigned char **) &string);
3880 pNextEntry = ACTIVE_PSD->clientList;
3881 while (pNextEntry &&
3882 (pEntry = FindClientNameMatch (pNextEntry, True, string,
3885 pNextEntry = pEntry->nextSibling;
3887 if (ClientInWorkspace (pWS, pEntry->pCD))
3890 Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3891 pStackEntry = pEntry;
3897 /* process family stacking stuff */
3900 unsigned int slen, len, index;
3902 slen = strlen(args) - 2; /* subtract '\n' and NULL */
3903 for (index = 0; index < slen; string = &args[index+1])
3905 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3907 len = strlen(string);
3908 if (!strcmp(string,"within"))
3910 flags |= STACK_WITHIN_FAMILY;
3912 else if (!strcmp(string,"freeFamily"))
3914 flags |= STACK_FREE_FAMILY;
3919 if (ClientInWorkspace (pWS, pCD))
3922 Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3931 if (ClientInWorkspace (pWS, pCD))
3934 Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3942 } /* END OF FUNCTION F_Raise */
3946 /*************************************<->*************************************
3948 * Do_Raise (pCD, pStackEntry)
3953 * This is the window manager function handler for topping the client window
3954 * so that it is unobscured.
3959 * pCD = pointer to the client data of the window (or icon) to be raised.
3961 * pStackEntry = pointer to client list entry for window that is to be
3962 * above the raised window (if NULL window is raised to the top of the
3965 *************************************<->***********************************/
3967 void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3969 Boolean restackTransients;
3970 ClientData *pcdLeader;
3971 WmWorkspaceData *pWS = ACTIVE_WS;
3973 Boolean bLeaderRestacked;
3980 * Window has been reparented into the front panel.
3981 * Don't follow through on window stacking change.
3986 #else /* PANELIST */
3987 #endif /* PANELIST */
3989 if (ClientInWorkspace(pWS, pCD) &&
3990 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
3993 * Both clients are in the current workspace. Set
3994 * client indices so that the access macros work.
3996 SetClientWsIndex (pCD);
3999 SetClientWsIndex (pStackEntry->pCD);
4005 * One or both of the clients are not in the current workspace
4012 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
4014 if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
4017 * Don't raise the window above the system modal window.
4020 else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
4021 !P_ICON_BOX(pcdLeader))
4024 * If a dirtyStackEntry exists, return it to its original place
4025 * in the stack (for all stacking types)
4027 if (dirtyStackEntry)
4029 if (dirtyStackEntry->transientChildren ||
4030 dirtyStackEntry->transientLeader)
4031 RestackTransients (dirtyStackEntry);
4032 dirtyStackEntry = NULL;
4037 * Only restack the icon if it is not currently raised.
4042 if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
4044 StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
4046 MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
4052 if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
4054 StackWindow (pWS, &pcdLeader->iconEntry,
4055 True /*on top*/, (ClientListEntry *) NULL);
4056 MoveEntryInList (pWS, &pcdLeader->iconEntry,
4057 True /*on top*/, (ClientListEntry *) NULL);
4061 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
4065 * Handle restacking of primary/secondary windows
4066 * within the transient window tree. Don't raise this
4067 * window above any modal transients.
4069 bLeaderRestacked = False;
4070 if ((pcdLeader->transientChildren) &&
4071 (!pCD->secondariesOnTop) &&
4072 (!wmGD.bSuspendSecondaryRestack) &&
4073 (!IS_APP_MODALIZED(pCD)))
4075 if (pCD != pcdLeader)
4078 * This is not the transient leader, make sure
4079 * the transient leader isn't on top.
4080 * (Brute force solution)
4082 bLeaderRestacked = NormalizeTransientTreeStacking (pcdLeader);
4084 if (pCD->transientChildren)
4087 * This isn't the overall leader of the transient
4088 * tree, but it does have transient's of its own.
4089 * Move it to the top of its own transient sub-tree.
4091 bLeaderRestacked |= BumpPrimaryToTop (pCD);
4097 * This is the transient leader, move it to the
4100 bLeaderRestacked = BumpPrimaryToTop (pcdLeader);
4106 * If this is a transient window then put it on top of its
4107 * sibling transient windows.
4110 restackTransients = False;
4114 * Fix for 5325 - The following code has been reorganized to cause the
4115 * action of F_Raise to match the current documentation.
4116 * The new algorithm is as follows:
4118 * if (dirtyStackEntry)
4119 * restore dirty tree
4120 * if (not withinFamily)
4121 * bring window group to the top of global stack
4123 * raise the requested window to top of family
4125 * raise requested window to top of siblings
4126 * if (need to restack windows)
4131 * If a dirtyStackEntry exists, return it to its original place
4132 * in the stack (for all stacking types)
4134 if (dirtyStackEntry)
4137 * Check to make sure that the dirty pCD has either transient
4138 * children or a transient leader. If not, do not restore
4141 if (dirtyStackEntry->transientChildren ||
4142 dirtyStackEntry->transientLeader)
4143 RestackTransients (dirtyStackEntry);
4144 dirtyStackEntry = NULL;
4149 * If the flags do not indicate "within", raise the window family
4150 * to the top of the window stack. If the window is the primary,
4151 * raise it to the top regardless of the flags.
4153 if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
4157 if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
4159 StackWindow (pWS, &pcdLeader->clientEntry,
4160 False /*below*/, pStackEntry);
4161 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4162 False /*below*/, pStackEntry);
4167 if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
4169 StackWindow (pWS, &pcdLeader->clientEntry,
4170 True /*on top*/, (ClientListEntry *) NULL);
4171 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4172 True /*on top*/, (ClientListEntry *) NULL);
4178 * If freeFamily stacking is requested, check to make sure that
4179 * the window has either a transientChild or Leader. This will
4180 * guarantee that windows that form their own family are not
4181 * labelled as dirty (what's to dirty it up?). If it has either,
4182 * raise the window to the top of the family stack.
4184 if ((flags & STACK_FREE_FAMILY) &&
4185 (pCD->transientLeader || pCD->transientChildren))
4187 dirtyStackEntry = pCD;
4188 dirtyLeader = pcdLeader;
4190 restackTransients = ForceRaiseWindow (pCD);
4194 * If withinFamily stacking is requested, put the current transient
4195 * on top of its sibling transient windows.
4199 restackTransients = PutTransientOnTop (pCD);
4202 /* At this point, if doing a regular f.raise the window family has
4203 * already been brought to the top of the stack, so nothing further
4204 * needs to be done for it.
4207 /* Restack the transients if needed */
4210 if ((restackTransients) || (bLeaderRestacked))
4212 if (restackTransients)
4215 RestackTransients (pCD);
4219 } /* END OF FUNCTION Do_Raise */
4223 /*************************************<->*************************************
4225 * F_Raise_Lower (args, pCD, event)
4230 * This window manager function tops an obscured window or icon and bottoms
4231 * a window or icon that is on top of the window stack.
4233 *************************************<->***********************************/
4235 Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
4237 ClientData *pcdLeader;
4241 pcdLeader = (pCD->transientLeader) ?
4242 FindTransientTreeLeader (pCD) : pCD;
4245 * Treat a raise/lower on a window in a transient tree as if it is
4246 * a raise/lower for the whole tree.
4249 if (CheckIfClientObscuredByAny (pcdLeader))
4252 * The window is obscured by another window, raise the window.
4256 F_Raise (NULL, pCD, (XEvent *)NULL);
4258 F_Raise (NULL, pcdLeader, (XEvent *)NULL);
4261 else if (CheckIfClientObscuringAny (pcdLeader) &&
4262 !(wmGD.systemModalActive &&
4263 (pcdLeader == wmGD.systemModalClient)))
4266 * The window is obscuring another window and is
4267 * not system modal, lower the window.
4270 F_Lower (NULL, pcdLeader, (XEvent *)NULL);
4272 if ((pcdLeader->secondariesOnTop == False) &&
4273 (pCD->transientLeader != NULL) &&
4274 (!IS_APP_MODALIZED(pcdLeader)))
4276 /* Push transient below primary */
4277 (void) BumpPrimaryToTop (pcdLeader);
4278 RestackTransients (pcdLeader);
4283 else if ((pcdLeader->secondariesOnTop == False) &&
4284 (pcdLeader->transientChildren != NULL) &&
4285 (!wmGD.systemModalActive) &&
4286 (!IS_APP_MODALIZED(pcdLeader)))
4288 if (LeaderOnTop(pcdLeader))
4290 /* Push primary below transient */
4291 (void) BumpPrimaryToBottom (pcdLeader);
4292 RestackTransients (pcdLeader);
4296 F_Raise (NULL, pCD, (XEvent *)NULL);
4297 /* Push transient below primary */
4298 (void) BumpPrimaryToTop (pcdLeader);
4299 RestackTransients (pcdLeader);
4307 } /* END OF FUNCTION F_Raise_Lower */
4311 /*************************************<->*************************************
4313 * F_Refresh_Win (args, pCD, event)
4318 * This is the window manager function handler for causing a client window
4319 * to redisplay itself.
4321 *************************************<->***********************************/
4323 Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
4328 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
4329 (pCD->clientState == MAXIMIZED_STATE)))
4331 if (pCD->clientState == NORMAL_STATE)
4333 w = (unsigned int) pCD->clientWidth;
4334 h = (unsigned int) pCD->clientHeight;
4338 w = (unsigned int) pCD->maxWidth;
4339 h = (unsigned int) pCD->maxHeight;
4343 if (wmGD.refreshByClearing)
4345 RefreshByClearing (pCD->clientFrameWin);
4350 /* default background_pixmap is None */
4351 win = XCreateWindow (DISPLAY,
4361 (XSetWindowAttributes *)NULL);
4363 XMapWindow (DISPLAY, win);
4364 XDestroyWindow (DISPLAY, win);
4373 } /* END OF FUNCTION F_Refresh_Win */
4377 /*************************************<->*************************************
4379 * F_Set_Behavior (args, pCD, event)
4384 * This function is used to switch the window manager configuration between
4385 * the built-in configuration (for CXI behavior) and the user's custom
4388 *************************************<->***********************************/
4390 Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
4393 * Go system modal in starting to do the set behavior.
4396 /* !!! grab the server and the pointer !!! */
4400 * Confirm that a set_behavior should be done.
4401 * Execute restart if so.
4404 if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
4406 ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
4407 CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
4411 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4412 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4416 } /* END OF FUNCTION F_Set_Behavior */
4420 /*************************************<->*************************************
4422 * Do_Set_Behavior (dummy)
4427 * Callback to do the f.set_behavior function.
4429 *************************************<->***********************************/
4431 void Do_Set_Behavior (Boolean dummy)
4433 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4434 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4436 } /* END OF FUNCTION Do_Set_Behavior */
4440 /*************************************<->*************************************
4442 * F_Set_Context (args, pCD, event)
4447 * This function is used to set a client context for subsequent
4450 *************************************<->***********************************/
4452 Boolean F_Set_Context (String args, ClientData *pCD, XEvent *event)
4455 wmGD.requestContextWin = (Window) args;
4458 } /* END OF FUNCTION F_Set_Context */
4462 /*************************************<->*************************************
4464 * F_Title (args, pCD, event)
4469 * This is a placeholder function; it should never be called.
4471 *************************************<->***********************************/
4473 Boolean F_Title (String args, ClientData *pCD, XEvent *event)
4478 } /* END OF FUNCTION F_Title */
4482 /******************************<->*************************************
4484 * F_Screen (args, pCD, event)
4489 * This is the window manager function handler for warping to screens
4494 * args = (immediate value) window type flags
4496 * pCD = pointer to the client data
4498 * event = X event that invoked the function (key, button, or menu/NULL)
4500 * NOTE: May want to consider tracking changes in screen because in
4501 * managing a new window (ie. in ManageWindow()).
4505 * RETURN = if True then further button binding/function processing can
4506 * be done for the event that caused this function to be called.
4508 *************************************<->***********************************/
4510 Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
4514 unsigned int dummask;
4515 WmScreenData *newscr = NULL;
4517 static int PreviousScreen = -1;
4521 if (PreviousScreen == -1)
4523 PreviousScreen = DefaultScreen(DISPLAY);
4526 if (strcmp (args, "next") == 0)
4528 scr = ACTIVE_PSD->screen + 1;
4531 else if (strcmp (args, "prev") == 0)
4533 scr = ACTIVE_PSD->screen - 1;
4536 else if (strcmp (args, "back") == 0)
4538 scr = PreviousScreen;
4550 scr = wmGD.numScreens - 1;
4551 else if (scr >= wmGD.numScreens)
4554 newscr = &(wmGD.Screens[scr]);
4555 if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
4556 if (inc) { /* walk around the list */
4561 "Unable to warp to unmanaged screen %d\n", scr);
4568 if (ACTIVE_PSD->screen == scr) return (False); /* already on that screen */
4570 PreviousScreen = ACTIVE_PSD->screen;
4571 XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
4572 &dumint, &dumint, &dummask);
4574 XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
4576 if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
4579 * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can
4580 * uses the new screen instead of the old screen. Then call
4581 * Do_Focus_Key with a NULL pCD to find a reasonable client to
4584 SetActiveScreen (newscr);
4585 Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
4594 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
4595 /*************************************<->*************************************
4597 * F_InvokeCommand (args, pCD, event)
4602 * This is the window manager function for invoking client inserted menu
4605 *************************************<->***********************************/
4607 Boolean F_InvokeCommand (String args, ClientData *pCD, XEvent *event)
4609 CARD32 commandID, clientWindow;
4610 Atom notifySelection;
4612 if (args == (String) NULL) return(FALSE);
4614 if (sscanf(args, "%d %d %ld", &commandID, &clientWindow,
4615 ¬ifySelection) != 3)
4618 SendInvokeMessage(commandID,
4619 (pCD == (ClientData *) NULL ? 0 : pCD->client),
4624 } /* END OF FUNCTION F_InvokeCommand */
4625 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
4628 /*************************************<->*************************************
4630 * GetFunctionTimestamp (pEvent)
4635 * This function is used to extract a timestamp from a key or button event.
4636 * If the event passed in is not a key or button event then a timestamp
4642 * event = pointer to an X event
4647 * RETURN = a timestamp
4649 *************************************<->***********************************/
4651 Time GetFunctionTimestamp (XButtonEvent *pEvent)
4656 (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
4657 ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
4659 time = pEvent->time;
4663 time = GetTimestamp ();
4668 } /* END OF FUNCTION GetFunctionTimestamp */
4672 ** name the event mask we need for a grab in order to find the matching
4673 ** event for an event; right now handle only button-presses
4675 static unsigned int GetEventInverseMask(XEvent *event)
4677 if ((XEvent*)NULL == event)
4679 if (ButtonPress == event->type)
4680 return ButtonReleaseMask; /* detail ? */
4682 expansion further here
4690 /*************************************<->*************************************
4692 * ClearDirtyStackEntry (pCD)
4697 * This function is used to clear the static dirtyStackEntry structure and
4698 * the dirtyLeader static variable when a pCD is destroyed. This
4699 * guarantees that freed memory will not be accessed.
4704 * pCD = pointer to clientData being freed
4711 *************************************<->***********************************/
4713 void ClearDirtyStackEntry (ClientData *pCD)
4715 if (pCD == dirtyStackEntry)
4717 dirtyStackEntry = NULL;
4721 #if defined(DEBUG) && defined(WSM)
4723 /***********************<->*************************************
4725 * F_ZZ_Debug (args, pCD, event)
4730 * This is the window manager debug (multi) function
4737 * pCD = pointer to the ClientData for the whole front panel
4739 * event = X event that invoked the function (key, button, or menu/NULL)
4744 * RETURN = if True then further button binding/function processing can
4745 * be done for the event that caused this function to be called.
4749 * Argument 1 determines the debug function to execute:
4753 * "color_server_info" - dump out color server info
4755 ******************************<->***********************************/
4758 F_ZZ_Debug (String subFcn, ClientData *pCD, XEvent *event)
4760 /* Only do something is sub function is specified */
4764 if (!(strcmp(subFcn, "dump_resources")))
4769 for (scr=0; scr<wmGD.numScreens; scr++)
4771 sprintf (szRes, "/tmp/dtwm.resources.%d", scr);
4773 XrmPutFileDatabase(XtScreenDatabase(
4774 XScreenOfDisplay(DISPLAY, scr)),
4785 /*************************************<->*************************************
4787 * F_Next_Workspace (args, pCD, event)
4792 * This function switches to the next workspace in the list
4794 *************************************<->***********************************/
4796 Boolean F_Next_Workspace (String args, ClientData *pCD, XEvent *event)
4798 WmScreenData *pSD = ACTIVE_PSD;
4801 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4803 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4810 /* check bounds and wrap */
4811 if (iwsx >= pSD->numWorkspaces)
4814 ChangeToWorkspace (&pSD->pWS[iwsx]);
4819 } /* END OF FUNCTION F_Next_Workspace */
4822 /*************************************<->*************************************
4824 * F_Prev_Workspace (args, pCD, event)
4829 * This function switches to the previous workspace in the list
4831 *************************************<->***********************************/
4833 Boolean F_Prev_Workspace (String args, ClientData *pCD, XEvent *event)
4835 WmScreenData *pSD = ACTIVE_PSD;
4838 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4840 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4847 /* check bounds and wrap */
4849 iwsx = pSD->numWorkspaces - 1;
4851 ChangeToWorkspace (&pSD->pWS[iwsx]);
4856 } /* END OF FUNCTION F_Prev_Workspace */
4860 /*************************************<->*************************************
4862 * F_Workspace_Presence (args, pCD, event)
4867 * This function pops up the workspace presence dialog box
4869 *************************************<->***********************************/
4871 Boolean F_Workspace_Presence (String args, ClientData *pCD, XEvent *event)
4873 Context wsContext = (Context)NULL;
4875 if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4877 if (pCD->clientState == NORMAL_STATE)
4879 wsContext = F_CONTEXT_NORMAL;
4881 else if (pCD->clientState == MAXIMIZED_STATE)
4883 wsContext = F_CONTEXT_MAXIMIZE;
4887 wsContext = F_CONTEXT_ICON;
4888 /* return (False); */
4890 ShowPresenceBox (pCD, wsContext);
4894 } /* END OF FUNCTION F_Workspace_Presence */
4900 WmScreenData *pSD = (ACTIVE_WS)->pSD;
4901 ClientListEntry *pCLE;
4903 fprintf (stdout, "Window stacking (bottom to top)\n");
4904 pCLE = pSD->lastClient;
4907 if (ClientInWorkspace (ACTIVE_WS, pCLE->pCD))
4908 fprintf (stdout, "* ");
4910 fprintf (stdout, " ");
4912 fprintf (stdout, "%08lx\t%s\n",
4914 pCLE->pCD->clientName);
4916 pCLE = pCLE->prevSibling;