diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/focus_tracking.txt | 161 |
1 files changed, 0 insertions, 161 deletions
diff --git a/docs/focus_tracking.txt b/docs/focus_tracking.txt deleted file mode 100644 index f3576c180c..0000000000 --- a/docs/focus_tracking.txt +++ /dev/null @@ -1,161 +0,0 @@ -Notational conventions -====================== - -We have a window W that we are tracking events on. Focus -can be on the following classes of objects - - None : defined by X protocol - PointerRoot : defined by X protocol - W : the window itself - Ancestor : An ancestor of W, including W's root window - Descendant : A descendant of W - Other: : A window that is neither an ancestor or - descendant of W - -has_pointer(W): the pointer is in W or one of its descendants. - -NotifyPointer events -==================== - -X sends FocusIn or FocusOut events to W with a detail of NotifyPointer -in the following transitions, when the pointer is inside W - - Other => Ancestor: FocusIn - Ancestor => {Other,None}: FocusOut - Ancestor => PointerRoot: FocusOut, then FocusIn - {None,W,Descendant,Other} => PointerRoot: FocusIn - PointerRoot => Ancestor: FocusOut, then FocusIn - PointerRoot => {None,W,Descendant,Other} => FocusOut - -[ Ignoring keyboard grabs for the moment ] - -Basic focus tracking algorithm -============================== - -Keystroke events are delivered within W if and only if one of two -predicates hold: - - has_focus_window(W): F==W || F==Descendant - has_pointer_focus(W): (F==Ancestor || F==PointerRoot) && has_pointer(W) - -These two conditions are mutually exclusive. - -has_focus_window(W) is easy to track. - - FocusIn: detail != NotifyInferior: Set has_focus_iwndow - FocusOut: detail != NotifyInferior: Clear has_focus_iwndow - -has_pointer_focus(W) is harder to track. - -We can separate out the transitions from !has_pointer_focus(W) to -has_pointer_focus(W) into four cases: - - T1: [(F==W || F==Descendant) => F==Ancestor]; has_pointer(W) - - T2: [(F==W || F==Descendant) => F==PointerRoot]; has_pointer(W) - - T3: [(F==None || F==Other) => (F==PointerRoot || F==Ancestor)]; - has_pointer(W) - - T4: [!has_pointer(W) => has_pointer(W)]; (F==Ancestor || F==PointerRoot) - -All of these can be tracked by watching events on W. - -T1:, we get a FocusOut with a mode of Ancestor or Virtual - We need to separately track has_pointer(W) to distinguish - this from the case where we get these events and !has_pointer(W) - -T2, T3: together these are exactly the cases where we get - FocusIn/NotifyPointer. - -For T4, we get an EnterNotify with the focus flag set. An - EnterNotify with a focus flag set will also be sent if - F==W, so we have to to explicitly test for that case - using has_focus_window(W) - - -The transitions from has_pointer_focus(W) to !has_pointer_focus(W) -are exactly the opposite - - F1: [(F==W || F==Descendant) <= F==Ancestor]; has_pointer(W) - - F2: [(F==W || F==Descendant) <= F==PointerRoot]; has_pointer(W) - - F3: [(F==None || F==Other) <= (F==PointerRoot || F==Ancestor)]; - has_pointer(W) - - F4: [!has_pointer(W) <= has_pointer(W)]; (F==Ancestor || F==PointerRoot) - -And can be tracked in the same ways: - -F1: we get a FocusIn with a mode of Ancestor or Virtual - We need to separately track has_pointer(W) to distinguish - this from the case we get these events and !has_pointer(W) - -F2, F3: together these are exactly the cases where we get - FocusOut/NotifyPointer. - -F4: we get an LeaveNotify with the focus flag set. An - LeaveNotify with a focus flag set will also be sent if - F==W, so we have to to explicitly test for that case - using has_focus_window(W). - - -Modifications for keyboard grabs -================================ - -The above algorithm ignores keyboard grabs, which also -generate focus events, and needs to be modified somewhat -to take keyboard grabs into effect. The basic idea -is that for has_pointer_focus(W)/has_window_focus(W) we track -them ignoring grabs and ungrabs, and then supplement -that with another predicate has_focus(W) which pays -attention to grabs and ungrabs. - -Modification 1: - - When tracking has_pointer_focus(W), ignore all Focus - events with a mode of NotifyGrab or NotifyUngrab. - - Note that this means that with grabs, we don't perfectly. - track the delivery of keyboard events ... since we think - we are getting events in the case where - - has_pointer_focus(W) && !(G == None || G==W || G==descendant) - - But the X protocol doesn't provide sufficient information - to do this right... example: - - F=Ancestor, G=None => F=Ancestor, G=Ancestor - - We stop getting events, but receive no notification. - - The case of no window manager and keyboard grabs is pretty - rare in any case. - -Modification 2: - - When tracking has_focus_window(W), ignore all Focus - events with a mode of NotifyGrab or NotifyUngrab. - -Modification 3: instead of calculating focus as - - has_focus_window(W) || has_pointer_focus(W) - - Calculate it as - - has_focus(W) || has_pointer_focus(W) - - where has_focus(W) is defined as: - - has_focus(W): F==W || F==Descendant || G=W - - Tracking has_focus(W) is done by - - FocusIn: detail != NotifyInferior, mode != NotifyWhileGrabbed: - set has_focus - FocusOut: detail != NotifyInferior, mode != NotifyWhileGrabbed: - clear has_focus - - We still need to track has_focus_window(W) for the T4/F4 - transitions. |