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[] = "$XConsortium: WmKeyFocus.c /main/5 1996/05/17 12:53:16 rswiston $"
36 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
44 * include extern functions
46 #include "WmKeyFocus.h"
48 #include "WmColormap.h"
51 #include "WmFunction.h"
53 #include "WmProtocol.h"
54 #include "WmWinInfo.h"
55 #include "WmWinList.h"
63 static Boolean removeSelectGrab = True;
67 /*************************************<->*************************************
69 * InitKeyboardFocus ()
74 * This function sets the keyboard input focus to a client window or icon
75 * when the window manager starts up.
80 * wmGD = (keyboardFocusPolicy, colormapFocusPolicy)
82 *************************************<->***********************************/
84 void InitKeyboardFocus (void)
88 Boolean focusSet = False;
91 Window junk_win, root_returned;
92 int currentX, currentY;
96 * Set the keyboard focus based on the keyboard focus policy.
99 wmGD.keyboardFocus = NULL;
100 wmGD.nextKeyboardFocus = NULL;
102 for (scr = 0; scr < wmGD.numScreens; scr++)
104 if (wmGD.Screens[scr].managed)
106 wmGD.Screens[scr].focusPriority = 0;
108 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
111 * Set the keyboard focus to the window that
112 * currently contains the pointer.
115 pCD = GetClientUnderPointer (&sameScreen);
117 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
120 * Do some colormap installation that has been
121 * deferred from the InitColormapFocus routine.
124 SetColormapFocus (ACTIVE_PSD, pCD);
129 Do_Focus_Key (pCD, GetTimestamp (), ALWAYS_SET_FOCUS);
135 ButtonSpec *buttonSpec;
138 * Prepare to do explicit selection button grabs.
141 buttonSpec = wmGD.Screens[scr].buttonSpecs;
144 if ((buttonSpec->button == FOCUS_SELECT_BUTTON) &&
145 (buttonSpec->context & F_CONTEXT_WINDOW) &&
146 (buttonSpec->subContext & F_SUBCONTEXT_W_CLIENT))
148 if (buttonSpec->state == 0)
150 removeSelectGrab = False;
153 buttonSpec = buttonSpec->nextButtonSpec;
163 * This is keyboard focus policy is either "explicit" or it it
165 * and there is no window under the pointer. No window currently has
166 * the keyboard input focus. Set the keyboard focus to the window
167 * manager default (non-client) OR to the last client with focus.
169 * In Mwm 1.1.4 and later, calling Do_Focus_Key with NULL will try
170 * to find a 'reasonable' window to put focus. This means that on
171 * startup and restarts, a Mwm window will have focus! Yeah!
175 * Set Active Screen First
177 if (XQueryPointer(DISPLAY, DefaultRootWindow(DISPLAY),
178 &root_returned, &junk_win,
179 ¤tX, ¤tY,
180 &junk, &junk, (unsigned int *)&junk))
182 for (scr = 0; scr < wmGD.numScreens; scr++)
184 if (wmGD.Screens[scr].managed &&
185 wmGD.Screens[scr].rootWindow == root_returned)
187 SetActiveScreen(&(wmGD.Screens[scr]));
193 Do_Focus_Key ((ClientData *)NULL, CurrentTime, ALWAYS_SET_FOCUS);
196 } /* END OF FUNCTION InitKeyboardFocus */
200 /*************************************<->*************************************
202 * SetKeyboardFocus (pCD, focusFlags)
207 * This function is used to handle a client window getting the input
208 * focus (as the RESULT of an XSetInput call - probably done by
214 * pCD = pointer to client data for window that is to get the focus
216 * focusFlags = flags that indicate focus change details
217 * {REFRESH_LAST_FOCUS}
222 * wmGD = (keyboardFocus)
224 *************************************<->***********************************/
226 void SetKeyboardFocus (ClientData *pCD, long focusFlags)
228 ClientData *currentFocus;
232 * Don't set the keyboard input focus if it is already set to
236 if (wmGD.keyboardFocus == pCD)
240 currentFocus = wmGD.keyboardFocus;
241 ACTIVE_PSD->focusPriority++;
245 * If the keyboard input focus policy is "explicit" then reset the
246 * selection button event handling.
249 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
252 * Reset explicit focus selection event tracking on the last focus
253 * window (reset the passive grab on the focus button).
258 ResetExplicitSelectHandling (currentFocus);
259 wmGD.keyboardFocus = NULL;
262 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
263 (pCD->clientState == MAXIMIZED_STATE)))
266 * The focus is to be set to a client window (not the root).
267 * Stop explicit focus selection event tracking on the new focus
271 if (removeSelectGrab)
273 WmUngrabButton (DISPLAY, FOCUS_SELECT_BUTTON, 0,
279 wmGD.keyboardFocus = pCD;
283 * Do focus auto raise if specified.
286 if (pCD && pCD->focusAutoRaise)
288 if (wmGD.autoRaiseDelay &&
289 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER))
291 AddWmTimer (TIMER_RAISE, (unsigned long)wmGD.autoRaiseDelay,
298 if (((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
299 (!pCD->focusAutoRaiseDisabled)) ||
300 ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) &&
301 (pCD == GetClientUnderPointer (&sameScreen))))
303 Do_Raise (pCD, (ClientListEntry *)NULL, STACK_NORMAL);
310 * Clear the focus indication if it is set for a client window or icon.
315 ClearFocusIndication (currentFocus,
316 ((focusFlags & REFRESH_LAST_FOCUS) ? True : False));
321 * Install the client window colormap if the colormap focus policy is
325 if ((wmGD.colormapFocusPolicy == CMAP_FOCUS_KEYBOARD) &&
326 (!(focusFlags & SCREEN_SWITCH_FOCUS)))
328 SetColormapFocus (ACTIVE_PSD, pCD);
333 * Set the focus window or icon visual indication.
338 pCD->focusPriority = ACTIVE_PSD->focusPriority;
339 SetFocusIndication (pCD);
342 } /* END OF FUNCTION SetKeyboardFocus */
346 /*************************************<->*************************************
348 * ResetExplicitSelectHandling (pCD)
353 * This function resets the selection button event handling for a client
354 * window or icon. This applies only if the keyboard focus policy is
360 * pCD = pointer to client data for window that has focus handling reset
362 *************************************<->***********************************/
364 void ResetExplicitSelectHandling (ClientData *pCD)
369 bUnseen = (pCD->clientState & UNSEEN_STATE) ? True : False;
371 pCD->clientState &= ~UNSEEN_STATE;
374 if ((pCD->clientState == NORMAL_STATE) ||
375 (pCD->clientState == MAXIMIZED_STATE))
378 * A client window was selected.
381 DoExplicitSelectGrab (pCD->clientBaseWin);
383 else if (pCD->clientState == MINIMIZED_STATE)
386 * An icon was selected.
389 /* !!! grab reset if client icon window? !!! */
394 pCD->clientState |= UNSEEN_STATE;
398 } /* END OF FUNCTION ResetExplicitSelectHandling */
402 /*************************************<->*************************************
404 * DoExplicitSelectGrab (window)
409 * This function is used to do a grab button on the specified window. The
410 * grab is intended to catch the keyboard focus select button.
415 * widow = grab widow for the select button
417 *************************************<->***********************************/
419 void DoExplicitSelectGrab (Window window)
422 WmGrabButton (DISPLAY, FOCUS_SELECT_BUTTON, 0, window,
423 False, ButtonReleaseMask, GrabModeSync, GrabModeSync, None,
426 } /* END OF FUNCTION DoExplicitSelectGrab */
430 /*************************************<->*************************************
432 * SetFocusIndication (pCD)
437 * This function changes the client window or icon decoration to have it
438 * indicate that the window or icon has the keyboard input focus.
443 * pCD = pointer to client data for window/icon that is getting the focus
446 *************************************<->***********************************/
448 void SetFocusIndication (ClientData *pCD)
453 * Set the "focus" to pCD to insure correct display of the frame
454 * This is necessary because the called routines get GCs based
455 * on the current keyboard focus.
457 saveCD = wmGD.keyboardFocus;
458 wmGD.keyboardFocus = pCD;
460 if ((pCD->clientState == NORMAL_STATE) ||
461 (pCD->clientState == MAXIMIZED_STATE))
464 * A client window has the input focus.
467 ShowActiveClientFrame (pCD);
469 else if (pCD->clientState == MINIMIZED_STATE)
472 * An icon has the input focus.
475 ShowActiveIcon (pCD);
478 /* restore old keyboard focus */
479 wmGD.keyboardFocus = saveCD;
481 } /* END OF FUNCTION SetFocusIndication */
485 /*************************************<->*************************************
487 * ClearFocusIndication (pCD, refresh)
492 * This function changes the client window or icon decoration to have it
493 * indicate that the window or icon does not have the keyboard input focus
494 * (i.e. it is inactive).
499 * pCD = pointer to client data for window/icon that is losing the focus
501 * refresh = True if window/icon frame is to redrawn
503 *************************************<->***********************************/
505 void ClearFocusIndication (ClientData *pCD, Boolean refresh)
513 * Set the "focus" to NULL to insure correct display of the frame
514 * This is necessary because the called routines get GCs based
515 * on the current keyboard focus.
518 saveCD = wmGD.keyboardFocus;
519 wmGD.keyboardFocus = NULL;
521 bUnseen = (pCD->clientState & UNSEEN_STATE) ? True : False;
523 pCD->clientState &= ~UNSEEN_STATE;
526 if ((pCD->clientState == NORMAL_STATE) ||
527 (pCD->clientState == MAXIMIZED_STATE))
530 * A client window no longer has the input focus.
533 ShowInactiveClientFrame (pCD);
535 else if (pCD->clientState == MINIMIZED_STATE)
538 * An icon no longer has the input focus.
541 ShowInactiveIcon (pCD, refresh);
546 pCD->clientState |= UNSEEN_STATE;
549 /* restore old keyboard focus */
550 wmGD.keyboardFocus = saveCD;
552 } /* END OF FUNCTION ClearFocusIndication */
556 /*************************************<->*************************************
558 * GetClientUnderPointer (pSameScreen)
563 * This function identifies the managed client window or icon that is under
569 * pSameScreen = pointer to flag that indicates if pointer is on the wm screen
571 * Return = client data pointer for the client window / icon under the
574 *************************************<->***********************************/
576 ClientData *GetClientUnderPointer (pSameScreen)
577 Boolean *pSameScreen;
590 if ((*pSameScreen = XQueryPointer (DISPLAY, ACTIVE_ROOT, &root, &child,
591 &rootX, &rootY, &winX, &winY, &mask)) != False)
594 !XFindContext (DISPLAY, child, wmGD.windowContextType,
598 * There is a client window or icon under the pointer.
607 } /* END OF FUNCTION GetClientUnderPointer */
611 /*************************************<->*************************************
613 * FocusNextWindow (type, focusTime)
618 * This function is used to change the focus to the next window in the
619 * window stacking order. The next focus window must be of the specified
620 * type(s). If the focus traversal cannot be done because there is not
621 * an object of the specified type (accepting focus) then don't change the
622 * focus (!!!should the focus be unset in this case!!!).
627 * type = type of objects to change the focus to
629 * focusTime = timestamp to be used for setting the input focus
631 *************************************<->***********************************/
633 Boolean FocusNextWindow (unsigned long type, Time focusTime)
635 ClientListEntry *pCurrentEntry;
636 ClientListEntry *pNextEntry;
637 Boolean focused = False;
642 * Identify the window or icon that currently has the focus and start
643 * traversing to the next object.
646 if (type & F_GROUP_TRANSIENT)
649 * Move the keyboard input focus around in a transient tree.
652 focused = FocusNextTransient (wmGD.keyboardFocus, type, False,
658 if (wmGD.systemModalActive)
662 else if (wmGD.keyboardFocus)
664 if (wmGD.keyboardFocus->transientLeader)
666 pCD = FindTransientTreeLeader (wmGD.keyboardFocus);
670 pCD = wmGD.keyboardFocus;
673 if (pCD->clientState == MINIMIZED_STATE)
675 pCurrentEntry = &pCD->iconEntry;
679 pCurrentEntry = &pCD->clientEntry;
682 pNextEntry = pCurrentEntry->nextSibling;
685 pNextEntry = ACTIVE_PSD->clientList;
690 pCurrentEntry = ACTIVE_PSD->clientList;
691 pNextEntry = pCurrentEntry;
696 while (!focused && pNextEntry)
698 focused = CheckForKeyFocus (pNextEntry, type, True /*next*/, focusTime);
701 pNextEntry = pNextEntry->nextSibling;
707 pNextEntry = ACTIVE_PSD->clientList;
708 while ((pNextEntry != pCurrentEntry) && !focused)
710 focused = CheckForKeyFocus (pNextEntry, type, True/*next*/,
714 pNextEntry = pNextEntry->nextSibling;
721 } /* END OF FUNCTION FocusNextWindow */
725 /*************************************<->*************************************
727 * FocusNextTransient (pCD, type, initiate, focusTime)
732 * This function is used to determine if another window in a transient
733 * tree should get the input focus.
737 * pCD = pointer to the client data for the client window that has the focus
739 * type = type of objects to change the focus to
741 * initiate = set True if transient focus traversal is to be initiated;
742 * set to False if transient focus traversal is to be continued
744 * focusTime = timestamp to be used to set the input focus
749 * RETURN = True if the focus window has been identified and the focus
750 * has been set (or is already set)
752 *************************************<->***********************************/
754 Boolean FocusNextTransient (ClientData *pCD, unsigned long type, Boolean initiate, Time focusTime)
756 Boolean focused = False;
757 unsigned long startAt;
758 ClientData *pcdLeader;
759 ClientData *pcdLowerLeader;
760 ClientData *pcdFocus;
763 if (initiate && !(type & F_GROUP_TRANSIENT))
766 * If in a transient tree focus on the last transient window that
770 if (pCD->transientChildren)
772 pcdFocus = FindLastTransientTreeFocus (pCD, (ClientData *)NULL);
773 if (pcdFocus != wmGD.keyboardFocus)
775 pcdLeader = FindTransientTreeLeader (pcdFocus);
776 if (wmGD.keyboardFocus && wmGD.keyboardFocus->focusAutoRaise &&
777 (wmGD.keyboardFocus != pcdLeader))
780 FindTransientTreeLeader (wmGD.keyboardFocus);
781 if (pcdLowerLeader == pcdLeader)
783 if (PutTransientBelowSiblings (wmGD.keyboardFocus))
785 RestackTransients (pcdLeader);
790 F_Lower (NULL, wmGD.keyboardFocus, (XEvent *) NULL);
793 Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
802 else if (pCD && (pCD->clientState != MINIMIZED_STATE) &&
803 (pCD->transientLeader || pCD->transientChildren))
805 startAt = (initiate) ? (ACTIVE_PSD->clientCounter + 1) :
807 pcdLeader = FindTransientTreeLeader (pCD);
808 pcdFocus = FindNextTFocusInSeq (pcdLeader, startAt);
809 if ((pcdFocus == NULL) && (type == F_GROUP_TRANSIENT))
812 * Wrap around and find a focus window.
815 pcdFocus = FindNextTFocusInSeq (pcdLeader,
816 (unsigned long) (ACTIVE_PSD->clientCounter + 1));
820 if (pcdFocus != wmGD.keyboardFocus)
822 if (wmGD.keyboardFocus && wmGD.keyboardFocus->focusAutoRaise &&
823 (wmGD.keyboardFocus != pcdLeader))
826 FindTransientTreeLeader (wmGD.keyboardFocus);
827 if (pcdLowerLeader == pcdLeader)
829 if (PutTransientBelowSiblings (wmGD.keyboardFocus))
831 RestackTransients (pcdLeader);
836 F_Lower (NULL, wmGD.keyboardFocus, (XEvent *)NULL);
839 Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
846 if (type == F_GROUP_TRANSIENT)
849 * Focus only within a transient tree. In this case the current
850 * or prospective focus is not within a transient tree so leave
851 * the focus where it is.
860 } /* END OF FUNCTION FocusNextTransient */
864 /*************************************<->*************************************
866 * FindLastTransientTreeFocus (pCD, pcdNoFocus)
871 * This function is used to scan a transient tree for the last window in
872 * the tree that had the focus.
876 * pCD = pointer to the client data for the transient tree (or subtree)
879 * pcdNoFocus = pointer to the client data for a client window that is not
880 * to get the input focus (NULL if no client window restriction).
884 * RETURN = pointer to the client data of the window that last had the
887 *************************************<->***********************************/
889 ClientData *FindLastTransientTreeFocus (pCD, pcdNoFocus)
891 ClientData *pcdNoFocus;
895 ClientData *pcdFocus;
896 ClientData *pcdLastFocus = NULL;
899 pcdNext = pCD->transientChildren;
902 pcdFocus = FindLastTransientTreeFocus (pcdNext, pcdNoFocus);
904 (!IS_APP_MODALIZED(pcdFocus)) &&
905 ((pcdLastFocus == NULL) ||
906 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
908 pcdLastFocus = pcdFocus;
910 pcdNext = pcdNext->transientSiblings;
913 if ((!IS_APP_MODALIZED(pCD)) &&
914 ((pcdLastFocus == NULL) ||
915 (pCD->focusPriority > pcdLastFocus->focusPriority)))
920 return (pcdLastFocus);
923 } /* END OF FUNCTION FindLastTransientTreeFocus */
927 /*************************************<->*************************************
929 * FindNextTFocusInSeq (pCD, startAt)
934 * This function is used to scan a transient tree for the next window that
935 * can accept the focus.
939 * pCD = pointer to the client data for the transient tree (or subtree)
942 * startAt = focus window should have a lower id then this client id
947 * RETURN = pointer to the client data of the window that should get the
950 *************************************<->***********************************/
952 ClientData *FindNextTFocusInSeq (pCD, startAt)
954 unsigned long startAt;
957 ClientData *pcdNextFocus = NULL;
959 ClientData *pcdFocus;
962 pcdNext = pCD->transientChildren;
965 pcdFocus = FindNextTFocusInSeq (pcdNext, startAt);
968 if ((pcdNextFocus == NULL) ||
969 (pcdFocus->clientID > pcdNextFocus->clientID))
971 pcdNextFocus = pcdFocus;
974 pcdNext = pcdNext->transientSiblings;
977 if ((pcdNextFocus == NULL) ||
978 (pCD->clientID > pcdNextFocus->clientID))
980 if ((!IS_APP_MODALIZED(pCD)) && (pCD->clientID < startAt))
986 return (pcdNextFocus);
989 } /* END OF FUNCTION FindNextTFocusInSeq */
993 /*************************************<->*************************************
995 * FocusPrevWindow (type, focusTime)
1000 * This function is used to change the focus to the previous window in the
1001 * window stacking order. The next focus window must be of the specified
1002 * type(s). If the focus traversal cannot be done because there is not
1003 * an object of the specified type (accepting focus) then don't change the
1004 * focus (!!!should the focus be unset in this case!!!).
1009 * type = type of objects to change the focus to
1011 * focusTime = timestamp to be used to set the input focus
1013 *************************************<->***********************************/
1015 Boolean FocusPrevWindow (unsigned long type, Time focusTime)
1017 ClientListEntry *pCurrentEntry;
1018 ClientListEntry *pNextEntry;
1019 Boolean focused = False;
1024 * Identify the window or icon that currently has the focus and start
1025 * traversing to the previous object.
1028 if (type & F_GROUP_TRANSIENT)
1031 * Move the keyboard input focus around in a transient tree.
1034 focused = FocusPrevTransient (wmGD.keyboardFocus, type, False,
1040 if (wmGD.systemModalActive)
1044 else if (wmGD.keyboardFocus)
1046 if (wmGD.keyboardFocus->transientLeader)
1048 pCD = FindTransientTreeLeader (wmGD.keyboardFocus);
1052 pCD = wmGD.keyboardFocus;
1055 if (pCD->clientState == MINIMIZED_STATE)
1057 pCurrentEntry = &pCD->iconEntry;
1061 pCurrentEntry = &pCD->clientEntry;
1064 pNextEntry = pCurrentEntry->prevSibling;
1067 pNextEntry = ACTIVE_PSD->lastClient;
1072 pCurrentEntry = ACTIVE_PSD->lastClient;
1073 pNextEntry = pCurrentEntry;
1078 while (!focused && pNextEntry)
1080 focused = CheckForKeyFocus (pNextEntry, type, False /*previous*/,
1084 pNextEntry = pNextEntry->prevSibling;
1090 pNextEntry = ACTIVE_PSD->lastClient;
1091 while ((pNextEntry != pCurrentEntry) && !focused)
1093 focused = CheckForKeyFocus (pNextEntry, type, False/*previous*/,
1097 pNextEntry = pNextEntry->prevSibling;
1104 } /* END OF FUNCTION FocusPrevWindow */
1108 /*************************************<->*************************************
1110 * FocusPrevTransient (pCD, type, initiate, focusTime)
1115 * This function is used to determine if another (previous) window in a
1116 * transient tree should get the input focus.
1120 * pCD = pointer to the client data for the client window that has the focus
1122 * type = type of objects to change the focus to
1124 * initiate = set True if transient focus traversal is to be initiated;
1125 * set to False if transient focus traversal is to be continued
1127 * focusTime = timestamp to be used to set the input focus
1132 * RETURN = True if the focus window has been identified and the focus
1133 * has been set (or is already set)
1135 *************************************<->***********************************/
1137 Boolean FocusPrevTransient (ClientData *pCD, unsigned long type, Boolean initiate, Time focusTime)
1139 Boolean focused = False;
1140 unsigned long startAt;
1141 ClientData *pcdLeader;
1142 ClientData *pcdFocus;
1145 if (initiate && !(type & F_GROUP_TRANSIENT))
1148 * If in a transient tree focus on the last transient window that
1152 if (pCD->transientChildren)
1154 pcdFocus = FindLastTransientTreeFocus (pCD, (ClientData *)NULL);
1155 if (pcdFocus != wmGD.keyboardFocus)
1157 Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
1166 else if (pCD && (pCD->clientState != MINIMIZED_STATE) &&
1167 (pCD->transientLeader || pCD->transientChildren))
1169 startAt = (initiate) ? 0 : pCD->clientID;
1170 pcdLeader = FindTransientTreeLeader (pCD);
1171 pcdFocus = FindPrevTFocusInSeq (pcdLeader, startAt);
1172 if ((pcdFocus == NULL) && (type == F_GROUP_TRANSIENT))
1175 * Wrap around and find a focus window.
1178 pcdFocus = FindPrevTFocusInSeq (pcdLeader, 0);
1182 if (pcdFocus != wmGD.keyboardFocus)
1184 Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
1191 if (type == F_GROUP_TRANSIENT)
1194 * Focus only within a transient tree. In this case the current
1195 * or prospective focus is not within a transient tree so leave
1196 * the focus where it is.
1205 } /* END OF FUNCTION FocusPrevTransient */
1209 /*************************************<->*************************************
1211 * FindPrevTFocusInSeq (pCD, startAt)
1216 * This function is used to scan a transient tree for the previous window that
1217 * can accept the focus.
1221 * pCD = pointer to the client data for the transient tree (or subtree)
1224 * startAt = focus window should have a higher id then this client id
1229 * RETURN = pointer to the client data of the window that should get the
1232 *************************************<->***********************************/
1234 ClientData *FindPrevTFocusInSeq (pCD, startAt)
1236 unsigned long startAt;
1239 ClientData *pcdNextFocus = NULL;
1240 ClientData *pcdNext;
1241 ClientData *pcdFocus;
1244 pcdNext = pCD->transientChildren;
1247 pcdFocus = FindPrevTFocusInSeq (pcdNext, startAt);
1250 if ((pcdNextFocus == NULL) ||
1251 (pcdFocus->clientID < pcdNextFocus->clientID))
1253 pcdNextFocus = pcdFocus;
1256 pcdNext = pcdNext->transientSiblings;
1259 if ((pcdNextFocus == NULL) ||
1260 (pCD->clientID < pcdNextFocus->clientID))
1262 if (!(IS_APP_MODALIZED(pCD)) && (pCD->clientID > startAt))
1268 return (pcdNextFocus);
1271 } /* END OF FUNCTION FindPrevTFocusInSeq */
1275 /*************************************<->*************************************
1277 * CheckForKeyFocus (pNextEntry, type, focusNext, focusTime)
1282 * This function is used to determine if a window is a worthy candidate for
1283 * getting the input focus (it is on-screen and is of the desired type).
1284 * If it is, the window gets the keyboard input focus.
1289 * pNextEntry = the client list entry to be checked
1291 * type = the desired type of the focus window
1293 * focusNext = if true then focus the next window in the window stack
1295 * focusTime = timestamp to be used to set the input focus
1300 * Return = True if the window gets the keyboard input focus otherwise False
1302 *************************************<->***********************************/
1304 Boolean CheckForKeyFocus (ClientListEntry *pNextEntry, unsigned long type, Boolean focusNext, Time focusTime)
1306 ClientData *pCD = pNextEntry->pCD;
1307 unsigned long windowType;
1308 Boolean focused = False;
1312 * First check for focusing within a transient tree.
1317 * Make sure the window is being displayed and is of the specified type.
1320 if (((pNextEntry->type == NORMAL_STATE) &&
1322 (!(pCD->clientState & UNSEEN_STATE)) &&
1324 (pCD->clientState != MINIMIZED_STATE)) ||
1325 ((pNextEntry->type == MINIMIZED_STATE) &&
1326 (pCD->clientState == MINIMIZED_STATE)))
1328 if (pCD->clientState == MINIMIZED_STATE)
1330 windowType = F_GROUP_ICON;
1336 focused = FocusNextTransient (pCD, type, True, focusTime);
1340 focused = FocusPrevTransient (pCD, type, True, focusTime);
1342 windowType = F_GROUP_WINDOW;
1343 if (pCD->transientLeader || pCD->transientChildren)
1345 windowType |= F_GROUP_TRANSIENT;
1349 if (!focused && (type & windowType))
1352 if (focusNext && wmGD.keyboardFocus &&
1353 wmGD.keyboardFocus->focusAutoRaise)
1355 F_Lower (NULL, wmGD.keyboardFocus, (XEvent *)NULL);
1357 Do_Focus_Key (pCD, focusTime, ALWAYS_SET_FOCUS);
1363 } /* END OF FUNCTION CheckForKeyFocus */
1367 /*************************************<->*************************************
1374 * This function sets the keyboard and colormap focus to a client
1375 * window or icon when the window manager is recovering from a
1376 * configuration action.
1385 * o we only need to repair keyboard focus policy is "pointer"
1387 *************************************<->***********************************/
1389 void RepairFocus (void)
1397 * Repair the keyboard and colormap focus based on the policies
1400 if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) ||
1401 (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER))
1404 * Move old enter and leave events and then get the window that
1405 * the pointer is currently in.
1408 XSync (DISPLAY, False);
1409 while (XCheckMaskEvent (DISPLAY, EnterWindowMask | LeaveWindowMask,
1414 pCD = GetClientUnderPointer (&sameScreen);
1417 * Set the keyboard focus to the window that currently contains the
1421 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1424 * This will also set colormap focus if it is CMAP_FOCUS_KEYBOARD.
1427 Do_Focus_Key (pCD, CurrentTime, ALWAYS_SET_FOCUS);
1429 else if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
1431 SetColormapFocus (ACTIVE_PSD, pCD);
1435 } /* END OF FUNCTION RepairFocus */
1439 /*************************************<->*************************************
1441 * AutoResetKeyFocus (pcdFocus, focusTime)
1446 * This function resets the keyboard input focus when a window with the
1447 * focus is withdrawn or iconified. The focus is set to the last window
1448 * that had the focus. The focus is not set to an icon.
1453 * pcdFocus = pointer to the client data of the window with the focus or
1454 * the leader of the transient tree that contains the focus window;
1455 * the focus should not be set to the pcdFocus window or subordinates.
1457 * focusTime = timestamp to be used in setting the keyboard input focus.
1459 *************************************<->***********************************/
1461 void AutoResetKeyFocus (ClientData *pcdNoFocus, Time focusTime)
1463 ClientListEntry *pNextEntry;
1465 ClientData *pcdLastFocus = NULL;
1466 ClientData *pcdFocus;
1470 * Scan through the list of clients to find a window to get the focus.
1473 pNextEntry = ACTIVE_PSD->clientList;
1477 pCD = pNextEntry->pCD;
1478 if (!wmGD.systemModalActive ||
1479 (wmGD.systemModalClient == pCD))
1481 if ((pNextEntry->type != MINIMIZED_STATE) &&
1482 (pCD->clientState != MINIMIZED_STATE) &&
1484 (!(pCD->clientState & UNSEEN_STATE)) &&
1486 (pCD != pcdNoFocus))
1488 if (pCD->transientChildren)
1490 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1497 ((pcdLastFocus == NULL) ||
1498 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1500 pcdLastFocus = pcdFocus;
1504 pNextEntry = pNextEntry->nextSibling;
1509 * Set the focus if there is a window that is a good candidate for
1510 * getting the focus.
1515 Do_Focus_Key (pcdLastFocus, focusTime, ALWAYS_SET_FOCUS);
1520 * !!! Immediately set the focus indication !!!
1523 Do_Focus_Key ((ClientData *)NULL, focusTime, ALWAYS_SET_FOCUS);
1526 } /* END OF FUNCTION AutoResetKeyFocus */