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 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.
43 #define MWM_NEED_NOENTER16
48 * include extern functions
50 #include "WmWinList.h"
53 #include "WmFunction.h"
54 #include "WmKeyFocus.h"
56 #include "WmResource.h"
57 #include "WmWinInfo.h"
59 #include "WmWrkspace.h"
70 /*************************************<->*************************************
72 * AddClientToList (pWS, pCD, onTop)
77 * This function adds a client window to the client window list. If it is
78 * a transient window then it is added to the transient window tree that
79 * contains its transient leader. The window stacking order is also
80 * maintained for the cases where there is a system modal window active
81 * or the window is a transient window. If a system modal window is being
82 * added then the system modal "input screen" window is setup.
87 * pCD = pointer to client data for the window to be added to the list
89 * pWS = pointer to workspace data
91 * onTop = if True then the window is displayed on top of the window
92 * stack and is added to the beginning of the window list, otherwise
93 * it is added to the end of the window list.
98 * pWS = (clientList, lastClient)
100 *************************************<->***********************************/
102 void AddClientToList (WmWorkspaceData *pWS, ClientData *pCD, Boolean onTop)
104 Boolean belowSystemModal = False;
105 XWindowChanges windowChanges;
106 WmScreenData *pSD = pWS->pSD;
108 WsClientData *pWsc = GetWsClientData (pWS, pCD);
112 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
115 * Set up the system modal input screen window just below the
116 * system modal window.
119 SetupSystemModalState (pCD);
121 if (!wmGD.systemModalActive || (wmGD.systemModalClient != pCD))
124 * If we failed to setup as system modal, then
125 * back off to MWM_INPUT_FULL_APPLICATION_MODAL.
126 * This will do *something* if this is a transient
129 pCD->inputMode = MWM_INPUT_FULL_APPLICATION_MODAL;
132 else if (wmGD.systemModalActive &&
133 ((FindTransientTreeLeader (pCD))->inputMode !=
134 MWM_INPUT_SYSTEM_MODAL))
137 * If a system modal window is active then place the window below
138 * the system modal input screen window if the window is not a
139 * descendant of the system modal window.
142 windowChanges.sibling = pSD->inputScreenWindow;
143 windowChanges.stack_mode = Below;
144 XConfigureWindow (DISPLAY, pCD->clientFrameWin,
145 CWSibling | CWStackMode, &windowChanges);
146 belowSystemModal = True;
149 if (pCD->transientLeader)
151 AddTransient (pWS, pCD);
155 pCD->clientEntry.type = NORMAL_STATE;
156 pCD->clientEntry.pCD = pCD;
158 if (belowSystemModal && wmGD.systemModalClient)
160 AddEntryToList (pWS, &pCD->clientEntry, False /*below*/,
165 AddEntryToList (pWS, &pCD->clientEntry, True /*on top*/, NULL);
169 AddEntryToList (pWS, &pCD->clientEntry, False /*on bottom*/, NULL);
174 if (!pWsc->pIconBox && pWsc->iconFrameWin)
176 if (!pCD->pIconBox && pCD->iconFrameWin)
180 * Put the icon on the bottom of the stack.
183 if (pSD->lastClient->type == MINIMIZED_STATE)
188 pWsib = &pSD->lastClient->pCD->pWsList[0];
189 windowChanges.sibling = pWsib->iconFrameWin;
191 windowChanges.sibling = pSD->lastClient->pCD->iconFrameWin;
196 windowChanges.sibling = pSD->lastClient->pCD->clientFrameWin;
198 windowChanges.stack_mode = Below;
200 XConfigureWindow (DISPLAY, pWsc->iconFrameWin,
201 CWSibling | CWStackMode, &windowChanges);
203 XConfigureWindow (DISPLAY, pCD->iconFrameWin,
204 CWSibling | CWStackMode, &windowChanges);
207 pCD->iconEntry.type = MINIMIZED_STATE;
208 pCD->iconEntry.pCD = pCD;
209 pCD->iconEntry.nextSibling = NULL;
210 pCD->iconEntry.prevSibling = pSD->lastClient;
211 pSD->lastClient->nextSibling = &pCD->iconEntry;
212 pSD->lastClient = &pCD->iconEntry;
216 } /* END OF FUNCTION AddClientToList */
220 /*************************************<->*************************************
222 * AddEntryToList (pWS, pEntry, onTop, pStackEntry)
227 * This function adds a client list entry to the client window list.
228 * This is usually done as part of the process of changing the ordering
229 * of the window list.
234 * pWS = pointer to workspace data
235 * pEntry = pointer to a client list entry to be added to the client list
237 * onTop = if True then the client list entry is added on top of the
238 * specified client list stack entry (if the stack entry is not
239 * specified then the entry is added to the front of the list);
240 * otherwise the entry is added after the specified stacking entry
241 * (or to the end of the list if the stacking entry is not specified).
243 * pStackEntry = pointer to a client list entry to be used as a reference
244 * in adding an entry to the client list.
248 * pWS = (clientList, lastClient)
250 *************************************<->***********************************/
252 void AddEntryToList (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
254 WmScreenData *pSD = pWS->pSD;
260 if (pEntry != pStackEntry)
262 pEntry->nextSibling = pStackEntry;
263 pEntry->prevSibling = pStackEntry->prevSibling;
264 pStackEntry->prevSibling = pEntry;
265 if (pEntry->prevSibling)
267 pEntry->prevSibling->nextSibling = pEntry;
271 pSD->clientList = pEntry;
277 if (pSD->clientList != pEntry)
279 pEntry->nextSibling = pSD->clientList;
280 pEntry->prevSibling = NULL;
283 pSD->clientList->prevSibling = pEntry;
287 pSD->lastClient = pEntry;
289 pSD->clientList = pEntry;
297 if (pEntry != pStackEntry)
299 pEntry->nextSibling = pStackEntry->nextSibling;
300 pEntry->prevSibling = pStackEntry;
301 pStackEntry->nextSibling = pEntry;
302 if (pEntry->nextSibling)
304 pEntry->nextSibling->prevSibling = pEntry;
308 pSD->lastClient = pEntry;
314 if (pSD->lastClient != pEntry)
316 pEntry->nextSibling = NULL;
317 pEntry->prevSibling = pSD->lastClient;
320 pSD->lastClient->nextSibling = pEntry;
324 pSD->clientList = pEntry;
326 pSD->lastClient = pEntry;
331 } /* END OF FUNCTION AddEntryToList */
335 /*************************************<->*************************************
337 * MoveEntryInList (pWS, pEntry, onTop, pStackEntry)
342 * This function moves a client list entry in the client window list.
347 * pWS = pointer to workspace data
349 * pEntry = pointer to a client list entry to be moved in the client list
351 * onTop = if True then the client list entry is moved on top of the
352 * specified client list stack entry (if the stack entry is not
353 * specified then the entry is moved to the front of the list);
354 * otherwise the entry is moved after the specified stacking entry
355 * (or to the end of the list if the stacking entry is not specified).
357 * pStackEntry = pointer to a client list entry to be used as a reference
358 * in moving an entry in the client list.
362 * pWS = (clientList, lastClient)
364 *************************************<->***********************************/
366 void MoveEntryInList (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
368 DeleteEntryFromList (pWS, pEntry);
369 AddEntryToList (pWS, pEntry, onTop, pStackEntry);
371 } /* END OF FUNCTION MoveEntryInList */
375 /*************************************<->*************************************
377 * DeleteEntryFromList (pWS, pListEntry)
382 * This function deletes a client list entry from the client window list.
383 * This is usually done as part of the process of changing the ordering
384 * of the window list.
389 * pWS = pointer to workspace data
390 * listEntry = pointer to a client list entry
394 * pWS = (clientList, lastClient)
396 *************************************<->***********************************/
398 void DeleteEntryFromList (WmWorkspaceData *pWS, ClientListEntry *pListEntry)
401 if (pListEntry->prevSibling)
403 pListEntry->prevSibling->nextSibling = pListEntry->nextSibling;
407 pWS->pSD->clientList = pListEntry->nextSibling;
410 if (pListEntry->nextSibling)
412 pListEntry->nextSibling->prevSibling = pListEntry->prevSibling;
416 pWS->pSD->lastClient = pListEntry->prevSibling;
419 } /* END OF FUNCTION DeleteEntryFromList */
423 /*************************************<->*************************************
425 * DeleteClientFromList (pWS, pCD)
430 * This function deletes a client from the client window list. If this is
431 * a transient window then it is deleted from its transient window tree.
432 * If this is a system modal window then clean up the system modal state.
437 * pCD = pointer to client data for the window to be added to the list
441 * pWS = (clientList, lastClient)
443 *************************************<->***********************************/
445 void DeleteClientFromList (WmWorkspaceData *pWS, ClientData *pCD)
448 WsClientData *pWsc = GetWsClientData (pWS, pCD);
450 WmScreenData *pSD = pWS->pSD;
452 if (pCD->transientLeader)
454 DeleteTransient (pCD);
459 * If this is a system modal window then clean up the system modal
463 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
465 UndoSystemModalState ();
469 * Remove the client and icon entries from the window list.
473 if (!pWsc->pIconBox && pWsc->iconFrameWin)
475 if (!pCD->pIconBox && pCD->iconFrameWin)
478 if (pCD->iconEntry.prevSibling)
480 pCD->iconEntry.prevSibling->nextSibling =
481 pCD->iconEntry.nextSibling;
485 pSD->clientList = pCD->iconEntry.nextSibling;
487 if (pCD->iconEntry.nextSibling)
489 pCD->iconEntry.nextSibling->prevSibling =
490 pCD->iconEntry.prevSibling;
494 pSD->lastClient = pCD->iconEntry.prevSibling;
498 if (pCD->clientEntry.prevSibling)
500 pCD->clientEntry.prevSibling->nextSibling =
501 pCD->clientEntry.nextSibling;
505 pSD->clientList = pCD->clientEntry.nextSibling;
508 if (pCD->clientEntry.nextSibling)
510 pCD->clientEntry.nextSibling->prevSibling =
511 pCD->clientEntry.prevSibling;
515 pSD->lastClient = pCD->clientEntry.prevSibling;
519 } /* END OF FUNCTION DeleteClientFromList */
523 /*************************************<->*************************************
525 * AddTransient (pWS, pCD)
530 * This function adds the transient window to the lead window's list of
536 * pWS = pointer to workspace data
537 * pCD = pointer to client data of a transient window
542 * pCD->transientLeader = (transientChildren, modalCount)
544 *************************************<->***********************************/
546 void AddTransient (WmWorkspaceData *pWS, ClientData *pCD)
548 ClientData *pcdLeader = pCD->transientLeader;
549 ClientData *pcdTop = FindTransientTreeLeader (pCD);
550 Boolean restackTransients;
551 WmScreenData *pSD = pWS->pSD;
554 pCD->transientSiblings = pcdLeader->transientChildren;
555 pcdLeader->transientChildren = pCD;
559 * Insure that the new transient window is on top of its siblings
560 * and that the transient window tree is on top of the window
561 * stack (this is the standard behavior for newly mapped and
562 * managed windows). If there is a system modal window that the
563 * transient window is not associated with then don't raise the
567 restackTransients = PutTransientOnTop (pCD);
571 * Handle application modal transient windows
574 if (pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
577 * If this is a primary application modal window then increment
578 * the modal count for transient leaders that are directly up
579 * the transient tree.
581 * (This is the old MWM_INPUT_APPLICATION_MODAL behavior.)
585 MarkModalTransient (pcdLeader, pCD);
586 pcdLeader = pcdLeader->transientLeader;
589 else if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
592 * If this is a full application modal window then increment
593 * the modal count for the rest of the transient tree.
596 MarkModalSubtree (pcdTop, pCD);
598 else if (pcdTop->fullModalCount)
601 * There is already a full application modal window in the tree
603 pcdLeader = pCD->transientLeader;
604 if ((pcdLeader->inputMode != MWM_INPUT_FULL_APPLICATION_MODAL) ||
605 (IS_APP_MODALIZED(pcdLeader)))
608 * The immediate parent of this transient is not the
609 * current full application modal window. Set the full
610 * modal count to the parent's so that they both become
611 * unmodalized at the same time. This allows a full
612 * app modal window to have active, non-modal transients.
614 pCD->fullModalCount = pcdLeader->fullModalCount;
620 * Do the actual restacking in the X window stack if necessary.
623 if ((pSD->clientList != &pcdTop->clientEntry) && !wmGD.systemModalActive)
625 F_Raise (NULL, pCD, NULL);
627 else if (restackTransients)
629 RestackTransientsAtWindow (pCD);
631 else if (pCD != FindTransientOnTop (pcdTop))
633 StackTransientWindow (pCD);
637 } /* END OF FUNCTION AddTransient */
641 /*************************************<->*************************************
643 * MarkModalSubtree (pcdTree, pcdAvoid)
648 * This function marks the transient tree with pcdTree as its leader.
649 * If pcdAvoid is in the tree, it is not marked.
653 * pcdTree = pointer to client data of the tree to mark
654 * pcdAvoid = pointer to client data to not mark if in tree
657 *************************************<->***********************************/
659 void MarkModalSubtree (ClientData *pcdTree, ClientData *pcdAvoid)
661 /* Mark children, if any */
663 if (pcdTree->transientChildren)
664 MarkModalSubtree (pcdTree->transientChildren, pcdAvoid);
668 if (pcdTree != pcdAvoid)
670 MarkModalTransient (pcdTree, pcdAvoid);
675 if (pcdTree->transientSiblings)
676 MarkModalSubtree (pcdTree->transientSiblings, pcdAvoid);
681 /*************************************<->*************************************
683 * MarkModalTransient (pcdLeader, pCD)
688 * This function marks a transient window for application modal processing.
689 * Grabs are done to eat up pointer button events.
693 * pcdLeader = pointer to client data to mark
694 * pCD = pointer to client data of new transient
697 *************************************<->***********************************/
699 void MarkModalTransient (ClientData *pcdLeader, ClientData *pCD)
701 if (!IS_APP_MODALIZED(pcdLeader))
704 * Eat pointer button events while application modal.
706 XGrabButton (DISPLAY, AnyButton, AnyModifier,
707 pcdLeader->clientBaseWin, True,
708 ButtonPressMask | ButtonMotionMask, GrabModeAsync,
709 GrabModeAsync, None, wmGD.workspaceCursor);
712 /* bump application modal count */
713 if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
714 pcdLeader->fullModalCount++;
716 pcdLeader->primaryModalCount++;
720 /*************************************<->*************************************
722 * DeleteTransient (pCD)
727 * This function deletes the transient window from the lead window's list
730 * Much of the complication of this code arises from trying to handle
731 * mixtures of both full- and primary-application modal transients.
732 * It also tries to handle the case where a sequence of application
733 * modal transients appear in different places in the transient tree
734 * (i.e. not as descendents of a previously existing full app modal
739 * pCD = pointer to client data of transient.
741 *************************************<->***********************************/
743 void DeleteTransient (ClientData *pCD)
745 ClientData *pcdLeader;
751 * Handle primary application modality.
752 * Reset the modal window counts for the leader windows up through the
753 * transient window tree.
756 modalCount = pCD->primaryModalCount;
757 if (pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
763 pcdLeader = pCD->transientLeader;
767 UnMarkModalTransient (pcdLeader, modalCount, pCD);
769 pcdLeader = pcdLeader->transientLeader;
774 * Handle full application modality.
775 * Undo application modal windows in a depth first manner.
778 pcdLeader = FindTransientTreeLeader (pCD);
780 if (pCD->transientChildren)
782 DeleteFullAppModalChildren (pcdLeader, pCD->transientChildren);
784 if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
788 * If this is a full application modal window then decrement
789 * the modal count for the rest of the transient tree.
792 FixupFullAppModalCounts (pcdLeader, pCD);
797 * Delete this transient from its parent's list of transient windows.
800 pcdPrev = pCD->transientLeader->transientChildren;
805 pCD->transientLeader->transientChildren = pCD->transientSiblings;
809 while (pcdPrev && (pcdPrev->transientSiblings != pCD))
811 pcdPrev = pcdPrev->transientSiblings;
814 pcdPrev->transientSiblings = pCD->transientSiblings;
818 } /* END OF FUNCTION DeleteTransient */
821 /*************************************<->*************************************
823 * DeleteFullAppModalChildren (pcdLeader, pCD)
828 * This function handles the clean-up of nested full application modal
829 * windows. The deletion has to be handled carefully to keep a correct
830 * fullModalCount on the transients that remain in the tree.
832 * The algorithm is to traverse the transient children depth first and
833 * fix up the tree's fullModalCount for each full application modal
834 * window that's found.
838 * pcdLeader = pointer to client data of transient tree root.
839 * pCD = pointer to client data of transient subtree to delete.
841 *************************************<->***********************************/
843 void DeleteFullAppModalChildren (ClientData *pcdLeader, ClientData *pCD)
846 /* recursively do children first */
847 if (pCD->transientChildren)
848 DeleteFullAppModalChildren (pcdLeader, pCD->transientChildren);
850 /* do fullAppModal fixup for this guy */
851 FixupFullAppModalCounts (pcdLeader, pCD);
853 /* do siblings of passed transient */
854 if (pCD->transientSiblings)
855 DeleteFullAppModalChildren (pcdLeader, pCD->transientSiblings);
858 } /* END OF FUNCTION DeleteFullAppModalChildren */
861 /*************************************<->*************************************
863 * FixupFullAppModalCounts (pcdLeader, pcdDelete)
868 * This function traverses the entire transient tree (pointed to by
869 * pcdLeader) and fixes up the fullModalCounts to reflect the removal
872 * The fix-up consists of decrementing the count
873 * of the remaining full app modal windows in the tree iff the remaining
874 * window's fullModalCount is greater than the fullModalCount of the
875 * transient being deleted.
879 * pcdLeader = pointer to client data for head of transient tree.
880 * pcdDelet = pointer to client data of transient being deleted.
882 *************************************<->***********************************/
885 FixupFullAppModalCounts (ClientData *pcdLeader, ClientData *pcdDelete)
890 if (pcdLeader->transientChildren)
892 FixupFullAppModalCounts (pcdLeader->transientChildren, pcdDelete);
896 * fixup leader: decrement the count if it is greater than
897 * the transient being deleted.
900 if (pcdLeader->fullModalCount > pcdDelete->fullModalCount)
902 UnMarkModalTransient (pcdLeader, 1, pcdDelete);
906 if (pcdLeader->transientSiblings)
908 FixupFullAppModalCounts (pcdLeader->transientSiblings, pcdDelete);
911 } /* END OF FUNCTION FixupFullAppModalCounts */
915 /*************************************<->*************************************
917 * UnMarkModalTransient (pcdModee, modalCount, pcdModal)
922 * This function unmarks a transient window for application modal processing.
923 * Original grabs are restored.
927 * pcdModee = pointer to client data for transient to unmark
928 * pcdModal = pointer to client data for modal transient
929 * modalCount = amount to decrement the client's modal count by
932 *************************************<->***********************************/
934 void UnMarkModalTransient (ClientData *pcdModee, int modalCount, ClientData *pcdModal)
936 /* decrement application modal count */
937 if (pcdModal->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
938 pcdModee->fullModalCount -= modalCount;
939 else if (pcdModal->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
940 pcdModee->primaryModalCount -= modalCount;
943 * Restore original button bindings/grabs if not modal anymore
945 if (!IS_APP_MODALIZED(pcdModee))
947 XUngrabButton (DISPLAY, AnyButton, AnyModifier,
948 pcdModee->clientBaseWin);
950 SetupCButtonBindings (pcdModee->clientBaseWin, BUTTON_SPECS(pcdModee));
952 if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
953 (wmGD.keyboardFocus != pcdModee))
955 DoExplicitSelectGrab (pcdModee->clientBaseWin);
961 /*************************************<->*************************************
963 * PutTransientOnTop (pcd)
968 * This function changes the transient window list to insure that the
969 * specified transient window is on top of its siblings and its parent
970 * is on top of its siblings, etc. The sibling list is ordered such
971 * that the first window in the list is on top of second window in the
977 * pcd = pointer to client data of a transient window
982 * pcdLeader = (transientSiblings)
984 * RETURN = True if the transient tree needs to be restacked
986 *************************************<->***********************************/
988 Boolean PutTransientOnTop (ClientData *pcd)
990 ClientData *pcdLeader;
992 Boolean restack = False;
995 pcdLeader = pcd->transientLeader;
996 if (pcdLeader != NULL)
998 pcdPrev = pcdLeader->transientChildren;
1001 while (pcdPrev->transientSiblings != pcd)
1003 pcdPrev = pcdPrev->transientSiblings;
1005 pcdPrev->transientSiblings = pcd->transientSiblings;
1006 pcd->transientSiblings = pcdLeader->transientChildren;
1007 pcdLeader->transientChildren = pcd;
1011 if (PutTransientOnTop (pcdLeader))
1016 if (BumpPrimaryToBottom (pcdLeader))
1025 } /* END OF FUNCTION PutTransientOnTop */
1029 /*************************************<->*************************************
1031 * PutTransientBelowSiblings (pcd)
1036 * This function changes the transient window list to insure that the
1037 * specified transient window is below its sibling windows.
1042 * pcd = pointer to client data of a transient window
1047 * pcdLeader = (transientSiblings)
1049 * RETURN = True if restacking has been done in the transient window tree.
1051 *************************************<->***********************************/
1053 Boolean PutTransientBelowSiblings (ClientData *pcd)
1055 ClientData *pcdLeader;
1056 ClientData *pcdNext;
1057 Boolean restack = False;
1060 pcdLeader = pcd->transientLeader;
1063 if (pcd->transientSiblings || (pcdLeader->transientChildren != pcd))
1066 if (pcdLeader->transientChildren == pcd)
1068 pcdLeader->transientChildren = pcd->transientSiblings;
1071 pcdNext = pcdLeader->transientChildren;
1072 while (pcdNext->transientSiblings)
1074 if (pcdNext->transientSiblings == pcd)
1076 pcdNext->transientSiblings = pcd->transientSiblings;
1080 pcdNext = pcdNext->transientSiblings;
1083 pcdNext->transientSiblings = pcd;
1085 pcd->transientSiblings = NULL;
1090 } /* END OF FUNCTION PutTransientBelowSiblings */
1094 /*************************************<->*************************************
1096 * RestackTransients (pcd)
1101 * This function restacks windows in a transient window tree. Secondary
1102 * (transient) windows are stacked on top of their associated primary
1103 * windows and the first secondary window in the transientSiblings list
1104 * is stacked on top of the second window in the list, etc.
1109 * pcd = pointer to client data of a window in a transient tree
1111 *************************************<->***********************************/
1113 void RestackTransients (ClientData *pcd)
1115 ClientData *pcdLeader;
1117 static int size = 0;
1118 static Window *windows = NULL;
1122 XWindowChanges windowChanges;
1127 * Build a restacking list and do the restacking.
1130 pcdLeader = FindTransientTreeLeader (pcd);
1131 count = CountTransientChildren (pcdLeader);
1133 /* No work to do if no transient children; count includes leader. */
1140 * Expand the (static) windows buffer that is used in restacking.
1144 (Window *)WmMalloc ((char*)windows, (count + 5) * sizeof (Window))))
1146 /* cannot get memory space */
1154 MakeTransientFamilyStackingList (windows, pcdLeader);
1156 nextWindow = MakeTransientWindowList (windows, pcdLeader);
1157 *nextWindow = pcdLeader->clientFrameWin;
1161 * Changes for CDExc19397.
1162 * XRestackWindows may move pcdLeader; that messes up the
1163 * global window stack. Call XConfigureWindow() instead,
1164 * and don't change location of pcdLeader.
1166 for (leaderIndex = 0; leaderIndex < count; leaderIndex++)
1168 if (windows[leaderIndex] == pcdLeader->clientFrameWin)
1171 if (leaderIndex >= count) /* ? Couldn't find leader; should NOT happen. */
1172 leaderIndex = count - 1;
1174 windowChanges.stack_mode = Above;
1175 for (i = leaderIndex; i > 0; i--)
1177 windowChanges.sibling = windows[i];
1178 XConfigureWindow (DISPLAY, windows[i - 1],
1179 CWSibling | CWStackMode, &windowChanges);
1182 windowChanges.stack_mode = Below;
1183 for (i = leaderIndex; i < count - 1; i++)
1185 windowChanges.sibling = windows[i];
1186 XConfigureWindow (DISPLAY, windows[i + 1],
1187 CWSibling | CWStackMode, &windowChanges);
1190 } /* END OF FUNCTION RestackTransients */
1194 /*************************************<->*************************************
1196 * RestackTransientsAtWindow (pcd)
1201 * This function restacks windows in a transient window tree. The
1202 * "anchor point" in the stack for the transient window tree is the
1208 * pcd = pointer to client data of a window in a transient tree
1210 *************************************<->***********************************/
1212 void RestackTransientsAtWindow (ClientData *pcd)
1214 ClientData *pcdLeader;
1215 XWindowChanges windowChanges;
1217 pcdLeader = FindTransientTreeLeader (pcd);
1218 if (pcdLeader && (pcdLeader != pcd))
1220 windowChanges.sibling = pcd->clientFrameWin;
1221 windowChanges.stack_mode = Below;
1222 XConfigureWindow (DISPLAY, pcdLeader->clientFrameWin,
1223 CWSibling | CWStackMode, &windowChanges);
1226 RestackTransients (pcd);
1228 } /* END OF FUNCTION RestackTransientsAtWindow */
1232 /*************************************<->*************************************
1234 * FindTransientTreeLeader (pcd)
1239 * This function identifies the leader of the transient tree that
1240 * contains the specified client.
1245 * pcd = pointer to client data of a window in a transient tree.
1249 * RETURN = pointer to the client data for the transient tree leader.
1251 *************************************<->***********************************/
1253 ClientData * FindTransientTreeLeader (ClientData *pcd)
1258 * Find the head of the transient window tree.
1261 while (pcd->transientLeader)
1263 pcd = pcd->transientLeader;
1268 } /* END OF FUNCTION FindTransientTreeLeader */
1272 /*************************************<->*************************************
1274 * CountTransientChildren (pcd)
1279 * This function returns a count of the number of children in the
1280 * transient window tree headed by the specified client window.
1285 * pcd = pointer to client data of a window in a transient tree
1289 * RETURN = count of transient windows in the transient window tree
1291 *************************************<->***********************************/
1294 CountTransientChildren (ClientData *pcd)
1297 ClientData *pcdNext;
1301 pcdNext = pcd->transientChildren;
1304 if (pcdNext->transientChildren)
1306 count += CountTransientChildren (pcdNext);
1312 pcdNext = pcdNext->transientSiblings;
1317 } /* END OF FUNCTION CountTransientChildren */
1321 /*************************************<->*************************************
1323 * MakeTransientWindowList (windows, pcd)
1328 * This function makes a transient window list of windows in the
1329 * transient window tree headed by the specified client. This list is
1330 * to be passed to XRestackWindows.
1335 * windows = pointer to the windows list to be filled out
1337 * pcd = pointer to client data of a window in a transient tree
1341 * RETURN = pointer to the next entry in the windows list
1343 *************************************<->***********************************/
1345 Window * MakeTransientWindowList (Window *windows, ClientData *pcd)
1348 ClientData *pcdNext;
1351 pcdNext = pcd->transientChildren;
1354 if (pcdNext->transientChildren)
1356 windows = MakeTransientWindowList (windows, pcdNext);
1358 *windows = pcdNext->clientFrameWin;
1360 pcdNext = pcdNext->transientSiblings;
1366 } /* END OF FUNCTION MakeTransientWindowList */
1370 /*************************************<->*************************************
1372 * FindTransientFocus (pcd)
1377 * This function identifies a window in the transient tree that is headed
1378 * by the specified client that can accept the keyboard input. The
1379 * effect of application modal windows is taken into account.
1384 * pcd = pointer to client data of a window in a transient tree.
1388 * RETURN = pointer to the client data for a window that can accept the
1389 * keyboard input focus.
1391 *************************************<->***********************************/
1393 ClientData * FindTransientFocus (ClientData *pcd)
1397 ClientData *pcdFocus;
1400 * Find a window that does not have an application modal subordinate.
1401 * First, search descendents
1405 while (pcdFocus->transientChildren && IS_APP_MODALIZED(pcdFocus))
1407 pcdFocus = pcdFocus->transientChildren;
1411 * If (search of descendents FAILS) then search siblings.
1414 if (IS_APP_MODALIZED(pcdFocus))
1416 ClientData *pcdSibling;
1419 while (pcdFocus && IS_APP_MODALIZED(pcdFocus))
1421 pcdSibling = pcdFocus;
1422 while (pcdSibling->transientSiblings && IS_APP_MODALIZED(pcdFocus))
1424 pcdSibling = pcdSibling->transientSiblings;
1426 if (IS_APP_MODALIZED(pcdSibling))
1428 pcdFocus = pcdFocus->transientChildren;
1432 pcdFocus = pcdSibling;
1438 return (pcdFocus ? pcdFocus : wmGD.keyboardFocus);
1440 } /* END OF FUNCTION FindTransientFocus */
1444 /*************************************<->*************************************
1446 * FindTransientOnTop (pcd)
1451 * This function identifies the top-most transient window in the
1452 * transient window tree that contains the specified client.
1457 * pcd = pointer to client data of a window in a transient tree.
1461 * RETURN = pointer to the client data for the top-most transient window.
1463 *************************************<->***********************************/
1465 ClientData * FindTransientOnTop (ClientData *pcd)
1470 * Find the head of the transient window tree.
1473 pcd = FindTransientTreeLeader (pcd);
1475 if (!(pcd->secondariesOnTop) &&
1476 (LeaderOnTop (pcd)))
1480 if (LeaderOnTop (pcd))
1482 /* The primary window is on top! */
1487 pcdSub = FindSubLeaderToTop (pcd);
1496 * Find the top-most transient window (the window in the transient tree
1497 * that is highest in the window stack).
1500 while (pcd->transientChildren)
1502 pcd = pcd->transientChildren;
1507 } /* END OF FUNCTION FindTransientOnTop */
1511 /*************************************<->*************************************
1513 * StackWindow (pWS, pEntry, onTop, pStackEntry)
1518 * This function stacks a window of a particular type (normal or icon)
1519 * to the top or botton of the window stack on the screen.
1524 * pWS = pointer to workspace data
1526 * pEntry = pointer to the client list entry for the window to be restacked.
1528 * onTop = if True then the window is to be restacked on top of the
1529 * specified stack window (if the stack window is not specified then
1530 * the entry is added to the top of the window stack)
1531 * otherwise the window is stacked below the specified stack window
1532 * (or at the bottom of the window stack if the stack window is not
1535 * pStackEntry = pointer to a client list entry for a window in the window
1536 * stack that is to be used as a reference in restacking.
1538 *************************************<->***********************************/
1540 void StackWindow (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
1543 Boolean stackTransientTreeWindows = False;
1544 Window activeIconWindow;
1546 XWindowChanges changes;
1547 WmScreenData *pSD = pWS->pSD;
1552 if (pStackEntry->type == MINIMIZED_STATE)
1554 stackWindow = ICON_FRAME_WIN(pStackEntry->pCD);
1558 stackWindow = pStackEntry->pCD->clientFrameWin;
1563 stackWindow = (Window)0;
1566 if (pEntry->type == MINIMIZED_STATE)
1568 window = ICON_FRAME_WIN(pEntry->pCD);
1573 * Restack the transient tree if appropriate.
1576 if (pEntry->pCD->transientLeader || pEntry->pCD->transientChildren)
1578 stackTransientTreeWindows = True;
1580 window = (FindTransientOnTop (pEntry->pCD))->clientFrameWin;
1584 window = pEntry->pCD->clientFrameWin;
1590 * The active icon text label must be restacked along with the associated
1594 if ((pEntry->type == MINIMIZED_STATE) &&
1595 (pEntry->pCD == wmGD.keyboardFocus) &&
1596 (ICON_DECORATION(pEntry->pCD) & ICON_ACTIVE_LABEL_PART) &&
1597 (ACTIVE_ICON_TEXT_WIN))
1599 activeIconWindow = ACTIVE_ICON_TEXT_WIN;
1603 activeIconWindow = (Window)0;
1608 if ((stackWindow == 0) && (pSD->clientList))
1610 if (pSD->clientList->type == MINIMIZED_STATE)
1612 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
1616 if (pSD->clientList->pCD->transientChildren)
1619 (FindTransientOnTop(pSD->clientList->pCD))->clientFrameWin;
1623 stackWindow = pSD->clientList->pCD->clientFrameWin;
1628 if (activeIconWindow)
1630 changes.sibling = stackWindow;
1631 changes.stack_mode = Above;
1632 XConfigureWindow (DISPLAY, activeIconWindow,
1633 (CWSibling | CWStackMode), &changes);
1634 changes.sibling = activeIconWindow;
1635 changes.stack_mode = Below;
1636 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1641 changes.sibling = stackWindow;
1642 changes.stack_mode = Above;
1643 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1645 if (stackTransientTreeWindows)
1647 /* make sure that the leader is in the correct spot */
1648 changes.sibling = window;
1649 changes.stack_mode = Below;
1650 XConfigureWindow (DISPLAY, pEntry->pCD->clientFrameWin,
1651 (CWSibling | CWStackMode), &changes);
1652 RestackTransients (pEntry->pCD);
1660 * Adjust stack entry window if we're stacking below a
1663 if (pStackEntry && pStackEntry->pCD->transientChildren)
1665 stackWindow = LowestWindowInTransientFamily (pStackEntry->pCD);
1669 if (stackWindow == 0)
1671 if (pSD->lastClient->type == MINIMIZED_STATE)
1673 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
1678 if (pSD->lastClient->pCD->transientChildren)
1681 LowestWindowInTransientFamily (pSD->lastClient->pCD);
1685 stackWindow = pSD->lastClient->pCD->clientFrameWin;
1689 if (activeIconWindow)
1691 changes.sibling = stackWindow;
1692 changes.stack_mode = Below;
1693 XConfigureWindow (DISPLAY, activeIconWindow,
1694 (CWSibling | CWStackMode), &changes);
1695 changes.sibling = activeIconWindow;
1696 changes.stack_mode = Below;
1697 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1702 changes.sibling = stackWindow;
1703 changes.stack_mode = Below;
1704 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1706 if (stackTransientTreeWindows)
1708 /* make sure that the leader is in the correct spot */
1709 changes.sibling = window;
1710 changes.stack_mode = Below;
1711 XConfigureWindow (DISPLAY, pEntry->pCD->clientFrameWin,
1712 (CWSibling | CWStackMode), &changes);
1713 RestackTransients (pEntry->pCD);
1718 } /* END OF FUNCTION StackWindow */
1722 /*************************************<->*************************************
1724 * StackTransientWindow (pcd)
1729 * This function stacks a transient window within its transient window
1730 * tree on the screen. The transient window tree should indicate the
1731 * intended stacking position.
1736 * pcd = pointer to client data of a window in a transient tree
1738 *************************************<->***********************************/
1740 void StackTransientWindow (ClientData *pcd)
1742 XWindowChanges changes;
1743 ClientData *pcdPrev;
1746 if (pcd->transientLeader->transientChildren == pcd)
1748 if (pcd->transientSiblings)
1750 changes.sibling = pcd->transientSiblings->clientFrameWin;
1754 changes.sibling = pcd->transientLeader->clientFrameWin;
1756 changes.stack_mode = Above;
1760 pcdPrev = pcd->transientLeader;
1761 while (pcdPrev->transientSiblings != pcd)
1763 pcdPrev = pcdPrev->transientSiblings;
1765 changes.sibling = pcdPrev->clientFrameWin;
1766 changes.stack_mode = Below;
1769 XConfigureWindow (DISPLAY, pcd->clientFrameWin, (CWSibling | CWStackMode),
1773 } /* END OF FUNCTION StackTransientWindow */
1777 /*************************************<->*************************************
1779 * CheckIfClientObscuring (pcdTop, pcd)
1784 * This function determines whether a window or a transient window tree
1785 * is obscuring (at least partially) a window or a transient window tree
1786 * that is below it in the window stack.
1791 * pcdTop = pointer to client data for a window (it may be the leader of
1792 * a transient tree; this window is the higher in the window stack
1793 * than the window it is be checked against.
1795 * pcd = pointer to client data for a window (it may be the leader of
1801 * RETURN = True if the top window(s) overlap the lower window(s)
1803 *************************************<->***********************************/
1805 Boolean CheckIfClientObscuring (ClientData *pcdTop, ClientData *pcd)
1807 Boolean obscuring = False;
1808 ClientData *pcdNext;
1812 * Check only if the top window is visible onscreen.
1815 if (pcdTop->transientChildren && (pcdTop->clientState != MINIMIZED_STATE))
1817 pcdNext = pcdTop->transientChildren;
1818 while (pcdNext && !obscuring)
1820 obscuring = CheckIfClientObscuring (pcdNext, pcd);
1821 pcdNext = pcdNext->transientSiblings;
1825 if (!obscuring && pcd->transientChildren &&
1826 (pcd->clientState != MINIMIZED_STATE))
1828 pcdNext = pcd->transientChildren;
1829 while (pcdNext && !obscuring)
1831 obscuring = CheckIfClientObscuring (pcdTop, pcdNext);
1832 pcdNext = pcdNext->transientSiblings;
1838 obscuring = CheckIfObscuring (pcdTop, pcd);
1843 } /* END OF FUNCTION CheckIfClientObscuring */
1847 /*************************************<->*************************************
1849 * CheckIfObscuring (pcdA, pcdB)
1854 * This function determines whether a window (not a transient tree)
1855 * is obscuring (at least partially) a window (not a transient tree)
1856 * that is below it in the window stack.
1861 * pcdA = pointer to client data for a window; this window is higher in
1862 * the window stack than the window it is be checked against.
1864 * pcdB = pointer to client data for a window.
1869 * RETURN = True if the top window overlaps the lower window
1871 *************************************<->***********************************/
1873 Boolean CheckIfObscuring (ClientData *pcdA, ClientData *pcdB)
1875 Boolean obscuring = False;
1887 * For workspace stuff: if either is unseen, then neither
1890 if ((pcdA->clientState & UNSEEN_STATE) ||
1891 (pcdB->clientState & UNSEEN_STATE))
1897 if (pcdA->clientState == NORMAL_STATE)
1899 aX1 = pcdA->clientX - pcdA->clientOffset.x;
1900 aY1 = pcdA->clientY - pcdA->clientOffset.y;
1901 aX2 = aX1 + pcdA->clientWidth + (2 * pcdA->clientOffset.x) - 1;
1902 aY2 = aY1 + pcdA->clientHeight + pcdA->clientOffset.y +
1903 pcdA->clientOffset.x - 1;
1905 else if (pcdA->clientState == MINIMIZED_STATE)
1909 aX2 = aX1 + ICON_WIDTH(pcdA) - 1;
1910 aY2 = aY1 + ICON_HEIGHT(pcdA) - 1;
1912 else /* (pcdA->clientState == MAXIMIZED_STATE) */
1914 aX1 = pcdA->maxX - pcdA->clientOffset.x;
1915 aY1 = pcdA->maxY - pcdA->clientOffset.y;
1916 aX2 = aX1 + pcdA->maxWidth + (2 * pcdA->clientOffset.x) - 1;
1917 aY2 = aY1 + pcdA->maxHeight + pcdA->clientOffset.y +
1918 pcdA->clientOffset.x - 1;
1921 if (pcdB->clientState == NORMAL_STATE)
1923 bX1 = pcdB->clientX - pcdB->clientOffset.x;
1924 bY1 = pcdB->clientY - pcdB->clientOffset.y;
1925 bX2 = bX1 + pcdB->clientWidth + (2 * pcdB->clientOffset.x) - 1;
1926 bY2 = bY1 + pcdB->clientHeight + pcdB->clientOffset.y +
1927 pcdB->clientOffset.x - 1;
1929 else if (pcdB->clientState == MINIMIZED_STATE)
1933 bX2 = bX1 + ICON_WIDTH(pcdB) - 1;
1934 bY2 = bY1 + ICON_HEIGHT(pcdB) - 1;
1936 else /* (pcdB->clientState == MAXIMIZED_STATE) */
1938 bX1 = pcdB->maxX - pcdB->clientOffset.x;
1939 bY1 = pcdB->maxY - pcdB->clientOffset.y;
1940 bX2 = bX1 + pcdB->maxWidth + (2 * pcdB->clientOffset.x) - 1;
1941 bY2 = bY1 + pcdB->maxHeight + pcdB->clientOffset.y +
1942 pcdB->clientOffset.x - 1;
1946 * Check if there is overlap in both dimensions.
1949 if (((aX1 >= bX1) && (aX1 <= bX2)) || ((aX2 >= bX1) && (aX2 <= bX2)) ||
1950 ((bX1 >= aX1) && (bX1 <= aX2)) || ((bX2 >= aX1) && (bX2 <= aX2)))
1952 if (((aY1 >= bY1) && (aY1 <= bY2)) || ((aY2 >= bY1) && (aY2 <= bY2)) ||
1953 ((bY1 >= aY1) && (bY1 <= aY2)) || ((bY2 >= aY1) && (bY2 <= aY2)))
1962 } /* END OF FUNCTION CheckIfObscuring */
1966 /*************************************<->*************************************
1968 * CheckIfClientObscuredByAny (pcd)
1973 * This function determines whether a window or a transient window tree
1974 * is obscured (at least partially) by any other window.
1979 * pcd = pointer to client data for a window (it may be the leader of
1985 * RETURN = True if the window(s) are overlapped.
1987 *************************************<->***********************************/
1989 Boolean CheckIfClientObscuredByAny (ClientData *pcd)
1991 Boolean obscured = False;
1992 ClientListEntry *pListEntry;
1995 pListEntry = ACTIVE_PSD->clientList;
1996 while (pListEntry && !obscured)
1998 if (pListEntry->pCD == pcd)
2000 if (((pListEntry->type == MINIMIZED_STATE) &&
2001 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2002 ((pListEntry->type != MINIMIZED_STATE) &&
2003 (pListEntry->pCD->clientState != MINIMIZED_STATE)))
2008 else if (((pListEntry->type == MINIMIZED_STATE) &&
2009 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2010 ((pListEntry->type != MINIMIZED_STATE) &&
2011 (pListEntry->pCD->clientState != MINIMIZED_STATE)))
2014 * The window for the entry is visible on screen. See if it
2015 * obscures the indicated window.
2018 obscured = CheckIfClientObscuring (pListEntry->pCD, pcd);
2023 pListEntry = pListEntry->nextSibling;
2029 } /* END OF FUNCTION CheckIfClientObscuredByAny */
2033 /*************************************<->*************************************
2035 * CheckIfClientObscuringAny (pcd)
2040 * This function determines whether a window or a transient window tree
2041 * is obscuring another window.
2046 * pcd = pointer to client data for a window (it may be the leader of
2052 * RETURN = True if the window(s) overlaps anther window.
2054 *************************************<->***********************************/
2056 Boolean CheckIfClientObscuringAny (ClientData *pcd)
2058 Boolean obscuring = False;
2059 ClientListEntry *pListEntry;
2062 pListEntry = (pcd->clientState == MINIMIZED_STATE) ?
2063 &pcd->iconEntry : &pcd->clientEntry;
2064 while (pListEntry && !obscuring)
2066 if ((pListEntry->pCD != pcd) &&
2067 (((pListEntry->type == MINIMIZED_STATE) &&
2068 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2069 ((pListEntry->type != MINIMIZED_STATE) &&
2070 (pListEntry->pCD->clientState != MINIMIZED_STATE))))
2072 obscuring = CheckIfClientObscuring (pcd, pListEntry->pCD);
2075 pListEntry = pListEntry->nextSibling;
2080 } /* END OF FUNCTION CheckIfClientObscuringAny */
2084 /*************************************<->*************************************
2086 * SetupSystemModalState (pCD)
2091 * This function prepares for mapping a system modal window. An input
2092 * screen window is mapped below the system modal window to prevent input
2093 * to the windows not related to the system modal window.
2098 * pCD = pointer to client data for the system modal window; if NULL the
2099 * system modal window is a special window manager dialog box
2104 * wmGD = changes to system modal state data
2106 *************************************<->***********************************/
2108 void SetupSystemModalState (ClientData *pCD)
2110 XWindowChanges windowChanges;
2111 unsigned int width, height;
2112 unsigned int x_hot, y_hot;
2113 unsigned char *bits;
2114 unsigned char *mask_bits;
2119 * If we've got a menu active, then unpost it first
2120 * so that grabs from the menu don't interfere with
2121 * the system modal dialog. We want to avoid lock-ups.
2123 if (wmGD.menuActive != NULL)
2125 UnpostMenu (wmGD.menuActive);
2126 XSync (DISPLAY, False);
2130 * Try to grab the pointer and keyboard. If either
2131 * fails because event processing is frozen by another grab, then
2132 * don't do system modal for fear of leaving the system unusable.
2134 if (XGrabPointer(DISPLAY,
2135 ROOT_FOR_CLIENT(pCD),
2136 FALSE, /* owner_events */
2137 (unsigned int) 0, /* event mask */
2138 GrabModeAsync, /* pointer_mode */
2139 GrabModeAsync, /* keyboard_mode */
2140 None, /* confine_to window */
2142 CurrentTime) == GrabFrozen)
2148 XUngrabPointer (DISPLAY, CurrentTime);
2151 if (XGrabKeyboard(DISPLAY,
2152 ROOT_FOR_CLIENT(pCD),
2153 FALSE, /* owner_events */
2154 GrabModeAsync, /* pointer_mode */
2155 GrabModeAsync, /* keyboard_mode */
2156 CurrentTime) == GrabFrozen)
2162 XUngrabKeyboard (DISPLAY, CurrentTime);
2167 if (wmGD.useLargeCursors)
2169 width = noenter32_width;
2170 height = noenter32_height;
2171 x_hot = noenter32_x_hot;
2172 y_hot = noenter32_y_hot;
2173 bits = noenter32_bits;
2174 mask_bits = noenter32m_bits;
2178 #endif /* LARGECURSORS */
2181 width = noenter16_width;
2182 height = noenter16_height;
2183 x_hot = noenter16_x_hot;
2184 y_hot = noenter16_y_hot;
2185 bits = noenter16_bits;
2186 mask_bits = noenter16m_bits;
2189 for (scr=0; scr<wmGD.numScreens; scr++)
2191 pSD = &(wmGD.Screens[scr]);
2194 * Make the system modal input screen window if necessary.
2197 if (pSD->managed && pSD->inputScreenWindow == 0)
2199 XSetWindowAttributes windowAttributes;
2204 windowAttributes.event_mask = ButtonPressMask;
2205 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
2207 windowAttributes.event_mask |= EnterWindowMask;
2209 windowAttributes.override_redirect = True;
2211 pixmap = XCreateBitmapFromData (DISPLAY, pSD->rootWindow,
2212 (char *)bits, width, height);
2214 maskPixmap = XCreateBitmapFromData (DISPLAY, pSD->rootWindow,
2215 (char *)mask_bits, width, height);
2217 xcolors[0].pixel = BlackPixel (DISPLAY, pSD->screen);
2218 xcolors[1].pixel = WhitePixel (DISPLAY, pSD->screen);
2219 XQueryColors (DISPLAY, DefaultColormap (DISPLAY, pSD->screen),
2221 windowAttributes.cursor =
2222 XCreatePixmapCursor (DISPLAY, pixmap, maskPixmap,
2223 &(xcolors[0]), &(xcolors[1]),
2225 XFreePixmap (DISPLAY, pixmap);
2226 XFreePixmap (DISPLAY, maskPixmap);
2228 pSD->inputScreenWindow =
2229 XCreateWindow (DISPLAY, pSD->rootWindow, 0, 0,
2230 DisplayWidth (DISPLAY, pSD->screen),
2231 DisplayHeight (DISPLAY, pSD->screen),
2236 CWEventMask | CWOverrideRedirect | CWCursor,
2239 if (pSD->managed && pSD != ACTIVE_PSD)
2241 XMapRaised (DISPLAY, pSD->inputScreenWindow);
2247 wmGD.systemModalWindow = pCD->clientFrameWin;
2252 * ELSE: the system modal window is a special window manager dialog
2253 * box and wmGD.systemModalWindow is set prior to the call to
2254 * SetupSystemModalState. Set the focus to the special window manager
2258 SetKeyboardFocus (NULL, REFRESH_LAST_FOCUS);
2259 XSetInputFocus (DISPLAY, wmGD.systemModalWindow, RevertToPointerRoot,
2265 * Map the system modal input screen window below the system modal
2269 windowChanges.sibling = wmGD.systemModalWindow;
2270 windowChanges.stack_mode = Below;
2271 XConfigureWindow (DISPLAY, ACTIVE_PSD->inputScreenWindow,
2272 CWSibling | CWStackMode, &windowChanges);
2274 XMapWindow (DISPLAY, ACTIVE_PSD->inputScreenWindow);
2278 * Setup the system modal global data.
2281 wmGD.systemModalActive = True;
2282 wmGD.systemModalClient = pCD;
2285 } /* END OF FUNCTION SetupSystemModalState */
2289 /*************************************<->*************************************
2291 * UndoSystemModalState ()
2296 * This function cleans up after a system modal window goes away.
2301 * wmGD = (system modal state data)
2306 * wmGD = changes to system modal state data
2308 *************************************<->***********************************/
2310 void UndoSystemModalState (void)
2315 * Unmap the system modal input screen window.
2318 for (scr = 0; scr < wmGD.numScreens; scr++)
2320 if(wmGD.Screens[scr].managed)
2322 XUnmapWindow (DISPLAY, wmGD.Screens[scr].inputScreenWindow);
2327 * Reset the focus if a window manager system modal dialog box was
2331 if (!wmGD.systemModalClient)
2333 AutoResetKeyFocus (NULL, GetTimestamp());
2338 * Reset the system modal global data.
2341 wmGD.systemModalActive = False;
2342 wmGD.systemModalClient = NULL;
2343 wmGD.systemModalWindow = 0;
2345 } /* END OF FUNCTION UndoSystemModalState */
2349 /*************************************<->*************************************
2351 * FindClientNameMatch (pStartingEntry, toNext, clientName, types)
2356 * This function searches for a client that has a particular name or class.
2357 * A match will be indicated if the client with the name or class also
2358 * is in a particular state.
2363 * pEntry = pointer to the client list entry where the search is
2366 * toNext = if True then search client list from first to last; otherwise
2367 * search the client list last to first.
2369 * clientName = string that indicates a client name or class.
2371 * type = types of objects (icon, window, ...) that are to be matched.
2376 * RETURN = pointer to client list entry for matched client.
2378 *************************************<->***********************************/
2379 ClientListEntry * FindClientNameMatch (ClientListEntry *pEntry,
2382 unsigned long types)
2385 Boolean foundMatch = False;
2390 while (!foundMatch && pEntry)
2394 if (pEntry->type == MINIMIZED_STATE)
2396 if ((pCD->clientState == MINIMIZED_STATE) &&
2397 (types & F_GROUP_ICON))
2404 if ((pCD->clientState != MINIMIZED_STATE) &&
2405 (types & F_GROUP_WINDOW))
2412 ((pCD->clientName && (strcmp (clientName,pCD->clientName) == 0)) ||
2413 (pCD->clientClass && (strcmp (clientName,pCD->clientClass) == 0))))
2419 pEntry = (toNext) ? pEntry->nextSibling : pEntry->prevSibling;
2425 } /* END OF FUNCTION FindClientNameMatch */
2428 /*************************************<->*************************************
2430 * BumpPrimaryToTop (pcdLeader)
2435 * This function moves the primary window to the "top" of the transient
2440 * pcdLeader = pointer to client data of transient tree root.
2442 * Returns: True if stacking order of leader window changed.
2443 * False if not stacking change.
2447 * This affects only the clientData structures. There is no immediate
2448 * effect on the actual stacking order on the display. That is done
2449 * by StackWindow and/or RestackTransients.
2451 *************************************<->***********************************/
2453 Boolean BumpPrimaryToTop (ClientData *pcdLeader)
2458 count = CountTransientChildren (pcdLeader);
2460 if (pcdLeader->primaryStackPosition != (count-1))
2462 pcdLeader->primaryStackPosition = count - 1;
2473 /*************************************<->*************************************
2475 * BumpPrimaryToBottom (pcdLeader)
2480 * This function moves the primary window to the "bottom" of the transient
2485 * pcdLeader = pointer to client data of transient tree root.
2487 * Returns: True if stacking order of leader window changed.
2488 * False if not stacking change.
2492 * This affects only the clientData structures. There is no immediate
2493 * effect on the actual stacking order on the display. That is done
2494 * by StackWindow and/or RestackTransients.
2496 *************************************<->***********************************/
2498 Boolean BumpPrimaryToBottom (ClientData *pcdLeader)
2502 if (pcdLeader->primaryStackPosition != 0)
2504 pcdLeader->primaryStackPosition = 0;
2516 /*************************************<->*************************************
2518 * LowestWindowInTransientFamily (pcdLeader)
2523 * This function returns the lowest stacked window in a transient
2528 * pcdLeader = pointer to client data of leader of a transient tree
2530 * Returns: id of lowest window in the transient tree for this family
2532 *************************************<->***********************************/
2535 LowestWindowInTransientFamily (ClientData *pcdLeader)
2538 static int size = 0;
2539 static Window *windows = NULL;
2540 Window wReturn = None;
2543 * Build a window list
2545 count = CountTransientChildren (pcdLeader);
2550 * Expand the (static) windows buffer
2554 (Window *)WmMalloc ((char*)windows, (count + 5) * sizeof (Window))))
2556 /* cannot get memory space */
2563 MakeTransientFamilyStackingList (windows, pcdLeader);
2567 wReturn = windows[count-1];
2576 } /* END OF FUNCTION LowestWindowInTransientFamily */
2579 /*************************************<->*************************************
2581 * FindSubLeaderToTop (pcd)
2586 * This function identifies a candidate window to top within the
2587 * transient tree that is a local transient leader (the window has
2588 * transients hanging off of it, too).
2593 * pcd = pointer to client data of a transient leader window
2595 * Return: ptr to client data for client that should be topped, or NULL
2601 *************************************<->***********************************/
2604 FindSubLeaderToTop (
2608 ClientData *pcdRet = NULL;
2609 ClientData *pcdNext;
2611 pcdNext = pcd->transientChildren;
2612 while (pcdNext && (!pcdRet))
2614 if (pcdNext->transientChildren)
2616 if (LeaderOnTop (pcdNext))
2622 pcdRet = FindSubLeaderToTop (pcdNext);
2625 pcdNext = pcdNext->transientSiblings;
2632 /*************************************<->*************************************
2634 * MakeTransientFamilyStackingList (windows, pcdLeader)
2639 * This function makes a transient window list of windows in the
2640 * transient window tree headed by the specified client.
2645 * windows = pointer to the windows list to be filled out
2647 * pcdLeader = pointer to client data of a window in a transient tree
2651 * The windows array is modified.
2655 * This function puts the transient leader window in the list in the
2658 *************************************<->***********************************/
2661 MakeTransientFamilyStackingList (
2663 ClientData *pcdLeader)
2667 Window *nextWindow, wSave, wTemp, wTop;
2668 int count = CountTransientChildren (pcdLeader);
2672 * Construct the transient stacking list according to
2673 * normal Motif rules.
2675 nextWindow = MakeTransientWindowList (windows, pcdLeader);
2677 if (!(pcdLeader->secondariesOnTop))
2680 * If the leader window shouldn't be on the bottom , then
2681 * adjust the stacking of the list.
2683 if ((pcdLeader->primaryStackPosition > 0) &&
2684 (pcdLeader->primaryStackPosition < count))
2686 for (i=0; i<pcdLeader->primaryStackPosition; i++)
2689 windows[j] = windows[j-1];
2691 j = count - pcdLeader->primaryStackPosition - 1;
2692 windows[j] = pcdLeader->clientFrameWin;
2697 * Put the leader at the bottom.
2699 *nextWindow = pcdLeader->clientFrameWin;
2702 * If one of the transients is also a local leader
2703 * and wants to be on top, then adjust the list.
2705 pcdSub = FindSubLeaderToTop (pcdLeader);
2706 if (pcdSub && (pcdSub->clientFrameWin != None))
2708 /* insert this window at top */
2709 wTop = wSave = pcdSub->clientFrameWin;
2711 /* shuffle the rest down */
2712 for (i=0; i<count; i++)
2727 * Put the leader at the bottom.
2729 *nextWindow = pcdLeader->clientFrameWin;
2732 } /* END OF FUNCTION MakeTransientFamilyStackingList */
2735 /*************************************<->*************************************
2737 * NormalizeTransientTreeStacking (pcdLeader)
2742 * This function traverses the transient tree and cleans up any
2743 * local primary windows that are above their respective secondary
2749 * pcdLeader = pointer to client data of a transient tree leader
2751 * Return: True if any changes in stacking order were made
2756 * This only touches the data structures.
2758 *************************************<->***********************************/
2761 NormalizeTransientTreeStacking (
2762 ClientData *pcdLeader)
2765 ClientData *pcdNext;
2766 Boolean bChanged = False;
2768 pcdNext = pcdLeader->transientChildren;
2769 bChanged = BumpPrimaryToBottom (pcdLeader);
2772 if (pcdNext->transientChildren)
2774 bChanged |= BumpPrimaryToBottom (pcdNext);
2776 bChanged |= NormalizeTransientTreeStacking (pcdNext);
2778 pcdNext = pcdNext->transientSiblings;
2784 /*************************************<->*************************************
2786 * LeaderOnTop (pcdLeader)
2791 * This function tests a leader of a transient (sub) tree to see if
2792 * it should be on top of its transient windows.
2797 * pcdLeader = pointer to client data of a transient tree leader
2799 * Return: True if this leader is on top of its transients
2805 *************************************<->***********************************/
2809 ClientData *pcdLeader)
2812 Boolean bOnTop = False;
2813 int count = CountTransientChildren (pcdLeader);
2815 if ((pcdLeader->primaryStackPosition > 0) &&
2816 (pcdLeader->primaryStackPosition < count))