2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
32 static char rcsid[] = "$TOG: WmWinList.c /main/8 1997/06/10 15:50:50 samborn $"
36 * (c) Copyright 1987, 1988, 1989, 1990, 1993, 1994 Hewlett-Packard Company
37 * (c) Copyright 1993, 1994 International Business Machines Corp.
38 * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
39 * (c) Copyright 1993, 1994 Novell, Inc.
48 #define MWM_NEED_NOENTER16
53 * include extern functions
55 #include "WmWinList.h"
57 #include "WmFunction.h"
58 #include "WmKeyFocus.h"
60 #include "WmResource.h"
61 #include "WmWinInfo.h"
63 #include "WmWrkspace.h"
74 /*************************************<->*************************************
76 * AddClientToList (pWS, pCD, onTop)
81 * This function adds a client window to the client window list. If it is
82 * a transient window then it is added to the transient window tree that
83 * contains its transient leader. The window stacking order is also
84 * maintained for the cases where there is a system modal window active
85 * or the window is a transient window. If a system modal window is being
86 * added then the system modal "input screen" window is setup.
91 * pCD = pointer to client data for the window to be added to the list
93 * pWS = pointer to workspace data
95 * onTop = if True then the window is displayed on top of the window
96 * stack and is added to the beginning of the window list, otherwise
97 * it is added to the end of the window list.
102 * pWS = (clientList, lastClient)
104 *************************************<->***********************************/
106 void AddClientToList (WmWorkspaceData *pWS, ClientData *pCD, Boolean onTop)
108 Boolean belowSystemModal = False;
109 XWindowChanges windowChanges;
110 WmScreenData *pSD = pWS->pSD;
112 WsClientData *pWsc = GetWsClientData (pWS, pCD);
116 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
119 * Set up the system modal input screen window just below the
120 * system modal window.
123 SetupSystemModalState (pCD);
125 if (!wmGD.systemModalActive || (wmGD.systemModalClient != pCD))
128 * If we failed to setup as system modal, then
129 * back off to MWM_INPUT_FULL_APPLICATION_MODAL.
130 * This will do *something* if this is a transient
133 pCD->inputMode = MWM_INPUT_FULL_APPLICATION_MODAL;
136 else if (wmGD.systemModalActive &&
137 ((FindTransientTreeLeader (pCD))->inputMode !=
138 MWM_INPUT_SYSTEM_MODAL))
141 * If a system modal window is active then place the window below
142 * the system modal input screen window if the window is not a
143 * descendant of the system modal window.
146 windowChanges.sibling = pSD->inputScreenWindow;
147 windowChanges.stack_mode = Below;
148 XConfigureWindow (DISPLAY, pCD->clientFrameWin,
149 CWSibling | CWStackMode, &windowChanges);
150 belowSystemModal = True;
153 if (pCD->transientLeader)
155 AddTransient (pWS, pCD);
159 pCD->clientEntry.type = NORMAL_STATE;
160 pCD->clientEntry.pCD = pCD;
162 if (belowSystemModal && wmGD.systemModalClient)
164 AddEntryToList (pWS, &pCD->clientEntry, False /*below*/,
169 AddEntryToList (pWS, &pCD->clientEntry, True /*on top*/, NULL);
173 AddEntryToList (pWS, &pCD->clientEntry, False /*on bottom*/, NULL);
178 if (!pWsc->pIconBox && pWsc->iconFrameWin)
180 if (!pCD->pIconBox && pCD->iconFrameWin)
184 * Put the icon on the bottom of the stack.
187 if (pSD->lastClient->type == MINIMIZED_STATE)
192 pWsib = &pSD->lastClient->pCD->pWsList[0];
193 windowChanges.sibling = pWsib->iconFrameWin;
195 windowChanges.sibling = pSD->lastClient->pCD->iconFrameWin;
200 windowChanges.sibling = pSD->lastClient->pCD->clientFrameWin;
202 windowChanges.stack_mode = Below;
204 XConfigureWindow (DISPLAY, pWsc->iconFrameWin,
205 CWSibling | CWStackMode, &windowChanges);
207 XConfigureWindow (DISPLAY, pCD->iconFrameWin,
208 CWSibling | CWStackMode, &windowChanges);
211 pCD->iconEntry.type = MINIMIZED_STATE;
212 pCD->iconEntry.pCD = pCD;
213 pCD->iconEntry.nextSibling = NULL;
214 pCD->iconEntry.prevSibling = pSD->lastClient;
215 pSD->lastClient->nextSibling = &pCD->iconEntry;
216 pSD->lastClient = &pCD->iconEntry;
220 } /* END OF FUNCTION AddClientToList */
224 /*************************************<->*************************************
226 * AddEntryToList (pWS, pEntry, onTop, pStackEntry)
231 * This function adds a client list entry to the client window list.
232 * This is usually done as part of the process of changing the ordering
233 * of the window list.
238 * pWS = pointer to workspace data
239 * pEntry = pointer to a client list entry to be added to the client list
241 * onTop = if True then the client list entry is added on top of the
242 * specified client list stack entry (if the stack entry is not
243 * specified then the entry is added to the front of the list);
244 * otherwise the entry is added after the specified stacking entry
245 * (or to the end of the list if the stacking entry is not specified).
247 * pStackEntry = pointer to a client list entry to be used as a reference
248 * in adding an entry to the client list.
252 * pWS = (clientList, lastClient)
254 *************************************<->***********************************/
256 void AddEntryToList (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
258 WmScreenData *pSD = pWS->pSD;
264 if (pEntry != pStackEntry)
266 pEntry->nextSibling = pStackEntry;
267 pEntry->prevSibling = pStackEntry->prevSibling;
268 pStackEntry->prevSibling = pEntry;
269 if (pEntry->prevSibling)
271 pEntry->prevSibling->nextSibling = pEntry;
275 pSD->clientList = pEntry;
281 if (pSD->clientList != pEntry)
283 pEntry->nextSibling = pSD->clientList;
284 pEntry->prevSibling = NULL;
287 pSD->clientList->prevSibling = pEntry;
291 pSD->lastClient = pEntry;
293 pSD->clientList = pEntry;
301 if (pEntry != pStackEntry)
303 pEntry->nextSibling = pStackEntry->nextSibling;
304 pEntry->prevSibling = pStackEntry;
305 pStackEntry->nextSibling = pEntry;
306 if (pEntry->nextSibling)
308 pEntry->nextSibling->prevSibling = pEntry;
312 pSD->lastClient = pEntry;
318 if (pSD->lastClient != pEntry)
320 pEntry->nextSibling = NULL;
321 pEntry->prevSibling = pSD->lastClient;
324 pSD->lastClient->nextSibling = pEntry;
328 pSD->clientList = pEntry;
330 pSD->lastClient = pEntry;
335 } /* END OF FUNCTION AddEntryToList */
339 /*************************************<->*************************************
341 * MoveEntryInList (pWS, pEntry, onTop, pStackEntry)
346 * This function moves a client list entry in the client window list.
351 * pWS = pointer to workspace data
353 * pEntry = pointer to a client list entry to be moved in the client list
355 * onTop = if True then the client list entry is moved on top of the
356 * specified client list stack entry (if the stack entry is not
357 * specified then the entry is moved to the front of the list);
358 * otherwise the entry is moved after the specified stacking entry
359 * (or to the end of the list if the stacking entry is not specified).
361 * pStackEntry = pointer to a client list entry to be used as a reference
362 * in moving an entry in the client list.
366 * pWS = (clientList, lastClient)
368 *************************************<->***********************************/
370 void MoveEntryInList (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
372 DeleteEntryFromList (pWS, pEntry);
373 AddEntryToList (pWS, pEntry, onTop, pStackEntry);
375 } /* END OF FUNCTION MoveEntryInList */
379 /*************************************<->*************************************
381 * DeleteEntryFromList (pWS, pListEntry)
386 * This function deletes a client list entry from the client window list.
387 * This is usually done as part of the process of changing the ordering
388 * of the window list.
393 * pWS = pointer to workspace data
394 * listEntry = pointer to a client list entry
398 * pWS = (clientList, lastClient)
400 *************************************<->***********************************/
402 void DeleteEntryFromList (WmWorkspaceData *pWS, ClientListEntry *pListEntry)
405 if (pListEntry->prevSibling)
407 pListEntry->prevSibling->nextSibling = pListEntry->nextSibling;
411 pWS->pSD->clientList = pListEntry->nextSibling;
414 if (pListEntry->nextSibling)
416 pListEntry->nextSibling->prevSibling = pListEntry->prevSibling;
420 pWS->pSD->lastClient = pListEntry->prevSibling;
423 } /* END OF FUNCTION DeleteEntryFromList */
427 /*************************************<->*************************************
429 * DeleteClientFromList (pWS, pCD)
434 * This function deletes a client from the client window list. If this is
435 * a transient window then it is deleted from its transient window tree.
436 * If this is a system modal window then clean up the system modal state.
441 * pCD = pointer to client data for the window to be added to the list
445 * pWS = (clientList, lastClient)
447 *************************************<->***********************************/
449 void DeleteClientFromList (WmWorkspaceData *pWS, ClientData *pCD)
452 WsClientData *pWsc = GetWsClientData (pWS, pCD);
454 WmScreenData *pSD = pWS->pSD;
456 if (pCD->transientLeader)
458 DeleteTransient (pCD);
463 * If this is a system modal window then clean up the system modal
467 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
469 UndoSystemModalState ();
473 * Remove the client and icon entries from the window list.
477 if (!pWsc->pIconBox && pWsc->iconFrameWin)
479 if (!pCD->pIconBox && pCD->iconFrameWin)
482 if (pCD->iconEntry.prevSibling)
484 pCD->iconEntry.prevSibling->nextSibling =
485 pCD->iconEntry.nextSibling;
489 pSD->clientList = pCD->iconEntry.nextSibling;
491 if (pCD->iconEntry.nextSibling)
493 pCD->iconEntry.nextSibling->prevSibling =
494 pCD->iconEntry.prevSibling;
498 pSD->lastClient = pCD->iconEntry.prevSibling;
502 if (pCD->clientEntry.prevSibling)
504 pCD->clientEntry.prevSibling->nextSibling =
505 pCD->clientEntry.nextSibling;
509 pSD->clientList = pCD->clientEntry.nextSibling;
512 if (pCD->clientEntry.nextSibling)
514 pCD->clientEntry.nextSibling->prevSibling =
515 pCD->clientEntry.prevSibling;
519 pSD->lastClient = pCD->clientEntry.prevSibling;
523 } /* END OF FUNCTION DeleteClientFromList */
527 /*************************************<->*************************************
529 * AddTransient (pWS, pCD)
534 * This function adds the transient window to the lead window's list of
540 * pWS = pointer to workspace data
541 * pCD = pointer to client data of a transient window
546 * pCD->transientLeader = (transientChildren, modalCount)
548 *************************************<->***********************************/
550 void AddTransient (WmWorkspaceData *pWS, ClientData *pCD)
552 ClientData *pcdLeader = pCD->transientLeader;
553 ClientData *pcdTop = FindTransientTreeLeader (pCD);
554 Boolean restackTransients;
555 WmScreenData *pSD = pWS->pSD;
558 pCD->transientSiblings = pcdLeader->transientChildren;
559 pcdLeader->transientChildren = pCD;
563 * Insure that the new transient window is on top of its siblings
564 * and that the transient window tree is on top of the window
565 * stack (this is the standard behavior for newly mapped and
566 * managed windows). If there is a system modal window that the
567 * transient window is not associated with then don't raise the
571 restackTransients = PutTransientOnTop (pCD);
575 * Handle application modal transient windows
578 if (pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
581 * If this is a primary application modal window then increment
582 * the modal count for transient leaders that are directly up
583 * the transient tree.
585 * (This is the old MWM_INPUT_APPLICATION_MODAL behavior.)
589 MarkModalTransient (pcdLeader, pCD);
590 pcdLeader = pcdLeader->transientLeader;
593 else if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
596 * If this is a full application modal window then increment
597 * the modal count for the rest of the transient tree.
600 MarkModalSubtree (pcdTop, pCD);
602 else if (pcdTop->fullModalCount)
605 * There is already a full application modal window in the tree
607 pcdLeader = pCD->transientLeader;
608 if ((pcdLeader->inputMode != MWM_INPUT_FULL_APPLICATION_MODAL) ||
609 (IS_APP_MODALIZED(pcdLeader)))
612 * The immediate parent of this transient is not the
613 * current full application modal window. Set the full
614 * modal count to the parent's so that they both become
615 * unmodalized at the same time. This allows a full
616 * app modal window to have active, non-modal transients.
618 pCD->fullModalCount = pcdLeader->fullModalCount;
624 * Do the actual restacking in the X window stack if necessary.
627 if ((pSD->clientList != &pcdTop->clientEntry) && !wmGD.systemModalActive)
629 F_Raise (NULL, pCD, NULL);
631 else if (restackTransients)
633 RestackTransientsAtWindow (pCD);
635 else if (pCD != FindTransientOnTop (pcdTop))
637 StackTransientWindow (pCD);
641 } /* END OF FUNCTION AddTransient */
645 /*************************************<->*************************************
647 * MarkModalSubtree (pcdTree, pcdAvoid)
652 * This function marks the transient tree with pcdTree as its leader.
653 * If pcdAvoid is in the tree, it is not marked.
657 * pcdTree = pointer to client data of the tree to mark
658 * pcdAvoid = pointer to client data to not mark if in tree
661 *************************************<->***********************************/
663 void MarkModalSubtree (ClientData *pcdTree, ClientData *pcdAvoid)
665 /* Mark children, if any */
667 if (pcdTree->transientChildren)
668 MarkModalSubtree (pcdTree->transientChildren, pcdAvoid);
672 if (pcdTree != pcdAvoid)
674 MarkModalTransient (pcdTree, pcdAvoid);
679 if (pcdTree->transientSiblings)
680 MarkModalSubtree (pcdTree->transientSiblings, pcdAvoid);
685 /*************************************<->*************************************
687 * MarkModalTransient (pcdLeader, pCD)
692 * This function marks a transient window for application modal processing.
693 * Grabs are done to eat up pointer button events.
697 * pcdLeader = pointer to client data to mark
698 * pCD = pointer to client data of new transient
701 *************************************<->***********************************/
703 void MarkModalTransient (ClientData *pcdLeader, ClientData *pCD)
705 if (!IS_APP_MODALIZED(pcdLeader))
708 * Eat pointer button events while application modal.
710 XGrabButton (DISPLAY, AnyButton, AnyModifier,
711 pcdLeader->clientBaseWin, True,
712 ButtonPressMask | ButtonMotionMask, GrabModeAsync,
713 GrabModeAsync, None, wmGD.workspaceCursor);
716 /* bump application modal count */
717 if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
718 pcdLeader->fullModalCount++;
720 pcdLeader->primaryModalCount++;
724 /*************************************<->*************************************
726 * DeleteTransient (pCD)
731 * This function deletes the transient window from the lead window's list
734 * Much of the complication of this code arises from trying to handle
735 * mixtures of both full- and primary-application modal transients.
736 * It also tries to handle the case where a sequence of application
737 * modal transients appear in different places in the transient tree
738 * (i.e. not as descendents of a previously existing full app modal
743 * pCD = pointer to client data of transient.
745 *************************************<->***********************************/
747 void DeleteTransient (ClientData *pCD)
749 ClientData *pcdLeader;
755 * Handle primary application modality.
756 * Reset the modal window counts for the leader windows up through the
757 * transient window tree.
760 modalCount = pCD->primaryModalCount;
761 if (pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
767 pcdLeader = pCD->transientLeader;
771 UnMarkModalTransient (pcdLeader, modalCount, pCD);
773 pcdLeader = pcdLeader->transientLeader;
778 * Handle full application modality.
779 * Undo application modal windows in a depth first manner.
782 pcdLeader = FindTransientTreeLeader (pCD);
784 if (pCD->transientChildren)
786 DeleteFullAppModalChildren (pcdLeader, pCD->transientChildren);
788 if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
792 * If this is a full application modal window then decrement
793 * the modal count for the rest of the transient tree.
796 FixupFullAppModalCounts (pcdLeader, pCD);
801 * Delete this transient from its parent's list of transient windows.
804 pcdPrev = pCD->transientLeader->transientChildren;
809 pCD->transientLeader->transientChildren = pCD->transientSiblings;
813 while (pcdPrev && (pcdPrev->transientSiblings != pCD))
815 pcdPrev = pcdPrev->transientSiblings;
818 pcdPrev->transientSiblings = pCD->transientSiblings;
822 } /* END OF FUNCTION DeleteTransient */
825 /*************************************<->*************************************
827 * DeleteFullAppModalChildren (pcdLeader, pCD)
832 * This function handles the clean-up of nested full application modal
833 * windows. The deletion has to be handled carefully to keep a correct
834 * fullModalCount on the transients that remain in the tree.
836 * The algorithm is to traverse the transient children depth first and
837 * fix up the tree's fullModalCount for each full application modal
838 * window that's found.
842 * pcdLeader = pointer to client data of transient tree root.
843 * pCD = pointer to client data of transient subtree to delete.
845 *************************************<->***********************************/
847 void DeleteFullAppModalChildren (ClientData *pcdLeader, ClientData *pCD)
850 /* recursively do children first */
851 if (pCD->transientChildren)
852 DeleteFullAppModalChildren (pcdLeader, pCD->transientChildren);
854 /* do fullAppModal fixup for this guy */
855 FixupFullAppModalCounts (pcdLeader, pCD);
857 /* do siblings of passed transient */
858 if (pCD->transientSiblings)
859 DeleteFullAppModalChildren (pcdLeader, pCD->transientSiblings);
862 } /* END OF FUNCTION DeleteFullAppModalChildren */
865 /*************************************<->*************************************
867 * FixupFullAppModalCounts (pcdLeader, pcdDelete)
872 * This function traverses the entire transient tree (pointed to by
873 * pcdLeader) and fixes up the fullModalCounts to reflect the removal
876 * The fix-up consists of decrementing the count
877 * of the remaining full app modal windows in the tree iff the remaining
878 * window's fullModalCount is greater than the fullModalCount of the
879 * transient being deleted.
883 * pcdLeader = pointer to client data for head of transient tree.
884 * pcdDelet = pointer to client data of transient being deleted.
886 *************************************<->***********************************/
889 FixupFullAppModalCounts (ClientData *pcdLeader, ClientData *pcdDelete)
894 if (pcdLeader->transientChildren)
896 FixupFullAppModalCounts (pcdLeader->transientChildren, pcdDelete);
900 * fixup leader: decrement the count if it is greater than
901 * the transient being deleted.
904 if (pcdLeader->fullModalCount > pcdDelete->fullModalCount)
906 UnMarkModalTransient (pcdLeader, 1, pcdDelete);
910 if (pcdLeader->transientSiblings)
912 FixupFullAppModalCounts (pcdLeader->transientSiblings, pcdDelete);
915 } /* END OF FUNCTION FixupFullAppModalCounts */
919 /*************************************<->*************************************
921 * UnMarkModalTransient (pcdModee, modalCount, pcdModal)
926 * This function unmarks a transient window for application modal processing.
927 * Original grabs are restored.
931 * pcdModee = pointer to client data for transient to unmark
932 * pcdModal = pointer to client data for modal transient
933 * modalCount = amount to decrement the client's modal count by
936 *************************************<->***********************************/
938 void UnMarkModalTransient (ClientData *pcdModee, int modalCount, ClientData *pcdModal)
940 /* decrement application modal count */
941 if (pcdModal->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
942 pcdModee->fullModalCount -= modalCount;
943 else if (pcdModal->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
944 pcdModee->primaryModalCount -= modalCount;
947 * Restore original button bindings/grabs if not modal anymore
949 if (!IS_APP_MODALIZED(pcdModee))
951 XUngrabButton (DISPLAY, AnyButton, AnyModifier,
952 pcdModee->clientBaseWin);
954 SetupCButtonBindings (pcdModee->clientBaseWin, BUTTON_SPECS(pcdModee));
956 if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
957 (wmGD.keyboardFocus != pcdModee))
959 DoExplicitSelectGrab (pcdModee->clientBaseWin);
965 /*************************************<->*************************************
967 * PutTransientOnTop (pcd)
972 * This function changes the transient window list to insure that the
973 * specified transient window is on top of its siblings and its parent
974 * is on top of its siblings, etc. The sibling list is ordered such
975 * that the first window in the list is on top of second window in the
981 * pcd = pointer to client data of a transient window
986 * pcdLeader = (transientSiblings)
988 * RETURN = True if the transient tree needs to be restacked
990 *************************************<->***********************************/
992 Boolean PutTransientOnTop (ClientData *pcd)
994 ClientData *pcdLeader;
996 Boolean restack = False;
999 pcdLeader = pcd->transientLeader;
1000 if (pcdLeader != NULL)
1002 pcdPrev = pcdLeader->transientChildren;
1005 while (pcdPrev->transientSiblings != pcd)
1007 pcdPrev = pcdPrev->transientSiblings;
1009 pcdPrev->transientSiblings = pcd->transientSiblings;
1010 pcd->transientSiblings = pcdLeader->transientChildren;
1011 pcdLeader->transientChildren = pcd;
1015 if (PutTransientOnTop (pcdLeader))
1020 if (BumpPrimaryToBottom (pcdLeader))
1029 } /* END OF FUNCTION PutTransientOnTop */
1033 /*************************************<->*************************************
1035 * PutTransientBelowSiblings (pcd)
1040 * This function changes the transient window list to insure that the
1041 * specified transient window is below its sibling windows.
1046 * pcd = pointer to client data of a transient window
1051 * pcdLeader = (transientSiblings)
1053 * RETURN = True if restacking has been done in the transient window tree.
1055 *************************************<->***********************************/
1057 Boolean PutTransientBelowSiblings (ClientData *pcd)
1059 ClientData *pcdLeader;
1060 ClientData *pcdNext;
1061 Boolean restack = False;
1064 pcdLeader = pcd->transientLeader;
1067 if (pcd->transientSiblings || (pcdLeader->transientChildren != pcd))
1070 if (pcdLeader->transientChildren == pcd)
1072 pcdLeader->transientChildren = pcd->transientSiblings;
1075 pcdNext = pcdLeader->transientChildren;
1076 while (pcdNext->transientSiblings)
1078 if (pcdNext->transientSiblings == pcd)
1080 pcdNext->transientSiblings = pcd->transientSiblings;
1084 pcdNext = pcdNext->transientSiblings;
1087 pcdNext->transientSiblings = pcd;
1089 pcd->transientSiblings = NULL;
1094 } /* END OF FUNCTION PutTransientBelowSiblings */
1098 /*************************************<->*************************************
1100 * RestackTransients (pcd)
1105 * This function restacks windows in a transient window tree. Secondary
1106 * (transient) windows are stacked on top of their associated primary
1107 * windows and the first secondary window in the transientSiblings list
1108 * is stacked on top of the second window in the list, etc.
1113 * pcd = pointer to client data of a window in a transient tree
1115 *************************************<->***********************************/
1117 void RestackTransients (ClientData *pcd)
1119 ClientData *pcdLeader;
1121 static int size = 0;
1122 static Window *windows = NULL;
1126 XWindowChanges windowChanges;
1131 * Build a restacking list and do the restacking.
1134 pcdLeader = FindTransientTreeLeader (pcd);
1135 count = CountTransientChildren (pcdLeader);
1137 /* No work to do if no transient children; count includes leader. */
1144 * Expand the (static) windows buffer that is used in restacking.
1148 (Window *)WmMalloc ((char*)windows, (count + 5) * sizeof (Window))))
1150 /* cannot get memory space */
1158 MakeTransientFamilyStackingList (windows, pcdLeader);
1160 nextWindow = MakeTransientWindowList (windows, pcdLeader);
1161 *nextWindow = pcdLeader->clientFrameWin;
1165 * Changes for CDExc19397.
1166 * XRestackWindows may move pcdLeader; that messes up the
1167 * global window stack. Call XConfigureWindow() instead,
1168 * and don't change location of pcdLeader.
1170 for (leaderIndex = 0; leaderIndex < count; leaderIndex++)
1172 if (windows[leaderIndex] == pcdLeader->clientFrameWin)
1175 if (leaderIndex >= count) /* ? Couldn't find leader; should NOT happen. */
1176 leaderIndex = count - 1;
1178 windowChanges.stack_mode = Above;
1179 for (i = leaderIndex; i > 0; i--)
1181 windowChanges.sibling = windows[i];
1182 XConfigureWindow (DISPLAY, windows[i - 1],
1183 CWSibling | CWStackMode, &windowChanges);
1186 windowChanges.stack_mode = Below;
1187 for (i = leaderIndex; i < count - 1; i++)
1189 windowChanges.sibling = windows[i];
1190 XConfigureWindow (DISPLAY, windows[i + 1],
1191 CWSibling | CWStackMode, &windowChanges);
1194 } /* END OF FUNCTION RestackTransients */
1198 /*************************************<->*************************************
1200 * RestackTransientsAtWindow (pcd)
1205 * This function restacks windows in a transient window tree. The
1206 * "anchor point" in the stack for the transient window tree is the
1212 * pcd = pointer to client data of a window in a transient tree
1214 *************************************<->***********************************/
1216 void RestackTransientsAtWindow (ClientData *pcd)
1218 ClientData *pcdLeader;
1219 XWindowChanges windowChanges;
1221 pcdLeader = FindTransientTreeLeader (pcd);
1222 if (pcdLeader && (pcdLeader != pcd))
1224 windowChanges.sibling = pcd->clientFrameWin;
1225 windowChanges.stack_mode = Below;
1226 XConfigureWindow (DISPLAY, pcdLeader->clientFrameWin,
1227 CWSibling | CWStackMode, &windowChanges);
1230 RestackTransients (pcd);
1232 } /* END OF FUNCTION RestackTransientsAtWindow */
1236 /*************************************<->*************************************
1238 * FindTransientTreeLeader (pcd)
1243 * This function identifies the leader of the transient tree that
1244 * contains the specified client.
1249 * pcd = pointer to client data of a window in a transient tree.
1253 * RETURN = pointer to the client data for the transient tree leader.
1255 *************************************<->***********************************/
1257 ClientData * FindTransientTreeLeader (ClientData *pcd)
1262 * Find the head of the transient window tree.
1265 while (pcd->transientLeader)
1267 pcd = pcd->transientLeader;
1272 } /* END OF FUNCTION FindTransientTreeLeader */
1276 /*************************************<->*************************************
1278 * CountTransientChildren (pcd)
1283 * This function returns a count of the number of children in the
1284 * transient window tree headed by the specified client window.
1289 * pcd = pointer to client data of a window in a transient tree
1293 * RETURN = count of transient windows in the transient window tree
1295 *************************************<->***********************************/
1298 CountTransientChildren (ClientData *pcd)
1301 ClientData *pcdNext;
1305 pcdNext = pcd->transientChildren;
1308 if (pcdNext->transientChildren)
1310 count += CountTransientChildren (pcdNext);
1316 pcdNext = pcdNext->transientSiblings;
1321 } /* END OF FUNCTION CountTransientChildren */
1325 /*************************************<->*************************************
1327 * MakeTransientWindowList (windows, pcd)
1332 * This function makes a transient window list of windows in the
1333 * transient window tree headed by the specified client. This list is
1334 * to be passed to XRestackWindows.
1339 * windows = pointer to the windows list to be filled out
1341 * pcd = pointer to client data of a window in a transient tree
1345 * RETURN = pointer to the next entry in the windows list
1347 *************************************<->***********************************/
1349 Window * MakeTransientWindowList (Window *windows, ClientData *pcd)
1352 ClientData *pcdNext;
1355 pcdNext = pcd->transientChildren;
1358 if (pcdNext->transientChildren)
1360 windows = MakeTransientWindowList (windows, pcdNext);
1362 *windows = pcdNext->clientFrameWin;
1364 pcdNext = pcdNext->transientSiblings;
1370 } /* END OF FUNCTION MakeTransientWindowList */
1374 /*************************************<->*************************************
1376 * FindTransientFocus (pcd)
1381 * This function identifies a window in the transient tree that is headed
1382 * by the specified client that can accept the keyboard input. The
1383 * effect of application modal windows is taken into account.
1388 * pcd = pointer to client data of a window in a transient tree.
1392 * RETURN = pointer to the client data for a window that can accept the
1393 * keyboard input focus.
1395 *************************************<->***********************************/
1397 ClientData * FindTransientFocus (ClientData *pcd)
1401 ClientData *pcdFocus;
1404 * Find a window that does not have an application modal subordinate.
1405 * First, search descendents
1409 while (pcdFocus->transientChildren && IS_APP_MODALIZED(pcdFocus))
1411 pcdFocus = pcdFocus->transientChildren;
1415 * If (search of descendents FAILS) then search siblings.
1418 if (IS_APP_MODALIZED(pcdFocus))
1420 ClientData *pcdSibling;
1423 while (pcdFocus && IS_APP_MODALIZED(pcdFocus))
1425 pcdSibling = pcdFocus;
1426 while (pcdSibling->transientSiblings && IS_APP_MODALIZED(pcdFocus))
1428 pcdSibling = pcdSibling->transientSiblings;
1430 if (IS_APP_MODALIZED(pcdSibling))
1432 pcdFocus = pcdFocus->transientChildren;
1436 pcdFocus = pcdSibling;
1442 return (pcdFocus ? pcdFocus : wmGD.keyboardFocus);
1444 } /* END OF FUNCTION FindTransientFocus */
1448 /*************************************<->*************************************
1450 * FindTransientOnTop (pcd)
1455 * This function identifies the top-most transient window in the
1456 * transient window tree that contains the specified client.
1461 * pcd = pointer to client data of a window in a transient tree.
1465 * RETURN = pointer to the client data for the top-most transient window.
1467 *************************************<->***********************************/
1469 ClientData * FindTransientOnTop (ClientData *pcd)
1474 * Find the head of the transient window tree.
1477 pcd = FindTransientTreeLeader (pcd);
1479 if (!(pcd->secondariesOnTop) &&
1480 (LeaderOnTop (pcd)))
1484 if (LeaderOnTop (pcd))
1486 /* The primary window is on top! */
1491 pcdSub = FindSubLeaderToTop (pcd);
1500 * Find the top-most transient window (the window in the transient tree
1501 * that is highest in the window stack).
1504 while (pcd->transientChildren)
1506 pcd = pcd->transientChildren;
1511 } /* END OF FUNCTION FindTransientOnTop */
1515 /*************************************<->*************************************
1517 * StackWindow (pWS, pEntry, onTop, pStackEntry)
1522 * This function stacks a window of a particular type (normal or icon)
1523 * to the top or botton of the window stack on the screen.
1528 * pWS = pointer to workspace data
1530 * pEntry = pointer to the client list entry for the window to be restacked.
1532 * onTop = if True then the window is to be restacked on top of the
1533 * specified stack window (if the stack window is not specified then
1534 * the entry is added to the top of the window stack)
1535 * otherwise the window is stacked below the specified stack window
1536 * (or at the bottom of the window stack if the stack window is not
1539 * pStackEntry = pointer to a client list entry for a window in the window
1540 * stack that is to be used as a reference in restacking.
1542 *************************************<->***********************************/
1544 void StackWindow (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
1547 Boolean stackTransientTreeWindows = False;
1548 Window activeIconWindow;
1550 XWindowChanges changes;
1551 WmScreenData *pSD = pWS->pSD;
1556 if (pStackEntry->type == MINIMIZED_STATE)
1558 stackWindow = ICON_FRAME_WIN(pStackEntry->pCD);
1562 stackWindow = pStackEntry->pCD->clientFrameWin;
1567 stackWindow = (Window)0;
1570 if (pEntry->type == MINIMIZED_STATE)
1572 window = ICON_FRAME_WIN(pEntry->pCD);
1577 * Restack the transient tree if appropriate.
1580 if (pEntry->pCD->transientLeader || pEntry->pCD->transientChildren)
1582 stackTransientTreeWindows = True;
1584 window = (FindTransientOnTop (pEntry->pCD))->clientFrameWin;
1588 window = pEntry->pCD->clientFrameWin;
1594 * The active icon text label must be restacked along with the associated
1598 if ((pEntry->type == MINIMIZED_STATE) &&
1599 (pEntry->pCD == wmGD.keyboardFocus) &&
1600 (ICON_DECORATION(pEntry->pCD) & ICON_ACTIVE_LABEL_PART) &&
1601 (ACTIVE_ICON_TEXT_WIN))
1603 activeIconWindow = ACTIVE_ICON_TEXT_WIN;
1607 activeIconWindow = (Window)0;
1612 if ((stackWindow == 0) && (pSD->clientList))
1614 if (pSD->clientList->type == MINIMIZED_STATE)
1616 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
1620 if (pSD->clientList->pCD->transientChildren)
1623 (FindTransientOnTop(pSD->clientList->pCD))->clientFrameWin;
1627 stackWindow = pSD->clientList->pCD->clientFrameWin;
1632 if (activeIconWindow)
1634 changes.sibling = stackWindow;
1635 changes.stack_mode = Above;
1636 XConfigureWindow (DISPLAY, activeIconWindow,
1637 (CWSibling | CWStackMode), &changes);
1638 changes.sibling = activeIconWindow;
1639 changes.stack_mode = Below;
1640 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1645 changes.sibling = stackWindow;
1646 changes.stack_mode = Above;
1647 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1649 if (stackTransientTreeWindows)
1651 /* make sure that the leader is in the correct spot */
1652 changes.sibling = window;
1653 changes.stack_mode = Below;
1654 XConfigureWindow (DISPLAY, pEntry->pCD->clientFrameWin,
1655 (CWSibling | CWStackMode), &changes);
1656 RestackTransients (pEntry->pCD);
1664 * Adjust stack entry window if we're stacking below a
1667 if (pStackEntry && pStackEntry->pCD->transientChildren)
1669 stackWindow = LowestWindowInTransientFamily (pStackEntry->pCD);
1673 if (stackWindow == 0)
1675 if (pSD->lastClient->type == MINIMIZED_STATE)
1677 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
1682 if (pSD->lastClient->pCD->transientChildren)
1685 LowestWindowInTransientFamily (pSD->lastClient->pCD);
1689 stackWindow = pSD->lastClient->pCD->clientFrameWin;
1693 if (activeIconWindow)
1695 changes.sibling = stackWindow;
1696 changes.stack_mode = Below;
1697 XConfigureWindow (DISPLAY, activeIconWindow,
1698 (CWSibling | CWStackMode), &changes);
1699 changes.sibling = activeIconWindow;
1700 changes.stack_mode = Below;
1701 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1706 changes.sibling = stackWindow;
1707 changes.stack_mode = Below;
1708 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1710 if (stackTransientTreeWindows)
1712 /* make sure that the leader is in the correct spot */
1713 changes.sibling = window;
1714 changes.stack_mode = Below;
1715 XConfigureWindow (DISPLAY, pEntry->pCD->clientFrameWin,
1716 (CWSibling | CWStackMode), &changes);
1717 RestackTransients (pEntry->pCD);
1722 } /* END OF FUNCTION StackWindow */
1726 /*************************************<->*************************************
1728 * StackTransientWindow (pcd)
1733 * This function stacks a transient window within its transient window
1734 * tree on the screen. The transient window tree should indicate the
1735 * intended stacking position.
1740 * pcd = pointer to client data of a window in a transient tree
1742 *************************************<->***********************************/
1744 void StackTransientWindow (ClientData *pcd)
1746 XWindowChanges changes;
1747 ClientData *pcdPrev;
1750 if (pcd->transientLeader->transientChildren == pcd)
1752 if (pcd->transientSiblings)
1754 changes.sibling = pcd->transientSiblings->clientFrameWin;
1758 changes.sibling = pcd->transientLeader->clientFrameWin;
1760 changes.stack_mode = Above;
1764 pcdPrev = pcd->transientLeader;
1765 while (pcdPrev->transientSiblings != pcd)
1767 pcdPrev = pcdPrev->transientSiblings;
1769 changes.sibling = pcdPrev->clientFrameWin;
1770 changes.stack_mode = Below;
1773 XConfigureWindow (DISPLAY, pcd->clientFrameWin, (CWSibling | CWStackMode),
1777 } /* END OF FUNCTION StackTransientWindow */
1781 /*************************************<->*************************************
1783 * CheckIfClientObscuring (pcdTop, pcd)
1788 * This function determines whether a window or a transient window tree
1789 * is obscuring (at least partially) a window or a transient window tree
1790 * that is below it in the window stack.
1795 * pcdTop = pointer to client data for a window (it may be the leader of
1796 * a transient tree; this window is the higher in the window stack
1797 * than the window it is be checked against.
1799 * pcd = pointer to client data for a window (it may be the leader of
1805 * RETURN = True if the top window(s) overlap the lower window(s)
1807 *************************************<->***********************************/
1809 Boolean CheckIfClientObscuring (ClientData *pcdTop, ClientData *pcd)
1811 Boolean obscuring = False;
1812 ClientData *pcdNext;
1816 * Check only if the top window is visible onscreen.
1819 if (pcdTop->transientChildren && (pcdTop->clientState != MINIMIZED_STATE))
1821 pcdNext = pcdTop->transientChildren;
1822 while (pcdNext && !obscuring)
1824 obscuring = CheckIfClientObscuring (pcdNext, pcd);
1825 pcdNext = pcdNext->transientSiblings;
1829 if (!obscuring && pcd->transientChildren &&
1830 (pcd->clientState != MINIMIZED_STATE))
1832 pcdNext = pcd->transientChildren;
1833 while (pcdNext && !obscuring)
1835 obscuring = CheckIfClientObscuring (pcdTop, pcdNext);
1836 pcdNext = pcdNext->transientSiblings;
1842 obscuring = CheckIfObscuring (pcdTop, pcd);
1847 } /* END OF FUNCTION CheckIfClientObscuring */
1851 /*************************************<->*************************************
1853 * CheckIfObscuring (pcdA, pcdB)
1858 * This function determines whether a window (not a transient tree)
1859 * is obscuring (at least partially) a window (not a transient tree)
1860 * that is below it in the window stack.
1865 * pcdA = pointer to client data for a window; this window is higher in
1866 * the window stack than the window it is be checked against.
1868 * pcdB = pointer to client data for a window.
1873 * RETURN = True if the top window overlaps the lower window
1875 *************************************<->***********************************/
1877 Boolean CheckIfObscuring (ClientData *pcdA, ClientData *pcdB)
1879 Boolean obscuring = False;
1891 * For workspace stuff: if either is unseen, then neither
1894 if ((pcdA->clientState & UNSEEN_STATE) ||
1895 (pcdB->clientState & UNSEEN_STATE))
1901 if (pcdA->clientState == NORMAL_STATE)
1903 aX1 = pcdA->clientX - pcdA->clientOffset.x;
1904 aY1 = pcdA->clientY - pcdA->clientOffset.y;
1905 aX2 = aX1 + pcdA->clientWidth + (2 * pcdA->clientOffset.x) - 1;
1906 aY2 = aY1 + pcdA->clientHeight + pcdA->clientOffset.y +
1907 pcdA->clientOffset.x - 1;
1909 else if (pcdA->clientState == MINIMIZED_STATE)
1913 aX2 = aX1 + ICON_WIDTH(pcdA) - 1;
1914 aY2 = aY1 + ICON_HEIGHT(pcdA) - 1;
1916 else /* (pcdA->clientState == MAXIMIZED_STATE) */
1918 aX1 = pcdA->maxX - pcdA->clientOffset.x;
1919 aY1 = pcdA->maxY - pcdA->clientOffset.y;
1920 aX2 = aX1 + pcdA->maxWidth + (2 * pcdA->clientOffset.x) - 1;
1921 aY2 = aY1 + pcdA->maxHeight + pcdA->clientOffset.y +
1922 pcdA->clientOffset.x - 1;
1925 if (pcdB->clientState == NORMAL_STATE)
1927 bX1 = pcdB->clientX - pcdB->clientOffset.x;
1928 bY1 = pcdB->clientY - pcdB->clientOffset.y;
1929 bX2 = bX1 + pcdB->clientWidth + (2 * pcdB->clientOffset.x) - 1;
1930 bY2 = bY1 + pcdB->clientHeight + pcdB->clientOffset.y +
1931 pcdB->clientOffset.x - 1;
1933 else if (pcdB->clientState == MINIMIZED_STATE)
1937 bX2 = bX1 + ICON_WIDTH(pcdB) - 1;
1938 bY2 = bY1 + ICON_HEIGHT(pcdB) - 1;
1940 else /* (pcdB->clientState == MAXIMIZED_STATE) */
1942 bX1 = pcdB->maxX - pcdB->clientOffset.x;
1943 bY1 = pcdB->maxY - pcdB->clientOffset.y;
1944 bX2 = bX1 + pcdB->maxWidth + (2 * pcdB->clientOffset.x) - 1;
1945 bY2 = bY1 + pcdB->maxHeight + pcdB->clientOffset.y +
1946 pcdB->clientOffset.x - 1;
1950 * Check if there is overlap in both dimensions.
1953 if (((aX1 >= bX1) && (aX1 <= bX2)) || ((aX2 >= bX1) && (aX2 <= bX2)) ||
1954 ((bX1 >= aX1) && (bX1 <= aX2)) || ((bX2 >= aX1) && (bX2 <= aX2)))
1956 if (((aY1 >= bY1) && (aY1 <= bY2)) || ((aY2 >= bY1) && (aY2 <= bY2)) ||
1957 ((bY1 >= aY1) && (bY1 <= aY2)) || ((bY2 >= aY1) && (bY2 <= aY2)))
1966 } /* END OF FUNCTION CheckIfObscuring */
1970 /*************************************<->*************************************
1972 * CheckIfClientObscuredByAny (pcd)
1977 * This function determines whether a window or a transient window tree
1978 * is obscured (at least partially) by any other window.
1983 * pcd = pointer to client data for a window (it may be the leader of
1989 * RETURN = True if the window(s) are overlapped.
1991 *************************************<->***********************************/
1993 Boolean CheckIfClientObscuredByAny (ClientData *pcd)
1995 Boolean obscured = False;
1996 ClientListEntry *pListEntry;
1999 pListEntry = ACTIVE_PSD->clientList;
2000 while (pListEntry && !obscured)
2002 if (pListEntry->pCD == pcd)
2004 if (((pListEntry->type == MINIMIZED_STATE) &&
2005 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2006 ((pListEntry->type != MINIMIZED_STATE) &&
2007 (pListEntry->pCD->clientState != MINIMIZED_STATE)))
2012 else if (((pListEntry->type == MINIMIZED_STATE) &&
2013 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2014 ((pListEntry->type != MINIMIZED_STATE) &&
2015 (pListEntry->pCD->clientState != MINIMIZED_STATE)))
2018 * The window for the entry is visible on screen. See if it
2019 * obscures the indicated window.
2022 obscured = CheckIfClientObscuring (pListEntry->pCD, pcd);
2027 pListEntry = pListEntry->nextSibling;
2033 } /* END OF FUNCTION CheckIfClientObscuredByAny */
2037 /*************************************<->*************************************
2039 * CheckIfClientObscuringAny (pcd)
2044 * This function determines whether a window or a transient window tree
2045 * is obscuring another window.
2050 * pcd = pointer to client data for a window (it may be the leader of
2056 * RETURN = True if the window(s) overlaps anther window.
2058 *************************************<->***********************************/
2060 Boolean CheckIfClientObscuringAny (ClientData *pcd)
2062 Boolean obscuring = False;
2063 ClientListEntry *pListEntry;
2066 pListEntry = (pcd->clientState == MINIMIZED_STATE) ?
2067 &pcd->iconEntry : &pcd->clientEntry;
2068 while (pListEntry && !obscuring)
2070 if ((pListEntry->pCD != pcd) &&
2071 (((pListEntry->type == MINIMIZED_STATE) &&
2072 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2073 ((pListEntry->type != MINIMIZED_STATE) &&
2074 (pListEntry->pCD->clientState != MINIMIZED_STATE))))
2076 obscuring = CheckIfClientObscuring (pcd, pListEntry->pCD);
2079 pListEntry = pListEntry->nextSibling;
2084 } /* END OF FUNCTION CheckIfClientObscuringAny */
2088 /*************************************<->*************************************
2090 * SetupSystemModalState (pCD)
2095 * This function prepares for mapping a system modal window. An input
2096 * screen window is mapped below the system modal window to prevent input
2097 * to the windows not related to the system modal window.
2102 * pCD = pointer to client data for the system modal window; if NULL the
2103 * system modal window is a special window manager dialog box
2108 * wmGD = changes to system modal state data
2110 *************************************<->***********************************/
2112 void SetupSystemModalState (ClientData *pCD)
2114 XWindowChanges windowChanges;
2115 unsigned int width, height;
2116 unsigned int x_hot, y_hot;
2117 unsigned char *bits;
2118 unsigned char *mask_bits;
2123 * If we've got a menu active, then unpost it first
2124 * so that grabs from the menu don't interfere with
2125 * the system modal dialog. We want to avoid lock-ups.
2127 if (wmGD.menuActive != NULL)
2129 UnpostMenu (wmGD.menuActive);
2130 XSync (DISPLAY, False);
2134 * Try to grab the pointer and keyboard. If either
2135 * fails because event processing is frozen by another grab, then
2136 * don't do system modal for fear of leaving the system unusable.
2138 if (XGrabPointer(DISPLAY,
2139 ROOT_FOR_CLIENT(pCD),
2140 FALSE, /* owner_events */
2141 (unsigned int) 0, /* event mask */
2142 GrabModeAsync, /* pointer_mode */
2143 GrabModeAsync, /* keyboard_mode */
2144 None, /* confine_to window */
2146 CurrentTime) == GrabFrozen)
2152 XUngrabPointer (DISPLAY, CurrentTime);
2155 if (XGrabKeyboard(DISPLAY,
2156 ROOT_FOR_CLIENT(pCD),
2157 FALSE, /* owner_events */
2158 GrabModeAsync, /* pointer_mode */
2159 GrabModeAsync, /* keyboard_mode */
2160 CurrentTime) == GrabFrozen)
2166 XUngrabKeyboard (DISPLAY, CurrentTime);
2171 if (wmGD.useLargeCursors)
2173 width = noenter32_width;
2174 height = noenter32_height;
2175 x_hot = noenter32_x_hot;
2176 y_hot = noenter32_y_hot;
2177 bits = noenter32_bits;
2178 mask_bits = noenter32m_bits;
2182 #endif /* LARGECURSORS */
2185 width = noenter16_width;
2186 height = noenter16_height;
2187 x_hot = noenter16_x_hot;
2188 y_hot = noenter16_y_hot;
2189 bits = noenter16_bits;
2190 mask_bits = noenter16m_bits;
2193 for (scr=0; scr<wmGD.numScreens; scr++)
2195 pSD = &(wmGD.Screens[scr]);
2198 * Make the system modal input screen window if necessary.
2201 if (pSD->managed && pSD->inputScreenWindow == 0)
2203 XSetWindowAttributes windowAttributes;
2208 windowAttributes.event_mask = ButtonPressMask;
2209 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
2211 windowAttributes.event_mask |= EnterWindowMask;
2213 windowAttributes.override_redirect = True;
2215 pixmap = XCreateBitmapFromData (DISPLAY, pSD->rootWindow,
2216 (char *)bits, width, height);
2218 maskPixmap = XCreateBitmapFromData (DISPLAY, pSD->rootWindow,
2219 (char *)mask_bits, width, height);
2221 xcolors[0].pixel = BlackPixel (DISPLAY, pSD->screen);
2222 xcolors[1].pixel = WhitePixel (DISPLAY, pSD->screen);
2223 XQueryColors (DISPLAY, DefaultColormap (DISPLAY, pSD->screen),
2225 windowAttributes.cursor =
2226 XCreatePixmapCursor (DISPLAY, pixmap, maskPixmap,
2227 &(xcolors[0]), &(xcolors[1]),
2229 XFreePixmap (DISPLAY, pixmap);
2230 XFreePixmap (DISPLAY, maskPixmap);
2232 pSD->inputScreenWindow =
2233 XCreateWindow (DISPLAY, pSD->rootWindow, 0, 0,
2234 DisplayWidth (DISPLAY, pSD->screen),
2235 DisplayHeight (DISPLAY, pSD->screen),
2240 CWEventMask | CWOverrideRedirect | CWCursor,
2243 if (pSD->managed && pSD != ACTIVE_PSD)
2245 XMapRaised (DISPLAY, pSD->inputScreenWindow);
2251 wmGD.systemModalWindow = pCD->clientFrameWin;
2256 * ELSE: the system modal window is a special window manager dialog
2257 * box and wmGD.systemModalWindow is set prior to the call to
2258 * SetupSystemModalState. Set the focus to the special window manager
2262 SetKeyboardFocus (NULL, REFRESH_LAST_FOCUS);
2263 XSetInputFocus (DISPLAY, wmGD.systemModalWindow, RevertToPointerRoot,
2269 * Map the system modal input screen window below the system modal
2273 windowChanges.sibling = wmGD.systemModalWindow;
2274 windowChanges.stack_mode = Below;
2275 XConfigureWindow (DISPLAY, ACTIVE_PSD->inputScreenWindow,
2276 CWSibling | CWStackMode, &windowChanges);
2278 XMapWindow (DISPLAY, ACTIVE_PSD->inputScreenWindow);
2282 * Setup the system modal global data.
2285 wmGD.systemModalActive = True;
2286 wmGD.systemModalClient = pCD;
2289 } /* END OF FUNCTION SetupSystemModalState */
2293 /*************************************<->*************************************
2295 * UndoSystemModalState ()
2300 * This function cleans up after a system modal window goes away.
2305 * wmGD = (system modal state data)
2310 * wmGD = changes to system modal state data
2312 *************************************<->***********************************/
2314 void UndoSystemModalState (void)
2319 * Unmap the system modal input screen window.
2322 for (scr = 0; scr < wmGD.numScreens; scr++)
2324 if(wmGD.Screens[scr].managed)
2326 XUnmapWindow (DISPLAY, wmGD.Screens[scr].inputScreenWindow);
2331 * Reset the focus if a window manager system modal dialog box was
2335 if (!wmGD.systemModalClient)
2337 AutoResetKeyFocus (NULL, GetTimestamp());
2342 * Reset the system modal global data.
2345 wmGD.systemModalActive = False;
2346 wmGD.systemModalClient = NULL;
2347 wmGD.systemModalWindow = 0;
2349 } /* END OF FUNCTION UndoSystemModalState */
2353 /*************************************<->*************************************
2355 * FindClientNameMatch (pStartingEntry, toNext, clientName, types)
2360 * This function searches for a client that has a particular name or class.
2361 * A match will be indicated if the client with the name or class also
2362 * is in a particular state.
2367 * pEntry = pointer to the client list entry where the search is
2370 * toNext = if True then search client list from first to last; otherwise
2371 * search the client list last to first.
2373 * clientName = string that indicates a client name or class.
2375 * type = types of objects (icon, window, ...) that are to be matched.
2380 * RETURN = pointer to client list entry for matched client.
2382 *************************************<->***********************************/
2383 ClientListEntry * FindClientNameMatch (ClientListEntry *pEntry,
2386 unsigned long types)
2389 Boolean foundMatch = False;
2394 while (!foundMatch && pEntry)
2398 if (pEntry->type == MINIMIZED_STATE)
2400 if ((pCD->clientState == MINIMIZED_STATE) &&
2401 (types & F_GROUP_ICON))
2408 if ((pCD->clientState != MINIMIZED_STATE) &&
2409 (types & F_GROUP_WINDOW))
2416 ((pCD->clientName && (strcmp (clientName,pCD->clientName) == 0)) ||
2417 (pCD->clientClass && (strcmp (clientName,pCD->clientClass) == 0))))
2423 pEntry = (toNext) ? pEntry->nextSibling : pEntry->prevSibling;
2429 } /* END OF FUNCTION FindClientNameMatch */
2432 /*************************************<->*************************************
2434 * BumpPrimaryToTop (pcdLeader)
2439 * This function moves the primary window to the "top" of the transient
2444 * pcdLeader = pointer to client data of transient tree root.
2446 * Returns: True if stacking order of leader window changed.
2447 * False if not stacking change.
2451 * This affects only the clientData structures. There is no immediate
2452 * effect on the actual stacking order on the display. That is done
2453 * by StackWindow and/or RestackTransients.
2455 *************************************<->***********************************/
2457 Boolean BumpPrimaryToTop (ClientData *pcdLeader)
2462 count = CountTransientChildren (pcdLeader);
2464 if (pcdLeader->primaryStackPosition != (count-1))
2466 pcdLeader->primaryStackPosition = count - 1;
2477 /*************************************<->*************************************
2479 * BumpPrimaryToBottom (pcdLeader)
2484 * This function moves the primary window to the "bottom" of the transient
2489 * pcdLeader = pointer to client data of transient tree root.
2491 * Returns: True if stacking order of leader window changed.
2492 * False if not stacking change.
2496 * This affects only the clientData structures. There is no immediate
2497 * effect on the actual stacking order on the display. That is done
2498 * by StackWindow and/or RestackTransients.
2500 *************************************<->***********************************/
2502 Boolean BumpPrimaryToBottom (ClientData *pcdLeader)
2506 if (pcdLeader->primaryStackPosition != 0)
2508 pcdLeader->primaryStackPosition = 0;
2520 /*************************************<->*************************************
2522 * LowestWindowInTransientFamily (pcdLeader)
2527 * This function returns the lowest stacked window in a transient
2532 * pcdLeader = pointer to client data of leader of a transient tree
2534 * Returns: id of lowest window in the transient tree for this family
2536 *************************************<->***********************************/
2539 LowestWindowInTransientFamily (ClientData *pcdLeader)
2542 static int size = 0;
2543 static Window *windows = NULL;
2544 Window wReturn = None;
2547 * Build a window list
2549 count = CountTransientChildren (pcdLeader);
2554 * Expand the (static) windows buffer
2558 (Window *)WmMalloc ((char*)windows, (count + 5) * sizeof (Window))))
2560 /* cannot get memory space */
2567 MakeTransientFamilyStackingList (windows, pcdLeader);
2571 wReturn = windows[count-1];
2580 } /* END OF FUNCTION LowestWindowInTransientFamily */
2583 /*************************************<->*************************************
2585 * FindSubLeaderToTop (pcd)
2590 * This function identifies a candidate window to top within the
2591 * transient tree that is a local transient leader (the window has
2592 * transients hanging off of it, too).
2597 * pcd = pointer to client data of a transient leader window
2599 * Return: ptr to client data for client that should be topped, or NULL
2605 *************************************<->***********************************/
2608 FindSubLeaderToTop (
2612 ClientData *pcdRet = NULL;
2613 ClientData *pcdNext;
2615 pcdNext = pcd->transientChildren;
2616 while (pcdNext && (!pcdRet))
2618 if (pcdNext->transientChildren)
2620 if (LeaderOnTop (pcdNext))
2626 pcdRet = FindSubLeaderToTop (pcdNext);
2629 pcdNext = pcdNext->transientSiblings;
2636 /*************************************<->*************************************
2638 * MakeTransientFamilyStackingList (windows, pcdLeader)
2643 * This function makes a transient window list of windows in the
2644 * transient window tree headed by the specified client.
2649 * windows = pointer to the windows list to be filled out
2651 * pcdLeader = pointer to client data of a window in a transient tree
2655 * The windows array is modified.
2659 * This function puts the transient leader window in the list in the
2662 *************************************<->***********************************/
2665 MakeTransientFamilyStackingList (
2667 ClientData *pcdLeader)
2670 ClientData *pcdNext, *pcdSub;
2671 Window *nextWindow, wSave, wTemp, wTop;
2672 int count = CountTransientChildren (pcdLeader);
2676 * Construct the transient stacking list according to
2677 * normal Motif rules.
2679 nextWindow = MakeTransientWindowList (windows, pcdLeader);
2681 if (!(pcdLeader->secondariesOnTop))
2684 * If the leader window shouldn't be on the bottom , then
2685 * adjust the stacking of the list.
2687 if ((pcdLeader->primaryStackPosition > 0) &&
2688 (pcdLeader->primaryStackPosition < count))
2690 for (i=0; i<pcdLeader->primaryStackPosition; i++)
2693 windows[j] = windows[j-1];
2695 j = count - pcdLeader->primaryStackPosition - 1;
2696 windows[j] = pcdLeader->clientFrameWin;
2701 * Put the leader at the bottom.
2703 *nextWindow = pcdLeader->clientFrameWin;
2706 * If one of the transients is also a local leader
2707 * and wants to be on top, then adjust the list.
2709 pcdSub = FindSubLeaderToTop (pcdLeader);
2710 if (pcdSub && (pcdSub->clientFrameWin != None))
2712 /* insert this window at top */
2713 wTop = wSave = pcdSub->clientFrameWin;
2715 /* shuffle the rest down */
2716 for (i=0; i<count; i++)
2731 * Put the leader at the bottom.
2733 *nextWindow = pcdLeader->clientFrameWin;
2736 } /* END OF FUNCTION MakeTransientFamilyStackingList */
2739 /*************************************<->*************************************
2741 * NormalizeTransientTreeStacking (pcdLeader)
2746 * This function traverses the transient tree and cleans up any
2747 * local primary windows that are above their respective secondary
2753 * pcdLeader = pointer to client data of a transient tree leader
2755 * Return: True if any changes in stacking order were made
2760 * This only touches the data structures.
2762 *************************************<->***********************************/
2765 NormalizeTransientTreeStacking (
2766 ClientData *pcdLeader)
2769 ClientData *pcdNext;
2770 Boolean bChanged = False;
2772 pcdNext = pcdLeader->transientChildren;
2773 bChanged = BumpPrimaryToBottom (pcdLeader);
2776 if (pcdNext->transientChildren)
2778 bChanged |= BumpPrimaryToBottom (pcdNext);
2780 bChanged |= NormalizeTransientTreeStacking (pcdNext);
2782 pcdNext = pcdNext->transientSiblings;
2788 /*************************************<->*************************************
2790 * LeaderOnTop (pcdLeader)
2795 * This function tests a leader of a transient (sub) tree to see if
2796 * it should be on top of its transient windows.
2801 * pcdLeader = pointer to client data of a transient tree leader
2803 * Return: True if this leader is on top of its transients
2809 *************************************<->***********************************/
2813 ClientData *pcdLeader)
2816 Boolean bOnTop = False;
2817 int count = CountTransientChildren (pcdLeader);
2819 if ((pcdLeader->primaryStackPosition > 0) &&
2820 (pcdLeader->primaryStackPosition < count))