2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these libraries and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
31 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
39 * include extern functions
41 #include "WmKeyFocus.h"
43 #include "WmColormap.h"
46 #include "WmFunction.h"
48 #include "WmProtocol.h"
49 #include "WmWinInfo.h"
50 #include "WmWinList.h"
58 static Boolean removeSelectGrab = True;
62 /*************************************<->*************************************
64 * InitKeyboardFocus ()
69 * This function sets the keyboard input focus to a client window or icon
70 * when the window manager starts up.
75 * wmGD = (keyboardFocusPolicy, colormapFocusPolicy)
77 *************************************<->***********************************/
79 void InitKeyboardFocus (void)
83 Boolean focusSet = False;
86 Window junk_win, root_returned;
87 int currentX, currentY;
91 * Set the keyboard focus based on the keyboard focus policy.
94 wmGD.keyboardFocus = NULL;
95 wmGD.nextKeyboardFocus = NULL;
97 for (scr = 0; scr < wmGD.numScreens; scr++)
99 if (wmGD.Screens[scr].managed)
101 wmGD.Screens[scr].focusPriority = 0;
103 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
106 * Set the keyboard focus to the window that
107 * currently contains the pointer.
110 pCD = GetClientUnderPointer (&sameScreen);
112 if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
115 * Do some colormap installation that has been
116 * deferred from the InitColormapFocus routine.
119 SetColormapFocus (ACTIVE_PSD, pCD);
124 Do_Focus_Key (pCD, GetTimestamp (), ALWAYS_SET_FOCUS);
130 ButtonSpec *buttonSpec;
133 * Prepare to do explicit selection button grabs.
136 buttonSpec = wmGD.Screens[scr].buttonSpecs;
139 if ((buttonSpec->button == FOCUS_SELECT_BUTTON) &&
140 (buttonSpec->context & F_CONTEXT_WINDOW) &&
141 (buttonSpec->subContext & F_SUBCONTEXT_W_CLIENT))
143 if (buttonSpec->state == 0)
145 removeSelectGrab = False;
148 buttonSpec = buttonSpec->nextButtonSpec;
158 * This is keyboard focus policy is either "explicit" or it it
160 * and there is no window under the pointer. No window currently has
161 * the keyboard input focus. Set the keyboard focus to the window
162 * manager default (non-client) OR to the last client with focus.
164 * In Mwm 1.1.4 and later, calling Do_Focus_Key with NULL will try
165 * to find a 'reasonable' window to put focus. This means that on
166 * startup and restarts, a Mwm window will have focus! Yeah!
170 * Set Active Screen First
172 if (XQueryPointer(DISPLAY, DefaultRootWindow(DISPLAY),
173 &root_returned, &junk_win,
174 ¤tX, ¤tY,
175 &junk, &junk, (unsigned int *)&junk))
177 for (scr = 0; scr < wmGD.numScreens; scr++)
179 if (wmGD.Screens[scr].managed &&
180 wmGD.Screens[scr].rootWindow == root_returned)
182 SetActiveScreen(&(wmGD.Screens[scr]));
188 Do_Focus_Key ((ClientData *)NULL, CurrentTime, ALWAYS_SET_FOCUS);
191 } /* END OF FUNCTION InitKeyboardFocus */
195 /*************************************<->*************************************
197 * SetKeyboardFocus (pCD, focusFlags)
202 * This function is used to handle a client window getting the input
203 * focus (as the RESULT of an XSetInput call - probably done by
209 * pCD = pointer to client data for window that is to get the focus
211 * focusFlags = flags that indicate focus change details
212 * {REFRESH_LAST_FOCUS}
217 * wmGD = (keyboardFocus)
219 *************************************<->***********************************/
221 void SetKeyboardFocus (ClientData *pCD, long focusFlags)
223 ClientData *currentFocus;
227 * Don't set the keyboard input focus if it is already set to
231 if (wmGD.keyboardFocus == pCD)
235 currentFocus = wmGD.keyboardFocus;
236 ACTIVE_PSD->focusPriority++;
240 * If the keyboard input focus policy is "explicit" then reset the
241 * selection button event handling.
244 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
247 * Reset explicit focus selection event tracking on the last focus
248 * window (reset the passive grab on the focus button).
253 ResetExplicitSelectHandling (currentFocus);
254 wmGD.keyboardFocus = NULL;
257 if (pCD && ((pCD->clientState == NORMAL_STATE) ||
258 (pCD->clientState == MAXIMIZED_STATE)))
261 * The focus is to be set to a client window (not the root).
262 * Stop explicit focus selection event tracking on the new focus
266 if (removeSelectGrab)
268 WmUngrabButton (DISPLAY, FOCUS_SELECT_BUTTON, 0,
274 wmGD.keyboardFocus = pCD;
278 * Do focus auto raise if specified.
281 if (pCD && pCD->focusAutoRaise)
283 if (wmGD.autoRaiseDelay &&
284 (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER))
286 AddWmTimer (TIMER_RAISE, (unsigned long)wmGD.autoRaiseDelay,
293 if (((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
294 (!pCD->focusAutoRaiseDisabled)) ||
295 ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) &&
296 (pCD == GetClientUnderPointer (&sameScreen))))
298 Do_Raise (pCD, (ClientListEntry *)NULL, STACK_NORMAL);
305 * Clear the focus indication if it is set for a client window or icon.
310 ClearFocusIndication (currentFocus,
311 ((focusFlags & REFRESH_LAST_FOCUS) ? True : False));
316 * Install the client window colormap if the colormap focus policy is
320 if ((wmGD.colormapFocusPolicy == CMAP_FOCUS_KEYBOARD) &&
321 (!(focusFlags & SCREEN_SWITCH_FOCUS)))
323 SetColormapFocus (ACTIVE_PSD, pCD);
328 * Set the focus window or icon visual indication.
333 pCD->focusPriority = ACTIVE_PSD->focusPriority;
334 SetFocusIndication (pCD);
337 } /* END OF FUNCTION SetKeyboardFocus */
341 /*************************************<->*************************************
343 * ResetExplicitSelectHandling (pCD)
348 * This function resets the selection button event handling for a client
349 * window or icon. This applies only if the keyboard focus policy is
355 * pCD = pointer to client data for window that has focus handling reset
357 *************************************<->***********************************/
359 void ResetExplicitSelectHandling (ClientData *pCD)
363 bUnseen = (pCD->clientState & UNSEEN_STATE) ? True : False;
365 pCD->clientState &= ~UNSEEN_STATE;
367 if ((pCD->clientState == NORMAL_STATE) ||
368 (pCD->clientState == MAXIMIZED_STATE))
371 * A client window was selected.
374 DoExplicitSelectGrab (pCD->clientBaseWin);
376 else if (pCD->clientState == MINIMIZED_STATE)
379 * An icon was selected.
382 /* !!! grab reset if client icon window? !!! */
386 pCD->clientState |= UNSEEN_STATE;
389 } /* END OF FUNCTION ResetExplicitSelectHandling */
393 /*************************************<->*************************************
395 * DoExplicitSelectGrab (window)
400 * This function is used to do a grab button on the specified window. The
401 * grab is intended to catch the keyboard focus select button.
406 * widow = grab widow for the select button
408 *************************************<->***********************************/
410 void DoExplicitSelectGrab (Window window)
413 WmGrabButton (DISPLAY, FOCUS_SELECT_BUTTON, 0, window,
414 False, ButtonReleaseMask, GrabModeSync, GrabModeSync, None,
417 } /* END OF FUNCTION DoExplicitSelectGrab */
421 /*************************************<->*************************************
423 * SetFocusIndication (pCD)
428 * This function changes the client window or icon decoration to have it
429 * indicate that the window or icon has the keyboard input focus.
434 * pCD = pointer to client data for window/icon that is getting the focus
437 *************************************<->***********************************/
439 void SetFocusIndication (ClientData *pCD)
444 * Set the "focus" to pCD to insure correct display of the frame
445 * This is necessary because the called routines get GCs based
446 * on the current keyboard focus.
448 saveCD = wmGD.keyboardFocus;
449 wmGD.keyboardFocus = pCD;
451 if ((pCD->clientState == NORMAL_STATE) ||
452 (pCD->clientState == MAXIMIZED_STATE))
455 * A client window has the input focus.
458 ShowActiveClientFrame (pCD);
460 else if (pCD->clientState == MINIMIZED_STATE)
463 * An icon has the input focus.
466 ShowActiveIcon (pCD);
469 /* restore old keyboard focus */
470 wmGD.keyboardFocus = saveCD;
472 } /* END OF FUNCTION SetFocusIndication */
476 /*************************************<->*************************************
478 * ClearFocusIndication (pCD, refresh)
483 * This function changes the client window or icon decoration to have it
484 * indicate that the window or icon does not have the keyboard input focus
485 * (i.e. it is inactive).
490 * pCD = pointer to client data for window/icon that is losing the focus
492 * refresh = True if window/icon frame is to redrawn
494 *************************************<->***********************************/
496 void ClearFocusIndication (ClientData *pCD, Boolean refresh)
502 * Set the "focus" to NULL to insure correct display of the frame
503 * This is necessary because the called routines get GCs based
504 * on the current keyboard focus.
507 saveCD = wmGD.keyboardFocus;
508 wmGD.keyboardFocus = NULL;
509 bUnseen = (pCD->clientState & UNSEEN_STATE) ? True : False;
511 pCD->clientState &= ~UNSEEN_STATE;
513 if ((pCD->clientState == NORMAL_STATE) ||
514 (pCD->clientState == MAXIMIZED_STATE))
517 * A client window no longer has the input focus.
520 ShowInactiveClientFrame (pCD);
522 else if (pCD->clientState == MINIMIZED_STATE)
525 * An icon no longer has the input focus.
528 ShowInactiveIcon (pCD, refresh);
532 pCD->clientState |= UNSEEN_STATE;
534 /* restore old keyboard focus */
535 wmGD.keyboardFocus = saveCD;
537 } /* END OF FUNCTION ClearFocusIndication */
541 /*************************************<->*************************************
543 * GetClientUnderPointer (pSameScreen)
548 * This function identifies the managed client window or icon that is under
554 * pSameScreen = pointer to flag that indicates if pointer is on the wm screen
556 * Return = client data pointer for the client window / icon under the
559 *************************************<->***********************************/
561 ClientData *GetClientUnderPointer (Boolean *pSameScreen)
573 if ((*pSameScreen = XQueryPointer (DISPLAY, ACTIVE_ROOT, &root, &child,
574 &rootX, &rootY, &winX, &winY, &mask)) != False)
577 !XFindContext (DISPLAY, child, wmGD.windowContextType,
581 * There is a client window or icon under the pointer.
590 } /* END OF FUNCTION GetClientUnderPointer */
594 /*************************************<->*************************************
596 * FocusNextWindow (type, focusTime)
601 * This function is used to change the focus to the next window in the
602 * window stacking order. The next focus window must be of the specified
603 * type(s). If the focus traversal cannot be done because there is not
604 * an object of the specified type (accepting focus) then don't change the
605 * focus (!!!should the focus be unset in this case!!!).
610 * type = type of objects to change the focus to
612 * focusTime = timestamp to be used for setting the input focus
614 *************************************<->***********************************/
616 Boolean FocusNextWindow (unsigned long type, Time focusTime)
618 ClientListEntry *pCurrentEntry;
619 ClientListEntry *pNextEntry;
620 Boolean focused = False;
625 * Identify the window or icon that currently has the focus and start
626 * traversing to the next object.
629 if (type & F_GROUP_TRANSIENT)
632 * Move the keyboard input focus around in a transient tree.
635 focused = FocusNextTransient (wmGD.keyboardFocus, type, False,
641 if (wmGD.systemModalActive)
645 else if (wmGD.keyboardFocus)
647 if (wmGD.keyboardFocus->transientLeader)
649 pCD = FindTransientTreeLeader (wmGD.keyboardFocus);
653 pCD = wmGD.keyboardFocus;
656 if (pCD->clientState == MINIMIZED_STATE)
658 pCurrentEntry = &pCD->iconEntry;
662 pCurrentEntry = &pCD->clientEntry;
665 pNextEntry = pCurrentEntry->nextSibling;
668 pNextEntry = ACTIVE_PSD->clientList;
673 pCurrentEntry = ACTIVE_PSD->clientList;
674 pNextEntry = pCurrentEntry;
679 while (!focused && pNextEntry)
681 focused = CheckForKeyFocus (pNextEntry, type, True /*next*/, focusTime);
684 pNextEntry = pNextEntry->nextSibling;
690 pNextEntry = ACTIVE_PSD->clientList;
691 while ((pNextEntry != pCurrentEntry) && !focused)
693 focused = CheckForKeyFocus (pNextEntry, type, True/*next*/,
697 pNextEntry = pNextEntry->nextSibling;
704 } /* END OF FUNCTION FocusNextWindow */
708 /*************************************<->*************************************
710 * FocusNextTransient (pCD, type, initiate, focusTime)
715 * This function is used to determine if another window in a transient
716 * tree should get the input focus.
720 * pCD = pointer to the client data for the client window that has the focus
722 * type = type of objects to change the focus to
724 * initiate = set True if transient focus traversal is to be initiated;
725 * set to False if transient focus traversal is to be continued
727 * focusTime = timestamp to be used to set the input focus
732 * RETURN = True if the focus window has been identified and the focus
733 * has been set (or is already set)
735 *************************************<->***********************************/
737 Boolean FocusNextTransient (ClientData *pCD, unsigned long type, Boolean initiate, Time focusTime)
739 Boolean focused = False;
740 unsigned long startAt;
741 ClientData *pcdLeader;
742 ClientData *pcdLowerLeader;
743 ClientData *pcdFocus;
746 if (initiate && !(type & F_GROUP_TRANSIENT))
749 * If in a transient tree focus on the last transient window that
753 if (pCD->transientChildren)
755 pcdFocus = FindLastTransientTreeFocus (pCD, (ClientData *)NULL);
756 if (pcdFocus != wmGD.keyboardFocus)
758 pcdLeader = FindTransientTreeLeader (pcdFocus);
759 if (wmGD.keyboardFocus && wmGD.keyboardFocus->focusAutoRaise &&
760 (wmGD.keyboardFocus != pcdLeader))
763 FindTransientTreeLeader (wmGD.keyboardFocus);
764 if (pcdLowerLeader == pcdLeader)
766 if (PutTransientBelowSiblings (wmGD.keyboardFocus))
768 RestackTransients (pcdLeader);
773 F_Lower (NULL, wmGD.keyboardFocus, (XEvent *) NULL);
776 Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
785 else if (pCD && (pCD->clientState != MINIMIZED_STATE) &&
786 (pCD->transientLeader || pCD->transientChildren))
788 startAt = (initiate) ? (ACTIVE_PSD->clientCounter + 1) :
790 pcdLeader = FindTransientTreeLeader (pCD);
791 pcdFocus = FindNextTFocusInSeq (pcdLeader, startAt);
792 if ((pcdFocus == NULL) && (type == F_GROUP_TRANSIENT))
795 * Wrap around and find a focus window.
798 pcdFocus = FindNextTFocusInSeq (pcdLeader,
799 (unsigned long) (ACTIVE_PSD->clientCounter + 1));
803 if (pcdFocus != wmGD.keyboardFocus)
805 if (wmGD.keyboardFocus && wmGD.keyboardFocus->focusAutoRaise &&
806 (wmGD.keyboardFocus != pcdLeader))
809 FindTransientTreeLeader (wmGD.keyboardFocus);
810 if (pcdLowerLeader == pcdLeader)
812 if (PutTransientBelowSiblings (wmGD.keyboardFocus))
814 RestackTransients (pcdLeader);
819 F_Lower (NULL, wmGD.keyboardFocus, (XEvent *)NULL);
822 Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
829 if (type == F_GROUP_TRANSIENT)
832 * Focus only within a transient tree. In this case the current
833 * or prospective focus is not within a transient tree so leave
834 * the focus where it is.
843 } /* END OF FUNCTION FocusNextTransient */
847 /*************************************<->*************************************
849 * FindLastTransientTreeFocus (pCD, pcdNoFocus)
854 * This function is used to scan a transient tree for the last window in
855 * the tree that had the focus.
859 * pCD = pointer to the client data for the transient tree (or subtree)
862 * pcdNoFocus = pointer to the client data for a client window that is not
863 * to get the input focus (NULL if no client window restriction).
867 * RETURN = pointer to the client data of the window that last had the
870 *************************************<->***********************************/
872 ClientData *FindLastTransientTreeFocus (ClientData *pCD, ClientData *pcdNoFocus)
876 ClientData *pcdFocus;
877 ClientData *pcdLastFocus = NULL;
880 pcdNext = pCD->transientChildren;
883 pcdFocus = FindLastTransientTreeFocus (pcdNext, pcdNoFocus);
885 (!IS_APP_MODALIZED(pcdFocus)) &&
886 ((pcdLastFocus == NULL) ||
887 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
889 pcdLastFocus = pcdFocus;
891 pcdNext = pcdNext->transientSiblings;
894 if ((!IS_APP_MODALIZED(pCD)) &&
895 ((pcdLastFocus == NULL) ||
896 (pCD->focusPriority > pcdLastFocus->focusPriority)))
901 return (pcdLastFocus);
904 } /* END OF FUNCTION FindLastTransientTreeFocus */
908 /*************************************<->*************************************
910 * FindNextTFocusInSeq (pCD, startAt)
915 * This function is used to scan a transient tree for the next window that
916 * can accept the focus.
920 * pCD = pointer to the client data for the transient tree (or subtree)
923 * startAt = focus window should have a lower id then this client id
928 * RETURN = pointer to the client data of the window that should get the
931 *************************************<->***********************************/
933 ClientData *FindNextTFocusInSeq (ClientData *pCD, unsigned long startAt)
935 ClientData *pcdNextFocus = NULL;
937 ClientData *pcdFocus;
940 pcdNext = pCD->transientChildren;
943 pcdFocus = FindNextTFocusInSeq (pcdNext, startAt);
946 if ((pcdNextFocus == NULL) ||
947 (pcdFocus->clientID > pcdNextFocus->clientID))
949 pcdNextFocus = pcdFocus;
952 pcdNext = pcdNext->transientSiblings;
955 if ((pcdNextFocus == NULL) ||
956 (pCD->clientID > pcdNextFocus->clientID))
958 if ((!IS_APP_MODALIZED(pCD)) && (pCD->clientID < startAt))
964 return (pcdNextFocus);
967 } /* END OF FUNCTION FindNextTFocusInSeq */
971 /*************************************<->*************************************
973 * FocusPrevWindow (type, focusTime)
978 * This function is used to change the focus to the previous window in the
979 * window stacking order. The next focus window must be of the specified
980 * type(s). If the focus traversal cannot be done because there is not
981 * an object of the specified type (accepting focus) then don't change the
982 * focus (!!!should the focus be unset in this case!!!).
987 * type = type of objects to change the focus to
989 * focusTime = timestamp to be used to set the input focus
991 *************************************<->***********************************/
993 Boolean FocusPrevWindow (unsigned long type, Time focusTime)
995 ClientListEntry *pCurrentEntry;
996 ClientListEntry *pNextEntry;
997 Boolean focused = False;
1002 * Identify the window or icon that currently has the focus and start
1003 * traversing to the previous object.
1006 if (type & F_GROUP_TRANSIENT)
1009 * Move the keyboard input focus around in a transient tree.
1012 focused = FocusPrevTransient (wmGD.keyboardFocus, type, False,
1018 if (wmGD.systemModalActive)
1022 else if (wmGD.keyboardFocus)
1024 if (wmGD.keyboardFocus->transientLeader)
1026 pCD = FindTransientTreeLeader (wmGD.keyboardFocus);
1030 pCD = wmGD.keyboardFocus;
1033 if (pCD->clientState == MINIMIZED_STATE)
1035 pCurrentEntry = &pCD->iconEntry;
1039 pCurrentEntry = &pCD->clientEntry;
1042 pNextEntry = pCurrentEntry->prevSibling;
1045 pNextEntry = ACTIVE_PSD->lastClient;
1050 pCurrentEntry = ACTIVE_PSD->lastClient;
1051 pNextEntry = pCurrentEntry;
1056 while (!focused && pNextEntry)
1058 focused = CheckForKeyFocus (pNextEntry, type, False /*previous*/,
1062 pNextEntry = pNextEntry->prevSibling;
1068 pNextEntry = ACTIVE_PSD->lastClient;
1069 while ((pNextEntry != pCurrentEntry) && !focused)
1071 focused = CheckForKeyFocus (pNextEntry, type, False/*previous*/,
1075 pNextEntry = pNextEntry->prevSibling;
1082 } /* END OF FUNCTION FocusPrevWindow */
1086 /*************************************<->*************************************
1088 * FocusPrevTransient (pCD, type, initiate, focusTime)
1093 * This function is used to determine if another (previous) window in a
1094 * transient tree should get the input focus.
1098 * pCD = pointer to the client data for the client window that has the focus
1100 * type = type of objects to change the focus to
1102 * initiate = set True if transient focus traversal is to be initiated;
1103 * set to False if transient focus traversal is to be continued
1105 * focusTime = timestamp to be used to set the input focus
1110 * RETURN = True if the focus window has been identified and the focus
1111 * has been set (or is already set)
1113 *************************************<->***********************************/
1115 Boolean FocusPrevTransient (ClientData *pCD, unsigned long type, Boolean initiate, Time focusTime)
1117 Boolean focused = False;
1118 unsigned long startAt;
1119 ClientData *pcdLeader;
1120 ClientData *pcdFocus;
1123 if (initiate && !(type & F_GROUP_TRANSIENT))
1126 * If in a transient tree focus on the last transient window that
1130 if (pCD->transientChildren)
1132 pcdFocus = FindLastTransientTreeFocus (pCD, (ClientData *)NULL);
1133 if (pcdFocus != wmGD.keyboardFocus)
1135 Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
1144 else if (pCD && (pCD->clientState != MINIMIZED_STATE) &&
1145 (pCD->transientLeader || pCD->transientChildren))
1147 startAt = (initiate) ? 0 : pCD->clientID;
1148 pcdLeader = FindTransientTreeLeader (pCD);
1149 pcdFocus = FindPrevTFocusInSeq (pcdLeader, startAt);
1150 if ((pcdFocus == NULL) && (type == F_GROUP_TRANSIENT))
1153 * Wrap around and find a focus window.
1156 pcdFocus = FindPrevTFocusInSeq (pcdLeader, 0);
1160 if (pcdFocus != wmGD.keyboardFocus)
1162 Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
1169 if (type == F_GROUP_TRANSIENT)
1172 * Focus only within a transient tree. In this case the current
1173 * or prospective focus is not within a transient tree so leave
1174 * the focus where it is.
1183 } /* END OF FUNCTION FocusPrevTransient */
1187 /*************************************<->*************************************
1189 * FindPrevTFocusInSeq (pCD, startAt)
1194 * This function is used to scan a transient tree for the previous window that
1195 * can accept the focus.
1199 * pCD = pointer to the client data for the transient tree (or subtree)
1202 * startAt = focus window should have a higher id then this client id
1207 * RETURN = pointer to the client data of the window that should get the
1210 *************************************<->***********************************/
1212 ClientData *FindPrevTFocusInSeq (ClientData *pCD, unsigned long startAt)
1214 ClientData *pcdNextFocus = NULL;
1215 ClientData *pcdNext;
1216 ClientData *pcdFocus;
1219 pcdNext = pCD->transientChildren;
1222 pcdFocus = FindPrevTFocusInSeq (pcdNext, startAt);
1225 if ((pcdNextFocus == NULL) ||
1226 (pcdFocus->clientID < pcdNextFocus->clientID))
1228 pcdNextFocus = pcdFocus;
1231 pcdNext = pcdNext->transientSiblings;
1234 if ((pcdNextFocus == NULL) ||
1235 (pCD->clientID < pcdNextFocus->clientID))
1237 if (!(IS_APP_MODALIZED(pCD)) && (pCD->clientID > startAt))
1243 return (pcdNextFocus);
1246 } /* END OF FUNCTION FindPrevTFocusInSeq */
1250 /*************************************<->*************************************
1252 * CheckForKeyFocus (pNextEntry, type, focusNext, focusTime)
1257 * This function is used to determine if a window is a worthy candidate for
1258 * getting the input focus (it is on-screen and is of the desired type).
1259 * If it is, the window gets the keyboard input focus.
1264 * pNextEntry = the client list entry to be checked
1266 * type = the desired type of the focus window
1268 * focusNext = if true then focus the next window in the window stack
1270 * focusTime = timestamp to be used to set the input focus
1275 * Return = True if the window gets the keyboard input focus otherwise False
1277 *************************************<->***********************************/
1279 Boolean CheckForKeyFocus (ClientListEntry *pNextEntry, unsigned long type, Boolean focusNext, Time focusTime)
1281 ClientData *pCD = pNextEntry->pCD;
1282 unsigned long windowType;
1283 Boolean focused = False;
1287 * First check for focusing within a transient tree.
1292 * Make sure the window is being displayed and is of the specified type.
1295 if (((pNextEntry->type == NORMAL_STATE) &&
1296 (!(pCD->clientState & UNSEEN_STATE)) &&
1297 (pCD->clientState != MINIMIZED_STATE)) ||
1298 ((pNextEntry->type == MINIMIZED_STATE) &&
1299 (pCD->clientState == MINIMIZED_STATE)))
1301 if (pCD->clientState == MINIMIZED_STATE)
1303 windowType = F_GROUP_ICON;
1309 focused = FocusNextTransient (pCD, type, True, focusTime);
1313 focused = FocusPrevTransient (pCD, type, True, focusTime);
1315 windowType = F_GROUP_WINDOW;
1316 if (pCD->transientLeader || pCD->transientChildren)
1318 windowType |= F_GROUP_TRANSIENT;
1322 if (!focused && (type & windowType))
1325 if (focusNext && wmGD.keyboardFocus &&
1326 wmGD.keyboardFocus->focusAutoRaise)
1328 F_Lower (NULL, wmGD.keyboardFocus, (XEvent *)NULL);
1330 Do_Focus_Key (pCD, focusTime, ALWAYS_SET_FOCUS);
1336 } /* END OF FUNCTION CheckForKeyFocus */
1340 /*************************************<->*************************************
1347 * This function sets the keyboard and colormap focus to a client
1348 * window or icon when the window manager is recovering from a
1349 * configuration action.
1358 * o we only need to repair keyboard focus policy is "pointer"
1360 *************************************<->***********************************/
1362 void RepairFocus (void)
1370 * Repair the keyboard and colormap focus based on the policies
1373 if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) ||
1374 (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER))
1377 * Move old enter and leave events and then get the window that
1378 * the pointer is currently in.
1381 XSync (DISPLAY, False);
1382 while (XCheckMaskEvent (DISPLAY, EnterWindowMask | LeaveWindowMask,
1387 pCD = GetClientUnderPointer (&sameScreen);
1390 * Set the keyboard focus to the window that currently contains the
1394 if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
1397 * This will also set colormap focus if it is CMAP_FOCUS_KEYBOARD.
1400 Do_Focus_Key (pCD, CurrentTime, ALWAYS_SET_FOCUS);
1402 else if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
1404 SetColormapFocus (ACTIVE_PSD, pCD);
1408 } /* END OF FUNCTION RepairFocus */
1412 /*************************************<->*************************************
1414 * AutoResetKeyFocus (pcdFocus, focusTime)
1419 * This function resets the keyboard input focus when a window with the
1420 * focus is withdrawn or iconified. The focus is set to the last window
1421 * that had the focus. The focus is not set to an icon.
1426 * pcdFocus = pointer to the client data of the window with the focus or
1427 * the leader of the transient tree that contains the focus window;
1428 * the focus should not be set to the pcdFocus window or subordinates.
1430 * focusTime = timestamp to be used in setting the keyboard input focus.
1432 *************************************<->***********************************/
1434 void AutoResetKeyFocus (ClientData *pcdNoFocus, Time focusTime)
1436 ClientListEntry *pNextEntry;
1438 ClientData *pcdLastFocus = NULL;
1439 ClientData *pcdFocus;
1443 * Scan through the list of clients to find a window to get the focus.
1446 pNextEntry = ACTIVE_PSD->clientList;
1450 pCD = pNextEntry->pCD;
1451 if (!wmGD.systemModalActive ||
1452 (wmGD.systemModalClient == pCD))
1454 if ((pNextEntry->type != MINIMIZED_STATE) &&
1455 (pCD->clientState != MINIMIZED_STATE) &&
1456 (!(pCD->clientState & UNSEEN_STATE)) &&
1457 (pCD != pcdNoFocus))
1459 if (pCD->transientChildren)
1461 pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
1468 ((pcdLastFocus == NULL) ||
1469 (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
1471 pcdLastFocus = pcdFocus;
1475 pNextEntry = pNextEntry->nextSibling;
1480 * Set the focus if there is a window that is a good candidate for
1481 * getting the focus.
1486 Do_Focus_Key (pcdLastFocus, focusTime, ALWAYS_SET_FOCUS);
1491 * !!! Immediately set the focus indication !!!
1494 Do_Focus_Key ((ClientData *)NULL, focusTime, ALWAYS_SET_FOCUS);
1497 } /* END OF FUNCTION AutoResetKeyFocus */