2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$TOG: WmFunction.c /main/19 1998/04/20 13:00:48 mgreess $"
36 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY
37 * (c) Copyright 1993, 1994 International Business Machines Corp.
38 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39 * (c) Copyright 1993, 1994 Novell, Inc.
54 #include "WmWrkspace.h" /* for ClientInWorkspace() test */
55 #include <Dt/EnvControlP.h> /* for restoring **environ before an exec() */
56 #include "WmResNames.h"
57 #include <Dt/Message.h>
61 #include <Dt/DtStrDefs.h>
67 * include extern functions
69 #include "WmFunction.h"
75 #include "WmColormap.h"
78 #include "WmFeedback.h"
83 #include "WmIconBox.h"
84 #include "WmKeyFocus.h"
87 #include "WmPresence.h"
89 #include "WmProperty.h"
90 #include "WmProtocol.h"
91 #include "WmResParse.h"
92 #include "WmWinConf.h"
93 #include "WmWinInfo.h"
94 #include "WmWinList.h"
95 #include "WmWinState.h"
98 #include <Xm/RowColumnP.h> /* for MS_LastManagedMenuTime */
99 extern XmMenuState _XmGetMenuState();
101 extern int putenv ();
102 extern char * getenv ();
104 extern pid_t vfork();
105 #endif /* PORT_NOVFORK */
107 static unsigned int GetEventInverseMask(XEvent *event);
111 #if (defined(USL) || defined(__uxp__) || defined(linux) || defined(CSRG_BASED)) && !defined(_NFILE)
112 #define _NFILE FOPEN_MAX
114 #define CLOSE_FILES_ON_EXEC() \
115 {int ifx; for (ifx=3; ifx < _NFILE; ifx++) (void) fcntl (ifx, F_SETFD, 1);}
123 * The 'dirty' variables are used to keep track of the transient window
124 * that has been lowered via "f.lower freeFamily".
126 static ClientData *dirtyStackEntry = NULL;
127 static ClientData *dirtyLeader = NULL;
131 /***********************<->*************************************
133 * F_Action (args, pCD, event)
138 * This is the window manager function handler for invoking actions.
143 * args = action function and arguments
145 * pCD = pointer to the ClientData for the whole front panel
147 * event = X event that invoked the function (key, button, or menu/NULL)
152 * RETURN = if True then further button binding/function processing can
153 * be done for the event that caused this function to be called.
157 * The pCD->controlWindow is a temporary area used solely for
158 * this function invocation--it stores the pCW of the control
159 * that want the function to happen.
160 ******************************<->***********************************/
163 F_Action (String actionName, ClientData *pCD, XEvent *event)
166 WmActionArg *pAP = (WmActionArg *) actionName;
168 /* make sure the command runs on the right display. */
169 if (wmGD.pActiveSD->displayString)
171 putenv(wmGD.pActiveSD->displayString);
176 WmFrontPanelSetBusy (True);
180 DtActionInvoke (wmGD.pActiveSD->screenTopLevelW1,
181 pAP->actionName, pAP->aap, pAP->numArgs,
182 pAP->szExecParms, NULL, NULL, 1, NULL, NULL);
185 * Restore original DISPLAY environment variable
187 if(wmGD.pActiveSD->displayString && wmGD.displayString)
189 putenv(wmGD.displayString);
194 } /* END OF FUNCTION F_Action */
198 /******************************<->*************************************
200 * F_Beep (args, pCD, event)
205 * This is the window manager function handler for beeping.
210 * args = function arguments (specified in .mwmrc file)
212 * pCD = pointer to the client data for the client window to which the
213 * function is to be applied
215 * event = X event that invoked the function (key, button, or menu/NULL)
220 * RETURN = if True then further button binding/function processing can
221 * be done for the event that caused this function to be called.
223 ******************************<->***********************************/
225 Boolean F_Beep (String args, ClientData *pCD, XEvent *event)
228 /* !!! what is a good value for percent (the second arg) !!! */
233 } /* END OF FUNCTION F_Beep */
238 * Handle Special case where the dirty window is the top most
239 * transient window. When this is the case, raising the window
240 * that was on top (the window just below the dirty window) will
241 * fail because Mwm stack database is out of sync. So the solution
242 * is to restack the dirty transient relative to the second to the
243 * top transient. This function is used to support freeFamily stacking.
245 ClientData * FindSecondToTopTransient (pcd)
249 static ClientData *second;
251 pcdNext = pcd->transientChildren;
254 if (pcdNext->transientChildren)
256 if (!pcdNext->transientChildren->transientChildren)
260 FindSecondToTopTransient (pcdNext);
262 pcdNext = pcdNext->transientSiblings;
263 if (pcdNext && !pcdNext->transientSiblings)
271 } /* END OF FUNCTION */
275 Boolean ForceLowerWindow (ClientData *pcd)
279 WmScreenData *pSD = (ACTIVE_WS)->pSD;
281 XWindowChanges changes;
282 Boolean restack = False;
285 WmScreenData *pSD = (ACTIVE_WS)->pSD;
287 ClientListEntry *pCLE;
290 * Find lowest window in this workspace. We'll stack this transient
293 pCLE = pSD->lastClient;
298 if ((pCLE->pCD != pcd) &&
299 (ClientInWorkspace (ACTIVE_WS, pCLE->pCD)))
301 if ((pCLE->type == MINIMIZED_STATE) &&
302 (pCLE->pCD->clientState == MINIMIZED_STATE))
304 stackWindow = ICON_FRAME_WIN(pCLE->pCD);
306 else if ((pCLE->type == NORMAL_STATE) &&
307 ((pCLE->pCD->clientState == NORMAL_STATE) ||
308 (pCLE->pCD->clientState == MAXIMIZED_STATE)))
310 stackWindow = pCLE->pCD->clientFrameWin;
313 if (stackWindow != None)
316 changes.sibling = stackWindow;
320 if (stackWindow == None)
322 pCLE = pCLE->prevSibling;
327 if (pSD->lastClient->type == MINIMIZED_STATE)
329 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
333 stackWindow = pSD->lastClient->pCD->clientFrameWin;
337 changes.stack_mode = Below;
341 XConfigureWindow (DISPLAY, pcd->clientFrameWin, mask, &changes);
344 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
353 /*************************************<->*************************************
355 * F_Lower (args, pCD, event)
360 * This is the window manager function handler for bottoming a client window
366 * args = function arguments (specified in .mwmrc file)
368 * pCD = pointer to the client data for the client window to which the
369 * function is to be applied
371 * event = X event that invoked the function (key, button, or menu/NULL)
376 * RETURN = if True then further button binding/function processing can
377 * be done for the event that caused this function to be called.
379 *************************************<->***********************************/
381 Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
383 ClientListEntry *pEntry;
384 ClientListEntry *pNextEntry;
385 ClientListEntry *pStackEntry;
386 String string = args;
387 int flags = STACK_NORMAL;
389 WmWorkspaceData *pWS = ACTIVE_WS;
394 /* process '-client' argument */
395 if (string[0] == '-')
398 string = (String) GetString ((unsigned char **) &string);
401 pNextEntry = ACTIVE_PSD->lastClient;
403 (pEntry = FindClientNameMatch (pNextEntry, False,
404 string, F_GROUP_ALL)))
406 pNextEntry = pEntry->prevSibling;
408 if (ClientInWorkspace (pWS, pEntry->pCD))
411 Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
412 pStackEntry = pEntry;
418 /* process family stacking stuff */
421 unsigned int slen, len, index;
423 slen = strlen(args) - 2; /* subtract '\n' and NULL */
424 for (index = 0; index < slen; string = &args[index+1])
426 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
428 len = strlen(string);
429 if (!strcmp(string,"within"))
431 flags |= STACK_WITHIN_FAMILY;
433 else if (!strcmp(string,"freeFamily"))
435 flags |= STACK_FREE_FAMILY;
440 if (ClientInWorkspace (pWS, pCD))
443 Do_Lower (pCD, (ClientListEntry *) NULL, flags);
452 if (ClientInWorkspace (pWS, pCD))
455 Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
462 * If caused by button press, event may ALSO cause focus to be
463 * passed to this client - prepare to disable focusAutoRaise.
465 if (pCD && event && (event->type == ButtonPress))
466 pCD->focusAutoRaiseDisablePending = True;
468 wmGD.passButtonsCheck = False;
471 } /* END OF FUNCTION F_Lower */
475 /*************************************<->*************************************
477 * Do_Lower (pCD, pStackEntry)
482 * This is the window manager function handler for lowering the client window
483 * so that it does not obscure any other window above the stack entry
489 * pCD = pointer to the client data of the window (or icon) to be lowered.
491 * pStackEntry = pointer to client list entry for window that is to be
492 * below the lowered window (if NULL, window is lowered to the bottom
495 *************************************<->***********************************/
497 void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
499 Boolean restackTransients;
500 ClientData *pcdLeader;
501 WmWorkspaceData *pWS = ACTIVE_WS;
503 Boolean bLeaderRestacked;
510 * Window has been reparented into the front panel.
511 * Don't follow through on window stacking change.
517 #endif /* PANELIST */
519 if (ClientInWorkspace(pWS, pCD) &&
520 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
523 * Both clients are in the current workspace. Set
524 * client indices so that the access macros work.
526 SetClientWsIndex (pCD);
529 SetClientWsIndex (pStackEntry->pCD);
535 * One or both of the clients are not in the current workspace
542 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
544 if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
547 * If a dirtyStackEntry exists, return it to its original place
548 * in the stack (for all stacking types)
552 if (dirtyStackEntry->transientChildren ||
553 dirtyStackEntry->transientLeader)
554 RestackTransients (dirtyStackEntry);
555 dirtyStackEntry = NULL;
560 * Only restack the icon if it is not currently lowered.
565 if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
567 StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
569 MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
575 if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
577 StackWindow (pWS, &pcdLeader->iconEntry,
578 False /*on bottom*/, (ClientListEntry *) NULL);
579 MoveEntryInList (pWS, &pcdLeader->iconEntry,
580 False /*on bottom*/, (ClientListEntry *) NULL);
584 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
588 * Handle restacking of primary/secondary windows
589 * within the transient window tree.
591 bLeaderRestacked = False;
592 if ((pcdLeader->transientChildren) &&
593 (!pcdLeader->secondariesOnTop) &&
594 (!wmGD.bSuspendSecondaryRestack))
596 if (pCD == pcdLeader)
599 * Lower requested on the leader itself, insure it's
602 bLeaderRestacked = BumpPrimaryToBottom (pcdLeader);
604 else if (pCD->transientChildren)
607 * Lower requested on the leader of a subtree. Insure
608 * that this subtree leader is at the bottom of the
611 bLeaderRestacked = BumpPrimaryToBottom (pCD);
613 else if (pCD->transientLeader)
618 * Lower requested on a transient. Insure all the
619 * subtree leaders up to the top are at the bottom
620 * of their respective transient subtrees.
622 for (pcdLdr = pCD->transientLeader;
624 pcdLdr = pcdLdr->transientLeader)
626 bLeaderRestacked |= BumpPrimaryToBottom (pcdLdr);
633 * If this is a transient window then put it below its
634 * sibling transient windows.
637 restackTransients = False;
638 if (pCD->transientLeader)
642 * If freeFamily stacking, then put dirty transient window
643 * (if any) back in place before force lowering current window
644 * to the bottom of the global window stack. Then return.
647 if (flags & STACK_FREE_FAMILY)
649 /* Restore dirty transient if not current window. */
650 if ((dirtyStackEntry) &&
651 (dirtyStackEntry != pCD))
653 RestackTransients (dirtyStackEntry);
656 dirtyStackEntry = pCD;
657 dirtyLeader = pcdLeader;
659 ForceLowerWindow (pCD);
664 * Reach here only if NOT doing a f.lower freeFamily (see
665 * return; statement above). Put current transient below
666 * its sibling transient windows.
668 restackTransients = PutTransientBelowSiblings (pCD);
672 * If doing a regular f.lower and you have a dirty window, then
673 * clean up dirty transient window.
679 * If lowering a window in the same family as the dirty
680 * transient window, then just restack before lowering.
681 * Else, restore the dirty transient in place before
682 * lowering the current window. Clear dirtyStack.
684 if (dirtyLeader == pcdLeader)
686 restackTransients = True;
690 RestackTransients (dirtyStackEntry);
693 dirtyStackEntry = NULL;
697 * Only restack the window or transient window tree if it is
698 * not currently lowered and the window is not a system
704 if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
705 !(wmGD.systemModalActive &&
706 (pcdLeader == wmGD.systemModalClient)))
708 StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
710 MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
714 else if ((restackTransients) || (bLeaderRestacked))
716 else if (restackTransients)
719 RestackTransients (pCD);
724 if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
725 !(wmGD.systemModalActive &&
726 (pcdLeader == wmGD.systemModalClient)) &&
727 !(flags & STACK_WITHIN_FAMILY))
729 StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
730 (ClientListEntry *) NULL);
731 MoveEntryInList (pWS, &pcdLeader->clientEntry,
732 False /*on bottom*/, (ClientListEntry *) NULL);
735 else if ((restackTransients) || (bLeaderRestacked))
737 else if (restackTransients)
740 RestackTransients (pCD);
745 } /* END OF FUNCTION Do_Lower */
749 /*************************************<->*************************************
751 * F_CircleDown (args, pCD, event)
756 * This is the window manager function handler for moving the client window
757 * on top of stack to the bottom.
762 * args = function arguments (specified in .mwmrc file)
764 * pCD = pointer to the client data for the client window to which the
765 * function is to be applied
767 * event = X event that invoked the function (key, button, or menu/NULL)
772 * RETURN = if True then further button binding/function processing can
773 * be done for the event that caused this function to be called.
775 *************************************<->***********************************/
777 Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
780 unsigned long windowType;
781 ClientListEntry *pNextEntry;
786 * Go down through the client list looking for a window of an
787 * appropriate type that is obscuring lower windows.
790 types = (unsigned long)args;
791 pNextEntry = ACTIVE_PSD->clientList;
795 * Only check out the window if it is onscreen.
798 pcdNext = pNextEntry->pCD;
799 if (((pNextEntry->type == NORMAL_STATE) &&
800 (pcdNext->clientState != MINIMIZED_STATE)) ||
801 ((pNextEntry->type == MINIMIZED_STATE) &&
802 (pcdNext->clientState == MINIMIZED_STATE)))
804 if (pcdNext->clientState == MINIMIZED_STATE)
806 windowType = F_GROUP_ICON;
810 windowType = F_GROUP_WINDOW;
811 if (pcdNext->transientLeader || pcdNext->transientChildren)
813 windowType |= F_GROUP_TRANSIENT;
816 if (types & windowType)
818 if (CheckIfClientObscuringAny (pcdNext))
821 * This window (or window tree) is obscuring another window
822 * on the screen. Lower the window.
826 wmGD.bSuspendSecondaryRestack = True;
828 F_Lower (NULL, pcdNext, (XEvent *) NULL);
830 wmGD.bSuspendSecondaryRestack = False;
836 pNextEntry = pNextEntry->nextSibling;
841 } /* END OF FUNCTION F_Circle_Down */
845 /*************************************<->*************************************
847 * F_Circle_Up (args, pCD, event)
852 * This is the window manager function handler for moving the client window
853 * on the bottom of the stack to the top.
858 * args = function arguments (specified in .mwmrc file)
860 * pCD = pointer to the client data for the client window to which the
861 * function is to be applied
863 * event = X event that invoked the function (key, button, or menu/NULL)
868 * RETURN = if True then further button binding/function processing can
869 * be done for the event that caused this function to be called.
871 *************************************<->***********************************/
873 Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
876 unsigned long windowType;
877 ClientListEntry *pNextEntry;
882 * Go up through the client list looking for a window of an
883 * appropriate type that is obscured by higher windows.
886 types = (unsigned long)args;
887 pNextEntry = ACTIVE_PSD->lastClient;
891 * Only check out the window if it is onscreen.
894 pcdNext = pNextEntry->pCD;
895 if (((pNextEntry->type == NORMAL_STATE) &&
896 (pcdNext->clientState != MINIMIZED_STATE)) ||
897 ((pNextEntry->type == MINIMIZED_STATE) &&
898 (pcdNext->clientState == MINIMIZED_STATE)))
900 if (pcdNext->clientState == MINIMIZED_STATE)
902 windowType = F_GROUP_ICON;
906 windowType = F_GROUP_WINDOW;
907 if (pcdNext->transientLeader || pcdNext->transientChildren)
909 windowType |= F_GROUP_TRANSIENT;
912 if (types & windowType)
914 if (CheckIfClientObscuredByAny (pcdNext))
917 * This window (or window tree) is obscured by another
918 * window on the screen. Raise the window.
922 wmGD.bSuspendSecondaryRestack = True;
924 F_Raise (NULL, pcdNext, (XEvent *) NULL);
926 wmGD.bSuspendSecondaryRestack = False;
932 pNextEntry = pNextEntry->prevSibling;
938 } /* END OF FUNCTION F_Circle_Up */
942 /*************************************<->*************************************
944 * F_Focus_Color (args, pCD, event)
949 * This is the window manager function handler for setting the colormap
950 * focus to a client window or reinstalling the default colormap.
952 *************************************<->***********************************/
954 Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
957 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
962 * The window selected for the colormap focus is a top-level client
963 * window. If there are subwindow colormaps then determine if the
964 * selection was in one of the subwindows.
967 if (pCD->clientState == MINIMIZED_STATE)
969 /* !!! colormap for client supplied icon window !!! */
974 SetColormapFocus (ACTIVE_PSD, pCD);
979 } /* END OF FUNCTION F_Focus_Color */
983 /*************************************<->*************************************
985 * F_Exec (args, pCD, event)
990 * This is the window manager function handler for executing a command
993 *************************************<->***********************************/
995 Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
1002 void (*quitStat) ();
1008 /* make sure the f.exec command runs on the right display. */
1009 if (wmGD.pActiveSD->displayString)
1011 putenv(wmGD.pActiveSD->displayString);
1018 * Start the busy indicator, waiting for a pushbutton window
1019 * for the given duration
1021 WmFrontPanelSetBusy (True);
1023 #endif /* PANELIST */
1026 * Fork a process to exec a shell to run the specified command:
1030 if ((pid = fork ()) == 0)
1032 if ((pid = vfork ()) == 0)
1037 #if defined(SVR4) || defined(__OSF1__) || defined(__osf__) || defined(linux)
1046 setpgrp(tpid, tpid);
1049 #endif /* NO_SETPGRP */
1052 * Clean up window manager resources.
1053 * The X file descriptor should be automatically closed.
1057 * Fix up signal handling.
1059 RestoreDefaultSignalHandlers ();
1062 * Fix up the child application's environment NOT to
1063 * inherit the XFILESEARCHPATH, XBMLANGPATH, NLSPATH, etc.
1066 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
1068 CLOSE_FILES_ON_EXEC();
1072 * Exec the command using $MWMSHELL if set or
1073 * $SHELL if set and $MWMSHELL not set or sh.
1076 if (((shell = getenv ("MWMSHELL")) != NULL) ||
1077 ((shell = getenv ("SHELL")) != NULL))
1080 shellname = strrchr (shell, '/');
1081 if (shellname == NULL)
1084 If the shell pathname obtained from SHELL or MWMSHELL does not
1085 have a "/" in the path and if the user expects this shell to be
1086 obtained using the PATH variable rather than the current
1087 directory, then we must call execlp and not execl
1090 execlp (shell, shellname, "-c", args, 0);
1095 execl (shell, shellname, "-c", args, 0);
1100 * There is no SHELL environment variable or the first execl failed.
1104 execl ("/usr/bin/sh", "sh", "-c", args, 0);
1106 execl ("/bin/sh", "sh", "-c", args, 0);
1111 * Error - command could not be exec'ed.
1121 * Have the window manager wait for the shell to complete.
1125 intStat = (void (*)())signal (SIGINT, SIG_IGN);
1126 quitStat = (void (*)())signal (SIGQUIT, SIG_IGN);
1131 * Don't need to wait because WSM sets SIGCLD handler
1134 while ((w = wait (&status)) != pid && (w != -1));
1143 signal (SIGINT, intStat);
1144 signal (SIGQUIT, quitStat);
1148 * Restore original DISPLAY environment variable value
1149 * so a restart will start on the same screen
1152 if(wmGD.pActiveSD->displayString &&
1155 putenv(wmGD.displayString);
1162 } /* END OF FUNCTION F_Exec */
1166 /*************************************<->*************************************
1168 * F_Quit_Mwm (args, pCD, event)
1173 * This is the window manager function handler for terminating the window
1176 *************************************<->***********************************/
1178 Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
1180 if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
1182 ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
1191 } /* END OF FUNCTION F_Quit_Mwm */
1195 /*************************************<->*************************************
1197 * Do_Quit_Mwm (diedOnRestart)
1202 * Callback to do the f.quit_mwm function.
1204 *************************************<->***********************************/
1206 void Do_Quit_Mwm (Boolean diedOnRestart)
1209 ClientListEntry *pNextEntry;
1213 * Close the X connection to get all the X resources cleaned up.
1214 * !!! maybe windows should be reparented / rebordered before closing? !!!
1215 * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
1221 XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
1222 for (scr = 0; scr < wmGD.numScreens; scr++)
1224 if (wmGD.Screens[scr].managed)
1227 SaveResources(&wmGD.Screens[scr]);
1229 pNextEntry = wmGD.Screens[scr].lastClient;
1232 if (pNextEntry->type == NORMAL_STATE)
1234 if (!(pNextEntry->pCD->clientFlags &
1237 ReBorderClient (pNextEntry->pCD, diedOnRestart);
1240 pNextEntry = pNextEntry->prevSibling;
1242 #if defined(PANELIST)
1243 UnParentControls (&wmGD.Screens[scr], False);
1244 #endif /* PANELIST */
1247 XDeleteProperty(DISPLAY, wmGD.Screens[scr].rootWindow,
1253 /* shut down the messaging connection */
1257 XSync (DISPLAY, False);
1258 XCloseDisplay (DISPLAY);
1263 exit (WM_ERROR_EXIT_VALUE);
1270 } /* END OF FUNCTION Do_Quit_Mwm */
1273 /*************************************<->*************************************
1275 * ReBorderClient (pCD, reMapClient)
1280 * Restores X border for client window and reparents the
1281 * window back to the root.
1286 * pCD = pointer to the client data for the window to be re-bordered.
1288 *************************************<->***********************************/
1290 void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1294 XWindowChanges windowChanges;
1298 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1301 XUnmapWindow (DISPLAY, pCD->iconWindow);
1303 XReparentWindow (DISPLAY, pCD->iconWindow,
1304 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
1305 pCD->pWsList->iconY);
1307 XReparentWindow (DISPLAY, pCD->iconWindow,
1308 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
1321 if(wmGD.positionIsFrame)
1323 CalculateGravityOffset (pCD, &xoff, &yoff);
1324 x = pCD->clientX - xoff;
1325 y = pCD->clientY - yoff;
1333 XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1334 XReparentWindow (DISPLAY, pCD->client,
1335 ROOT_FOR_CLIENT(pCD), x, y);
1339 XMapWindow(wmGD.display, pCD->client);
1342 if (pCD->transientChildren)
1344 ReBorderClient (pCD->transientChildren, reMapClient);
1352 windowChanges.x = x;
1353 windowChanges.y = y;
1354 windowChanges.border_width = pCD->xBorderWidth;
1355 XConfigureWindow (DISPLAY, pCD->client,
1356 CWBorderWidth | CWX | CWY, &windowChanges);
1359 if (pCD->transientLeader)
1361 pCD = pCD->transientSiblings;
1369 } /* END OF FUNCTION ReBorderClient */
1373 /*************************************<->*************************************
1375 * F_Focus_Key (args, pCD, event)
1380 * This is the window manager function handler for setting the keyboard
1381 * focus to a particular client window.
1386 * args = (immediate value) focus flags
1388 * pCD = pointer to the client data
1390 * event = X event that invoked the function (key, button, or menu/NULL)
1392 *************************************<->***********************************/
1394 Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1396 long focusFlags = (long)args;
1399 if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1401 Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1402 (focusFlags | ALWAYS_SET_FOCUS));
1407 } /* END OF FUNCTION F_Focus_Key */
1410 /*************************************<->*************************************
1412 * FindSomeReasonableClient
1416 * Find a client, any client to set the focus to, return client or NULL.
1417 * This code is ripped off from AutoResetKeyFocus().
1419 *************************************<->***********************************/
1421 static Window FindSomeReasonableClient(void)
1423 ClientData *pcdNoFocus=NULL;
1425 ClientListEntry *pNextEntry;
1427 ClientData *pcdLastFocus = (ClientData *) NULL;
1428 ClientData *pcdFocus;
1429 Window focusWindow = (Window) NULL;
1432 * Scan through the list of clients to find a window to get the focus.
1435 pNextEntry = ACTIVE_PSD->clientList;
1439 pCD = pNextEntry->pCD;
1440 if (!wmGD.systemModalActive ||
1441 (wmGD.systemModalClient == pCD))
1443 if ((pNextEntry->type != MINIMIZED_STATE) &&
1444 (pCD->clientState != MINIMIZED_STATE) &&
1446 (ClientInWorkspace (ACTIVE_WS, pCD)) &&
1448 (pCD != pcdNoFocus))
1450 if (pCD->transientChildren)
1452 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1459 ((pcdLastFocus == NULL) ||
1460 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1462 pcdLastFocus = pcdFocus;
1466 pNextEntry = pNextEntry->nextSibling;
1470 * Set the focus window if one is found
1475 ClientInWorkspace (ACTIVE_WS, pcdLastFocus))
1479 focusWindow = pcdLastFocus->client;
1482 * If a client window could not be found, then just put focus
1486 if (focusWindow == (Window) NULL)
1488 pNextEntry = ACTIVE_PSD->clientList;
1492 pCD = pNextEntry->pCD;
1495 if (ClientInWorkspace (ACTIVE_WS, pCD))
1498 if ((pNextEntry->type == MINIMIZED_STATE) ||
1499 (pCD->clientState == MINIMIZED_STATE))
1501 focusWindow = ICON_FRAME_WIN(pCD);
1507 pNextEntry = pNextEntry->nextSibling;
1511 return (focusWindow);
1513 } /* END OF FUNCTION FindSomeReasonableClient */
1518 /*************************************<->*************************************
1520 * Do_Focus_Key (pCD, focusTime, flags)
1525 * This function is used to set the focus to a window. The focus indication
1526 * is not changed until the FocusIn event is received.
1531 * pCD = pointer to the client data
1533 * focusTime = focus change time
1535 * flags = wm focus change flags
1537 *************************************<->***********************************/
1539 void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1541 ClientData *pcdFocus;
1545 /* Clear the replay flag */
1546 wmGD.replayEnterEvent = False;
1551 * Make sure the client is in the current workspace
1554 (ClientInWorkspace (ACTIVE_WS, pCD)))
1559 if (pCD->clientState == MINIMIZED_STATE)
1561 focusWindow = ICON_FRAME_WIN(pCD);
1563 else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1566 * Set the keyboard focus to the indicated client window.
1567 * If the window has an application modal subordinate then
1568 * set the input focus to that window if the focus isn't
1569 * already owned by a subordinate.
1572 if (IS_APP_MODALIZED(pCD))
1574 ClientData *pcdFocusLeader,*currFocusLeader;
1577 * Handle case where a modal window exists when Mwm starts up.
1578 * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1581 if (wmGD.keyboardFocus)
1583 currFocusLeader = wmGD.keyboardFocus->transientLeader;
1587 currFocusLeader = (ClientData *) NULL;
1591 * Find focus leader for pCD
1594 pcdFocusLeader = pCD;
1595 while (pcdFocusLeader->transientLeader &&
1596 (pcdFocusLeader != currFocusLeader))
1598 pcdFocusLeader = pcdFocusLeader->transientLeader;
1601 if (pcdFocusLeader == currFocusLeader)
1603 pcdFocus = wmGD.keyboardFocus;
1608 pcdFocus = FindTransientFocus (pcdFocusLeader);
1613 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1614 * We must look at why FindTransientFocus is
1615 * returning a NULL pcd. The old code simply set
1616 * focusWindow = pcdFocus->client;
1617 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1619 * 11/26/96 rswiston - In tracking down CDExc22816, we
1620 * discovered that pCD could get tricked into thinking
1621 * it had modal transients when in fact all its transients
1622 * had been withdrawn (fixed in WithdrawTransientChildren()).
1623 * As a result, FindTransientFocus() returns wmGD.keyboardFocus;
1624 * if nobody has the focus, FindTransientFocus() returns NULL.
1628 focusWindow = pcdFocus->client;
1632 focusWindow = (wmGD.keyboardFocus) ?
1633 wmGD.keyboardFocus->client : ACTIVE_PSD->wmWorkspaceWin;
1639 * If the focus policy is "pointer" don't set the focus to a
1640 * window if it has an application modal subordinate.
1643 if (IS_APP_MODALIZED(pCD))
1646 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1648 /* Replay this later when the modal window is removed. */
1649 wmGD.replayEnterEvent = True;
1653 focusWindow = pcdFocus->client;
1660 * Set up the default (non client specific) keyboard input focus.
1663 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1665 focusWindow = PointerRoot;
1670 * The WORKSPACE_IF_NULL flag is used to prevent client
1671 * windows from flashing when deiconifying a client.
1674 if (WORKSPACE_IF_NULL & flags)
1676 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1680 /* find some reasonable client so that focus is not lost */
1682 focusWindow = FindSomeReasonableClient();
1683 if (focusWindow == (Window)NULL)
1685 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1691 if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1696 * Set the focus and/or send a take focus client message. This
1697 * is not done if a client area button press was done to set
1698 * set the focus and the window is a globally active input
1699 * style window (See ICCCM).
1702 if ( (flags & CLIENT_AREA_FOCUS) &&
1703 (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1704 ! pcdFocus->inputFocusModel &&
1705 (pcdFocus == pCD) &&
1706 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
1707 !(pcdFocus->clientState == MINIMIZED_STATE)
1712 * 1. User clicked in the client area AND
1713 * 2. Input model is Globally Active AND
1714 * 3. Keyboard focus policy is explicit
1717 /* this window has WM_TAKE_FOCUS set and InputField false. */
1718 /* just send a message. */
1719 SendClientMsg (pcdFocus->client,
1720 (long) wmGD.xa_WM_PROTOCOLS,
1721 (long) wmGD.xa_WM_TAKE_FOCUS,
1722 focusTime, NULL, 0);
1726 if ((pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1727 !(pcdFocus->clientState == MINIMIZED_STATE))
1730 * Locally Active Input Model - Send a take focus message to the client.
1733 SendClientMsg (pcdFocus->client,
1734 (long) wmGD.xa_WM_PROTOCOLS,
1735 (long) wmGD.xa_WM_TAKE_FOCUS,
1736 focusTime, NULL, 0);
1740 * Don't set the input focus if the window has input_field set
1741 * to False or has expressed an interest in WM_TAKE_FOCUS
1742 * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1743 * and the user click in the client area. If the user clicks
1744 * on the titlebar or traverses to this window via f.next_key,
1745 * set the focus so that the user can access the window menu
1749 if ( wmGD.enforceKeyFocus || /* res - default == True. */
1750 (flags & ALWAYS_SET_FOCUS) ||
1751 !(flags & CLIENT_AREA_FOCUS)|| /* clicked on frame? */
1752 pcdFocus->inputFocusModel || /* Pass.|Glob. Active */
1753 (pcdFocus->clientState == MINIMIZED_STATE)
1756 if ( !(flags & CLIENT_AREA_FOCUS) &&
1757 !pcdFocus->inputFocusModel &&
1758 !(pcdFocus->clientState == MINIMIZED_STATE))
1760 /* the window doesn't want the focus - set it to the frame */
1761 /* user clicked on the frame but we don't want the focus */
1762 /* set it to the client's frame */
1763 XSetInputFocus (DISPLAY, pcdFocus->clientBaseWin,
1764 RevertToPointerRoot, focusTime);
1766 else if ( !(flags & CLIENT_AREA_FOCUS) &&
1767 !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1768 pcdFocus->inputFocusModel
1771 XSetInputFocus (DISPLAY, focusWindow,
1772 RevertToPointerRoot, focusTime);
1776 XSetInputFocus (DISPLAY, focusWindow,
1777 RevertToParent, focusTime);
1783 * We've decided that the window shouldn't get the focus,
1784 * so don't change the focus.
1786 pcdFocus = wmGD.nextKeyboardFocus;
1792 XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1796 wmGD.nextKeyboardFocus = pcdFocus;
1800 } /* END OF FUNCTION Do_Focus_Key */
1805 /***********************<->*************************************
1807 * F_Goto_Workspace (args, pCD, event)
1811 * This is the window manager function handler for switching
1812 * to another workspace by name.
1816 * args = action function and arguments
1818 * pCD = pointer to the ClientData
1820 * event = X event that invoked the function (key, button, or menu/NULL)
1828 ******************************<->***********************************/
1830 F_Goto_Workspace (String args, ClientData *pCD, XEvent *event)
1832 WmScreenData *pSD = ACTIVE_PSD;
1837 * Compare argument against both resource name
1838 * and workspace title, take the first match.
1840 xms = XmStringCreate (args, XmFONTLIST_DEFAULT_TAG);
1841 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1843 if (!strcmp(pSD->pWS[iwsx].name, args) ||
1844 XmStringCompare (xms, pSD->pWS[iwsx].title))
1853 if (iwsx >= pSD->numWorkspaces)
1855 Warning (((char *)GETMESSAGE(26, 4,
1856 "Invalid workspace name specified for f.goto_workspace")));
1860 ChangeToWorkspace (&pSD->pWS[iwsx]);
1865 } /* END OF FUNCTION F_Goto_Workspace */
1871 /******************************<->*************************************
1873 * Boolean F_Help (String args, ClientData *pCD, XEvent *event)
1877 * Invoke help on the workspace manager
1881 * args - incoming values
1882 * pCD - associated client data structure
1883 * event - what triggered this call
1887 * Return - True if the call occurs; false otherwise.
1892 ******************************<->***********************************/
1894 F_Help (String args, ClientData *pCD, XEvent *event)
1899 rval = WmDtHelp(args);
1901 #endif /* PANELIST */
1904 } /* END OF FUNCTION F_Help */
1907 /******************************<->*************************************
1909 * Boolean F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1913 * Invoke item help on the frontpanel
1918 * pCD - associated client data structure ??
1919 * event - what triggered this call
1923 * Return - True if the call occurs; false otherwise.
1928 ******************************<->***********************************/
1930 F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1934 * Help mode event processing interferes
1935 * with slide up windows. Don't continue
1936 * if windows are sliding.
1938 if (wmGD.iSlideUpsInProgress == 0)
1940 (void) WmDtHelpMode();
1943 #endif /* PANELIST */
1945 } /* END OF FUNCTION F_Help_Mode */
1949 /******************************<->*************************************
1951 * F_Next_Key (args, pCD, event)
1956 * This is the window manager function handler for setting the keyboard
1957 * input focus to the next window in the set of managed windows.
1962 * args = (immediate value) window type flags
1964 * pCD = pointer to the client data
1966 * event = X event that invoked the function (key, button, or menu/NULL)
1968 *************************************<->***********************************/
1970 Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1972 #ifdef ROOT_ICON_MENU
1973 Boolean focused = False;
1974 #endif /* ROOT_ICON_MENU */
1975 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1977 #ifdef ROOT_ICON_MENU
1979 #endif /* ROOT_ICON_MENU */
1980 FocusNextWindow ((unsigned long)args,
1981 GetFunctionTimestamp ((XButtonEvent *)event));
1982 #ifdef ROOT_ICON_MENU
1983 if (focused && wmGD.iconClick &&
1984 event && event->type == KeyPress &&
1985 wmGD.nextKeyboardFocus &&
1986 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1987 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1990 * Post system menu from the icon
1992 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1995 #endif /* ROOT_ICON_MENU */
2000 } /* END OF FUNCTION F_Next_Key */
2004 /*************************************<->*************************************
2006 * F_Prev_Cmap (args, pCD, event)
2011 * This is the window manager function handler installing the previous
2012 * colormap in the list of client window colormaps.
2014 *************************************<->***********************************/
2016 Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
2020 pCD = ACTIVE_PSD->colormapFocus;
2023 if (pCD && (pCD->clientCmapCount > 0) &&
2024 ((pCD->clientState == NORMAL_STATE) ||
2025 (pCD->clientState == MAXIMIZED_STATE)))
2027 if (--(pCD->clientCmapIndex) < 0)
2029 pCD->clientCmapIndex = pCD->clientCmapCount - 1;
2031 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2032 if (ACTIVE_PSD->colormapFocus == pCD)
2034 #ifndef OLD_COLORMAP /* colormap */
2036 * We just re-ordered the colormaps list,
2037 * so we need to re-run the whole thing.
2039 pCD->clientCmapFlagsInitialized = 0;
2040 ProcessColormapList (ACTIVE_PSD, pCD);
2041 #else /* OSF original */
2042 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2049 } /* END OF FUNCTION F_Prev_Cmap */
2053 /*************************************<->*************************************
2055 * F_Prev_Key (args, pCD, event)
2060 * This is the window manager function handler for setting the keyboard
2061 * input focus to the previous window in the set of managed windows.
2066 * args = (immediate value) window type flags
2068 * pCD = pointer to the client data
2070 * event = X event that invoked the function (key, button, or menu/NULL)
2072 *************************************<->***********************************/
2074 Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
2076 #ifdef ROOT_ICON_MENU
2077 Boolean focused = False;
2078 #endif /* ROOT_ICON_MENU */
2079 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
2081 #ifdef ROOT_ICON_MENU
2083 #endif /* ROOT_ICON_MENU */
2084 FocusPrevWindow ((unsigned long)args,
2085 GetFunctionTimestamp ((XButtonEvent *)event));
2086 #ifdef ROOT_ICON_MENU
2087 if (focused && wmGD.iconClick &&
2088 event && event->type == KeyPress &&
2089 wmGD.nextKeyboardFocus &&
2090 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
2091 !P_ICON_BOX(wmGD.nextKeyboardFocus))
2094 * Post system menu from the icon
2096 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
2099 #endif /* ROOT_ICON_MENU */
2105 } /* END OF FUNCTION F_Prev_Key */
2109 /***********************<->*************************************
2111 * F_Post_FpMenu (args, pCD, event)
2116 * This is the window manager function handler for posting
2117 * the Front Panel window menu.
2121 * args = arguments (none)
2123 * pCD = pointer to the FP ClientData
2125 * event = X button press that invoked the function
2127 ******************************<->***********************************/
2130 F_Post_FpMenu (String args, ClientData *pCD, XEvent *event)
2132 static MenuSpec *fpMenuSpec = (MenuSpec *)NULL;
2134 if (event->type != ButtonPress)
2139 WmScreenData *pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2144 newMenuName = pCD ? pCD->systemMenu : "DtPanelMenu";
2146 for (oldSpec = pSD->menuSpecs;
2147 oldSpec != (MenuSpec *)NULL;
2148 oldSpec = oldSpec->nextMenuSpec)
2150 if (oldSpec->name && (strcmp(oldSpec->name, newMenuName) == 0))
2156 fpMenuSpec = DuplicateMenuSpec(oldSpec);
2159 * TEMPORARILY modify pSD so the new menu will be
2160 * created on DISPLAY1 instead of DISPLAY.
2162 fpMenuSpec->nextMenuSpec = pSD->menuSpecs;
2163 pSD->menuSpecs = fpMenuSpec;
2164 tmpWidget = pSD->screenTopLevelW;
2165 pSD->screenTopLevelW = pSD->screenTopLevelW1;
2167 (void)MAKE_MENU (pSD, pCD, newMenuName,
2168 F_CONTEXT_NORMAL, F_CONTEXT_NORMAL,
2169 (MenuItem *) NULL, FALSE);
2172 pSD->screenTopLevelW = tmpWidget;
2173 pSD->menuSpecs = fpMenuSpec->nextMenuSpec;
2176 PostMenu (fpMenuSpec, pCD, event->xbutton.x_root, event->xbutton.y_root,
2177 event->xbutton.button, F_CONTEXT_NORMAL, POST_AT_XY, event);
2179 _XmGetMenuState(XtParent(fpMenuSpec->menuWidget))
2180 ->MS_LastManagedMenuTime = event->xbutton.time;
2186 /***********************<->*************************************
2188 * F_Push_Recall (args, pCD, event)
2193 * This is the window manager function handler for invoking/topping
2194 * push_recall clients.
2201 * pCD = pointer to the ClientData
2203 * event = X event that invoked the function (key, button, or menu/NULL)
2208 * RETURN = if True then further button binding/function processing can
2209 * be done for the event that caused this function to be called.
2213 ******************************<->***********************************/
2216 F_Push_Recall (String args, ClientData *pCD, XEvent *event)
2218 WmPushRecallArg *pPRP;
2220 WmFpPushRecallClientData *pPRCD;
2222 pPRP = (WmPushRecallArg *) args;
2223 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2225 if (pPRP->ixReg < pSD->numPushRecallClients)
2227 /* get slot for this client */
2228 pPRCD = &(pSD->pPRCD[pPRP->ixReg]);
2231 * If the client is already running, then top it in this workspace,
2232 * else invoke the function to start it.
2236 /* Client is managed already. */
2237 if (!(ClientInWorkspace (pSD->pActiveWS, pPRCD->pCD)))
2239 WorkspaceID *wsRemoveList;
2243 * Move client to current workspace
2245 wsRemoveList = GetListOfOccupiedWorkspaces (pPRCD->pCD,
2247 RemoveClientFromWorkspaces (pPRCD->pCD, wsRemoveList,
2249 XtFree ((char *)wsRemoveList);
2250 AddClientToWorkspaces (pPRCD->pCD, &(pSD->pActiveWS->id), 1);
2251 SetClientWsIndex(pPRCD->pCD);
2252 SetClientState(pPRCD->pCD,
2253 pPRCD->pCD->clientState & ~UNSEEN_STATE, CurrentTime);
2256 /* Make this client visible */
2258 wmGD.bSuspendSecondaryRestack = True;
2260 F_Normalize_And_Raise (NULL, pPRCD->pCD, event);
2262 wmGD.bSuspendSecondaryRestack = False;
2267 struct timeval tvNow;
2269 Boolean bWaiting = False;
2271 if (pPRCD->tvTimeout.tv_sec != 0)
2273 gettimeofday (&tvNow, &tz);
2275 if ((pPRCD->tvTimeout.tv_sec > tvNow.tv_sec) ||
2276 ((pPRCD->tvTimeout.tv_sec == tvNow.tv_sec) &&
2277 (pPRCD->tvTimeout.tv_usec > tvNow.tv_usec)))
2279 /* still waiting for client to start */
2289 WmPanelistObject pPanelist;
2291 pPanelist = (WmPanelistObject) pSD->wPanelist;
2293 /* invoke the function to start the client */
2294 pPRP->wmFunc ( pPRP->pArgs, pCD, event);
2296 if (pPanelist && panel.busy_light_data)
2298 /* set timeout value */
2301 XmNclientTimeoutInterval, &clientTimeout); ac++;
2302 XtGetValues (panel.busy_light_data->icon, (ArgList)al, ac);
2306 * ClientTimeout is in milliseconds, timeval values
2307 * are in seconds and microseconds.
2309 gettimeofday (&(pPRCD->tvTimeout), &tz);
2311 pPRCD->tvTimeout.tv_sec += clientTimeout / 1000;
2312 pPRCD->tvTimeout.tv_usec +=
2313 (clientTimeout % 1000) * 1000;
2315 pPRCD->tvTimeout.tv_sec += pPRCD->tvTimeout.tv_usec / 1000000;
2316 pPRCD->tvTimeout.tv_usec %= 1000000;
2323 } /* END OF FUNCTION F_Push_Recall */
2324 #endif /* PANELIST */
2327 /*************************************<->*************************************
2329 * F_Pass_Key (args, pCD, event)
2334 * This is a function stub for the f.pass_key window manager function.
2339 * args = (immediate value) window type flags
2341 * pCD = pointer to the client data
2343 * event = X event that invoked the function (key, button, or menu/NULL)
2345 *************************************<->***********************************/
2347 Boolean F_Pass_Key (args, pCD, event)
2353 if (wmGD.passKeysActive)
2356 * Get out of pass keys mode.
2359 wmGD.passKeysActive = False;
2360 wmGD.passKeysKeySpec = NULL;
2365 * Get into pass keys mode.
2368 wmGD.passKeysActive = True;
2373 } /* END OF FUNCTION F_Pass_Key */
2377 /*************************************<->*************************************
2379 * F_Maximize (args, pCD, event)
2384 * This is the window manager function handler for maximizing a client
2387 *************************************<->***********************************/
2389 Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
2391 if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
2393 SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
2394 GetFunctionTimestamp ((XButtonEvent *)event),
2395 GetEventInverseMask(event));
2400 } /* END OF FUNCTION F_Maximize */
2404 /*************************************<->*************************************
2406 * F_Menu (args, pCD, event)
2411 * This is the window manager function handler for posting a menu.
2412 * This function can only be invoked by a key or button event.
2413 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2414 * NULL when the menu is unposted.
2416 *************************************<->***********************************/
2418 Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
2421 Context menuContext;
2422 unsigned int button;
2425 long flags = POST_AT_XY;
2430 ((event->type == ButtonPress) || (event->type == ButtonRelease)))
2432 button = event->xbutton.button;
2433 x = event->xbutton.x_root;
2434 y = event->xbutton.y_root;
2435 if (event->type == ButtonRelease)
2437 flags |= POST_TRAVERSAL_ON;
2441 * Root menu, if posted with button press, then
2442 * set up to handle root menu click to make the menu
2445 else if (wmGD.rootButtonClick && (event->type == ButtonPress))
2447 if (wmGD.bReplayedButton)
2449 /* This button was replayed, it most likely dismissed
2450 a previous sticky menu, don't post a menu here */
2453 wmGD.checkHotspot = True;
2454 wmGD.hotspotRectangle.x = x - wmGD.moveThreshold/2;
2455 wmGD.hotspotRectangle.y = y - wmGD.moveThreshold/2;
2456 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2457 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2462 ((event->type == KeyPress) || (event->type == KeyRelease)))
2465 x = event->xkey.x_root;
2466 y = event->xkey.y_root;
2471 * A button or key event must be used to post a menu using this
2480 if (pCD->clientState == NORMAL_STATE)
2482 menuContext = F_CONTEXT_NORMAL;
2484 else if (pCD->clientState == MAXIMIZED_STATE)
2486 menuContext = F_CONTEXT_MAXIMIZE;
2490 menuContext = F_CONTEXT_ICON;
2492 if (P_ICON_BOX(pCD) &&
2493 event->xany.window == ICON_FRAME_WIN(pCD))
2495 if (pCD->clientState == MINIMIZED_STATE)
2497 menuContext = F_SUBCONTEXT_IB_IICON;
2501 menuContext = F_SUBCONTEXT_IB_WICON;
2507 menuContext = F_CONTEXT_ROOT;
2511 /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
2512 * This should have been done in MakeWmFunctionResources().
2515 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2516 if ((menuSpec = MAKE_MENU (pSD, pCD, args, menuContext,
2517 menuContext, (MenuItem *) NULL, FALSE)) != NULL)
2519 PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
2524 } /* END OF FUNCTION F_Menu */
2527 /*************************************<->*************************************
2529 * F_Minimize (args, pCD, event)
2534 * This is the window manager function handler for minimizing a client
2537 *************************************<->***********************************/
2539 Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
2541 ClientData *pcdLeader;
2547 * If the window is a transient then minimize the entire transient
2548 * tree including the transient leader.
2551 pcdLeader = (pCD->transientLeader) ?
2552 FindTransientTreeLeader (pCD) : pCD;
2553 if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
2555 SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
2556 GetFunctionTimestamp ((XButtonEvent *)event),
2557 GetEventInverseMask(event));
2563 } /* END OF FUNCTION F_Minimize */
2567 /*************************************<->*************************************
2569 * F_Move (args, pCD, event)
2574 * This is the window manager function handler for moving a client window
2577 *************************************<->***********************************/
2579 Boolean F_Move (String args, ClientData *pCD, XEvent *event)
2581 if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
2583 StartClientMove (pCD, event);
2584 HandleClientFrameMove (pCD, event);
2589 } /* END OF FUNCTION F_Move */
2593 /*************************************<->*************************************
2595 * F_Next_Cmap (args, pCD, event)
2600 * This is the window manager function handler installing the next
2601 * colormap in the list of client window colormaps.
2603 *************************************<->***********************************/
2605 Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
2609 pCD = ACTIVE_PSD->colormapFocus;
2612 if (pCD && (pCD->clientCmapCount > 0) &&
2613 ((pCD->clientState == NORMAL_STATE) ||
2614 (pCD->clientState == MAXIMIZED_STATE)))
2616 if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
2618 pCD->clientCmapIndex = 0;
2620 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2621 if (ACTIVE_PSD->colormapFocus == pCD)
2623 #ifndef OLD_COLORMAP /* colormap */
2625 * We just re-ordered the colormaps list,
2626 * so we need to re-run the whole thing.
2628 pCD->clientCmapFlagsInitialized = 0;
2629 ProcessColormapList (ACTIVE_PSD, pCD);
2630 #else /* OSF original */
2631 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2638 } /* END OF FUNCTION F_Next_Cmap */
2642 /*************************************<->*************************************
2644 * F_Nop (args, pCD, event)
2649 * This is the window manager function handler for doing nothing.
2651 *************************************<->***********************************/
2653 Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2658 } /* END OF FUNCTION F_Nop */
2662 /*************************************<->*************************************
2664 * F_Normalize (args, pCD, event)
2669 * This is the window manager function handler for putting a client window
2670 * in the normal state.
2672 *************************************<->***********************************/
2674 Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2679 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2680 GetFunctionTimestamp ((XButtonEvent *)event),
2681 GetEventInverseMask(event));
2686 } /* END OF FUNCTION F_Normalize */
2690 /*************************************<->*************************************
2692 * F_Normalize_And_Raise (args, pCD, event)
2697 * This is the window manager function handler for putting a client window
2698 * in the normal state and raising it from and icon.
2700 *************************************<->***********************************/
2702 Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2706 WmWorkspaceData *pWS;
2711 pSD = PSD_FOR_CLIENT (pCD);
2715 pWS = pSD->pActiveWS;
2717 if (pSD->useIconBox &&
2718 wmGD.useFrontPanel &&
2719 pSD->iconBoxControl &&
2720 (!strcmp(args, WmNiconBox)))
2723 * There's an icon box in the front panel and this is a
2724 * request to pop up the icon box.
2726 IconBoxPopUp (pWS, True);
2730 #endif /* PANELIST */
2733 if (pCD->clientState == MINIMIZED_STATE)
2735 /* normalize window */
2736 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2739 ? GetFunctionTimestamp ((XButtonEvent *)event)
2741 GetEventInverseMask(event));
2745 /* Make sure we are in NORMAL_STATE */
2746 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2747 GetFunctionTimestamp ((XButtonEvent *)event),
2748 GetEventInverseMask(event));
2750 /* Raise the window and set the keyboard focus to the window */
2752 wmGD.bSuspendSecondaryRestack = True;
2754 F_Raise (NULL, pCD, (XEvent *)NULL);
2756 wmGD.bSuspendSecondaryRestack = False;
2758 if (wmGD.raiseKeyFocus)
2760 F_Focus_Key (NULL, pCD,
2763 : ((XEvent *)NULL)));
2766 wmGD.clickData.clickPending = False;
2767 wmGD.clickData.doubleClickPending = False;
2772 } /* END OF FUNCTION F_Normalize_And_Raise */
2776 /*************************************<->*************************************
2778 * F_Restore (args, pCD, event)
2783 * This is the window manager function handler for putting a client window
2784 * in the normal state.
2786 *************************************<->***********************************/
2788 Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2795 * If current state is MAXIMIZED state then just go to NORMAL state,
2796 * otherwise (you are in MINIMIZED state) return to previous state.
2799 if (pCD->clientState == MAXIMIZED_STATE)
2801 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2802 GetFunctionTimestamp ((XButtonEvent *)event),
2803 GetEventInverseMask(event));
2809 newState = MAXIMIZED_STATE;
2813 newState = NORMAL_STATE;
2816 SetClientStateWithEventMask (pCD, newState,
2817 GetFunctionTimestamp ((XButtonEvent *)event),
2818 GetEventInverseMask(event));
2824 } /* END OF FUNCTION F_Restore */
2828 /*************************************<->*************************************
2830 * F_Restore_And_Raise (args, pCD, event)
2835 * This is the window manager function handler for putting a client window
2836 * in the normal state and raising it from and icon.
2838 *************************************<->***********************************/
2840 Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2846 if (pCD->clientState == MINIMIZED_STATE)
2848 /* Restore window */
2851 newState = MAXIMIZED_STATE;
2855 newState = NORMAL_STATE;
2858 SetClientStateWithEventMask (pCD, newState,
2861 ? GetFunctionTimestamp ((XButtonEvent *)event)
2863 GetEventInverseMask(event));
2867 /* Make sure we restore the window first */
2868 F_Restore (NULL, pCD, event);
2870 /* Raise the window and set the keyboard focus to the window */
2872 wmGD.bSuspendSecondaryRestack = True;
2874 F_Raise (NULL, pCD, (XEvent *)NULL);
2876 wmGD.bSuspendSecondaryRestack = False;
2878 if (wmGD.raiseKeyFocus)
2880 F_Focus_Key (NULL, pCD,
2883 : ((XEvent *)NULL)));
2886 wmGD.clickData.clickPending = False;
2887 wmGD.clickData.doubleClickPending = False;
2892 } /* END OF FUNCTION F_Restore_And_Raise */
2896 /*************************************<->*************************************
2898 * F_Pack_Icons (args, pCD, event)
2903 * This is the window manager function handler for packing icons in the
2904 * icon box or on the desktop.
2906 *************************************<->***********************************/
2908 Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2913 if (ACTIVE_PSD->useIconBox)
2915 pIBD = ACTIVE_WS->pIconBox;
2918 while (pCD != pIBD->pCD_iconBox)
2920 if (pIBD->pNextIconBox)
2922 pIBD = pIBD->pNextIconBox;
2933 PackIconBox (pIBD, False, False, 0, 0);
2948 } /* END OF FUNCTION F_Pack_Icons */
2951 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2952 /*************************************<->*************************************
2954 * F_Post_RMenu (args, pCD, event)
2959 * This is the window manager function handler for posting the
2961 * This function can only be invoked by a key event.
2963 *************************************<->***********************************/
2965 Boolean F_Post_RMenu (String args, ClientData *pCD, XEvent *event)
2968 unsigned int button = NoButton;
2970 long flags = POST_AT_XY;
2976 if ((event->type == KeyPress) || (event->type == KeyRelease))
2979 /* Find the root menu spec */
2980 for (rootMenu = ACTIVE_PSD->menuSpecs;
2981 rootMenu != (MenuSpec *) NULL;
2982 rootMenu = rootMenu->nextMenuSpec)
2984 if (strcmp(rootMenu->name, ACTIVE_PSD->rootMenu) == 0)
2988 /* If we couldn't find the root menu, then do nothing. */
2989 if (rootMenu == (MenuSpec *) NULL)
2994 XQueryPointer(DISPLAY, ACTIVE_ROOT,
2995 &rwin, &cwin, &x, &y, &winx, &winy, &mask);
2997 PostMenu (rootMenu, NULL, x, y, NoButton, F_CONTEXT_ROOT,
3004 } /* END OF FUNCTION F_Post_RMenu */
3005 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
3008 /*************************************<->*************************************
3010 * F_Post_SMenu (args, pCD, event)
3015 * This is the window manager function handler for posting the system menu
3016 * for the specified client.
3017 * This function can only be invoked by a key or button event.
3018 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
3019 * NULL when the menu is unposted.
3021 *************************************<->***********************************/
3023 Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
3025 Context menuContext;
3029 * An event must be used to post the system menu using this function.
3032 if (event && pCD && pCD->systemMenuSpec)
3035 * Determine whether the keyboard is posting the menu and post
3036 * the menu at an appropriate place.
3039 if (pCD->clientState == NORMAL_STATE)
3041 menuContext = F_CONTEXT_NORMAL;
3043 else if (pCD->clientState == MAXIMIZED_STATE)
3045 menuContext = F_CONTEXT_MAXIMIZE;
3049 menuContext = F_CONTEXT_ICON;
3051 if (P_ICON_BOX(pCD) &&
3052 event->xany.window == ICON_FRAME_WIN(pCD))
3054 if (pCD->clientState == MINIMIZED_STATE)
3056 menuContext = F_SUBCONTEXT_IB_IICON;
3060 menuContext = F_SUBCONTEXT_IB_WICON;
3064 if ((event->type == KeyPress) || (event->type == KeyRelease))
3067 * Set up for "sticky" menu processing if specified.
3070 if (pCD->clientState == MINIMIZED_STATE ||
3071 menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
3075 wmGD.checkHotspot = True;
3078 else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
3080 wmGD.checkHotspot = True;
3083 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
3086 else if (event->type == ButtonPress)
3090 * Root menu, if posted with button press, then
3091 * set up to handle root menu click to make the menu
3094 if (wmGD.rootButtonClick && (!wmGD.checkHotspot))
3096 wmGD.checkHotspot = True;
3097 wmGD.hotspotRectangle.x =
3098 event->xbutton.x_root - wmGD.moveThreshold/2;
3099 wmGD.hotspotRectangle.y =
3100 event->xbutton.y_root - wmGD.moveThreshold/2;
3101 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
3102 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
3105 PostMenu (pCD->systemMenuSpec, pCD,
3106 event->xbutton.x_root, event->xbutton.y_root,
3107 event->xbutton.button, menuContext, POST_AT_XY, event);
3109 else if (event->type == ButtonRelease)
3111 PostMenu (pCD->systemMenuSpec, pCD,
3112 event->xbutton.x_root, event->xbutton.y_root,
3113 event->xbutton.button, menuContext,
3114 POST_AT_XY | POST_TRAVERSAL_ON, event);
3120 } /* END OF FUNCTION F_PostSMenu */
3124 /*************************************<->*************************************
3126 * F_Kill (args, pCD, event)
3131 * This is the window manager function handler for terminating a client.
3132 * Essentially the client connection is shut down.
3134 *************************************<->***********************************/
3136 Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
3138 if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
3140 Boolean do_delete_window =
3141 pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
3142 Boolean do_save_yourself =
3143 pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
3146 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3151 * Get the widget for the subpanel
3152 * (Should be only child of the shell!)
3154 wPanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
3157 SlideSubpanelBackIn (pCD, wPanel);
3161 if (pCD->clientFlags & ICON_BOX)
3164 * When the front panel is used with the icon box,
3165 * "Close" hides the icon box into the front panel.
3167 if ((wmGD.useFrontPanel) &&
3168 (pCD->pSD->iconBoxControl) &&
3169 (IconBoxShowing(pCD->pSD->pActiveWS)))
3171 IconBoxPopUp (pCD->pSD->pActiveWS, False);
3175 #endif /* PANELIST */
3176 if (!do_delete_window && !do_save_yourself)
3178 XKillClient (DISPLAY, pCD->client);
3182 if (do_delete_window)
3185 * The client wants to be notified, not killed.
3188 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3189 (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
3193 * HP does not want to send a client message for both
3194 * delete_window AND save_yourself. The current OSF
3195 * patch did just that. This "else if" returns dtwm
3196 * to the behavior of dt 2.01
3198 else if (do_save_yourself)
3200 if (do_save_yourself)
3204 * Send a WM_SAVE_YOURSELF message and wait for a change to
3205 * the WM_COMMAND property.
3206 * !!! button and key input should be kept from the window !!!
3209 if (AddWmTimer (TIMER_QUIT,
3210 (unsigned long) wmGD.quitTimeout, pCD))
3212 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3213 (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
3215 pCD->clientFlags |= CLIENT_TERMINATING;
3219 XKillClient (DISPLAY, pCD->client);
3227 } /* END OF FUNCTION F_Kill */
3231 /*************************************<->*************************************
3233 * F_Marquee_Selection (args, pCD, event)
3238 * This is the window manager function handler for selecting
3239 * non-window manager objects on the root window.
3241 *************************************<->***********************************/
3243 Boolean F_Marquee_Selection (String args, ClientData *pCD, XEvent *event)
3248 * This function only valid in root context
3250 StartMarqueeSelect (ACTIVE_PSD, event);
3251 HandleMarqueeSelect (ACTIVE_PSD, event);
3256 } /* END OF FUNCTION F_Marquee_Selection */
3258 /*************************************<->*************************************
3260 * RefreshByClearing (win)
3265 * Recursively refresh this window and its children by doing
3268 *************************************<->***********************************/
3270 RefreshByClearing (Window win)
3274 Window root, parent;
3275 unsigned int nchildren;
3276 Window *winChildren;
3278 /* clear this window */
3279 XClearArea(DISPLAY, win, 0, 0, 0, 0, True);
3281 /* find any children and clear them, too */
3282 status = XQueryTree(DISPLAY, win, &root, &parent, &winChildren,
3286 /* recurse for each child window */
3287 for (i=0; i<nchildren; ++i)
3289 RefreshByClearing(winChildren[i]);
3294 XFree((char *)winChildren);
3300 /*************************************<->*************************************
3302 * F_Refresh (args, pCD, event)
3307 * This is the window manager function handler for causing all windows
3308 * in the workspace to be redrawn.
3310 *************************************<->***********************************/
3312 Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
3317 if (wmGD.refreshByClearing)
3319 RefreshByClearing (ACTIVE_ROOT);
3324 /* default background_pixmap is None */
3325 win = XCreateWindow (DISPLAY,
3327 (unsigned int) DisplayWidth (DISPLAY,
3329 (unsigned int) DisplayHeight (DISPLAY,
3336 (XSetWindowAttributes *)NULL);
3338 XMapWindow (DISPLAY, win);
3339 XDestroyWindow (DISPLAY, win);
3347 } /* END OF FUNCTION F_Refresh */
3351 /*************************************<->*************************************
3353 * F_Resize (args, pCD, event)
3358 * This is the window manager function handler for resizing a client window.
3360 *************************************<->***********************************/
3362 Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
3364 if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
3365 ((pCD->clientState == NORMAL_STATE) ||
3366 (pCD->clientState == MAXIMIZED_STATE)))
3368 StartClientResize (pCD, event);
3369 HandleClientFrameResize (pCD, event);
3374 } /* END OF FUNCTION F_Resize */
3378 /*************************************<->*************************************
3380 * F_Restart (args, pCD, event)
3385 * This is the window manager function handler for restarting the window
3388 *************************************<->***********************************/
3390 Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
3393 if (args && *args && !strcmp (args, DTWM_REQP_NO_CONFIRM))
3395 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3399 if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
3401 ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
3405 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3409 } /* END OF FUNCTION F_Restart */
3413 /*************************************<->*************************************
3415 * Do_Restart (dummy)
3420 * Callback function for restarting the window manager.
3422 *************************************<->***********************************/
3424 void Do_Restart (Boolean dummy)
3426 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3428 } /* END OF FUNCTION Do_Restart */
3432 /*************************************<->*************************************
3434 * RestartWm (startupFlags)
3439 * Actually restarts the window manager.
3444 * startupFlags = flags to be put into the Wm_INFO property for restart.
3446 *************************************<->***********************************/
3448 void RestartWm (long startupFlags)
3450 ClientListEntry *pNextEntry;
3454 for (scr=0; scr<wmGD.numScreens; scr++)
3456 if(wmGD.Screens[scr].managed)
3460 * Set up the _MOTIF_WM_INFO property on the root window
3461 * to indicate a restart.
3464 SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
3466 SaveResources(&wmGD.Screens[scr]);
3469 * Unmap client windows and reparent them to the root window.
3472 pNextEntry = wmGD.Screens[scr].lastClient;
3475 if (pNextEntry->type == NORMAL_STATE)
3477 if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
3479 if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
3481 XUnmapWindow (DISPLAY,
3482 pNextEntry->pCD->clientFrameWin);
3487 DeFrameClient (pNextEntry->pCD);
3490 pNextEntry = pNextEntry->prevSibling;
3492 #if defined(PANELIST)
3493 UnParentControls (&wmGD.Screens[scr], True);
3494 #endif /* PANELIST */
3500 /* shut down the messaging connection */
3506 * This fixes restart problem when going from explicit focus to
3507 * pointer focus. Window under pointer was not getting focus indication
3508 * until pointer was moved to new window, or out of and into the
3512 XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
3513 XSync (DISPLAY, False);
3516 CLOSE_FILES_ON_EXEC();
3517 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3520 * Restart the window manager with the initial arguments plus
3521 * the restart settings.
3524 execvp (*(wmGD.argv), wmGD.argv);
3527 Warning (((char *)GETMESSAGE(26, 1,
3528 "The window manager restart failed. The window manager program could not \
3529 be found or could not be executed.")));
3531 Warning ("Cannot restart the window manager");
3537 } /* END OF FUNCTION RestartWm */
3540 /*************************************<->*************************************
3542 * DeFrameClient (pCD)
3547 * Unmaps a client window (and client icon window) and reparents the
3548 * window back to the root.
3553 * pCD = pointer to the client data for the window to be de-framed.
3555 *************************************<->***********************************/
3557 void DeFrameClient (ClientData *pCD)
3561 XWindowChanges windowChanges;
3565 if (pCD->clientState != MINIMIZED_STATE)
3567 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
3570 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
3572 XUnmapWindow (DISPLAY, pCD->iconWindow);
3573 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
3575 XReparentWindow (DISPLAY, pCD->iconWindow,
3576 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
3577 pCD->pWsList->iconY);
3579 XReparentWindow (DISPLAY, pCD->iconWindow,
3580 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
3591 if(wmGD.positionIsFrame)
3593 CalculateGravityOffset (pCD, &xoff, &yoff);
3594 x = pCD->clientX - xoff;
3595 y = pCD->clientY - yoff;
3604 #ifndef UNMAP_ON_RESTART
3605 if (pCD->clientState == MINIMIZED_STATE)
3607 XUnmapWindow (DISPLAY, pCD->client);
3610 XUnmapWindow (DISPLAY, pCD->client);
3612 XRemoveFromSaveSet (DISPLAY, pCD->client);
3613 XReparentWindow (DISPLAY, pCD->client,
3614 ROOT_FOR_CLIENT(pCD), x, y);
3616 if (pCD->transientChildren)
3618 DeFrameClient (pCD->transientChildren);
3624 windowChanges.x = x;
3625 windowChanges.y = y;
3626 windowChanges.border_width = pCD->xBorderWidth;
3627 XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
3630 if (pCD->transientLeader)
3632 pCD = pCD->transientSiblings;
3640 } /* END OF FUNCTION DeFrameClient */
3642 #if defined(PANELIST)
3644 /******************************<->*************************************
3646 * F_Toggle_Front_Panel (args, pCD, event)
3651 * This is the window manager function handler for toggling the
3652 * front panel off and on.
3653 ******************************<->***********************************/
3656 F_Toggle_Front_Panel (String args, ClientData *pCD, XEvent *event)
3659 WmPanelistObject pPanelist;
3663 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3667 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3673 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3674 wmGD.windowContextType, (caddr_t *)&pCD);
3680 if (pCD->clientState & MINIMIZED_STATE)
3682 SetClientState (pCD, NORMAL_STATE,
3683 GetFunctionTimestamp ((XButtonEvent *)event));
3687 SetClientState (pCD, MINIMIZED_STATE,
3688 GetFunctionTimestamp ((XButtonEvent *)event));
3693 } /* END OF FUNCTION F_Toggle_Front_Panel */
3696 /******************************<->*************************************
3698 * Boolean F_Version (String args, ClientData *pCD, XEvent *event)
3702 * Invoke the help on version dialogue.
3706 * args - incoming values
3707 * pCD - associated client data structure
3708 * event - what triggered this call
3712 * Return - True if the call occurs; false otherwise.
3717 ******************************<->***********************************/
3719 F_Version (String args, ClientData *pCD, XEvent *event)
3722 WmPanelistObject pPanelist;
3726 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3730 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3735 WmDtHelpOnVersion (O_Shell (pPanelist));
3740 } /* END OF FUNCTION F_Version */
3741 #endif /* PANELIST */
3744 /******************************<->*************************************
3746 * F_Send_Msg (args, pCD, event)
3751 * This is the window manager function handler for sending a client
3752 * message event to a client window.
3757 * args = (immediate value) message id
3759 * pCD = pointer to the client data
3761 * event = X event that invoked the function (key, button, or menu/NULL)
3764 ******************************<->***********************************/
3766 Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
3771 if (pCD && pCD->mwmMessagesCount)
3774 * A message id must be made "active" by being included in the
3775 * _MWM_MESSAGES property before the associated message can be sent.
3778 for (i = 0; i < pCD->mwmMessagesCount; i++)
3780 if (pCD->mwmMessages[i] == (long)args)
3782 SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES,
3783 (long)args, CurrentTime, NULL, 0);
3791 } /* END OF FUNCTION F_Send_Msg */
3795 /*************************************<->*************************************
3797 * F_Separator (args, pCD, event)
3802 * This is a placeholder function; it should never be called.
3804 *************************************<->***********************************/
3806 Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
3811 } /* END OF FUNCTION F_Separator */
3814 Boolean ForceRaiseWindow (ClientData *pcd)
3818 WmScreenData *pSD = (ACTIVE_WS)->pSD;
3820 XWindowChanges changes;
3821 Boolean restack = False;
3824 if (pSD->clientList->type == MINIMIZED_STATE)
3826 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
3830 stackWindow = pSD->clientList->pCD->clientFrameWin;
3835 * Windows did not raise on regular f.raise because the raise was
3836 * not relative to another window (methinks).
3838 changes.stack_mode = Above;
3839 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
3847 /*************************************<->*************************************
3849 * F_Raise (args, pCD, event)
3854 * This is the window manager function handler for topping the client window
3855 * so that it is unobscured.
3857 *************************************<->***********************************/
3859 Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
3861 ClientListEntry *pEntry;
3862 ClientListEntry *pNextEntry;
3863 ClientListEntry *pStackEntry;
3864 String string = args;
3865 int flags = STACK_NORMAL;
3867 WmWorkspaceData *pWS = ACTIVE_WS;
3872 /* process '-client' argument */
3873 if (string[0] == '-')
3875 string = &string[1];
3876 string = (String) GetString ((unsigned char **) &string);
3879 pNextEntry = ACTIVE_PSD->clientList;
3880 while (pNextEntry &&
3881 (pEntry = FindClientNameMatch (pNextEntry, True, string,
3884 pNextEntry = pEntry->nextSibling;
3886 if (ClientInWorkspace (pWS, pEntry->pCD))
3889 Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3890 pStackEntry = pEntry;
3896 /* process family stacking stuff */
3899 unsigned int slen, len, index;
3901 slen = strlen(args) - 2; /* subtract '\n' and NULL */
3902 for (index = 0; index < slen; string = &args[index+1])
3904 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3906 len = strlen(string);
3907 if (!strcmp(string,"within"))
3909 flags |= STACK_WITHIN_FAMILY;
3911 else if (!strcmp(string,"freeFamily"))
3913 flags |= STACK_FREE_FAMILY;
3918 if (ClientInWorkspace (pWS, pCD))
3921 Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3930 if (ClientInWorkspace (pWS, pCD))
3933 Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3941 } /* END OF FUNCTION F_Raise */
3945 /*************************************<->*************************************
3947 * Do_Raise (pCD, pStackEntry)
3952 * This is the window manager function handler for topping the client window
3953 * so that it is unobscured.
3958 * pCD = pointer to the client data of the window (or icon) to be raised.
3960 * pStackEntry = pointer to client list entry for window that is to be
3961 * above the raised window (if NULL window is raised to the top of the
3964 *************************************<->***********************************/
3966 void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3968 Boolean restackTransients;
3969 ClientData *pcdLeader;
3970 WmWorkspaceData *pWS = ACTIVE_WS;
3972 Boolean bLeaderRestacked;
3979 * Window has been reparented into the front panel.
3980 * Don't follow through on window stacking change.
3985 #else /* PANELIST */
3986 #endif /* PANELIST */
3988 if (ClientInWorkspace(pWS, pCD) &&
3989 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
3992 * Both clients are in the current workspace. Set
3993 * client indices so that the access macros work.
3995 SetClientWsIndex (pCD);
3998 SetClientWsIndex (pStackEntry->pCD);
4004 * One or both of the clients are not in the current workspace
4011 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
4013 if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
4016 * Don't raise the window above the system modal window.
4019 else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
4020 !P_ICON_BOX(pcdLeader))
4023 * If a dirtyStackEntry exists, return it to its original place
4024 * in the stack (for all stacking types)
4026 if (dirtyStackEntry)
4028 if (dirtyStackEntry->transientChildren ||
4029 dirtyStackEntry->transientLeader)
4030 RestackTransients (dirtyStackEntry);
4031 dirtyStackEntry = NULL;
4036 * Only restack the icon if it is not currently raised.
4041 if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
4043 StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
4045 MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
4051 if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
4053 StackWindow (pWS, &pcdLeader->iconEntry,
4054 True /*on top*/, (ClientListEntry *) NULL);
4055 MoveEntryInList (pWS, &pcdLeader->iconEntry,
4056 True /*on top*/, (ClientListEntry *) NULL);
4060 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
4064 * Handle restacking of primary/secondary windows
4065 * within the transient window tree. Don't raise this
4066 * window above any modal transients.
4068 bLeaderRestacked = False;
4069 if ((pcdLeader->transientChildren) &&
4070 (!pCD->secondariesOnTop) &&
4071 (!wmGD.bSuspendSecondaryRestack) &&
4072 (!IS_APP_MODALIZED(pCD)))
4074 if (pCD != pcdLeader)
4077 * This is not the transient leader, make sure
4078 * the transient leader isn't on top.
4079 * (Brute force solution)
4081 bLeaderRestacked = NormalizeTransientTreeStacking (pcdLeader);
4083 if (pCD->transientChildren)
4086 * This isn't the overall leader of the transient
4087 * tree, but it does have transient's of its own.
4088 * Move it to the top of its own transient sub-tree.
4090 bLeaderRestacked |= BumpPrimaryToTop (pCD);
4096 * This is the transient leader, move it to the
4099 bLeaderRestacked = BumpPrimaryToTop (pcdLeader);
4105 * If this is a transient window then put it on top of its
4106 * sibling transient windows.
4109 restackTransients = False;
4113 * Fix for 5325 - The following code has been reorganized to cause the
4114 * action of F_Raise to match the current documentation.
4115 * The new algorithm is as follows:
4117 * if (dirtyStackEntry)
4118 * restore dirty tree
4119 * if (not withinFamily)
4120 * bring window group to the top of global stack
4122 * raise the requested window to top of family
4124 * raise requested window to top of siblings
4125 * if (need to restack windows)
4130 * If a dirtyStackEntry exists, return it to its original place
4131 * in the stack (for all stacking types)
4133 if (dirtyStackEntry)
4136 * Check to make sure that the dirty pCD has either transient
4137 * children or a transient leader. If not, do not restore
4140 if (dirtyStackEntry->transientChildren ||
4141 dirtyStackEntry->transientLeader)
4142 RestackTransients (dirtyStackEntry);
4143 dirtyStackEntry = NULL;
4148 * If the flags do not indicate "within", raise the window family
4149 * to the top of the window stack. If the window is the primary,
4150 * raise it to the top regardless of the flags.
4152 if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
4156 if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
4158 StackWindow (pWS, &pcdLeader->clientEntry,
4159 False /*below*/, pStackEntry);
4160 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4161 False /*below*/, pStackEntry);
4166 if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
4168 StackWindow (pWS, &pcdLeader->clientEntry,
4169 True /*on top*/, (ClientListEntry *) NULL);
4170 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4171 True /*on top*/, (ClientListEntry *) NULL);
4177 * If freeFamily stacking is requested, check to make sure that
4178 * the window has either a transientChild or Leader. This will
4179 * guarantee that windows that form their own family are not
4180 * labelled as dirty (what's to dirty it up?). If it has either,
4181 * raise the window to the top of the family stack.
4183 if ((flags & STACK_FREE_FAMILY) &&
4184 (pCD->transientLeader || pCD->transientChildren))
4186 dirtyStackEntry = pCD;
4187 dirtyLeader = pcdLeader;
4189 restackTransients = ForceRaiseWindow (pCD);
4193 * If withinFamily stacking is requested, put the current transient
4194 * on top of its sibling transient windows.
4198 restackTransients = PutTransientOnTop (pCD);
4201 /* At this point, if doing a regular f.raise the window family has
4202 * already been brought to the top of the stack, so nothing further
4203 * needs to be done for it.
4206 /* Restack the transients if needed */
4209 if ((restackTransients) || (bLeaderRestacked))
4211 if (restackTransients)
4214 RestackTransients (pCD);
4218 } /* END OF FUNCTION Do_Raise */
4222 /*************************************<->*************************************
4224 * F_Raise_Lower (args, pCD, event)
4229 * This window manager function tops an obscured window or icon and bottoms
4230 * a window or icon that is on top of the window stack.
4232 *************************************<->***********************************/
4234 Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
4236 ClientData *pcdLeader;
4240 pcdLeader = (pCD->transientLeader) ?
4241 FindTransientTreeLeader (pCD) : pCD;
4244 * Treat a raise/lower on a window in a transient tree as if it is
4245 * a raise/lower for the whole tree.
4248 if (CheckIfClientObscuredByAny (pcdLeader))
4251 * The window is obscured by another window, raise the window.
4255 F_Raise (NULL, pCD, (XEvent *)NULL);
4257 F_Raise (NULL, pcdLeader, (XEvent *)NULL);
4260 else if (CheckIfClientObscuringAny (pcdLeader) &&
4261 !(wmGD.systemModalActive &&
4262 (pcdLeader == wmGD.systemModalClient)))
4265 * The window is obscuring another window and is
4266 * not system modal, lower the window.
4269 F_Lower (NULL, pcdLeader, (XEvent *)NULL);
4271 if ((pcdLeader->secondariesOnTop == False) &&
4272 (pCD->transientLeader != NULL) &&
4273 (!IS_APP_MODALIZED(pcdLeader)))
4275 /* Push transient below primary */
4276 (void) BumpPrimaryToTop (pcdLeader);
4277 RestackTransients (pcdLeader);
4282 else if ((pcdLeader->secondariesOnTop == False) &&
4283 (pcdLeader->transientChildren != NULL) &&
4284 (!wmGD.systemModalActive) &&
4285 (!IS_APP_MODALIZED(pcdLeader)))
4287 if (LeaderOnTop(pcdLeader))
4289 /* Push primary below transient */
4290 (void) BumpPrimaryToBottom (pcdLeader);
4291 RestackTransients (pcdLeader);
4295 F_Raise (NULL, pCD, (XEvent *)NULL);
4296 /* Push transient below primary */
4297 (void) BumpPrimaryToTop (pcdLeader);
4298 RestackTransients (pcdLeader);
4306 } /* END OF FUNCTION F_Raise_Lower */
4310 /*************************************<->*************************************
4312 * F_Refresh_Win (args, pCD, event)
4317 * This is the window manager function handler for causing a client window
4318 * to redisplay itself.
4320 *************************************<->***********************************/
4322 Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
4327 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
4328 (pCD->clientState == MAXIMIZED_STATE)))
4330 if (pCD->clientState == NORMAL_STATE)
4332 w = (unsigned int) pCD->clientWidth;
4333 h = (unsigned int) pCD->clientHeight;
4337 w = (unsigned int) pCD->maxWidth;
4338 h = (unsigned int) pCD->maxHeight;
4342 if (wmGD.refreshByClearing)
4344 RefreshByClearing (pCD->clientFrameWin);
4349 /* default background_pixmap is None */
4350 win = XCreateWindow (DISPLAY,
4360 (XSetWindowAttributes *)NULL);
4362 XMapWindow (DISPLAY, win);
4363 XDestroyWindow (DISPLAY, win);
4372 } /* END OF FUNCTION F_Refresh_Win */
4376 /*************************************<->*************************************
4378 * F_Set_Behavior (args, pCD, event)
4383 * This function is used to switch the window manager configuration between
4384 * the built-in configuration (for CXI behavior) and the user's custom
4387 *************************************<->***********************************/
4389 Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
4392 * Go system modal in starting to do the set behavior.
4395 /* !!! grab the server and the pointer !!! */
4399 * Confirm that a set_behavior should be done.
4400 * Execute restart if so.
4403 if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
4405 ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
4406 CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
4410 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4411 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4415 } /* END OF FUNCTION F_Set_Behavior */
4419 /*************************************<->*************************************
4421 * Do_Set_Behavior (dummy)
4426 * Callback to do the f.set_behavior function.
4428 *************************************<->***********************************/
4430 void Do_Set_Behavior (Boolean dummy)
4432 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4433 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4435 } /* END OF FUNCTION Do_Set_Behavior */
4439 /*************************************<->*************************************
4441 * F_Set_Context (args, pCD, event)
4446 * This function is used to set a client context for subsequent
4449 *************************************<->***********************************/
4451 Boolean F_Set_Context (String args, ClientData *pCD, XEvent *event)
4454 wmGD.requestContextWin = (Window) args;
4457 } /* END OF FUNCTION F_Set_Context */
4461 /*************************************<->*************************************
4463 * F_Title (args, pCD, event)
4468 * This is a placeholder function; it should never be called.
4470 *************************************<->***********************************/
4472 Boolean F_Title (String args, ClientData *pCD, XEvent *event)
4477 } /* END OF FUNCTION F_Title */
4481 /******************************<->*************************************
4483 * F_Screen (args, pCD, event)
4488 * This is the window manager function handler for warping to screens
4493 * args = (immediate value) window type flags
4495 * pCD = pointer to the client data
4497 * event = X event that invoked the function (key, button, or menu/NULL)
4499 * NOTE: May want to consider tracking changes in screen because in
4500 * managing a new window (ie. in ManageWindow()).
4504 * RETURN = if True then further button binding/function processing can
4505 * be done for the event that caused this function to be called.
4507 *************************************<->***********************************/
4509 Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
4513 unsigned int dummask;
4514 WmScreenData *newscr = NULL;
4516 static int PreviousScreen = -1;
4520 if (PreviousScreen == -1)
4522 PreviousScreen = DefaultScreen(DISPLAY);
4525 if (strcmp (args, "next") == 0)
4527 scr = ACTIVE_PSD->screen + 1;
4530 else if (strcmp (args, "prev") == 0)
4532 scr = ACTIVE_PSD->screen - 1;
4535 else if (strcmp (args, "back") == 0)
4537 scr = PreviousScreen;
4549 scr = wmGD.numScreens - 1;
4550 else if (scr >= wmGD.numScreens)
4553 newscr = &(wmGD.Screens[scr]);
4554 if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
4555 if (inc) { /* walk around the list */
4560 "Unable to warp to unmanaged screen %d\n", scr);
4567 if (ACTIVE_PSD->screen == scr) return (False); /* already on that screen */
4569 PreviousScreen = ACTIVE_PSD->screen;
4570 XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
4571 &dumint, &dumint, &dummask);
4573 XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
4575 if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
4578 * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can
4579 * uses the new screen instead of the old screen. Then call
4580 * Do_Focus_Key with a NULL pCD to find a reasonable client to
4583 SetActiveScreen (newscr);
4584 Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
4593 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
4594 /*************************************<->*************************************
4596 * F_InvokeCommand (args, pCD, event)
4601 * This is the window manager function for invoking client inserted menu
4604 *************************************<->***********************************/
4606 Boolean F_InvokeCommand (String args, ClientData *pCD, XEvent *event)
4608 CARD32 commandID, clientWindow;
4609 Atom notifySelection;
4611 if (args == (String) NULL) return(FALSE);
4613 if (sscanf(args, "%d %d %ld", &commandID, &clientWindow,
4614 ¬ifySelection) != 3)
4617 SendInvokeMessage(commandID,
4618 (pCD == (ClientData *) NULL ? 0 : pCD->client),
4623 } /* END OF FUNCTION F_InvokeCommand */
4624 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
4627 /*************************************<->*************************************
4629 * GetFunctionTimestamp (pEvent)
4634 * This function is used to extract a timestamp from a key or button event.
4635 * If the event passed in is not a key or button event then a timestamp
4641 * event = pointer to an X event
4646 * RETURN = a timestamp
4648 *************************************<->***********************************/
4650 Time GetFunctionTimestamp (XButtonEvent *pEvent)
4655 (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
4656 ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
4658 time = pEvent->time;
4662 time = GetTimestamp ();
4667 } /* END OF FUNCTION GetFunctionTimestamp */
4671 ** name the event mask we need for a grab in order to find the matching
4672 ** event for an event; right now handle only button-presses
4674 static unsigned int GetEventInverseMask(XEvent *event)
4676 if ((XEvent*)NULL == event)
4678 if (ButtonPress == event->type)
4679 return ButtonReleaseMask; /* detail ? */
4681 expansion further here
4689 /*************************************<->*************************************
4691 * ClearDirtyStackEntry (pCD)
4696 * This function is used to clear the static dirtyStackEntry structure and
4697 * the dirtyLeader static variable when a pCD is destroyed. This
4698 * guarantees that freed memory will not be accessed.
4703 * pCD = pointer to clientData being freed
4710 *************************************<->***********************************/
4712 void ClearDirtyStackEntry (ClientData *pCD)
4714 if (pCD == dirtyStackEntry)
4716 dirtyStackEntry = NULL;
4720 #if defined(DEBUG) && defined(WSM)
4722 /***********************<->*************************************
4724 * F_ZZ_Debug (args, pCD, event)
4729 * This is the window manager debug (multi) function
4736 * pCD = pointer to the ClientData for the whole front panel
4738 * event = X event that invoked the function (key, button, or menu/NULL)
4743 * RETURN = if True then further button binding/function processing can
4744 * be done for the event that caused this function to be called.
4748 * Argument 1 determines the debug function to execute:
4752 * "color_server_info" - dump out color server info
4754 ******************************<->***********************************/
4757 F_ZZ_Debug (String subFcn, ClientData *pCD, XEvent *event)
4759 /* Only do something is sub function is specified */
4763 if (!(strcmp(subFcn, "dump_resources")))
4768 for (scr=0; scr<wmGD.numScreens; scr++)
4770 sprintf (szRes, "/tmp/dtwm.resources.%d", scr);
4772 XrmPutFileDatabase(XtScreenDatabase(
4773 XScreenOfDisplay(DISPLAY, scr)),
4784 /*************************************<->*************************************
4786 * F_Next_Workspace (args, pCD, event)
4791 * This function switches to the next workspace in the list
4793 *************************************<->***********************************/
4795 Boolean F_Next_Workspace (String args, ClientData *pCD, XEvent *event)
4797 WmScreenData *pSD = ACTIVE_PSD;
4800 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4802 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4809 /* check bounds and wrap */
4810 if (iwsx >= pSD->numWorkspaces)
4813 ChangeToWorkspace (&pSD->pWS[iwsx]);
4818 } /* END OF FUNCTION F_Next_Workspace */
4821 /*************************************<->*************************************
4823 * F_Prev_Workspace (args, pCD, event)
4828 * This function switches to the previous workspace in the list
4830 *************************************<->***********************************/
4832 Boolean F_Prev_Workspace (String args, ClientData *pCD, XEvent *event)
4834 WmScreenData *pSD = ACTIVE_PSD;
4837 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4839 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4846 /* check bounds and wrap */
4848 iwsx = pSD->numWorkspaces - 1;
4850 ChangeToWorkspace (&pSD->pWS[iwsx]);
4855 } /* END OF FUNCTION F_Prev_Workspace */
4859 /*************************************<->*************************************
4861 * F_Workspace_Presence (args, pCD, event)
4866 * This function pops up the workspace presence dialog box
4868 *************************************<->***********************************/
4870 Boolean F_Workspace_Presence (String args, ClientData *pCD, XEvent *event)
4872 Context wsContext = (Context)NULL;
4874 if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4876 if (pCD->clientState == NORMAL_STATE)
4878 wsContext = F_CONTEXT_NORMAL;
4880 else if (pCD->clientState == MAXIMIZED_STATE)
4882 wsContext = F_CONTEXT_MAXIMIZE;
4886 wsContext = F_CONTEXT_ICON;
4887 /* return (False); */
4889 ShowPresenceBox (pCD, wsContext);
4893 } /* END OF FUNCTION F_Workspace_Presence */
4899 WmScreenData *pSD = (ACTIVE_WS)->pSD;
4900 ClientListEntry *pCLE;
4902 fprintf (stdout, "Window stacking (bottom to top)\n");
4903 pCLE = pSD->lastClient;
4906 if (ClientInWorkspace (ACTIVE_WS, pCLE->pCD))
4907 fprintf (stdout, "* ");
4909 fprintf (stdout, " ");
4911 fprintf (stdout, "%08lx\t%s\n",
4913 pCLE->pCD->clientName);
4915 pCLE = pCLE->prevSibling;