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.
45 #include "WmWrkspace.h" /* for ClientInWorkspace() test */
46 #include <Dt/EnvControlP.h> /* for restoring **environ before an exec() */
47 #include "WmResNames.h"
48 #include <Dt/Message.h>
50 #include <Dt/DtStrDefs.h>
56 * include extern functions
58 #include "WmFunction.h"
62 #include "WmColormap.h"
65 #include "WmFeedback.h"
68 #include "WmIconBox.h"
69 #include "WmKeyFocus.h"
71 #include "WmPresence.h"
72 #include "WmProperty.h"
73 #include "WmProtocol.h"
74 #include "WmResParse.h"
75 #include "WmWinConf.h"
76 #include "WmWinInfo.h"
77 #include "WmWinList.h"
78 #include "WmWinState.h"
81 #include <Xm/RowColumnP.h> /* for MS_LastManagedMenuTime */
82 extern XmMenuState _XmGetMenuState();
85 extern char * getenv ();
88 #endif /* PORT_NOVFORK */
90 static unsigned int GetEventInverseMask(XEvent *event);
92 #if (defined(__linux__) || defined(sun) || defined(CSRG_BASED)) && !defined(_NFILE)
93 #define _NFILE FOPEN_MAX
95 #define CLOSE_FILES_ON_EXEC() \
96 {int ifx; for (ifx=3; ifx < _NFILE; ifx++) (void) fcntl (ifx, F_SETFD, 1);}
103 * The 'dirty' variables are used to keep track of the transient window
104 * that has been lowered via "f.lower freeFamily".
106 static ClientData *dirtyStackEntry = NULL;
107 static ClientData *dirtyLeader = NULL;
109 /***********************<->*************************************
111 * F_Action (args, pCD, event)
116 * This is the window manager function handler for invoking actions.
121 * args = action function and arguments
123 * pCD = pointer to the ClientData for the whole front panel
125 * event = X event that invoked the function (key, button, or menu/NULL)
130 * RETURN = if True then further button binding/function processing can
131 * be done for the event that caused this function to be called.
135 * The pCD->controlWindow is a temporary area used solely for
136 * this function invocation--it stores the pCW of the control
137 * that want the function to happen.
138 ******************************<->***********************************/
141 F_Action (String actionName, ClientData *pCD, XEvent *event)
144 WmActionArg *pAP = (WmActionArg *) actionName;
146 /* make sure the command runs on the right display. */
147 if (wmGD.pActiveSD->displayString)
149 putenv(wmGD.pActiveSD->displayString);
154 WmFrontPanelSetBusy (True);
158 DtActionInvoke (wmGD.pActiveSD->screenTopLevelW1,
159 pAP->actionName, pAP->aap, pAP->numArgs,
160 pAP->szExecParms, NULL, NULL, 1, NULL, NULL);
163 * Restore original DISPLAY environment variable
165 if(wmGD.pActiveSD->displayString && wmGD.displayString)
167 putenv(wmGD.displayString);
172 } /* END OF FUNCTION F_Action */
174 /******************************<->*************************************
176 * F_Beep (args, pCD, event)
181 * This is the window manager function handler for beeping.
186 * args = function arguments (specified in .mwmrc file)
188 * pCD = pointer to the client data for the client window to which the
189 * function is to be applied
191 * event = X event that invoked the function (key, button, or menu/NULL)
196 * RETURN = if True then further button binding/function processing can
197 * be done for the event that caused this function to be called.
199 ******************************<->***********************************/
201 Boolean F_Beep (String args, ClientData *pCD, XEvent *event)
204 /* !!! what is a good value for percent (the second arg) !!! */
209 } /* END OF FUNCTION F_Beep */
214 * Handle Special case where the dirty window is the top most
215 * transient window. When this is the case, raising the window
216 * that was on top (the window just below the dirty window) will
217 * fail because Mwm stack database is out of sync. So the solution
218 * is to restack the dirty transient relative to the second to the
219 * top transient. This function is used to support freeFamily stacking.
221 ClientData * FindSecondToTopTransient (ClientData *pcd)
224 static ClientData *second;
226 pcdNext = pcd->transientChildren;
229 if (pcdNext->transientChildren)
231 if (!pcdNext->transientChildren->transientChildren)
235 FindSecondToTopTransient (pcdNext);
237 pcdNext = pcdNext->transientSiblings;
238 if (pcdNext && !pcdNext->transientSiblings)
246 } /* END OF FUNCTION */
250 Boolean ForceLowerWindow (ClientData *pcd)
254 WmScreenData *pSD = (ACTIVE_WS)->pSD;
256 XWindowChanges changes;
257 Boolean restack = False;
259 WmScreenData *pSD = (ACTIVE_WS)->pSD;
261 ClientListEntry *pCLE;
264 * Find lowest window in this workspace. We'll stack this transient
267 pCLE = pSD->lastClient;
272 if ((pCLE->pCD != pcd) &&
273 (ClientInWorkspace (ACTIVE_WS, pCLE->pCD)))
275 if ((pCLE->type == MINIMIZED_STATE) &&
276 (pCLE->pCD->clientState == MINIMIZED_STATE))
278 stackWindow = ICON_FRAME_WIN(pCLE->pCD);
280 else if ((pCLE->type == NORMAL_STATE) &&
281 ((pCLE->pCD->clientState == NORMAL_STATE) ||
282 (pCLE->pCD->clientState == MAXIMIZED_STATE)))
284 stackWindow = pCLE->pCD->clientFrameWin;
287 if (stackWindow != None)
290 changes.sibling = stackWindow;
294 if (stackWindow == None)
296 pCLE = pCLE->prevSibling;
300 if (pSD->lastClient->type == MINIMIZED_STATE)
302 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
306 stackWindow = pSD->lastClient->pCD->clientFrameWin;
310 changes.stack_mode = Below;
313 XConfigureWindow (DISPLAY, pcd->clientFrameWin, mask, &changes);
321 /*************************************<->*************************************
323 * F_Lower (args, pCD, event)
328 * This is the window manager function handler for bottoming a client window
334 * args = function arguments (specified in .mwmrc file)
336 * pCD = pointer to the client data for the client window to which the
337 * function is to be applied
339 * event = X event that invoked the function (key, button, or menu/NULL)
344 * RETURN = if True then further button binding/function processing can
345 * be done for the event that caused this function to be called.
347 *************************************<->***********************************/
349 Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
351 ClientListEntry *pEntry;
352 ClientListEntry *pNextEntry;
353 ClientListEntry *pStackEntry;
354 String string = args;
355 int flags = STACK_NORMAL;
356 WmWorkspaceData *pWS = ACTIVE_WS;
360 /* process '-client' argument */
361 if (string[0] == '-')
364 string = (String) GetString ((unsigned char **) &string);
367 pNextEntry = ACTIVE_PSD->lastClient;
369 (pEntry = FindClientNameMatch (pNextEntry, False,
370 string, F_GROUP_ALL)))
372 pNextEntry = pEntry->prevSibling;
373 if (ClientInWorkspace (pWS, pEntry->pCD))
375 Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
376 pStackEntry = pEntry;
380 /* process family stacking stuff */
383 unsigned int slen, len, index;
385 slen = strlen(args) - 2; /* subtract '\n' and NULL */
386 for (index = 0; index < slen; string = &args[index+1])
388 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
390 len = strlen(string);
391 if (!strcmp(string,"within"))
393 flags |= STACK_WITHIN_FAMILY;
395 else if (!strcmp(string,"freeFamily"))
397 flags |= STACK_FREE_FAMILY;
401 if (ClientInWorkspace (pWS, pCD))
403 Do_Lower (pCD, (ClientListEntry *) NULL, flags);
409 if (ClientInWorkspace (pWS, pCD))
411 Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
416 * If caused by button press, event may ALSO cause focus to be
417 * passed to this client - prepare to disable focusAutoRaise.
419 if (pCD && event && (event->type == ButtonPress))
420 pCD->focusAutoRaiseDisablePending = True;
422 wmGD.passButtonsCheck = False;
425 } /* END OF FUNCTION F_Lower */
429 /*************************************<->*************************************
431 * Do_Lower (pCD, pStackEntry)
436 * This is the window manager function handler for lowering the client window
437 * so that it does not obscure any other window above the stack entry
443 * pCD = pointer to the client data of the window (or icon) to be lowered.
445 * pStackEntry = pointer to client list entry for window that is to be
446 * below the lowered window (if NULL, window is lowered to the bottom
449 *************************************<->***********************************/
451 void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
453 Boolean restackTransients;
454 ClientData *pcdLeader;
455 WmWorkspaceData *pWS = ACTIVE_WS;
456 Boolean bLeaderRestacked;
461 * Window has been reparented into the front panel.
462 * Don't follow through on window stacking change.
467 if (ClientInWorkspace(pWS, pCD) &&
468 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
471 * Both clients are in the current workspace. Set
472 * client indices so that the access macros work.
474 SetClientWsIndex (pCD);
477 SetClientWsIndex (pStackEntry->pCD);
483 * One or both of the clients are not in the current workspace
489 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
491 if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
494 * If a dirtyStackEntry exists, return it to its original place
495 * in the stack (for all stacking types)
499 if (dirtyStackEntry->transientChildren ||
500 dirtyStackEntry->transientLeader)
501 RestackTransients (dirtyStackEntry);
502 dirtyStackEntry = NULL;
507 * Only restack the icon if it is not currently lowered.
512 if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
514 StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
516 MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
522 if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
524 StackWindow (pWS, &pcdLeader->iconEntry,
525 False /*on bottom*/, (ClientListEntry *) NULL);
526 MoveEntryInList (pWS, &pcdLeader->iconEntry,
527 False /*on bottom*/, (ClientListEntry *) NULL);
531 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
534 * Handle restacking of primary/secondary windows
535 * within the transient window tree.
537 bLeaderRestacked = False;
538 if ((pcdLeader->transientChildren) &&
539 (!pcdLeader->secondariesOnTop) &&
540 (!wmGD.bSuspendSecondaryRestack))
542 if (pCD == pcdLeader)
545 * Lower requested on the leader itself, insure it's
548 bLeaderRestacked = BumpPrimaryToBottom (pcdLeader);
550 else if (pCD->transientChildren)
553 * Lower requested on the leader of a subtree. Insure
554 * that this subtree leader is at the bottom of the
557 bLeaderRestacked = BumpPrimaryToBottom (pCD);
559 else if (pCD->transientLeader)
564 * Lower requested on a transient. Insure all the
565 * subtree leaders up to the top are at the bottom
566 * of their respective transient subtrees.
568 for (pcdLdr = pCD->transientLeader;
570 pcdLdr = pcdLdr->transientLeader)
572 bLeaderRestacked |= BumpPrimaryToBottom (pcdLdr);
579 * If this is a transient window then put it below its
580 * sibling transient windows.
583 restackTransients = False;
584 if (pCD->transientLeader)
588 * If freeFamily stacking, then put dirty transient window
589 * (if any) back in place before force lowering current window
590 * to the bottom of the global window stack. Then return.
593 if (flags & STACK_FREE_FAMILY)
595 /* Restore dirty transient if not current window. */
596 if ((dirtyStackEntry) &&
597 (dirtyStackEntry != pCD))
599 RestackTransients (dirtyStackEntry);
602 dirtyStackEntry = pCD;
603 dirtyLeader = pcdLeader;
605 ForceLowerWindow (pCD);
610 * Reach here only if NOT doing a f.lower freeFamily (see
611 * return; statement above). Put current transient below
612 * its sibling transient windows.
614 restackTransients = PutTransientBelowSiblings (pCD);
618 * If doing a regular f.lower and you have a dirty window, then
619 * clean up dirty transient window.
625 * If lowering a window in the same family as the dirty
626 * transient window, then just restack before lowering.
627 * Else, restore the dirty transient in place before
628 * lowering the current window. Clear dirtyStack.
630 if (dirtyLeader == pcdLeader)
632 restackTransients = True;
636 RestackTransients (dirtyStackEntry);
639 dirtyStackEntry = NULL;
643 * Only restack the window or transient window tree if it is
644 * not currently lowered and the window is not a system
650 if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
651 !(wmGD.systemModalActive &&
652 (pcdLeader == wmGD.systemModalClient)))
654 StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
656 MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
659 else if ((restackTransients) || (bLeaderRestacked))
661 RestackTransients (pCD);
666 if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
667 !(wmGD.systemModalActive &&
668 (pcdLeader == wmGD.systemModalClient)) &&
669 !(flags & STACK_WITHIN_FAMILY))
671 StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
672 (ClientListEntry *) NULL);
673 MoveEntryInList (pWS, &pcdLeader->clientEntry,
674 False /*on bottom*/, (ClientListEntry *) NULL);
676 else if ((restackTransients) || (bLeaderRestacked))
678 RestackTransients (pCD);
683 } /* END OF FUNCTION Do_Lower */
687 /*************************************<->*************************************
689 * F_CircleDown (args, pCD, event)
694 * This is the window manager function handler for moving the client window
695 * on top of stack to the bottom.
700 * args = function arguments (specified in .mwmrc file)
702 * pCD = pointer to the client data for the client window to which the
703 * function is to be applied
705 * event = X event that invoked the function (key, button, or menu/NULL)
710 * RETURN = if True then further button binding/function processing can
711 * be done for the event that caused this function to be called.
713 *************************************<->***********************************/
715 Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
718 unsigned long windowType;
719 ClientListEntry *pNextEntry;
724 * Go down through the client list looking for a window of an
725 * appropriate type that is obscuring lower windows.
728 types = (unsigned long)args;
729 pNextEntry = ACTIVE_PSD->clientList;
733 * Only check out the window if it is onscreen.
736 pcdNext = pNextEntry->pCD;
737 if (((pNextEntry->type == NORMAL_STATE) &&
738 (pcdNext->clientState != MINIMIZED_STATE)) ||
739 ((pNextEntry->type == MINIMIZED_STATE) &&
740 (pcdNext->clientState == MINIMIZED_STATE)))
742 if (pcdNext->clientState == MINIMIZED_STATE)
744 windowType = F_GROUP_ICON;
748 windowType = F_GROUP_WINDOW;
749 if (pcdNext->transientLeader || pcdNext->transientChildren)
751 windowType |= F_GROUP_TRANSIENT;
754 if (types & windowType)
756 if (CheckIfClientObscuringAny (pcdNext))
759 * This window (or window tree) is obscuring another window
760 * on the screen. Lower the window.
763 wmGD.bSuspendSecondaryRestack = True;
764 F_Lower (NULL, pcdNext, (XEvent *) NULL);
765 wmGD.bSuspendSecondaryRestack = False;
770 pNextEntry = pNextEntry->nextSibling;
775 } /* END OF FUNCTION F_Circle_Down */
779 /*************************************<->*************************************
781 * F_Circle_Up (args, pCD, event)
786 * This is the window manager function handler for moving the client window
787 * on the bottom of the stack to the top.
792 * args = function arguments (specified in .mwmrc file)
794 * pCD = pointer to the client data for the client window to which the
795 * function is to be applied
797 * event = X event that invoked the function (key, button, or menu/NULL)
802 * RETURN = if True then further button binding/function processing can
803 * be done for the event that caused this function to be called.
805 *************************************<->***********************************/
807 Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
810 unsigned long windowType;
811 ClientListEntry *pNextEntry;
816 * Go up through the client list looking for a window of an
817 * appropriate type that is obscured by higher windows.
820 types = (unsigned long)args;
821 pNextEntry = ACTIVE_PSD->lastClient;
825 * Only check out the window if it is onscreen.
828 pcdNext = pNextEntry->pCD;
829 if (((pNextEntry->type == NORMAL_STATE) &&
830 (pcdNext->clientState != MINIMIZED_STATE)) ||
831 ((pNextEntry->type == MINIMIZED_STATE) &&
832 (pcdNext->clientState == MINIMIZED_STATE)))
834 if (pcdNext->clientState == MINIMIZED_STATE)
836 windowType = F_GROUP_ICON;
840 windowType = F_GROUP_WINDOW;
841 if (pcdNext->transientLeader || pcdNext->transientChildren)
843 windowType |= F_GROUP_TRANSIENT;
846 if (types & windowType)
848 if (CheckIfClientObscuredByAny (pcdNext))
851 * This window (or window tree) is obscured by another
852 * window on the screen. Raise the window.
855 wmGD.bSuspendSecondaryRestack = True;
856 F_Raise (NULL, pcdNext, (XEvent *) NULL);
857 wmGD.bSuspendSecondaryRestack = False;
862 pNextEntry = pNextEntry->prevSibling;
868 } /* END OF FUNCTION F_Circle_Up */
872 /*************************************<->*************************************
874 * F_Focus_Color (args, pCD, event)
879 * This is the window manager function handler for setting the colormap
880 * focus to a client window or reinstalling the default colormap.
882 *************************************<->***********************************/
884 Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
887 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
892 * The window selected for the colormap focus is a top-level client
893 * window. If there are subwindow colormaps then determine if the
894 * selection was in one of the subwindows.
897 if (pCD->clientState == MINIMIZED_STATE)
899 /* !!! colormap for client supplied icon window !!! */
904 SetColormapFocus (ACTIVE_PSD, pCD);
909 } /* END OF FUNCTION F_Focus_Color */
913 /*************************************<->*************************************
915 * F_Exec (args, pCD, event)
920 * This is the window manager function handler for executing a command
923 *************************************<->***********************************/
925 Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
932 /* make sure the f.exec command runs on the right display. */
933 if (wmGD.pActiveSD->displayString)
935 putenv(wmGD.pActiveSD->displayString);
941 * Start the busy indicator, waiting for a pushbutton window
942 * for the given duration
944 WmFrontPanelSetBusy (True);
948 * Fork a process to exec a shell to run the specified command:
952 if ((pid = fork ()) == 0)
954 if ((pid = vfork ()) == 0)
959 #if defined(SVR4) || defined(__linux__)
971 #endif /* NO_SETPGRP */
974 * Clean up window manager resources.
975 * The X file descriptor should be automatically closed.
979 * Fix up signal handling.
981 RestoreDefaultSignalHandlers ();
984 * Fix up the child application's environment NOT to
985 * inherit the XFILESEARCHPATH, XBMLANGPATH, NLSPATH, etc.
988 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
990 CLOSE_FILES_ON_EXEC();
993 * Exec the command using $MWMSHELL if set or
994 * $SHELL if set and $MWMSHELL not set or sh.
997 if (((shell = getenv ("MWMSHELL")) != NULL) ||
998 ((shell = getenv ("SHELL")) != NULL))
1001 shellname = strrchr (shell, '/');
1002 if (shellname == NULL)
1005 If the shell pathname obtained from SHELL or MWMSHELL does not
1006 have a "/" in the path and if the user expects this shell to be
1007 obtained using the PATH variable rather than the current
1008 directory, then we must call execlp and not execl
1011 execlp (shell, shellname, "-c", args, NULL);
1016 execl (shell, shellname, "-c", args, NULL);
1021 * There is no SHELL environment variable or the first execl failed.
1025 execl ("/usr/bin/sh", "sh", "-c", args, NULL);
1027 execl ("/bin/sh", "sh", "-c", args, NULL);
1032 * Error - command could not be exec'ed.
1042 * Have the window manager wait for the shell to complete.
1046 * Don't need to wait because WSM sets SIGCLD handler
1051 * Restore original DISPLAY environment variable value
1052 * so a restart will start on the same screen
1055 if(wmGD.pActiveSD->displayString &&
1058 putenv(wmGD.displayString);
1065 } /* END OF FUNCTION F_Exec */
1069 /*************************************<->*************************************
1071 * F_Quit_Mwm (args, pCD, event)
1076 * This is the window manager function handler for terminating the window
1079 *************************************<->***********************************/
1081 Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
1083 if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
1085 ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
1094 } /* END OF FUNCTION F_Quit_Mwm */
1098 /*************************************<->*************************************
1100 * Do_Quit_Mwm (diedOnRestart)
1105 * Callback to do the f.quit_mwm function.
1107 *************************************<->***********************************/
1109 void Do_Quit_Mwm (Boolean diedOnRestart)
1112 ClientListEntry *pNextEntry;
1116 * Close the X connection to get all the X resources cleaned up.
1117 * !!! maybe windows should be reparented / rebordered before closing? !!!
1118 * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
1124 XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
1125 for (scr = 0; scr < wmGD.numScreens; scr++)
1127 if (wmGD.Screens[scr].managed)
1129 SaveResources(&wmGD.Screens[scr]);
1130 pNextEntry = wmGD.Screens[scr].lastClient;
1133 if (pNextEntry->type == NORMAL_STATE)
1135 if (!(pNextEntry->pCD->clientFlags &
1138 ReBorderClient (pNextEntry->pCD, diedOnRestart);
1141 pNextEntry = pNextEntry->prevSibling;
1143 UnParentControls (&wmGD.Screens[scr], False);
1147 /* shut down the messaging connection */
1150 XSync (DISPLAY, False);
1151 XCloseDisplay (DISPLAY);
1156 exit (WM_ERROR_EXIT_VALUE);
1163 } /* END OF FUNCTION Do_Quit_Mwm */
1166 /*************************************<->*************************************
1168 * ReBorderClient (pCD, reMapClient)
1173 * Restores X border for client window and reparents the
1174 * window back to the root.
1179 * pCD = pointer to the client data for the window to be re-bordered.
1181 *************************************<->***********************************/
1183 void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1187 XWindowChanges windowChanges;
1191 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1194 XUnmapWindow (DISPLAY, pCD->iconWindow);
1195 XReparentWindow (DISPLAY, pCD->iconWindow,
1196 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
1197 pCD->pWsList->iconY);
1209 if(wmGD.positionIsFrame)
1211 CalculateGravityOffset (pCD, &xoff, &yoff);
1212 x = pCD->clientX - xoff;
1213 y = pCD->clientY - yoff;
1221 XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1222 XReparentWindow (DISPLAY, pCD->client,
1223 ROOT_FOR_CLIENT(pCD), x, y);
1227 XMapWindow(wmGD.display, pCD->client);
1230 if (pCD->transientChildren)
1232 ReBorderClient (pCD->transientChildren, reMapClient);
1240 windowChanges.x = x;
1241 windowChanges.y = y;
1242 windowChanges.border_width = pCD->xBorderWidth;
1243 XConfigureWindow (DISPLAY, pCD->client,
1244 CWBorderWidth | CWX | CWY, &windowChanges);
1247 if (pCD->transientLeader)
1249 pCD = pCD->transientSiblings;
1257 } /* END OF FUNCTION ReBorderClient */
1261 /*************************************<->*************************************
1263 * F_Focus_Key (args, pCD, event)
1268 * This is the window manager function handler for setting the keyboard
1269 * focus to a particular client window.
1274 * args = (immediate value) focus flags
1276 * pCD = pointer to the client data
1278 * event = X event that invoked the function (key, button, or menu/NULL)
1280 *************************************<->***********************************/
1282 Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1284 long focusFlags = (long)args;
1287 if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1289 Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1290 (focusFlags | ALWAYS_SET_FOCUS));
1295 } /* END OF FUNCTION F_Focus_Key */
1298 /*************************************<->*************************************
1300 * FindSomeReasonableClient
1304 * Find a client, any client to set the focus to, return client or NULL.
1305 * This code is ripped off from AutoResetKeyFocus().
1307 *************************************<->***********************************/
1309 static Window FindSomeReasonableClient(void)
1311 ClientData *pcdNoFocus=NULL;
1313 ClientListEntry *pNextEntry;
1315 ClientData *pcdLastFocus = (ClientData *) NULL;
1316 ClientData *pcdFocus;
1317 Window focusWindow = (Window) NULL;
1320 * Scan through the list of clients to find a window to get the focus.
1323 pNextEntry = ACTIVE_PSD->clientList;
1327 pCD = pNextEntry->pCD;
1328 if (!wmGD.systemModalActive ||
1329 (wmGD.systemModalClient == pCD))
1331 if ((pNextEntry->type != MINIMIZED_STATE) &&
1332 (pCD->clientState != MINIMIZED_STATE) &&
1333 (ClientInWorkspace (ACTIVE_WS, pCD)) &&
1334 (pCD != pcdNoFocus))
1336 if (pCD->transientChildren)
1338 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1345 ((pcdLastFocus == NULL) ||
1346 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1348 pcdLastFocus = pcdFocus;
1352 pNextEntry = pNextEntry->nextSibling;
1356 * Set the focus window if one is found
1360 ClientInWorkspace (ACTIVE_WS, pcdLastFocus))
1361 focusWindow = pcdLastFocus->client;
1364 * If a client window could not be found, then just put focus
1368 if (focusWindow == (Window) NULL)
1370 pNextEntry = ACTIVE_PSD->clientList;
1374 pCD = pNextEntry->pCD;
1376 if (ClientInWorkspace (ACTIVE_WS, pCD))
1378 if ((pNextEntry->type == MINIMIZED_STATE) ||
1379 (pCD->clientState == MINIMIZED_STATE))
1381 focusWindow = ICON_FRAME_WIN(pCD);
1385 pNextEntry = pNextEntry->nextSibling;
1389 return (focusWindow);
1391 } /* END OF FUNCTION FindSomeReasonableClient */
1396 /*************************************<->*************************************
1398 * Do_Focus_Key (pCD, focusTime, flags)
1403 * This function is used to set the focus to a window. The focus indication
1404 * is not changed until the FocusIn event is received.
1409 * pCD = pointer to the client data
1411 * focusTime = focus change time
1413 * flags = wm focus change flags
1415 *************************************<->***********************************/
1417 void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1419 ClientData *pcdFocus;
1423 /* Clear the replay flag */
1424 wmGD.replayEnterEvent = False;
1428 * Make sure the client is in the current workspace
1431 (ClientInWorkspace (ACTIVE_WS, pCD)))
1433 if (pCD->clientState == MINIMIZED_STATE)
1435 focusWindow = ICON_FRAME_WIN(pCD);
1437 else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1440 * Set the keyboard focus to the indicated client window.
1441 * If the window has an application modal subordinate then
1442 * set the input focus to that window if the focus isn't
1443 * already owned by a subordinate.
1446 if (IS_APP_MODALIZED(pCD))
1448 ClientData *pcdFocusLeader,*currFocusLeader;
1451 * Handle case where a modal window exists when Mwm starts up.
1452 * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1455 if (wmGD.keyboardFocus)
1457 currFocusLeader = wmGD.keyboardFocus->transientLeader;
1461 currFocusLeader = (ClientData *) NULL;
1465 * Find focus leader for pCD
1468 pcdFocusLeader = pCD;
1469 while (pcdFocusLeader->transientLeader &&
1470 (pcdFocusLeader != currFocusLeader))
1472 pcdFocusLeader = pcdFocusLeader->transientLeader;
1475 if (pcdFocusLeader == currFocusLeader)
1477 pcdFocus = wmGD.keyboardFocus;
1482 pcdFocus = FindTransientFocus (pcdFocusLeader);
1487 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1488 * We must look at why FindTransientFocus is
1489 * returning a NULL pcd. The old code simply set
1490 * focusWindow = pcdFocus->client;
1491 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1493 * 11/26/96 rswiston - In tracking down CDExc22816, we
1494 * discovered that pCD could get tricked into thinking
1495 * it had modal transients when in fact all its transients
1496 * had been withdrawn (fixed in WithdrawTransientChildren()).
1497 * As a result, FindTransientFocus() returns wmGD.keyboardFocus;
1498 * if nobody has the focus, FindTransientFocus() returns NULL.
1502 focusWindow = pcdFocus->client;
1506 focusWindow = (wmGD.keyboardFocus) ?
1507 wmGD.keyboardFocus->client : ACTIVE_PSD->wmWorkspaceWin;
1513 * If the focus policy is "pointer" don't set the focus to a
1514 * window if it has an application modal subordinate.
1517 if (IS_APP_MODALIZED(pCD))
1520 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1522 /* Replay this later when the modal window is removed. */
1523 wmGD.replayEnterEvent = True;
1527 focusWindow = pcdFocus->client;
1534 * Set up the default (non client specific) keyboard input focus.
1537 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1539 focusWindow = PointerRoot;
1544 * The WORKSPACE_IF_NULL flag is used to prevent client
1545 * windows from flashing when deiconifying a client.
1548 if (WORKSPACE_IF_NULL & flags)
1550 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1554 /* find some reasonable client so that focus is not lost */
1556 focusWindow = FindSomeReasonableClient();
1557 if (focusWindow == (Window)NULL)
1559 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1565 if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1570 * Set the focus and/or send a take focus client message. This
1571 * is not done if a client area button press was done to set
1572 * set the focus and the window is a globally active input
1573 * style window (See ICCCM).
1576 if ( (flags & CLIENT_AREA_FOCUS) &&
1577 (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1578 ! pcdFocus->inputFocusModel &&
1579 (pcdFocus == pCD) &&
1580 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
1581 !(pcdFocus->clientState == MINIMIZED_STATE)
1586 * 1. User clicked in the client area AND
1587 * 2. Input model is Globally Active AND
1588 * 3. Keyboard focus policy is explicit
1591 /* this window has WM_TAKE_FOCUS set and InputField false. */
1592 /* just send a message. */
1593 SendClientMsg (pcdFocus->client,
1594 (long) wmGD.xa_WM_PROTOCOLS,
1595 (long) wmGD.xa_WM_TAKE_FOCUS,
1596 focusTime, NULL, 0);
1600 if ((pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1601 !(pcdFocus->clientState == MINIMIZED_STATE))
1604 * Locally Active Input Model - Send a take focus message to the client.
1607 SendClientMsg (pcdFocus->client,
1608 (long) wmGD.xa_WM_PROTOCOLS,
1609 (long) wmGD.xa_WM_TAKE_FOCUS,
1610 focusTime, NULL, 0);
1614 * Don't set the input focus if the window has input_field set
1615 * to False or has expressed an interest in WM_TAKE_FOCUS
1616 * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1617 * and the user click in the client area. If the user clicks
1618 * on the titlebar or traverses to this window via f.next_key,
1619 * set the focus so that the user can access the window menu
1623 if ( wmGD.enforceKeyFocus || /* res - default == True. */
1624 (flags & ALWAYS_SET_FOCUS) ||
1625 !(flags & CLIENT_AREA_FOCUS)|| /* clicked on frame? */
1626 pcdFocus->inputFocusModel || /* Pass.|Glob. Active */
1627 (pcdFocus->clientState == MINIMIZED_STATE)
1630 if ( !(flags & CLIENT_AREA_FOCUS) &&
1631 !pcdFocus->inputFocusModel &&
1632 !(pcdFocus->clientState == MINIMIZED_STATE))
1634 /* the window doesn't want the focus - set it to the frame */
1635 /* user clicked on the frame but we don't want the focus */
1636 /* set it to the client's frame */
1637 XSetInputFocus (DISPLAY, pcdFocus->clientBaseWin,
1638 RevertToPointerRoot, focusTime);
1640 else if ( !(flags & CLIENT_AREA_FOCUS) &&
1641 !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1642 pcdFocus->inputFocusModel
1645 XSetInputFocus (DISPLAY, focusWindow,
1646 RevertToPointerRoot, focusTime);
1650 XSetInputFocus (DISPLAY, focusWindow,
1651 RevertToParent, focusTime);
1657 * We've decided that the window shouldn't get the focus,
1658 * so don't change the focus.
1660 pcdFocus = wmGD.nextKeyboardFocus;
1666 XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1670 wmGD.nextKeyboardFocus = pcdFocus;
1674 } /* END OF FUNCTION Do_Focus_Key */
1677 /***********************<->*************************************
1679 * F_Goto_Workspace (args, pCD, event)
1683 * This is the window manager function handler for switching
1684 * to another workspace by name.
1688 * args = action function and arguments
1690 * pCD = pointer to the ClientData
1692 * event = X event that invoked the function (key, button, or menu/NULL)
1700 ******************************<->***********************************/
1702 F_Goto_Workspace (String args, ClientData *pCD, XEvent *event)
1704 WmScreenData *pSD = ACTIVE_PSD;
1709 * Compare argument against both resource name
1710 * and workspace title, take the first match.
1712 xms = XmStringCreate (args, XmFONTLIST_DEFAULT_TAG);
1713 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1715 if (!strcmp(pSD->pWS[iwsx].name, args) ||
1716 XmStringCompare (xms, pSD->pWS[iwsx].title))
1725 if (iwsx >= pSD->numWorkspaces)
1727 Warning (((char *)GETMESSAGE(26, 4,
1728 "Invalid workspace name specified for f.goto_workspace")));
1732 ChangeToWorkspace (&pSD->pWS[iwsx]);
1737 } /* END OF FUNCTION F_Goto_Workspace */
1740 /******************************<->*************************************
1742 * Boolean F_Help (String args, ClientData *pCD, XEvent *event)
1746 * Invoke help on the workspace manager
1750 * args - incoming values
1751 * pCD - associated client data structure
1752 * event - what triggered this call
1756 * Return - True if the call occurs; false otherwise.
1761 ******************************<->***********************************/
1763 F_Help (String args, ClientData *pCD, XEvent *event)
1767 rval = WmDtHelp(args);
1769 } /* END OF FUNCTION F_Help */
1772 /******************************<->*************************************
1774 * Boolean F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1778 * Invoke item help on the frontpanel
1783 * pCD - associated client data structure ??
1784 * event - what triggered this call
1788 * Return - True if the call occurs; false otherwise.
1793 ******************************<->***********************************/
1795 F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1798 * Help mode event processing interferes
1799 * with slide up windows. Don't continue
1800 * if windows are sliding.
1802 if (wmGD.iSlideUpsInProgress == 0)
1804 (void) WmDtHelpMode();
1807 } /* END OF FUNCTION F_Help_Mode */
1810 /******************************<->*************************************
1812 * F_Next_Key (args, pCD, event)
1817 * This is the window manager function handler for setting the keyboard
1818 * input focus to the next window in the set of managed windows.
1823 * args = (immediate value) window type flags
1825 * pCD = pointer to the client data
1827 * event = X event that invoked the function (key, button, or menu/NULL)
1829 *************************************<->***********************************/
1831 Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1833 #ifdef ROOT_ICON_MENU
1834 Boolean focused = False;
1835 #endif /* ROOT_ICON_MENU */
1836 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1838 #ifdef ROOT_ICON_MENU
1840 #endif /* ROOT_ICON_MENU */
1841 FocusNextWindow ((unsigned long)args,
1842 GetFunctionTimestamp ((XButtonEvent *)event));
1843 #ifdef ROOT_ICON_MENU
1844 if (focused && wmGD.iconClick &&
1845 event && event->type == KeyPress &&
1846 wmGD.nextKeyboardFocus &&
1847 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1848 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1851 * Post system menu from the icon
1853 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1856 #endif /* ROOT_ICON_MENU */
1861 } /* END OF FUNCTION F_Next_Key */
1865 /*************************************<->*************************************
1867 * F_Prev_Cmap (args, pCD, event)
1872 * This is the window manager function handler installing the previous
1873 * colormap in the list of client window colormaps.
1875 *************************************<->***********************************/
1877 Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
1881 pCD = ACTIVE_PSD->colormapFocus;
1884 if (pCD && (pCD->clientCmapCount > 0) &&
1885 ((pCD->clientState == NORMAL_STATE) ||
1886 (pCD->clientState == MAXIMIZED_STATE)))
1888 if (--(pCD->clientCmapIndex) < 0)
1890 pCD->clientCmapIndex = pCD->clientCmapCount - 1;
1892 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
1893 if (ACTIVE_PSD->colormapFocus == pCD)
1895 #ifndef OLD_COLORMAP /* colormap */
1897 * We just re-ordered the colormaps list,
1898 * so we need to re-run the whole thing.
1900 pCD->clientCmapFlagsInitialized = 0;
1901 ProcessColormapList (ACTIVE_PSD, pCD);
1902 #else /* OSF original */
1903 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
1910 } /* END OF FUNCTION F_Prev_Cmap */
1914 /*************************************<->*************************************
1916 * F_Prev_Key (args, pCD, event)
1921 * This is the window manager function handler for setting the keyboard
1922 * input focus to the previous window in the set of managed windows.
1927 * args = (immediate value) window type flags
1929 * pCD = pointer to the client data
1931 * event = X event that invoked the function (key, button, or menu/NULL)
1933 *************************************<->***********************************/
1935 Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
1937 #ifdef ROOT_ICON_MENU
1938 Boolean focused = False;
1939 #endif /* ROOT_ICON_MENU */
1940 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1942 #ifdef ROOT_ICON_MENU
1944 #endif /* ROOT_ICON_MENU */
1945 FocusPrevWindow ((unsigned long)args,
1946 GetFunctionTimestamp ((XButtonEvent *)event));
1947 #ifdef ROOT_ICON_MENU
1948 if (focused && wmGD.iconClick &&
1949 event && event->type == KeyPress &&
1950 wmGD.nextKeyboardFocus &&
1951 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1952 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1955 * Post system menu from the icon
1957 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1960 #endif /* ROOT_ICON_MENU */
1966 } /* END OF FUNCTION F_Prev_Key */
1968 /***********************<->*************************************
1970 * F_Post_FpMenu (args, pCD, event)
1975 * This is the window manager function handler for posting
1976 * the Front Panel window menu.
1980 * args = arguments (none)
1982 * pCD = pointer to the FP ClientData
1984 * event = X button press that invoked the function
1986 ******************************<->***********************************/
1989 F_Post_FpMenu (String args, ClientData *pCD, XEvent *event)
1991 static MenuSpec *fpMenuSpec = (MenuSpec *)NULL;
1993 if (event->type != ButtonPress)
1998 WmScreenData *pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2003 newMenuName = pCD ? pCD->systemMenu : "DtPanelMenu";
2005 for (oldSpec = pSD->menuSpecs;
2006 oldSpec != (MenuSpec *)NULL;
2007 oldSpec = oldSpec->nextMenuSpec)
2009 if (oldSpec->name && (strcmp(oldSpec->name, newMenuName) == 0))
2015 fpMenuSpec = DuplicateMenuSpec(oldSpec);
2018 * TEMPORARILY modify pSD so the new menu will be
2019 * created on DISPLAY1 instead of DISPLAY.
2021 fpMenuSpec->nextMenuSpec = pSD->menuSpecs;
2022 pSD->menuSpecs = fpMenuSpec;
2023 tmpWidget = pSD->screenTopLevelW;
2024 pSD->screenTopLevelW = pSD->screenTopLevelW1;
2026 (void)MAKE_MENU (pSD, pCD, newMenuName,
2027 F_CONTEXT_NORMAL, F_CONTEXT_NORMAL,
2028 (MenuItem *) NULL, FALSE);
2031 pSD->screenTopLevelW = tmpWidget;
2032 pSD->menuSpecs = fpMenuSpec->nextMenuSpec;
2035 PostMenu (fpMenuSpec, pCD, event->xbutton.x_root, event->xbutton.y_root,
2036 event->xbutton.button, F_CONTEXT_NORMAL, POST_AT_XY, event);
2038 _XmGetMenuState(XtParent(fpMenuSpec->menuWidget))
2039 ->MS_LastManagedMenuTime = event->xbutton.time;
2045 /***********************<->*************************************
2047 * F_Push_Recall (args, pCD, event)
2052 * This is the window manager function handler for invoking/topping
2053 * push_recall clients.
2060 * pCD = pointer to the ClientData
2062 * event = X event that invoked the function (key, button, or menu/NULL)
2067 * RETURN = if True then further button binding/function processing can
2068 * be done for the event that caused this function to be called.
2072 ******************************<->***********************************/
2075 F_Push_Recall (String args, ClientData *pCD, XEvent *event)
2077 WmPushRecallArg *pPRP;
2079 WmFpPushRecallClientData *pPRCD;
2081 pPRP = (WmPushRecallArg *) args;
2082 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2084 if (pPRP->ixReg < pSD->numPushRecallClients)
2086 /* get slot for this client */
2087 pPRCD = &(pSD->pPRCD[pPRP->ixReg]);
2090 * If the client is already running, then top it in this workspace,
2091 * else invoke the function to start it.
2095 /* Client is managed already. */
2096 if (!(ClientInWorkspace (pSD->pActiveWS, pPRCD->pCD)))
2098 WorkspaceID *wsRemoveList;
2102 * Move client to current workspace
2104 wsRemoveList = GetListOfOccupiedWorkspaces (pPRCD->pCD,
2106 RemoveClientFromWorkspaces (pPRCD->pCD, wsRemoveList,
2108 XtFree ((char *)wsRemoveList);
2109 AddClientToWorkspaces (pPRCD->pCD, &(pSD->pActiveWS->id), 1);
2110 SetClientWsIndex(pPRCD->pCD);
2111 SetClientState(pPRCD->pCD,
2112 pPRCD->pCD->clientState & ~UNSEEN_STATE, CurrentTime);
2115 /* Make this client visible */
2116 wmGD.bSuspendSecondaryRestack = True;
2117 F_Normalize_And_Raise (NULL, pPRCD->pCD, event);
2118 wmGD.bSuspendSecondaryRestack = False;
2122 struct timeval tvNow;
2124 Boolean bWaiting = False;
2126 if (pPRCD->tvTimeout.tv_sec != 0)
2128 gettimeofday (&tvNow, &tz);
2130 if ((pPRCD->tvTimeout.tv_sec > tvNow.tv_sec) ||
2131 ((pPRCD->tvTimeout.tv_sec == tvNow.tv_sec) &&
2132 (pPRCD->tvTimeout.tv_usec > tvNow.tv_usec)))
2134 /* still waiting for client to start */
2141 long clientTimeout = 0;
2144 WmPanelistObject pPanelist;
2146 pPanelist = (WmPanelistObject) pSD->wPanelist;
2148 /* invoke the function to start the client */
2149 pPRP->wmFunc ( pPRP->pArgs, pCD, event);
2151 if (pPanelist && panel.busy_light_data)
2153 /* set timeout value */
2156 XmNclientTimeoutInterval, &clientTimeout); ac++;
2157 XtGetValues (panel.busy_light_data->icon, (ArgList)al, ac);
2161 * ClientTimeout is in milliseconds, timeval values
2162 * are in seconds and microseconds.
2164 gettimeofday (&(pPRCD->tvTimeout), &tz);
2166 pPRCD->tvTimeout.tv_sec += clientTimeout / 1000;
2167 pPRCD->tvTimeout.tv_usec +=
2168 (clientTimeout % 1000) * 1000;
2170 pPRCD->tvTimeout.tv_sec += pPRCD->tvTimeout.tv_usec / 1000000;
2171 pPRCD->tvTimeout.tv_usec %= 1000000;
2178 } /* END OF FUNCTION F_Push_Recall */
2181 /*************************************<->*************************************
2183 * F_Pass_Key (args, pCD, event)
2188 * This is a function stub for the f.pass_key window manager function.
2193 * args = (immediate value) window type flags
2195 * pCD = pointer to the client data
2197 * event = X event that invoked the function (key, button, or menu/NULL)
2199 *************************************<->***********************************/
2201 Boolean F_Pass_Key (String args, ClientData *pCD, XEvent *event)
2203 if (wmGD.passKeysActive)
2206 * Get out of pass keys mode.
2209 wmGD.passKeysActive = False;
2210 wmGD.passKeysKeySpec = NULL;
2215 * Get into pass keys mode.
2218 wmGD.passKeysActive = True;
2223 } /* END OF FUNCTION F_Pass_Key */
2227 /*************************************<->*************************************
2229 * F_Maximize (args, pCD, event)
2234 * This is the window manager function handler for maximizing a client
2237 *************************************<->***********************************/
2239 Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
2241 if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
2243 SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
2244 GetFunctionTimestamp ((XButtonEvent *)event),
2245 GetEventInverseMask(event));
2250 } /* END OF FUNCTION F_Maximize */
2254 /*************************************<->*************************************
2256 * F_Menu (args, pCD, event)
2261 * This is the window manager function handler for posting a menu.
2262 * This function can only be invoked by a key or button event.
2263 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2264 * NULL when the menu is unposted.
2266 *************************************<->***********************************/
2268 Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
2271 Context menuContext;
2272 unsigned int button;
2275 long flags = POST_AT_XY;
2280 ((event->type == ButtonPress) || (event->type == ButtonRelease)))
2282 button = event->xbutton.button;
2283 x = event->xbutton.x_root;
2284 y = event->xbutton.y_root;
2285 if (event->type == ButtonRelease)
2287 flags |= POST_TRAVERSAL_ON;
2290 * Root menu, if posted with button press, then
2291 * set up to handle root menu click to make the menu
2294 else if (wmGD.rootButtonClick && (event->type == ButtonPress))
2296 if (wmGD.bReplayedButton)
2298 /* This button was replayed, it most likely dismissed
2299 a previous sticky menu, don't post a menu here */
2302 wmGD.checkHotspot = True;
2303 wmGD.hotspotRectangle.x = x - wmGD.moveThreshold/2;
2304 wmGD.hotspotRectangle.y = y - wmGD.moveThreshold/2;
2305 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2306 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2310 ((event->type == KeyPress) || (event->type == KeyRelease)))
2313 x = event->xkey.x_root;
2314 y = event->xkey.y_root;
2319 * A button or key event must be used to post a menu using this
2328 if (pCD->clientState == NORMAL_STATE)
2330 menuContext = F_CONTEXT_NORMAL;
2332 else if (pCD->clientState == MAXIMIZED_STATE)
2334 menuContext = F_CONTEXT_MAXIMIZE;
2338 menuContext = F_CONTEXT_ICON;
2340 if (P_ICON_BOX(pCD) &&
2341 event->xany.window == ICON_FRAME_WIN(pCD))
2343 if (pCD->clientState == MINIMIZED_STATE)
2345 menuContext = F_SUBCONTEXT_IB_IICON;
2349 menuContext = F_SUBCONTEXT_IB_WICON;
2355 menuContext = F_CONTEXT_ROOT;
2359 /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
2360 * This should have been done in MakeWmFunctionResources().
2363 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2364 if ((menuSpec = MAKE_MENU (pSD, pCD, args, menuContext,
2365 menuContext, (MenuItem *) NULL, FALSE)) != NULL)
2367 PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
2372 } /* END OF FUNCTION F_Menu */
2375 /*************************************<->*************************************
2377 * F_Minimize (args, pCD, event)
2382 * This is the window manager function handler for minimizing a client
2385 *************************************<->***********************************/
2387 Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
2389 ClientData *pcdLeader;
2395 * If the window is a transient then minimize the entire transient
2396 * tree including the transient leader.
2399 pcdLeader = (pCD->transientLeader) ?
2400 FindTransientTreeLeader (pCD) : pCD;
2401 if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
2403 SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
2404 GetFunctionTimestamp ((XButtonEvent *)event),
2405 GetEventInverseMask(event));
2411 } /* END OF FUNCTION F_Minimize */
2415 /*************************************<->*************************************
2417 * F_Move (args, pCD, event)
2422 * This is the window manager function handler for moving a client window
2425 *************************************<->***********************************/
2427 Boolean F_Move (String args, ClientData *pCD, XEvent *event)
2429 if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
2431 StartClientMove (pCD, event);
2432 HandleClientFrameMove (pCD, event);
2437 } /* END OF FUNCTION F_Move */
2441 /*************************************<->*************************************
2443 * F_Next_Cmap (args, pCD, event)
2448 * This is the window manager function handler installing the next
2449 * colormap in the list of client window colormaps.
2451 *************************************<->***********************************/
2453 Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
2457 pCD = ACTIVE_PSD->colormapFocus;
2460 if (pCD && (pCD->clientCmapCount > 0) &&
2461 ((pCD->clientState == NORMAL_STATE) ||
2462 (pCD->clientState == MAXIMIZED_STATE)))
2464 if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
2466 pCD->clientCmapIndex = 0;
2468 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2469 if (ACTIVE_PSD->colormapFocus == pCD)
2471 #ifndef OLD_COLORMAP /* colormap */
2473 * We just re-ordered the colormaps list,
2474 * so we need to re-run the whole thing.
2476 pCD->clientCmapFlagsInitialized = 0;
2477 ProcessColormapList (ACTIVE_PSD, pCD);
2478 #else /* OSF original */
2479 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2486 } /* END OF FUNCTION F_Next_Cmap */
2490 /*************************************<->*************************************
2492 * F_Nop (args, pCD, event)
2497 * This is the window manager function handler for doing nothing.
2499 *************************************<->***********************************/
2501 Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2506 } /* END OF FUNCTION F_Nop */
2510 /*************************************<->*************************************
2512 * F_Normalize (args, pCD, event)
2517 * This is the window manager function handler for putting a client window
2518 * in the normal state.
2520 *************************************<->***********************************/
2522 Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2527 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2528 GetFunctionTimestamp ((XButtonEvent *)event),
2529 GetEventInverseMask(event));
2534 } /* END OF FUNCTION F_Normalize */
2538 /*************************************<->*************************************
2540 * F_Normalize_And_Raise (args, pCD, event)
2545 * This is the window manager function handler for putting a client window
2546 * in the normal state and raising it from and icon.
2548 *************************************<->***********************************/
2550 Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2553 WmWorkspaceData *pWS;
2558 pSD = PSD_FOR_CLIENT (pCD);
2562 pWS = pSD->pActiveWS;
2564 if (pSD->useIconBox &&
2565 wmGD.useFrontPanel &&
2566 pSD->iconBoxControl &&
2567 (!strcmp(args, WmNiconBox)))
2570 * There's an icon box in the front panel and this is a
2571 * request to pop up the icon box.
2573 IconBoxPopUp (pWS, True);
2580 if (pCD->clientState == MINIMIZED_STATE)
2582 /* normalize window */
2583 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2586 ? GetFunctionTimestamp ((XButtonEvent *)event)
2588 GetEventInverseMask(event));
2592 /* Make sure we are in NORMAL_STATE */
2593 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2594 GetFunctionTimestamp ((XButtonEvent *)event),
2595 GetEventInverseMask(event));
2597 /* Raise the window and set the keyboard focus to the window */
2598 wmGD.bSuspendSecondaryRestack = True;
2599 F_Raise (NULL, pCD, (XEvent *)NULL);
2600 wmGD.bSuspendSecondaryRestack = False;
2601 if (wmGD.raiseKeyFocus)
2603 F_Focus_Key (NULL, pCD,
2606 : ((XEvent *)NULL)));
2609 wmGD.clickData.clickPending = False;
2610 wmGD.clickData.doubleClickPending = False;
2615 } /* END OF FUNCTION F_Normalize_And_Raise */
2619 /*************************************<->*************************************
2621 * F_Restore (args, pCD, event)
2626 * This is the window manager function handler for putting a client window
2627 * in the normal state.
2629 *************************************<->***********************************/
2631 Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2638 * If current state is MAXIMIZED state then just go to NORMAL state,
2639 * otherwise (you are in MINIMIZED state) return to previous state.
2642 if (pCD->clientState == MAXIMIZED_STATE)
2644 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2645 GetFunctionTimestamp ((XButtonEvent *)event),
2646 GetEventInverseMask(event));
2652 newState = MAXIMIZED_STATE;
2656 newState = NORMAL_STATE;
2659 SetClientStateWithEventMask (pCD, newState,
2660 GetFunctionTimestamp ((XButtonEvent *)event),
2661 GetEventInverseMask(event));
2667 } /* END OF FUNCTION F_Restore */
2671 /*************************************<->*************************************
2673 * F_Restore_And_Raise (args, pCD, event)
2678 * This is the window manager function handler for putting a client window
2679 * in the normal state and raising it from and icon.
2681 *************************************<->***********************************/
2683 Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2689 if (pCD->clientState == MINIMIZED_STATE)
2691 /* Restore window */
2694 newState = MAXIMIZED_STATE;
2698 newState = NORMAL_STATE;
2701 SetClientStateWithEventMask (pCD, newState,
2704 ? GetFunctionTimestamp ((XButtonEvent *)event)
2706 GetEventInverseMask(event));
2710 /* Make sure we restore the window first */
2711 F_Restore (NULL, pCD, event);
2713 /* Raise the window and set the keyboard focus to the window */
2714 wmGD.bSuspendSecondaryRestack = True;
2715 F_Raise (NULL, pCD, (XEvent *)NULL);
2716 wmGD.bSuspendSecondaryRestack = False;
2717 if (wmGD.raiseKeyFocus)
2719 F_Focus_Key (NULL, pCD,
2722 : ((XEvent *)NULL)));
2725 wmGD.clickData.clickPending = False;
2726 wmGD.clickData.doubleClickPending = False;
2731 } /* END OF FUNCTION F_Restore_And_Raise */
2735 /*************************************<->*************************************
2737 * F_Pack_Icons (args, pCD, event)
2742 * This is the window manager function handler for packing icons in the
2743 * icon box or on the desktop.
2745 *************************************<->***********************************/
2747 Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2752 if (ACTIVE_PSD->useIconBox)
2754 pIBD = ACTIVE_WS->pIconBox;
2757 while (pCD != pIBD->pCD_iconBox)
2759 if (pIBD->pNextIconBox)
2761 pIBD = pIBD->pNextIconBox;
2772 PackIconBox (pIBD, False, False, 0, 0);
2787 } /* END OF FUNCTION F_Pack_Icons */
2789 /*************************************<->*************************************
2791 * F_Post_SMenu (args, pCD, event)
2796 * This is the window manager function handler for posting the system menu
2797 * for the specified client.
2798 * This function can only be invoked by a key or button event.
2799 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2800 * NULL when the menu is unposted.
2802 *************************************<->***********************************/
2804 Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
2806 Context menuContext;
2810 * An event must be used to post the system menu using this function.
2813 if (event && pCD && pCD->systemMenuSpec)
2816 * Determine whether the keyboard is posting the menu and post
2817 * the menu at an appropriate place.
2820 if (pCD->clientState == NORMAL_STATE)
2822 menuContext = F_CONTEXT_NORMAL;
2824 else if (pCD->clientState == MAXIMIZED_STATE)
2826 menuContext = F_CONTEXT_MAXIMIZE;
2830 menuContext = F_CONTEXT_ICON;
2832 if (P_ICON_BOX(pCD) &&
2833 event->xany.window == ICON_FRAME_WIN(pCD))
2835 if (pCD->clientState == MINIMIZED_STATE)
2837 menuContext = F_SUBCONTEXT_IB_IICON;
2841 menuContext = F_SUBCONTEXT_IB_WICON;
2845 if ((event->type == KeyPress) || (event->type == KeyRelease))
2848 * Set up for "sticky" menu processing if specified.
2851 if (pCD->clientState == MINIMIZED_STATE ||
2852 menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
2856 wmGD.checkHotspot = True;
2859 else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
2861 wmGD.checkHotspot = True;
2864 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
2867 else if (event->type == ButtonPress)
2870 * Root menu, if posted with button press, then
2871 * set up to handle root menu click to make the menu
2874 if (wmGD.rootButtonClick && (!wmGD.checkHotspot))
2876 wmGD.checkHotspot = True;
2877 wmGD.hotspotRectangle.x =
2878 event->xbutton.x_root - wmGD.moveThreshold/2;
2879 wmGD.hotspotRectangle.y =
2880 event->xbutton.y_root - wmGD.moveThreshold/2;
2881 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2882 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2884 PostMenu (pCD->systemMenuSpec, pCD,
2885 event->xbutton.x_root, event->xbutton.y_root,
2886 event->xbutton.button, menuContext, POST_AT_XY, event);
2888 else if (event->type == ButtonRelease)
2890 PostMenu (pCD->systemMenuSpec, pCD,
2891 event->xbutton.x_root, event->xbutton.y_root,
2892 event->xbutton.button, menuContext,
2893 POST_AT_XY | POST_TRAVERSAL_ON, event);
2899 } /* END OF FUNCTION F_PostSMenu */
2903 /*************************************<->*************************************
2905 * F_Kill (args, pCD, event)
2910 * This is the window manager function handler for terminating a client.
2911 * Essentially the client connection is shut down.
2913 *************************************<->***********************************/
2915 Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
2917 if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
2919 Boolean do_delete_window =
2920 pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
2921 Boolean do_save_yourself =
2922 pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
2924 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
2929 * Get the widget for the subpanel
2930 * (Should be only child of the shell!)
2932 wPanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
2935 SlideSubpanelBackIn (pCD, wPanel);
2939 if (pCD->clientFlags & ICON_BOX)
2942 * When the front panel is used with the icon box,
2943 * "Close" hides the icon box into the front panel.
2945 if ((wmGD.useFrontPanel) &&
2946 (pCD->pSD->iconBoxControl) &&
2947 (IconBoxShowing(pCD->pSD->pActiveWS)))
2949 IconBoxPopUp (pCD->pSD->pActiveWS, False);
2952 else if (!do_delete_window && !do_save_yourself)
2954 XKillClient (DISPLAY, pCD->client);
2958 if (do_delete_window)
2961 * The client wants to be notified, not killed.
2964 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
2965 (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
2968 * HP does not want to send a client message for both
2969 * delete_window AND save_yourself. The current OSF
2970 * patch did just that. This "else if" returns dtwm
2971 * to the behavior of dt 2.01
2973 else if (do_save_yourself)
2976 * Send a WM_SAVE_YOURSELF message and wait for a change to
2977 * the WM_COMMAND property.
2978 * !!! button and key input should be kept from the window !!!
2981 if (AddWmTimer (TIMER_QUIT,
2982 (unsigned long) wmGD.quitTimeout, pCD))
2984 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
2985 (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
2987 pCD->clientFlags |= CLIENT_TERMINATING;
2991 XKillClient (DISPLAY, pCD->client);
2999 } /* END OF FUNCTION F_Kill */
3001 /*************************************<->*************************************
3003 * F_Marquee_Selection (args, pCD, event)
3008 * This is the window manager function handler for selecting
3009 * non-window manager objects on the root window.
3011 *************************************<->***********************************/
3013 Boolean F_Marquee_Selection (String args, ClientData *pCD, XEvent *event)
3018 * This function only valid in root context
3020 StartMarqueeSelect (ACTIVE_PSD, event);
3021 HandleMarqueeSelect (ACTIVE_PSD, event);
3026 } /* END OF FUNCTION F_Marquee_Selection */
3028 /*************************************<->*************************************
3030 * RefreshByClearing (win)
3035 * Recursively refresh this window and its children by doing
3038 *************************************<->***********************************/
3040 RefreshByClearing (Window win)
3044 Window root, parent;
3045 unsigned int nchildren;
3046 Window *winChildren;
3048 /* clear this window */
3049 XClearArea(DISPLAY, win, 0, 0, 0, 0, True);
3051 /* find any children and clear them, too */
3052 status = XQueryTree(DISPLAY, win, &root, &parent, &winChildren,
3056 /* recurse for each child window */
3057 for (i=0; i<nchildren; ++i)
3059 RefreshByClearing(winChildren[i]);
3064 XFree((char *)winChildren);
3069 /*************************************<->*************************************
3071 * F_Refresh (args, pCD, event)
3076 * This is the window manager function handler for causing all windows
3077 * in the workspace to be redrawn.
3079 *************************************<->***********************************/
3081 Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
3085 if (wmGD.refreshByClearing)
3087 RefreshByClearing (ACTIVE_ROOT);
3091 /* default background_pixmap is None */
3092 win = XCreateWindow (DISPLAY,
3094 (unsigned int) DisplayWidth (DISPLAY,
3096 (unsigned int) DisplayHeight (DISPLAY,
3103 (XSetWindowAttributes *)NULL);
3105 XMapWindow (DISPLAY, win);
3106 XDestroyWindow (DISPLAY, win);
3112 } /* END OF FUNCTION F_Refresh */
3116 /*************************************<->*************************************
3118 * F_Resize (args, pCD, event)
3123 * This is the window manager function handler for resizing a client window.
3125 *************************************<->***********************************/
3127 Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
3129 if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
3130 ((pCD->clientState == NORMAL_STATE) ||
3131 (pCD->clientState == MAXIMIZED_STATE)))
3133 StartClientResize (pCD, event);
3134 HandleClientFrameResize (pCD, event);
3139 } /* END OF FUNCTION F_Resize */
3143 /*************************************<->*************************************
3145 * F_Restart (args, pCD, event)
3150 * This is the window manager function handler for restarting the window
3153 *************************************<->***********************************/
3155 Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
3157 if (args && *args && !strcmp (args, DTWM_REQP_NO_CONFIRM))
3159 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3161 else if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
3163 ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
3167 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3171 } /* END OF FUNCTION F_Restart */
3175 /*************************************<->*************************************
3177 * Do_Restart (dummy)
3182 * Callback function for restarting the window manager.
3184 *************************************<->***********************************/
3186 void Do_Restart (Boolean dummy)
3188 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3190 } /* END OF FUNCTION Do_Restart */
3194 /*************************************<->*************************************
3196 * RestartWm (startupFlags)
3201 * Actually restarts the window manager.
3206 * startupFlags = flags to be put into the Wm_INFO property for restart.
3208 *************************************<->***********************************/
3210 void RestartWm (long startupFlags)
3212 ClientListEntry *pNextEntry;
3216 for (scr=0; scr<wmGD.numScreens; scr++)
3218 if(wmGD.Screens[scr].managed)
3222 * Set up the _MOTIF_WM_INFO property on the root window
3223 * to indicate a restart.
3226 SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
3227 SaveResources(&wmGD.Screens[scr]);
3229 * Unmap client windows and reparent them to the root window.
3232 pNextEntry = wmGD.Screens[scr].lastClient;
3235 if (pNextEntry->type == NORMAL_STATE)
3237 if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
3239 if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
3241 XUnmapWindow (DISPLAY,
3242 pNextEntry->pCD->clientFrameWin);
3247 DeFrameClient (pNextEntry->pCD);
3250 pNextEntry = pNextEntry->prevSibling;
3252 UnParentControls (&wmGD.Screens[scr], True);
3257 /* shut down the messaging connection */
3262 * This fixes restart problem when going from explicit focus to
3263 * pointer focus. Window under pointer was not getting focus indication
3264 * until pointer was moved to new window, or out of and into the
3268 XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
3269 XSync (DISPLAY, False);
3271 CLOSE_FILES_ON_EXEC();
3272 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3274 * Restart the window manager with the initial arguments plus
3275 * the restart settings.
3278 execvp (*(wmGD.argv), wmGD.argv);
3280 Warning (((char *)GETMESSAGE(26, 1,
3281 "The window manager restart failed. The window manager program could not \
3282 be found or could not be executed.")));
3287 } /* END OF FUNCTION RestartWm */
3290 /*************************************<->*************************************
3292 * DeFrameClient (pCD)
3297 * Unmaps a client window (and client icon window) and reparents the
3298 * window back to the root.
3303 * pCD = pointer to the client data for the window to be de-framed.
3305 *************************************<->***********************************/
3307 void DeFrameClient (ClientData *pCD)
3311 XWindowChanges windowChanges;
3315 if (pCD->clientState != MINIMIZED_STATE)
3317 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
3320 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
3322 XUnmapWindow (DISPLAY, pCD->iconWindow);
3323 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
3324 XReparentWindow (DISPLAY, pCD->iconWindow,
3325 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
3326 pCD->pWsList->iconY);
3336 if(wmGD.positionIsFrame)
3338 CalculateGravityOffset (pCD, &xoff, &yoff);
3339 x = pCD->clientX - xoff;
3340 y = pCD->clientY - yoff;
3349 #ifndef UNMAP_ON_RESTART
3350 if (pCD->clientState == MINIMIZED_STATE)
3352 XUnmapWindow (DISPLAY, pCD->client);
3355 XUnmapWindow (DISPLAY, pCD->client);
3357 XRemoveFromSaveSet (DISPLAY, pCD->client);
3358 XReparentWindow (DISPLAY, pCD->client,
3359 ROOT_FOR_CLIENT(pCD), x, y);
3361 if (pCD->transientChildren)
3363 DeFrameClient (pCD->transientChildren);
3369 windowChanges.x = x;
3370 windowChanges.y = y;
3371 windowChanges.border_width = pCD->xBorderWidth;
3372 XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
3375 if (pCD->transientLeader)
3377 pCD = pCD->transientSiblings;
3385 } /* END OF FUNCTION DeFrameClient */
3387 /******************************<->*************************************
3389 * F_Toggle_Front_Panel (args, pCD, event)
3394 * This is the window manager function handler for toggling the
3395 * front panel off and on.
3396 ******************************<->***********************************/
3399 F_Toggle_Front_Panel (String args, ClientData *pCD, XEvent *event)
3402 WmPanelistObject pPanelist;
3406 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3410 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3416 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3417 wmGD.windowContextType, (caddr_t *)&pCD);
3423 if (pCD->clientState & MINIMIZED_STATE)
3425 SetClientState (pCD, NORMAL_STATE,
3426 GetFunctionTimestamp ((XButtonEvent *)event));
3430 SetClientState (pCD, MINIMIZED_STATE,
3431 GetFunctionTimestamp ((XButtonEvent *)event));
3436 } /* END OF FUNCTION F_Toggle_Front_Panel */
3439 /******************************<->*************************************
3441 * Boolean F_Version (String args, ClientData *pCD, XEvent *event)
3445 * Invoke the help on version dialogue.
3449 * args - incoming values
3450 * pCD - associated client data structure
3451 * event - what triggered this call
3455 * Return - True if the call occurs; false otherwise.
3460 ******************************<->***********************************/
3462 F_Version (String args, ClientData *pCD, XEvent *event)
3465 WmPanelistObject pPanelist;
3469 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3473 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3478 WmDtHelpOnVersion (O_Shell (pPanelist));
3483 } /* END OF FUNCTION F_Version */
3486 /******************************<->*************************************
3488 * F_Send_Msg (args, pCD, event)
3493 * This is the window manager function handler for sending a client
3494 * message event to a client window.
3499 * args = (immediate value) message id
3501 * pCD = pointer to the client data
3503 * event = X event that invoked the function (key, button, or menu/NULL)
3506 ******************************<->***********************************/
3508 Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
3513 if (pCD && pCD->mwmMessagesCount)
3516 * A message id must be made "active" by being included in the
3517 * _MWM_MESSAGES property before the associated message can be sent.
3520 for (i = 0; i < pCD->mwmMessagesCount; i++)
3522 if (pCD->mwmMessages[i] == (long)args)
3524 SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES,
3525 (long)args, CurrentTime, NULL, 0);
3533 } /* END OF FUNCTION F_Send_Msg */
3537 /*************************************<->*************************************
3539 * F_Separator (args, pCD, event)
3544 * This is a placeholder function; it should never be called.
3546 *************************************<->***********************************/
3548 Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
3553 } /* END OF FUNCTION F_Separator */
3556 Boolean ForceRaiseWindow (ClientData *pcd)
3560 WmScreenData *pSD = (ACTIVE_WS)->pSD;
3562 XWindowChanges changes;
3563 Boolean restack = False;
3566 if (pSD->clientList->type == MINIMIZED_STATE)
3568 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
3572 stackWindow = pSD->clientList->pCD->clientFrameWin;
3577 * Windows did not raise on regular f.raise because the raise was
3578 * not relative to another window (methinks).
3580 changes.stack_mode = Above;
3581 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
3589 /*************************************<->*************************************
3591 * F_Raise (args, pCD, event)
3596 * This is the window manager function handler for topping the client window
3597 * so that it is unobscured.
3599 *************************************<->***********************************/
3601 Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
3603 ClientListEntry *pEntry;
3604 ClientListEntry *pNextEntry;
3605 ClientListEntry *pStackEntry;
3606 String string = args;
3607 int flags = STACK_NORMAL;
3608 WmWorkspaceData *pWS = ACTIVE_WS;
3612 /* process '-client' argument */
3613 if (string[0] == '-')
3615 string = &string[1];
3616 string = (String) GetString ((unsigned char **) &string);
3619 pNextEntry = ACTIVE_PSD->clientList;
3620 while (pNextEntry &&
3621 (pEntry = FindClientNameMatch (pNextEntry, True, string,
3624 pNextEntry = pEntry->nextSibling;
3625 if (ClientInWorkspace (pWS, pEntry->pCD))
3627 Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3628 pStackEntry = pEntry;
3632 /* process family stacking stuff */
3635 unsigned int slen, len, index;
3637 slen = strlen(args) - 2; /* subtract '\n' and NULL */
3638 for (index = 0; index < slen; string = &args[index+1])
3640 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3642 len = strlen(string);
3643 if (!strcmp(string,"within"))
3645 flags |= STACK_WITHIN_FAMILY;
3647 else if (!strcmp(string,"freeFamily"))
3649 flags |= STACK_FREE_FAMILY;
3653 if (ClientInWorkspace (pWS, pCD))
3655 Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3661 if (ClientInWorkspace (pWS, pCD))
3663 Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3669 } /* END OF FUNCTION F_Raise */
3673 /*************************************<->*************************************
3675 * Do_Raise (pCD, pStackEntry)
3680 * This is the window manager function handler for topping the client window
3681 * so that it is unobscured.
3686 * pCD = pointer to the client data of the window (or icon) to be raised.
3688 * pStackEntry = pointer to client list entry for window that is to be
3689 * above the raised window (if NULL window is raised to the top of the
3692 *************************************<->***********************************/
3694 void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3696 Boolean restackTransients;
3697 ClientData *pcdLeader;
3698 WmWorkspaceData *pWS = ACTIVE_WS;
3699 Boolean bLeaderRestacked;
3704 * Window has been reparented into the front panel.
3705 * Don't follow through on window stacking change.
3709 else if (ClientInWorkspace(pWS, pCD) &&
3710 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
3713 * Both clients are in the current workspace. Set
3714 * client indices so that the access macros work.
3716 SetClientWsIndex (pCD);
3719 SetClientWsIndex (pStackEntry->pCD);
3725 * One or both of the clients are not in the current workspace
3731 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
3733 if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
3736 * Don't raise the window above the system modal window.
3739 else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
3740 !P_ICON_BOX(pcdLeader))
3743 * If a dirtyStackEntry exists, return it to its original place
3744 * in the stack (for all stacking types)
3746 if (dirtyStackEntry)
3748 if (dirtyStackEntry->transientChildren ||
3749 dirtyStackEntry->transientLeader)
3750 RestackTransients (dirtyStackEntry);
3751 dirtyStackEntry = NULL;
3756 * Only restack the icon if it is not currently raised.
3761 if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
3763 StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
3765 MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
3771 if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
3773 StackWindow (pWS, &pcdLeader->iconEntry,
3774 True /*on top*/, (ClientListEntry *) NULL);
3775 MoveEntryInList (pWS, &pcdLeader->iconEntry,
3776 True /*on top*/, (ClientListEntry *) NULL);
3780 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
3783 * Handle restacking of primary/secondary windows
3784 * within the transient window tree. Don't raise this
3785 * window above any modal transients.
3787 bLeaderRestacked = False;
3788 if ((pcdLeader->transientChildren) &&
3789 (!pCD->secondariesOnTop) &&
3790 (!wmGD.bSuspendSecondaryRestack) &&
3791 (!IS_APP_MODALIZED(pCD)))
3793 if (pCD != pcdLeader)
3796 * This is not the transient leader, make sure
3797 * the transient leader isn't on top.
3798 * (Brute force solution)
3800 bLeaderRestacked = NormalizeTransientTreeStacking (pcdLeader);
3802 if (pCD->transientChildren)
3805 * This isn't the overall leader of the transient
3806 * tree, but it does have transient's of its own.
3807 * Move it to the top of its own transient sub-tree.
3809 bLeaderRestacked |= BumpPrimaryToTop (pCD);
3815 * This is the transient leader, move it to the
3818 bLeaderRestacked = BumpPrimaryToTop (pcdLeader);
3824 * If this is a transient window then put it on top of its
3825 * sibling transient windows.
3828 restackTransients = False;
3832 * Fix for 5325 - The following code has been reorganized to cause the
3833 * action of F_Raise to match the current documentation.
3834 * The new algorithm is as follows:
3836 * if (dirtyStackEntry)
3837 * restore dirty tree
3838 * if (not withinFamily)
3839 * bring window group to the top of global stack
3841 * raise the requested window to top of family
3843 * raise requested window to top of siblings
3844 * if (need to restack windows)
3849 * If a dirtyStackEntry exists, return it to its original place
3850 * in the stack (for all stacking types)
3852 if (dirtyStackEntry)
3855 * Check to make sure that the dirty pCD has either transient
3856 * children or a transient leader. If not, do not restore
3859 if (dirtyStackEntry->transientChildren ||
3860 dirtyStackEntry->transientLeader)
3861 RestackTransients (dirtyStackEntry);
3862 dirtyStackEntry = NULL;
3867 * If the flags do not indicate "within", raise the window family
3868 * to the top of the window stack. If the window is the primary,
3869 * raise it to the top regardless of the flags.
3871 if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
3875 if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
3877 StackWindow (pWS, &pcdLeader->clientEntry,
3878 False /*below*/, pStackEntry);
3879 MoveEntryInList (pWS, &pcdLeader->clientEntry,
3880 False /*below*/, pStackEntry);
3885 if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
3887 StackWindow (pWS, &pcdLeader->clientEntry,
3888 True /*on top*/, (ClientListEntry *) NULL);
3889 MoveEntryInList (pWS, &pcdLeader->clientEntry,
3890 True /*on top*/, (ClientListEntry *) NULL);
3896 * If freeFamily stacking is requested, check to make sure that
3897 * the window has either a transientChild or Leader. This will
3898 * guarantee that windows that form their own family are not
3899 * labelled as dirty (what's to dirty it up?). If it has either,
3900 * raise the window to the top of the family stack.
3902 if ((flags & STACK_FREE_FAMILY) &&
3903 (pCD->transientLeader || pCD->transientChildren))
3905 dirtyStackEntry = pCD;
3906 dirtyLeader = pcdLeader;
3908 restackTransients = ForceRaiseWindow (pCD);
3912 * If withinFamily stacking is requested, put the current transient
3913 * on top of its sibling transient windows.
3917 restackTransients = PutTransientOnTop (pCD);
3920 /* At this point, if doing a regular f.raise the window family has
3921 * already been brought to the top of the stack, so nothing further
3922 * needs to be done for it.
3925 /* Restack the transients if needed */
3927 if ((restackTransients) || (bLeaderRestacked))
3929 RestackTransients (pCD);
3933 } /* END OF FUNCTION Do_Raise */
3937 /*************************************<->*************************************
3939 * F_Raise_Lower (args, pCD, event)
3944 * This window manager function tops an obscured window or icon and bottoms
3945 * a window or icon that is on top of the window stack.
3947 *************************************<->***********************************/
3949 Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
3951 ClientData *pcdLeader;
3955 pcdLeader = (pCD->transientLeader) ?
3956 FindTransientTreeLeader (pCD) : pCD;
3959 * Treat a raise/lower on a window in a transient tree as if it is
3960 * a raise/lower for the whole tree.
3963 if (CheckIfClientObscuredByAny (pcdLeader))
3966 * The window is obscured by another window, raise the window.
3969 F_Raise (NULL, pCD, (XEvent *)NULL);
3971 else if (CheckIfClientObscuringAny (pcdLeader) &&
3972 !(wmGD.systemModalActive &&
3973 (pcdLeader == wmGD.systemModalClient)))
3976 * The window is obscuring another window and is
3977 * not system modal, lower the window.
3980 F_Lower (NULL, pcdLeader, (XEvent *)NULL);
3981 if ((pcdLeader->secondariesOnTop == False) &&
3982 (pCD->transientLeader != NULL) &&
3983 (!IS_APP_MODALIZED(pcdLeader)))
3985 /* Push transient below primary */
3986 (void) BumpPrimaryToTop (pcdLeader);
3987 RestackTransients (pcdLeader);
3990 else if ((pcdLeader->secondariesOnTop == False) &&
3991 (pcdLeader->transientChildren != NULL) &&
3992 (!wmGD.systemModalActive) &&
3993 (!IS_APP_MODALIZED(pcdLeader)))
3995 if (LeaderOnTop(pcdLeader))
3997 /* Push primary below transient */
3998 (void) BumpPrimaryToBottom (pcdLeader);
3999 RestackTransients (pcdLeader);
4003 F_Raise (NULL, pCD, (XEvent *)NULL);
4004 /* Push transient below primary */
4005 (void) BumpPrimaryToTop (pcdLeader);
4006 RestackTransients (pcdLeader);
4013 } /* END OF FUNCTION F_Raise_Lower */
4017 /*************************************<->*************************************
4019 * F_Refresh_Win (args, pCD, event)
4024 * This is the window manager function handler for causing a client window
4025 * to redisplay itself.
4027 *************************************<->***********************************/
4029 Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
4034 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
4035 (pCD->clientState == MAXIMIZED_STATE)))
4037 if (pCD->clientState == NORMAL_STATE)
4039 w = (unsigned int) pCD->clientWidth;
4040 h = (unsigned int) pCD->clientHeight;
4044 w = (unsigned int) pCD->maxWidth;
4045 h = (unsigned int) pCD->maxHeight;
4048 if (wmGD.refreshByClearing)
4050 RefreshByClearing (pCD->clientFrameWin);
4054 /* default background_pixmap is None */
4055 win = XCreateWindow (DISPLAY,
4065 (XSetWindowAttributes *)NULL);
4067 XMapWindow (DISPLAY, win);
4068 XDestroyWindow (DISPLAY, win);
4075 } /* END OF FUNCTION F_Refresh_Win */
4079 /*************************************<->*************************************
4081 * F_Set_Behavior (args, pCD, event)
4086 * This function is used to switch the window manager configuration between
4087 * the built-in configuration (for CXI behavior) and the user's custom
4090 *************************************<->***********************************/
4092 Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
4095 * Go system modal in starting to do the set behavior.
4098 /* !!! grab the server and the pointer !!! */
4102 * Confirm that a set_behavior should be done.
4103 * Execute restart if so.
4106 if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
4108 ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
4109 CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
4113 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4114 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4118 } /* END OF FUNCTION F_Set_Behavior */
4122 /*************************************<->*************************************
4124 * Do_Set_Behavior (dummy)
4129 * Callback to do the f.set_behavior function.
4131 *************************************<->***********************************/
4133 void Do_Set_Behavior (Boolean dummy)
4135 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4136 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4138 } /* END OF FUNCTION Do_Set_Behavior */
4140 /*************************************<->*************************************
4142 * F_Set_Context (args, pCD, event)
4147 * This function is used to set a client context for subsequent
4150 *************************************<->***********************************/
4152 Boolean F_Set_Context (String args, ClientData *pCD, XEvent *event)
4155 wmGD.requestContextWin = (Window) args;
4158 } /* END OF FUNCTION F_Set_Context */
4161 /*************************************<->*************************************
4163 * F_Title (args, pCD, event)
4168 * This is a placeholder function; it should never be called.
4170 *************************************<->***********************************/
4172 Boolean F_Title (String args, ClientData *pCD, XEvent *event)
4177 } /* END OF FUNCTION F_Title */
4181 /******************************<->*************************************
4183 * F_Screen (args, pCD, event)
4188 * This is the window manager function handler for warping to screens
4193 * args = (immediate value) window type flags
4195 * pCD = pointer to the client data
4197 * event = X event that invoked the function (key, button, or menu/NULL)
4199 * NOTE: May want to consider tracking changes in screen because in
4200 * managing a new window (ie. in ManageWindow()).
4204 * RETURN = if True then further button binding/function processing can
4205 * be done for the event that caused this function to be called.
4207 *************************************<->***********************************/
4209 Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
4213 unsigned int dummask;
4214 WmScreenData *newscr = NULL;
4216 static int PreviousScreen = -1;
4220 if (PreviousScreen == -1)
4222 PreviousScreen = DefaultScreen(DISPLAY);
4225 if (strcmp (args, "next") == 0)
4227 scr = ACTIVE_PSD->screen + 1;
4230 else if (strcmp (args, "prev") == 0)
4232 scr = ACTIVE_PSD->screen - 1;
4235 else if (strcmp (args, "back") == 0)
4237 scr = PreviousScreen;
4249 scr = wmGD.numScreens - 1;
4250 else if (scr >= wmGD.numScreens)
4253 newscr = &(wmGD.Screens[scr]);
4254 if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
4255 if (inc) { /* walk around the list */
4260 "Unable to warp to unmanaged screen %d\n", scr);
4267 if (ACTIVE_PSD->screen == scr) return (False); /* already on that screen */
4269 PreviousScreen = ACTIVE_PSD->screen;
4270 XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
4271 &dumint, &dumint, &dummask);
4273 XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
4275 if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
4278 * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can
4279 * uses the new screen instead of the old screen. Then call
4280 * Do_Focus_Key with a NULL pCD to find a reasonable client to
4283 SetActiveScreen (newscr);
4284 Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
4292 /*************************************<->*************************************
4294 * GetFunctionTimestamp (pEvent)
4299 * This function is used to extract a timestamp from a key or button event.
4300 * If the event passed in is not a key or button event then a timestamp
4306 * event = pointer to an X event
4311 * RETURN = a timestamp
4313 *************************************<->***********************************/
4315 Time GetFunctionTimestamp (XButtonEvent *pEvent)
4320 (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
4321 ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
4323 time = pEvent->time;
4327 time = GetTimestamp ();
4332 } /* END OF FUNCTION GetFunctionTimestamp */
4336 ** name the event mask we need for a grab in order to find the matching
4337 ** event for an event; right now handle only button-presses
4339 static unsigned int GetEventInverseMask(XEvent *event)
4341 if ((XEvent*)NULL == event)
4343 if (ButtonPress == event->type)
4344 return ButtonReleaseMask; /* detail ? */
4346 expansion further here
4354 /*************************************<->*************************************
4356 * ClearDirtyStackEntry (pCD)
4361 * This function is used to clear the static dirtyStackEntry structure and
4362 * the dirtyLeader static variable when a pCD is destroyed. This
4363 * guarantees that freed memory will not be accessed.
4368 * pCD = pointer to clientData being freed
4375 *************************************<->***********************************/
4377 void ClearDirtyStackEntry (ClientData *pCD)
4379 if (pCD == dirtyStackEntry)
4381 dirtyStackEntry = NULL;
4387 /***********************<->*************************************
4389 * F_ZZ_Debug (args, pCD, event)
4394 * This is the window manager debug (multi) function
4401 * pCD = pointer to the ClientData for the whole front panel
4403 * event = X event that invoked the function (key, button, or menu/NULL)
4408 * RETURN = if True then further button binding/function processing can
4409 * be done for the event that caused this function to be called.
4413 * Argument 1 determines the debug function to execute:
4417 * "color_server_info" - dump out color server info
4419 ******************************<->***********************************/
4422 F_ZZ_Debug (String subFcn, ClientData *pCD, XEvent *event)
4424 /* Only do something is sub function is specified */
4428 if (!(strcmp(subFcn, "dump_resources")))
4433 for (scr=0; scr<wmGD.numScreens; scr++)
4435 sprintf (szRes, "/tmp/dtwm.resources.%d", scr);
4437 XrmPutFileDatabase(XtScreenDatabase(
4438 XScreenOfDisplay(DISPLAY, scr)),
4447 /*************************************<->*************************************
4449 * F_Next_Workspace (args, pCD, event)
4454 * This function switches to the next workspace in the list
4456 *************************************<->***********************************/
4458 Boolean F_Next_Workspace (String args, ClientData *pCD, XEvent *event)
4460 WmScreenData *pSD = ACTIVE_PSD;
4463 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4465 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4472 /* check bounds and wrap */
4473 if (iwsx >= pSD->numWorkspaces)
4476 ChangeToWorkspace (&pSD->pWS[iwsx]);
4481 } /* END OF FUNCTION F_Next_Workspace */
4484 /*************************************<->*************************************
4486 * F_Prev_Workspace (args, pCD, event)
4491 * This function switches to the previous workspace in the list
4493 *************************************<->***********************************/
4495 Boolean F_Prev_Workspace (String args, ClientData *pCD, XEvent *event)
4497 WmScreenData *pSD = ACTIVE_PSD;
4500 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4502 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4509 /* check bounds and wrap */
4511 iwsx = pSD->numWorkspaces - 1;
4513 ChangeToWorkspace (&pSD->pWS[iwsx]);
4518 } /* END OF FUNCTION F_Prev_Workspace */
4522 /*************************************<->*************************************
4524 * F_Workspace_Presence (args, pCD, event)
4529 * This function pops up the workspace presence dialog box
4531 *************************************<->***********************************/
4533 Boolean F_Workspace_Presence (String args, ClientData *pCD, XEvent *event)
4535 Context wsContext = (Context)NULL;
4537 if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4539 if (pCD->clientState == NORMAL_STATE)
4541 wsContext = F_CONTEXT_NORMAL;
4543 else if (pCD->clientState == MAXIMIZED_STATE)
4545 wsContext = F_CONTEXT_MAXIMIZE;
4549 wsContext = F_CONTEXT_ICON;
4550 /* return (False); */
4552 ShowPresenceBox (pCD, wsContext);
4556 } /* END OF FUNCTION F_Workspace_Presence */
4562 WmScreenData *pSD = (ACTIVE_WS)->pSD;
4563 ClientListEntry *pCLE;
4565 fprintf (stdout, "Window stacking (bottom to top)\n");
4566 pCLE = pSD->lastClient;
4569 if (ClientInWorkspace (ACTIVE_WS, pCLE->pCD))
4570 fprintf (stdout, "* ");
4572 fprintf (stdout, " ");
4574 fprintf (stdout, "%08lx\t%s\n",
4576 pCLE->pCD->clientName);
4578 pCLE = pCLE->prevSibling;