123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /*
- * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
- * ALL RIGHTS RESERVED
- */
- /*
- * Motif Release 1.2.3
- */
- /*
- * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
- /*
- * Included Files:
- */
- #include "WmGlobal.h"
- /*
- * include extern functions
- */
- #include "WmKeyFocus.h"
- #include "WmCDecor.h"
- #include "WmColormap.h"
- #include "WmEvent.h"
- #include "WmCEvent.h"
- #include "WmFunction.h"
- #include "WmIDecor.h"
- #include "WmProtocol.h"
- #include "WmWinInfo.h"
- #include "WmWinList.h"
- /*
- * Global Variables:
- */
- static Boolean removeSelectGrab = True;
- /*************************************<->*************************************
- *
- * InitKeyboardFocus ()
- *
- *
- * Description:
- * -----------
- * This function sets the keyboard input focus to a client window or icon
- * when the window manager starts up.
- *
- *
- * Inputs:
- * ------
- * wmGD = (keyboardFocusPolicy, colormapFocusPolicy)
- *
- *************************************<->***********************************/
- void InitKeyboardFocus (void)
- {
- ClientData *pCD;
- Boolean sameScreen;
- Boolean focusSet = False;
- int scr;
- int junk;
- Window junk_win, root_returned;
- int currentX, currentY;
- /*
- * Set the keyboard focus based on the keyboard focus policy.
- */
- wmGD.keyboardFocus = NULL;
- wmGD.nextKeyboardFocus = NULL;
- for (scr = 0; scr < wmGD.numScreens; scr++)
- {
- if (wmGD.Screens[scr].managed)
- {
- wmGD.Screens[scr].focusPriority = 0;
- if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
- {
- /*
- * Set the keyboard focus to the window that
- * currently contains the pointer.
- */
- pCD = GetClientUnderPointer (&sameScreen);
- if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
- {
- /*
- * Do some colormap installation that has been
- * deferred from the InitColormapFocus routine.
- */
- SetColormapFocus (ACTIVE_PSD, pCD);
- }
- if (pCD)
- {
- Do_Focus_Key (pCD, GetTimestamp (), ALWAYS_SET_FOCUS);
- focusSet = True;
- }
- }
- else
- {
- ButtonSpec *buttonSpec;
-
- /*
- * Prepare to do explicit selection button grabs.
- */
- buttonSpec = wmGD.Screens[scr].buttonSpecs;
- while (buttonSpec)
- {
- if ((buttonSpec->button == FOCUS_SELECT_BUTTON) &&
- (buttonSpec->context & F_CONTEXT_WINDOW) &&
- (buttonSpec->subContext & F_SUBCONTEXT_W_CLIENT))
- {
- if (buttonSpec->state == 0)
- {
- removeSelectGrab = False;
- }
- }
- buttonSpec = buttonSpec->nextButtonSpec;
- }
- }
- }
- }
- if (!focusSet)
- {
- /*
- * This is keyboard focus policy is either "explicit" or it it
- * "pointer"
- * and there is no window under the pointer. No window currently has
- * the keyboard input focus. Set the keyboard focus to the window
- * manager default (non-client) OR to the last client with focus.
- *
- * In Mwm 1.1.4 and later, calling Do_Focus_Key with NULL will try
- * to find a 'reasonable' window to put focus. This means that on
- * startup and restarts, a Mwm window will have focus! Yeah!
- */
- /*
- * Set Active Screen First
- */
- if (XQueryPointer(DISPLAY, DefaultRootWindow(DISPLAY),
- &root_returned, &junk_win,
- ¤tX, ¤tY,
- &junk, &junk, (unsigned int *)&junk))
- {
- for (scr = 0; scr < wmGD.numScreens; scr++)
- {
- if (wmGD.Screens[scr].managed &&
- wmGD.Screens[scr].rootWindow == root_returned)
- {
- SetActiveScreen(&(wmGD.Screens[scr]));
- break;
- }
- }
- }
- Do_Focus_Key ((ClientData *)NULL, CurrentTime, ALWAYS_SET_FOCUS);
- }
- } /* END OF FUNCTION InitKeyboardFocus */
- /*************************************<->*************************************
- *
- * SetKeyboardFocus (pCD, focusFlags)
- *
- *
- * Description:
- * -----------
- * This function is used to handle a client window getting the input
- * focus (as the RESULT of an XSetInput call - probably done by
- * Do_Focus_Key).
- *
- *
- * Inputs:
- * ------
- * pCD = pointer to client data for window that is to get the focus
- *
- * focusFlags = flags that indicate focus change details
- * {REFRESH_LAST_FOCUS}
- *
- *
- * Outputs:
- * -------
- * wmGD = (keyboardFocus)
- *
- *************************************<->***********************************/
- void SetKeyboardFocus (ClientData *pCD, long focusFlags)
- {
- ClientData *currentFocus;
-
- /*
- * Don't set the keyboard input focus if it is already set to
- * the client window.
- */
- if (wmGD.keyboardFocus == pCD)
- {
- return;
- }
- currentFocus = wmGD.keyboardFocus;
- ACTIVE_PSD->focusPriority++;
- /*
- * If the keyboard input focus policy is "explicit" then reset the
- * selection button event handling.
- */
- if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT)
- {
- /*
- * Reset explicit focus selection event tracking on the last focus
- * window (reset the passive grab on the focus button).
- */
- if (currentFocus)
- {
- ResetExplicitSelectHandling (currentFocus);
- wmGD.keyboardFocus = NULL;
- }
-
- if (pCD && ((pCD->clientState == NORMAL_STATE) ||
- (pCD->clientState == MAXIMIZED_STATE)))
- {
- /*
- * The focus is to be set to a client window (not the root).
- * Stop explicit focus selection event tracking on the new focus
- * window.
- */
- if (removeSelectGrab)
- {
- WmUngrabButton (DISPLAY, FOCUS_SELECT_BUTTON, 0,
- pCD->clientBaseWin);
- }
- }
- }
-
- wmGD.keyboardFocus = pCD;
- /*
- * Do focus auto raise if specified.
- */
- if (pCD && pCD->focusAutoRaise)
- {
- if (wmGD.autoRaiseDelay &&
- (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER))
- {
- AddWmTimer (TIMER_RAISE, (unsigned long)wmGD.autoRaiseDelay,
- pCD);
- }
- else
- {
- Boolean sameScreen;
- if (((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_EXPLICIT) &&
- (!pCD->focusAutoRaiseDisabled)) ||
- ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) &&
- (pCD == GetClientUnderPointer (&sameScreen))))
- {
- Do_Raise (pCD, (ClientListEntry *)NULL, STACK_NORMAL);
- }
- }
- }
- /*
- * Clear the focus indication if it is set for a client window or icon.
- */
- if (currentFocus)
- {
- ClearFocusIndication (currentFocus,
- ((focusFlags & REFRESH_LAST_FOCUS) ? True : False));
- }
- /*
- * Install the client window colormap if the colormap focus policy is
- * "keyboard".
- */
- if ((wmGD.colormapFocusPolicy == CMAP_FOCUS_KEYBOARD) &&
- (!(focusFlags & SCREEN_SWITCH_FOCUS)))
- {
- SetColormapFocus (ACTIVE_PSD, pCD);
- }
- /*
- * Set the focus window or icon visual indication.
- */
- if (pCD)
- {
- pCD->focusPriority = ACTIVE_PSD->focusPriority;
- SetFocusIndication (pCD);
- }
- } /* END OF FUNCTION SetKeyboardFocus */
- /*************************************<->*************************************
- *
- * ResetExplicitSelectHandling (pCD)
- *
- *
- * Description:
- * -----------
- * This function resets the selection button event handling for a client
- * window or icon. This applies only if the keyboard focus policy is
- * "explicit".
- *
- *
- * Inputs:
- * ------
- * pCD = pointer to client data for window that has focus handling reset
- *
- *************************************<->***********************************/
- void ResetExplicitSelectHandling (ClientData *pCD)
- {
- Boolean bUnseen;
- bUnseen = (pCD->clientState & UNSEEN_STATE) ? True : False;
- if (bUnseen)
- pCD->clientState &= ~UNSEEN_STATE;
- if ((pCD->clientState == NORMAL_STATE) ||
- (pCD->clientState == MAXIMIZED_STATE))
- {
- /*
- * A client window was selected.
- */
- DoExplicitSelectGrab (pCD->clientBaseWin);
- }
- else if (pCD->clientState == MINIMIZED_STATE)
- {
- /*
- * An icon was selected.
- */
- /* !!! grab reset if client icon window? !!! */
- }
- if (bUnseen)
- pCD->clientState |= UNSEEN_STATE;
-
- } /* END OF FUNCTION ResetExplicitSelectHandling */
- /*************************************<->*************************************
- *
- * DoExplicitSelectGrab (window)
- *
- *
- * Description:
- * -----------
- * This function is used to do a grab button on the specified window. The
- * grab is intended to catch the keyboard focus select button.
- *
- *
- * Inputs:
- * ------
- * widow = grab widow for the select button
- *
- *************************************<->***********************************/
- void DoExplicitSelectGrab (Window window)
- {
- WmGrabButton (DISPLAY, FOCUS_SELECT_BUTTON, 0, window,
- False, ButtonReleaseMask, GrabModeSync, GrabModeSync, None,
- None);
- } /* END OF FUNCTION DoExplicitSelectGrab */
- /*************************************<->*************************************
- *
- * SetFocusIndication (pCD)
- *
- *
- * Description:
- * -----------
- * This function changes the client window or icon decoration to have it
- * indicate that the window or icon has the keyboard input focus.
- *
- *
- * Inputs:
- * ------
- * pCD = pointer to client data for window/icon that is getting the focus
- *
- *
- *************************************<->***********************************/
- void SetFocusIndication (ClientData *pCD)
- {
- ClientData *saveCD;
- /*
- * Set the "focus" to pCD to insure correct display of the frame
- * This is necessary because the called routines get GCs based
- * on the current keyboard focus.
- */
- saveCD = wmGD.keyboardFocus;
- wmGD.keyboardFocus = pCD;
- if ((pCD->clientState == NORMAL_STATE) ||
- (pCD->clientState == MAXIMIZED_STATE))
- {
- /*
- * A client window has the input focus.
- */
- ShowActiveClientFrame (pCD);
- }
- else if (pCD->clientState == MINIMIZED_STATE)
- {
- /*
- * An icon has the input focus.
- */
- ShowActiveIcon (pCD);
- }
- /* restore old keyboard focus */
- wmGD.keyboardFocus = saveCD;
- } /* END OF FUNCTION SetFocusIndication */
- /*************************************<->*************************************
- *
- * ClearFocusIndication (pCD, refresh)
- *
- *
- * Description:
- * -----------
- * This function changes the client window or icon decoration to have it
- * indicate that the window or icon does not have the keyboard input focus
- * (i.e. it is inactive).
- *
- *
- * Inputs:
- * ------
- * pCD = pointer to client data for window/icon that is losing the focus
- *
- * refresh = True if window/icon frame is to redrawn
- *
- *************************************<->***********************************/
- void ClearFocusIndication (ClientData *pCD, Boolean refresh)
- {
- ClientData *saveCD;
- Boolean bUnseen;
- /*
- * Set the "focus" to NULL to insure correct display of the frame
- * This is necessary because the called routines get GCs based
- * on the current keyboard focus.
- */
- saveCD = wmGD.keyboardFocus;
- wmGD.keyboardFocus = NULL;
- bUnseen = (pCD->clientState & UNSEEN_STATE) ? True : False;
- if (bUnseen)
- pCD->clientState &= ~UNSEEN_STATE;
- if ((pCD->clientState == NORMAL_STATE) ||
- (pCD->clientState == MAXIMIZED_STATE))
- {
- /*
- * A client window no longer has the input focus.
- */
- ShowInactiveClientFrame (pCD);
- }
- else if (pCD->clientState == MINIMIZED_STATE)
- {
- /*
- * An icon no longer has the input focus.
- */
- ShowInactiveIcon (pCD, refresh);
- }
- if (bUnseen)
- pCD->clientState |= UNSEEN_STATE;
- /* restore old keyboard focus */
- wmGD.keyboardFocus = saveCD;
- } /* END OF FUNCTION ClearFocusIndication */
- /*************************************<->*************************************
- *
- * GetClientUnderPointer (pSameScreen)
- *
- *
- * Description:
- * -----------
- * This function identifies the managed client window or icon that is under
- * the pointer.
- *
- *
- * Outputs:
- * -------
- * pSameScreen = pointer to flag that indicates if pointer is on the wm screen
- *
- * Return = client data pointer for the client window / icon under the
- * mouse cursor
- *
- *************************************<->***********************************/
- ClientData *GetClientUnderPointer (Boolean *pSameScreen)
- {
- Window root;
- Window child;
- int rootX;
- int rootY;
- int winX;
- int winY;
- unsigned int mask;
- ClientData *pCD;
- if ((*pSameScreen = XQueryPointer (DISPLAY, ACTIVE_ROOT, &root, &child,
- &rootX, &rootY, &winX, &winY, &mask)) != False)
- {
- if (child &&
- !XFindContext (DISPLAY, child, wmGD.windowContextType,
- (caddr_t *)&pCD))
- {
- /*
- * There is a client window or icon under the pointer.
- */
- return (pCD);
- }
- }
- return (NULL);
- } /* END OF FUNCTION GetClientUnderPointer */
- /*************************************<->*************************************
- *
- * FocusNextWindow (type, focusTime)
- *
- *
- * Description:
- * -----------
- * This function is used to change the focus to the next window in the
- * window stacking order. The next focus window must be of the specified
- * type(s). If the focus traversal cannot be done because there is not
- * an object of the specified type (accepting focus) then don't change the
- * focus (!!!should the focus be unset in this case!!!).
- *
- *
- * Inputs:
- * ------
- * type = type of objects to change the focus to
- *
- * focusTime = timestamp to be used for setting the input focus
- *
- *************************************<->***********************************/
- Boolean FocusNextWindow (unsigned long type, Time focusTime)
- {
- ClientListEntry *pCurrentEntry;
- ClientListEntry *pNextEntry;
- Boolean focused = False;
- ClientData *pCD;
- /*
- * Identify the window or icon that currently has the focus and start
- * traversing to the next object.
- */
- if (type & F_GROUP_TRANSIENT)
- {
- /*
- * Move the keyboard input focus around in a transient tree.
- */
- focused = FocusNextTransient (wmGD.keyboardFocus, type, False,
- focusTime);
- }
- if (!focused)
- {
- if (wmGD.systemModalActive)
- {
- focused = True;
- }
- else if (wmGD.keyboardFocus)
- {
- if (wmGD.keyboardFocus->transientLeader)
- {
- pCD = FindTransientTreeLeader (wmGD.keyboardFocus);
- }
- else
- {
- pCD = wmGD.keyboardFocus;
- }
- if (pCD->clientState == MINIMIZED_STATE)
- {
- pCurrentEntry = &pCD->iconEntry;
- }
- else
- {
- pCurrentEntry = &pCD->clientEntry;
- }
- pNextEntry = pCurrentEntry->nextSibling;
- if (!pNextEntry)
- {
- pNextEntry = ACTIVE_PSD->clientList;
- }
- }
- else
- {
- pCurrentEntry = ACTIVE_PSD->clientList;
- pNextEntry = pCurrentEntry;
- }
- }
- while (!focused && pNextEntry)
- {
- focused = CheckForKeyFocus (pNextEntry, type, True /*next*/, focusTime);
- if (!focused)
- {
- pNextEntry = pNextEntry->nextSibling;
- }
- }
- if (!focused)
- {
- pNextEntry = ACTIVE_PSD->clientList;
- while ((pNextEntry != pCurrentEntry) && !focused)
- {
- focused = CheckForKeyFocus (pNextEntry, type, True/*next*/,
- focusTime);
- if (!focused)
- {
- pNextEntry = pNextEntry->nextSibling;
- }
- }
- }
- return (focused);
- } /* END OF FUNCTION FocusNextWindow */
- /*************************************<->*************************************
- *
- * FocusNextTransient (pCD, type, initiate, focusTime)
- *
- *
- * Description:
- * -----------
- * This function is used to determine if another window in a transient
- * tree should get the input focus.
- *
- * Inputs:
- * ------
- * pCD = pointer to the client data for the client window that has the focus
- *
- * type = type of objects to change the focus to
- *
- * initiate = set True if transient focus traversal is to be initiated;
- * set to False if transient focus traversal is to be continued
- *
- * focusTime = timestamp to be used to set the input focus
- *
- *
- * Outputs:
- * -------
- * RETURN = True if the focus window has been identified and the focus
- * has been set (or is already set)
- *
- *************************************<->***********************************/
- Boolean FocusNextTransient (ClientData *pCD, unsigned long type, Boolean initiate, Time focusTime)
- {
- Boolean focused = False;
- unsigned long startAt;
- ClientData *pcdLeader;
- ClientData *pcdLowerLeader;
- ClientData *pcdFocus;
- if (initiate && !(type & F_GROUP_TRANSIENT))
- {
- /*
- * If in a transient tree focus on the last transient window that
- * had the focus.
- */
- if (pCD->transientChildren)
- {
- pcdFocus = FindLastTransientTreeFocus (pCD, (ClientData *)NULL);
- if (pcdFocus != wmGD.keyboardFocus)
- {
- pcdLeader = FindTransientTreeLeader (pcdFocus);
- if (wmGD.keyboardFocus && wmGD.keyboardFocus->focusAutoRaise &&
- (wmGD.keyboardFocus != pcdLeader))
- {
- pcdLowerLeader =
- FindTransientTreeLeader (wmGD.keyboardFocus);
- if (pcdLowerLeader == pcdLeader)
- {
- if (PutTransientBelowSiblings (wmGD.keyboardFocus))
- {
- RestackTransients (pcdLeader);
- }
- }
- else
- {
- F_Lower (NULL, wmGD.keyboardFocus, (XEvent *) NULL);
- }
- }
- Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
- }
- focused = True;
- }
- else
- {
- focused = False;
- }
- }
- else if (pCD && (pCD->clientState != MINIMIZED_STATE) &&
- (pCD->transientLeader || pCD->transientChildren))
- {
- startAt = (initiate) ? (ACTIVE_PSD->clientCounter + 1) :
- pCD->clientID;
- pcdLeader = FindTransientTreeLeader (pCD);
- pcdFocus = FindNextTFocusInSeq (pcdLeader, startAt);
- if ((pcdFocus == NULL) && (type == F_GROUP_TRANSIENT))
- {
- /*
- * Wrap around and find a focus window.
- */
- pcdFocus = FindNextTFocusInSeq (pcdLeader,
- (unsigned long) (ACTIVE_PSD->clientCounter + 1));
- }
- if (pcdFocus)
- {
- if (pcdFocus != wmGD.keyboardFocus)
- {
- if (wmGD.keyboardFocus && wmGD.keyboardFocus->focusAutoRaise &&
- (wmGD.keyboardFocus != pcdLeader))
- {
- pcdLowerLeader =
- FindTransientTreeLeader (wmGD.keyboardFocus);
- if (pcdLowerLeader == pcdLeader)
- {
- if (PutTransientBelowSiblings (wmGD.keyboardFocus))
- {
- RestackTransients (pcdLeader);
- }
- }
- else
- {
- F_Lower (NULL, wmGD.keyboardFocus, (XEvent *)NULL);
- }
- }
- Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
- }
- focused = True;
- }
- }
- else
- {
- if (type == F_GROUP_TRANSIENT)
- {
- /*
- * Focus only within a transient tree. In this case the current
- * or prospective focus is not within a transient tree so leave
- * the focus where it is.
- */
- focused = True;
- }
- }
- return (focused);
- } /* END OF FUNCTION FocusNextTransient */
- /*************************************<->*************************************
- *
- * FindLastTransientTreeFocus (pCD, pcdNoFocus)
- *
- *
- * Description:
- * -----------
- * This function is used to scan a transient tree for the last window in
- * the tree that had the focus.
- *
- * Inputs:
- * ------
- * pCD = pointer to the client data for the transient tree (or subtree)
- * leader.
- *
- * pcdNoFocus = pointer to the client data for a client window that is not
- * to get the input focus (NULL if no client window restriction).
- *
- * Outputs:
- * -------
- * RETURN = pointer to the client data of the window that last had the
- * focus.
- *
- *************************************<->***********************************/
- ClientData *FindLastTransientTreeFocus (ClientData *pCD, ClientData *pcdNoFocus)
- {
- ClientData *pcdNext;
- ClientData *pcdFocus;
- ClientData *pcdLastFocus = NULL;
- pcdNext = pCD->transientChildren;
- while (pcdNext)
- {
- pcdFocus = FindLastTransientTreeFocus (pcdNext, pcdNoFocus);
- if (pcdFocus &&
- (!IS_APP_MODALIZED(pcdFocus)) &&
- ((pcdLastFocus == NULL) ||
- (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
- {
- pcdLastFocus = pcdFocus;
- }
- pcdNext = pcdNext->transientSiblings;
- }
- if ((!IS_APP_MODALIZED(pCD)) &&
- ((pcdLastFocus == NULL) ||
- (pCD->focusPriority > pcdLastFocus->focusPriority)))
- {
- pcdLastFocus = pCD;
- }
- return (pcdLastFocus);
- } /* END OF FUNCTION FindLastTransientTreeFocus */
- /*************************************<->*************************************
- *
- * FindNextTFocusInSeq (pCD, startAt)
- *
- *
- * Description:
- * -----------
- * This function is used to scan a transient tree for the next window that
- * can accept the focus.
- *
- * Inputs:
- * ------
- * pCD = pointer to the client data for the transient tree (or subtree)
- * leader.
- *
- * startAt = focus window should have a lower id then this client id
- *
- *
- * Outputs:
- * -------
- * RETURN = pointer to the client data of the window that should get the
- * focus.
- *
- *************************************<->***********************************/
- ClientData *FindNextTFocusInSeq (ClientData *pCD, unsigned long startAt)
- {
- ClientData *pcdNextFocus = NULL;
- ClientData *pcdNext;
- ClientData *pcdFocus;
- pcdNext = pCD->transientChildren;
- while (pcdNext)
- {
- pcdFocus = FindNextTFocusInSeq (pcdNext, startAt);
- if (pcdFocus)
- {
- if ((pcdNextFocus == NULL) ||
- (pcdFocus->clientID > pcdNextFocus->clientID))
- {
- pcdNextFocus = pcdFocus;
- }
- }
- pcdNext = pcdNext->transientSiblings;
- }
- if ((pcdNextFocus == NULL) ||
- (pCD->clientID > pcdNextFocus->clientID))
- {
- if ((!IS_APP_MODALIZED(pCD)) && (pCD->clientID < startAt))
- {
- pcdNextFocus = pCD;
- }
- }
- return (pcdNextFocus);
- } /* END OF FUNCTION FindNextTFocusInSeq */
- /*************************************<->*************************************
- *
- * FocusPrevWindow (type, focusTime)
- *
- *
- * Description:
- * -----------
- * This function is used to change the focus to the previous window in the
- * window stacking order. The next focus window must be of the specified
- * type(s). If the focus traversal cannot be done because there is not
- * an object of the specified type (accepting focus) then don't change the
- * focus (!!!should the focus be unset in this case!!!).
- *
- *
- * Inputs:
- * ------
- * type = type of objects to change the focus to
- *
- * focusTime = timestamp to be used to set the input focus
- *
- *************************************<->***********************************/
- Boolean FocusPrevWindow (unsigned long type, Time focusTime)
- {
- ClientListEntry *pCurrentEntry;
- ClientListEntry *pNextEntry;
- Boolean focused = False;
- ClientData *pCD;
- /*
- * Identify the window or icon that currently has the focus and start
- * traversing to the previous object.
- */
- if (type & F_GROUP_TRANSIENT)
- {
- /*
- * Move the keyboard input focus around in a transient tree.
- */
- focused = FocusPrevTransient (wmGD.keyboardFocus, type, False,
- focusTime);
- }
-
- if (!focused)
- {
- if (wmGD.systemModalActive)
- {
- focused = True;
- }
- else if (wmGD.keyboardFocus)
- {
- if (wmGD.keyboardFocus->transientLeader)
- {
- pCD = FindTransientTreeLeader (wmGD.keyboardFocus);
- }
- else
- {
- pCD = wmGD.keyboardFocus;
- }
- if (pCD->clientState == MINIMIZED_STATE)
- {
- pCurrentEntry = &pCD->iconEntry;
- }
- else
- {
- pCurrentEntry = &pCD->clientEntry;
- }
- pNextEntry = pCurrentEntry->prevSibling;
- if (!pNextEntry)
- {
- pNextEntry = ACTIVE_PSD->lastClient;
- }
- }
- else
- {
- pCurrentEntry = ACTIVE_PSD->lastClient;
- pNextEntry = pCurrentEntry;
- }
- }
- while (!focused && pNextEntry)
- {
- focused = CheckForKeyFocus (pNextEntry, type, False /*previous*/,
- focusTime);
- if (!focused)
- {
- pNextEntry = pNextEntry->prevSibling;
- }
- }
- if (!focused)
- {
- pNextEntry = ACTIVE_PSD->lastClient;
- while ((pNextEntry != pCurrentEntry) && !focused)
- {
- focused = CheckForKeyFocus (pNextEntry, type, False/*previous*/,
- focusTime);
- if (!focused)
- {
- pNextEntry = pNextEntry->prevSibling;
- }
- }
- }
- return (focused);
- } /* END OF FUNCTION FocusPrevWindow */
- /*************************************<->*************************************
- *
- * FocusPrevTransient (pCD, type, initiate, focusTime)
- *
- *
- * Description:
- * -----------
- * This function is used to determine if another (previous) window in a
- * transient tree should get the input focus.
- *
- * Inputs:
- * ------
- * pCD = pointer to the client data for the client window that has the focus
- *
- * type = type of objects to change the focus to
- *
- * initiate = set True if transient focus traversal is to be initiated;
- * set to False if transient focus traversal is to be continued
- *
- * focusTime = timestamp to be used to set the input focus
- *
- *
- * Outputs:
- * -------
- * RETURN = True if the focus window has been identified and the focus
- * has been set (or is already set)
- *
- *************************************<->***********************************/
- Boolean FocusPrevTransient (ClientData *pCD, unsigned long type, Boolean initiate, Time focusTime)
- {
- Boolean focused = False;
- unsigned long startAt;
- ClientData *pcdLeader;
- ClientData *pcdFocus;
- if (initiate && !(type & F_GROUP_TRANSIENT))
- {
- /*
- * If in a transient tree focus on the last transient window that
- * had the focus.
- */
- if (pCD->transientChildren)
- {
- pcdFocus = FindLastTransientTreeFocus (pCD, (ClientData *)NULL);
- if (pcdFocus != wmGD.keyboardFocus)
- {
- Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
- }
- focused = True;
- }
- else
- {
- focused = False;
- }
- }
- else if (pCD && (pCD->clientState != MINIMIZED_STATE) &&
- (pCD->transientLeader || pCD->transientChildren))
- {
- startAt = (initiate) ? 0 : pCD->clientID;
- pcdLeader = FindTransientTreeLeader (pCD);
- pcdFocus = FindPrevTFocusInSeq (pcdLeader, startAt);
- if ((pcdFocus == NULL) && (type == F_GROUP_TRANSIENT))
- {
- /*
- * Wrap around and find a focus window.
- */
- pcdFocus = FindPrevTFocusInSeq (pcdLeader, 0);
- }
- if (pcdFocus)
- {
- if (pcdFocus != wmGD.keyboardFocus)
- {
- Do_Focus_Key (pcdFocus, focusTime, ALWAYS_SET_FOCUS);
- }
- focused = True;
- }
- }
- else
- {
- if (type == F_GROUP_TRANSIENT)
- {
- /*
- * Focus only within a transient tree. In this case the current
- * or prospective focus is not within a transient tree so leave
- * the focus where it is.
- */
- focused = True;
- }
- }
- return (focused);
- } /* END OF FUNCTION FocusPrevTransient */
- /*************************************<->*************************************
- *
- * FindPrevTFocusInSeq (pCD, startAt)
- *
- *
- * Description:
- * -----------
- * This function is used to scan a transient tree for the previous window that
- * can accept the focus.
- *
- * Inputs:
- * ------
- * pCD = pointer to the client data for the transient tree (or subtree)
- * leader.
- *
- * startAt = focus window should have a higher id then this client id
- *
- *
- * Outputs:
- * -------
- * RETURN = pointer to the client data of the window that should get the
- * focus.
- *
- *************************************<->***********************************/
- ClientData *FindPrevTFocusInSeq (ClientData *pCD, unsigned long startAt)
- {
- ClientData *pcdNextFocus = NULL;
- ClientData *pcdNext;
- ClientData *pcdFocus;
- pcdNext = pCD->transientChildren;
- while (pcdNext)
- {
- pcdFocus = FindPrevTFocusInSeq (pcdNext, startAt);
- if (pcdFocus)
- {
- if ((pcdNextFocus == NULL) ||
- (pcdFocus->clientID < pcdNextFocus->clientID))
- {
- pcdNextFocus = pcdFocus;
- }
- }
- pcdNext = pcdNext->transientSiblings;
- }
- if ((pcdNextFocus == NULL) ||
- (pCD->clientID < pcdNextFocus->clientID))
- {
- if (!(IS_APP_MODALIZED(pCD)) && (pCD->clientID > startAt))
- {
- pcdNextFocus = pCD;
- }
- }
- return (pcdNextFocus);
- } /* END OF FUNCTION FindPrevTFocusInSeq */
- /*************************************<->*************************************
- *
- * CheckForKeyFocus (pNextEntry, type, focusNext, focusTime)
- *
- *
- * Description:
- * -----------
- * This function is used to determine if a window is a worthy candidate for
- * getting the input focus (it is on-screen and is of the desired type).
- * If it is, the window gets the keyboard input focus.
- *
- *
- * Inputs:
- * ------
- * pNextEntry = the client list entry to be checked
- *
- * type = the desired type of the focus window
- *
- * focusNext = if true then focus the next window in the window stack
- *
- * focusTime = timestamp to be used to set the input focus
- *
- *
- * Outputs:
- * -------
- * Return = True if the window gets the keyboard input focus otherwise False
- *
- *************************************<->***********************************/
- Boolean CheckForKeyFocus (ClientListEntry *pNextEntry, unsigned long type, Boolean focusNext, Time focusTime)
- {
- ClientData *pCD = pNextEntry->pCD;
- unsigned long windowType;
- Boolean focused = False;
- /*
- * First check for focusing within a transient tree.
- */
- /*
- * Make sure the window is being displayed and is of the specified type.
- */
- if (((pNextEntry->type == NORMAL_STATE) &&
- (!(pCD->clientState & UNSEEN_STATE)) &&
- (pCD->clientState != MINIMIZED_STATE)) ||
- ((pNextEntry->type == MINIMIZED_STATE) &&
- (pCD->clientState == MINIMIZED_STATE)))
- {
- if (pCD->clientState == MINIMIZED_STATE)
- {
- windowType = F_GROUP_ICON;
- }
- else
- {
- if (focusNext)
- {
- focused = FocusNextTransient (pCD, type, True, focusTime);
- }
- else
- {
- focused = FocusPrevTransient (pCD, type, True, focusTime);
- }
- windowType = F_GROUP_WINDOW;
- if (pCD->transientLeader || pCD->transientChildren)
- {
- windowType |= F_GROUP_TRANSIENT;
- }
- }
- if (!focused && (type & windowType))
- {
- focused = True;
- if (focusNext && wmGD.keyboardFocus &&
- wmGD.keyboardFocus->focusAutoRaise)
- {
- F_Lower (NULL, wmGD.keyboardFocus, (XEvent *)NULL);
- }
- Do_Focus_Key (pCD, focusTime, ALWAYS_SET_FOCUS);
- }
- }
- return (focused);
- } /* END OF FUNCTION CheckForKeyFocus */
- /*************************************<->*************************************
- *
- * RepairFocus ()
- *
- *
- * Description:
- * -----------
- * This function sets the keyboard and colormap focus to a client
- * window or icon when the window manager is recovering from a
- * configuration action.
- *
- *
- * Inputs:
- * ------
- *
- *
- * Comments:
- * --------
- * o we only need to repair keyboard focus policy is "pointer"
- *
- *************************************<->***********************************/
- void RepairFocus (void)
- {
- ClientData *pCD;
- Boolean sameScreen;
- XEvent event;
- /*
- * Repair the keyboard and colormap focus based on the policies
- */
- if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) ||
- (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER))
- {
- /*
- * Move old enter and leave events and then get the window that
- * the pointer is currently in.
- */
- XSync (DISPLAY, False);
- while (XCheckMaskEvent (DISPLAY, EnterWindowMask | LeaveWindowMask,
- &event))
- {
- }
- pCD = GetClientUnderPointer (&sameScreen);
- /*
- * Set the keyboard focus to the window that currently contains the
- * pointer.
- */
- if (wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER)
- {
- /*
- * This will also set colormap focus if it is CMAP_FOCUS_KEYBOARD.
- */
- Do_Focus_Key (pCD, CurrentTime, ALWAYS_SET_FOCUS);
- }
- else if (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER)
- {
- SetColormapFocus (ACTIVE_PSD, pCD);
- }
- }
- } /* END OF FUNCTION RepairFocus */
- /*************************************<->*************************************
- *
- * AutoResetKeyFocus (pcdFocus, focusTime)
- *
- *
- * Description:
- * -----------
- * This function resets the keyboard input focus when a window with the
- * focus is withdrawn or iconified. The focus is set to the last window
- * that had the focus. The focus is not set to an icon.
- *
- *
- * Inputs:
- * ------
- * pcdFocus = pointer to the client data of the window with the focus or
- * the leader of the transient tree that contains the focus window;
- * the focus should not be set to the pcdFocus window or subordinates.
- *
- * focusTime = timestamp to be used in setting the keyboard input focus.
- *
- *************************************<->***********************************/
- void AutoResetKeyFocus (ClientData *pcdNoFocus, Time focusTime)
- {
- ClientListEntry *pNextEntry;
- ClientData *pCD;
- ClientData *pcdLastFocus = NULL;
- ClientData *pcdFocus;
- /*
- * Scan through the list of clients to find a window to get the focus.
- */
- pNextEntry = ACTIVE_PSD->clientList;
- while (pNextEntry)
- {
- pCD = pNextEntry->pCD;
- if (!wmGD.systemModalActive ||
- (wmGD.systemModalClient == pCD))
- {
- if ((pNextEntry->type != MINIMIZED_STATE) &&
- (pCD->clientState != MINIMIZED_STATE) &&
- (!(pCD->clientState & UNSEEN_STATE)) &&
- (pCD != pcdNoFocus))
- {
- if (pCD->transientChildren)
- {
- pcdFocus = FindLastTransientTreeFocus (pCD, pcdNoFocus);
- }
- else
- {
- pcdFocus = pCD;
- }
- if (pcdFocus &&
- ((pcdLastFocus == NULL) ||
- (pcdFocus->focusPriority > pcdLastFocus->focusPriority)))
- {
- pcdLastFocus = pcdFocus;
- }
- }
- }
- pNextEntry = pNextEntry->nextSibling;
- }
- /*
- * Set the focus if there is a window that is a good candidate for
- * getting the focus.
- */
- if (pcdLastFocus)
- {
- Do_Focus_Key (pcdLastFocus, focusTime, ALWAYS_SET_FOCUS);
- }
- else
- {
- /*
- * !!! Immediately set the focus indication !!!
- */
- Do_Focus_Key ((ClientData *)NULL, focusTime, ALWAYS_SET_FOCUS);
- }
- } /* END OF FUNCTION AutoResetKeyFocus */
|