FocusIn and FocusOut events occur when the keyboard focus window changes as a result of an XSetInputFocus() call. They are much like EnterNotify and LeaveNotify events except that they track the focus rather than the pointer.
When a focus change occurs, a FocusOut event is delivered to the old focus window and a FocusIn event to the window which receives the focus. In addition, windows in between these two windows in the window hierarchy are virtually crossed and receive focus change events, as described below. Some or all of the windows between the window containing the pointer at the time of the focus change and the root window also receive focus change events, as described below.
FocusIn and FocusOut events are selected with FocusChangeMask. They cannot be selected separately.
typedef struct { int type; /* FocusIn or FocusOut */ unsigned long serial; /* # of last request processed by server */ Bool send_event; /* True if this came from SendEvent request */ Display *display; /* Display the event was read from */ Window window; /* Window of event */ int mode; /* NotifyNormal, NotifyGrab, NotifyUngrab */ int detail; /* NotifyAncestor, NotifyDetailNone, * NotifyInferior, NotifyNonLinear, * NotifyNonLinearVirtual, NotifyPointer, * NotifyPointerRoot, NotifyVirtual */ } XFocusChangeEvent; typedef XFocusChangeEvent XFocusInEvent; typedef XFocusChangeEvent XFocusOutEvent; |
mode | For events generated when the keyboard is not grabbed, mode is NotifyNormal; when the keyboard is grabbed, mode is NotifyGrab; and when a keyboard is ungrabbed, mode is NotifyUngrab. | |
detail | The detail member identifies the relationship between the window that receives the event and the origin and destination windows. It will be described in detail after the description of which windows get what types of events. |
The keyboard focus is a window that has been designated as the one to receive all keyboard input irrespective of the pointer position. Only the keyboard focus window and its descendants receive keyboard events. By default, the focus window is the root window. Since all windows are descendants of the root, the pointer controls the window that receives input.
Most window managers allow the user to set a focus window to avoid the problem where the pointer sometimes gets bumped into the wrong window and your typing does not go to the intended window. If the pointer is pointing at the root window, all typing is usually lost, since there is no application for this input to propagate to. Some applications may set the keyboard focus so that they can get all keyboard input for a given period of time, but this practice is not encouraged.
Focus events are used when an application wants to act differently when the keyboard focus is set to another window or to itself. FocusChangeMask is used to select FocusIn and FocusOut events.
When a focus change occurs, a FocusOut event is delivered to the old focus window and a FocusIn event is delivered to the window which receives the focus. Windows in between in the hierarchy are virtually crossed and receive one focus change event each depending on the relationship and direction of transfer between the origin and destination windows. Some or all of the windows between the window containing the pointer at the time of the focus change and that window's root window can also receive focus change events. By checking the detail member of FocusIn and FocusOut events, an application can tell which of its windows can receive input.
The detail member gives clues about the relationship of the event receiving window to the origin and destination of the focus. The detail member of FocusIn and FocusOut events is analogous to the detail member of EnterNotify and LeaveNotify events but with even more permutations to make life complicated.
We will now embark on specifying the types of events sent to each window and the detail member in each event, depending on the relative position in the hierarchy of the origin window (old focus), destination window (new focus), and the pointer window (window containing pointer at time of focus change). Don't even try to figure this out unless you have to.
E-3 shows the event types generated by a focus transition from window A to window B when window C is the least common ancestor of A and B. This table includes most of the events generated, but not all of them. It is quite possible for a single window to receive more than one focus change event from a single focus change.
Table E-3. FocusIn and FocusOut Events and Window Relationship
FocusOut | FocusIn |
---|---|
Origin window (A) | Destination window (B) |
Windows between A and B, exclusive, if A is inferior | Windows between A and B, exclusive, if B is inferior |
Windows between A and C, exclusive | Windows between B and C, exclusive |
Root window on screen of origin if different from screen of destination | Root window on screen of destination if different from screen of origin |
Pointer window up to but not including origin window if pointer window is descendant of origin | Pointer window up to but not including destination window if pointer window is descendant of destination |
Pointer window up to and including pointer window's root if transfer was from PointerRoot | Pointer window up to and including pointer window's root if transfer was to PointerRoot |
E-4 lists the detail members in events generated by a focus transition from window A to window B when window C is the least common ancestor of A and B, with P being the window containing the pointer.
Table E-4. Event detail Member and Window Relationship
detail Flag | Window Delivered To |
---|---|
NotifyAncestor | Origin or destination when either is descendant |
NotifyInferior | Origin or destination when either is ancestor |
NotifyVirtual | Windows between A and B, exclusive, if either is descendant |
NotifyNonlinear | Origin and destination when A and B are two or more windows distant from least common ancestor C |
NotifyNonlinearVirtual | Windows between A and C, exclusive, and between B and C, exclusive, when A and B have least common ancestor C; also on both root windows if A and B are on different screens |
NotifyPointer | Window P and windows up to but not including the origin or destination windows |
NotifyPointerRoot | Window P and all windows up to its root, and all other roots, when focus is set to or from PointerRoot |
NotifyDetailNone | All roots, when focus is set to or from None |
In any branch, there may be windows that are not shown. Windows in a single branch between two boxes shown will get the event types and details shown beside the branch.
FocusIn and FocusOut events are also generated when the keyboard is grabbed, if the focus was not already assigned to the grabbing window. In this case, all windows receive events as if the focus was set from the current focus to the grab window. When the grab is released, the events generated are just as if the focus was set back.