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.
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"
58 #include "WmFunction.h"
59 #include "WmKeyFocus.h"
61 #include "WmResource.h"
62 #include "WmWinInfo.h"
64 #include "WmWrkspace.h"
75 /*************************************<->*************************************
77 * AddClientToList (pWS, pCD, onTop)
82 * This function adds a client window to the client window list. If it is
83 * a transient window then it is added to the transient window tree that
84 * contains its transient leader. The window stacking order is also
85 * maintained for the cases where there is a system modal window active
86 * or the window is a transient window. If a system modal window is being
87 * added then the system modal "input screen" window is setup.
92 * pCD = pointer to client data for the window to be added to the list
94 * pWS = pointer to workspace data
96 * onTop = if True then the window is displayed on top of the window
97 * stack and is added to the beginning of the window list, otherwise
98 * it is added to the end of the window list.
103 * pWS = (clientList, lastClient)
105 *************************************<->***********************************/
107 void AddClientToList (WmWorkspaceData *pWS, ClientData *pCD, Boolean onTop)
109 Boolean belowSystemModal = False;
110 XWindowChanges windowChanges;
111 WmScreenData *pSD = pWS->pSD;
113 WsClientData *pWsc = GetWsClientData (pWS, pCD);
117 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
120 * Set up the system modal input screen window just below the
121 * system modal window.
124 SetupSystemModalState (pCD);
126 if (!wmGD.systemModalActive || (wmGD.systemModalClient != pCD))
129 * If we failed to setup as system modal, then
130 * back off to MWM_INPUT_FULL_APPLICATION_MODAL.
131 * This will do *something* if this is a transient
134 pCD->inputMode = MWM_INPUT_FULL_APPLICATION_MODAL;
137 else if (wmGD.systemModalActive &&
138 ((FindTransientTreeLeader (pCD))->inputMode !=
139 MWM_INPUT_SYSTEM_MODAL))
142 * If a system modal window is active then place the window below
143 * the system modal input screen window if the window is not a
144 * descendant of the system modal window.
147 windowChanges.sibling = pSD->inputScreenWindow;
148 windowChanges.stack_mode = Below;
149 XConfigureWindow (DISPLAY, pCD->clientFrameWin,
150 CWSibling | CWStackMode, &windowChanges);
151 belowSystemModal = True;
154 if (pCD->transientLeader)
156 AddTransient (pWS, pCD);
160 pCD->clientEntry.type = NORMAL_STATE;
161 pCD->clientEntry.pCD = pCD;
163 if (belowSystemModal && wmGD.systemModalClient)
165 AddEntryToList (pWS, &pCD->clientEntry, False /*below*/,
170 AddEntryToList (pWS, &pCD->clientEntry, True /*on top*/, NULL);
174 AddEntryToList (pWS, &pCD->clientEntry, False /*on bottom*/, NULL);
179 if (!pWsc->pIconBox && pWsc->iconFrameWin)
181 if (!pCD->pIconBox && pCD->iconFrameWin)
185 * Put the icon on the bottom of the stack.
188 if (pSD->lastClient->type == MINIMIZED_STATE)
193 pWsib = &pSD->lastClient->pCD->pWsList[0];
194 windowChanges.sibling = pWsib->iconFrameWin;
196 windowChanges.sibling = pSD->lastClient->pCD->iconFrameWin;
201 windowChanges.sibling = pSD->lastClient->pCD->clientFrameWin;
203 windowChanges.stack_mode = Below;
205 XConfigureWindow (DISPLAY, pWsc->iconFrameWin,
206 CWSibling | CWStackMode, &windowChanges);
208 XConfigureWindow (DISPLAY, pCD->iconFrameWin,
209 CWSibling | CWStackMode, &windowChanges);
212 pCD->iconEntry.type = MINIMIZED_STATE;
213 pCD->iconEntry.pCD = pCD;
214 pCD->iconEntry.nextSibling = NULL;
215 pCD->iconEntry.prevSibling = pSD->lastClient;
216 pSD->lastClient->nextSibling = &pCD->iconEntry;
217 pSD->lastClient = &pCD->iconEntry;
221 } /* END OF FUNCTION AddClientToList */
225 /*************************************<->*************************************
227 * AddEntryToList (pWS, pEntry, onTop, pStackEntry)
232 * This function adds a client list entry to the client window list.
233 * This is usually done as part of the process of changing the ordering
234 * of the window list.
239 * pWS = pointer to workspace data
240 * pEntry = pointer to a client list entry to be added to the client list
242 * onTop = if True then the client list entry is added on top of the
243 * specified client list stack entry (if the stack entry is not
244 * specified then the entry is added to the front of the list);
245 * otherwise the entry is added after the specified stacking entry
246 * (or to the end of the list if the stacking entry is not specified).
248 * pStackEntry = pointer to a client list entry to be used as a reference
249 * in adding an entry to the client list.
253 * pWS = (clientList, lastClient)
255 *************************************<->***********************************/
257 void AddEntryToList (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
259 WmScreenData *pSD = pWS->pSD;
265 if (pEntry != pStackEntry)
267 pEntry->nextSibling = pStackEntry;
268 pEntry->prevSibling = pStackEntry->prevSibling;
269 pStackEntry->prevSibling = pEntry;
270 if (pEntry->prevSibling)
272 pEntry->prevSibling->nextSibling = pEntry;
276 pSD->clientList = pEntry;
282 if (pSD->clientList != pEntry)
284 pEntry->nextSibling = pSD->clientList;
285 pEntry->prevSibling = NULL;
288 pSD->clientList->prevSibling = pEntry;
292 pSD->lastClient = pEntry;
294 pSD->clientList = pEntry;
302 if (pEntry != pStackEntry)
304 pEntry->nextSibling = pStackEntry->nextSibling;
305 pEntry->prevSibling = pStackEntry;
306 pStackEntry->nextSibling = pEntry;
307 if (pEntry->nextSibling)
309 pEntry->nextSibling->prevSibling = pEntry;
313 pSD->lastClient = pEntry;
319 if (pSD->lastClient != pEntry)
321 pEntry->nextSibling = NULL;
322 pEntry->prevSibling = pSD->lastClient;
325 pSD->lastClient->nextSibling = pEntry;
329 pSD->clientList = pEntry;
331 pSD->lastClient = pEntry;
336 } /* END OF FUNCTION AddEntryToList */
340 /*************************************<->*************************************
342 * MoveEntryInList (pWS, pEntry, onTop, pStackEntry)
347 * This function moves a client list entry in the client window list.
352 * pWS = pointer to workspace data
354 * pEntry = pointer to a client list entry to be moved in the client list
356 * onTop = if True then the client list entry is moved on top of the
357 * specified client list stack entry (if the stack entry is not
358 * specified then the entry is moved to the front of the list);
359 * otherwise the entry is moved after the specified stacking entry
360 * (or to the end of the list if the stacking entry is not specified).
362 * pStackEntry = pointer to a client list entry to be used as a reference
363 * in moving an entry in the client list.
367 * pWS = (clientList, lastClient)
369 *************************************<->***********************************/
371 void MoveEntryInList (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
373 DeleteEntryFromList (pWS, pEntry);
374 AddEntryToList (pWS, pEntry, onTop, pStackEntry);
376 } /* END OF FUNCTION MoveEntryInList */
380 /*************************************<->*************************************
382 * DeleteEntryFromList (pWS, pListEntry)
387 * This function deletes a client list entry from the client window list.
388 * This is usually done as part of the process of changing the ordering
389 * of the window list.
394 * pWS = pointer to workspace data
395 * listEntry = pointer to a client list entry
399 * pWS = (clientList, lastClient)
401 *************************************<->***********************************/
403 void DeleteEntryFromList (WmWorkspaceData *pWS, ClientListEntry *pListEntry)
406 if (pListEntry->prevSibling)
408 pListEntry->prevSibling->nextSibling = pListEntry->nextSibling;
412 pWS->pSD->clientList = pListEntry->nextSibling;
415 if (pListEntry->nextSibling)
417 pListEntry->nextSibling->prevSibling = pListEntry->prevSibling;
421 pWS->pSD->lastClient = pListEntry->prevSibling;
424 } /* END OF FUNCTION DeleteEntryFromList */
428 /*************************************<->*************************************
430 * DeleteClientFromList (pWS, pCD)
435 * This function deletes a client from the client window list. If this is
436 * a transient window then it is deleted from its transient window tree.
437 * If this is a system modal window then clean up the system modal state.
442 * pCD = pointer to client data for the window to be added to the list
446 * pWS = (clientList, lastClient)
448 *************************************<->***********************************/
450 void DeleteClientFromList (WmWorkspaceData *pWS, ClientData *pCD)
453 WsClientData *pWsc = GetWsClientData (pWS, pCD);
455 WmScreenData *pSD = pWS->pSD;
457 if (pCD->transientLeader)
459 DeleteTransient (pCD);
464 * If this is a system modal window then clean up the system modal
468 if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
470 UndoSystemModalState ();
474 * Remove the client and icon entries from the window list.
478 if (!pWsc->pIconBox && pWsc->iconFrameWin)
480 if (!pCD->pIconBox && pCD->iconFrameWin)
483 if (pCD->iconEntry.prevSibling)
485 pCD->iconEntry.prevSibling->nextSibling =
486 pCD->iconEntry.nextSibling;
490 pSD->clientList = pCD->iconEntry.nextSibling;
492 if (pCD->iconEntry.nextSibling)
494 pCD->iconEntry.nextSibling->prevSibling =
495 pCD->iconEntry.prevSibling;
499 pSD->lastClient = pCD->iconEntry.prevSibling;
503 if (pCD->clientEntry.prevSibling)
505 pCD->clientEntry.prevSibling->nextSibling =
506 pCD->clientEntry.nextSibling;
510 pSD->clientList = pCD->clientEntry.nextSibling;
513 if (pCD->clientEntry.nextSibling)
515 pCD->clientEntry.nextSibling->prevSibling =
516 pCD->clientEntry.prevSibling;
520 pSD->lastClient = pCD->clientEntry.prevSibling;
524 } /* END OF FUNCTION DeleteClientFromList */
528 /*************************************<->*************************************
530 * AddTransient (pWS, pCD)
535 * This function adds the transient window to the lead window's list of
541 * pWS = pointer to workspace data
542 * pCD = pointer to client data of a transient window
547 * pCD->transientLeader = (transientChildren, modalCount)
549 *************************************<->***********************************/
551 void AddTransient (WmWorkspaceData *pWS, ClientData *pCD)
553 ClientData *pcdLeader = pCD->transientLeader;
554 ClientData *pcdTop = FindTransientTreeLeader (pCD);
555 Boolean restackTransients;
556 WmScreenData *pSD = pWS->pSD;
559 pCD->transientSiblings = pcdLeader->transientChildren;
560 pcdLeader->transientChildren = pCD;
564 * Insure that the new transient window is on top of its siblings
565 * and that the transient window tree is on top of the window
566 * stack (this is the standard behavior for newly mapped and
567 * managed windows). If there is a system modal window that the
568 * transient window is not associated with then don't raise the
572 restackTransients = PutTransientOnTop (pCD);
576 * Handle application modal transient windows
579 if (pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
582 * If this is a primary application modal window then increment
583 * the modal count for transient leaders that are directly up
584 * the transient tree.
586 * (This is the old MWM_INPUT_APPLICATION_MODAL behavior.)
590 MarkModalTransient (pcdLeader, pCD);
591 pcdLeader = pcdLeader->transientLeader;
594 else if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
597 * If this is a full application modal window then increment
598 * the modal count for the rest of the transient tree.
601 MarkModalSubtree (pcdTop, pCD);
603 else if (pcdTop->fullModalCount)
606 * There is already a full application modal window in the tree
608 pcdLeader = pCD->transientLeader;
609 if ((pcdLeader->inputMode != MWM_INPUT_FULL_APPLICATION_MODAL) ||
610 (IS_APP_MODALIZED(pcdLeader)))
613 * The immediate parent of this transient is not the
614 * current full application modal window. Set the full
615 * modal count to the parent's so that they both become
616 * unmodalized at the same time. This allows a full
617 * app modal window to have active, non-modal transients.
619 pCD->fullModalCount = pcdLeader->fullModalCount;
625 * Do the actual restacking in the X window stack if necessary.
628 if ((pSD->clientList != &pcdTop->clientEntry) && !wmGD.systemModalActive)
630 F_Raise (NULL, pCD, NULL);
632 else if (restackTransients)
634 RestackTransientsAtWindow (pCD);
636 else if (pCD != FindTransientOnTop (pcdTop))
638 StackTransientWindow (pCD);
642 } /* END OF FUNCTION AddTransient */
646 /*************************************<->*************************************
648 * MarkModalSubtree (pcdTree, pcdAvoid)
653 * This function marks the transient tree with pcdTree as its leader.
654 * If pcdAvoid is in the tree, it is not marked.
658 * pcdTree = pointer to client data of the tree to mark
659 * pcdAvoid = pointer to client data to not mark if in tree
662 *************************************<->***********************************/
664 void MarkModalSubtree (ClientData *pcdTree, ClientData *pcdAvoid)
666 /* Mark children, if any */
668 if (pcdTree->transientChildren)
669 MarkModalSubtree (pcdTree->transientChildren, pcdAvoid);
673 if (pcdTree != pcdAvoid)
675 MarkModalTransient (pcdTree, pcdAvoid);
680 if (pcdTree->transientSiblings)
681 MarkModalSubtree (pcdTree->transientSiblings, pcdAvoid);
686 /*************************************<->*************************************
688 * MarkModalTransient (pcdLeader, pCD)
693 * This function marks a transient window for application modal processing.
694 * Grabs are done to eat up pointer button events.
698 * pcdLeader = pointer to client data to mark
699 * pCD = pointer to client data of new transient
702 *************************************<->***********************************/
704 void MarkModalTransient (ClientData *pcdLeader, ClientData *pCD)
706 if (!IS_APP_MODALIZED(pcdLeader))
709 * Eat pointer button events while application modal.
711 XGrabButton (DISPLAY, AnyButton, AnyModifier,
712 pcdLeader->clientBaseWin, True,
713 ButtonPressMask | ButtonMotionMask, GrabModeAsync,
714 GrabModeAsync, None, wmGD.workspaceCursor);
717 /* bump application modal count */
718 if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
719 pcdLeader->fullModalCount++;
721 pcdLeader->primaryModalCount++;
725 /*************************************<->*************************************
727 * DeleteTransient (pCD)
732 * This function deletes the transient window from the lead window's list
735 * Much of the complication of this code arises from trying to handle
736 * mixtures of both full- and primary-application modal transients.
737 * It also tries to handle the case where a sequence of application
738 * modal transients appear in different places in the transient tree
739 * (i.e. not as descendents of a previously existing full app modal
744 * pCD = pointer to client data of transient.
746 *************************************<->***********************************/
748 void DeleteTransient (ClientData *pCD)
750 ClientData *pcdLeader;
756 * Handle primary application modality.
757 * Reset the modal window counts for the leader windows up through the
758 * transient window tree.
761 modalCount = pCD->primaryModalCount;
762 if (pCD->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
768 pcdLeader = pCD->transientLeader;
772 UnMarkModalTransient (pcdLeader, modalCount, pCD);
774 pcdLeader = pcdLeader->transientLeader;
779 * Handle full application modality.
780 * Undo application modal windows in a depth first manner.
783 pcdLeader = FindTransientTreeLeader (pCD);
785 if (pCD->transientChildren)
787 DeleteFullAppModalChildren (pcdLeader, pCD->transientChildren);
789 if (pCD->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
793 * If this is a full application modal window then decrement
794 * the modal count for the rest of the transient tree.
797 FixupFullAppModalCounts (pcdLeader, pCD);
802 * Delete this transient from its parent's list of transient windows.
805 pcdPrev = pCD->transientLeader->transientChildren;
810 pCD->transientLeader->transientChildren = pCD->transientSiblings;
814 while (pcdPrev && (pcdPrev->transientSiblings != pCD))
816 pcdPrev = pcdPrev->transientSiblings;
819 pcdPrev->transientSiblings = pCD->transientSiblings;
823 } /* END OF FUNCTION DeleteTransient */
826 /*************************************<->*************************************
828 * DeleteFullAppModalChildren (pcdLeader, pCD)
833 * This function handles the clean-up of nested full application modal
834 * windows. The deletion has to be handled carefully to keep a correct
835 * fullModalCount on the transients that remain in the tree.
837 * The algorithm is to traverse the transient children depth first and
838 * fix up the tree's fullModalCount for each full application modal
839 * window that's found.
843 * pcdLeader = pointer to client data of transient tree root.
844 * pCD = pointer to client data of transient subtree to delete.
846 *************************************<->***********************************/
848 void DeleteFullAppModalChildren (ClientData *pcdLeader, ClientData *pCD)
851 /* recursively do children first */
852 if (pCD->transientChildren)
853 DeleteFullAppModalChildren (pcdLeader, pCD->transientChildren);
855 /* do fullAppModal fixup for this guy */
856 FixupFullAppModalCounts (pcdLeader, pCD);
858 /* do siblings of passed transient */
859 if (pCD->transientSiblings)
860 DeleteFullAppModalChildren (pcdLeader, pCD->transientSiblings);
863 } /* END OF FUNCTION DeleteFullAppModalChildren */
866 /*************************************<->*************************************
868 * FixupFullAppModalCounts (pcdLeader, pcdDelete)
873 * This function traverses the entire transient tree (pointed to by
874 * pcdLeader) and fixes up the fullModalCounts to reflect the removal
877 * The fix-up consists of decrementing the count
878 * of the remaining full app modal windows in the tree iff the remaining
879 * window's fullModalCount is greater than the fullModalCount of the
880 * transient being deleted.
884 * pcdLeader = pointer to client data for head of transient tree.
885 * pcdDelet = pointer to client data of transient being deleted.
887 *************************************<->***********************************/
890 FixupFullAppModalCounts (ClientData *pcdLeader, ClientData *pcdDelete)
895 if (pcdLeader->transientChildren)
897 FixupFullAppModalCounts (pcdLeader->transientChildren, pcdDelete);
901 * fixup leader: decrement the count if it is greater than
902 * the transient being deleted.
905 if (pcdLeader->fullModalCount > pcdDelete->fullModalCount)
907 UnMarkModalTransient (pcdLeader, 1, pcdDelete);
911 if (pcdLeader->transientSiblings)
913 FixupFullAppModalCounts (pcdLeader->transientSiblings, pcdDelete);
916 } /* END OF FUNCTION FixupFullAppModalCounts */
920 /*************************************<->*************************************
922 * UnMarkModalTransient (pcdModee, modalCount, pcdModal)
927 * This function unmarks a transient window for application modal processing.
928 * Original grabs are restored.
932 * pcdModee = pointer to client data for transient to unmark
933 * pcdModal = pointer to client data for modal transient
934 * modalCount = amount to decrement the client's modal count by
937 *************************************<->***********************************/
939 void UnMarkModalTransient (ClientData *pcdModee, int modalCount, ClientData *pcdModal)
941 /* decrement application modal count */
942 if (pcdModal->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL)
943 pcdModee->fullModalCount -= modalCount;
944 else if (pcdModal->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL)
945 pcdModee->primaryModalCount -= modalCount;
948 * Restore original button bindings/grabs if not modal anymore
950 if (!IS_APP_MODALIZED(pcdModee))
952 XUngrabButton (DISPLAY, AnyButton, AnyModifier,
953 pcdModee->clientBaseWin);
955 SetupCButtonBindings (pcdModee->clientBaseWin, BUTTON_SPECS(pcdModee));
957 if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
958 (wmGD.keyboardFocus != pcdModee))
960 DoExplicitSelectGrab (pcdModee->clientBaseWin);
966 /*************************************<->*************************************
968 * PutTransientOnTop (pcd)
973 * This function changes the transient window list to insure that the
974 * specified transient window is on top of its siblings and its parent
975 * is on top of its siblings, etc. The sibling list is ordered such
976 * that the first window in the list is on top of second window in the
982 * pcd = pointer to client data of a transient window
987 * pcdLeader = (transientSiblings)
989 * RETURN = True if the transient tree needs to be restacked
991 *************************************<->***********************************/
993 Boolean PutTransientOnTop (ClientData *pcd)
995 ClientData *pcdLeader;
997 Boolean restack = False;
1000 pcdLeader = pcd->transientLeader;
1001 if (pcdLeader != NULL)
1003 pcdPrev = pcdLeader->transientChildren;
1006 while (pcdPrev->transientSiblings != pcd)
1008 pcdPrev = pcdPrev->transientSiblings;
1010 pcdPrev->transientSiblings = pcd->transientSiblings;
1011 pcd->transientSiblings = pcdLeader->transientChildren;
1012 pcdLeader->transientChildren = pcd;
1016 if (PutTransientOnTop (pcdLeader))
1021 if (BumpPrimaryToBottom (pcdLeader))
1030 } /* END OF FUNCTION PutTransientOnTop */
1034 /*************************************<->*************************************
1036 * PutTransientBelowSiblings (pcd)
1041 * This function changes the transient window list to insure that the
1042 * specified transient window is below its sibling windows.
1047 * pcd = pointer to client data of a transient window
1052 * pcdLeader = (transientSiblings)
1054 * RETURN = True if restacking has been done in the transient window tree.
1056 *************************************<->***********************************/
1058 Boolean PutTransientBelowSiblings (ClientData *pcd)
1060 ClientData *pcdLeader;
1061 ClientData *pcdNext;
1062 Boolean restack = False;
1065 pcdLeader = pcd->transientLeader;
1068 if (pcd->transientSiblings || (pcdLeader->transientChildren != pcd))
1071 if (pcdLeader->transientChildren == pcd)
1073 pcdLeader->transientChildren = pcd->transientSiblings;
1076 pcdNext = pcdLeader->transientChildren;
1077 while (pcdNext->transientSiblings)
1079 if (pcdNext->transientSiblings == pcd)
1081 pcdNext->transientSiblings = pcd->transientSiblings;
1085 pcdNext = pcdNext->transientSiblings;
1088 pcdNext->transientSiblings = pcd;
1090 pcd->transientSiblings = NULL;
1095 } /* END OF FUNCTION PutTransientBelowSiblings */
1099 /*************************************<->*************************************
1101 * RestackTransients (pcd)
1106 * This function restacks windows in a transient window tree. Secondary
1107 * (transient) windows are stacked on top of their associated primary
1108 * windows and the first secondary window in the transientSiblings list
1109 * is stacked on top of the second window in the list, etc.
1114 * pcd = pointer to client data of a window in a transient tree
1116 *************************************<->***********************************/
1118 void RestackTransients (ClientData *pcd)
1120 ClientData *pcdLeader;
1122 static int size = 0;
1123 static Window *windows = NULL;
1127 XWindowChanges windowChanges;
1132 * Build a restacking list and do the restacking.
1135 pcdLeader = FindTransientTreeLeader (pcd);
1136 count = CountTransientChildren (pcdLeader);
1138 /* No work to do if no transient children; count includes leader. */
1145 * Expand the (static) windows buffer that is used in restacking.
1149 (Window *)WmMalloc ((char*)windows, (count + 5) * sizeof (Window))))
1151 /* cannot get memory space */
1159 MakeTransientFamilyStackingList (windows, pcdLeader);
1161 nextWindow = MakeTransientWindowList (windows, pcdLeader);
1162 *nextWindow = pcdLeader->clientFrameWin;
1166 * Changes for CDExc19397.
1167 * XRestackWindows may move pcdLeader; that messes up the
1168 * global window stack. Call XConfigureWindow() instead,
1169 * and don't change location of pcdLeader.
1171 for (leaderIndex = 0; leaderIndex < count; leaderIndex++)
1173 if (windows[leaderIndex] == pcdLeader->clientFrameWin)
1176 if (leaderIndex >= count) /* ? Couldn't find leader; should NOT happen. */
1177 leaderIndex = count - 1;
1179 windowChanges.stack_mode = Above;
1180 for (i = leaderIndex; i > 0; i--)
1182 windowChanges.sibling = windows[i];
1183 XConfigureWindow (DISPLAY, windows[i - 1],
1184 CWSibling | CWStackMode, &windowChanges);
1187 windowChanges.stack_mode = Below;
1188 for (i = leaderIndex; i < count - 1; i++)
1190 windowChanges.sibling = windows[i];
1191 XConfigureWindow (DISPLAY, windows[i + 1],
1192 CWSibling | CWStackMode, &windowChanges);
1195 } /* END OF FUNCTION RestackTransients */
1199 /*************************************<->*************************************
1201 * RestackTransientsAtWindow (pcd)
1206 * This function restacks windows in a transient window tree. The
1207 * "anchor point" in the stack for the transient window tree is the
1213 * pcd = pointer to client data of a window in a transient tree
1215 *************************************<->***********************************/
1217 void RestackTransientsAtWindow (ClientData *pcd)
1219 ClientData *pcdLeader;
1220 XWindowChanges windowChanges;
1222 pcdLeader = FindTransientTreeLeader (pcd);
1223 if (pcdLeader && (pcdLeader != pcd))
1225 windowChanges.sibling = pcd->clientFrameWin;
1226 windowChanges.stack_mode = Below;
1227 XConfigureWindow (DISPLAY, pcdLeader->clientFrameWin,
1228 CWSibling | CWStackMode, &windowChanges);
1231 RestackTransients (pcd);
1233 } /* END OF FUNCTION RestackTransientsAtWindow */
1237 /*************************************<->*************************************
1239 * FindTransientTreeLeader (pcd)
1244 * This function identifies the leader of the transient tree that
1245 * contains the specified client.
1250 * pcd = pointer to client data of a window in a transient tree.
1254 * RETURN = pointer to the client data for the transient tree leader.
1256 *************************************<->***********************************/
1258 ClientData * FindTransientTreeLeader (ClientData *pcd)
1263 * Find the head of the transient window tree.
1266 while (pcd->transientLeader)
1268 pcd = pcd->transientLeader;
1273 } /* END OF FUNCTION FindTransientTreeLeader */
1277 /*************************************<->*************************************
1279 * CountTransientChildren (pcd)
1284 * This function returns a count of the number of children in the
1285 * transient window tree headed by the specified client window.
1290 * pcd = pointer to client data of a window in a transient tree
1294 * RETURN = count of transient windows in the transient window tree
1296 *************************************<->***********************************/
1299 CountTransientChildren (ClientData *pcd)
1302 ClientData *pcdNext;
1306 pcdNext = pcd->transientChildren;
1309 if (pcdNext->transientChildren)
1311 count += CountTransientChildren (pcdNext);
1317 pcdNext = pcdNext->transientSiblings;
1322 } /* END OF FUNCTION CountTransientChildren */
1326 /*************************************<->*************************************
1328 * MakeTransientWindowList (windows, pcd)
1333 * This function makes a transient window list of windows in the
1334 * transient window tree headed by the specified client. This list is
1335 * to be passed to XRestackWindows.
1340 * windows = pointer to the windows list to be filled out
1342 * pcd = pointer to client data of a window in a transient tree
1346 * RETURN = pointer to the next entry in the windows list
1348 *************************************<->***********************************/
1350 Window * MakeTransientWindowList (Window *windows, ClientData *pcd)
1353 ClientData *pcdNext;
1356 pcdNext = pcd->transientChildren;
1359 if (pcdNext->transientChildren)
1361 windows = MakeTransientWindowList (windows, pcdNext);
1363 *windows = pcdNext->clientFrameWin;
1365 pcdNext = pcdNext->transientSiblings;
1371 } /* END OF FUNCTION MakeTransientWindowList */
1375 /*************************************<->*************************************
1377 * FindTransientFocus (pcd)
1382 * This function identifies a window in the transient tree that is headed
1383 * by the specified client that can accept the keyboard input. The
1384 * effect of application modal windows is taken into account.
1389 * pcd = pointer to client data of a window in a transient tree.
1393 * RETURN = pointer to the client data for a window that can accept the
1394 * keyboard input focus.
1396 *************************************<->***********************************/
1398 ClientData * FindTransientFocus (ClientData *pcd)
1402 ClientData *pcdFocus;
1405 * Find a window that does not have an application modal subordinate.
1406 * First, search descendents
1410 while (pcdFocus->transientChildren && IS_APP_MODALIZED(pcdFocus))
1412 pcdFocus = pcdFocus->transientChildren;
1416 * If (search of descendents FAILS) then search siblings.
1419 if (IS_APP_MODALIZED(pcdFocus))
1421 ClientData *pcdSibling;
1424 while (pcdFocus && IS_APP_MODALIZED(pcdFocus))
1426 pcdSibling = pcdFocus;
1427 while (pcdSibling->transientSiblings && IS_APP_MODALIZED(pcdFocus))
1429 pcdSibling = pcdSibling->transientSiblings;
1431 if (IS_APP_MODALIZED(pcdSibling))
1433 pcdFocus = pcdFocus->transientChildren;
1437 pcdFocus = pcdSibling;
1443 return (pcdFocus ? pcdFocus : wmGD.keyboardFocus);
1445 } /* END OF FUNCTION FindTransientFocus */
1449 /*************************************<->*************************************
1451 * FindTransientOnTop (pcd)
1456 * This function identifies the top-most transient window in the
1457 * transient window tree that contains the specified client.
1462 * pcd = pointer to client data of a window in a transient tree.
1466 * RETURN = pointer to the client data for the top-most transient window.
1468 *************************************<->***********************************/
1470 ClientData * FindTransientOnTop (ClientData *pcd)
1475 * Find the head of the transient window tree.
1478 pcd = FindTransientTreeLeader (pcd);
1480 if (!(pcd->secondariesOnTop) &&
1481 (LeaderOnTop (pcd)))
1485 if (LeaderOnTop (pcd))
1487 /* The primary window is on top! */
1492 pcdSub = FindSubLeaderToTop (pcd);
1501 * Find the top-most transient window (the window in the transient tree
1502 * that is highest in the window stack).
1505 while (pcd->transientChildren)
1507 pcd = pcd->transientChildren;
1512 } /* END OF FUNCTION FindTransientOnTop */
1516 /*************************************<->*************************************
1518 * StackWindow (pWS, pEntry, onTop, pStackEntry)
1523 * This function stacks a window of a particular type (normal or icon)
1524 * to the top or botton of the window stack on the screen.
1529 * pWS = pointer to workspace data
1531 * pEntry = pointer to the client list entry for the window to be restacked.
1533 * onTop = if True then the window is to be restacked on top of the
1534 * specified stack window (if the stack window is not specified then
1535 * the entry is added to the top of the window stack)
1536 * otherwise the window is stacked below the specified stack window
1537 * (or at the bottom of the window stack if the stack window is not
1540 * pStackEntry = pointer to a client list entry for a window in the window
1541 * stack that is to be used as a reference in restacking.
1543 *************************************<->***********************************/
1545 void StackWindow (WmWorkspaceData *pWS, ClientListEntry *pEntry, Boolean onTop, ClientListEntry *pStackEntry)
1548 Boolean stackTransientTreeWindows = False;
1549 Window activeIconWindow;
1551 XWindowChanges changes;
1552 WmScreenData *pSD = pWS->pSD;
1557 if (pStackEntry->type == MINIMIZED_STATE)
1559 stackWindow = ICON_FRAME_WIN(pStackEntry->pCD);
1563 stackWindow = pStackEntry->pCD->clientFrameWin;
1568 stackWindow = (Window)0;
1571 if (pEntry->type == MINIMIZED_STATE)
1573 window = ICON_FRAME_WIN(pEntry->pCD);
1578 * Restack the transient tree if appropriate.
1581 if (pEntry->pCD->transientLeader || pEntry->pCD->transientChildren)
1583 stackTransientTreeWindows = True;
1585 window = (FindTransientOnTop (pEntry->pCD))->clientFrameWin;
1589 window = pEntry->pCD->clientFrameWin;
1595 * The active icon text label must be restacked along with the associated
1599 if ((pEntry->type == MINIMIZED_STATE) &&
1600 (pEntry->pCD == wmGD.keyboardFocus) &&
1601 (ICON_DECORATION(pEntry->pCD) & ICON_ACTIVE_LABEL_PART) &&
1602 (ACTIVE_ICON_TEXT_WIN))
1604 activeIconWindow = ACTIVE_ICON_TEXT_WIN;
1608 activeIconWindow = (Window)0;
1613 if ((stackWindow == 0) && (pSD->clientList))
1615 if (pSD->clientList->type == MINIMIZED_STATE)
1617 stackWindow = ICON_FRAME_WIN(pSD->clientList->pCD);
1621 if (pSD->clientList->pCD->transientChildren)
1624 (FindTransientOnTop(pSD->clientList->pCD))->clientFrameWin;
1628 stackWindow = pSD->clientList->pCD->clientFrameWin;
1633 if (activeIconWindow)
1635 changes.sibling = stackWindow;
1636 changes.stack_mode = Above;
1637 XConfigureWindow (DISPLAY, activeIconWindow,
1638 (CWSibling | CWStackMode), &changes);
1639 changes.sibling = activeIconWindow;
1640 changes.stack_mode = Below;
1641 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1646 changes.sibling = stackWindow;
1647 changes.stack_mode = Above;
1648 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1650 if (stackTransientTreeWindows)
1652 /* make sure that the leader is in the correct spot */
1653 changes.sibling = window;
1654 changes.stack_mode = Below;
1655 XConfigureWindow (DISPLAY, pEntry->pCD->clientFrameWin,
1656 (CWSibling | CWStackMode), &changes);
1657 RestackTransients (pEntry->pCD);
1665 * Adjust stack entry window if we're stacking below a
1668 if (pStackEntry && pStackEntry->pCD->transientChildren)
1670 stackWindow = LowestWindowInTransientFamily (pStackEntry->pCD);
1674 if (stackWindow == 0)
1676 if (pSD->lastClient->type == MINIMIZED_STATE)
1678 stackWindow = ICON_FRAME_WIN(pSD->lastClient->pCD);
1683 if (pSD->lastClient->pCD->transientChildren)
1686 LowestWindowInTransientFamily (pSD->lastClient->pCD);
1690 stackWindow = pSD->lastClient->pCD->clientFrameWin;
1694 if (activeIconWindow)
1696 changes.sibling = stackWindow;
1697 changes.stack_mode = Below;
1698 XConfigureWindow (DISPLAY, activeIconWindow,
1699 (CWSibling | CWStackMode), &changes);
1700 changes.sibling = activeIconWindow;
1701 changes.stack_mode = Below;
1702 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1707 changes.sibling = stackWindow;
1708 changes.stack_mode = Below;
1709 XConfigureWindow (DISPLAY, window, (CWSibling | CWStackMode),
1711 if (stackTransientTreeWindows)
1713 /* make sure that the leader is in the correct spot */
1714 changes.sibling = window;
1715 changes.stack_mode = Below;
1716 XConfigureWindow (DISPLAY, pEntry->pCD->clientFrameWin,
1717 (CWSibling | CWStackMode), &changes);
1718 RestackTransients (pEntry->pCD);
1723 } /* END OF FUNCTION StackWindow */
1727 /*************************************<->*************************************
1729 * StackTransientWindow (pcd)
1734 * This function stacks a transient window within its transient window
1735 * tree on the screen. The transient window tree should indicate the
1736 * intended stacking position.
1741 * pcd = pointer to client data of a window in a transient tree
1743 *************************************<->***********************************/
1745 void StackTransientWindow (ClientData *pcd)
1747 XWindowChanges changes;
1748 ClientData *pcdPrev;
1751 if (pcd->transientLeader->transientChildren == pcd)
1753 if (pcd->transientSiblings)
1755 changes.sibling = pcd->transientSiblings->clientFrameWin;
1759 changes.sibling = pcd->transientLeader->clientFrameWin;
1761 changes.stack_mode = Above;
1765 pcdPrev = pcd->transientLeader;
1766 while (pcdPrev->transientSiblings != pcd)
1768 pcdPrev = pcdPrev->transientSiblings;
1770 changes.sibling = pcdPrev->clientFrameWin;
1771 changes.stack_mode = Below;
1774 XConfigureWindow (DISPLAY, pcd->clientFrameWin, (CWSibling | CWStackMode),
1778 } /* END OF FUNCTION StackTransientWindow */
1782 /*************************************<->*************************************
1784 * CheckIfClientObscuring (pcdTop, pcd)
1789 * This function determines whether a window or a transient window tree
1790 * is obscuring (at least partially) a window or a transient window tree
1791 * that is below it in the window stack.
1796 * pcdTop = pointer to client data for a window (it may be the leader of
1797 * a transient tree; this window is the higher in the window stack
1798 * than the window it is be checked against.
1800 * pcd = pointer to client data for a window (it may be the leader of
1806 * RETURN = True if the top window(s) overlap the lower window(s)
1808 *************************************<->***********************************/
1810 Boolean CheckIfClientObscuring (ClientData *pcdTop, ClientData *pcd)
1812 Boolean obscuring = False;
1813 ClientData *pcdNext;
1817 * Check only if the top window is visible onscreen.
1820 if (pcdTop->transientChildren && (pcdTop->clientState != MINIMIZED_STATE))
1822 pcdNext = pcdTop->transientChildren;
1823 while (pcdNext && !obscuring)
1825 obscuring = CheckIfClientObscuring (pcdNext, pcd);
1826 pcdNext = pcdNext->transientSiblings;
1830 if (!obscuring && pcd->transientChildren &&
1831 (pcd->clientState != MINIMIZED_STATE))
1833 pcdNext = pcd->transientChildren;
1834 while (pcdNext && !obscuring)
1836 obscuring = CheckIfClientObscuring (pcdTop, pcdNext);
1837 pcdNext = pcdNext->transientSiblings;
1843 obscuring = CheckIfObscuring (pcdTop, pcd);
1848 } /* END OF FUNCTION CheckIfClientObscuring */
1852 /*************************************<->*************************************
1854 * CheckIfObscuring (pcdA, pcdB)
1859 * This function determines whether a window (not a transient tree)
1860 * is obscuring (at least partially) a window (not a transient tree)
1861 * that is below it in the window stack.
1866 * pcdA = pointer to client data for a window; this window is higher in
1867 * the window stack than the window it is be checked against.
1869 * pcdB = pointer to client data for a window.
1874 * RETURN = True if the top window overlaps the lower window
1876 *************************************<->***********************************/
1878 Boolean CheckIfObscuring (ClientData *pcdA, ClientData *pcdB)
1880 Boolean obscuring = False;
1892 * For workspace stuff: if either is unseen, then neither
1895 if ((pcdA->clientState & UNSEEN_STATE) ||
1896 (pcdB->clientState & UNSEEN_STATE))
1902 if (pcdA->clientState == NORMAL_STATE)
1904 aX1 = pcdA->clientX - pcdA->clientOffset.x;
1905 aY1 = pcdA->clientY - pcdA->clientOffset.y;
1906 aX2 = aX1 + pcdA->clientWidth + (2 * pcdA->clientOffset.x) - 1;
1907 aY2 = aY1 + pcdA->clientHeight + pcdA->clientOffset.y +
1908 pcdA->clientOffset.x - 1;
1910 else if (pcdA->clientState == MINIMIZED_STATE)
1914 aX2 = aX1 + ICON_WIDTH(pcdA) - 1;
1915 aY2 = aY1 + ICON_HEIGHT(pcdA) - 1;
1917 else /* (pcdA->clientState == MAXIMIZED_STATE) */
1919 aX1 = pcdA->maxX - pcdA->clientOffset.x;
1920 aY1 = pcdA->maxY - pcdA->clientOffset.y;
1921 aX2 = aX1 + pcdA->maxWidth + (2 * pcdA->clientOffset.x) - 1;
1922 aY2 = aY1 + pcdA->maxHeight + pcdA->clientOffset.y +
1923 pcdA->clientOffset.x - 1;
1926 if (pcdB->clientState == NORMAL_STATE)
1928 bX1 = pcdB->clientX - pcdB->clientOffset.x;
1929 bY1 = pcdB->clientY - pcdB->clientOffset.y;
1930 bX2 = bX1 + pcdB->clientWidth + (2 * pcdB->clientOffset.x) - 1;
1931 bY2 = bY1 + pcdB->clientHeight + pcdB->clientOffset.y +
1932 pcdB->clientOffset.x - 1;
1934 else if (pcdB->clientState == MINIMIZED_STATE)
1938 bX2 = bX1 + ICON_WIDTH(pcdB) - 1;
1939 bY2 = bY1 + ICON_HEIGHT(pcdB) - 1;
1941 else /* (pcdB->clientState == MAXIMIZED_STATE) */
1943 bX1 = pcdB->maxX - pcdB->clientOffset.x;
1944 bY1 = pcdB->maxY - pcdB->clientOffset.y;
1945 bX2 = bX1 + pcdB->maxWidth + (2 * pcdB->clientOffset.x) - 1;
1946 bY2 = bY1 + pcdB->maxHeight + pcdB->clientOffset.y +
1947 pcdB->clientOffset.x - 1;
1951 * Check if there is overlap in both dimensions.
1954 if (((aX1 >= bX1) && (aX1 <= bX2)) || ((aX2 >= bX1) && (aX2 <= bX2)) ||
1955 ((bX1 >= aX1) && (bX1 <= aX2)) || ((bX2 >= aX1) && (bX2 <= aX2)))
1957 if (((aY1 >= bY1) && (aY1 <= bY2)) || ((aY2 >= bY1) && (aY2 <= bY2)) ||
1958 ((bY1 >= aY1) && (bY1 <= aY2)) || ((bY2 >= aY1) && (bY2 <= aY2)))
1967 } /* END OF FUNCTION CheckIfObscuring */
1971 /*************************************<->*************************************
1973 * CheckIfClientObscuredByAny (pcd)
1978 * This function determines whether a window or a transient window tree
1979 * is obscured (at least partially) by any other window.
1984 * pcd = pointer to client data for a window (it may be the leader of
1990 * RETURN = True if the window(s) are overlapped.
1992 *************************************<->***********************************/
1994 Boolean CheckIfClientObscuredByAny (ClientData *pcd)
1996 Boolean obscured = False;
1997 ClientListEntry *pListEntry;
2000 pListEntry = ACTIVE_PSD->clientList;
2001 while (pListEntry && !obscured)
2003 if (pListEntry->pCD == pcd)
2005 if (((pListEntry->type == MINIMIZED_STATE) &&
2006 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2007 ((pListEntry->type != MINIMIZED_STATE) &&
2008 (pListEntry->pCD->clientState != MINIMIZED_STATE)))
2013 else if (((pListEntry->type == MINIMIZED_STATE) &&
2014 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2015 ((pListEntry->type != MINIMIZED_STATE) &&
2016 (pListEntry->pCD->clientState != MINIMIZED_STATE)))
2019 * The window for the entry is visible on screen. See if it
2020 * obscures the indicated window.
2023 obscured = CheckIfClientObscuring (pListEntry->pCD, pcd);
2028 pListEntry = pListEntry->nextSibling;
2034 } /* END OF FUNCTION CheckIfClientObscuredByAny */
2038 /*************************************<->*************************************
2040 * CheckIfClientObscuringAny (pcd)
2045 * This function determines whether a window or a transient window tree
2046 * is obscuring another window.
2051 * pcd = pointer to client data for a window (it may be the leader of
2057 * RETURN = True if the window(s) overlaps anther window.
2059 *************************************<->***********************************/
2061 Boolean CheckIfClientObscuringAny (ClientData *pcd)
2063 Boolean obscuring = False;
2064 ClientListEntry *pListEntry;
2067 pListEntry = (pcd->clientState == MINIMIZED_STATE) ?
2068 &pcd->iconEntry : &pcd->clientEntry;
2069 while (pListEntry && !obscuring)
2071 if ((pListEntry->pCD != pcd) &&
2072 (((pListEntry->type == MINIMIZED_STATE) &&
2073 (pListEntry->pCD->clientState == MINIMIZED_STATE)) ||
2074 ((pListEntry->type != MINIMIZED_STATE) &&
2075 (pListEntry->pCD->clientState != MINIMIZED_STATE))))
2077 obscuring = CheckIfClientObscuring (pcd, pListEntry->pCD);
2080 pListEntry = pListEntry->nextSibling;
2085 } /* END OF FUNCTION CheckIfClientObscuringAny */
2089 /*************************************<->*************************************
2091 * SetupSystemModalState (pCD)
2096 * This function prepares for mapping a system modal window. An input
2097 * screen window is mapped below the system modal window to prevent input
2098 * to the windows not related to the system modal window.
2103 * pCD = pointer to client data for the system modal window; if NULL the
2104 * system modal window is a special window manager dialog box
2109 * wmGD = changes to system modal state data
2111 *************************************<->***********************************/
2113 void SetupSystemModalState (ClientData *pCD)
2115 XWindowChanges windowChanges;
2116 unsigned int width, height;
2117 unsigned int x_hot, y_hot;
2118 unsigned char *bits;
2119 unsigned char *mask_bits;
2124 * If we've got a menu active, then unpost it first
2125 * so that grabs from the menu don't interfere with
2126 * the system modal dialog. We want to avoid lock-ups.
2128 if (wmGD.menuActive != NULL)
2130 UnpostMenu (wmGD.menuActive);
2131 XSync (DISPLAY, False);
2135 * Try to grab the pointer and keyboard. If either
2136 * fails because event processing is frozen by another grab, then
2137 * don't do system modal for fear of leaving the system unusable.
2139 if (XGrabPointer(DISPLAY,
2140 ROOT_FOR_CLIENT(pCD),
2141 FALSE, /* owner_events */
2142 (unsigned int) 0, /* event mask */
2143 GrabModeAsync, /* pointer_mode */
2144 GrabModeAsync, /* keyboard_mode */
2145 None, /* confine_to window */
2147 CurrentTime) == GrabFrozen)
2153 XUngrabPointer (DISPLAY, CurrentTime);
2156 if (XGrabKeyboard(DISPLAY,
2157 ROOT_FOR_CLIENT(pCD),
2158 FALSE, /* owner_events */
2159 GrabModeAsync, /* pointer_mode */
2160 GrabModeAsync, /* keyboard_mode */
2161 CurrentTime) == GrabFrozen)
2167 XUngrabKeyboard (DISPLAY, CurrentTime);
2172 if (wmGD.useLargeCursors)
2174 width = noenter32_width;
2175 height = noenter32_height;
2176 x_hot = noenter32_x_hot;
2177 y_hot = noenter32_y_hot;
2178 bits = noenter32_bits;
2179 mask_bits = noenter32m_bits;
2183 #endif /* LARGECURSORS */
2186 width = noenter16_width;
2187 height = noenter16_height;
2188 x_hot = noenter16_x_hot;
2189 y_hot = noenter16_y_hot;
2190 bits = noenter16_bits;
2191 mask_bits = noenter16m_bits;
2194 for (scr=0; scr<wmGD.numScreens; scr++)
2196 pSD = &(wmGD.Screens[scr]);
2199 * Make the system modal input screen window if necessary.
2202 if (pSD->managed && pSD->inputScreenWindow == 0)
2204 XSetWindowAttributes windowAttributes;
2209 windowAttributes.event_mask = ButtonPressMask;
2210 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
2212 windowAttributes.event_mask |= EnterWindowMask;
2214 windowAttributes.override_redirect = True;
2216 pixmap = XCreateBitmapFromData (DISPLAY, pSD->rootWindow,
2217 (char *)bits, width, height);
2219 maskPixmap = XCreateBitmapFromData (DISPLAY, pSD->rootWindow,
2220 (char *)mask_bits, width, height);
2222 xcolors[0].pixel = BlackPixel (DISPLAY, pSD->screen);
2223 xcolors[1].pixel = WhitePixel (DISPLAY, pSD->screen);
2224 XQueryColors (DISPLAY, DefaultColormap (DISPLAY, pSD->screen),
2226 windowAttributes.cursor =
2227 XCreatePixmapCursor (DISPLAY, pixmap, maskPixmap,
2228 &(xcolors[0]), &(xcolors[1]),
2230 XFreePixmap (DISPLAY, pixmap);
2231 XFreePixmap (DISPLAY, maskPixmap);
2233 pSD->inputScreenWindow =
2234 XCreateWindow (DISPLAY, pSD->rootWindow, 0, 0,
2235 DisplayWidth (DISPLAY, pSD->screen),
2236 DisplayHeight (DISPLAY, pSD->screen),
2241 CWEventMask | CWOverrideRedirect | CWCursor,
2244 if (pSD->managed && pSD != ACTIVE_PSD)
2246 XMapRaised (DISPLAY, pSD->inputScreenWindow);
2252 wmGD.systemModalWindow = pCD->clientFrameWin;
2257 * ELSE: the system modal window is a special window manager dialog
2258 * box and wmGD.systemModalWindow is set prior to the call to
2259 * SetupSystemModalState. Set the focus to the special window manager
2263 SetKeyboardFocus (NULL, REFRESH_LAST_FOCUS);
2264 XSetInputFocus (DISPLAY, wmGD.systemModalWindow, RevertToPointerRoot,
2270 * Map the system modal input screen window below the system modal
2274 windowChanges.sibling = wmGD.systemModalWindow;
2275 windowChanges.stack_mode = Below;
2276 XConfigureWindow (DISPLAY, ACTIVE_PSD->inputScreenWindow,
2277 CWSibling | CWStackMode, &windowChanges);
2279 XMapWindow (DISPLAY, ACTIVE_PSD->inputScreenWindow);
2283 * Setup the system modal global data.
2286 wmGD.systemModalActive = True;
2287 wmGD.systemModalClient = pCD;
2290 } /* END OF FUNCTION SetupSystemModalState */
2294 /*************************************<->*************************************
2296 * UndoSystemModalState ()
2301 * This function cleans up after a system modal window goes away.
2306 * wmGD = (system modal state data)
2311 * wmGD = changes to system modal state data
2313 *************************************<->***********************************/
2315 void UndoSystemModalState (void)
2320 * Unmap the system modal input screen window.
2323 for (scr = 0; scr < wmGD.numScreens; scr++)
2325 if(wmGD.Screens[scr].managed)
2327 XUnmapWindow (DISPLAY, wmGD.Screens[scr].inputScreenWindow);
2332 * Reset the focus if a window manager system modal dialog box was
2336 if (!wmGD.systemModalClient)
2338 AutoResetKeyFocus (NULL, GetTimestamp());
2343 * Reset the system modal global data.
2346 wmGD.systemModalActive = False;
2347 wmGD.systemModalClient = NULL;
2348 wmGD.systemModalWindow = 0;
2350 } /* END OF FUNCTION UndoSystemModalState */
2354 /*************************************<->*************************************
2356 * FindClientNameMatch (pStartingEntry, toNext, clientName, types)
2361 * This function searches for a client that has a particular name or class.
2362 * A match will be indicated if the client with the name or class also
2363 * is in a particular state.
2368 * pEntry = pointer to the client list entry where the search is
2371 * toNext = if True then search client list from first to last; otherwise
2372 * search the client list last to first.
2374 * clientName = string that indicates a client name or class.
2376 * type = types of objects (icon, window, ...) that are to be matched.
2381 * RETURN = pointer to client list entry for matched client.
2383 *************************************<->***********************************/
2384 ClientListEntry * FindClientNameMatch (ClientListEntry *pEntry,
2387 unsigned long types)
2390 Boolean foundMatch = False;
2395 while (!foundMatch && pEntry)
2399 if (pEntry->type == MINIMIZED_STATE)
2401 if ((pCD->clientState == MINIMIZED_STATE) &&
2402 (types & F_GROUP_ICON))
2409 if ((pCD->clientState != MINIMIZED_STATE) &&
2410 (types & F_GROUP_WINDOW))
2417 ((pCD->clientName && (strcmp (clientName,pCD->clientName) == 0)) ||
2418 (pCD->clientClass && (strcmp (clientName,pCD->clientClass) == 0))))
2424 pEntry = (toNext) ? pEntry->nextSibling : pEntry->prevSibling;
2430 } /* END OF FUNCTION FindClientNameMatch */
2433 /*************************************<->*************************************
2435 * BumpPrimaryToTop (pcdLeader)
2440 * This function moves the primary window to the "top" of the transient
2445 * pcdLeader = pointer to client data of transient tree root.
2447 * Returns: True if stacking order of leader window changed.
2448 * False if not stacking change.
2452 * This affects only the clientData structures. There is no immediate
2453 * effect on the actual stacking order on the display. That is done
2454 * by StackWindow and/or RestackTransients.
2456 *************************************<->***********************************/
2458 Boolean BumpPrimaryToTop (ClientData *pcdLeader)
2463 count = CountTransientChildren (pcdLeader);
2465 if (pcdLeader->primaryStackPosition != (count-1))
2467 pcdLeader->primaryStackPosition = count - 1;
2478 /*************************************<->*************************************
2480 * BumpPrimaryToBottom (pcdLeader)
2485 * This function moves the primary window to the "bottom" of the transient
2490 * pcdLeader = pointer to client data of transient tree root.
2492 * Returns: True if stacking order of leader window changed.
2493 * False if not stacking change.
2497 * This affects only the clientData structures. There is no immediate
2498 * effect on the actual stacking order on the display. That is done
2499 * by StackWindow and/or RestackTransients.
2501 *************************************<->***********************************/
2503 Boolean BumpPrimaryToBottom (ClientData *pcdLeader)
2507 if (pcdLeader->primaryStackPosition != 0)
2509 pcdLeader->primaryStackPosition = 0;
2521 /*************************************<->*************************************
2523 * LowestWindowInTransientFamily (pcdLeader)
2528 * This function returns the lowest stacked window in a transient
2533 * pcdLeader = pointer to client data of leader of a transient tree
2535 * Returns: id of lowest window in the transient tree for this family
2537 *************************************<->***********************************/
2540 LowestWindowInTransientFamily (ClientData *pcdLeader)
2543 static int size = 0;
2544 static Window *windows = NULL;
2545 Window wReturn = None;
2548 * Build a window list
2550 count = CountTransientChildren (pcdLeader);
2555 * Expand the (static) windows buffer
2559 (Window *)WmMalloc ((char*)windows, (count + 5) * sizeof (Window))))
2561 /* cannot get memory space */
2568 MakeTransientFamilyStackingList (windows, pcdLeader);
2572 wReturn = windows[count-1];
2581 } /* END OF FUNCTION LowestWindowInTransientFamily */
2584 /*************************************<->*************************************
2586 * FindSubLeaderToTop (pcd)
2591 * This function identifies a candidate window to top within the
2592 * transient tree that is a local transient leader (the window has
2593 * transients hanging off of it, too).
2598 * pcd = pointer to client data of a transient leader window
2600 * Return: ptr to client data for client that should be topped, or NULL
2606 *************************************<->***********************************/
2609 FindSubLeaderToTop (
2613 ClientData *pcdRet = NULL;
2614 ClientData *pcdNext;
2616 pcdNext = pcd->transientChildren;
2617 while (pcdNext && (!pcdRet))
2619 if (pcdNext->transientChildren)
2621 if (LeaderOnTop (pcdNext))
2627 pcdRet = FindSubLeaderToTop (pcdNext);
2630 pcdNext = pcdNext->transientSiblings;
2637 /*************************************<->*************************************
2639 * MakeTransientFamilyStackingList (windows, pcdLeader)
2644 * This function makes a transient window list of windows in the
2645 * transient window tree headed by the specified client.
2650 * windows = pointer to the windows list to be filled out
2652 * pcdLeader = pointer to client data of a window in a transient tree
2656 * The windows array is modified.
2660 * This function puts the transient leader window in the list in the
2663 *************************************<->***********************************/
2666 MakeTransientFamilyStackingList (
2668 ClientData *pcdLeader)
2672 Window *nextWindow, wSave, wTemp, wTop;
2673 int count = CountTransientChildren (pcdLeader);
2677 * Construct the transient stacking list according to
2678 * normal Motif rules.
2680 nextWindow = MakeTransientWindowList (windows, pcdLeader);
2682 if (!(pcdLeader->secondariesOnTop))
2685 * If the leader window shouldn't be on the bottom , then
2686 * adjust the stacking of the list.
2688 if ((pcdLeader->primaryStackPosition > 0) &&
2689 (pcdLeader->primaryStackPosition < count))
2691 for (i=0; i<pcdLeader->primaryStackPosition; i++)
2694 windows[j] = windows[j-1];
2696 j = count - pcdLeader->primaryStackPosition - 1;
2697 windows[j] = pcdLeader->clientFrameWin;
2702 * Put the leader at the bottom.
2704 *nextWindow = pcdLeader->clientFrameWin;
2707 * If one of the transients is also a local leader
2708 * and wants to be on top, then adjust the list.
2710 pcdSub = FindSubLeaderToTop (pcdLeader);
2711 if (pcdSub && (pcdSub->clientFrameWin != None))
2713 /* insert this window at top */
2714 wTop = wSave = pcdSub->clientFrameWin;
2716 /* shuffle the rest down */
2717 for (i=0; i<count; i++)
2732 * Put the leader at the bottom.
2734 *nextWindow = pcdLeader->clientFrameWin;
2737 } /* END OF FUNCTION MakeTransientFamilyStackingList */
2740 /*************************************<->*************************************
2742 * NormalizeTransientTreeStacking (pcdLeader)
2747 * This function traverses the transient tree and cleans up any
2748 * local primary windows that are above their respective secondary
2754 * pcdLeader = pointer to client data of a transient tree leader
2756 * Return: True if any changes in stacking order were made
2761 * This only touches the data structures.
2763 *************************************<->***********************************/
2766 NormalizeTransientTreeStacking (
2767 ClientData *pcdLeader)
2770 ClientData *pcdNext;
2771 Boolean bChanged = False;
2773 pcdNext = pcdLeader->transientChildren;
2774 bChanged = BumpPrimaryToBottom (pcdLeader);
2777 if (pcdNext->transientChildren)
2779 bChanged |= BumpPrimaryToBottom (pcdNext);
2781 bChanged |= NormalizeTransientTreeStacking (pcdNext);
2783 pcdNext = pcdNext->transientSiblings;
2789 /*************************************<->*************************************
2791 * LeaderOnTop (pcdLeader)
2796 * This function tests a leader of a transient (sub) tree to see if
2797 * it should be on top of its transient windows.
2802 * pcdLeader = pointer to client data of a transient tree leader
2804 * Return: True if this leader is on top of its transients
2810 *************************************<->***********************************/
2814 ClientData *pcdLeader)
2817 Boolean bOnTop = False;
2818 int count = CountTransientChildren (pcdLeader);
2820 if ((pcdLeader->primaryStackPosition > 0) &&
2821 (pcdLeader->primaryStackPosition < count))