2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$TOG: WmFunction.c /main/19 1998/04/20 13:00:48 mgreess $"
36 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY
37 * (c) Copyright 1993, 1994 International Business Machines Corp.
38 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39 * (c) Copyright 1993, 1994 Novell, Inc.
54 #include "WmWrkspace.h" /* for ClientInWorkspace() test */
55 #include <Dt/EnvControlP.h> /* for restoring **environ before an exec() */
56 #include "WmResNames.h"
57 #include <Dt/Message.h>
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(linux) || \
113 defined(sun) || defined(CSRG_BASED)) && !defined(_NFILE)
114 #define _NFILE FOPEN_MAX
116 #define CLOSE_FILES_ON_EXEC() \
117 {int ifx; for (ifx=3; ifx < _NFILE; ifx++) (void) fcntl (ifx, F_SETFD, 1);}
125 * The 'dirty' variables are used to keep track of the transient window
126 * that has been lowered via "f.lower freeFamily".
128 static ClientData *dirtyStackEntry = NULL;
129 static ClientData *dirtyLeader = NULL;
133 /***********************<->*************************************
135 * F_Action (args, pCD, event)
140 * This is the window manager function handler for invoking actions.
145 * args = action function and arguments
147 * pCD = pointer to the ClientData for the whole front panel
149 * event = X event that invoked the function (key, button, or menu/NULL)
154 * RETURN = if True then further button binding/function processing can
155 * be done for the event that caused this function to be called.
159 * The pCD->controlWindow is a temporary area used solely for
160 * this function invocation--it stores the pCW of the control
161 * that want the function to happen.
162 ******************************<->***********************************/
165 F_Action (String actionName, ClientData *pCD, XEvent *event)
168 WmActionArg *pAP = (WmActionArg *) actionName;
170 /* make sure the command runs on the right display. */
171 if (wmGD.pActiveSD->displayString)
173 putenv(wmGD.pActiveSD->displayString);
178 WmFrontPanelSetBusy (True);
182 DtActionInvoke (wmGD.pActiveSD->screenTopLevelW1,
183 pAP->actionName, pAP->aap, pAP->numArgs,
184 pAP->szExecParms, NULL, NULL, 1, NULL, NULL);
187 * Restore original DISPLAY environment variable
189 if(wmGD.pActiveSD->displayString && wmGD.displayString)
191 putenv(wmGD.displayString);
196 } /* END OF FUNCTION F_Action */
200 /******************************<->*************************************
202 * F_Beep (args, pCD, event)
207 * This is the window manager function handler for beeping.
212 * args = function arguments (specified in .mwmrc file)
214 * pCD = pointer to the client data for the client window to which the
215 * function is to be applied
217 * event = X event that invoked the function (key, button, or menu/NULL)
222 * RETURN = if True then further button binding/function processing can
223 * be done for the event that caused this function to be called.
225 ******************************<->***********************************/
227 Boolean F_Beep (String args, ClientData *pCD, XEvent *event)
230 /* !!! what is a good value for percent (the second arg) !!! */
235 } /* END OF FUNCTION F_Beep */
240 * Handle Special case where the dirty window is the top most
241 * transient window. When this is the case, raising the window
242 * that was on top (the window just below the dirty window) will
243 * fail because Mwm stack database is out of sync. So the solution
244 * is to restack the dirty transient relative to the second to the
245 * top transient. This function is used to support freeFamily stacking.
247 ClientData * FindSecondToTopTransient (pcd)
251 static ClientData *second;
253 pcdNext = pcd->transientChildren;
256 if (pcdNext->transientChildren)
258 if (!pcdNext->transientChildren->transientChildren)
262 FindSecondToTopTransient (pcdNext);
264 pcdNext = pcdNext->transientSiblings;
265 if (pcdNext && !pcdNext->transientSiblings)
273 } /* END OF FUNCTION */
277 Boolean ForceLowerWindow (ClientData *pcd)
281 WmScreenData *pSD = (ACTIVE_WS)->pSD;
283 XWindowChanges changes;
284 Boolean restack = False;
287 WmScreenData *pSD = (ACTIVE_WS)->pSD;
289 ClientListEntry *pCLE;
292 * Find lowest window in this workspace. We'll stack this transient
295 pCLE = pSD->lastClient;
300 if ((pCLE->pCD != pcd) &&
301 (ClientInWorkspace (ACTIVE_WS, pCLE->pCD)))
303 if ((pCLE->type == MINIMIZED_STATE) &&
304 (pCLE->pCD->clientState == MINIMIZED_STATE))
306 stackWindow = ICON_FRAME_WIN(pCLE->pCD);
308 else if ((pCLE->type == NORMAL_STATE) &&
309 ((pCLE->pCD->clientState == NORMAL_STATE) ||
310 (pCLE->pCD->clientState == MAXIMIZED_STATE)))
312 stackWindow = pCLE->pCD->clientFrameWin;
315 if (stackWindow != None)
318 changes.sibling = stackWindow;
322 if (stackWindow == None)
324 pCLE = pCLE->prevSibling;
329 if (pSD->lastClient->type == MINIMIZED_STATE)
331 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
335 stackWindow = pSD->lastClient->pCD->clientFrameWin;
339 changes.stack_mode = Below;
343 XConfigureWindow (DISPLAY, pcd->clientFrameWin, mask, &changes);
346 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
355 /*************************************<->*************************************
357 * F_Lower (args, pCD, event)
362 * This is the window manager function handler for bottoming a client window
368 * args = function arguments (specified in .mwmrc file)
370 * pCD = pointer to the client data for the client window to which the
371 * function is to be applied
373 * event = X event that invoked the function (key, button, or menu/NULL)
378 * RETURN = if True then further button binding/function processing can
379 * be done for the event that caused this function to be called.
381 *************************************<->***********************************/
383 Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
385 ClientListEntry *pEntry;
386 ClientListEntry *pNextEntry;
387 ClientListEntry *pStackEntry;
388 String string = args;
389 int flags = STACK_NORMAL;
391 WmWorkspaceData *pWS = ACTIVE_WS;
396 /* process '-client' argument */
397 if (string[0] == '-')
400 string = (String) GetString ((unsigned char **) &string);
403 pNextEntry = ACTIVE_PSD->lastClient;
405 (pEntry = FindClientNameMatch (pNextEntry, False,
406 string, F_GROUP_ALL)))
408 pNextEntry = pEntry->prevSibling;
410 if (ClientInWorkspace (pWS, pEntry->pCD))
413 Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
414 pStackEntry = pEntry;
420 /* process family stacking stuff */
423 unsigned int slen, len, index;
425 slen = strlen(args) - 2; /* subtract '\n' and NULL */
426 for (index = 0; index < slen; string = &args[index+1])
428 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
430 len = strlen(string);
431 if (!strcmp(string,"within"))
433 flags |= STACK_WITHIN_FAMILY;
435 else if (!strcmp(string,"freeFamily"))
437 flags |= STACK_FREE_FAMILY;
442 if (ClientInWorkspace (pWS, pCD))
445 Do_Lower (pCD, (ClientListEntry *) NULL, flags);
454 if (ClientInWorkspace (pWS, pCD))
457 Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
464 * If caused by button press, event may ALSO cause focus to be
465 * passed to this client - prepare to disable focusAutoRaise.
467 if (pCD && event && (event->type == ButtonPress))
468 pCD->focusAutoRaiseDisablePending = True;
470 wmGD.passButtonsCheck = False;
473 } /* END OF FUNCTION F_Lower */
477 /*************************************<->*************************************
479 * Do_Lower (pCD, pStackEntry)
484 * This is the window manager function handler for lowering the client window
485 * so that it does not obscure any other window above the stack entry
491 * pCD = pointer to the client data of the window (or icon) to be lowered.
493 * pStackEntry = pointer to client list entry for window that is to be
494 * below the lowered window (if NULL, window is lowered to the bottom
497 *************************************<->***********************************/
499 void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
501 Boolean restackTransients;
502 ClientData *pcdLeader;
503 WmWorkspaceData *pWS = ACTIVE_WS;
505 Boolean bLeaderRestacked;
512 * Window has been reparented into the front panel.
513 * Don't follow through on window stacking change.
519 #endif /* PANELIST */
521 if (ClientInWorkspace(pWS, pCD) &&
522 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
525 * Both clients are in the current workspace. Set
526 * client indices so that the access macros work.
528 SetClientWsIndex (pCD);
531 SetClientWsIndex (pStackEntry->pCD);
537 * One or both of the clients are not in the current workspace
544 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
546 if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
549 * If a dirtyStackEntry exists, return it to its original place
550 * in the stack (for all stacking types)
554 if (dirtyStackEntry->transientChildren ||
555 dirtyStackEntry->transientLeader)
556 RestackTransients (dirtyStackEntry);
557 dirtyStackEntry = NULL;
562 * Only restack the icon if it is not currently lowered.
567 if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
569 StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
571 MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
577 if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
579 StackWindow (pWS, &pcdLeader->iconEntry,
580 False /*on bottom*/, (ClientListEntry *) NULL);
581 MoveEntryInList (pWS, &pcdLeader->iconEntry,
582 False /*on bottom*/, (ClientListEntry *) NULL);
586 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
590 * Handle restacking of primary/secondary windows
591 * within the transient window tree.
593 bLeaderRestacked = False;
594 if ((pcdLeader->transientChildren) &&
595 (!pcdLeader->secondariesOnTop) &&
596 (!wmGD.bSuspendSecondaryRestack))
598 if (pCD == pcdLeader)
601 * Lower requested on the leader itself, insure it's
604 bLeaderRestacked = BumpPrimaryToBottom (pcdLeader);
606 else if (pCD->transientChildren)
609 * Lower requested on the leader of a subtree. Insure
610 * that this subtree leader is at the bottom of the
613 bLeaderRestacked = BumpPrimaryToBottom (pCD);
615 else if (pCD->transientLeader)
620 * Lower requested on a transient. Insure all the
621 * subtree leaders up to the top are at the bottom
622 * of their respective transient subtrees.
624 for (pcdLdr = pCD->transientLeader;
626 pcdLdr = pcdLdr->transientLeader)
628 bLeaderRestacked |= BumpPrimaryToBottom (pcdLdr);
635 * If this is a transient window then put it below its
636 * sibling transient windows.
639 restackTransients = False;
640 if (pCD->transientLeader)
644 * If freeFamily stacking, then put dirty transient window
645 * (if any) back in place before force lowering current window
646 * to the bottom of the global window stack. Then return.
649 if (flags & STACK_FREE_FAMILY)
651 /* Restore dirty transient if not current window. */
652 if ((dirtyStackEntry) &&
653 (dirtyStackEntry != pCD))
655 RestackTransients (dirtyStackEntry);
658 dirtyStackEntry = pCD;
659 dirtyLeader = pcdLeader;
661 ForceLowerWindow (pCD);
666 * Reach here only if NOT doing a f.lower freeFamily (see
667 * return; statement above). Put current transient below
668 * its sibling transient windows.
670 restackTransients = PutTransientBelowSiblings (pCD);
674 * If doing a regular f.lower and you have a dirty window, then
675 * clean up dirty transient window.
681 * If lowering a window in the same family as the dirty
682 * transient window, then just restack before lowering.
683 * Else, restore the dirty transient in place before
684 * lowering the current window. Clear dirtyStack.
686 if (dirtyLeader == pcdLeader)
688 restackTransients = True;
692 RestackTransients (dirtyStackEntry);
695 dirtyStackEntry = NULL;
699 * Only restack the window or transient window tree if it is
700 * not currently lowered and the window is not a system
706 if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
707 !(wmGD.systemModalActive &&
708 (pcdLeader == wmGD.systemModalClient)))
710 StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
712 MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
716 else if ((restackTransients) || (bLeaderRestacked))
718 else if (restackTransients)
721 RestackTransients (pCD);
726 if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
727 !(wmGD.systemModalActive &&
728 (pcdLeader == wmGD.systemModalClient)) &&
729 !(flags & STACK_WITHIN_FAMILY))
731 StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
732 (ClientListEntry *) NULL);
733 MoveEntryInList (pWS, &pcdLeader->clientEntry,
734 False /*on bottom*/, (ClientListEntry *) NULL);
737 else if ((restackTransients) || (bLeaderRestacked))
739 else if (restackTransients)
742 RestackTransients (pCD);
747 } /* END OF FUNCTION Do_Lower */
751 /*************************************<->*************************************
753 * F_CircleDown (args, pCD, event)
758 * This is the window manager function handler for moving the client window
759 * on top of stack to the bottom.
764 * args = function arguments (specified in .mwmrc file)
766 * pCD = pointer to the client data for the client window to which the
767 * function is to be applied
769 * event = X event that invoked the function (key, button, or menu/NULL)
774 * RETURN = if True then further button binding/function processing can
775 * be done for the event that caused this function to be called.
777 *************************************<->***********************************/
779 Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
782 unsigned long windowType;
783 ClientListEntry *pNextEntry;
788 * Go down through the client list looking for a window of an
789 * appropriate type that is obscuring lower windows.
792 types = (unsigned long)args;
793 pNextEntry = ACTIVE_PSD->clientList;
797 * Only check out the window if it is onscreen.
800 pcdNext = pNextEntry->pCD;
801 if (((pNextEntry->type == NORMAL_STATE) &&
802 (pcdNext->clientState != MINIMIZED_STATE)) ||
803 ((pNextEntry->type == MINIMIZED_STATE) &&
804 (pcdNext->clientState == MINIMIZED_STATE)))
806 if (pcdNext->clientState == MINIMIZED_STATE)
808 windowType = F_GROUP_ICON;
812 windowType = F_GROUP_WINDOW;
813 if (pcdNext->transientLeader || pcdNext->transientChildren)
815 windowType |= F_GROUP_TRANSIENT;
818 if (types & windowType)
820 if (CheckIfClientObscuringAny (pcdNext))
823 * This window (or window tree) is obscuring another window
824 * on the screen. Lower the window.
828 wmGD.bSuspendSecondaryRestack = True;
830 F_Lower (NULL, pcdNext, (XEvent *) NULL);
832 wmGD.bSuspendSecondaryRestack = False;
838 pNextEntry = pNextEntry->nextSibling;
843 } /* END OF FUNCTION F_Circle_Down */
847 /*************************************<->*************************************
849 * F_Circle_Up (args, pCD, event)
854 * This is the window manager function handler for moving the client window
855 * on the bottom of the stack to the top.
860 * args = function arguments (specified in .mwmrc file)
862 * pCD = pointer to the client data for the client window to which the
863 * function is to be applied
865 * event = X event that invoked the function (key, button, or menu/NULL)
870 * RETURN = if True then further button binding/function processing can
871 * be done for the event that caused this function to be called.
873 *************************************<->***********************************/
875 Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
878 unsigned long windowType;
879 ClientListEntry *pNextEntry;
884 * Go up through the client list looking for a window of an
885 * appropriate type that is obscured by higher windows.
888 types = (unsigned long)args;
889 pNextEntry = ACTIVE_PSD->lastClient;
893 * Only check out the window if it is onscreen.
896 pcdNext = pNextEntry->pCD;
897 if (((pNextEntry->type == NORMAL_STATE) &&
898 (pcdNext->clientState != MINIMIZED_STATE)) ||
899 ((pNextEntry->type == MINIMIZED_STATE) &&
900 (pcdNext->clientState == MINIMIZED_STATE)))
902 if (pcdNext->clientState == MINIMIZED_STATE)
904 windowType = F_GROUP_ICON;
908 windowType = F_GROUP_WINDOW;
909 if (pcdNext->transientLeader || pcdNext->transientChildren)
911 windowType |= F_GROUP_TRANSIENT;
914 if (types & windowType)
916 if (CheckIfClientObscuredByAny (pcdNext))
919 * This window (or window tree) is obscured by another
920 * window on the screen. Raise the window.
924 wmGD.bSuspendSecondaryRestack = True;
926 F_Raise (NULL, pcdNext, (XEvent *) NULL);
928 wmGD.bSuspendSecondaryRestack = False;
934 pNextEntry = pNextEntry->prevSibling;
940 } /* END OF FUNCTION F_Circle_Up */
944 /*************************************<->*************************************
946 * F_Focus_Color (args, pCD, event)
951 * This is the window manager function handler for setting the colormap
952 * focus to a client window or reinstalling the default colormap.
954 *************************************<->***********************************/
956 Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
959 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
964 * The window selected for the colormap focus is a top-level client
965 * window. If there are subwindow colormaps then determine if the
966 * selection was in one of the subwindows.
969 if (pCD->clientState == MINIMIZED_STATE)
971 /* !!! colormap for client supplied icon window !!! */
976 SetColormapFocus (ACTIVE_PSD, pCD);
981 } /* END OF FUNCTION F_Focus_Color */
985 /*************************************<->*************************************
987 * F_Exec (args, pCD, event)
992 * This is the window manager function handler for executing a command
995 *************************************<->***********************************/
997 Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
1004 void (*quitStat) ();
1010 /* make sure the f.exec command runs on the right display. */
1011 if (wmGD.pActiveSD->displayString)
1013 putenv(wmGD.pActiveSD->displayString);
1020 * Start the busy indicator, waiting for a pushbutton window
1021 * for the given duration
1023 WmFrontPanelSetBusy (True);
1025 #endif /* PANELIST */
1028 * Fork a process to exec a shell to run the specified command:
1032 if ((pid = fork ()) == 0)
1034 if ((pid = vfork ()) == 0)
1039 #if defined(SVR4) || defined(__OSF1__) || defined(__osf__) || defined(linux)
1048 setpgrp(tpid, tpid);
1051 #endif /* NO_SETPGRP */
1054 * Clean up window manager resources.
1055 * The X file descriptor should be automatically closed.
1059 * Fix up signal handling.
1061 RestoreDefaultSignalHandlers ();
1064 * Fix up the child application's environment NOT to
1065 * inherit the XFILESEARCHPATH, XBMLANGPATH, NLSPATH, etc.
1068 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
1070 CLOSE_FILES_ON_EXEC();
1074 * Exec the command using $MWMSHELL if set or
1075 * $SHELL if set and $MWMSHELL not set or sh.
1078 if (((shell = getenv ("MWMSHELL")) != NULL) ||
1079 ((shell = getenv ("SHELL")) != NULL))
1082 shellname = strrchr (shell, '/');
1083 if (shellname == NULL)
1086 If the shell pathname obtained from SHELL or MWMSHELL does not
1087 have a "/" in the path and if the user expects this shell to be
1088 obtained using the PATH variable rather than the current
1089 directory, then we must call execlp and not execl
1092 execlp (shell, shellname, "-c", args, NULL);
1097 execl (shell, shellname, "-c", args, NULL);
1102 * There is no SHELL environment variable or the first execl failed.
1106 execl ("/usr/bin/sh", "sh", "-c", args, NULL);
1108 execl ("/bin/sh", "sh", "-c", args, NULL);
1113 * Error - command could not be exec'ed.
1123 * Have the window manager wait for the shell to complete.
1127 intStat = (void (*)())signal (SIGINT, SIG_IGN);
1128 quitStat = (void (*)())signal (SIGQUIT, SIG_IGN);
1133 * Don't need to wait because WSM sets SIGCLD handler
1136 while ((w = wait (&status)) != pid && (w != -1));
1145 signal (SIGINT, intStat);
1146 signal (SIGQUIT, quitStat);
1150 * Restore original DISPLAY environment variable value
1151 * so a restart will start on the same screen
1154 if(wmGD.pActiveSD->displayString &&
1157 putenv(wmGD.displayString);
1164 } /* END OF FUNCTION F_Exec */
1168 /*************************************<->*************************************
1170 * F_Quit_Mwm (args, pCD, event)
1175 * This is the window manager function handler for terminating the window
1178 *************************************<->***********************************/
1180 Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
1182 if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
1184 ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
1193 } /* END OF FUNCTION F_Quit_Mwm */
1197 /*************************************<->*************************************
1199 * Do_Quit_Mwm (diedOnRestart)
1204 * Callback to do the f.quit_mwm function.
1206 *************************************<->***********************************/
1208 void Do_Quit_Mwm (Boolean diedOnRestart)
1211 ClientListEntry *pNextEntry;
1215 * Close the X connection to get all the X resources cleaned up.
1216 * !!! maybe windows should be reparented / rebordered before closing? !!!
1217 * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
1223 XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
1224 for (scr = 0; scr < wmGD.numScreens; scr++)
1226 if (wmGD.Screens[scr].managed)
1229 SaveResources(&wmGD.Screens[scr]);
1231 pNextEntry = wmGD.Screens[scr].lastClient;
1234 if (pNextEntry->type == NORMAL_STATE)
1236 if (!(pNextEntry->pCD->clientFlags &
1239 ReBorderClient (pNextEntry->pCD, diedOnRestart);
1242 pNextEntry = pNextEntry->prevSibling;
1244 #if defined(PANELIST)
1245 UnParentControls (&wmGD.Screens[scr], False);
1246 #endif /* PANELIST */
1249 XDeleteProperty(DISPLAY, wmGD.Screens[scr].rootWindow,
1255 /* shut down the messaging connection */
1259 XSync (DISPLAY, False);
1260 XCloseDisplay (DISPLAY);
1265 exit (WM_ERROR_EXIT_VALUE);
1272 } /* END OF FUNCTION Do_Quit_Mwm */
1275 /*************************************<->*************************************
1277 * ReBorderClient (pCD, reMapClient)
1282 * Restores X border for client window and reparents the
1283 * window back to the root.
1288 * pCD = pointer to the client data for the window to be re-bordered.
1290 *************************************<->***********************************/
1292 void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1296 XWindowChanges windowChanges;
1300 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1303 XUnmapWindow (DISPLAY, pCD->iconWindow);
1305 XReparentWindow (DISPLAY, pCD->iconWindow,
1306 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
1307 pCD->pWsList->iconY);
1309 XReparentWindow (DISPLAY, pCD->iconWindow,
1310 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
1323 if(wmGD.positionIsFrame)
1325 CalculateGravityOffset (pCD, &xoff, &yoff);
1326 x = pCD->clientX - xoff;
1327 y = pCD->clientY - yoff;
1335 XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1336 XReparentWindow (DISPLAY, pCD->client,
1337 ROOT_FOR_CLIENT(pCD), x, y);
1341 XMapWindow(wmGD.display, pCD->client);
1344 if (pCD->transientChildren)
1346 ReBorderClient (pCD->transientChildren, reMapClient);
1354 windowChanges.x = x;
1355 windowChanges.y = y;
1356 windowChanges.border_width = pCD->xBorderWidth;
1357 XConfigureWindow (DISPLAY, pCD->client,
1358 CWBorderWidth | CWX | CWY, &windowChanges);
1361 if (pCD->transientLeader)
1363 pCD = pCD->transientSiblings;
1371 } /* END OF FUNCTION ReBorderClient */
1375 /*************************************<->*************************************
1377 * F_Focus_Key (args, pCD, event)
1382 * This is the window manager function handler for setting the keyboard
1383 * focus to a particular client window.
1388 * args = (immediate value) focus flags
1390 * pCD = pointer to the client data
1392 * event = X event that invoked the function (key, button, or menu/NULL)
1394 *************************************<->***********************************/
1396 Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1398 long focusFlags = (long)args;
1401 if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1403 Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1404 (focusFlags | ALWAYS_SET_FOCUS));
1409 } /* END OF FUNCTION F_Focus_Key */
1412 /*************************************<->*************************************
1414 * FindSomeReasonableClient
1418 * Find a client, any client to set the focus to, return client or NULL.
1419 * This code is ripped off from AutoResetKeyFocus().
1421 *************************************<->***********************************/
1423 static Window FindSomeReasonableClient(void)
1425 ClientData *pcdNoFocus=NULL;
1427 ClientListEntry *pNextEntry;
1429 ClientData *pcdLastFocus = (ClientData *) NULL;
1430 ClientData *pcdFocus;
1431 Window focusWindow = (Window) NULL;
1434 * Scan through the list of clients to find a window to get the focus.
1437 pNextEntry = ACTIVE_PSD->clientList;
1441 pCD = pNextEntry->pCD;
1442 if (!wmGD.systemModalActive ||
1443 (wmGD.systemModalClient == pCD))
1445 if ((pNextEntry->type != MINIMIZED_STATE) &&
1446 (pCD->clientState != MINIMIZED_STATE) &&
1448 (ClientInWorkspace (ACTIVE_WS, pCD)) &&
1450 (pCD != pcdNoFocus))
1452 if (pCD->transientChildren)
1454 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1461 ((pcdLastFocus == NULL) ||
1462 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1464 pcdLastFocus = pcdFocus;
1468 pNextEntry = pNextEntry->nextSibling;
1472 * Set the focus window if one is found
1477 ClientInWorkspace (ACTIVE_WS, pcdLastFocus))
1481 focusWindow = pcdLastFocus->client;
1484 * If a client window could not be found, then just put focus
1488 if (focusWindow == (Window) NULL)
1490 pNextEntry = ACTIVE_PSD->clientList;
1494 pCD = pNextEntry->pCD;
1497 if (ClientInWorkspace (ACTIVE_WS, pCD))
1500 if ((pNextEntry->type == MINIMIZED_STATE) ||
1501 (pCD->clientState == MINIMIZED_STATE))
1503 focusWindow = ICON_FRAME_WIN(pCD);
1509 pNextEntry = pNextEntry->nextSibling;
1513 return (focusWindow);
1515 } /* END OF FUNCTION FindSomeReasonableClient */
1520 /*************************************<->*************************************
1522 * Do_Focus_Key (pCD, focusTime, flags)
1527 * This function is used to set the focus to a window. The focus indication
1528 * is not changed until the FocusIn event is received.
1533 * pCD = pointer to the client data
1535 * focusTime = focus change time
1537 * flags = wm focus change flags
1539 *************************************<->***********************************/
1541 void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1543 ClientData *pcdFocus;
1547 /* Clear the replay flag */
1548 wmGD.replayEnterEvent = False;
1553 * Make sure the client is in the current workspace
1556 (ClientInWorkspace (ACTIVE_WS, pCD)))
1561 if (pCD->clientState == MINIMIZED_STATE)
1563 focusWindow = ICON_FRAME_WIN(pCD);
1565 else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1568 * Set the keyboard focus to the indicated client window.
1569 * If the window has an application modal subordinate then
1570 * set the input focus to that window if the focus isn't
1571 * already owned by a subordinate.
1574 if (IS_APP_MODALIZED(pCD))
1576 ClientData *pcdFocusLeader,*currFocusLeader;
1579 * Handle case where a modal window exists when Mwm starts up.
1580 * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1583 if (wmGD.keyboardFocus)
1585 currFocusLeader = wmGD.keyboardFocus->transientLeader;
1589 currFocusLeader = (ClientData *) NULL;
1593 * Find focus leader for pCD
1596 pcdFocusLeader = pCD;
1597 while (pcdFocusLeader->transientLeader &&
1598 (pcdFocusLeader != currFocusLeader))
1600 pcdFocusLeader = pcdFocusLeader->transientLeader;
1603 if (pcdFocusLeader == currFocusLeader)
1605 pcdFocus = wmGD.keyboardFocus;
1610 pcdFocus = FindTransientFocus (pcdFocusLeader);
1615 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1616 * We must look at why FindTransientFocus is
1617 * returning a NULL pcd. The old code simply set
1618 * focusWindow = pcdFocus->client;
1619 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1621 * 11/26/96 rswiston - In tracking down CDExc22816, we
1622 * discovered that pCD could get tricked into thinking
1623 * it had modal transients when in fact all its transients
1624 * had been withdrawn (fixed in WithdrawTransientChildren()).
1625 * As a result, FindTransientFocus() returns wmGD.keyboardFocus;
1626 * if nobody has the focus, FindTransientFocus() returns NULL.
1630 focusWindow = pcdFocus->client;
1634 focusWindow = (wmGD.keyboardFocus) ?
1635 wmGD.keyboardFocus->client : ACTIVE_PSD->wmWorkspaceWin;
1641 * If the focus policy is "pointer" don't set the focus to a
1642 * window if it has an application modal subordinate.
1645 if (IS_APP_MODALIZED(pCD))
1648 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1650 /* Replay this later when the modal window is removed. */
1651 wmGD.replayEnterEvent = True;
1655 focusWindow = pcdFocus->client;
1662 * Set up the default (non client specific) keyboard input focus.
1665 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1667 focusWindow = PointerRoot;
1672 * The WORKSPACE_IF_NULL flag is used to prevent client
1673 * windows from flashing when deiconifying a client.
1676 if (WORKSPACE_IF_NULL & flags)
1678 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1682 /* find some reasonable client so that focus is not lost */
1684 focusWindow = FindSomeReasonableClient();
1685 if (focusWindow == (Window)NULL)
1687 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1693 if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1698 * Set the focus and/or send a take focus client message. This
1699 * is not done if a client area button press was done to set
1700 * set the focus and the window is a globally active input
1701 * style window (See ICCCM).
1704 if ( (flags & CLIENT_AREA_FOCUS) &&
1705 (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1706 ! pcdFocus->inputFocusModel &&
1707 (pcdFocus == pCD) &&
1708 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
1709 !(pcdFocus->clientState == MINIMIZED_STATE)
1714 * 1. User clicked in the client area AND
1715 * 2. Input model is Globally Active AND
1716 * 3. Keyboard focus policy is explicit
1719 /* this window has WM_TAKE_FOCUS set and InputField false. */
1720 /* just send a message. */
1721 SendClientMsg (pcdFocus->client,
1722 (long) wmGD.xa_WM_PROTOCOLS,
1723 (long) wmGD.xa_WM_TAKE_FOCUS,
1724 focusTime, NULL, 0);
1728 if ((pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1729 !(pcdFocus->clientState == MINIMIZED_STATE))
1732 * Locally Active Input Model - Send a take focus message to the client.
1735 SendClientMsg (pcdFocus->client,
1736 (long) wmGD.xa_WM_PROTOCOLS,
1737 (long) wmGD.xa_WM_TAKE_FOCUS,
1738 focusTime, NULL, 0);
1742 * Don't set the input focus if the window has input_field set
1743 * to False or has expressed an interest in WM_TAKE_FOCUS
1744 * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1745 * and the user click in the client area. If the user clicks
1746 * on the titlebar or traverses to this window via f.next_key,
1747 * set the focus so that the user can access the window menu
1751 if ( wmGD.enforceKeyFocus || /* res - default == True. */
1752 (flags & ALWAYS_SET_FOCUS) ||
1753 !(flags & CLIENT_AREA_FOCUS)|| /* clicked on frame? */
1754 pcdFocus->inputFocusModel || /* Pass.|Glob. Active */
1755 (pcdFocus->clientState == MINIMIZED_STATE)
1758 if ( !(flags & CLIENT_AREA_FOCUS) &&
1759 !pcdFocus->inputFocusModel &&
1760 !(pcdFocus->clientState == MINIMIZED_STATE))
1762 /* the window doesn't want the focus - set it to the frame */
1763 /* user clicked on the frame but we don't want the focus */
1764 /* set it to the client's frame */
1765 XSetInputFocus (DISPLAY, pcdFocus->clientBaseWin,
1766 RevertToPointerRoot, focusTime);
1768 else if ( !(flags & CLIENT_AREA_FOCUS) &&
1769 !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1770 pcdFocus->inputFocusModel
1773 XSetInputFocus (DISPLAY, focusWindow,
1774 RevertToPointerRoot, focusTime);
1778 XSetInputFocus (DISPLAY, focusWindow,
1779 RevertToParent, focusTime);
1785 * We've decided that the window shouldn't get the focus,
1786 * so don't change the focus.
1788 pcdFocus = wmGD.nextKeyboardFocus;
1794 XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1798 wmGD.nextKeyboardFocus = pcdFocus;
1802 } /* END OF FUNCTION Do_Focus_Key */
1807 /***********************<->*************************************
1809 * F_Goto_Workspace (args, pCD, event)
1813 * This is the window manager function handler for switching
1814 * to another workspace by name.
1818 * args = action function and arguments
1820 * pCD = pointer to the ClientData
1822 * event = X event that invoked the function (key, button, or menu/NULL)
1830 ******************************<->***********************************/
1832 F_Goto_Workspace (String args, ClientData *pCD, XEvent *event)
1834 WmScreenData *pSD = ACTIVE_PSD;
1839 * Compare argument against both resource name
1840 * and workspace title, take the first match.
1842 xms = XmStringCreate (args, XmFONTLIST_DEFAULT_TAG);
1843 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1845 if (!strcmp(pSD->pWS[iwsx].name, args) ||
1846 XmStringCompare (xms, pSD->pWS[iwsx].title))
1855 if (iwsx >= pSD->numWorkspaces)
1857 Warning (((char *)GETMESSAGE(26, 4,
1858 "Invalid workspace name specified for f.goto_workspace")));
1862 ChangeToWorkspace (&pSD->pWS[iwsx]);
1867 } /* END OF FUNCTION F_Goto_Workspace */
1873 /******************************<->*************************************
1875 * Boolean F_Help (String args, ClientData *pCD, XEvent *event)
1879 * Invoke help on the workspace manager
1883 * args - incoming values
1884 * pCD - associated client data structure
1885 * event - what triggered this call
1889 * Return - True if the call occurs; false otherwise.
1894 ******************************<->***********************************/
1896 F_Help (String args, ClientData *pCD, XEvent *event)
1901 rval = WmDtHelp(args);
1903 #endif /* PANELIST */
1906 } /* END OF FUNCTION F_Help */
1909 /******************************<->*************************************
1911 * Boolean F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1915 * Invoke item help on the frontpanel
1920 * pCD - associated client data structure ??
1921 * event - what triggered this call
1925 * Return - True if the call occurs; false otherwise.
1930 ******************************<->***********************************/
1932 F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1936 * Help mode event processing interferes
1937 * with slide up windows. Don't continue
1938 * if windows are sliding.
1940 if (wmGD.iSlideUpsInProgress == 0)
1942 (void) WmDtHelpMode();
1945 #endif /* PANELIST */
1947 } /* END OF FUNCTION F_Help_Mode */
1951 /******************************<->*************************************
1953 * F_Next_Key (args, pCD, event)
1958 * This is the window manager function handler for setting the keyboard
1959 * input focus to the next window in the set of managed windows.
1964 * args = (immediate value) window type flags
1966 * pCD = pointer to the client data
1968 * event = X event that invoked the function (key, button, or menu/NULL)
1970 *************************************<->***********************************/
1972 Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1974 #ifdef ROOT_ICON_MENU
1975 Boolean focused = False;
1976 #endif /* ROOT_ICON_MENU */
1977 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1979 #ifdef ROOT_ICON_MENU
1981 #endif /* ROOT_ICON_MENU */
1982 FocusNextWindow ((unsigned long)args,
1983 GetFunctionTimestamp ((XButtonEvent *)event));
1984 #ifdef ROOT_ICON_MENU
1985 if (focused && wmGD.iconClick &&
1986 event && event->type == KeyPress &&
1987 wmGD.nextKeyboardFocus &&
1988 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1989 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1992 * Post system menu from the icon
1994 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1997 #endif /* ROOT_ICON_MENU */
2002 } /* END OF FUNCTION F_Next_Key */
2006 /*************************************<->*************************************
2008 * F_Prev_Cmap (args, pCD, event)
2013 * This is the window manager function handler installing the previous
2014 * colormap in the list of client window colormaps.
2016 *************************************<->***********************************/
2018 Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
2022 pCD = ACTIVE_PSD->colormapFocus;
2025 if (pCD && (pCD->clientCmapCount > 0) &&
2026 ((pCD->clientState == NORMAL_STATE) ||
2027 (pCD->clientState == MAXIMIZED_STATE)))
2029 if (--(pCD->clientCmapIndex) < 0)
2031 pCD->clientCmapIndex = pCD->clientCmapCount - 1;
2033 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2034 if (ACTIVE_PSD->colormapFocus == pCD)
2036 #ifndef OLD_COLORMAP /* colormap */
2038 * We just re-ordered the colormaps list,
2039 * so we need to re-run the whole thing.
2041 pCD->clientCmapFlagsInitialized = 0;
2042 ProcessColormapList (ACTIVE_PSD, pCD);
2043 #else /* OSF original */
2044 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2051 } /* END OF FUNCTION F_Prev_Cmap */
2055 /*************************************<->*************************************
2057 * F_Prev_Key (args, pCD, event)
2062 * This is the window manager function handler for setting the keyboard
2063 * input focus to the previous window in the set of managed windows.
2068 * args = (immediate value) window type flags
2070 * pCD = pointer to the client data
2072 * event = X event that invoked the function (key, button, or menu/NULL)
2074 *************************************<->***********************************/
2076 Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
2078 #ifdef ROOT_ICON_MENU
2079 Boolean focused = False;
2080 #endif /* ROOT_ICON_MENU */
2081 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
2083 #ifdef ROOT_ICON_MENU
2085 #endif /* ROOT_ICON_MENU */
2086 FocusPrevWindow ((unsigned long)args,
2087 GetFunctionTimestamp ((XButtonEvent *)event));
2088 #ifdef ROOT_ICON_MENU
2089 if (focused && wmGD.iconClick &&
2090 event && event->type == KeyPress &&
2091 wmGD.nextKeyboardFocus &&
2092 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
2093 !P_ICON_BOX(wmGD.nextKeyboardFocus))
2096 * Post system menu from the icon
2098 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
2101 #endif /* ROOT_ICON_MENU */
2107 } /* END OF FUNCTION F_Prev_Key */
2111 /***********************<->*************************************
2113 * F_Post_FpMenu (args, pCD, event)
2118 * This is the window manager function handler for posting
2119 * the Front Panel window menu.
2123 * args = arguments (none)
2125 * pCD = pointer to the FP ClientData
2127 * event = X button press that invoked the function
2129 ******************************<->***********************************/
2132 F_Post_FpMenu (String args, ClientData *pCD, XEvent *event)
2134 static MenuSpec *fpMenuSpec = (MenuSpec *)NULL;
2136 if (event->type != ButtonPress)
2141 WmScreenData *pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2146 newMenuName = pCD ? pCD->systemMenu : "DtPanelMenu";
2148 for (oldSpec = pSD->menuSpecs;
2149 oldSpec != (MenuSpec *)NULL;
2150 oldSpec = oldSpec->nextMenuSpec)
2152 if (oldSpec->name && (strcmp(oldSpec->name, newMenuName) == 0))
2158 fpMenuSpec = DuplicateMenuSpec(oldSpec);
2161 * TEMPORARILY modify pSD so the new menu will be
2162 * created on DISPLAY1 instead of DISPLAY.
2164 fpMenuSpec->nextMenuSpec = pSD->menuSpecs;
2165 pSD->menuSpecs = fpMenuSpec;
2166 tmpWidget = pSD->screenTopLevelW;
2167 pSD->screenTopLevelW = pSD->screenTopLevelW1;
2169 (void)MAKE_MENU (pSD, pCD, newMenuName,
2170 F_CONTEXT_NORMAL, F_CONTEXT_NORMAL,
2171 (MenuItem *) NULL, FALSE);
2174 pSD->screenTopLevelW = tmpWidget;
2175 pSD->menuSpecs = fpMenuSpec->nextMenuSpec;
2178 PostMenu (fpMenuSpec, pCD, event->xbutton.x_root, event->xbutton.y_root,
2179 event->xbutton.button, F_CONTEXT_NORMAL, POST_AT_XY, event);
2181 _XmGetMenuState(XtParent(fpMenuSpec->menuWidget))
2182 ->MS_LastManagedMenuTime = event->xbutton.time;
2188 /***********************<->*************************************
2190 * F_Push_Recall (args, pCD, event)
2195 * This is the window manager function handler for invoking/topping
2196 * push_recall clients.
2203 * pCD = pointer to the ClientData
2205 * event = X event that invoked the function (key, button, or menu/NULL)
2210 * RETURN = if True then further button binding/function processing can
2211 * be done for the event that caused this function to be called.
2215 ******************************<->***********************************/
2218 F_Push_Recall (String args, ClientData *pCD, XEvent *event)
2220 WmPushRecallArg *pPRP;
2222 WmFpPushRecallClientData *pPRCD;
2224 pPRP = (WmPushRecallArg *) args;
2225 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2227 if (pPRP->ixReg < pSD->numPushRecallClients)
2229 /* get slot for this client */
2230 pPRCD = &(pSD->pPRCD[pPRP->ixReg]);
2233 * If the client is already running, then top it in this workspace,
2234 * else invoke the function to start it.
2238 /* Client is managed already. */
2239 if (!(ClientInWorkspace (pSD->pActiveWS, pPRCD->pCD)))
2241 WorkspaceID *wsRemoveList;
2245 * Move client to current workspace
2247 wsRemoveList = GetListOfOccupiedWorkspaces (pPRCD->pCD,
2249 RemoveClientFromWorkspaces (pPRCD->pCD, wsRemoveList,
2251 XtFree ((char *)wsRemoveList);
2252 AddClientToWorkspaces (pPRCD->pCD, &(pSD->pActiveWS->id), 1);
2253 SetClientWsIndex(pPRCD->pCD);
2254 SetClientState(pPRCD->pCD,
2255 pPRCD->pCD->clientState & ~UNSEEN_STATE, CurrentTime);
2258 /* Make this client visible */
2260 wmGD.bSuspendSecondaryRestack = True;
2262 F_Normalize_And_Raise (NULL, pPRCD->pCD, event);
2264 wmGD.bSuspendSecondaryRestack = False;
2269 struct timeval tvNow;
2271 Boolean bWaiting = False;
2273 if (pPRCD->tvTimeout.tv_sec != 0)
2275 gettimeofday (&tvNow, &tz);
2277 if ((pPRCD->tvTimeout.tv_sec > tvNow.tv_sec) ||
2278 ((pPRCD->tvTimeout.tv_sec == tvNow.tv_sec) &&
2279 (pPRCD->tvTimeout.tv_usec > tvNow.tv_usec)))
2281 /* still waiting for client to start */
2288 long clientTimeout = 0;
2291 WmPanelistObject pPanelist;
2293 pPanelist = (WmPanelistObject) pSD->wPanelist;
2295 /* invoke the function to start the client */
2296 pPRP->wmFunc ( pPRP->pArgs, pCD, event);
2298 if (pPanelist && panel.busy_light_data)
2300 /* set timeout value */
2303 XmNclientTimeoutInterval, &clientTimeout); ac++;
2304 XtGetValues (panel.busy_light_data->icon, (ArgList)al, ac);
2308 * ClientTimeout is in milliseconds, timeval values
2309 * are in seconds and microseconds.
2311 gettimeofday (&(pPRCD->tvTimeout), &tz);
2313 pPRCD->tvTimeout.tv_sec += clientTimeout / 1000;
2314 pPRCD->tvTimeout.tv_usec +=
2315 (clientTimeout % 1000) * 1000;
2317 pPRCD->tvTimeout.tv_sec += pPRCD->tvTimeout.tv_usec / 1000000;
2318 pPRCD->tvTimeout.tv_usec %= 1000000;
2325 } /* END OF FUNCTION F_Push_Recall */
2326 #endif /* PANELIST */
2329 /*************************************<->*************************************
2331 * F_Pass_Key (args, pCD, event)
2336 * This is a function stub for the f.pass_key window manager function.
2341 * args = (immediate value) window type flags
2343 * pCD = pointer to the client data
2345 * event = X event that invoked the function (key, button, or menu/NULL)
2347 *************************************<->***********************************/
2349 Boolean F_Pass_Key (args, pCD, event)
2355 if (wmGD.passKeysActive)
2358 * Get out of pass keys mode.
2361 wmGD.passKeysActive = False;
2362 wmGD.passKeysKeySpec = NULL;
2367 * Get into pass keys mode.
2370 wmGD.passKeysActive = True;
2375 } /* END OF FUNCTION F_Pass_Key */
2379 /*************************************<->*************************************
2381 * F_Maximize (args, pCD, event)
2386 * This is the window manager function handler for maximizing a client
2389 *************************************<->***********************************/
2391 Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
2393 if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
2395 SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
2396 GetFunctionTimestamp ((XButtonEvent *)event),
2397 GetEventInverseMask(event));
2402 } /* END OF FUNCTION F_Maximize */
2406 /*************************************<->*************************************
2408 * F_Menu (args, pCD, event)
2413 * This is the window manager function handler for posting a menu.
2414 * This function can only be invoked by a key or button event.
2415 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2416 * NULL when the menu is unposted.
2418 *************************************<->***********************************/
2420 Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
2423 Context menuContext;
2424 unsigned int button;
2427 long flags = POST_AT_XY;
2432 ((event->type == ButtonPress) || (event->type == ButtonRelease)))
2434 button = event->xbutton.button;
2435 x = event->xbutton.x_root;
2436 y = event->xbutton.y_root;
2437 if (event->type == ButtonRelease)
2439 flags |= POST_TRAVERSAL_ON;
2443 * Root menu, if posted with button press, then
2444 * set up to handle root menu click to make the menu
2447 else if (wmGD.rootButtonClick && (event->type == ButtonPress))
2449 if (wmGD.bReplayedButton)
2451 /* This button was replayed, it most likely dismissed
2452 a previous sticky menu, don't post a menu here */
2455 wmGD.checkHotspot = True;
2456 wmGD.hotspotRectangle.x = x - wmGD.moveThreshold/2;
2457 wmGD.hotspotRectangle.y = y - wmGD.moveThreshold/2;
2458 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2459 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2464 ((event->type == KeyPress) || (event->type == KeyRelease)))
2467 x = event->xkey.x_root;
2468 y = event->xkey.y_root;
2473 * A button or key event must be used to post a menu using this
2482 if (pCD->clientState == NORMAL_STATE)
2484 menuContext = F_CONTEXT_NORMAL;
2486 else if (pCD->clientState == MAXIMIZED_STATE)
2488 menuContext = F_CONTEXT_MAXIMIZE;
2492 menuContext = F_CONTEXT_ICON;
2494 if (P_ICON_BOX(pCD) &&
2495 event->xany.window == ICON_FRAME_WIN(pCD))
2497 if (pCD->clientState == MINIMIZED_STATE)
2499 menuContext = F_SUBCONTEXT_IB_IICON;
2503 menuContext = F_SUBCONTEXT_IB_WICON;
2509 menuContext = F_CONTEXT_ROOT;
2513 /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
2514 * This should have been done in MakeWmFunctionResources().
2517 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2518 if ((menuSpec = MAKE_MENU (pSD, pCD, args, menuContext,
2519 menuContext, (MenuItem *) NULL, FALSE)) != NULL)
2521 PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
2526 } /* END OF FUNCTION F_Menu */
2529 /*************************************<->*************************************
2531 * F_Minimize (args, pCD, event)
2536 * This is the window manager function handler for minimizing a client
2539 *************************************<->***********************************/
2541 Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
2543 ClientData *pcdLeader;
2549 * If the window is a transient then minimize the entire transient
2550 * tree including the transient leader.
2553 pcdLeader = (pCD->transientLeader) ?
2554 FindTransientTreeLeader (pCD) : pCD;
2555 if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
2557 SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
2558 GetFunctionTimestamp ((XButtonEvent *)event),
2559 GetEventInverseMask(event));
2565 } /* END OF FUNCTION F_Minimize */
2569 /*************************************<->*************************************
2571 * F_Move (args, pCD, event)
2576 * This is the window manager function handler for moving a client window
2579 *************************************<->***********************************/
2581 Boolean F_Move (String args, ClientData *pCD, XEvent *event)
2583 if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
2585 StartClientMove (pCD, event);
2586 HandleClientFrameMove (pCD, event);
2591 } /* END OF FUNCTION F_Move */
2595 /*************************************<->*************************************
2597 * F_Next_Cmap (args, pCD, event)
2602 * This is the window manager function handler installing the next
2603 * colormap in the list of client window colormaps.
2605 *************************************<->***********************************/
2607 Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
2611 pCD = ACTIVE_PSD->colormapFocus;
2614 if (pCD && (pCD->clientCmapCount > 0) &&
2615 ((pCD->clientState == NORMAL_STATE) ||
2616 (pCD->clientState == MAXIMIZED_STATE)))
2618 if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
2620 pCD->clientCmapIndex = 0;
2622 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2623 if (ACTIVE_PSD->colormapFocus == pCD)
2625 #ifndef OLD_COLORMAP /* colormap */
2627 * We just re-ordered the colormaps list,
2628 * so we need to re-run the whole thing.
2630 pCD->clientCmapFlagsInitialized = 0;
2631 ProcessColormapList (ACTIVE_PSD, pCD);
2632 #else /* OSF original */
2633 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2640 } /* END OF FUNCTION F_Next_Cmap */
2644 /*************************************<->*************************************
2646 * F_Nop (args, pCD, event)
2651 * This is the window manager function handler for doing nothing.
2653 *************************************<->***********************************/
2655 Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2660 } /* END OF FUNCTION F_Nop */
2664 /*************************************<->*************************************
2666 * F_Normalize (args, pCD, event)
2671 * This is the window manager function handler for putting a client window
2672 * in the normal state.
2674 *************************************<->***********************************/
2676 Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2681 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2682 GetFunctionTimestamp ((XButtonEvent *)event),
2683 GetEventInverseMask(event));
2688 } /* END OF FUNCTION F_Normalize */
2692 /*************************************<->*************************************
2694 * F_Normalize_And_Raise (args, pCD, event)
2699 * This is the window manager function handler for putting a client window
2700 * in the normal state and raising it from and icon.
2702 *************************************<->***********************************/
2704 Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2708 WmWorkspaceData *pWS;
2713 pSD = PSD_FOR_CLIENT (pCD);
2717 pWS = pSD->pActiveWS;
2719 if (pSD->useIconBox &&
2720 wmGD.useFrontPanel &&
2721 pSD->iconBoxControl &&
2722 (!strcmp(args, WmNiconBox)))
2725 * There's an icon box in the front panel and this is a
2726 * request to pop up the icon box.
2728 IconBoxPopUp (pWS, True);
2732 #endif /* PANELIST */
2735 if (pCD->clientState == MINIMIZED_STATE)
2737 /* normalize window */
2738 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2741 ? GetFunctionTimestamp ((XButtonEvent *)event)
2743 GetEventInverseMask(event));
2747 /* Make sure we are in NORMAL_STATE */
2748 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2749 GetFunctionTimestamp ((XButtonEvent *)event),
2750 GetEventInverseMask(event));
2752 /* Raise the window and set the keyboard focus to the window */
2754 wmGD.bSuspendSecondaryRestack = True;
2756 F_Raise (NULL, pCD, (XEvent *)NULL);
2758 wmGD.bSuspendSecondaryRestack = False;
2760 if (wmGD.raiseKeyFocus)
2762 F_Focus_Key (NULL, pCD,
2765 : ((XEvent *)NULL)));
2768 wmGD.clickData.clickPending = False;
2769 wmGD.clickData.doubleClickPending = False;
2774 } /* END OF FUNCTION F_Normalize_And_Raise */
2778 /*************************************<->*************************************
2780 * F_Restore (args, pCD, event)
2785 * This is the window manager function handler for putting a client window
2786 * in the normal state.
2788 *************************************<->***********************************/
2790 Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2797 * If current state is MAXIMIZED state then just go to NORMAL state,
2798 * otherwise (you are in MINIMIZED state) return to previous state.
2801 if (pCD->clientState == MAXIMIZED_STATE)
2803 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2804 GetFunctionTimestamp ((XButtonEvent *)event),
2805 GetEventInverseMask(event));
2811 newState = MAXIMIZED_STATE;
2815 newState = NORMAL_STATE;
2818 SetClientStateWithEventMask (pCD, newState,
2819 GetFunctionTimestamp ((XButtonEvent *)event),
2820 GetEventInverseMask(event));
2826 } /* END OF FUNCTION F_Restore */
2830 /*************************************<->*************************************
2832 * F_Restore_And_Raise (args, pCD, event)
2837 * This is the window manager function handler for putting a client window
2838 * in the normal state and raising it from and icon.
2840 *************************************<->***********************************/
2842 Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2848 if (pCD->clientState == MINIMIZED_STATE)
2850 /* Restore window */
2853 newState = MAXIMIZED_STATE;
2857 newState = NORMAL_STATE;
2860 SetClientStateWithEventMask (pCD, newState,
2863 ? GetFunctionTimestamp ((XButtonEvent *)event)
2865 GetEventInverseMask(event));
2869 /* Make sure we restore the window first */
2870 F_Restore (NULL, pCD, event);
2872 /* Raise the window and set the keyboard focus to the window */
2874 wmGD.bSuspendSecondaryRestack = True;
2876 F_Raise (NULL, pCD, (XEvent *)NULL);
2878 wmGD.bSuspendSecondaryRestack = False;
2880 if (wmGD.raiseKeyFocus)
2882 F_Focus_Key (NULL, pCD,
2885 : ((XEvent *)NULL)));
2888 wmGD.clickData.clickPending = False;
2889 wmGD.clickData.doubleClickPending = False;
2894 } /* END OF FUNCTION F_Restore_And_Raise */
2898 /*************************************<->*************************************
2900 * F_Pack_Icons (args, pCD, event)
2905 * This is the window manager function handler for packing icons in the
2906 * icon box or on the desktop.
2908 *************************************<->***********************************/
2910 Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2915 if (ACTIVE_PSD->useIconBox)
2917 pIBD = ACTIVE_WS->pIconBox;
2920 while (pCD != pIBD->pCD_iconBox)
2922 if (pIBD->pNextIconBox)
2924 pIBD = pIBD->pNextIconBox;
2935 PackIconBox (pIBD, False, False, 0, 0);
2950 } /* END OF FUNCTION F_Pack_Icons */
2953 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2954 /*************************************<->*************************************
2956 * F_Post_RMenu (args, pCD, event)
2961 * This is the window manager function handler for posting the
2963 * This function can only be invoked by a key event.
2965 *************************************<->***********************************/
2967 Boolean F_Post_RMenu (String args, ClientData *pCD, XEvent *event)
2970 unsigned int button = NoButton;
2972 long flags = POST_AT_XY;
2978 if ((event->type == KeyPress) || (event->type == KeyRelease))
2981 /* Find the root menu spec */
2982 for (rootMenu = ACTIVE_PSD->menuSpecs;
2983 rootMenu != (MenuSpec *) NULL;
2984 rootMenu = rootMenu->nextMenuSpec)
2986 if (strcmp(rootMenu->name, ACTIVE_PSD->rootMenu) == 0)
2990 /* If we couldn't find the root menu, then do nothing. */
2991 if (rootMenu == (MenuSpec *) NULL)
2996 XQueryPointer(DISPLAY, ACTIVE_ROOT,
2997 &rwin, &cwin, &x, &y, &winx, &winy, &mask);
2999 PostMenu (rootMenu, NULL, x, y, NoButton, F_CONTEXT_ROOT,
3006 } /* END OF FUNCTION F_Post_RMenu */
3007 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
3010 /*************************************<->*************************************
3012 * F_Post_SMenu (args, pCD, event)
3017 * This is the window manager function handler for posting the system menu
3018 * for the specified client.
3019 * This function can only be invoked by a key or button event.
3020 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
3021 * NULL when the menu is unposted.
3023 *************************************<->***********************************/
3025 Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
3027 Context menuContext;
3031 * An event must be used to post the system menu using this function.
3034 if (event && pCD && pCD->systemMenuSpec)
3037 * Determine whether the keyboard is posting the menu and post
3038 * the menu at an appropriate place.
3041 if (pCD->clientState == NORMAL_STATE)
3043 menuContext = F_CONTEXT_NORMAL;
3045 else if (pCD->clientState == MAXIMIZED_STATE)
3047 menuContext = F_CONTEXT_MAXIMIZE;
3051 menuContext = F_CONTEXT_ICON;
3053 if (P_ICON_BOX(pCD) &&
3054 event->xany.window == ICON_FRAME_WIN(pCD))
3056 if (pCD->clientState == MINIMIZED_STATE)
3058 menuContext = F_SUBCONTEXT_IB_IICON;
3062 menuContext = F_SUBCONTEXT_IB_WICON;
3066 if ((event->type == KeyPress) || (event->type == KeyRelease))
3069 * Set up for "sticky" menu processing if specified.
3072 if (pCD->clientState == MINIMIZED_STATE ||
3073 menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
3077 wmGD.checkHotspot = True;
3080 else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
3082 wmGD.checkHotspot = True;
3085 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
3088 else if (event->type == ButtonPress)
3092 * Root menu, if posted with button press, then
3093 * set up to handle root menu click to make the menu
3096 if (wmGD.rootButtonClick && (!wmGD.checkHotspot))
3098 wmGD.checkHotspot = True;
3099 wmGD.hotspotRectangle.x =
3100 event->xbutton.x_root - wmGD.moveThreshold/2;
3101 wmGD.hotspotRectangle.y =
3102 event->xbutton.y_root - wmGD.moveThreshold/2;
3103 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
3104 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
3107 PostMenu (pCD->systemMenuSpec, pCD,
3108 event->xbutton.x_root, event->xbutton.y_root,
3109 event->xbutton.button, menuContext, POST_AT_XY, event);
3111 else if (event->type == ButtonRelease)
3113 PostMenu (pCD->systemMenuSpec, pCD,
3114 event->xbutton.x_root, event->xbutton.y_root,
3115 event->xbutton.button, menuContext,
3116 POST_AT_XY | POST_TRAVERSAL_ON, event);
3122 } /* END OF FUNCTION F_PostSMenu */
3126 /*************************************<->*************************************
3128 * F_Kill (args, pCD, event)
3133 * This is the window manager function handler for terminating a client.
3134 * Essentially the client connection is shut down.
3136 *************************************<->***********************************/
3138 Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
3140 if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
3142 Boolean do_delete_window =
3143 pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
3144 Boolean do_save_yourself =
3145 pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
3148 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3153 * Get the widget for the subpanel
3154 * (Should be only child of the shell!)
3156 wPanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
3159 SlideSubpanelBackIn (pCD, wPanel);
3163 if (pCD->clientFlags & ICON_BOX)
3166 * When the front panel is used with the icon box,
3167 * "Close" hides the icon box into the front panel.
3169 if ((wmGD.useFrontPanel) &&
3170 (pCD->pSD->iconBoxControl) &&
3171 (IconBoxShowing(pCD->pSD->pActiveWS)))
3173 IconBoxPopUp (pCD->pSD->pActiveWS, False);
3177 #endif /* PANELIST */
3178 if (!do_delete_window && !do_save_yourself)
3180 XKillClient (DISPLAY, pCD->client);
3184 if (do_delete_window)
3187 * The client wants to be notified, not killed.
3190 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3191 (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
3195 * HP does not want to send a client message for both
3196 * delete_window AND save_yourself. The current OSF
3197 * patch did just that. This "else if" returns dtwm
3198 * to the behavior of dt 2.01
3200 else if (do_save_yourself)
3202 if (do_save_yourself)
3206 * Send a WM_SAVE_YOURSELF message and wait for a change to
3207 * the WM_COMMAND property.
3208 * !!! button and key input should be kept from the window !!!
3211 if (AddWmTimer (TIMER_QUIT,
3212 (unsigned long) wmGD.quitTimeout, pCD))
3214 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3215 (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
3217 pCD->clientFlags |= CLIENT_TERMINATING;
3221 XKillClient (DISPLAY, pCD->client);
3229 } /* END OF FUNCTION F_Kill */
3233 /*************************************<->*************************************
3235 * F_Marquee_Selection (args, pCD, event)
3240 * This is the window manager function handler for selecting
3241 * non-window manager objects on the root window.
3243 *************************************<->***********************************/
3245 Boolean F_Marquee_Selection (String args, ClientData *pCD, XEvent *event)
3250 * This function only valid in root context
3252 StartMarqueeSelect (ACTIVE_PSD, event);
3253 HandleMarqueeSelect (ACTIVE_PSD, event);
3258 } /* END OF FUNCTION F_Marquee_Selection */
3260 /*************************************<->*************************************
3262 * RefreshByClearing (win)
3267 * Recursively refresh this window and its children by doing
3270 *************************************<->***********************************/
3272 RefreshByClearing (Window win)
3276 Window root, parent;
3277 unsigned int nchildren;
3278 Window *winChildren;
3280 /* clear this window */
3281 XClearArea(DISPLAY, win, 0, 0, 0, 0, True);
3283 /* find any children and clear them, too */
3284 status = XQueryTree(DISPLAY, win, &root, &parent, &winChildren,
3288 /* recurse for each child window */
3289 for (i=0; i<nchildren; ++i)
3291 RefreshByClearing(winChildren[i]);
3296 XFree((char *)winChildren);
3302 /*************************************<->*************************************
3304 * F_Refresh (args, pCD, event)
3309 * This is the window manager function handler for causing all windows
3310 * in the workspace to be redrawn.
3312 *************************************<->***********************************/
3314 Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
3319 if (wmGD.refreshByClearing)
3321 RefreshByClearing (ACTIVE_ROOT);
3326 /* default background_pixmap is None */
3327 win = XCreateWindow (DISPLAY,
3329 (unsigned int) DisplayWidth (DISPLAY,
3331 (unsigned int) DisplayHeight (DISPLAY,
3338 (XSetWindowAttributes *)NULL);
3340 XMapWindow (DISPLAY, win);
3341 XDestroyWindow (DISPLAY, win);
3349 } /* END OF FUNCTION F_Refresh */
3353 /*************************************<->*************************************
3355 * F_Resize (args, pCD, event)
3360 * This is the window manager function handler for resizing a client window.
3362 *************************************<->***********************************/
3364 Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
3366 if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
3367 ((pCD->clientState == NORMAL_STATE) ||
3368 (pCD->clientState == MAXIMIZED_STATE)))
3370 StartClientResize (pCD, event);
3371 HandleClientFrameResize (pCD, event);
3376 } /* END OF FUNCTION F_Resize */
3380 /*************************************<->*************************************
3382 * F_Restart (args, pCD, event)
3387 * This is the window manager function handler for restarting the window
3390 *************************************<->***********************************/
3392 Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
3395 if (args && *args && !strcmp (args, DTWM_REQP_NO_CONFIRM))
3397 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3401 if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
3403 ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
3407 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3411 } /* END OF FUNCTION F_Restart */
3415 /*************************************<->*************************************
3417 * Do_Restart (dummy)
3422 * Callback function for restarting the window manager.
3424 *************************************<->***********************************/
3426 void Do_Restart (Boolean dummy)
3428 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3430 } /* END OF FUNCTION Do_Restart */
3434 /*************************************<->*************************************
3436 * RestartWm (startupFlags)
3441 * Actually restarts the window manager.
3446 * startupFlags = flags to be put into the Wm_INFO property for restart.
3448 *************************************<->***********************************/
3450 void RestartWm (long startupFlags)
3452 ClientListEntry *pNextEntry;
3456 for (scr=0; scr<wmGD.numScreens; scr++)
3458 if(wmGD.Screens[scr].managed)
3462 * Set up the _MOTIF_WM_INFO property on the root window
3463 * to indicate a restart.
3466 SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
3468 SaveResources(&wmGD.Screens[scr]);
3471 * Unmap client windows and reparent them to the root window.
3474 pNextEntry = wmGD.Screens[scr].lastClient;
3477 if (pNextEntry->type == NORMAL_STATE)
3479 if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
3481 if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
3483 XUnmapWindow (DISPLAY,
3484 pNextEntry->pCD->clientFrameWin);
3489 DeFrameClient (pNextEntry->pCD);
3492 pNextEntry = pNextEntry->prevSibling;
3494 #if defined(PANELIST)
3495 UnParentControls (&wmGD.Screens[scr], True);
3496 #endif /* PANELIST */
3502 /* shut down the messaging connection */
3508 * This fixes restart problem when going from explicit focus to
3509 * pointer focus. Window under pointer was not getting focus indication
3510 * until pointer was moved to new window, or out of and into the
3514 XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
3515 XSync (DISPLAY, False);
3518 CLOSE_FILES_ON_EXEC();
3519 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3522 * Restart the window manager with the initial arguments plus
3523 * the restart settings.
3526 execvp (*(wmGD.argv), wmGD.argv);
3529 Warning (((char *)GETMESSAGE(26, 1,
3530 "The window manager restart failed. The window manager program could not \
3531 be found or could not be executed.")));
3533 Warning ("Cannot restart the window manager");
3539 } /* END OF FUNCTION RestartWm */
3542 /*************************************<->*************************************
3544 * DeFrameClient (pCD)
3549 * Unmaps a client window (and client icon window) and reparents the
3550 * window back to the root.
3555 * pCD = pointer to the client data for the window to be de-framed.
3557 *************************************<->***********************************/
3559 void DeFrameClient (ClientData *pCD)
3563 XWindowChanges windowChanges;
3567 if (pCD->clientState != MINIMIZED_STATE)
3569 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
3572 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
3574 XUnmapWindow (DISPLAY, pCD->iconWindow);
3575 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
3577 XReparentWindow (DISPLAY, pCD->iconWindow,
3578 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
3579 pCD->pWsList->iconY);
3581 XReparentWindow (DISPLAY, pCD->iconWindow,
3582 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
3593 if(wmGD.positionIsFrame)
3595 CalculateGravityOffset (pCD, &xoff, &yoff);
3596 x = pCD->clientX - xoff;
3597 y = pCD->clientY - yoff;
3606 #ifndef UNMAP_ON_RESTART
3607 if (pCD->clientState == MINIMIZED_STATE)
3609 XUnmapWindow (DISPLAY, pCD->client);
3612 XUnmapWindow (DISPLAY, pCD->client);
3614 XRemoveFromSaveSet (DISPLAY, pCD->client);
3615 XReparentWindow (DISPLAY, pCD->client,
3616 ROOT_FOR_CLIENT(pCD), x, y);
3618 if (pCD->transientChildren)
3620 DeFrameClient (pCD->transientChildren);
3626 windowChanges.x = x;
3627 windowChanges.y = y;
3628 windowChanges.border_width = pCD->xBorderWidth;
3629 XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
3632 if (pCD->transientLeader)
3634 pCD = pCD->transientSiblings;
3642 } /* END OF FUNCTION DeFrameClient */
3644 #if defined(PANELIST)
3646 /******************************<->*************************************
3648 * F_Toggle_Front_Panel (args, pCD, event)
3653 * This is the window manager function handler for toggling the
3654 * front panel off and on.
3655 ******************************<->***********************************/
3658 F_Toggle_Front_Panel (String args, ClientData *pCD, XEvent *event)
3661 WmPanelistObject pPanelist;
3665 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3669 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3675 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3676 wmGD.windowContextType, (caddr_t *)&pCD);
3682 if (pCD->clientState & MINIMIZED_STATE)
3684 SetClientState (pCD, NORMAL_STATE,
3685 GetFunctionTimestamp ((XButtonEvent *)event));
3689 SetClientState (pCD, MINIMIZED_STATE,
3690 GetFunctionTimestamp ((XButtonEvent *)event));
3695 } /* END OF FUNCTION F_Toggle_Front_Panel */
3698 /******************************<->*************************************
3700 * Boolean F_Version (String args, ClientData *pCD, XEvent *event)
3704 * Invoke the help on version dialogue.
3708 * args - incoming values
3709 * pCD - associated client data structure
3710 * event - what triggered this call
3714 * Return - True if the call occurs; false otherwise.
3719 ******************************<->***********************************/
3721 F_Version (String args, ClientData *pCD, XEvent *event)
3724 WmPanelistObject pPanelist;
3728 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3732 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3737 WmDtHelpOnVersion (O_Shell (pPanelist));
3742 } /* END OF FUNCTION F_Version */
3743 #endif /* PANELIST */
3746 /******************************<->*************************************
3748 * F_Send_Msg (args, pCD, event)
3753 * This is the window manager function handler for sending a client
3754 * message event to a client window.
3759 * args = (immediate value) message id
3761 * pCD = pointer to the client data
3763 * event = X event that invoked the function (key, button, or menu/NULL)
3766 ******************************<->***********************************/
3768 Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
3773 if (pCD && pCD->mwmMessagesCount)
3776 * A message id must be made "active" by being included in the
3777 * _MWM_MESSAGES property before the associated message can be sent.
3780 for (i = 0; i < pCD->mwmMessagesCount; i++)
3782 if (pCD->mwmMessages[i] == (long)args)
3784 SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES,
3785 (long)args, CurrentTime, NULL, 0);
3793 } /* END OF FUNCTION F_Send_Msg */
3797 /*************************************<->*************************************
3799 * F_Separator (args, pCD, event)
3804 * This is a placeholder function; it should never be called.
3806 *************************************<->***********************************/
3808 Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
3813 } /* END OF FUNCTION F_Separator */
3816 Boolean ForceRaiseWindow (ClientData *pcd)
3820 WmScreenData *pSD = (ACTIVE_WS)->pSD;
3822 XWindowChanges changes;
3823 Boolean restack = False;
3826 if (pSD->clientList->type == MINIMIZED_STATE)
3828 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
3832 stackWindow = pSD->clientList->pCD->clientFrameWin;
3837 * Windows did not raise on regular f.raise because the raise was
3838 * not relative to another window (methinks).
3840 changes.stack_mode = Above;
3841 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
3849 /*************************************<->*************************************
3851 * F_Raise (args, pCD, event)
3856 * This is the window manager function handler for topping the client window
3857 * so that it is unobscured.
3859 *************************************<->***********************************/
3861 Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
3863 ClientListEntry *pEntry;
3864 ClientListEntry *pNextEntry;
3865 ClientListEntry *pStackEntry;
3866 String string = args;
3867 int flags = STACK_NORMAL;
3869 WmWorkspaceData *pWS = ACTIVE_WS;
3874 /* process '-client' argument */
3875 if (string[0] == '-')
3877 string = &string[1];
3878 string = (String) GetString ((unsigned char **) &string);
3881 pNextEntry = ACTIVE_PSD->clientList;
3882 while (pNextEntry &&
3883 (pEntry = FindClientNameMatch (pNextEntry, True, string,
3886 pNextEntry = pEntry->nextSibling;
3888 if (ClientInWorkspace (pWS, pEntry->pCD))
3891 Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3892 pStackEntry = pEntry;
3898 /* process family stacking stuff */
3901 unsigned int slen, len, index;
3903 slen = strlen(args) - 2; /* subtract '\n' and NULL */
3904 for (index = 0; index < slen; string = &args[index+1])
3906 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3908 len = strlen(string);
3909 if (!strcmp(string,"within"))
3911 flags |= STACK_WITHIN_FAMILY;
3913 else if (!strcmp(string,"freeFamily"))
3915 flags |= STACK_FREE_FAMILY;
3920 if (ClientInWorkspace (pWS, pCD))
3923 Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3932 if (ClientInWorkspace (pWS, pCD))
3935 Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3943 } /* END OF FUNCTION F_Raise */
3947 /*************************************<->*************************************
3949 * Do_Raise (pCD, pStackEntry)
3954 * This is the window manager function handler for topping the client window
3955 * so that it is unobscured.
3960 * pCD = pointer to the client data of the window (or icon) to be raised.
3962 * pStackEntry = pointer to client list entry for window that is to be
3963 * above the raised window (if NULL window is raised to the top of the
3966 *************************************<->***********************************/
3968 void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3970 Boolean restackTransients;
3971 ClientData *pcdLeader;
3972 WmWorkspaceData *pWS = ACTIVE_WS;
3974 Boolean bLeaderRestacked;
3981 * Window has been reparented into the front panel.
3982 * Don't follow through on window stacking change.
3987 #else /* PANELIST */
3988 #endif /* PANELIST */
3990 if (ClientInWorkspace(pWS, pCD) &&
3991 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
3994 * Both clients are in the current workspace. Set
3995 * client indices so that the access macros work.
3997 SetClientWsIndex (pCD);
4000 SetClientWsIndex (pStackEntry->pCD);
4006 * One or both of the clients are not in the current workspace
4013 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
4015 if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
4018 * Don't raise the window above the system modal window.
4021 else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
4022 !P_ICON_BOX(pcdLeader))
4025 * If a dirtyStackEntry exists, return it to its original place
4026 * in the stack (for all stacking types)
4028 if (dirtyStackEntry)
4030 if (dirtyStackEntry->transientChildren ||
4031 dirtyStackEntry->transientLeader)
4032 RestackTransients (dirtyStackEntry);
4033 dirtyStackEntry = NULL;
4038 * Only restack the icon if it is not currently raised.
4043 if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
4045 StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
4047 MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
4053 if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
4055 StackWindow (pWS, &pcdLeader->iconEntry,
4056 True /*on top*/, (ClientListEntry *) NULL);
4057 MoveEntryInList (pWS, &pcdLeader->iconEntry,
4058 True /*on top*/, (ClientListEntry *) NULL);
4062 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
4066 * Handle restacking of primary/secondary windows
4067 * within the transient window tree. Don't raise this
4068 * window above any modal transients.
4070 bLeaderRestacked = False;
4071 if ((pcdLeader->transientChildren) &&
4072 (!pCD->secondariesOnTop) &&
4073 (!wmGD.bSuspendSecondaryRestack) &&
4074 (!IS_APP_MODALIZED(pCD)))
4076 if (pCD != pcdLeader)
4079 * This is not the transient leader, make sure
4080 * the transient leader isn't on top.
4081 * (Brute force solution)
4083 bLeaderRestacked = NormalizeTransientTreeStacking (pcdLeader);
4085 if (pCD->transientChildren)
4088 * This isn't the overall leader of the transient
4089 * tree, but it does have transient's of its own.
4090 * Move it to the top of its own transient sub-tree.
4092 bLeaderRestacked |= BumpPrimaryToTop (pCD);
4098 * This is the transient leader, move it to the
4101 bLeaderRestacked = BumpPrimaryToTop (pcdLeader);
4107 * If this is a transient window then put it on top of its
4108 * sibling transient windows.
4111 restackTransients = False;
4115 * Fix for 5325 - The following code has been reorganized to cause the
4116 * action of F_Raise to match the current documentation.
4117 * The new algorithm is as follows:
4119 * if (dirtyStackEntry)
4120 * restore dirty tree
4121 * if (not withinFamily)
4122 * bring window group to the top of global stack
4124 * raise the requested window to top of family
4126 * raise requested window to top of siblings
4127 * if (need to restack windows)
4132 * If a dirtyStackEntry exists, return it to its original place
4133 * in the stack (for all stacking types)
4135 if (dirtyStackEntry)
4138 * Check to make sure that the dirty pCD has either transient
4139 * children or a transient leader. If not, do not restore
4142 if (dirtyStackEntry->transientChildren ||
4143 dirtyStackEntry->transientLeader)
4144 RestackTransients (dirtyStackEntry);
4145 dirtyStackEntry = NULL;
4150 * If the flags do not indicate "within", raise the window family
4151 * to the top of the window stack. If the window is the primary,
4152 * raise it to the top regardless of the flags.
4154 if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
4158 if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
4160 StackWindow (pWS, &pcdLeader->clientEntry,
4161 False /*below*/, pStackEntry);
4162 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4163 False /*below*/, pStackEntry);
4168 if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
4170 StackWindow (pWS, &pcdLeader->clientEntry,
4171 True /*on top*/, (ClientListEntry *) NULL);
4172 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4173 True /*on top*/, (ClientListEntry *) NULL);
4179 * If freeFamily stacking is requested, check to make sure that
4180 * the window has either a transientChild or Leader. This will
4181 * guarantee that windows that form their own family are not
4182 * labelled as dirty (what's to dirty it up?). If it has either,
4183 * raise the window to the top of the family stack.
4185 if ((flags & STACK_FREE_FAMILY) &&
4186 (pCD->transientLeader || pCD->transientChildren))
4188 dirtyStackEntry = pCD;
4189 dirtyLeader = pcdLeader;
4191 restackTransients = ForceRaiseWindow (pCD);
4195 * If withinFamily stacking is requested, put the current transient
4196 * on top of its sibling transient windows.
4200 restackTransients = PutTransientOnTop (pCD);
4203 /* At this point, if doing a regular f.raise the window family has
4204 * already been brought to the top of the stack, so nothing further
4205 * needs to be done for it.
4208 /* Restack the transients if needed */
4211 if ((restackTransients) || (bLeaderRestacked))
4213 if (restackTransients)
4216 RestackTransients (pCD);
4220 } /* END OF FUNCTION Do_Raise */
4224 /*************************************<->*************************************
4226 * F_Raise_Lower (args, pCD, event)
4231 * This window manager function tops an obscured window or icon and bottoms
4232 * a window or icon that is on top of the window stack.
4234 *************************************<->***********************************/
4236 Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
4238 ClientData *pcdLeader;
4242 pcdLeader = (pCD->transientLeader) ?
4243 FindTransientTreeLeader (pCD) : pCD;
4246 * Treat a raise/lower on a window in a transient tree as if it is
4247 * a raise/lower for the whole tree.
4250 if (CheckIfClientObscuredByAny (pcdLeader))
4253 * The window is obscured by another window, raise the window.
4257 F_Raise (NULL, pCD, (XEvent *)NULL);
4259 F_Raise (NULL, pcdLeader, (XEvent *)NULL);
4262 else if (CheckIfClientObscuringAny (pcdLeader) &&
4263 !(wmGD.systemModalActive &&
4264 (pcdLeader == wmGD.systemModalClient)))
4267 * The window is obscuring another window and is
4268 * not system modal, lower the window.
4271 F_Lower (NULL, pcdLeader, (XEvent *)NULL);
4273 if ((pcdLeader->secondariesOnTop == False) &&
4274 (pCD->transientLeader != NULL) &&
4275 (!IS_APP_MODALIZED(pcdLeader)))
4277 /* Push transient below primary */
4278 (void) BumpPrimaryToTop (pcdLeader);
4279 RestackTransients (pcdLeader);
4284 else if ((pcdLeader->secondariesOnTop == False) &&
4285 (pcdLeader->transientChildren != NULL) &&
4286 (!wmGD.systemModalActive) &&
4287 (!IS_APP_MODALIZED(pcdLeader)))
4289 if (LeaderOnTop(pcdLeader))
4291 /* Push primary below transient */
4292 (void) BumpPrimaryToBottom (pcdLeader);
4293 RestackTransients (pcdLeader);
4297 F_Raise (NULL, pCD, (XEvent *)NULL);
4298 /* Push transient below primary */
4299 (void) BumpPrimaryToTop (pcdLeader);
4300 RestackTransients (pcdLeader);
4308 } /* END OF FUNCTION F_Raise_Lower */
4312 /*************************************<->*************************************
4314 * F_Refresh_Win (args, pCD, event)
4319 * This is the window manager function handler for causing a client window
4320 * to redisplay itself.
4322 *************************************<->***********************************/
4324 Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
4329 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
4330 (pCD->clientState == MAXIMIZED_STATE)))
4332 if (pCD->clientState == NORMAL_STATE)
4334 w = (unsigned int) pCD->clientWidth;
4335 h = (unsigned int) pCD->clientHeight;
4339 w = (unsigned int) pCD->maxWidth;
4340 h = (unsigned int) pCD->maxHeight;
4344 if (wmGD.refreshByClearing)
4346 RefreshByClearing (pCD->clientFrameWin);
4351 /* default background_pixmap is None */
4352 win = XCreateWindow (DISPLAY,
4362 (XSetWindowAttributes *)NULL);
4364 XMapWindow (DISPLAY, win);
4365 XDestroyWindow (DISPLAY, win);
4374 } /* END OF FUNCTION F_Refresh_Win */
4378 /*************************************<->*************************************
4380 * F_Set_Behavior (args, pCD, event)
4385 * This function is used to switch the window manager configuration between
4386 * the built-in configuration (for CXI behavior) and the user's custom
4389 *************************************<->***********************************/
4391 Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
4394 * Go system modal in starting to do the set behavior.
4397 /* !!! grab the server and the pointer !!! */
4401 * Confirm that a set_behavior should be done.
4402 * Execute restart if so.
4405 if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
4407 ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
4408 CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
4412 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4413 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4417 } /* END OF FUNCTION F_Set_Behavior */
4421 /*************************************<->*************************************
4423 * Do_Set_Behavior (dummy)
4428 * Callback to do the f.set_behavior function.
4430 *************************************<->***********************************/
4432 void Do_Set_Behavior (Boolean dummy)
4434 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4435 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4437 } /* END OF FUNCTION Do_Set_Behavior */
4441 /*************************************<->*************************************
4443 * F_Set_Context (args, pCD, event)
4448 * This function is used to set a client context for subsequent
4451 *************************************<->***********************************/
4453 Boolean F_Set_Context (String args, ClientData *pCD, XEvent *event)
4456 wmGD.requestContextWin = (Window) args;
4459 } /* END OF FUNCTION F_Set_Context */
4463 /*************************************<->*************************************
4465 * F_Title (args, pCD, event)
4470 * This is a placeholder function; it should never be called.
4472 *************************************<->***********************************/
4474 Boolean F_Title (String args, ClientData *pCD, XEvent *event)
4479 } /* END OF FUNCTION F_Title */
4483 /******************************<->*************************************
4485 * F_Screen (args, pCD, event)
4490 * This is the window manager function handler for warping to screens
4495 * args = (immediate value) window type flags
4497 * pCD = pointer to the client data
4499 * event = X event that invoked the function (key, button, or menu/NULL)
4501 * NOTE: May want to consider tracking changes in screen because in
4502 * managing a new window (ie. in ManageWindow()).
4506 * RETURN = if True then further button binding/function processing can
4507 * be done for the event that caused this function to be called.
4509 *************************************<->***********************************/
4511 Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
4515 unsigned int dummask;
4516 WmScreenData *newscr = NULL;
4518 static int PreviousScreen = -1;
4522 if (PreviousScreen == -1)
4524 PreviousScreen = DefaultScreen(DISPLAY);
4527 if (strcmp (args, "next") == 0)
4529 scr = ACTIVE_PSD->screen + 1;
4532 else if (strcmp (args, "prev") == 0)
4534 scr = ACTIVE_PSD->screen - 1;
4537 else if (strcmp (args, "back") == 0)
4539 scr = PreviousScreen;
4551 scr = wmGD.numScreens - 1;
4552 else if (scr >= wmGD.numScreens)
4555 newscr = &(wmGD.Screens[scr]);
4556 if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
4557 if (inc) { /* walk around the list */
4562 "Unable to warp to unmanaged screen %d\n", scr);
4569 if (ACTIVE_PSD->screen == scr) return (False); /* already on that screen */
4571 PreviousScreen = ACTIVE_PSD->screen;
4572 XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
4573 &dumint, &dumint, &dummask);
4575 XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
4577 if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
4580 * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can
4581 * uses the new screen instead of the old screen. Then call
4582 * Do_Focus_Key with a NULL pCD to find a reasonable client to
4585 SetActiveScreen (newscr);
4586 Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
4595 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
4596 /*************************************<->*************************************
4598 * F_InvokeCommand (args, pCD, event)
4603 * This is the window manager function for invoking client inserted menu
4606 *************************************<->***********************************/
4608 Boolean F_InvokeCommand (String args, ClientData *pCD, XEvent *event)
4610 CARD32 commandID, clientWindow;
4611 Atom notifySelection;
4613 if (args == (String) NULL) return(FALSE);
4615 if (sscanf(args, "%d %d %ld", &commandID, &clientWindow,
4616 ¬ifySelection) != 3)
4619 SendInvokeMessage(commandID,
4620 (pCD == (ClientData *) NULL ? 0 : pCD->client),
4625 } /* END OF FUNCTION F_InvokeCommand */
4626 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
4629 /*************************************<->*************************************
4631 * GetFunctionTimestamp (pEvent)
4636 * This function is used to extract a timestamp from a key or button event.
4637 * If the event passed in is not a key or button event then a timestamp
4643 * event = pointer to an X event
4648 * RETURN = a timestamp
4650 *************************************<->***********************************/
4652 Time GetFunctionTimestamp (XButtonEvent *pEvent)
4657 (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
4658 ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
4660 time = pEvent->time;
4664 time = GetTimestamp ();
4669 } /* END OF FUNCTION GetFunctionTimestamp */
4673 ** name the event mask we need for a grab in order to find the matching
4674 ** event for an event; right now handle only button-presses
4676 static unsigned int GetEventInverseMask(XEvent *event)
4678 if ((XEvent*)NULL == event)
4680 if (ButtonPress == event->type)
4681 return ButtonReleaseMask; /* detail ? */
4683 expansion further here
4691 /*************************************<->*************************************
4693 * ClearDirtyStackEntry (pCD)
4698 * This function is used to clear the static dirtyStackEntry structure and
4699 * the dirtyLeader static variable when a pCD is destroyed. This
4700 * guarantees that freed memory will not be accessed.
4705 * pCD = pointer to clientData being freed
4712 *************************************<->***********************************/
4714 void ClearDirtyStackEntry (ClientData *pCD)
4716 if (pCD == dirtyStackEntry)
4718 dirtyStackEntry = NULL;
4722 #if defined(DEBUG) && defined(WSM)
4724 /***********************<->*************************************
4726 * F_ZZ_Debug (args, pCD, event)
4731 * This is the window manager debug (multi) function
4738 * pCD = pointer to the ClientData for the whole front panel
4740 * event = X event that invoked the function (key, button, or menu/NULL)
4745 * RETURN = if True then further button binding/function processing can
4746 * be done for the event that caused this function to be called.
4750 * Argument 1 determines the debug function to execute:
4754 * "color_server_info" - dump out color server info
4756 ******************************<->***********************************/
4759 F_ZZ_Debug (String subFcn, ClientData *pCD, XEvent *event)
4761 /* Only do something is sub function is specified */
4765 if (!(strcmp(subFcn, "dump_resources")))
4770 for (scr=0; scr<wmGD.numScreens; scr++)
4772 sprintf (szRes, "/tmp/dtwm.resources.%d", scr);
4774 XrmPutFileDatabase(XtScreenDatabase(
4775 XScreenOfDisplay(DISPLAY, scr)),
4786 /*************************************<->*************************************
4788 * F_Next_Workspace (args, pCD, event)
4793 * This function switches to the next workspace in the list
4795 *************************************<->***********************************/
4797 Boolean F_Next_Workspace (String args, ClientData *pCD, XEvent *event)
4799 WmScreenData *pSD = ACTIVE_PSD;
4802 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4804 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4811 /* check bounds and wrap */
4812 if (iwsx >= pSD->numWorkspaces)
4815 ChangeToWorkspace (&pSD->pWS[iwsx]);
4820 } /* END OF FUNCTION F_Next_Workspace */
4823 /*************************************<->*************************************
4825 * F_Prev_Workspace (args, pCD, event)
4830 * This function switches to the previous workspace in the list
4832 *************************************<->***********************************/
4834 Boolean F_Prev_Workspace (String args, ClientData *pCD, XEvent *event)
4836 WmScreenData *pSD = ACTIVE_PSD;
4839 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4841 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4848 /* check bounds and wrap */
4850 iwsx = pSD->numWorkspaces - 1;
4852 ChangeToWorkspace (&pSD->pWS[iwsx]);
4857 } /* END OF FUNCTION F_Prev_Workspace */
4861 /*************************************<->*************************************
4863 * F_Workspace_Presence (args, pCD, event)
4868 * This function pops up the workspace presence dialog box
4870 *************************************<->***********************************/
4872 Boolean F_Workspace_Presence (String args, ClientData *pCD, XEvent *event)
4874 Context wsContext = (Context)NULL;
4876 if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4878 if (pCD->clientState == NORMAL_STATE)
4880 wsContext = F_CONTEXT_NORMAL;
4882 else if (pCD->clientState == MAXIMIZED_STATE)
4884 wsContext = F_CONTEXT_MAXIMIZE;
4888 wsContext = F_CONTEXT_ICON;
4889 /* return (False); */
4891 ShowPresenceBox (pCD, wsContext);
4895 } /* END OF FUNCTION F_Workspace_Presence */
4901 WmScreenData *pSD = (ACTIVE_WS)->pSD;
4902 ClientListEntry *pCLE;
4904 fprintf (stdout, "Window stacking (bottom to top)\n");
4905 pCLE = pSD->lastClient;
4908 if (ClientInWorkspace (ACTIVE_WS, pCLE->pCD))
4909 fprintf (stdout, "* ");
4911 fprintf (stdout, " ");
4913 fprintf (stdout, "%08lx\t%s\n",
4915 pCLE->pCD->clientName);
4917 pCLE = pCLE->prevSibling;