2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993, 1994 OPEN SOFTWARE FOUNDATION, INC.
31 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 HEWLETT-PACKARD COMPANY
32 * (c) Copyright 1993, 1994 International Business Machines Corp.
33 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
34 * (c) Copyright 1993, 1994 Novell, Inc.
49 #include "WmWrkspace.h" /* for ClientInWorkspace() test */
50 #include <Dt/EnvControlP.h> /* for restoring **environ before an exec() */
51 #include "WmResNames.h"
52 #include <Dt/Message.h>
55 #include <Dt/DtStrDefs.h>
61 * include extern functions
63 #include "WmFunction.h"
69 #include "WmColormap.h"
72 #include "WmFeedback.h"
77 #include "WmIconBox.h"
78 #include "WmKeyFocus.h"
81 #include "WmPresence.h"
83 #include "WmProperty.h"
84 #include "WmProtocol.h"
85 #include "WmResParse.h"
86 #include "WmWinConf.h"
87 #include "WmWinInfo.h"
88 #include "WmWinList.h"
89 #include "WmWinState.h"
92 #include <Xm/RowColumnP.h> /* for MS_LastManagedMenuTime */
93 extern XmMenuState _XmGetMenuState();
96 extern char * getenv ();
99 #endif /* PORT_NOVFORK */
101 static unsigned int GetEventInverseMask(XEvent *event);
105 #if (defined(__linux__) || defined(sun) || defined(CSRG_BASED)) && !defined(_NFILE)
106 #define _NFILE FOPEN_MAX
108 #define CLOSE_FILES_ON_EXEC() \
109 {int ifx; for (ifx=3; ifx < _NFILE; ifx++) (void) fcntl (ifx, F_SETFD, 1);}
117 * The 'dirty' variables are used to keep track of the transient window
118 * that has been lowered via "f.lower freeFamily".
120 static ClientData *dirtyStackEntry = NULL;
121 static ClientData *dirtyLeader = NULL;
125 /***********************<->*************************************
127 * F_Action (args, pCD, event)
132 * This is the window manager function handler for invoking actions.
137 * args = action function and arguments
139 * pCD = pointer to the ClientData for the whole front panel
141 * event = X event that invoked the function (key, button, or menu/NULL)
146 * RETURN = if True then further button binding/function processing can
147 * be done for the event that caused this function to be called.
151 * The pCD->controlWindow is a temporary area used solely for
152 * this function invocation--it stores the pCW of the control
153 * that want the function to happen.
154 ******************************<->***********************************/
157 F_Action (String actionName, ClientData *pCD, XEvent *event)
160 WmActionArg *pAP = (WmActionArg *) actionName;
162 /* make sure the command runs on the right display. */
163 if (wmGD.pActiveSD->displayString)
165 putenv(wmGD.pActiveSD->displayString);
170 WmFrontPanelSetBusy (True);
174 DtActionInvoke (wmGD.pActiveSD->screenTopLevelW1,
175 pAP->actionName, pAP->aap, pAP->numArgs,
176 pAP->szExecParms, NULL, NULL, 1, NULL, NULL);
179 * Restore original DISPLAY environment variable
181 if(wmGD.pActiveSD->displayString && wmGD.displayString)
183 putenv(wmGD.displayString);
188 } /* END OF FUNCTION F_Action */
192 /******************************<->*************************************
194 * F_Beep (args, pCD, event)
199 * This is the window manager function handler for beeping.
204 * args = function arguments (specified in .mwmrc file)
206 * pCD = pointer to the client data for the client window to which the
207 * function is to be applied
209 * event = X event that invoked the function (key, button, or menu/NULL)
214 * RETURN = if True then further button binding/function processing can
215 * be done for the event that caused this function to be called.
217 ******************************<->***********************************/
219 Boolean F_Beep (String args, ClientData *pCD, XEvent *event)
222 /* !!! what is a good value for percent (the second arg) !!! */
227 } /* END OF FUNCTION F_Beep */
232 * Handle Special case where the dirty window is the top most
233 * transient window. When this is the case, raising the window
234 * that was on top (the window just below the dirty window) will
235 * fail because Mwm stack database is out of sync. So the solution
236 * is to restack the dirty transient relative to the second to the
237 * top transient. This function is used to support freeFamily stacking.
239 ClientData * FindSecondToTopTransient (pcd)
243 static ClientData *second;
245 pcdNext = pcd->transientChildren;
248 if (pcdNext->transientChildren)
250 if (!pcdNext->transientChildren->transientChildren)
254 FindSecondToTopTransient (pcdNext);
256 pcdNext = pcdNext->transientSiblings;
257 if (pcdNext && !pcdNext->transientSiblings)
265 } /* END OF FUNCTION */
269 Boolean ForceLowerWindow (ClientData *pcd)
273 WmScreenData *pSD = (ACTIVE_WS)->pSD;
275 XWindowChanges changes;
276 Boolean restack = False;
279 WmScreenData *pSD = (ACTIVE_WS)->pSD;
281 ClientListEntry *pCLE;
284 * Find lowest window in this workspace. We'll stack this transient
287 pCLE = pSD->lastClient;
292 if ((pCLE->pCD != pcd) &&
293 (ClientInWorkspace (ACTIVE_WS, pCLE->pCD)))
295 if ((pCLE->type == MINIMIZED_STATE) &&
296 (pCLE->pCD->clientState == MINIMIZED_STATE))
298 stackWindow = ICON_FRAME_WIN(pCLE->pCD);
300 else if ((pCLE->type == NORMAL_STATE) &&
301 ((pCLE->pCD->clientState == NORMAL_STATE) ||
302 (pCLE->pCD->clientState == MAXIMIZED_STATE)))
304 stackWindow = pCLE->pCD->clientFrameWin;
307 if (stackWindow != None)
310 changes.sibling = stackWindow;
314 if (stackWindow == None)
316 pCLE = pCLE->prevSibling;
321 if (pSD->lastClient->type == MINIMIZED_STATE)
323 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
327 stackWindow = pSD->lastClient->pCD->clientFrameWin;
331 changes.stack_mode = Below;
335 XConfigureWindow (DISPLAY, pcd->clientFrameWin, mask, &changes);
338 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
347 /*************************************<->*************************************
349 * F_Lower (args, pCD, event)
354 * This is the window manager function handler for bottoming a client window
360 * args = function arguments (specified in .mwmrc file)
362 * pCD = pointer to the client data for the client window to which the
363 * function is to be applied
365 * event = X event that invoked the function (key, button, or menu/NULL)
370 * RETURN = if True then further button binding/function processing can
371 * be done for the event that caused this function to be called.
373 *************************************<->***********************************/
375 Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
377 ClientListEntry *pEntry;
378 ClientListEntry *pNextEntry;
379 ClientListEntry *pStackEntry;
380 String string = args;
381 int flags = STACK_NORMAL;
383 WmWorkspaceData *pWS = ACTIVE_WS;
388 /* process '-client' argument */
389 if (string[0] == '-')
392 string = (String) GetString ((unsigned char **) &string);
395 pNextEntry = ACTIVE_PSD->lastClient;
397 (pEntry = FindClientNameMatch (pNextEntry, False,
398 string, F_GROUP_ALL)))
400 pNextEntry = pEntry->prevSibling;
402 if (ClientInWorkspace (pWS, pEntry->pCD))
405 Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
406 pStackEntry = pEntry;
412 /* process family stacking stuff */
415 unsigned int slen, len, index;
417 slen = strlen(args) - 2; /* subtract '\n' and NULL */
418 for (index = 0; index < slen; string = &args[index+1])
420 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
422 len = strlen(string);
423 if (!strcmp(string,"within"))
425 flags |= STACK_WITHIN_FAMILY;
427 else if (!strcmp(string,"freeFamily"))
429 flags |= STACK_FREE_FAMILY;
434 if (ClientInWorkspace (pWS, pCD))
437 Do_Lower (pCD, (ClientListEntry *) NULL, flags);
446 if (ClientInWorkspace (pWS, pCD))
449 Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
456 * If caused by button press, event may ALSO cause focus to be
457 * passed to this client - prepare to disable focusAutoRaise.
459 if (pCD && event && (event->type == ButtonPress))
460 pCD->focusAutoRaiseDisablePending = True;
462 wmGD.passButtonsCheck = False;
465 } /* END OF FUNCTION F_Lower */
469 /*************************************<->*************************************
471 * Do_Lower (pCD, pStackEntry)
476 * This is the window manager function handler for lowering the client window
477 * so that it does not obscure any other window above the stack entry
483 * pCD = pointer to the client data of the window (or icon) to be lowered.
485 * pStackEntry = pointer to client list entry for window that is to be
486 * below the lowered window (if NULL, window is lowered to the bottom
489 *************************************<->***********************************/
491 void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
493 Boolean restackTransients;
494 ClientData *pcdLeader;
495 WmWorkspaceData *pWS = ACTIVE_WS;
497 Boolean bLeaderRestacked;
503 * Window has been reparented into the front panel.
504 * Don't follow through on window stacking change.
510 if (ClientInWorkspace(pWS, pCD) &&
511 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
514 * Both clients are in the current workspace. Set
515 * client indices so that the access macros work.
517 SetClientWsIndex (pCD);
520 SetClientWsIndex (pStackEntry->pCD);
526 * One or both of the clients are not in the current workspace
533 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
535 if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
538 * If a dirtyStackEntry exists, return it to its original place
539 * in the stack (for all stacking types)
543 if (dirtyStackEntry->transientChildren ||
544 dirtyStackEntry->transientLeader)
545 RestackTransients (dirtyStackEntry);
546 dirtyStackEntry = NULL;
551 * Only restack the icon if it is not currently lowered.
556 if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
558 StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
560 MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
566 if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
568 StackWindow (pWS, &pcdLeader->iconEntry,
569 False /*on bottom*/, (ClientListEntry *) NULL);
570 MoveEntryInList (pWS, &pcdLeader->iconEntry,
571 False /*on bottom*/, (ClientListEntry *) NULL);
575 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
579 * Handle restacking of primary/secondary windows
580 * within the transient window tree.
582 bLeaderRestacked = False;
583 if ((pcdLeader->transientChildren) &&
584 (!pcdLeader->secondariesOnTop) &&
585 (!wmGD.bSuspendSecondaryRestack))
587 if (pCD == pcdLeader)
590 * Lower requested on the leader itself, insure it's
593 bLeaderRestacked = BumpPrimaryToBottom (pcdLeader);
595 else if (pCD->transientChildren)
598 * Lower requested on the leader of a subtree. Insure
599 * that this subtree leader is at the bottom of the
602 bLeaderRestacked = BumpPrimaryToBottom (pCD);
604 else if (pCD->transientLeader)
609 * Lower requested on a transient. Insure all the
610 * subtree leaders up to the top are at the bottom
611 * of their respective transient subtrees.
613 for (pcdLdr = pCD->transientLeader;
615 pcdLdr = pcdLdr->transientLeader)
617 bLeaderRestacked |= BumpPrimaryToBottom (pcdLdr);
624 * If this is a transient window then put it below its
625 * sibling transient windows.
628 restackTransients = False;
629 if (pCD->transientLeader)
633 * If freeFamily stacking, then put dirty transient window
634 * (if any) back in place before force lowering current window
635 * to the bottom of the global window stack. Then return.
638 if (flags & STACK_FREE_FAMILY)
640 /* Restore dirty transient if not current window. */
641 if ((dirtyStackEntry) &&
642 (dirtyStackEntry != pCD))
644 RestackTransients (dirtyStackEntry);
647 dirtyStackEntry = pCD;
648 dirtyLeader = pcdLeader;
650 ForceLowerWindow (pCD);
655 * Reach here only if NOT doing a f.lower freeFamily (see
656 * return; statement above). Put current transient below
657 * its sibling transient windows.
659 restackTransients = PutTransientBelowSiblings (pCD);
663 * If doing a regular f.lower and you have a dirty window, then
664 * clean up dirty transient window.
670 * If lowering a window in the same family as the dirty
671 * transient window, then just restack before lowering.
672 * Else, restore the dirty transient in place before
673 * lowering the current window. Clear dirtyStack.
675 if (dirtyLeader == pcdLeader)
677 restackTransients = True;
681 RestackTransients (dirtyStackEntry);
684 dirtyStackEntry = NULL;
688 * Only restack the window or transient window tree if it is
689 * not currently lowered and the window is not a system
695 if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
696 !(wmGD.systemModalActive &&
697 (pcdLeader == wmGD.systemModalClient)))
699 StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
701 MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
705 else if ((restackTransients) || (bLeaderRestacked))
707 else if (restackTransients)
710 RestackTransients (pCD);
715 if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
716 !(wmGD.systemModalActive &&
717 (pcdLeader == wmGD.systemModalClient)) &&
718 !(flags & STACK_WITHIN_FAMILY))
720 StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
721 (ClientListEntry *) NULL);
722 MoveEntryInList (pWS, &pcdLeader->clientEntry,
723 False /*on bottom*/, (ClientListEntry *) NULL);
726 else if ((restackTransients) || (bLeaderRestacked))
728 else if (restackTransients)
731 RestackTransients (pCD);
736 } /* END OF FUNCTION Do_Lower */
740 /*************************************<->*************************************
742 * F_CircleDown (args, pCD, event)
747 * This is the window manager function handler for moving the client window
748 * on top of stack to the bottom.
753 * args = function arguments (specified in .mwmrc file)
755 * pCD = pointer to the client data for the client window to which the
756 * function is to be applied
758 * event = X event that invoked the function (key, button, or menu/NULL)
763 * RETURN = if True then further button binding/function processing can
764 * be done for the event that caused this function to be called.
766 *************************************<->***********************************/
768 Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
771 unsigned long windowType;
772 ClientListEntry *pNextEntry;
777 * Go down through the client list looking for a window of an
778 * appropriate type that is obscuring lower windows.
781 types = (unsigned long)args;
782 pNextEntry = ACTIVE_PSD->clientList;
786 * Only check out the window if it is onscreen.
789 pcdNext = pNextEntry->pCD;
790 if (((pNextEntry->type == NORMAL_STATE) &&
791 (pcdNext->clientState != MINIMIZED_STATE)) ||
792 ((pNextEntry->type == MINIMIZED_STATE) &&
793 (pcdNext->clientState == MINIMIZED_STATE)))
795 if (pcdNext->clientState == MINIMIZED_STATE)
797 windowType = F_GROUP_ICON;
801 windowType = F_GROUP_WINDOW;
802 if (pcdNext->transientLeader || pcdNext->transientChildren)
804 windowType |= F_GROUP_TRANSIENT;
807 if (types & windowType)
809 if (CheckIfClientObscuringAny (pcdNext))
812 * This window (or window tree) is obscuring another window
813 * on the screen. Lower the window.
817 wmGD.bSuspendSecondaryRestack = True;
819 F_Lower (NULL, pcdNext, (XEvent *) NULL);
821 wmGD.bSuspendSecondaryRestack = False;
827 pNextEntry = pNextEntry->nextSibling;
832 } /* END OF FUNCTION F_Circle_Down */
836 /*************************************<->*************************************
838 * F_Circle_Up (args, pCD, event)
843 * This is the window manager function handler for moving the client window
844 * on the bottom of the stack to the top.
849 * args = function arguments (specified in .mwmrc file)
851 * pCD = pointer to the client data for the client window to which the
852 * function is to be applied
854 * event = X event that invoked the function (key, button, or menu/NULL)
859 * RETURN = if True then further button binding/function processing can
860 * be done for the event that caused this function to be called.
862 *************************************<->***********************************/
864 Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
867 unsigned long windowType;
868 ClientListEntry *pNextEntry;
873 * Go up through the client list looking for a window of an
874 * appropriate type that is obscured by higher windows.
877 types = (unsigned long)args;
878 pNextEntry = ACTIVE_PSD->lastClient;
882 * Only check out the window if it is onscreen.
885 pcdNext = pNextEntry->pCD;
886 if (((pNextEntry->type == NORMAL_STATE) &&
887 (pcdNext->clientState != MINIMIZED_STATE)) ||
888 ((pNextEntry->type == MINIMIZED_STATE) &&
889 (pcdNext->clientState == MINIMIZED_STATE)))
891 if (pcdNext->clientState == MINIMIZED_STATE)
893 windowType = F_GROUP_ICON;
897 windowType = F_GROUP_WINDOW;
898 if (pcdNext->transientLeader || pcdNext->transientChildren)
900 windowType |= F_GROUP_TRANSIENT;
903 if (types & windowType)
905 if (CheckIfClientObscuredByAny (pcdNext))
908 * This window (or window tree) is obscured by another
909 * window on the screen. Raise the window.
913 wmGD.bSuspendSecondaryRestack = True;
915 F_Raise (NULL, pcdNext, (XEvent *) NULL);
917 wmGD.bSuspendSecondaryRestack = False;
923 pNextEntry = pNextEntry->prevSibling;
929 } /* END OF FUNCTION F_Circle_Up */
933 /*************************************<->*************************************
935 * F_Focus_Color (args, pCD, event)
940 * This is the window manager function handler for setting the colormap
941 * focus to a client window or reinstalling the default colormap.
943 *************************************<->***********************************/
945 Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
948 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
953 * The window selected for the colormap focus is a top-level client
954 * window. If there are subwindow colormaps then determine if the
955 * selection was in one of the subwindows.
958 if (pCD->clientState == MINIMIZED_STATE)
960 /* !!! colormap for client supplied icon window !!! */
965 SetColormapFocus (ACTIVE_PSD, pCD);
970 } /* END OF FUNCTION F_Focus_Color */
974 /*************************************<->*************************************
976 * F_Exec (args, pCD, event)
981 * This is the window manager function handler for executing a command
984 *************************************<->***********************************/
986 Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
999 /* make sure the f.exec command runs on the right display. */
1000 if (wmGD.pActiveSD->displayString)
1002 putenv(wmGD.pActiveSD->displayString);
1008 * Start the busy indicator, waiting for a pushbutton window
1009 * for the given duration
1011 WmFrontPanelSetBusy (True);
1015 * Fork a process to exec a shell to run the specified command:
1019 if ((pid = fork ()) == 0)
1021 if ((pid = vfork ()) == 0)
1026 #if defined(SVR4) || defined(__linux__)
1035 setpgrp(tpid, tpid);
1038 #endif /* NO_SETPGRP */
1041 * Clean up window manager resources.
1042 * The X file descriptor should be automatically closed.
1046 * Fix up signal handling.
1048 RestoreDefaultSignalHandlers ();
1051 * Fix up the child application's environment NOT to
1052 * inherit the XFILESEARCHPATH, XBMLANGPATH, NLSPATH, etc.
1055 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
1057 CLOSE_FILES_ON_EXEC();
1061 * Exec the command using $MWMSHELL if set or
1062 * $SHELL if set and $MWMSHELL not set or sh.
1065 if (((shell = getenv ("MWMSHELL")) != NULL) ||
1066 ((shell = getenv ("SHELL")) != NULL))
1069 shellname = strrchr (shell, '/');
1070 if (shellname == NULL)
1073 If the shell pathname obtained from SHELL or MWMSHELL does not
1074 have a "/" in the path and if the user expects this shell to be
1075 obtained using the PATH variable rather than the current
1076 directory, then we must call execlp and not execl
1079 execlp (shell, shellname, "-c", args, NULL);
1084 execl (shell, shellname, "-c", args, NULL);
1089 * There is no SHELL environment variable or the first execl failed.
1093 execl ("/usr/bin/sh", "sh", "-c", args, NULL);
1095 execl ("/bin/sh", "sh", "-c", args, NULL);
1100 * Error - command could not be exec'ed.
1110 * Have the window manager wait for the shell to complete.
1114 intStat = (void (*)())signal (SIGINT, SIG_IGN);
1115 quitStat = (void (*)())signal (SIGQUIT, SIG_IGN);
1120 * Don't need to wait because WSM sets SIGCLD handler
1123 while ((w = wait (&status)) != pid && (w != -1));
1132 signal (SIGINT, intStat);
1133 signal (SIGQUIT, quitStat);
1137 * Restore original DISPLAY environment variable value
1138 * so a restart will start on the same screen
1141 if(wmGD.pActiveSD->displayString &&
1144 putenv(wmGD.displayString);
1151 } /* END OF FUNCTION F_Exec */
1155 /*************************************<->*************************************
1157 * F_Quit_Mwm (args, pCD, event)
1162 * This is the window manager function handler for terminating the window
1165 *************************************<->***********************************/
1167 Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
1169 if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
1171 ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
1180 } /* END OF FUNCTION F_Quit_Mwm */
1184 /*************************************<->*************************************
1186 * Do_Quit_Mwm (diedOnRestart)
1191 * Callback to do the f.quit_mwm function.
1193 *************************************<->***********************************/
1195 void Do_Quit_Mwm (Boolean diedOnRestart)
1198 ClientListEntry *pNextEntry;
1202 * Close the X connection to get all the X resources cleaned up.
1203 * !!! maybe windows should be reparented / rebordered before closing? !!!
1204 * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
1210 XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
1211 for (scr = 0; scr < wmGD.numScreens; scr++)
1213 if (wmGD.Screens[scr].managed)
1216 SaveResources(&wmGD.Screens[scr]);
1218 pNextEntry = wmGD.Screens[scr].lastClient;
1221 if (pNextEntry->type == NORMAL_STATE)
1223 if (!(pNextEntry->pCD->clientFlags &
1226 ReBorderClient (pNextEntry->pCD, diedOnRestart);
1229 pNextEntry = pNextEntry->prevSibling;
1231 UnParentControls (&wmGD.Screens[scr], False);
1234 XDeleteProperty(DISPLAY, wmGD.Screens[scr].rootWindow,
1240 /* shut down the messaging connection */
1244 XSync (DISPLAY, False);
1245 XCloseDisplay (DISPLAY);
1250 exit (WM_ERROR_EXIT_VALUE);
1257 } /* END OF FUNCTION Do_Quit_Mwm */
1260 /*************************************<->*************************************
1262 * ReBorderClient (pCD, reMapClient)
1267 * Restores X border for client window and reparents the
1268 * window back to the root.
1273 * pCD = pointer to the client data for the window to be re-bordered.
1275 *************************************<->***********************************/
1277 void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1281 XWindowChanges windowChanges;
1285 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1288 XUnmapWindow (DISPLAY, pCD->iconWindow);
1290 XReparentWindow (DISPLAY, pCD->iconWindow,
1291 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
1292 pCD->pWsList->iconY);
1294 XReparentWindow (DISPLAY, pCD->iconWindow,
1295 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
1308 if(wmGD.positionIsFrame)
1310 CalculateGravityOffset (pCD, &xoff, &yoff);
1311 x = pCD->clientX - xoff;
1312 y = pCD->clientY - yoff;
1320 XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1321 XReparentWindow (DISPLAY, pCD->client,
1322 ROOT_FOR_CLIENT(pCD), x, y);
1326 XMapWindow(wmGD.display, pCD->client);
1329 if (pCD->transientChildren)
1331 ReBorderClient (pCD->transientChildren, reMapClient);
1339 windowChanges.x = x;
1340 windowChanges.y = y;
1341 windowChanges.border_width = pCD->xBorderWidth;
1342 XConfigureWindow (DISPLAY, pCD->client,
1343 CWBorderWidth | CWX | CWY, &windowChanges);
1346 if (pCD->transientLeader)
1348 pCD = pCD->transientSiblings;
1356 } /* END OF FUNCTION ReBorderClient */
1360 /*************************************<->*************************************
1362 * F_Focus_Key (args, pCD, event)
1367 * This is the window manager function handler for setting the keyboard
1368 * focus to a particular client window.
1373 * args = (immediate value) focus flags
1375 * pCD = pointer to the client data
1377 * event = X event that invoked the function (key, button, or menu/NULL)
1379 *************************************<->***********************************/
1381 Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1383 long focusFlags = (long)args;
1386 if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1388 Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1389 (focusFlags | ALWAYS_SET_FOCUS));
1394 } /* END OF FUNCTION F_Focus_Key */
1397 /*************************************<->*************************************
1399 * FindSomeReasonableClient
1403 * Find a client, any client to set the focus to, return client or NULL.
1404 * This code is ripped off from AutoResetKeyFocus().
1406 *************************************<->***********************************/
1408 static Window FindSomeReasonableClient(void)
1410 ClientData *pcdNoFocus=NULL;
1412 ClientListEntry *pNextEntry;
1414 ClientData *pcdLastFocus = (ClientData *) NULL;
1415 ClientData *pcdFocus;
1416 Window focusWindow = (Window) NULL;
1419 * Scan through the list of clients to find a window to get the focus.
1422 pNextEntry = ACTIVE_PSD->clientList;
1426 pCD = pNextEntry->pCD;
1427 if (!wmGD.systemModalActive ||
1428 (wmGD.systemModalClient == pCD))
1430 if ((pNextEntry->type != MINIMIZED_STATE) &&
1431 (pCD->clientState != MINIMIZED_STATE) &&
1433 (ClientInWorkspace (ACTIVE_WS, pCD)) &&
1435 (pCD != pcdNoFocus))
1437 if (pCD->transientChildren)
1439 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1446 ((pcdLastFocus == NULL) ||
1447 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1449 pcdLastFocus = pcdFocus;
1453 pNextEntry = pNextEntry->nextSibling;
1457 * Set the focus window if one is found
1462 ClientInWorkspace (ACTIVE_WS, pcdLastFocus))
1466 focusWindow = pcdLastFocus->client;
1469 * If a client window could not be found, then just put focus
1473 if (focusWindow == (Window) NULL)
1475 pNextEntry = ACTIVE_PSD->clientList;
1479 pCD = pNextEntry->pCD;
1482 if (ClientInWorkspace (ACTIVE_WS, pCD))
1485 if ((pNextEntry->type == MINIMIZED_STATE) ||
1486 (pCD->clientState == MINIMIZED_STATE))
1488 focusWindow = ICON_FRAME_WIN(pCD);
1494 pNextEntry = pNextEntry->nextSibling;
1498 return (focusWindow);
1500 } /* END OF FUNCTION FindSomeReasonableClient */
1505 /*************************************<->*************************************
1507 * Do_Focus_Key (pCD, focusTime, flags)
1512 * This function is used to set the focus to a window. The focus indication
1513 * is not changed until the FocusIn event is received.
1518 * pCD = pointer to the client data
1520 * focusTime = focus change time
1522 * flags = wm focus change flags
1524 *************************************<->***********************************/
1526 void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1528 ClientData *pcdFocus;
1532 /* Clear the replay flag */
1533 wmGD.replayEnterEvent = False;
1538 * Make sure the client is in the current workspace
1541 (ClientInWorkspace (ACTIVE_WS, pCD)))
1546 if (pCD->clientState == MINIMIZED_STATE)
1548 focusWindow = ICON_FRAME_WIN(pCD);
1550 else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1553 * Set the keyboard focus to the indicated client window.
1554 * If the window has an application modal subordinate then
1555 * set the input focus to that window if the focus isn't
1556 * already owned by a subordinate.
1559 if (IS_APP_MODALIZED(pCD))
1561 ClientData *pcdFocusLeader,*currFocusLeader;
1564 * Handle case where a modal window exists when Mwm starts up.
1565 * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1568 if (wmGD.keyboardFocus)
1570 currFocusLeader = wmGD.keyboardFocus->transientLeader;
1574 currFocusLeader = (ClientData *) NULL;
1578 * Find focus leader for pCD
1581 pcdFocusLeader = pCD;
1582 while (pcdFocusLeader->transientLeader &&
1583 (pcdFocusLeader != currFocusLeader))
1585 pcdFocusLeader = pcdFocusLeader->transientLeader;
1588 if (pcdFocusLeader == currFocusLeader)
1590 pcdFocus = wmGD.keyboardFocus;
1595 pcdFocus = FindTransientFocus (pcdFocusLeader);
1600 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1601 * We must look at why FindTransientFocus is
1602 * returning a NULL pcd. The old code simply set
1603 * focusWindow = pcdFocus->client;
1604 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1606 * 11/26/96 rswiston - In tracking down CDExc22816, we
1607 * discovered that pCD could get tricked into thinking
1608 * it had modal transients when in fact all its transients
1609 * had been withdrawn (fixed in WithdrawTransientChildren()).
1610 * As a result, FindTransientFocus() returns wmGD.keyboardFocus;
1611 * if nobody has the focus, FindTransientFocus() returns NULL.
1615 focusWindow = pcdFocus->client;
1619 focusWindow = (wmGD.keyboardFocus) ?
1620 wmGD.keyboardFocus->client : ACTIVE_PSD->wmWorkspaceWin;
1626 * If the focus policy is "pointer" don't set the focus to a
1627 * window if it has an application modal subordinate.
1630 if (IS_APP_MODALIZED(pCD))
1633 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1635 /* Replay this later when the modal window is removed. */
1636 wmGD.replayEnterEvent = True;
1640 focusWindow = pcdFocus->client;
1647 * Set up the default (non client specific) keyboard input focus.
1650 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1652 focusWindow = PointerRoot;
1657 * The WORKSPACE_IF_NULL flag is used to prevent client
1658 * windows from flashing when deiconifying a client.
1661 if (WORKSPACE_IF_NULL & flags)
1663 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1667 /* find some reasonable client so that focus is not lost */
1669 focusWindow = FindSomeReasonableClient();
1670 if (focusWindow == (Window)NULL)
1672 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1678 if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1683 * Set the focus and/or send a take focus client message. This
1684 * is not done if a client area button press was done to set
1685 * set the focus and the window is a globally active input
1686 * style window (See ICCCM).
1689 if ( (flags & CLIENT_AREA_FOCUS) &&
1690 (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1691 ! pcdFocus->inputFocusModel &&
1692 (pcdFocus == pCD) &&
1693 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
1694 !(pcdFocus->clientState == MINIMIZED_STATE)
1699 * 1. User clicked in the client area AND
1700 * 2. Input model is Globally Active AND
1701 * 3. Keyboard focus policy is explicit
1704 /* this window has WM_TAKE_FOCUS set and InputField false. */
1705 /* just send a message. */
1706 SendClientMsg (pcdFocus->client,
1707 (long) wmGD.xa_WM_PROTOCOLS,
1708 (long) wmGD.xa_WM_TAKE_FOCUS,
1709 focusTime, NULL, 0);
1713 if ((pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1714 !(pcdFocus->clientState == MINIMIZED_STATE))
1717 * Locally Active Input Model - Send a take focus message to the client.
1720 SendClientMsg (pcdFocus->client,
1721 (long) wmGD.xa_WM_PROTOCOLS,
1722 (long) wmGD.xa_WM_TAKE_FOCUS,
1723 focusTime, NULL, 0);
1727 * Don't set the input focus if the window has input_field set
1728 * to False or has expressed an interest in WM_TAKE_FOCUS
1729 * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1730 * and the user click in the client area. If the user clicks
1731 * on the titlebar or traverses to this window via f.next_key,
1732 * set the focus so that the user can access the window menu
1736 if ( wmGD.enforceKeyFocus || /* res - default == True. */
1737 (flags & ALWAYS_SET_FOCUS) ||
1738 !(flags & CLIENT_AREA_FOCUS)|| /* clicked on frame? */
1739 pcdFocus->inputFocusModel || /* Pass.|Glob. Active */
1740 (pcdFocus->clientState == MINIMIZED_STATE)
1743 if ( !(flags & CLIENT_AREA_FOCUS) &&
1744 !pcdFocus->inputFocusModel &&
1745 !(pcdFocus->clientState == MINIMIZED_STATE))
1747 /* the window doesn't want the focus - set it to the frame */
1748 /* user clicked on the frame but we don't want the focus */
1749 /* set it to the client's frame */
1750 XSetInputFocus (DISPLAY, pcdFocus->clientBaseWin,
1751 RevertToPointerRoot, focusTime);
1753 else if ( !(flags & CLIENT_AREA_FOCUS) &&
1754 !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1755 pcdFocus->inputFocusModel
1758 XSetInputFocus (DISPLAY, focusWindow,
1759 RevertToPointerRoot, focusTime);
1763 XSetInputFocus (DISPLAY, focusWindow,
1764 RevertToParent, focusTime);
1770 * We've decided that the window shouldn't get the focus,
1771 * so don't change the focus.
1773 pcdFocus = wmGD.nextKeyboardFocus;
1779 XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1783 wmGD.nextKeyboardFocus = pcdFocus;
1787 } /* END OF FUNCTION Do_Focus_Key */
1792 /***********************<->*************************************
1794 * F_Goto_Workspace (args, pCD, event)
1798 * This is the window manager function handler for switching
1799 * to another workspace by name.
1803 * args = action function and arguments
1805 * pCD = pointer to the ClientData
1807 * event = X event that invoked the function (key, button, or menu/NULL)
1815 ******************************<->***********************************/
1817 F_Goto_Workspace (String args, ClientData *pCD, XEvent *event)
1819 WmScreenData *pSD = ACTIVE_PSD;
1824 * Compare argument against both resource name
1825 * and workspace title, take the first match.
1827 xms = XmStringCreate (args, XmFONTLIST_DEFAULT_TAG);
1828 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1830 if (!strcmp(pSD->pWS[iwsx].name, args) ||
1831 XmStringCompare (xms, pSD->pWS[iwsx].title))
1840 if (iwsx >= pSD->numWorkspaces)
1842 Warning (((char *)GETMESSAGE(26, 4,
1843 "Invalid workspace name specified for f.goto_workspace")));
1847 ChangeToWorkspace (&pSD->pWS[iwsx]);
1852 } /* END OF FUNCTION F_Goto_Workspace */
1858 /******************************<->*************************************
1860 * Boolean F_Help (String args, ClientData *pCD, XEvent *event)
1864 * Invoke help on the workspace manager
1868 * args - incoming values
1869 * pCD - associated client data structure
1870 * event - what triggered this call
1874 * Return - True if the call occurs; false otherwise.
1879 ******************************<->***********************************/
1881 F_Help (String args, ClientData *pCD, XEvent *event)
1885 rval = WmDtHelp(args);
1887 } /* END OF FUNCTION F_Help */
1890 /******************************<->*************************************
1892 * Boolean F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1896 * Invoke item help on the frontpanel
1901 * pCD - associated client data structure ??
1902 * event - what triggered this call
1906 * Return - True if the call occurs; false otherwise.
1911 ******************************<->***********************************/
1913 F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1916 * Help mode event processing interferes
1917 * with slide up windows. Don't continue
1918 * if windows are sliding.
1920 if (wmGD.iSlideUpsInProgress == 0)
1922 (void) WmDtHelpMode();
1925 } /* END OF FUNCTION F_Help_Mode */
1929 /******************************<->*************************************
1931 * F_Next_Key (args, pCD, event)
1936 * This is the window manager function handler for setting the keyboard
1937 * input focus to the next window in the set of managed windows.
1942 * args = (immediate value) window type flags
1944 * pCD = pointer to the client data
1946 * event = X event that invoked the function (key, button, or menu/NULL)
1948 *************************************<->***********************************/
1950 Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1952 #ifdef ROOT_ICON_MENU
1953 Boolean focused = False;
1954 #endif /* ROOT_ICON_MENU */
1955 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1957 #ifdef ROOT_ICON_MENU
1959 #endif /* ROOT_ICON_MENU */
1960 FocusNextWindow ((unsigned long)args,
1961 GetFunctionTimestamp ((XButtonEvent *)event));
1962 #ifdef ROOT_ICON_MENU
1963 if (focused && wmGD.iconClick &&
1964 event && event->type == KeyPress &&
1965 wmGD.nextKeyboardFocus &&
1966 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1967 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1970 * Post system menu from the icon
1972 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1975 #endif /* ROOT_ICON_MENU */
1980 } /* END OF FUNCTION F_Next_Key */
1984 /*************************************<->*************************************
1986 * F_Prev_Cmap (args, pCD, event)
1991 * This is the window manager function handler installing the previous
1992 * colormap in the list of client window colormaps.
1994 *************************************<->***********************************/
1996 Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
2000 pCD = ACTIVE_PSD->colormapFocus;
2003 if (pCD && (pCD->clientCmapCount > 0) &&
2004 ((pCD->clientState == NORMAL_STATE) ||
2005 (pCD->clientState == MAXIMIZED_STATE)))
2007 if (--(pCD->clientCmapIndex) < 0)
2009 pCD->clientCmapIndex = pCD->clientCmapCount - 1;
2011 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2012 if (ACTIVE_PSD->colormapFocus == pCD)
2014 #ifndef OLD_COLORMAP /* colormap */
2016 * We just re-ordered the colormaps list,
2017 * so we need to re-run the whole thing.
2019 pCD->clientCmapFlagsInitialized = 0;
2020 ProcessColormapList (ACTIVE_PSD, pCD);
2021 #else /* OSF original */
2022 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2029 } /* END OF FUNCTION F_Prev_Cmap */
2033 /*************************************<->*************************************
2035 * F_Prev_Key (args, pCD, event)
2040 * This is the window manager function handler for setting the keyboard
2041 * input focus to the previous window in the set of managed windows.
2046 * args = (immediate value) window type flags
2048 * pCD = pointer to the client data
2050 * event = X event that invoked the function (key, button, or menu/NULL)
2052 *************************************<->***********************************/
2054 Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
2056 #ifdef ROOT_ICON_MENU
2057 Boolean focused = False;
2058 #endif /* ROOT_ICON_MENU */
2059 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
2061 #ifdef ROOT_ICON_MENU
2063 #endif /* ROOT_ICON_MENU */
2064 FocusPrevWindow ((unsigned long)args,
2065 GetFunctionTimestamp ((XButtonEvent *)event));
2066 #ifdef ROOT_ICON_MENU
2067 if (focused && wmGD.iconClick &&
2068 event && event->type == KeyPress &&
2069 wmGD.nextKeyboardFocus &&
2070 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
2071 !P_ICON_BOX(wmGD.nextKeyboardFocus))
2074 * Post system menu from the icon
2076 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
2079 #endif /* ROOT_ICON_MENU */
2085 } /* END OF FUNCTION F_Prev_Key */
2087 /***********************<->*************************************
2089 * F_Post_FpMenu (args, pCD, event)
2094 * This is the window manager function handler for posting
2095 * the Front Panel window menu.
2099 * args = arguments (none)
2101 * pCD = pointer to the FP ClientData
2103 * event = X button press that invoked the function
2105 ******************************<->***********************************/
2108 F_Post_FpMenu (String args, ClientData *pCD, XEvent *event)
2110 static MenuSpec *fpMenuSpec = (MenuSpec *)NULL;
2112 if (event->type != ButtonPress)
2117 WmScreenData *pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2122 newMenuName = pCD ? pCD->systemMenu : "DtPanelMenu";
2124 for (oldSpec = pSD->menuSpecs;
2125 oldSpec != (MenuSpec *)NULL;
2126 oldSpec = oldSpec->nextMenuSpec)
2128 if (oldSpec->name && (strcmp(oldSpec->name, newMenuName) == 0))
2134 fpMenuSpec = DuplicateMenuSpec(oldSpec);
2137 * TEMPORARILY modify pSD so the new menu will be
2138 * created on DISPLAY1 instead of DISPLAY.
2140 fpMenuSpec->nextMenuSpec = pSD->menuSpecs;
2141 pSD->menuSpecs = fpMenuSpec;
2142 tmpWidget = pSD->screenTopLevelW;
2143 pSD->screenTopLevelW = pSD->screenTopLevelW1;
2145 (void)MAKE_MENU (pSD, pCD, newMenuName,
2146 F_CONTEXT_NORMAL, F_CONTEXT_NORMAL,
2147 (MenuItem *) NULL, FALSE);
2150 pSD->screenTopLevelW = tmpWidget;
2151 pSD->menuSpecs = fpMenuSpec->nextMenuSpec;
2154 PostMenu (fpMenuSpec, pCD, event->xbutton.x_root, event->xbutton.y_root,
2155 event->xbutton.button, F_CONTEXT_NORMAL, POST_AT_XY, event);
2157 _XmGetMenuState(XtParent(fpMenuSpec->menuWidget))
2158 ->MS_LastManagedMenuTime = event->xbutton.time;
2164 /***********************<->*************************************
2166 * F_Push_Recall (args, pCD, event)
2171 * This is the window manager function handler for invoking/topping
2172 * push_recall clients.
2179 * pCD = pointer to the ClientData
2181 * event = X event that invoked the function (key, button, or menu/NULL)
2186 * RETURN = if True then further button binding/function processing can
2187 * be done for the event that caused this function to be called.
2191 ******************************<->***********************************/
2194 F_Push_Recall (String args, ClientData *pCD, XEvent *event)
2196 WmPushRecallArg *pPRP;
2198 WmFpPushRecallClientData *pPRCD;
2200 pPRP = (WmPushRecallArg *) args;
2201 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2203 if (pPRP->ixReg < pSD->numPushRecallClients)
2205 /* get slot for this client */
2206 pPRCD = &(pSD->pPRCD[pPRP->ixReg]);
2209 * If the client is already running, then top it in this workspace,
2210 * else invoke the function to start it.
2214 /* Client is managed already. */
2215 if (!(ClientInWorkspace (pSD->pActiveWS, pPRCD->pCD)))
2217 WorkspaceID *wsRemoveList;
2221 * Move client to current workspace
2223 wsRemoveList = GetListOfOccupiedWorkspaces (pPRCD->pCD,
2225 RemoveClientFromWorkspaces (pPRCD->pCD, wsRemoveList,
2227 XtFree ((char *)wsRemoveList);
2228 AddClientToWorkspaces (pPRCD->pCD, &(pSD->pActiveWS->id), 1);
2229 SetClientWsIndex(pPRCD->pCD);
2230 SetClientState(pPRCD->pCD,
2231 pPRCD->pCD->clientState & ~UNSEEN_STATE, CurrentTime);
2234 /* Make this client visible */
2236 wmGD.bSuspendSecondaryRestack = True;
2238 F_Normalize_And_Raise (NULL, pPRCD->pCD, event);
2240 wmGD.bSuspendSecondaryRestack = False;
2245 struct timeval tvNow;
2247 Boolean bWaiting = False;
2249 if (pPRCD->tvTimeout.tv_sec != 0)
2251 gettimeofday (&tvNow, &tz);
2253 if ((pPRCD->tvTimeout.tv_sec > tvNow.tv_sec) ||
2254 ((pPRCD->tvTimeout.tv_sec == tvNow.tv_sec) &&
2255 (pPRCD->tvTimeout.tv_usec > tvNow.tv_usec)))
2257 /* still waiting for client to start */
2264 long clientTimeout = 0;
2267 WmPanelistObject pPanelist;
2269 pPanelist = (WmPanelistObject) pSD->wPanelist;
2271 /* invoke the function to start the client */
2272 pPRP->wmFunc ( pPRP->pArgs, pCD, event);
2274 if (pPanelist && panel.busy_light_data)
2276 /* set timeout value */
2279 XmNclientTimeoutInterval, &clientTimeout); ac++;
2280 XtGetValues (panel.busy_light_data->icon, (ArgList)al, ac);
2284 * ClientTimeout is in milliseconds, timeval values
2285 * are in seconds and microseconds.
2287 gettimeofday (&(pPRCD->tvTimeout), &tz);
2289 pPRCD->tvTimeout.tv_sec += clientTimeout / 1000;
2290 pPRCD->tvTimeout.tv_usec +=
2291 (clientTimeout % 1000) * 1000;
2293 pPRCD->tvTimeout.tv_sec += pPRCD->tvTimeout.tv_usec / 1000000;
2294 pPRCD->tvTimeout.tv_usec %= 1000000;
2301 } /* END OF FUNCTION F_Push_Recall */
2304 /*************************************<->*************************************
2306 * F_Pass_Key (args, pCD, event)
2311 * This is a function stub for the f.pass_key window manager function.
2316 * args = (immediate value) window type flags
2318 * pCD = pointer to the client data
2320 * event = X event that invoked the function (key, button, or menu/NULL)
2322 *************************************<->***********************************/
2324 Boolean F_Pass_Key (args, pCD, event)
2330 if (wmGD.passKeysActive)
2333 * Get out of pass keys mode.
2336 wmGD.passKeysActive = False;
2337 wmGD.passKeysKeySpec = NULL;
2342 * Get into pass keys mode.
2345 wmGD.passKeysActive = True;
2350 } /* END OF FUNCTION F_Pass_Key */
2354 /*************************************<->*************************************
2356 * F_Maximize (args, pCD, event)
2361 * This is the window manager function handler for maximizing a client
2364 *************************************<->***********************************/
2366 Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
2368 if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
2370 SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
2371 GetFunctionTimestamp ((XButtonEvent *)event),
2372 GetEventInverseMask(event));
2377 } /* END OF FUNCTION F_Maximize */
2381 /*************************************<->*************************************
2383 * F_Menu (args, pCD, event)
2388 * This is the window manager function handler for posting a menu.
2389 * This function can only be invoked by a key or button event.
2390 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2391 * NULL when the menu is unposted.
2393 *************************************<->***********************************/
2395 Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
2398 Context menuContext;
2399 unsigned int button;
2402 long flags = POST_AT_XY;
2407 ((event->type == ButtonPress) || (event->type == ButtonRelease)))
2409 button = event->xbutton.button;
2410 x = event->xbutton.x_root;
2411 y = event->xbutton.y_root;
2412 if (event->type == ButtonRelease)
2414 flags |= POST_TRAVERSAL_ON;
2418 * Root menu, if posted with button press, then
2419 * set up to handle root menu click to make the menu
2422 else if (wmGD.rootButtonClick && (event->type == ButtonPress))
2424 if (wmGD.bReplayedButton)
2426 /* This button was replayed, it most likely dismissed
2427 a previous sticky menu, don't post a menu here */
2430 wmGD.checkHotspot = True;
2431 wmGD.hotspotRectangle.x = x - wmGD.moveThreshold/2;
2432 wmGD.hotspotRectangle.y = y - wmGD.moveThreshold/2;
2433 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2434 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2439 ((event->type == KeyPress) || (event->type == KeyRelease)))
2442 x = event->xkey.x_root;
2443 y = event->xkey.y_root;
2448 * A button or key event must be used to post a menu using this
2457 if (pCD->clientState == NORMAL_STATE)
2459 menuContext = F_CONTEXT_NORMAL;
2461 else if (pCD->clientState == MAXIMIZED_STATE)
2463 menuContext = F_CONTEXT_MAXIMIZE;
2467 menuContext = F_CONTEXT_ICON;
2469 if (P_ICON_BOX(pCD) &&
2470 event->xany.window == ICON_FRAME_WIN(pCD))
2472 if (pCD->clientState == MINIMIZED_STATE)
2474 menuContext = F_SUBCONTEXT_IB_IICON;
2478 menuContext = F_SUBCONTEXT_IB_WICON;
2484 menuContext = F_CONTEXT_ROOT;
2488 /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
2489 * This should have been done in MakeWmFunctionResources().
2492 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2493 if ((menuSpec = MAKE_MENU (pSD, pCD, args, menuContext,
2494 menuContext, (MenuItem *) NULL, FALSE)) != NULL)
2496 PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
2501 } /* END OF FUNCTION F_Menu */
2504 /*************************************<->*************************************
2506 * F_Minimize (args, pCD, event)
2511 * This is the window manager function handler for minimizing a client
2514 *************************************<->***********************************/
2516 Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
2518 ClientData *pcdLeader;
2524 * If the window is a transient then minimize the entire transient
2525 * tree including the transient leader.
2528 pcdLeader = (pCD->transientLeader) ?
2529 FindTransientTreeLeader (pCD) : pCD;
2530 if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
2532 SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
2533 GetFunctionTimestamp ((XButtonEvent *)event),
2534 GetEventInverseMask(event));
2540 } /* END OF FUNCTION F_Minimize */
2544 /*************************************<->*************************************
2546 * F_Move (args, pCD, event)
2551 * This is the window manager function handler for moving a client window
2554 *************************************<->***********************************/
2556 Boolean F_Move (String args, ClientData *pCD, XEvent *event)
2558 if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
2560 StartClientMove (pCD, event);
2561 HandleClientFrameMove (pCD, event);
2566 } /* END OF FUNCTION F_Move */
2570 /*************************************<->*************************************
2572 * F_Next_Cmap (args, pCD, event)
2577 * This is the window manager function handler installing the next
2578 * colormap in the list of client window colormaps.
2580 *************************************<->***********************************/
2582 Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
2586 pCD = ACTIVE_PSD->colormapFocus;
2589 if (pCD && (pCD->clientCmapCount > 0) &&
2590 ((pCD->clientState == NORMAL_STATE) ||
2591 (pCD->clientState == MAXIMIZED_STATE)))
2593 if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
2595 pCD->clientCmapIndex = 0;
2597 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2598 if (ACTIVE_PSD->colormapFocus == pCD)
2600 #ifndef OLD_COLORMAP /* colormap */
2602 * We just re-ordered the colormaps list,
2603 * so we need to re-run the whole thing.
2605 pCD->clientCmapFlagsInitialized = 0;
2606 ProcessColormapList (ACTIVE_PSD, pCD);
2607 #else /* OSF original */
2608 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2615 } /* END OF FUNCTION F_Next_Cmap */
2619 /*************************************<->*************************************
2621 * F_Nop (args, pCD, event)
2626 * This is the window manager function handler for doing nothing.
2628 *************************************<->***********************************/
2630 Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2635 } /* END OF FUNCTION F_Nop */
2639 /*************************************<->*************************************
2641 * F_Normalize (args, pCD, event)
2646 * This is the window manager function handler for putting a client window
2647 * in the normal state.
2649 *************************************<->***********************************/
2651 Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2656 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2657 GetFunctionTimestamp ((XButtonEvent *)event),
2658 GetEventInverseMask(event));
2663 } /* END OF FUNCTION F_Normalize */
2667 /*************************************<->*************************************
2669 * F_Normalize_And_Raise (args, pCD, event)
2674 * This is the window manager function handler for putting a client window
2675 * in the normal state and raising it from and icon.
2677 *************************************<->***********************************/
2679 Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2682 WmWorkspaceData *pWS;
2687 pSD = PSD_FOR_CLIENT (pCD);
2691 pWS = pSD->pActiveWS;
2693 if (pSD->useIconBox &&
2694 wmGD.useFrontPanel &&
2695 pSD->iconBoxControl &&
2696 (!strcmp(args, WmNiconBox)))
2699 * There's an icon box in the front panel and this is a
2700 * request to pop up the icon box.
2702 IconBoxPopUp (pWS, True);
2709 if (pCD->clientState == MINIMIZED_STATE)
2711 /* normalize window */
2712 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2715 ? GetFunctionTimestamp ((XButtonEvent *)event)
2717 GetEventInverseMask(event));
2721 /* Make sure we are in NORMAL_STATE */
2722 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2723 GetFunctionTimestamp ((XButtonEvent *)event),
2724 GetEventInverseMask(event));
2726 /* Raise the window and set the keyboard focus to the window */
2728 wmGD.bSuspendSecondaryRestack = True;
2730 F_Raise (NULL, pCD, (XEvent *)NULL);
2732 wmGD.bSuspendSecondaryRestack = False;
2734 if (wmGD.raiseKeyFocus)
2736 F_Focus_Key (NULL, pCD,
2739 : ((XEvent *)NULL)));
2742 wmGD.clickData.clickPending = False;
2743 wmGD.clickData.doubleClickPending = False;
2748 } /* END OF FUNCTION F_Normalize_And_Raise */
2752 /*************************************<->*************************************
2754 * F_Restore (args, pCD, event)
2759 * This is the window manager function handler for putting a client window
2760 * in the normal state.
2762 *************************************<->***********************************/
2764 Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2771 * If current state is MAXIMIZED state then just go to NORMAL state,
2772 * otherwise (you are in MINIMIZED state) return to previous state.
2775 if (pCD->clientState == MAXIMIZED_STATE)
2777 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2778 GetFunctionTimestamp ((XButtonEvent *)event),
2779 GetEventInverseMask(event));
2785 newState = MAXIMIZED_STATE;
2789 newState = NORMAL_STATE;
2792 SetClientStateWithEventMask (pCD, newState,
2793 GetFunctionTimestamp ((XButtonEvent *)event),
2794 GetEventInverseMask(event));
2800 } /* END OF FUNCTION F_Restore */
2804 /*************************************<->*************************************
2806 * F_Restore_And_Raise (args, pCD, event)
2811 * This is the window manager function handler for putting a client window
2812 * in the normal state and raising it from and icon.
2814 *************************************<->***********************************/
2816 Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2822 if (pCD->clientState == MINIMIZED_STATE)
2824 /* Restore window */
2827 newState = MAXIMIZED_STATE;
2831 newState = NORMAL_STATE;
2834 SetClientStateWithEventMask (pCD, newState,
2837 ? GetFunctionTimestamp ((XButtonEvent *)event)
2839 GetEventInverseMask(event));
2843 /* Make sure we restore the window first */
2844 F_Restore (NULL, pCD, event);
2846 /* Raise the window and set the keyboard focus to the window */
2848 wmGD.bSuspendSecondaryRestack = True;
2850 F_Raise (NULL, pCD, (XEvent *)NULL);
2852 wmGD.bSuspendSecondaryRestack = False;
2854 if (wmGD.raiseKeyFocus)
2856 F_Focus_Key (NULL, pCD,
2859 : ((XEvent *)NULL)));
2862 wmGD.clickData.clickPending = False;
2863 wmGD.clickData.doubleClickPending = False;
2868 } /* END OF FUNCTION F_Restore_And_Raise */
2872 /*************************************<->*************************************
2874 * F_Pack_Icons (args, pCD, event)
2879 * This is the window manager function handler for packing icons in the
2880 * icon box or on the desktop.
2882 *************************************<->***********************************/
2884 Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2889 if (ACTIVE_PSD->useIconBox)
2891 pIBD = ACTIVE_WS->pIconBox;
2894 while (pCD != pIBD->pCD_iconBox)
2896 if (pIBD->pNextIconBox)
2898 pIBD = pIBD->pNextIconBox;
2909 PackIconBox (pIBD, False, False, 0, 0);
2924 } /* END OF FUNCTION F_Pack_Icons */
2927 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
2928 /*************************************<->*************************************
2930 * F_Post_RMenu (args, pCD, event)
2935 * This is the window manager function handler for posting the
2937 * This function can only be invoked by a key event.
2939 *************************************<->***********************************/
2941 Boolean F_Post_RMenu (String args, ClientData *pCD, XEvent *event)
2944 unsigned int button = NoButton;
2946 long flags = POST_AT_XY;
2952 if ((event->type == KeyPress) || (event->type == KeyRelease))
2955 /* Find the root menu spec */
2956 for (rootMenu = ACTIVE_PSD->menuSpecs;
2957 rootMenu != (MenuSpec *) NULL;
2958 rootMenu = rootMenu->nextMenuSpec)
2960 if (strcmp(rootMenu->name, ACTIVE_PSD->rootMenu) == 0)
2964 /* If we couldn't find the root menu, then do nothing. */
2965 if (rootMenu == (MenuSpec *) NULL)
2970 XQueryPointer(DISPLAY, ACTIVE_ROOT,
2971 &rwin, &cwin, &x, &y, &winx, &winy, &mask);
2973 PostMenu (rootMenu, NULL, x, y, NoButton, F_CONTEXT_ROOT,
2980 } /* END OF FUNCTION F_Post_RMenu */
2981 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
2984 /*************************************<->*************************************
2986 * F_Post_SMenu (args, pCD, event)
2991 * This is the window manager function handler for posting the system menu
2992 * for the specified client.
2993 * This function can only be invoked by a key or button event.
2994 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2995 * NULL when the menu is unposted.
2997 *************************************<->***********************************/
2999 Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
3001 Context menuContext;
3005 * An event must be used to post the system menu using this function.
3008 if (event && pCD && pCD->systemMenuSpec)
3011 * Determine whether the keyboard is posting the menu and post
3012 * the menu at an appropriate place.
3015 if (pCD->clientState == NORMAL_STATE)
3017 menuContext = F_CONTEXT_NORMAL;
3019 else if (pCD->clientState == MAXIMIZED_STATE)
3021 menuContext = F_CONTEXT_MAXIMIZE;
3025 menuContext = F_CONTEXT_ICON;
3027 if (P_ICON_BOX(pCD) &&
3028 event->xany.window == ICON_FRAME_WIN(pCD))
3030 if (pCD->clientState == MINIMIZED_STATE)
3032 menuContext = F_SUBCONTEXT_IB_IICON;
3036 menuContext = F_SUBCONTEXT_IB_WICON;
3040 if ((event->type == KeyPress) || (event->type == KeyRelease))
3043 * Set up for "sticky" menu processing if specified.
3046 if (pCD->clientState == MINIMIZED_STATE ||
3047 menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
3051 wmGD.checkHotspot = True;
3054 else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
3056 wmGD.checkHotspot = True;
3059 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
3062 else if (event->type == ButtonPress)
3066 * Root menu, if posted with button press, then
3067 * set up to handle root menu click to make the menu
3070 if (wmGD.rootButtonClick && (!wmGD.checkHotspot))
3072 wmGD.checkHotspot = True;
3073 wmGD.hotspotRectangle.x =
3074 event->xbutton.x_root - wmGD.moveThreshold/2;
3075 wmGD.hotspotRectangle.y =
3076 event->xbutton.y_root - wmGD.moveThreshold/2;
3077 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
3078 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
3081 PostMenu (pCD->systemMenuSpec, pCD,
3082 event->xbutton.x_root, event->xbutton.y_root,
3083 event->xbutton.button, menuContext, POST_AT_XY, event);
3085 else if (event->type == ButtonRelease)
3087 PostMenu (pCD->systemMenuSpec, pCD,
3088 event->xbutton.x_root, event->xbutton.y_root,
3089 event->xbutton.button, menuContext,
3090 POST_AT_XY | POST_TRAVERSAL_ON, event);
3096 } /* END OF FUNCTION F_PostSMenu */
3100 /*************************************<->*************************************
3102 * F_Kill (args, pCD, event)
3107 * This is the window manager function handler for terminating a client.
3108 * Essentially the client connection is shut down.
3110 *************************************<->***********************************/
3112 Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
3114 if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
3116 Boolean do_delete_window =
3117 pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
3118 Boolean do_save_yourself =
3119 pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
3121 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
3126 * Get the widget for the subpanel
3127 * (Should be only child of the shell!)
3129 wPanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
3132 SlideSubpanelBackIn (pCD, wPanel);
3136 if (pCD->clientFlags & ICON_BOX)
3139 * When the front panel is used with the icon box,
3140 * "Close" hides the icon box into the front panel.
3142 if ((wmGD.useFrontPanel) &&
3143 (pCD->pSD->iconBoxControl) &&
3144 (IconBoxShowing(pCD->pSD->pActiveWS)))
3146 IconBoxPopUp (pCD->pSD->pActiveWS, False);
3149 else if (!do_delete_window && !do_save_yourself)
3151 XKillClient (DISPLAY, pCD->client);
3155 if (do_delete_window)
3158 * The client wants to be notified, not killed.
3161 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3162 (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
3166 * HP does not want to send a client message for both
3167 * delete_window AND save_yourself. The current OSF
3168 * patch did just that. This "else if" returns dtwm
3169 * to the behavior of dt 2.01
3171 else if (do_save_yourself)
3173 if (do_save_yourself)
3177 * Send a WM_SAVE_YOURSELF message and wait for a change to
3178 * the WM_COMMAND property.
3179 * !!! button and key input should be kept from the window !!!
3182 if (AddWmTimer (TIMER_QUIT,
3183 (unsigned long) wmGD.quitTimeout, pCD))
3185 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3186 (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
3188 pCD->clientFlags |= CLIENT_TERMINATING;
3192 XKillClient (DISPLAY, pCD->client);
3200 } /* END OF FUNCTION F_Kill */
3204 /*************************************<->*************************************
3206 * F_Marquee_Selection (args, pCD, event)
3211 * This is the window manager function handler for selecting
3212 * non-window manager objects on the root window.
3214 *************************************<->***********************************/
3216 Boolean F_Marquee_Selection (String args, ClientData *pCD, XEvent *event)
3221 * This function only valid in root context
3223 StartMarqueeSelect (ACTIVE_PSD, event);
3224 HandleMarqueeSelect (ACTIVE_PSD, event);
3229 } /* END OF FUNCTION F_Marquee_Selection */
3231 /*************************************<->*************************************
3233 * RefreshByClearing (win)
3238 * Recursively refresh this window and its children by doing
3241 *************************************<->***********************************/
3243 RefreshByClearing (Window win)
3247 Window root, parent;
3248 unsigned int nchildren;
3249 Window *winChildren;
3251 /* clear this window */
3252 XClearArea(DISPLAY, win, 0, 0, 0, 0, True);
3254 /* find any children and clear them, too */
3255 status = XQueryTree(DISPLAY, win, &root, &parent, &winChildren,
3259 /* recurse for each child window */
3260 for (i=0; i<nchildren; ++i)
3262 RefreshByClearing(winChildren[i]);
3267 XFree((char *)winChildren);
3273 /*************************************<->*************************************
3275 * F_Refresh (args, pCD, event)
3280 * This is the window manager function handler for causing all windows
3281 * in the workspace to be redrawn.
3283 *************************************<->***********************************/
3285 Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
3290 if (wmGD.refreshByClearing)
3292 RefreshByClearing (ACTIVE_ROOT);
3297 /* default background_pixmap is None */
3298 win = XCreateWindow (DISPLAY,
3300 (unsigned int) DisplayWidth (DISPLAY,
3302 (unsigned int) DisplayHeight (DISPLAY,
3309 (XSetWindowAttributes *)NULL);
3311 XMapWindow (DISPLAY, win);
3312 XDestroyWindow (DISPLAY, win);
3320 } /* END OF FUNCTION F_Refresh */
3324 /*************************************<->*************************************
3326 * F_Resize (args, pCD, event)
3331 * This is the window manager function handler for resizing a client window.
3333 *************************************<->***********************************/
3335 Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
3337 if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
3338 ((pCD->clientState == NORMAL_STATE) ||
3339 (pCD->clientState == MAXIMIZED_STATE)))
3341 StartClientResize (pCD, event);
3342 HandleClientFrameResize (pCD, event);
3347 } /* END OF FUNCTION F_Resize */
3351 /*************************************<->*************************************
3353 * F_Restart (args, pCD, event)
3358 * This is the window manager function handler for restarting the window
3361 *************************************<->***********************************/
3363 Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
3366 if (args && *args && !strcmp (args, DTWM_REQP_NO_CONFIRM))
3368 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3372 if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
3374 ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
3378 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3382 } /* END OF FUNCTION F_Restart */
3386 /*************************************<->*************************************
3388 * Do_Restart (dummy)
3393 * Callback function for restarting the window manager.
3395 *************************************<->***********************************/
3397 void Do_Restart (Boolean dummy)
3399 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3401 } /* END OF FUNCTION Do_Restart */
3405 /*************************************<->*************************************
3407 * RestartWm (startupFlags)
3412 * Actually restarts the window manager.
3417 * startupFlags = flags to be put into the Wm_INFO property for restart.
3419 *************************************<->***********************************/
3421 void RestartWm (long startupFlags)
3423 ClientListEntry *pNextEntry;
3427 for (scr=0; scr<wmGD.numScreens; scr++)
3429 if(wmGD.Screens[scr].managed)
3433 * Set up the _MOTIF_WM_INFO property on the root window
3434 * to indicate a restart.
3437 SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
3439 SaveResources(&wmGD.Screens[scr]);
3442 * Unmap client windows and reparent them to the root window.
3445 pNextEntry = wmGD.Screens[scr].lastClient;
3448 if (pNextEntry->type == NORMAL_STATE)
3450 if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
3452 if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
3454 XUnmapWindow (DISPLAY,
3455 pNextEntry->pCD->clientFrameWin);
3460 DeFrameClient (pNextEntry->pCD);
3463 pNextEntry = pNextEntry->prevSibling;
3465 UnParentControls (&wmGD.Screens[scr], True);
3471 /* shut down the messaging connection */
3477 * This fixes restart problem when going from explicit focus to
3478 * pointer focus. Window under pointer was not getting focus indication
3479 * until pointer was moved to new window, or out of and into the
3483 XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
3484 XSync (DISPLAY, False);
3487 CLOSE_FILES_ON_EXEC();
3488 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3491 * Restart the window manager with the initial arguments plus
3492 * the restart settings.
3495 execvp (*(wmGD.argv), wmGD.argv);
3498 Warning (((char *)GETMESSAGE(26, 1,
3499 "The window manager restart failed. The window manager program could not \
3500 be found or could not be executed.")));
3502 Warning ("Cannot restart the window manager");
3508 } /* END OF FUNCTION RestartWm */
3511 /*************************************<->*************************************
3513 * DeFrameClient (pCD)
3518 * Unmaps a client window (and client icon window) and reparents the
3519 * window back to the root.
3524 * pCD = pointer to the client data for the window to be de-framed.
3526 *************************************<->***********************************/
3528 void DeFrameClient (ClientData *pCD)
3532 XWindowChanges windowChanges;
3536 if (pCD->clientState != MINIMIZED_STATE)
3538 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
3541 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
3543 XUnmapWindow (DISPLAY, pCD->iconWindow);
3544 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
3546 XReparentWindow (DISPLAY, pCD->iconWindow,
3547 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
3548 pCD->pWsList->iconY);
3550 XReparentWindow (DISPLAY, pCD->iconWindow,
3551 ROOT_FOR_CLIENT(pCD), pCD->iconX, pCD->iconY);
3562 if(wmGD.positionIsFrame)
3564 CalculateGravityOffset (pCD, &xoff, &yoff);
3565 x = pCD->clientX - xoff;
3566 y = pCD->clientY - yoff;
3575 #ifndef UNMAP_ON_RESTART
3576 if (pCD->clientState == MINIMIZED_STATE)
3578 XUnmapWindow (DISPLAY, pCD->client);
3581 XUnmapWindow (DISPLAY, pCD->client);
3583 XRemoveFromSaveSet (DISPLAY, pCD->client);
3584 XReparentWindow (DISPLAY, pCD->client,
3585 ROOT_FOR_CLIENT(pCD), x, y);
3587 if (pCD->transientChildren)
3589 DeFrameClient (pCD->transientChildren);
3595 windowChanges.x = x;
3596 windowChanges.y = y;
3597 windowChanges.border_width = pCD->xBorderWidth;
3598 XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
3601 if (pCD->transientLeader)
3603 pCD = pCD->transientSiblings;
3611 } /* END OF FUNCTION DeFrameClient */
3613 /******************************<->*************************************
3615 * F_Toggle_Front_Panel (args, pCD, event)
3620 * This is the window manager function handler for toggling the
3621 * front panel off and on.
3622 ******************************<->***********************************/
3625 F_Toggle_Front_Panel (String args, ClientData *pCD, XEvent *event)
3628 WmPanelistObject pPanelist;
3632 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3636 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3642 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3643 wmGD.windowContextType, (caddr_t *)&pCD);
3649 if (pCD->clientState & MINIMIZED_STATE)
3651 SetClientState (pCD, NORMAL_STATE,
3652 GetFunctionTimestamp ((XButtonEvent *)event));
3656 SetClientState (pCD, MINIMIZED_STATE,
3657 GetFunctionTimestamp ((XButtonEvent *)event));
3662 } /* END OF FUNCTION F_Toggle_Front_Panel */
3665 /******************************<->*************************************
3667 * Boolean F_Version (String args, ClientData *pCD, XEvent *event)
3671 * Invoke the help on version dialogue.
3675 * args - incoming values
3676 * pCD - associated client data structure
3677 * event - what triggered this call
3681 * Return - True if the call occurs; false otherwise.
3686 ******************************<->***********************************/
3688 F_Version (String args, ClientData *pCD, XEvent *event)
3691 WmPanelistObject pPanelist;
3695 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3699 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3704 WmDtHelpOnVersion (O_Shell (pPanelist));
3709 } /* END OF FUNCTION F_Version */
3712 /******************************<->*************************************
3714 * F_Send_Msg (args, pCD, event)
3719 * This is the window manager function handler for sending a client
3720 * message event to a client window.
3725 * args = (immediate value) message id
3727 * pCD = pointer to the client data
3729 * event = X event that invoked the function (key, button, or menu/NULL)
3732 ******************************<->***********************************/
3734 Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
3739 if (pCD && pCD->mwmMessagesCount)
3742 * A message id must be made "active" by being included in the
3743 * _MWM_MESSAGES property before the associated message can be sent.
3746 for (i = 0; i < pCD->mwmMessagesCount; i++)
3748 if (pCD->mwmMessages[i] == (long)args)
3750 SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES,
3751 (long)args, CurrentTime, NULL, 0);
3759 } /* END OF FUNCTION F_Send_Msg */
3763 /*************************************<->*************************************
3765 * F_Separator (args, pCD, event)
3770 * This is a placeholder function; it should never be called.
3772 *************************************<->***********************************/
3774 Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
3779 } /* END OF FUNCTION F_Separator */
3782 Boolean ForceRaiseWindow (ClientData *pcd)
3786 WmScreenData *pSD = (ACTIVE_WS)->pSD;
3788 XWindowChanges changes;
3789 Boolean restack = False;
3792 if (pSD->clientList->type == MINIMIZED_STATE)
3794 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
3798 stackWindow = pSD->clientList->pCD->clientFrameWin;
3803 * Windows did not raise on regular f.raise because the raise was
3804 * not relative to another window (methinks).
3806 changes.stack_mode = Above;
3807 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
3815 /*************************************<->*************************************
3817 * F_Raise (args, pCD, event)
3822 * This is the window manager function handler for topping the client window
3823 * so that it is unobscured.
3825 *************************************<->***********************************/
3827 Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
3829 ClientListEntry *pEntry;
3830 ClientListEntry *pNextEntry;
3831 ClientListEntry *pStackEntry;
3832 String string = args;
3833 int flags = STACK_NORMAL;
3835 WmWorkspaceData *pWS = ACTIVE_WS;
3840 /* process '-client' argument */
3841 if (string[0] == '-')
3843 string = &string[1];
3844 string = (String) GetString ((unsigned char **) &string);
3847 pNextEntry = ACTIVE_PSD->clientList;
3848 while (pNextEntry &&
3849 (pEntry = FindClientNameMatch (pNextEntry, True, string,
3852 pNextEntry = pEntry->nextSibling;
3854 if (ClientInWorkspace (pWS, pEntry->pCD))
3857 Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3858 pStackEntry = pEntry;
3864 /* process family stacking stuff */
3867 unsigned int slen, len, index;
3869 slen = strlen(args) - 2; /* subtract '\n' and NULL */
3870 for (index = 0; index < slen; string = &args[index+1])
3872 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3874 len = strlen(string);
3875 if (!strcmp(string,"within"))
3877 flags |= STACK_WITHIN_FAMILY;
3879 else if (!strcmp(string,"freeFamily"))
3881 flags |= STACK_FREE_FAMILY;
3886 if (ClientInWorkspace (pWS, pCD))
3889 Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3898 if (ClientInWorkspace (pWS, pCD))
3901 Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3909 } /* END OF FUNCTION F_Raise */
3913 /*************************************<->*************************************
3915 * Do_Raise (pCD, pStackEntry)
3920 * This is the window manager function handler for topping the client window
3921 * so that it is unobscured.
3926 * pCD = pointer to the client data of the window (or icon) to be raised.
3928 * pStackEntry = pointer to client list entry for window that is to be
3929 * above the raised window (if NULL window is raised to the top of the
3932 *************************************<->***********************************/
3934 void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3936 Boolean restackTransients;
3937 ClientData *pcdLeader;
3938 WmWorkspaceData *pWS = ACTIVE_WS;
3940 Boolean bLeaderRestacked;
3946 * Window has been reparented into the front panel.
3947 * Don't follow through on window stacking change.
3953 if (ClientInWorkspace(pWS, pCD) &&
3954 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
3957 * Both clients are in the current workspace. Set
3958 * client indices so that the access macros work.
3960 SetClientWsIndex (pCD);
3963 SetClientWsIndex (pStackEntry->pCD);
3969 * One or both of the clients are not in the current workspace
3976 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
3978 if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
3981 * Don't raise the window above the system modal window.
3984 else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
3985 !P_ICON_BOX(pcdLeader))
3988 * If a dirtyStackEntry exists, return it to its original place
3989 * in the stack (for all stacking types)
3991 if (dirtyStackEntry)
3993 if (dirtyStackEntry->transientChildren ||
3994 dirtyStackEntry->transientLeader)
3995 RestackTransients (dirtyStackEntry);
3996 dirtyStackEntry = NULL;
4001 * Only restack the icon if it is not currently raised.
4006 if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
4008 StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
4010 MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
4016 if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
4018 StackWindow (pWS, &pcdLeader->iconEntry,
4019 True /*on top*/, (ClientListEntry *) NULL);
4020 MoveEntryInList (pWS, &pcdLeader->iconEntry,
4021 True /*on top*/, (ClientListEntry *) NULL);
4025 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
4029 * Handle restacking of primary/secondary windows
4030 * within the transient window tree. Don't raise this
4031 * window above any modal transients.
4033 bLeaderRestacked = False;
4034 if ((pcdLeader->transientChildren) &&
4035 (!pCD->secondariesOnTop) &&
4036 (!wmGD.bSuspendSecondaryRestack) &&
4037 (!IS_APP_MODALIZED(pCD)))
4039 if (pCD != pcdLeader)
4042 * This is not the transient leader, make sure
4043 * the transient leader isn't on top.
4044 * (Brute force solution)
4046 bLeaderRestacked = NormalizeTransientTreeStacking (pcdLeader);
4048 if (pCD->transientChildren)
4051 * This isn't the overall leader of the transient
4052 * tree, but it does have transient's of its own.
4053 * Move it to the top of its own transient sub-tree.
4055 bLeaderRestacked |= BumpPrimaryToTop (pCD);
4061 * This is the transient leader, move it to the
4064 bLeaderRestacked = BumpPrimaryToTop (pcdLeader);
4070 * If this is a transient window then put it on top of its
4071 * sibling transient windows.
4074 restackTransients = False;
4078 * Fix for 5325 - The following code has been reorganized to cause the
4079 * action of F_Raise to match the current documentation.
4080 * The new algorithm is as follows:
4082 * if (dirtyStackEntry)
4083 * restore dirty tree
4084 * if (not withinFamily)
4085 * bring window group to the top of global stack
4087 * raise the requested window to top of family
4089 * raise requested window to top of siblings
4090 * if (need to restack windows)
4095 * If a dirtyStackEntry exists, return it to its original place
4096 * in the stack (for all stacking types)
4098 if (dirtyStackEntry)
4101 * Check to make sure that the dirty pCD has either transient
4102 * children or a transient leader. If not, do not restore
4105 if (dirtyStackEntry->transientChildren ||
4106 dirtyStackEntry->transientLeader)
4107 RestackTransients (dirtyStackEntry);
4108 dirtyStackEntry = NULL;
4113 * If the flags do not indicate "within", raise the window family
4114 * to the top of the window stack. If the window is the primary,
4115 * raise it to the top regardless of the flags.
4117 if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
4121 if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
4123 StackWindow (pWS, &pcdLeader->clientEntry,
4124 False /*below*/, pStackEntry);
4125 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4126 False /*below*/, pStackEntry);
4131 if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
4133 StackWindow (pWS, &pcdLeader->clientEntry,
4134 True /*on top*/, (ClientListEntry *) NULL);
4135 MoveEntryInList (pWS, &pcdLeader->clientEntry,
4136 True /*on top*/, (ClientListEntry *) NULL);
4142 * If freeFamily stacking is requested, check to make sure that
4143 * the window has either a transientChild or Leader. This will
4144 * guarantee that windows that form their own family are not
4145 * labelled as dirty (what's to dirty it up?). If it has either,
4146 * raise the window to the top of the family stack.
4148 if ((flags & STACK_FREE_FAMILY) &&
4149 (pCD->transientLeader || pCD->transientChildren))
4151 dirtyStackEntry = pCD;
4152 dirtyLeader = pcdLeader;
4154 restackTransients = ForceRaiseWindow (pCD);
4158 * If withinFamily stacking is requested, put the current transient
4159 * on top of its sibling transient windows.
4163 restackTransients = PutTransientOnTop (pCD);
4166 /* At this point, if doing a regular f.raise the window family has
4167 * already been brought to the top of the stack, so nothing further
4168 * needs to be done for it.
4171 /* Restack the transients if needed */
4174 if ((restackTransients) || (bLeaderRestacked))
4176 if (restackTransients)
4179 RestackTransients (pCD);
4183 } /* END OF FUNCTION Do_Raise */
4187 /*************************************<->*************************************
4189 * F_Raise_Lower (args, pCD, event)
4194 * This window manager function tops an obscured window or icon and bottoms
4195 * a window or icon that is on top of the window stack.
4197 *************************************<->***********************************/
4199 Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
4201 ClientData *pcdLeader;
4205 pcdLeader = (pCD->transientLeader) ?
4206 FindTransientTreeLeader (pCD) : pCD;
4209 * Treat a raise/lower on a window in a transient tree as if it is
4210 * a raise/lower for the whole tree.
4213 if (CheckIfClientObscuredByAny (pcdLeader))
4216 * The window is obscured by another window, raise the window.
4220 F_Raise (NULL, pCD, (XEvent *)NULL);
4222 F_Raise (NULL, pcdLeader, (XEvent *)NULL);
4225 else if (CheckIfClientObscuringAny (pcdLeader) &&
4226 !(wmGD.systemModalActive &&
4227 (pcdLeader == wmGD.systemModalClient)))
4230 * The window is obscuring another window and is
4231 * not system modal, lower the window.
4234 F_Lower (NULL, pcdLeader, (XEvent *)NULL);
4236 if ((pcdLeader->secondariesOnTop == False) &&
4237 (pCD->transientLeader != NULL) &&
4238 (!IS_APP_MODALIZED(pcdLeader)))
4240 /* Push transient below primary */
4241 (void) BumpPrimaryToTop (pcdLeader);
4242 RestackTransients (pcdLeader);
4247 else if ((pcdLeader->secondariesOnTop == False) &&
4248 (pcdLeader->transientChildren != NULL) &&
4249 (!wmGD.systemModalActive) &&
4250 (!IS_APP_MODALIZED(pcdLeader)))
4252 if (LeaderOnTop(pcdLeader))
4254 /* Push primary below transient */
4255 (void) BumpPrimaryToBottom (pcdLeader);
4256 RestackTransients (pcdLeader);
4260 F_Raise (NULL, pCD, (XEvent *)NULL);
4261 /* Push transient below primary */
4262 (void) BumpPrimaryToTop (pcdLeader);
4263 RestackTransients (pcdLeader);
4271 } /* END OF FUNCTION F_Raise_Lower */
4275 /*************************************<->*************************************
4277 * F_Refresh_Win (args, pCD, event)
4282 * This is the window manager function handler for causing a client window
4283 * to redisplay itself.
4285 *************************************<->***********************************/
4287 Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
4292 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
4293 (pCD->clientState == MAXIMIZED_STATE)))
4295 if (pCD->clientState == NORMAL_STATE)
4297 w = (unsigned int) pCD->clientWidth;
4298 h = (unsigned int) pCD->clientHeight;
4302 w = (unsigned int) pCD->maxWidth;
4303 h = (unsigned int) pCD->maxHeight;
4307 if (wmGD.refreshByClearing)
4309 RefreshByClearing (pCD->clientFrameWin);
4314 /* default background_pixmap is None */
4315 win = XCreateWindow (DISPLAY,
4325 (XSetWindowAttributes *)NULL);
4327 XMapWindow (DISPLAY, win);
4328 XDestroyWindow (DISPLAY, win);
4337 } /* END OF FUNCTION F_Refresh_Win */
4341 /*************************************<->*************************************
4343 * F_Set_Behavior (args, pCD, event)
4348 * This function is used to switch the window manager configuration between
4349 * the built-in configuration (for CXI behavior) and the user's custom
4352 *************************************<->***********************************/
4354 Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
4357 * Go system modal in starting to do the set behavior.
4360 /* !!! grab the server and the pointer !!! */
4364 * Confirm that a set_behavior should be done.
4365 * Execute restart if so.
4368 if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
4370 ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
4371 CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
4375 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4376 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4380 } /* END OF FUNCTION F_Set_Behavior */
4384 /*************************************<->*************************************
4386 * Do_Set_Behavior (dummy)
4391 * Callback to do the f.set_behavior function.
4393 *************************************<->***********************************/
4395 void Do_Set_Behavior (Boolean dummy)
4397 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4398 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4400 } /* END OF FUNCTION Do_Set_Behavior */
4404 /*************************************<->*************************************
4406 * F_Set_Context (args, pCD, event)
4411 * This function is used to set a client context for subsequent
4414 *************************************<->***********************************/
4416 Boolean F_Set_Context (String args, ClientData *pCD, XEvent *event)
4419 wmGD.requestContextWin = (Window) args;
4422 } /* END OF FUNCTION F_Set_Context */
4426 /*************************************<->*************************************
4428 * F_Title (args, pCD, event)
4433 * This is a placeholder function; it should never be called.
4435 *************************************<->***********************************/
4437 Boolean F_Title (String args, ClientData *pCD, XEvent *event)
4442 } /* END OF FUNCTION F_Title */
4446 /******************************<->*************************************
4448 * F_Screen (args, pCD, event)
4453 * This is the window manager function handler for warping to screens
4458 * args = (immediate value) window type flags
4460 * pCD = pointer to the client data
4462 * event = X event that invoked the function (key, button, or menu/NULL)
4464 * NOTE: May want to consider tracking changes in screen because in
4465 * managing a new window (ie. in ManageWindow()).
4469 * RETURN = if True then further button binding/function processing can
4470 * be done for the event that caused this function to be called.
4472 *************************************<->***********************************/
4474 Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
4478 unsigned int dummask;
4479 WmScreenData *newscr = NULL;
4481 static int PreviousScreen = -1;
4485 if (PreviousScreen == -1)
4487 PreviousScreen = DefaultScreen(DISPLAY);
4490 if (strcmp (args, "next") == 0)
4492 scr = ACTIVE_PSD->screen + 1;
4495 else if (strcmp (args, "prev") == 0)
4497 scr = ACTIVE_PSD->screen - 1;
4500 else if (strcmp (args, "back") == 0)
4502 scr = PreviousScreen;
4514 scr = wmGD.numScreens - 1;
4515 else if (scr >= wmGD.numScreens)
4518 newscr = &(wmGD.Screens[scr]);
4519 if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
4520 if (inc) { /* walk around the list */
4525 "Unable to warp to unmanaged screen %d\n", scr);
4532 if (ACTIVE_PSD->screen == scr) return (False); /* already on that screen */
4534 PreviousScreen = ACTIVE_PSD->screen;
4535 XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
4536 &dumint, &dumint, &dummask);
4538 XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
4540 if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
4543 * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can
4544 * uses the new screen instead of the old screen. Then call
4545 * Do_Focus_Key with a NULL pCD to find a reasonable client to
4548 SetActiveScreen (newscr);
4549 Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
4558 #if ((!defined(WSM)) || defined(MWM_QATS_PROTOCOL))
4559 /*************************************<->*************************************
4561 * F_InvokeCommand (args, pCD, event)
4566 * This is the window manager function for invoking client inserted menu
4569 *************************************<->***********************************/
4571 Boolean F_InvokeCommand (String args, ClientData *pCD, XEvent *event)
4573 CARD32 commandID, clientWindow;
4574 Atom notifySelection;
4576 if (args == (String) NULL) return(FALSE);
4578 if (sscanf(args, "%d %d %ld", &commandID, &clientWindow,
4579 ¬ifySelection) != 3)
4582 SendInvokeMessage(commandID,
4583 (pCD == (ClientData *) NULL ? 0 : pCD->client),
4588 } /* END OF FUNCTION F_InvokeCommand */
4589 #endif /* !defined(WSM) || defined(MWM_QATS_PROTOCOL) */
4592 /*************************************<->*************************************
4594 * GetFunctionTimestamp (pEvent)
4599 * This function is used to extract a timestamp from a key or button event.
4600 * If the event passed in is not a key or button event then a timestamp
4606 * event = pointer to an X event
4611 * RETURN = a timestamp
4613 *************************************<->***********************************/
4615 Time GetFunctionTimestamp (XButtonEvent *pEvent)
4620 (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
4621 ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
4623 time = pEvent->time;
4627 time = GetTimestamp ();
4632 } /* END OF FUNCTION GetFunctionTimestamp */
4636 ** name the event mask we need for a grab in order to find the matching
4637 ** event for an event; right now handle only button-presses
4639 static unsigned int GetEventInverseMask(XEvent *event)
4641 if ((XEvent*)NULL == event)
4643 if (ButtonPress == event->type)
4644 return ButtonReleaseMask; /* detail ? */
4646 expansion further here
4654 /*************************************<->*************************************
4656 * ClearDirtyStackEntry (pCD)
4661 * This function is used to clear the static dirtyStackEntry structure and
4662 * the dirtyLeader static variable when a pCD is destroyed. This
4663 * guarantees that freed memory will not be accessed.
4668 * pCD = pointer to clientData being freed
4675 *************************************<->***********************************/
4677 void ClearDirtyStackEntry (ClientData *pCD)
4679 if (pCD == dirtyStackEntry)
4681 dirtyStackEntry = NULL;
4685 #if defined(DEBUG) && defined(WSM)
4687 /***********************<->*************************************
4689 * F_ZZ_Debug (args, pCD, event)
4694 * This is the window manager debug (multi) function
4701 * pCD = pointer to the ClientData for the whole front panel
4703 * event = X event that invoked the function (key, button, or menu/NULL)
4708 * RETURN = if True then further button binding/function processing can
4709 * be done for the event that caused this function to be called.
4713 * Argument 1 determines the debug function to execute:
4717 * "color_server_info" - dump out color server info
4719 ******************************<->***********************************/
4722 F_ZZ_Debug (String subFcn, ClientData *pCD, XEvent *event)
4724 /* Only do something is sub function is specified */
4728 if (!(strcmp(subFcn, "dump_resources")))
4733 for (scr=0; scr<wmGD.numScreens; scr++)
4735 sprintf (szRes, "/tmp/dtwm.resources.%d", scr);
4737 XrmPutFileDatabase(XtScreenDatabase(
4738 XScreenOfDisplay(DISPLAY, scr)),
4749 /*************************************<->*************************************
4751 * F_Next_Workspace (args, pCD, event)
4756 * This function switches to the next workspace in the list
4758 *************************************<->***********************************/
4760 Boolean F_Next_Workspace (String args, ClientData *pCD, XEvent *event)
4762 WmScreenData *pSD = ACTIVE_PSD;
4765 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4767 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4774 /* check bounds and wrap */
4775 if (iwsx >= pSD->numWorkspaces)
4778 ChangeToWorkspace (&pSD->pWS[iwsx]);
4783 } /* END OF FUNCTION F_Next_Workspace */
4786 /*************************************<->*************************************
4788 * F_Prev_Workspace (args, pCD, event)
4793 * This function switches to the previous workspace in the list
4795 *************************************<->***********************************/
4797 Boolean F_Prev_Workspace (String args, ClientData *pCD, XEvent *event)
4799 WmScreenData *pSD = ACTIVE_PSD;
4802 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4804 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4811 /* check bounds and wrap */
4813 iwsx = pSD->numWorkspaces - 1;
4815 ChangeToWorkspace (&pSD->pWS[iwsx]);
4820 } /* END OF FUNCTION F_Prev_Workspace */
4824 /*************************************<->*************************************
4826 * F_Workspace_Presence (args, pCD, event)
4831 * This function pops up the workspace presence dialog box
4833 *************************************<->***********************************/
4835 Boolean F_Workspace_Presence (String args, ClientData *pCD, XEvent *event)
4837 Context wsContext = (Context)NULL;
4839 if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4841 if (pCD->clientState == NORMAL_STATE)
4843 wsContext = F_CONTEXT_NORMAL;
4845 else if (pCD->clientState == MAXIMIZED_STATE)
4847 wsContext = F_CONTEXT_MAXIMIZE;
4851 wsContext = F_CONTEXT_ICON;
4852 /* return (False); */
4854 ShowPresenceBox (pCD, wsContext);
4858 } /* END OF FUNCTION F_Workspace_Presence */
4864 WmScreenData *pSD = (ACTIVE_WS)->pSD;
4865 ClientListEntry *pCLE;
4867 fprintf (stdout, "Window stacking (bottom to top)\n");
4868 pCLE = pSD->lastClient;
4871 if (ClientInWorkspace (ACTIVE_WS, pCLE->pCD))
4872 fprintf (stdout, "* ");
4874 fprintf (stdout, " ");
4876 fprintf (stdout, "%08lx\t%s\n",
4878 pCLE->pCD->clientName);
4880 pCLE = pCLE->prevSibling;