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 (pcd)
225 static ClientData *second;
227 pcdNext = pcd->transientChildren;
230 if (pcdNext->transientChildren)
232 if (!pcdNext->transientChildren->transientChildren)
236 FindSecondToTopTransient (pcdNext);
238 pcdNext = pcdNext->transientSiblings;
239 if (pcdNext && !pcdNext->transientSiblings)
247 } /* END OF FUNCTION */
251 Boolean ForceLowerWindow (ClientData *pcd)
255 WmScreenData *pSD = (ACTIVE_WS)->pSD;
257 XWindowChanges changes;
258 Boolean restack = False;
260 WmScreenData *pSD = (ACTIVE_WS)->pSD;
262 ClientListEntry *pCLE;
265 * Find lowest window in this workspace. We'll stack this transient
268 pCLE = pSD->lastClient;
273 if ((pCLE->pCD != pcd) &&
274 (ClientInWorkspace (ACTIVE_WS, pCLE->pCD)))
276 if ((pCLE->type == MINIMIZED_STATE) &&
277 (pCLE->pCD->clientState == MINIMIZED_STATE))
279 stackWindow = ICON_FRAME_WIN(pCLE->pCD);
281 else if ((pCLE->type == NORMAL_STATE) &&
282 ((pCLE->pCD->clientState == NORMAL_STATE) ||
283 (pCLE->pCD->clientState == MAXIMIZED_STATE)))
285 stackWindow = pCLE->pCD->clientFrameWin;
288 if (stackWindow != None)
291 changes.sibling = stackWindow;
295 if (stackWindow == None)
297 pCLE = pCLE->prevSibling;
301 if (pSD->lastClient->type == MINIMIZED_STATE)
303 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
307 stackWindow = pSD->lastClient->pCD->clientFrameWin;
311 changes.stack_mode = Below;
314 XConfigureWindow (DISPLAY, pcd->clientFrameWin, mask, &changes);
322 /*************************************<->*************************************
324 * F_Lower (args, pCD, event)
329 * This is the window manager function handler for bottoming a client window
335 * args = function arguments (specified in .mwmrc file)
337 * pCD = pointer to the client data for the client window to which the
338 * function is to be applied
340 * event = X event that invoked the function (key, button, or menu/NULL)
345 * RETURN = if True then further button binding/function processing can
346 * be done for the event that caused this function to be called.
348 *************************************<->***********************************/
350 Boolean F_Lower (String args, ClientData *pCD, XEvent *event)
352 ClientListEntry *pEntry;
353 ClientListEntry *pNextEntry;
354 ClientListEntry *pStackEntry;
355 String string = args;
356 int flags = STACK_NORMAL;
357 WmWorkspaceData *pWS = ACTIVE_WS;
361 /* process '-client' argument */
362 if (string[0] == '-')
365 string = (String) GetString ((unsigned char **) &string);
368 pNextEntry = ACTIVE_PSD->lastClient;
370 (pEntry = FindClientNameMatch (pNextEntry, False,
371 string, F_GROUP_ALL)))
373 pNextEntry = pEntry->prevSibling;
374 if (ClientInWorkspace (pWS, pEntry->pCD))
376 Do_Lower (pEntry->pCD, pStackEntry, STACK_NORMAL);
377 pStackEntry = pEntry;
381 /* process family stacking stuff */
384 unsigned int slen, len, index;
386 slen = strlen(args) - 2; /* subtract '\n' and NULL */
387 for (index = 0; index < slen; string = &args[index+1])
389 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
391 len = strlen(string);
392 if (!strcmp(string,"within"))
394 flags |= STACK_WITHIN_FAMILY;
396 else if (!strcmp(string,"freeFamily"))
398 flags |= STACK_FREE_FAMILY;
402 if (ClientInWorkspace (pWS, pCD))
404 Do_Lower (pCD, (ClientListEntry *) NULL, flags);
410 if (ClientInWorkspace (pWS, pCD))
412 Do_Lower (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
417 * If caused by button press, event may ALSO cause focus to be
418 * passed to this client - prepare to disable focusAutoRaise.
420 if (pCD && event && (event->type == ButtonPress))
421 pCD->focusAutoRaiseDisablePending = True;
423 wmGD.passButtonsCheck = False;
426 } /* END OF FUNCTION F_Lower */
430 /*************************************<->*************************************
432 * Do_Lower (pCD, pStackEntry)
437 * This is the window manager function handler for lowering the client window
438 * so that it does not obscure any other window above the stack entry
444 * pCD = pointer to the client data of the window (or icon) to be lowered.
446 * pStackEntry = pointer to client list entry for window that is to be
447 * below the lowered window (if NULL, window is lowered to the bottom
450 *************************************<->***********************************/
452 void Do_Lower (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
454 Boolean restackTransients;
455 ClientData *pcdLeader;
456 WmWorkspaceData *pWS = ACTIVE_WS;
457 Boolean bLeaderRestacked;
462 * Window has been reparented into the front panel.
463 * Don't follow through on window stacking change.
468 if (ClientInWorkspace(pWS, pCD) &&
469 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
472 * Both clients are in the current workspace. Set
473 * client indices so that the access macros work.
475 SetClientWsIndex (pCD);
478 SetClientWsIndex (pStackEntry->pCD);
484 * One or both of the clients are not in the current workspace
490 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
492 if ((pcdLeader->clientState == MINIMIZED_STATE) && !P_ICON_BOX(pcdLeader))
495 * If a dirtyStackEntry exists, return it to its original place
496 * in the stack (for all stacking types)
500 if (dirtyStackEntry->transientChildren ||
501 dirtyStackEntry->transientLeader)
502 RestackTransients (dirtyStackEntry);
503 dirtyStackEntry = NULL;
508 * Only restack the icon if it is not currently lowered.
513 if (pStackEntry->prevSibling != &pcdLeader->iconEntry)
515 StackWindow (pWS, &pcdLeader->iconEntry, True /*above*/,
517 MoveEntryInList (pWS, &pcdLeader->iconEntry, True /*above*/,
523 if (ACTIVE_PSD->lastClient != &pcdLeader->iconEntry)
525 StackWindow (pWS, &pcdLeader->iconEntry,
526 False /*on bottom*/, (ClientListEntry *) NULL);
527 MoveEntryInList (pWS, &pcdLeader->iconEntry,
528 False /*on bottom*/, (ClientListEntry *) NULL);
532 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
535 * Handle restacking of primary/secondary windows
536 * within the transient window tree.
538 bLeaderRestacked = False;
539 if ((pcdLeader->transientChildren) &&
540 (!pcdLeader->secondariesOnTop) &&
541 (!wmGD.bSuspendSecondaryRestack))
543 if (pCD == pcdLeader)
546 * Lower requested on the leader itself, insure it's
549 bLeaderRestacked = BumpPrimaryToBottom (pcdLeader);
551 else if (pCD->transientChildren)
554 * Lower requested on the leader of a subtree. Insure
555 * that this subtree leader is at the bottom of the
558 bLeaderRestacked = BumpPrimaryToBottom (pCD);
560 else if (pCD->transientLeader)
565 * Lower requested on a transient. Insure all the
566 * subtree leaders up to the top are at the bottom
567 * of their respective transient subtrees.
569 for (pcdLdr = pCD->transientLeader;
571 pcdLdr = pcdLdr->transientLeader)
573 bLeaderRestacked |= BumpPrimaryToBottom (pcdLdr);
580 * If this is a transient window then put it below its
581 * sibling transient windows.
584 restackTransients = False;
585 if (pCD->transientLeader)
589 * If freeFamily stacking, then put dirty transient window
590 * (if any) back in place before force lowering current window
591 * to the bottom of the global window stack. Then return.
594 if (flags & STACK_FREE_FAMILY)
596 /* Restore dirty transient if not current window. */
597 if ((dirtyStackEntry) &&
598 (dirtyStackEntry != pCD))
600 RestackTransients (dirtyStackEntry);
603 dirtyStackEntry = pCD;
604 dirtyLeader = pcdLeader;
606 ForceLowerWindow (pCD);
611 * Reach here only if NOT doing a f.lower freeFamily (see
612 * return; statement above). Put current transient below
613 * its sibling transient windows.
615 restackTransients = PutTransientBelowSiblings (pCD);
619 * If doing a regular f.lower and you have a dirty window, then
620 * clean up dirty transient window.
626 * If lowering a window in the same family as the dirty
627 * transient window, then just restack before lowering.
628 * Else, restore the dirty transient in place before
629 * lowering the current window. Clear dirtyStack.
631 if (dirtyLeader == pcdLeader)
633 restackTransients = True;
637 RestackTransients (dirtyStackEntry);
640 dirtyStackEntry = NULL;
644 * Only restack the window or transient window tree if it is
645 * not currently lowered and the window is not a system
651 if ((pStackEntry->prevSibling != &pcdLeader->clientEntry) &&
652 !(wmGD.systemModalActive &&
653 (pcdLeader == wmGD.systemModalClient)))
655 StackWindow (pWS, &pcdLeader->clientEntry, True /*above*/,
657 MoveEntryInList (pWS, &pcdLeader->clientEntry, True /*above*/,
660 else if ((restackTransients) || (bLeaderRestacked))
662 RestackTransients (pCD);
667 if ((pWS->pSD->lastClient != &pcdLeader->clientEntry) &&
668 !(wmGD.systemModalActive &&
669 (pcdLeader == wmGD.systemModalClient)) &&
670 !(flags & STACK_WITHIN_FAMILY))
672 StackWindow (pWS, &pcdLeader->clientEntry, False /*on bottom*/,
673 (ClientListEntry *) NULL);
674 MoveEntryInList (pWS, &pcdLeader->clientEntry,
675 False /*on bottom*/, (ClientListEntry *) NULL);
677 else if ((restackTransients) || (bLeaderRestacked))
679 RestackTransients (pCD);
684 } /* END OF FUNCTION Do_Lower */
688 /*************************************<->*************************************
690 * F_CircleDown (args, pCD, event)
695 * This is the window manager function handler for moving the client window
696 * on top of stack to the bottom.
701 * args = function arguments (specified in .mwmrc file)
703 * pCD = pointer to the client data for the client window to which the
704 * function is to be applied
706 * event = X event that invoked the function (key, button, or menu/NULL)
711 * RETURN = if True then further button binding/function processing can
712 * be done for the event that caused this function to be called.
714 *************************************<->***********************************/
716 Boolean F_Circle_Down (String args, ClientData *pCD, XEvent *event)
719 unsigned long windowType;
720 ClientListEntry *pNextEntry;
725 * Go down through the client list looking for a window of an
726 * appropriate type that is obscuring lower windows.
729 types = (unsigned long)args;
730 pNextEntry = ACTIVE_PSD->clientList;
734 * Only check out the window if it is onscreen.
737 pcdNext = pNextEntry->pCD;
738 if (((pNextEntry->type == NORMAL_STATE) &&
739 (pcdNext->clientState != MINIMIZED_STATE)) ||
740 ((pNextEntry->type == MINIMIZED_STATE) &&
741 (pcdNext->clientState == MINIMIZED_STATE)))
743 if (pcdNext->clientState == MINIMIZED_STATE)
745 windowType = F_GROUP_ICON;
749 windowType = F_GROUP_WINDOW;
750 if (pcdNext->transientLeader || pcdNext->transientChildren)
752 windowType |= F_GROUP_TRANSIENT;
755 if (types & windowType)
757 if (CheckIfClientObscuringAny (pcdNext))
760 * This window (or window tree) is obscuring another window
761 * on the screen. Lower the window.
764 wmGD.bSuspendSecondaryRestack = True;
765 F_Lower (NULL, pcdNext, (XEvent *) NULL);
766 wmGD.bSuspendSecondaryRestack = False;
771 pNextEntry = pNextEntry->nextSibling;
776 } /* END OF FUNCTION F_Circle_Down */
780 /*************************************<->*************************************
782 * F_Circle_Up (args, pCD, event)
787 * This is the window manager function handler for moving the client window
788 * on the bottom of the stack to the top.
793 * args = function arguments (specified in .mwmrc file)
795 * pCD = pointer to the client data for the client window to which the
796 * function is to be applied
798 * event = X event that invoked the function (key, button, or menu/NULL)
803 * RETURN = if True then further button binding/function processing can
804 * be done for the event that caused this function to be called.
806 *************************************<->***********************************/
808 Boolean F_Circle_Up (String args, ClientData *pCD, XEvent *event)
811 unsigned long windowType;
812 ClientListEntry *pNextEntry;
817 * Go up through the client list looking for a window of an
818 * appropriate type that is obscured by higher windows.
821 types = (unsigned long)args;
822 pNextEntry = ACTIVE_PSD->lastClient;
826 * Only check out the window if it is onscreen.
829 pcdNext = pNextEntry->pCD;
830 if (((pNextEntry->type == NORMAL_STATE) &&
831 (pcdNext->clientState != MINIMIZED_STATE)) ||
832 ((pNextEntry->type == MINIMIZED_STATE) &&
833 (pcdNext->clientState == MINIMIZED_STATE)))
835 if (pcdNext->clientState == MINIMIZED_STATE)
837 windowType = F_GROUP_ICON;
841 windowType = F_GROUP_WINDOW;
842 if (pcdNext->transientLeader || pcdNext->transientChildren)
844 windowType |= F_GROUP_TRANSIENT;
847 if (types & windowType)
849 if (CheckIfClientObscuredByAny (pcdNext))
852 * This window (or window tree) is obscured by another
853 * window on the screen. Raise the window.
856 wmGD.bSuspendSecondaryRestack = True;
857 F_Raise (NULL, pcdNext, (XEvent *) NULL);
858 wmGD.bSuspendSecondaryRestack = False;
863 pNextEntry = pNextEntry->prevSibling;
869 } /* END OF FUNCTION F_Circle_Up */
873 /*************************************<->*************************************
875 * F_Focus_Color (args, pCD, event)
880 * This is the window manager function handler for setting the colormap
881 * focus to a client window or reinstalling the default colormap.
883 *************************************<->***********************************/
885 Boolean F_Focus_Color (String args, ClientData *pCD, XEvent *event)
888 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_EXPLICIT)
893 * The window selected for the colormap focus is a top-level client
894 * window. If there are subwindow colormaps then determine if the
895 * selection was in one of the subwindows.
898 if (pCD->clientState == MINIMIZED_STATE)
900 /* !!! colormap for client supplied icon window !!! */
905 SetColormapFocus (ACTIVE_PSD, pCD);
910 } /* END OF FUNCTION F_Focus_Color */
914 /*************************************<->*************************************
916 * F_Exec (args, pCD, event)
921 * This is the window manager function handler for executing a command
924 *************************************<->***********************************/
926 Boolean F_Exec (String args, ClientData *pCD, XEvent *event)
933 /* make sure the f.exec command runs on the right display. */
934 if (wmGD.pActiveSD->displayString)
936 putenv(wmGD.pActiveSD->displayString);
942 * Start the busy indicator, waiting for a pushbutton window
943 * for the given duration
945 WmFrontPanelSetBusy (True);
949 * Fork a process to exec a shell to run the specified command:
953 if ((pid = fork ()) == 0)
955 if ((pid = vfork ()) == 0)
960 #if defined(SVR4) || defined(__linux__)
972 #endif /* NO_SETPGRP */
975 * Clean up window manager resources.
976 * The X file descriptor should be automatically closed.
980 * Fix up signal handling.
982 RestoreDefaultSignalHandlers ();
985 * Fix up the child application's environment NOT to
986 * inherit the XFILESEARCHPATH, XBMLANGPATH, NLSPATH, etc.
989 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
991 CLOSE_FILES_ON_EXEC();
994 * Exec the command using $MWMSHELL if set or
995 * $SHELL if set and $MWMSHELL not set or sh.
998 if (((shell = getenv ("MWMSHELL")) != NULL) ||
999 ((shell = getenv ("SHELL")) != NULL))
1002 shellname = strrchr (shell, '/');
1003 if (shellname == NULL)
1006 If the shell pathname obtained from SHELL or MWMSHELL does not
1007 have a "/" in the path and if the user expects this shell to be
1008 obtained using the PATH variable rather than the current
1009 directory, then we must call execlp and not execl
1012 execlp (shell, shellname, "-c", args, NULL);
1017 execl (shell, shellname, "-c", args, NULL);
1022 * There is no SHELL environment variable or the first execl failed.
1026 execl ("/usr/bin/sh", "sh", "-c", args, NULL);
1028 execl ("/bin/sh", "sh", "-c", args, NULL);
1033 * Error - command could not be exec'ed.
1043 * Have the window manager wait for the shell to complete.
1047 * Don't need to wait because WSM sets SIGCLD handler
1052 * Restore original DISPLAY environment variable value
1053 * so a restart will start on the same screen
1056 if(wmGD.pActiveSD->displayString &&
1059 putenv(wmGD.displayString);
1066 } /* END OF FUNCTION F_Exec */
1070 /*************************************<->*************************************
1072 * F_Quit_Mwm (args, pCD, event)
1077 * This is the window manager function handler for terminating the window
1080 *************************************<->***********************************/
1082 Boolean F_Quit_Mwm (String args, ClientData *pCD, XEvent *event)
1084 if (wmGD.showFeedback & WM_SHOW_FB_QUIT)
1086 ConfirmAction (ACTIVE_PSD, QUIT_MWM_ACTION);
1095 } /* END OF FUNCTION F_Quit_Mwm */
1099 /*************************************<->*************************************
1101 * Do_Quit_Mwm (diedOnRestart)
1106 * Callback to do the f.quit_mwm function.
1108 *************************************<->***********************************/
1110 void Do_Quit_Mwm (Boolean diedOnRestart)
1113 ClientListEntry *pNextEntry;
1117 * Close the X connection to get all the X resources cleaned up.
1118 * !!! maybe windows should be reparented / rebordered before closing? !!!
1119 * !!! clean up the _MOTIF_WM_INFO property on the root window !!!
1125 XSetInputFocus(DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
1126 for (scr = 0; scr < wmGD.numScreens; scr++)
1128 if (wmGD.Screens[scr].managed)
1130 SaveResources(&wmGD.Screens[scr]);
1131 pNextEntry = wmGD.Screens[scr].lastClient;
1134 if (pNextEntry->type == NORMAL_STATE)
1136 if (!(pNextEntry->pCD->clientFlags &
1139 ReBorderClient (pNextEntry->pCD, diedOnRestart);
1142 pNextEntry = pNextEntry->prevSibling;
1144 UnParentControls (&wmGD.Screens[scr], False);
1148 /* shut down the messaging connection */
1151 XSync (DISPLAY, False);
1152 XCloseDisplay (DISPLAY);
1157 exit (WM_ERROR_EXIT_VALUE);
1164 } /* END OF FUNCTION Do_Quit_Mwm */
1167 /*************************************<->*************************************
1169 * ReBorderClient (pCD, reMapClient)
1174 * Restores X border for client window and reparents the
1175 * window back to the root.
1180 * pCD = pointer to the client data for the window to be re-bordered.
1182 *************************************<->***********************************/
1184 void ReBorderClient (ClientData *pCD, Boolean reMapClient)
1188 XWindowChanges windowChanges;
1192 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED) &&
1195 XUnmapWindow (DISPLAY, pCD->iconWindow);
1196 XReparentWindow (DISPLAY, pCD->iconWindow,
1197 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
1198 pCD->pWsList->iconY);
1210 if(wmGD.positionIsFrame)
1212 CalculateGravityOffset (pCD, &xoff, &yoff);
1213 x = pCD->clientX - xoff;
1214 y = pCD->clientY - yoff;
1222 XUnmapWindow(DISPLAY, pCD->clientFrameWin);
1223 XReparentWindow (DISPLAY, pCD->client,
1224 ROOT_FOR_CLIENT(pCD), x, y);
1228 XMapWindow(wmGD.display, pCD->client);
1231 if (pCD->transientChildren)
1233 ReBorderClient (pCD->transientChildren, reMapClient);
1241 windowChanges.x = x;
1242 windowChanges.y = y;
1243 windowChanges.border_width = pCD->xBorderWidth;
1244 XConfigureWindow (DISPLAY, pCD->client,
1245 CWBorderWidth | CWX | CWY, &windowChanges);
1248 if (pCD->transientLeader)
1250 pCD = pCD->transientSiblings;
1258 } /* END OF FUNCTION ReBorderClient */
1262 /*************************************<->*************************************
1264 * F_Focus_Key (args, pCD, event)
1269 * This is the window manager function handler for setting the keyboard
1270 * focus to a particular client window.
1275 * args = (immediate value) focus flags
1277 * pCD = pointer to the client data
1279 * event = X event that invoked the function (key, button, or menu/NULL)
1281 *************************************<->***********************************/
1283 Boolean F_Focus_Key (String args, ClientData *pCD, XEvent *event)
1285 long focusFlags = (long)args;
1288 if (pCD && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
1290 Do_Focus_Key (pCD, GetFunctionTimestamp ((XButtonEvent *)event),
1291 (focusFlags | ALWAYS_SET_FOCUS));
1296 } /* END OF FUNCTION F_Focus_Key */
1299 /*************************************<->*************************************
1301 * FindSomeReasonableClient
1305 * Find a client, any client to set the focus to, return client or NULL.
1306 * This code is ripped off from AutoResetKeyFocus().
1308 *************************************<->***********************************/
1310 static Window FindSomeReasonableClient(void)
1312 ClientData *pcdNoFocus=NULL;
1314 ClientListEntry *pNextEntry;
1316 ClientData *pcdLastFocus = (ClientData *) NULL;
1317 ClientData *pcdFocus;
1318 Window focusWindow = (Window) NULL;
1321 * Scan through the list of clients to find a window to get the focus.
1324 pNextEntry = ACTIVE_PSD->clientList;
1328 pCD = pNextEntry->pCD;
1329 if (!wmGD.systemModalActive ||
1330 (wmGD.systemModalClient == pCD))
1332 if ((pNextEntry->type != MINIMIZED_STATE) &&
1333 (pCD->clientState != MINIMIZED_STATE) &&
1334 (ClientInWorkspace (ACTIVE_WS, pCD)) &&
1335 (pCD != pcdNoFocus))
1337 if (pCD->transientChildren)
1339 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1346 ((pcdLastFocus == NULL) ||
1347 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1349 pcdLastFocus = pcdFocus;
1353 pNextEntry = pNextEntry->nextSibling;
1357 * Set the focus window if one is found
1361 ClientInWorkspace (ACTIVE_WS, pcdLastFocus))
1362 focusWindow = pcdLastFocus->client;
1365 * If a client window could not be found, then just put focus
1369 if (focusWindow == (Window) NULL)
1371 pNextEntry = ACTIVE_PSD->clientList;
1375 pCD = pNextEntry->pCD;
1377 if (ClientInWorkspace (ACTIVE_WS, pCD))
1379 if ((pNextEntry->type == MINIMIZED_STATE) ||
1380 (pCD->clientState == MINIMIZED_STATE))
1382 focusWindow = ICON_FRAME_WIN(pCD);
1386 pNextEntry = pNextEntry->nextSibling;
1390 return (focusWindow);
1392 } /* END OF FUNCTION FindSomeReasonableClient */
1397 /*************************************<->*************************************
1399 * Do_Focus_Key (pCD, focusTime, flags)
1404 * This function is used to set the focus to a window. The focus indication
1405 * is not changed until the FocusIn event is received.
1410 * pCD = pointer to the client data
1412 * focusTime = focus change time
1414 * flags = wm focus change flags
1416 *************************************<->***********************************/
1418 void Do_Focus_Key (ClientData *pCD, Time focusTime, long flags)
1420 ClientData *pcdFocus;
1424 /* Clear the replay flag */
1425 wmGD.replayEnterEvent = False;
1429 * Make sure the client is in the current workspace
1432 (ClientInWorkspace (ACTIVE_WS, pCD)))
1434 if (pCD->clientState == MINIMIZED_STATE)
1436 focusWindow = ICON_FRAME_WIN(pCD);
1438 else if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1441 * Set the keyboard focus to the indicated client window.
1442 * If the window has an application modal subordinate then
1443 * set the input focus to that window if the focus isn't
1444 * already owned by a subordinate.
1447 if (IS_APP_MODALIZED(pCD))
1449 ClientData *pcdFocusLeader,*currFocusLeader;
1452 * Handle case where a modal window exists when Mwm starts up.
1453 * wmGD.keyboardFocus is NULL, give focus to the modal dialog.
1456 if (wmGD.keyboardFocus)
1458 currFocusLeader = wmGD.keyboardFocus->transientLeader;
1462 currFocusLeader = (ClientData *) NULL;
1466 * Find focus leader for pCD
1469 pcdFocusLeader = pCD;
1470 while (pcdFocusLeader->transientLeader &&
1471 (pcdFocusLeader != currFocusLeader))
1473 pcdFocusLeader = pcdFocusLeader->transientLeader;
1476 if (pcdFocusLeader == currFocusLeader)
1478 pcdFocus = wmGD.keyboardFocus;
1483 pcdFocus = FindTransientFocus (pcdFocusLeader);
1488 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1489 * We must look at why FindTransientFocus is
1490 * returning a NULL pcd. The old code simply set
1491 * focusWindow = pcdFocus->client;
1492 * !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
1494 * 11/26/96 rswiston - In tracking down CDExc22816, we
1495 * discovered that pCD could get tricked into thinking
1496 * it had modal transients when in fact all its transients
1497 * had been withdrawn (fixed in WithdrawTransientChildren()).
1498 * As a result, FindTransientFocus() returns wmGD.keyboardFocus;
1499 * if nobody has the focus, FindTransientFocus() returns NULL.
1503 focusWindow = pcdFocus->client;
1507 focusWindow = (wmGD.keyboardFocus) ?
1508 wmGD.keyboardFocus->client : ACTIVE_PSD->wmWorkspaceWin;
1514 * If the focus policy is "pointer" don't set the focus to a
1515 * window if it has an application modal subordinate.
1518 if (IS_APP_MODALIZED(pCD))
1521 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1523 /* Replay this later when the modal window is removed. */
1524 wmGD.replayEnterEvent = True;
1528 focusWindow = pcdFocus->client;
1535 * Set up the default (non client specific) keyboard input focus.
1538 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1540 focusWindow = PointerRoot;
1545 * The WORKSPACE_IF_NULL flag is used to prevent client
1546 * windows from flashing when deiconifying a client.
1549 if (WORKSPACE_IF_NULL & flags)
1551 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1555 /* find some reasonable client so that focus is not lost */
1557 focusWindow = FindSomeReasonableClient();
1558 if (focusWindow == (Window)NULL)
1560 focusWindow = ACTIVE_PSD->wmWorkspaceWin;
1566 if ((pcdFocus != wmGD.keyboardFocus) || (flags & ALWAYS_SET_FOCUS))
1571 * Set the focus and/or send a take focus client message. This
1572 * is not done if a client area button press was done to set
1573 * set the focus and the window is a globally active input
1574 * style window (See ICCCM).
1577 if ( (flags & CLIENT_AREA_FOCUS) &&
1578 (pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1579 ! pcdFocus->inputFocusModel &&
1580 (pcdFocus == pCD) &&
1581 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
1582 !(pcdFocus->clientState == MINIMIZED_STATE)
1587 * 1. User clicked in the client area AND
1588 * 2. Input model is Globally Active AND
1589 * 3. Keyboard focus policy is explicit
1592 /* this window has WM_TAKE_FOCUS set and InputField false. */
1593 /* just send a message. */
1594 SendClientMsg (pcdFocus->client,
1595 (long) wmGD.xa_WM_PROTOCOLS,
1596 (long) wmGD.xa_WM_TAKE_FOCUS,
1597 focusTime, NULL, 0);
1601 if ((pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1602 !(pcdFocus->clientState == MINIMIZED_STATE))
1605 * Locally Active Input Model - Send a take focus message to the client.
1608 SendClientMsg (pcdFocus->client,
1609 (long) wmGD.xa_WM_PROTOCOLS,
1610 (long) wmGD.xa_WM_TAKE_FOCUS,
1611 focusTime, NULL, 0);
1615 * Don't set the input focus if the window has input_field set
1616 * to False or has expressed an interest in WM_TAKE_FOCUS
1617 * (ie. 'No Input', 'Globally Active', or 'Locally Active'),
1618 * and the user click in the client area. If the user clicks
1619 * on the titlebar or traverses to this window via f.next_key,
1620 * set the focus so that the user can access the window menu
1624 if ( wmGD.enforceKeyFocus || /* res - default == True. */
1625 (flags & ALWAYS_SET_FOCUS) ||
1626 !(flags & CLIENT_AREA_FOCUS)|| /* clicked on frame? */
1627 pcdFocus->inputFocusModel || /* Pass.|Glob. Active */
1628 (pcdFocus->clientState == MINIMIZED_STATE)
1631 if ( !(flags & CLIENT_AREA_FOCUS) &&
1632 !pcdFocus->inputFocusModel &&
1633 !(pcdFocus->clientState == MINIMIZED_STATE))
1635 /* the window doesn't want the focus - set it to the frame */
1636 /* user clicked on the frame but we don't want the focus */
1637 /* set it to the client's frame */
1638 XSetInputFocus (DISPLAY, pcdFocus->clientBaseWin,
1639 RevertToPointerRoot, focusTime);
1641 else if ( !(flags & CLIENT_AREA_FOCUS) &&
1642 !(pcdFocus->protocolFlags & PROTOCOL_WM_TAKE_FOCUS) &&
1643 pcdFocus->inputFocusModel
1646 XSetInputFocus (DISPLAY, focusWindow,
1647 RevertToPointerRoot, focusTime);
1651 XSetInputFocus (DISPLAY, focusWindow,
1652 RevertToParent, focusTime);
1658 * We've decided that the window shouldn't get the focus,
1659 * so don't change the focus.
1661 pcdFocus = wmGD.nextKeyboardFocus;
1667 XSetInputFocus (DISPLAY, focusWindow, RevertToPointerRoot,
1671 wmGD.nextKeyboardFocus = pcdFocus;
1675 } /* END OF FUNCTION Do_Focus_Key */
1678 /***********************<->*************************************
1680 * F_Goto_Workspace (args, pCD, event)
1684 * This is the window manager function handler for switching
1685 * to another workspace by name.
1689 * args = action function and arguments
1691 * pCD = pointer to the ClientData
1693 * event = X event that invoked the function (key, button, or menu/NULL)
1701 ******************************<->***********************************/
1703 F_Goto_Workspace (String args, ClientData *pCD, XEvent *event)
1705 WmScreenData *pSD = ACTIVE_PSD;
1710 * Compare argument against both resource name
1711 * and workspace title, take the first match.
1713 xms = XmStringCreate (args, XmFONTLIST_DEFAULT_TAG);
1714 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
1716 if (!strcmp(pSD->pWS[iwsx].name, args) ||
1717 XmStringCompare (xms, pSD->pWS[iwsx].title))
1726 if (iwsx >= pSD->numWorkspaces)
1728 Warning (((char *)GETMESSAGE(26, 4,
1729 "Invalid workspace name specified for f.goto_workspace")));
1733 ChangeToWorkspace (&pSD->pWS[iwsx]);
1738 } /* END OF FUNCTION F_Goto_Workspace */
1741 /******************************<->*************************************
1743 * Boolean F_Help (String args, ClientData *pCD, XEvent *event)
1747 * Invoke help on the workspace manager
1751 * args - incoming values
1752 * pCD - associated client data structure
1753 * event - what triggered this call
1757 * Return - True if the call occurs; false otherwise.
1762 ******************************<->***********************************/
1764 F_Help (String args, ClientData *pCD, XEvent *event)
1768 rval = WmDtHelp(args);
1770 } /* END OF FUNCTION F_Help */
1773 /******************************<->*************************************
1775 * Boolean F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1779 * Invoke item help on the frontpanel
1784 * pCD - associated client data structure ??
1785 * event - what triggered this call
1789 * Return - True if the call occurs; false otherwise.
1794 ******************************<->***********************************/
1796 F_Help_Mode (String args, ClientData *pCD, XEvent *event)
1799 * Help mode event processing interferes
1800 * with slide up windows. Don't continue
1801 * if windows are sliding.
1803 if (wmGD.iSlideUpsInProgress == 0)
1805 (void) WmDtHelpMode();
1808 } /* END OF FUNCTION F_Help_Mode */
1811 /******************************<->*************************************
1813 * F_Next_Key (args, pCD, event)
1818 * This is the window manager function handler for setting the keyboard
1819 * input focus to the next window in the set of managed windows.
1824 * args = (immediate value) window type flags
1826 * pCD = pointer to the client data
1828 * event = X event that invoked the function (key, button, or menu/NULL)
1830 *************************************<->***********************************/
1832 Boolean F_Next_Key (String args, ClientData *pCD, XEvent *event)
1834 #ifdef ROOT_ICON_MENU
1835 Boolean focused = False;
1836 #endif /* ROOT_ICON_MENU */
1837 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1839 #ifdef ROOT_ICON_MENU
1841 #endif /* ROOT_ICON_MENU */
1842 FocusNextWindow ((unsigned long)args,
1843 GetFunctionTimestamp ((XButtonEvent *)event));
1844 #ifdef ROOT_ICON_MENU
1845 if (focused && wmGD.iconClick &&
1846 event && event->type == KeyPress &&
1847 wmGD.nextKeyboardFocus &&
1848 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1849 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1852 * Post system menu from the icon
1854 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1857 #endif /* ROOT_ICON_MENU */
1862 } /* END OF FUNCTION F_Next_Key */
1866 /*************************************<->*************************************
1868 * F_Prev_Cmap (args, pCD, event)
1873 * This is the window manager function handler installing the previous
1874 * colormap in the list of client window colormaps.
1876 *************************************<->***********************************/
1878 Boolean F_Prev_Cmap (String args, ClientData *pCD, XEvent *event)
1882 pCD = ACTIVE_PSD->colormapFocus;
1885 if (pCD && (pCD->clientCmapCount > 0) &&
1886 ((pCD->clientState == NORMAL_STATE) ||
1887 (pCD->clientState == MAXIMIZED_STATE)))
1889 if (--(pCD->clientCmapIndex) < 0)
1891 pCD->clientCmapIndex = pCD->clientCmapCount - 1;
1893 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
1894 if (ACTIVE_PSD->colormapFocus == pCD)
1896 #ifndef OLD_COLORMAP /* colormap */
1898 * We just re-ordered the colormaps list,
1899 * so we need to re-run the whole thing.
1901 pCD->clientCmapFlagsInitialized = 0;
1902 ProcessColormapList (ACTIVE_PSD, pCD);
1903 #else /* OSF original */
1904 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
1911 } /* END OF FUNCTION F_Prev_Cmap */
1915 /*************************************<->*************************************
1917 * F_Prev_Key (args, pCD, event)
1922 * This is the window manager function handler for setting the keyboard
1923 * input focus to the previous window in the set of managed windows.
1928 * args = (immediate value) window type flags
1930 * pCD = pointer to the client data
1932 * event = X event that invoked the function (key, button, or menu/NULL)
1934 *************************************<->***********************************/
1936 Boolean F_Prev_Key (String args, ClientData *pCD, XEvent *event)
1938 #ifdef ROOT_ICON_MENU
1939 Boolean focused = False;
1940 #endif /* ROOT_ICON_MENU */
1941 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
1943 #ifdef ROOT_ICON_MENU
1945 #endif /* ROOT_ICON_MENU */
1946 FocusPrevWindow ((unsigned long)args,
1947 GetFunctionTimestamp ((XButtonEvent *)event));
1948 #ifdef ROOT_ICON_MENU
1949 if (focused && wmGD.iconClick &&
1950 event && event->type == KeyPress &&
1951 wmGD.nextKeyboardFocus &&
1952 wmGD.nextKeyboardFocus->clientState == MINIMIZED_STATE &&
1953 !P_ICON_BOX(wmGD.nextKeyboardFocus))
1956 * Post system menu from the icon
1958 F_Post_SMenu (args, wmGD.nextKeyboardFocus, event);
1961 #endif /* ROOT_ICON_MENU */
1967 } /* END OF FUNCTION F_Prev_Key */
1969 /***********************<->*************************************
1971 * F_Post_FpMenu (args, pCD, event)
1976 * This is the window manager function handler for posting
1977 * the Front Panel window menu.
1981 * args = arguments (none)
1983 * pCD = pointer to the FP ClientData
1985 * event = X button press that invoked the function
1987 ******************************<->***********************************/
1990 F_Post_FpMenu (String args, ClientData *pCD, XEvent *event)
1992 static MenuSpec *fpMenuSpec = (MenuSpec *)NULL;
1994 if (event->type != ButtonPress)
1999 WmScreenData *pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2004 newMenuName = pCD ? pCD->systemMenu : "DtPanelMenu";
2006 for (oldSpec = pSD->menuSpecs;
2007 oldSpec != (MenuSpec *)NULL;
2008 oldSpec = oldSpec->nextMenuSpec)
2010 if (oldSpec->name && (strcmp(oldSpec->name, newMenuName) == 0))
2016 fpMenuSpec = DuplicateMenuSpec(oldSpec);
2019 * TEMPORARILY modify pSD so the new menu will be
2020 * created on DISPLAY1 instead of DISPLAY.
2022 fpMenuSpec->nextMenuSpec = pSD->menuSpecs;
2023 pSD->menuSpecs = fpMenuSpec;
2024 tmpWidget = pSD->screenTopLevelW;
2025 pSD->screenTopLevelW = pSD->screenTopLevelW1;
2027 (void)MAKE_MENU (pSD, pCD, newMenuName,
2028 F_CONTEXT_NORMAL, F_CONTEXT_NORMAL,
2029 (MenuItem *) NULL, FALSE);
2032 pSD->screenTopLevelW = tmpWidget;
2033 pSD->menuSpecs = fpMenuSpec->nextMenuSpec;
2036 PostMenu (fpMenuSpec, pCD, event->xbutton.x_root, event->xbutton.y_root,
2037 event->xbutton.button, F_CONTEXT_NORMAL, POST_AT_XY, event);
2039 _XmGetMenuState(XtParent(fpMenuSpec->menuWidget))
2040 ->MS_LastManagedMenuTime = event->xbutton.time;
2046 /***********************<->*************************************
2048 * F_Push_Recall (args, pCD, event)
2053 * This is the window manager function handler for invoking/topping
2054 * push_recall clients.
2061 * pCD = pointer to the ClientData
2063 * event = X event that invoked the function (key, button, or menu/NULL)
2068 * RETURN = if True then further button binding/function processing can
2069 * be done for the event that caused this function to be called.
2073 ******************************<->***********************************/
2076 F_Push_Recall (String args, ClientData *pCD, XEvent *event)
2078 WmPushRecallArg *pPRP;
2080 WmFpPushRecallClientData *pPRCD;
2082 pPRP = (WmPushRecallArg *) args;
2083 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2085 if (pPRP->ixReg < pSD->numPushRecallClients)
2087 /* get slot for this client */
2088 pPRCD = &(pSD->pPRCD[pPRP->ixReg]);
2091 * If the client is already running, then top it in this workspace,
2092 * else invoke the function to start it.
2096 /* Client is managed already. */
2097 if (!(ClientInWorkspace (pSD->pActiveWS, pPRCD->pCD)))
2099 WorkspaceID *wsRemoveList;
2103 * Move client to current workspace
2105 wsRemoveList = GetListOfOccupiedWorkspaces (pPRCD->pCD,
2107 RemoveClientFromWorkspaces (pPRCD->pCD, wsRemoveList,
2109 XtFree ((char *)wsRemoveList);
2110 AddClientToWorkspaces (pPRCD->pCD, &(pSD->pActiveWS->id), 1);
2111 SetClientWsIndex(pPRCD->pCD);
2112 SetClientState(pPRCD->pCD,
2113 pPRCD->pCD->clientState & ~UNSEEN_STATE, CurrentTime);
2116 /* Make this client visible */
2117 wmGD.bSuspendSecondaryRestack = True;
2118 F_Normalize_And_Raise (NULL, pPRCD->pCD, event);
2119 wmGD.bSuspendSecondaryRestack = False;
2123 struct timeval tvNow;
2125 Boolean bWaiting = False;
2127 if (pPRCD->tvTimeout.tv_sec != 0)
2129 gettimeofday (&tvNow, &tz);
2131 if ((pPRCD->tvTimeout.tv_sec > tvNow.tv_sec) ||
2132 ((pPRCD->tvTimeout.tv_sec == tvNow.tv_sec) &&
2133 (pPRCD->tvTimeout.tv_usec > tvNow.tv_usec)))
2135 /* still waiting for client to start */
2142 long clientTimeout = 0;
2145 WmPanelistObject pPanelist;
2147 pPanelist = (WmPanelistObject) pSD->wPanelist;
2149 /* invoke the function to start the client */
2150 pPRP->wmFunc ( pPRP->pArgs, pCD, event);
2152 if (pPanelist && panel.busy_light_data)
2154 /* set timeout value */
2157 XmNclientTimeoutInterval, &clientTimeout); ac++;
2158 XtGetValues (panel.busy_light_data->icon, (ArgList)al, ac);
2162 * ClientTimeout is in milliseconds, timeval values
2163 * are in seconds and microseconds.
2165 gettimeofday (&(pPRCD->tvTimeout), &tz);
2167 pPRCD->tvTimeout.tv_sec += clientTimeout / 1000;
2168 pPRCD->tvTimeout.tv_usec +=
2169 (clientTimeout % 1000) * 1000;
2171 pPRCD->tvTimeout.tv_sec += pPRCD->tvTimeout.tv_usec / 1000000;
2172 pPRCD->tvTimeout.tv_usec %= 1000000;
2179 } /* END OF FUNCTION F_Push_Recall */
2182 /*************************************<->*************************************
2184 * F_Pass_Key (args, pCD, event)
2189 * This is a function stub for the f.pass_key window manager function.
2194 * args = (immediate value) window type flags
2196 * pCD = pointer to the client data
2198 * event = X event that invoked the function (key, button, or menu/NULL)
2200 *************************************<->***********************************/
2202 Boolean F_Pass_Key (args, pCD, event)
2208 if (wmGD.passKeysActive)
2211 * Get out of pass keys mode.
2214 wmGD.passKeysActive = False;
2215 wmGD.passKeysKeySpec = NULL;
2220 * Get into pass keys mode.
2223 wmGD.passKeysActive = True;
2228 } /* END OF FUNCTION F_Pass_Key */
2232 /*************************************<->*************************************
2234 * F_Maximize (args, pCD, event)
2239 * This is the window manager function handler for maximizing a client
2242 *************************************<->***********************************/
2244 Boolean F_Maximize (String args, ClientData *pCD, XEvent *event)
2246 if (pCD && (pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
2248 SetClientStateWithEventMask (pCD, MAXIMIZED_STATE,
2249 GetFunctionTimestamp ((XButtonEvent *)event),
2250 GetEventInverseMask(event));
2255 } /* END OF FUNCTION F_Maximize */
2259 /*************************************<->*************************************
2261 * F_Menu (args, pCD, event)
2266 * This is the window manager function handler for posting a menu.
2267 * This function can only be invoked by a key or button event.
2268 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2269 * NULL when the menu is unposted.
2271 *************************************<->***********************************/
2273 Boolean F_Menu (String args, ClientData *pCD, XEvent *event)
2276 Context menuContext;
2277 unsigned int button;
2280 long flags = POST_AT_XY;
2285 ((event->type == ButtonPress) || (event->type == ButtonRelease)))
2287 button = event->xbutton.button;
2288 x = event->xbutton.x_root;
2289 y = event->xbutton.y_root;
2290 if (event->type == ButtonRelease)
2292 flags |= POST_TRAVERSAL_ON;
2295 * Root menu, if posted with button press, then
2296 * set up to handle root menu click to make the menu
2299 else if (wmGD.rootButtonClick && (event->type == ButtonPress))
2301 if (wmGD.bReplayedButton)
2303 /* This button was replayed, it most likely dismissed
2304 a previous sticky menu, don't post a menu here */
2307 wmGD.checkHotspot = True;
2308 wmGD.hotspotRectangle.x = x - wmGD.moveThreshold/2;
2309 wmGD.hotspotRectangle.y = y - wmGD.moveThreshold/2;
2310 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2311 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2315 ((event->type == KeyPress) || (event->type == KeyRelease)))
2318 x = event->xkey.x_root;
2319 y = event->xkey.y_root;
2324 * A button or key event must be used to post a menu using this
2333 if (pCD->clientState == NORMAL_STATE)
2335 menuContext = F_CONTEXT_NORMAL;
2337 else if (pCD->clientState == MAXIMIZED_STATE)
2339 menuContext = F_CONTEXT_MAXIMIZE;
2343 menuContext = F_CONTEXT_ICON;
2345 if (P_ICON_BOX(pCD) &&
2346 event->xany.window == ICON_FRAME_WIN(pCD))
2348 if (pCD->clientState == MINIMIZED_STATE)
2350 menuContext = F_SUBCONTEXT_IB_IICON;
2354 menuContext = F_SUBCONTEXT_IB_WICON;
2360 menuContext = F_CONTEXT_ROOT;
2364 /* We do not add this MenuSpec to wmGD.acceleratorMenuSpecs.
2365 * This should have been done in MakeWmFunctionResources().
2368 pSD = (pCD) ? PSD_FOR_CLIENT(pCD) : ACTIVE_PSD;
2369 if ((menuSpec = MAKE_MENU (pSD, pCD, args, menuContext,
2370 menuContext, (MenuItem *) NULL, FALSE)) != NULL)
2372 PostMenu (menuSpec, pCD, x, y, button, menuContext, flags, event);
2377 } /* END OF FUNCTION F_Menu */
2380 /*************************************<->*************************************
2382 * F_Minimize (args, pCD, event)
2387 * This is the window manager function handler for minimizing a client
2390 *************************************<->***********************************/
2392 Boolean F_Minimize (String args, ClientData *pCD, XEvent *event)
2394 ClientData *pcdLeader;
2400 * If the window is a transient then minimize the entire transient
2401 * tree including the transient leader.
2404 pcdLeader = (pCD->transientLeader) ?
2405 FindTransientTreeLeader (pCD) : pCD;
2406 if (pcdLeader->clientFunctions & MWM_FUNC_MINIMIZE)
2408 SetClientStateWithEventMask (pCD, MINIMIZED_STATE,
2409 GetFunctionTimestamp ((XButtonEvent *)event),
2410 GetEventInverseMask(event));
2416 } /* END OF FUNCTION F_Minimize */
2420 /*************************************<->*************************************
2422 * F_Move (args, pCD, event)
2427 * This is the window manager function handler for moving a client window
2430 *************************************<->***********************************/
2432 Boolean F_Move (String args, ClientData *pCD, XEvent *event)
2434 if (pCD && (pCD->clientFunctions & MWM_FUNC_MOVE))
2436 StartClientMove (pCD, event);
2437 HandleClientFrameMove (pCD, event);
2442 } /* END OF FUNCTION F_Move */
2446 /*************************************<->*************************************
2448 * F_Next_Cmap (args, pCD, event)
2453 * This is the window manager function handler installing the next
2454 * colormap in the list of client window colormaps.
2456 *************************************<->***********************************/
2458 Boolean F_Next_Cmap (String args, ClientData *pCD, XEvent *event)
2462 pCD = ACTIVE_PSD->colormapFocus;
2465 if (pCD && (pCD->clientCmapCount > 0) &&
2466 ((pCD->clientState == NORMAL_STATE) ||
2467 (pCD->clientState == MAXIMIZED_STATE)))
2469 if (++(pCD->clientCmapIndex) >= pCD->clientCmapCount)
2471 pCD->clientCmapIndex = 0;
2473 pCD->clientColormap = pCD->clientCmapList[pCD->clientCmapIndex];
2474 if (ACTIVE_PSD->colormapFocus == pCD)
2476 #ifndef OLD_COLORMAP /* colormap */
2478 * We just re-ordered the colormaps list,
2479 * so we need to re-run the whole thing.
2481 pCD->clientCmapFlagsInitialized = 0;
2482 ProcessColormapList (ACTIVE_PSD, pCD);
2483 #else /* OSF original */
2484 WmInstallColormap (ACTIVE_PSD, pCD->clientColormap);
2491 } /* END OF FUNCTION F_Next_Cmap */
2495 /*************************************<->*************************************
2497 * F_Nop (args, pCD, event)
2502 * This is the window manager function handler for doing nothing.
2504 *************************************<->***********************************/
2506 Boolean F_Nop (String args, ClientData *pCD, XEvent *event)
2511 } /* END OF FUNCTION F_Nop */
2515 /*************************************<->*************************************
2517 * F_Normalize (args, pCD, event)
2522 * This is the window manager function handler for putting a client window
2523 * in the normal state.
2525 *************************************<->***********************************/
2527 Boolean F_Normalize (String args, ClientData *pCD, XEvent *event)
2532 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2533 GetFunctionTimestamp ((XButtonEvent *)event),
2534 GetEventInverseMask(event));
2539 } /* END OF FUNCTION F_Normalize */
2543 /*************************************<->*************************************
2545 * F_Normalize_And_Raise (args, pCD, event)
2550 * This is the window manager function handler for putting a client window
2551 * in the normal state and raising it from and icon.
2553 *************************************<->***********************************/
2555 Boolean F_Normalize_And_Raise (String args, ClientData *pCD, XEvent *event)
2558 WmWorkspaceData *pWS;
2563 pSD = PSD_FOR_CLIENT (pCD);
2567 pWS = pSD->pActiveWS;
2569 if (pSD->useIconBox &&
2570 wmGD.useFrontPanel &&
2571 pSD->iconBoxControl &&
2572 (!strcmp(args, WmNiconBox)))
2575 * There's an icon box in the front panel and this is a
2576 * request to pop up the icon box.
2578 IconBoxPopUp (pWS, True);
2585 if (pCD->clientState == MINIMIZED_STATE)
2587 /* normalize window */
2588 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2591 ? GetFunctionTimestamp ((XButtonEvent *)event)
2593 GetEventInverseMask(event));
2597 /* Make sure we are in NORMAL_STATE */
2598 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2599 GetFunctionTimestamp ((XButtonEvent *)event),
2600 GetEventInverseMask(event));
2602 /* Raise the window and set the keyboard focus to the window */
2603 wmGD.bSuspendSecondaryRestack = True;
2604 F_Raise (NULL, pCD, (XEvent *)NULL);
2605 wmGD.bSuspendSecondaryRestack = False;
2606 if (wmGD.raiseKeyFocus)
2608 F_Focus_Key (NULL, pCD,
2611 : ((XEvent *)NULL)));
2614 wmGD.clickData.clickPending = False;
2615 wmGD.clickData.doubleClickPending = False;
2620 } /* END OF FUNCTION F_Normalize_And_Raise */
2624 /*************************************<->*************************************
2626 * F_Restore (args, pCD, event)
2631 * This is the window manager function handler for putting a client window
2632 * in the normal state.
2634 *************************************<->***********************************/
2636 Boolean F_Restore (String args, ClientData *pCD, XEvent *event)
2643 * If current state is MAXIMIZED state then just go to NORMAL state,
2644 * otherwise (you are in MINIMIZED state) return to previous state.
2647 if (pCD->clientState == MAXIMIZED_STATE)
2649 SetClientStateWithEventMask (pCD, NORMAL_STATE,
2650 GetFunctionTimestamp ((XButtonEvent *)event),
2651 GetEventInverseMask(event));
2657 newState = MAXIMIZED_STATE;
2661 newState = NORMAL_STATE;
2664 SetClientStateWithEventMask (pCD, newState,
2665 GetFunctionTimestamp ((XButtonEvent *)event),
2666 GetEventInverseMask(event));
2672 } /* END OF FUNCTION F_Restore */
2676 /*************************************<->*************************************
2678 * F_Restore_And_Raise (args, pCD, event)
2683 * This is the window manager function handler for putting a client window
2684 * in the normal state and raising it from and icon.
2686 *************************************<->***********************************/
2688 Boolean F_Restore_And_Raise (String args, ClientData *pCD, XEvent *event)
2694 if (pCD->clientState == MINIMIZED_STATE)
2696 /* Restore window */
2699 newState = MAXIMIZED_STATE;
2703 newState = NORMAL_STATE;
2706 SetClientStateWithEventMask (pCD, newState,
2709 ? GetFunctionTimestamp ((XButtonEvent *)event)
2711 GetEventInverseMask(event));
2715 /* Make sure we restore the window first */
2716 F_Restore (NULL, pCD, event);
2718 /* Raise the window and set the keyboard focus to the window */
2719 wmGD.bSuspendSecondaryRestack = True;
2720 F_Raise (NULL, pCD, (XEvent *)NULL);
2721 wmGD.bSuspendSecondaryRestack = False;
2722 if (wmGD.raiseKeyFocus)
2724 F_Focus_Key (NULL, pCD,
2727 : ((XEvent *)NULL)));
2730 wmGD.clickData.clickPending = False;
2731 wmGD.clickData.doubleClickPending = False;
2736 } /* END OF FUNCTION F_Restore_And_Raise */
2740 /*************************************<->*************************************
2742 * F_Pack_Icons (args, pCD, event)
2747 * This is the window manager function handler for packing icons in the
2748 * icon box or on the desktop.
2750 *************************************<->***********************************/
2752 Boolean F_Pack_Icons (String args, ClientData *pCD, XEvent *event)
2757 if (ACTIVE_PSD->useIconBox)
2759 pIBD = ACTIVE_WS->pIconBox;
2762 while (pCD != pIBD->pCD_iconBox)
2764 if (pIBD->pNextIconBox)
2766 pIBD = pIBD->pNextIconBox;
2777 PackIconBox (pIBD, False, False, 0, 0);
2792 } /* END OF FUNCTION F_Pack_Icons */
2795 #if (defined(MWM_QATS_PROTOCOL))
2796 /*************************************<->*************************************
2798 * F_Post_RMenu (args, pCD, event)
2803 * This is the window manager function handler for posting the
2805 * This function can only be invoked by a key event.
2807 *************************************<->***********************************/
2809 Boolean F_Post_RMenu (String args, ClientData *pCD, XEvent *event)
2812 unsigned int button = NoButton;
2814 long flags = POST_AT_XY;
2820 if ((event->type == KeyPress) || (event->type == KeyRelease))
2823 /* Find the root menu spec */
2824 for (rootMenu = ACTIVE_PSD->menuSpecs;
2825 rootMenu != (MenuSpec *) NULL;
2826 rootMenu = rootMenu->nextMenuSpec)
2828 if (strcmp(rootMenu->name, ACTIVE_PSD->rootMenu) == 0)
2832 /* If we couldn't find the root menu, then do nothing. */
2833 if (rootMenu == (MenuSpec *) NULL)
2838 XQueryPointer(DISPLAY, ACTIVE_ROOT,
2839 &rwin, &cwin, &x, &y, &winx, &winy, &mask);
2841 PostMenu (rootMenu, NULL, x, y, NoButton, F_CONTEXT_ROOT,
2848 } /* END OF FUNCTION F_Post_RMenu */
2849 #endif /* defined(MWM_QATS_PROTOCOL) */
2852 /*************************************<->*************************************
2854 * F_Post_SMenu (args, pCD, event)
2859 * This is the window manager function handler for posting the system menu
2860 * for the specified client.
2861 * This function can only be invoked by a key or button event.
2862 * wmGD.menuUnpostKeySpec is assumed set appropriately; it will be set to
2863 * NULL when the menu is unposted.
2865 *************************************<->***********************************/
2867 Boolean F_Post_SMenu (String args, ClientData *pCD, XEvent *event)
2869 Context menuContext;
2873 * An event must be used to post the system menu using this function.
2876 if (event && pCD && pCD->systemMenuSpec)
2879 * Determine whether the keyboard is posting the menu and post
2880 * the menu at an appropriate place.
2883 if (pCD->clientState == NORMAL_STATE)
2885 menuContext = F_CONTEXT_NORMAL;
2887 else if (pCD->clientState == MAXIMIZED_STATE)
2889 menuContext = F_CONTEXT_MAXIMIZE;
2893 menuContext = F_CONTEXT_ICON;
2895 if (P_ICON_BOX(pCD) &&
2896 event->xany.window == ICON_FRAME_WIN(pCD))
2898 if (pCD->clientState == MINIMIZED_STATE)
2900 menuContext = F_SUBCONTEXT_IB_IICON;
2904 menuContext = F_SUBCONTEXT_IB_WICON;
2908 if ((event->type == KeyPress) || (event->type == KeyRelease))
2911 * Set up for "sticky" menu processing if specified.
2914 if (pCD->clientState == MINIMIZED_STATE ||
2915 menuContext == (F_SUBCONTEXT_IB_IICON | F_SUBCONTEXT_IB_WICON))
2919 wmGD.checkHotspot = True;
2922 else if (wmGD.systemButtonClick && (pCD->decor & MWM_DECOR_MENU))
2924 wmGD.checkHotspot = True;
2927 PostMenu (pCD->systemMenuSpec, pCD, 0, 0, NoButton, menuContext,
2930 else if (event->type == ButtonPress)
2933 * Root menu, if posted with button press, then
2934 * set up to handle root menu click to make the menu
2937 if (wmGD.rootButtonClick && (!wmGD.checkHotspot))
2939 wmGD.checkHotspot = True;
2940 wmGD.hotspotRectangle.x =
2941 event->xbutton.x_root - wmGD.moveThreshold/2;
2942 wmGD.hotspotRectangle.y =
2943 event->xbutton.y_root - wmGD.moveThreshold/2;
2944 wmGD.hotspotRectangle.width = wmGD.moveThreshold;
2945 wmGD.hotspotRectangle.height = wmGD.moveThreshold;
2947 PostMenu (pCD->systemMenuSpec, pCD,
2948 event->xbutton.x_root, event->xbutton.y_root,
2949 event->xbutton.button, menuContext, POST_AT_XY, event);
2951 else if (event->type == ButtonRelease)
2953 PostMenu (pCD->systemMenuSpec, pCD,
2954 event->xbutton.x_root, event->xbutton.y_root,
2955 event->xbutton.button, menuContext,
2956 POST_AT_XY | POST_TRAVERSAL_ON, event);
2962 } /* END OF FUNCTION F_PostSMenu */
2966 /*************************************<->*************************************
2968 * F_Kill (args, pCD, event)
2973 * This is the window manager function handler for terminating a client.
2974 * Essentially the client connection is shut down.
2976 *************************************<->***********************************/
2978 Boolean F_Kill (String args, ClientData *pCD, XEvent *event)
2980 if (pCD && (pCD->clientFunctions & MWM_FUNC_CLOSE))
2982 Boolean do_delete_window =
2983 pCD->protocolFlags & PROTOCOL_WM_DELETE_WINDOW;
2984 Boolean do_save_yourself =
2985 pCD->protocolFlags & PROTOCOL_WM_SAVE_YOURSELF;
2987 if (pCD->dtwmBehaviors & DtWM_BEHAVIOR_SUBPANEL)
2992 * Get the widget for the subpanel
2993 * (Should be only child of the shell!)
2995 wPanel = WmPanelistWindowToSubpanel (DISPLAY1, pCD->client);
2998 SlideSubpanelBackIn (pCD, wPanel);
3002 if (pCD->clientFlags & ICON_BOX)
3005 * When the front panel is used with the icon box,
3006 * "Close" hides the icon box into the front panel.
3008 if ((wmGD.useFrontPanel) &&
3009 (pCD->pSD->iconBoxControl) &&
3010 (IconBoxShowing(pCD->pSD->pActiveWS)))
3012 IconBoxPopUp (pCD->pSD->pActiveWS, False);
3015 else if (!do_delete_window && !do_save_yourself)
3017 XKillClient (DISPLAY, pCD->client);
3021 if (do_delete_window)
3024 * The client wants to be notified, not killed.
3027 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3028 (long) wmGD.xa_WM_DELETE_WINDOW, CurrentTime, NULL, 0);
3031 * HP does not want to send a client message for both
3032 * delete_window AND save_yourself. The current OSF
3033 * patch did just that. This "else if" returns dtwm
3034 * to the behavior of dt 2.01
3036 else if (do_save_yourself)
3039 * Send a WM_SAVE_YOURSELF message and wait for a change to
3040 * the WM_COMMAND property.
3041 * !!! button and key input should be kept from the window !!!
3044 if (AddWmTimer (TIMER_QUIT,
3045 (unsigned long) wmGD.quitTimeout, pCD))
3047 SendClientMsg (pCD->client, (long) wmGD.xa_WM_PROTOCOLS,
3048 (long) wmGD.xa_WM_SAVE_YOURSELF, CurrentTime, NULL, 0);
3050 pCD->clientFlags |= CLIENT_TERMINATING;
3054 XKillClient (DISPLAY, pCD->client);
3062 } /* END OF FUNCTION F_Kill */
3064 /*************************************<->*************************************
3066 * F_Marquee_Selection (args, pCD, event)
3071 * This is the window manager function handler for selecting
3072 * non-window manager objects on the root window.
3074 *************************************<->***********************************/
3076 Boolean F_Marquee_Selection (String args, ClientData *pCD, XEvent *event)
3081 * This function only valid in root context
3083 StartMarqueeSelect (ACTIVE_PSD, event);
3084 HandleMarqueeSelect (ACTIVE_PSD, event);
3089 } /* END OF FUNCTION F_Marquee_Selection */
3091 /*************************************<->*************************************
3093 * RefreshByClearing (win)
3098 * Recursively refresh this window and its children by doing
3101 *************************************<->***********************************/
3103 RefreshByClearing (Window win)
3107 Window root, parent;
3108 unsigned int nchildren;
3109 Window *winChildren;
3111 /* clear this window */
3112 XClearArea(DISPLAY, win, 0, 0, 0, 0, True);
3114 /* find any children and clear them, too */
3115 status = XQueryTree(DISPLAY, win, &root, &parent, &winChildren,
3119 /* recurse for each child window */
3120 for (i=0; i<nchildren; ++i)
3122 RefreshByClearing(winChildren[i]);
3127 XFree((char *)winChildren);
3132 /*************************************<->*************************************
3134 * F_Refresh (args, pCD, event)
3139 * This is the window manager function handler for causing all windows
3140 * in the workspace to be redrawn.
3142 *************************************<->***********************************/
3144 Boolean F_Refresh (String args, ClientData *pCD, XEvent *event)
3148 if (wmGD.refreshByClearing)
3150 RefreshByClearing (ACTIVE_ROOT);
3154 /* default background_pixmap is None */
3155 win = XCreateWindow (DISPLAY,
3157 (unsigned int) DisplayWidth (DISPLAY,
3159 (unsigned int) DisplayHeight (DISPLAY,
3166 (XSetWindowAttributes *)NULL);
3168 XMapWindow (DISPLAY, win);
3169 XDestroyWindow (DISPLAY, win);
3175 } /* END OF FUNCTION F_Refresh */
3179 /*************************************<->*************************************
3181 * F_Resize (args, pCD, event)
3186 * This is the window manager function handler for resizing a client window.
3188 *************************************<->***********************************/
3190 Boolean F_Resize (String args, ClientData *pCD, XEvent *event)
3192 if (pCD && (pCD->clientFunctions & MWM_FUNC_RESIZE) &&
3193 ((pCD->clientState == NORMAL_STATE) ||
3194 (pCD->clientState == MAXIMIZED_STATE)))
3196 StartClientResize (pCD, event);
3197 HandleClientFrameResize (pCD, event);
3202 } /* END OF FUNCTION F_Resize */
3206 /*************************************<->*************************************
3208 * F_Restart (args, pCD, event)
3213 * This is the window manager function handler for restarting the window
3216 *************************************<->***********************************/
3218 Boolean F_Restart (String args, ClientData *pCD, XEvent *event)
3220 if (args && *args && !strcmp (args, DTWM_REQP_NO_CONFIRM))
3222 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3224 else if (wmGD.showFeedback & WM_SHOW_FB_RESTART)
3226 ConfirmAction (ACTIVE_PSD, RESTART_ACTION);
3230 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3234 } /* END OF FUNCTION F_Restart */
3238 /*************************************<->*************************************
3240 * Do_Restart (dummy)
3245 * Callback function for restarting the window manager.
3247 *************************************<->***********************************/
3249 void Do_Restart (Boolean dummy)
3251 RestartWm (MWM_INFO_STARTUP_CUSTOM);
3253 } /* END OF FUNCTION Do_Restart */
3257 /*************************************<->*************************************
3259 * RestartWm (startupFlags)
3264 * Actually restarts the window manager.
3269 * startupFlags = flags to be put into the Wm_INFO property for restart.
3271 *************************************<->***********************************/
3273 void RestartWm (long startupFlags)
3275 ClientListEntry *pNextEntry;
3279 for (scr=0; scr<wmGD.numScreens; scr++)
3281 if(wmGD.Screens[scr].managed)
3285 * Set up the _MOTIF_WM_INFO property on the root window
3286 * to indicate a restart.
3289 SetMwmInfo (wmGD.Screens[scr].rootWindow, startupFlags, 0);
3290 SaveResources(&wmGD.Screens[scr]);
3292 * Unmap client windows and reparent them to the root window.
3295 pNextEntry = wmGD.Screens[scr].lastClient;
3298 if (pNextEntry->type == NORMAL_STATE)
3300 if (pNextEntry->pCD->clientFlags & CLIENT_WM_CLIENTS)
3302 if (pNextEntry->pCD->clientState != MINIMIZED_STATE)
3304 XUnmapWindow (DISPLAY,
3305 pNextEntry->pCD->clientFrameWin);
3310 DeFrameClient (pNextEntry->pCD);
3313 pNextEntry = pNextEntry->prevSibling;
3315 UnParentControls (&wmGD.Screens[scr], True);
3320 /* shut down the messaging connection */
3325 * This fixes restart problem when going from explicit focus to
3326 * pointer focus. Window under pointer was not getting focus indication
3327 * until pointer was moved to new window, or out of and into the
3331 XSetInputFocus (DISPLAY, PointerRoot, RevertToPointerRoot, CurrentTime);
3332 XSync (DISPLAY, False);
3334 CLOSE_FILES_ON_EXEC();
3335 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3337 * Restart the window manager with the initial arguments plus
3338 * the restart settings.
3341 execvp (*(wmGD.argv), wmGD.argv);
3343 Warning (((char *)GETMESSAGE(26, 1,
3344 "The window manager restart failed. The window manager program could not \
3345 be found or could not be executed.")));
3350 } /* END OF FUNCTION RestartWm */
3353 /*************************************<->*************************************
3355 * DeFrameClient (pCD)
3360 * Unmaps a client window (and client icon window) and reparents the
3361 * window back to the root.
3366 * pCD = pointer to the client data for the window to be de-framed.
3368 *************************************<->***********************************/
3370 void DeFrameClient (ClientData *pCD)
3374 XWindowChanges windowChanges;
3378 if (pCD->clientState != MINIMIZED_STATE)
3380 XUnmapWindow (DISPLAY, pCD->clientFrameWin);
3383 if (pCD->iconWindow && (pCD->clientFlags & ICON_REPARENTED))
3385 XUnmapWindow (DISPLAY, pCD->iconWindow);
3386 XRemoveFromSaveSet (DISPLAY, pCD->iconWindow);
3387 XReparentWindow (DISPLAY, pCD->iconWindow,
3388 ROOT_FOR_CLIENT(pCD), pCD->pWsList->iconX,
3389 pCD->pWsList->iconY);
3399 if(wmGD.positionIsFrame)
3401 CalculateGravityOffset (pCD, &xoff, &yoff);
3402 x = pCD->clientX - xoff;
3403 y = pCD->clientY - yoff;
3412 #ifndef UNMAP_ON_RESTART
3413 if (pCD->clientState == MINIMIZED_STATE)
3415 XUnmapWindow (DISPLAY, pCD->client);
3418 XUnmapWindow (DISPLAY, pCD->client);
3420 XRemoveFromSaveSet (DISPLAY, pCD->client);
3421 XReparentWindow (DISPLAY, pCD->client,
3422 ROOT_FOR_CLIENT(pCD), x, y);
3424 if (pCD->transientChildren)
3426 DeFrameClient (pCD->transientChildren);
3432 windowChanges.x = x;
3433 windowChanges.y = y;
3434 windowChanges.border_width = pCD->xBorderWidth;
3435 XConfigureWindow (DISPLAY, pCD->client, CWBorderWidth | CWX | CWY,
3438 if (pCD->transientLeader)
3440 pCD = pCD->transientSiblings;
3448 } /* END OF FUNCTION DeFrameClient */
3450 /******************************<->*************************************
3452 * F_Toggle_Front_Panel (args, pCD, event)
3457 * This is the window manager function handler for toggling the
3458 * front panel off and on.
3459 ******************************<->***********************************/
3462 F_Toggle_Front_Panel (String args, ClientData *pCD, XEvent *event)
3465 WmPanelistObject pPanelist;
3469 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3473 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3479 (void) XFindContext (DISPLAY, XtWindow(O_Shell(pPanelist)),
3480 wmGD.windowContextType, (caddr_t *)&pCD);
3486 if (pCD->clientState & MINIMIZED_STATE)
3488 SetClientState (pCD, NORMAL_STATE,
3489 GetFunctionTimestamp ((XButtonEvent *)event));
3493 SetClientState (pCD, MINIMIZED_STATE,
3494 GetFunctionTimestamp ((XButtonEvent *)event));
3499 } /* END OF FUNCTION F_Toggle_Front_Panel */
3502 /******************************<->*************************************
3504 * Boolean F_Version (String args, ClientData *pCD, XEvent *event)
3508 * Invoke the help on version dialogue.
3512 * args - incoming values
3513 * pCD - associated client data structure
3514 * event - what triggered this call
3518 * Return - True if the call occurs; false otherwise.
3523 ******************************<->***********************************/
3525 F_Version (String args, ClientData *pCD, XEvent *event)
3528 WmPanelistObject pPanelist;
3532 pPanelist = (WmPanelistObject) pCD->pSD->wPanelist;
3536 pPanelist = (WmPanelistObject) ACTIVE_PSD->wPanelist;
3541 WmDtHelpOnVersion (O_Shell (pPanelist));
3546 } /* END OF FUNCTION F_Version */
3549 /******************************<->*************************************
3551 * F_Send_Msg (args, pCD, event)
3556 * This is the window manager function handler for sending a client
3557 * message event to a client window.
3562 * args = (immediate value) message id
3564 * pCD = pointer to the client data
3566 * event = X event that invoked the function (key, button, or menu/NULL)
3569 ******************************<->***********************************/
3571 Boolean F_Send_Msg (String args, ClientData *pCD, XEvent *event)
3576 if (pCD && pCD->mwmMessagesCount)
3579 * A message id must be made "active" by being included in the
3580 * _MWM_MESSAGES property before the associated message can be sent.
3583 for (i = 0; i < pCD->mwmMessagesCount; i++)
3585 if (pCD->mwmMessages[i] == (long)args)
3587 SendClientMsg (pCD->client, (long) wmGD.xa_MWM_MESSAGES,
3588 (long)args, CurrentTime, NULL, 0);
3596 } /* END OF FUNCTION F_Send_Msg */
3600 /*************************************<->*************************************
3602 * F_Separator (args, pCD, event)
3607 * This is a placeholder function; it should never be called.
3609 *************************************<->***********************************/
3611 Boolean F_Separator (String args, ClientData *pCD, XEvent *event)
3616 } /* END OF FUNCTION F_Separator */
3619 Boolean ForceRaiseWindow (ClientData *pcd)
3623 WmScreenData *pSD = (ACTIVE_WS)->pSD;
3625 XWindowChanges changes;
3626 Boolean restack = False;
3629 if (pSD->clientList->type == MINIMIZED_STATE)
3631 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
3635 stackWindow = pSD->clientList->pCD->clientFrameWin;
3640 * Windows did not raise on regular f.raise because the raise was
3641 * not relative to another window (methinks).
3643 changes.stack_mode = Above;
3644 XConfigureWindow (DISPLAY, pcd->clientFrameWin, CWStackMode,
3652 /*************************************<->*************************************
3654 * F_Raise (args, pCD, event)
3659 * This is the window manager function handler for topping the client window
3660 * so that it is unobscured.
3662 *************************************<->***********************************/
3664 Boolean F_Raise (String args, ClientData *pCD, XEvent *event)
3666 ClientListEntry *pEntry;
3667 ClientListEntry *pNextEntry;
3668 ClientListEntry *pStackEntry;
3669 String string = args;
3670 int flags = STACK_NORMAL;
3671 WmWorkspaceData *pWS = ACTIVE_WS;
3675 /* process '-client' argument */
3676 if (string[0] == '-')
3678 string = &string[1];
3679 string = (String) GetString ((unsigned char **) &string);
3682 pNextEntry = ACTIVE_PSD->clientList;
3683 while (pNextEntry &&
3684 (pEntry = FindClientNameMatch (pNextEntry, True, string,
3687 pNextEntry = pEntry->nextSibling;
3688 if (ClientInWorkspace (pWS, pEntry->pCD))
3690 Do_Raise (pEntry->pCD, pStackEntry, STACK_NORMAL);
3691 pStackEntry = pEntry;
3695 /* process family stacking stuff */
3698 unsigned int slen, len, index;
3700 slen = strlen(args) - 2; /* subtract '\n' and NULL */
3701 for (index = 0; index < slen; string = &args[index+1])
3703 if ((string = (String) GetString ((unsigned char **) &string)) == NULL)
3705 len = strlen(string);
3706 if (!strcmp(string,"within"))
3708 flags |= STACK_WITHIN_FAMILY;
3710 else if (!strcmp(string,"freeFamily"))
3712 flags |= STACK_FREE_FAMILY;
3716 if (ClientInWorkspace (pWS, pCD))
3718 Do_Raise (pCD, (ClientListEntry *) NULL, flags);
3724 if (ClientInWorkspace (pWS, pCD))
3726 Do_Raise (pCD, (ClientListEntry *) NULL, STACK_NORMAL);
3732 } /* END OF FUNCTION F_Raise */
3736 /*************************************<->*************************************
3738 * Do_Raise (pCD, pStackEntry)
3743 * This is the window manager function handler for topping the client window
3744 * so that it is unobscured.
3749 * pCD = pointer to the client data of the window (or icon) to be raised.
3751 * pStackEntry = pointer to client list entry for window that is to be
3752 * above the raised window (if NULL window is raised to the top of the
3755 *************************************<->***********************************/
3757 void Do_Raise (ClientData *pCD, ClientListEntry *pStackEntry, int flags)
3759 Boolean restackTransients;
3760 ClientData *pcdLeader;
3761 WmWorkspaceData *pWS = ACTIVE_WS;
3762 Boolean bLeaderRestacked;
3767 * Window has been reparented into the front panel.
3768 * Don't follow through on window stacking change.
3772 else if (ClientInWorkspace(pWS, pCD) &&
3773 (!pStackEntry || ClientInWorkspace (pWS, pStackEntry->pCD)))
3776 * Both clients are in the current workspace. Set
3777 * client indices so that the access macros work.
3779 SetClientWsIndex (pCD);
3782 SetClientWsIndex (pStackEntry->pCD);
3788 * One or both of the clients are not in the current workspace
3794 pcdLeader = (pCD->transientLeader) ? FindTransientTreeLeader (pCD) : pCD;
3796 if (wmGD.systemModalActive && (pcdLeader != wmGD.systemModalClient))
3799 * Don't raise the window above the system modal window.
3802 else if ((pcdLeader->clientState == MINIMIZED_STATE) &&
3803 !P_ICON_BOX(pcdLeader))
3806 * If a dirtyStackEntry exists, return it to its original place
3807 * in the stack (for all stacking types)
3809 if (dirtyStackEntry)
3811 if (dirtyStackEntry->transientChildren ||
3812 dirtyStackEntry->transientLeader)
3813 RestackTransients (dirtyStackEntry);
3814 dirtyStackEntry = NULL;
3819 * Only restack the icon if it is not currently raised.
3824 if (pStackEntry->nextSibling != &pcdLeader->iconEntry)
3826 StackWindow (pWS, &pcdLeader->iconEntry, False /*below*/,
3828 MoveEntryInList (pWS, &pcdLeader->iconEntry, False /*below*/,
3834 if (ACTIVE_PSD->clientList != &pcdLeader->iconEntry)
3836 StackWindow (pWS, &pcdLeader->iconEntry,
3837 True /*on top*/, (ClientListEntry *) NULL);
3838 MoveEntryInList (pWS, &pcdLeader->iconEntry,
3839 True /*on top*/, (ClientListEntry *) NULL);
3843 else /* NORMAL_STATE, MAXIMIZED_STATE, adoption */
3846 * Handle restacking of primary/secondary windows
3847 * within the transient window tree. Don't raise this
3848 * window above any modal transients.
3850 bLeaderRestacked = False;
3851 if ((pcdLeader->transientChildren) &&
3852 (!pCD->secondariesOnTop) &&
3853 (!wmGD.bSuspendSecondaryRestack) &&
3854 (!IS_APP_MODALIZED(pCD)))
3856 if (pCD != pcdLeader)
3859 * This is not the transient leader, make sure
3860 * the transient leader isn't on top.
3861 * (Brute force solution)
3863 bLeaderRestacked = NormalizeTransientTreeStacking (pcdLeader);
3865 if (pCD->transientChildren)
3868 * This isn't the overall leader of the transient
3869 * tree, but it does have transient's of its own.
3870 * Move it to the top of its own transient sub-tree.
3872 bLeaderRestacked |= BumpPrimaryToTop (pCD);
3878 * This is the transient leader, move it to the
3881 bLeaderRestacked = BumpPrimaryToTop (pcdLeader);
3887 * If this is a transient window then put it on top of its
3888 * sibling transient windows.
3891 restackTransients = False;
3895 * Fix for 5325 - The following code has been reorganized to cause the
3896 * action of F_Raise to match the current documentation.
3897 * The new algorithm is as follows:
3899 * if (dirtyStackEntry)
3900 * restore dirty tree
3901 * if (not withinFamily)
3902 * bring window group to the top of global stack
3904 * raise the requested window to top of family
3906 * raise requested window to top of siblings
3907 * if (need to restack windows)
3912 * If a dirtyStackEntry exists, return it to its original place
3913 * in the stack (for all stacking types)
3915 if (dirtyStackEntry)
3918 * Check to make sure that the dirty pCD has either transient
3919 * children or a transient leader. If not, do not restore
3922 if (dirtyStackEntry->transientChildren ||
3923 dirtyStackEntry->transientLeader)
3924 RestackTransients (dirtyStackEntry);
3925 dirtyStackEntry = NULL;
3930 * If the flags do not indicate "within", raise the window family
3931 * to the top of the window stack. If the window is the primary,
3932 * raise it to the top regardless of the flags.
3934 if (!pCD->transientLeader || !(flags & STACK_WITHIN_FAMILY))
3938 if (pStackEntry->nextSibling != &pcdLeader->clientEntry)
3940 StackWindow (pWS, &pcdLeader->clientEntry,
3941 False /*below*/, pStackEntry);
3942 MoveEntryInList (pWS, &pcdLeader->clientEntry,
3943 False /*below*/, pStackEntry);
3948 if (ACTIVE_PSD->clientList != &pcdLeader->clientEntry)
3950 StackWindow (pWS, &pcdLeader->clientEntry,
3951 True /*on top*/, (ClientListEntry *) NULL);
3952 MoveEntryInList (pWS, &pcdLeader->clientEntry,
3953 True /*on top*/, (ClientListEntry *) NULL);
3959 * If freeFamily stacking is requested, check to make sure that
3960 * the window has either a transientChild or Leader. This will
3961 * guarantee that windows that form their own family are not
3962 * labelled as dirty (what's to dirty it up?). If it has either,
3963 * raise the window to the top of the family stack.
3965 if ((flags & STACK_FREE_FAMILY) &&
3966 (pCD->transientLeader || pCD->transientChildren))
3968 dirtyStackEntry = pCD;
3969 dirtyLeader = pcdLeader;
3971 restackTransients = ForceRaiseWindow (pCD);
3975 * If withinFamily stacking is requested, put the current transient
3976 * on top of its sibling transient windows.
3980 restackTransients = PutTransientOnTop (pCD);
3983 /* At this point, if doing a regular f.raise the window family has
3984 * already been brought to the top of the stack, so nothing further
3985 * needs to be done for it.
3988 /* Restack the transients if needed */
3990 if ((restackTransients) || (bLeaderRestacked))
3992 RestackTransients (pCD);
3996 } /* END OF FUNCTION Do_Raise */
4000 /*************************************<->*************************************
4002 * F_Raise_Lower (args, pCD, event)
4007 * This window manager function tops an obscured window or icon and bottoms
4008 * a window or icon that is on top of the window stack.
4010 *************************************<->***********************************/
4012 Boolean F_Raise_Lower (String args, ClientData *pCD, XEvent *event)
4014 ClientData *pcdLeader;
4018 pcdLeader = (pCD->transientLeader) ?
4019 FindTransientTreeLeader (pCD) : pCD;
4022 * Treat a raise/lower on a window in a transient tree as if it is
4023 * a raise/lower for the whole tree.
4026 if (CheckIfClientObscuredByAny (pcdLeader))
4029 * The window is obscured by another window, raise the window.
4032 F_Raise (NULL, pCD, (XEvent *)NULL);
4034 else if (CheckIfClientObscuringAny (pcdLeader) &&
4035 !(wmGD.systemModalActive &&
4036 (pcdLeader == wmGD.systemModalClient)))
4039 * The window is obscuring another window and is
4040 * not system modal, lower the window.
4043 F_Lower (NULL, pcdLeader, (XEvent *)NULL);
4044 if ((pcdLeader->secondariesOnTop == False) &&
4045 (pCD->transientLeader != NULL) &&
4046 (!IS_APP_MODALIZED(pcdLeader)))
4048 /* Push transient below primary */
4049 (void) BumpPrimaryToTop (pcdLeader);
4050 RestackTransients (pcdLeader);
4053 else if ((pcdLeader->secondariesOnTop == False) &&
4054 (pcdLeader->transientChildren != NULL) &&
4055 (!wmGD.systemModalActive) &&
4056 (!IS_APP_MODALIZED(pcdLeader)))
4058 if (LeaderOnTop(pcdLeader))
4060 /* Push primary below transient */
4061 (void) BumpPrimaryToBottom (pcdLeader);
4062 RestackTransients (pcdLeader);
4066 F_Raise (NULL, pCD, (XEvent *)NULL);
4067 /* Push transient below primary */
4068 (void) BumpPrimaryToTop (pcdLeader);
4069 RestackTransients (pcdLeader);
4076 } /* END OF FUNCTION F_Raise_Lower */
4080 /*************************************<->*************************************
4082 * F_Refresh_Win (args, pCD, event)
4087 * This is the window manager function handler for causing a client window
4088 * to redisplay itself.
4090 *************************************<->***********************************/
4092 Boolean F_Refresh_Win (String args, ClientData *pCD, XEvent *event)
4097 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
4098 (pCD->clientState == MAXIMIZED_STATE)))
4100 if (pCD->clientState == NORMAL_STATE)
4102 w = (unsigned int) pCD->clientWidth;
4103 h = (unsigned int) pCD->clientHeight;
4107 w = (unsigned int) pCD->maxWidth;
4108 h = (unsigned int) pCD->maxHeight;
4111 if (wmGD.refreshByClearing)
4113 RefreshByClearing (pCD->clientFrameWin);
4117 /* default background_pixmap is None */
4118 win = XCreateWindow (DISPLAY,
4128 (XSetWindowAttributes *)NULL);
4130 XMapWindow (DISPLAY, win);
4131 XDestroyWindow (DISPLAY, win);
4138 } /* END OF FUNCTION F_Refresh_Win */
4142 /*************************************<->*************************************
4144 * F_Set_Behavior (args, pCD, event)
4149 * This function is used to switch the window manager configuration between
4150 * the built-in configuration (for CXI behavior) and the user's custom
4153 *************************************<->***********************************/
4155 Boolean F_Set_Behavior (String args, ClientData *pCD, XEvent *event)
4158 * Go system modal in starting to do the set behavior.
4161 /* !!! grab the server and the pointer !!! */
4165 * Confirm that a set_behavior should be done.
4166 * Execute restart if so.
4169 if (wmGD.showFeedback & WM_SHOW_FB_BEHAVIOR)
4171 ConfirmAction (ACTIVE_PSD, (wmGD.useStandardBehavior) ?
4172 CUSTOM_BEHAVIOR_ACTION : DEFAULT_BEHAVIOR_ACTION);
4176 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4177 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4181 } /* END OF FUNCTION F_Set_Behavior */
4185 /*************************************<->*************************************
4187 * Do_Set_Behavior (dummy)
4192 * Callback to do the f.set_behavior function.
4194 *************************************<->***********************************/
4196 void Do_Set_Behavior (Boolean dummy)
4198 RestartWm ((long) ((wmGD.useStandardBehavior) ?
4199 MWM_INFO_STARTUP_CUSTOM : MWM_INFO_STARTUP_STANDARD));
4201 } /* END OF FUNCTION Do_Set_Behavior */
4203 /*************************************<->*************************************
4205 * F_Set_Context (args, pCD, event)
4210 * This function is used to set a client context for subsequent
4213 *************************************<->***********************************/
4215 Boolean F_Set_Context (String args, ClientData *pCD, XEvent *event)
4218 wmGD.requestContextWin = (Window) args;
4221 } /* END OF FUNCTION F_Set_Context */
4224 /*************************************<->*************************************
4226 * F_Title (args, pCD, event)
4231 * This is a placeholder function; it should never be called.
4233 *************************************<->***********************************/
4235 Boolean F_Title (String args, ClientData *pCD, XEvent *event)
4240 } /* END OF FUNCTION F_Title */
4244 /******************************<->*************************************
4246 * F_Screen (args, pCD, event)
4251 * This is the window manager function handler for warping to screens
4256 * args = (immediate value) window type flags
4258 * pCD = pointer to the client data
4260 * event = X event that invoked the function (key, button, or menu/NULL)
4262 * NOTE: May want to consider tracking changes in screen because in
4263 * managing a new window (ie. in ManageWindow()).
4267 * RETURN = if True then further button binding/function processing can
4268 * be done for the event that caused this function to be called.
4270 *************************************<->***********************************/
4272 Boolean F_Screen (String args, ClientData *pCD, XEvent *event)
4276 unsigned int dummask;
4277 WmScreenData *newscr = NULL;
4279 static int PreviousScreen = -1;
4283 if (PreviousScreen == -1)
4285 PreviousScreen = DefaultScreen(DISPLAY);
4288 if (strcmp (args, "next") == 0)
4290 scr = ACTIVE_PSD->screen + 1;
4293 else if (strcmp (args, "prev") == 0)
4295 scr = ACTIVE_PSD->screen - 1;
4298 else if (strcmp (args, "back") == 0)
4300 scr = PreviousScreen;
4312 scr = wmGD.numScreens - 1;
4313 else if (scr >= wmGD.numScreens)
4316 newscr = &(wmGD.Screens[scr]);
4317 if (!wmGD.Screens[scr].managed) { /* make sure screen is managed */
4318 if (inc) { /* walk around the list */
4323 "Unable to warp to unmanaged screen %d\n", scr);
4330 if (ACTIVE_PSD->screen == scr) return (False); /* already on that screen */
4332 PreviousScreen = ACTIVE_PSD->screen;
4333 XQueryPointer (DISPLAY, ACTIVE_ROOT, &dumwin, &dumwin, &x, &y,
4334 &dumint, &dumint, &dummask);
4336 XWarpPointer (DISPLAY, None, newscr->rootWindow, 0, 0, 0, 0, x, y);
4338 if (newscr && (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT))
4341 * Set the ACTIVE_PSD to the new screen so that Do_Focus_Key can
4342 * uses the new screen instead of the old screen. Then call
4343 * Do_Focus_Key with a NULL pCD to find a reasonable client to
4346 SetActiveScreen (newscr);
4347 Do_Focus_Key (NULL, GetFunctionTimestamp ((XButtonEvent *)event),
4356 #if (defined(MWM_QATS_PROTOCOL))
4357 /*************************************<->*************************************
4359 * F_InvokeCommand (args, pCD, event)
4364 * This is the window manager function for invoking client inserted menu
4367 *************************************<->***********************************/
4369 Boolean F_InvokeCommand (String args, ClientData *pCD, XEvent *event)
4371 CARD32 commandID, clientWindow;
4372 Atom notifySelection;
4374 if (args == (String) NULL) return(FALSE);
4376 if (sscanf(args, "%d %d %ld", &commandID, &clientWindow,
4377 ¬ifySelection) != 3)
4380 SendInvokeMessage(commandID,
4381 (pCD == (ClientData *) NULL ? 0 : pCD->client),
4386 } /* END OF FUNCTION F_InvokeCommand */
4387 #endif /* defined(MWM_QATS_PROTOCOL) */
4390 /*************************************<->*************************************
4392 * GetFunctionTimestamp (pEvent)
4397 * This function is used to extract a timestamp from a key or button event.
4398 * If the event passed in is not a key or button event then a timestamp
4404 * event = pointer to an X event
4409 * RETURN = a timestamp
4411 *************************************<->***********************************/
4413 Time GetFunctionTimestamp (XButtonEvent *pEvent)
4418 (((pEvent->type == ButtonPress) || (pEvent->type == ButtonRelease)) ||
4419 ((pEvent->type == KeyPress) || (pEvent->type == KeyRelease))))
4421 time = pEvent->time;
4425 time = GetTimestamp ();
4430 } /* END OF FUNCTION GetFunctionTimestamp */
4434 ** name the event mask we need for a grab in order to find the matching
4435 ** event for an event; right now handle only button-presses
4437 static unsigned int GetEventInverseMask(XEvent *event)
4439 if ((XEvent*)NULL == event)
4441 if (ButtonPress == event->type)
4442 return ButtonReleaseMask; /* detail ? */
4444 expansion further here
4452 /*************************************<->*************************************
4454 * ClearDirtyStackEntry (pCD)
4459 * This function is used to clear the static dirtyStackEntry structure and
4460 * the dirtyLeader static variable when a pCD is destroyed. This
4461 * guarantees that freed memory will not be accessed.
4466 * pCD = pointer to clientData being freed
4473 *************************************<->***********************************/
4475 void ClearDirtyStackEntry (ClientData *pCD)
4477 if (pCD == dirtyStackEntry)
4479 dirtyStackEntry = NULL;
4485 /***********************<->*************************************
4487 * F_ZZ_Debug (args, pCD, event)
4492 * This is the window manager debug (multi) function
4499 * pCD = pointer to the ClientData for the whole front panel
4501 * event = X event that invoked the function (key, button, or menu/NULL)
4506 * RETURN = if True then further button binding/function processing can
4507 * be done for the event that caused this function to be called.
4511 * Argument 1 determines the debug function to execute:
4515 * "color_server_info" - dump out color server info
4517 ******************************<->***********************************/
4520 F_ZZ_Debug (String subFcn, ClientData *pCD, XEvent *event)
4522 /* Only do something is sub function is specified */
4526 if (!(strcmp(subFcn, "dump_resources")))
4531 for (scr=0; scr<wmGD.numScreens; scr++)
4533 sprintf (szRes, "/tmp/dtwm.resources.%d", scr);
4535 XrmPutFileDatabase(XtScreenDatabase(
4536 XScreenOfDisplay(DISPLAY, scr)),
4545 /*************************************<->*************************************
4547 * F_Next_Workspace (args, pCD, event)
4552 * This function switches to the next workspace in the list
4554 *************************************<->***********************************/
4556 Boolean F_Next_Workspace (String args, ClientData *pCD, XEvent *event)
4558 WmScreenData *pSD = ACTIVE_PSD;
4561 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4563 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4570 /* check bounds and wrap */
4571 if (iwsx >= pSD->numWorkspaces)
4574 ChangeToWorkspace (&pSD->pWS[iwsx]);
4579 } /* END OF FUNCTION F_Next_Workspace */
4582 /*************************************<->*************************************
4584 * F_Prev_Workspace (args, pCD, event)
4589 * This function switches to the previous workspace in the list
4591 *************************************<->***********************************/
4593 Boolean F_Prev_Workspace (String args, ClientData *pCD, XEvent *event)
4595 WmScreenData *pSD = ACTIVE_PSD;
4598 for (iwsx = 0; iwsx < pSD->numWorkspaces; iwsx++)
4600 if (pSD->pWS[iwsx].id == pSD->pActiveWS->id)
4607 /* check bounds and wrap */
4609 iwsx = pSD->numWorkspaces - 1;
4611 ChangeToWorkspace (&pSD->pWS[iwsx]);
4616 } /* END OF FUNCTION F_Prev_Workspace */
4620 /*************************************<->*************************************
4622 * F_Workspace_Presence (args, pCD, event)
4627 * This function pops up the workspace presence dialog box
4629 *************************************<->***********************************/
4631 Boolean F_Workspace_Presence (String args, ClientData *pCD, XEvent *event)
4633 Context wsContext = (Context)NULL;
4635 if (pCD && (pCD->dtwmFunctions & DtWM_FUNCTION_OCCUPY_WS))
4637 if (pCD->clientState == NORMAL_STATE)
4639 wsContext = F_CONTEXT_NORMAL;
4641 else if (pCD->clientState == MAXIMIZED_STATE)
4643 wsContext = F_CONTEXT_MAXIMIZE;
4647 wsContext = F_CONTEXT_ICON;
4648 /* return (False); */
4650 ShowPresenceBox (pCD, wsContext);
4654 } /* END OF FUNCTION F_Workspace_Presence */
4660 WmScreenData *pSD = (ACTIVE_WS)->pSD;
4661 ClientListEntry *pCLE;
4663 fprintf (stdout, "Window stacking (bottom to top)\n");
4664 pCLE = pSD->lastClient;
4667 if (ClientInWorkspace (ACTIVE_WS, pCLE->pCD))
4668 fprintf (stdout, "* ");
4670 fprintf (stdout, " ");
4672 fprintf (stdout, "%08lx\t%s\n",
4674 pCLE->pCD->clientName);
4676 pCLE = pCLE->prevSibling;