After adding lots of tracing intrumentation (printf debugging...) I've come to the following analysis. If you want to follow along, get the file event_handlers.c handy, with the function HandleEnterNotify().
This does a lot of stuff first that is not so relevant to our
discussion. Then it gets to
if(Tmp_win->mapped) {
/*
* unhighlight old focus window
*/
/*
* If entering the frame or the icon manager, then do
* "window activation things":
*
* 1. <highlighting is not done here any more>
* 2. install frame colormap
* 3. <frame and highlight border not set here>
* 4. focus on client window to forward typing
* 4a. same as 4 but for icon mgr w/with NoTitleFocus
* 5. send WM_TAKE_FOCUS if requested
*/
Here we have Scr->SloppyFocus is TRUE and Scr->TitleFocus is FALSE.
Let's assume we're having normal windows which accept input, so
Tmp_win->wmhints->input is TRUE.
Windows are first entered in their wrapper Tmp_win->frame, if the mouse
enters further it reaches Tmp_win->w, the application window itself.
Since TitleFocus is false, several things that are normally done on
entering frame should now be done later when entering w.
One thing that happens in this situation is
SynthesiseFocusIn(Tmp_win->w). So my first plan of attack was to also
SynthesiseFocusOut(Scr->Focus->w), the previously focused window.
This plan failed, because HandleFocusOut() ignores these synthetic
messages just like it ignores the real FocusOut message.
Another plan is to duplicate the actions when entering the frame a bit
better (but only when TitleFocus is FALSE).
Here it turns out that SetFocus() is NOT called in this case. That seems
to be because these nested conditions are ordered unfortunately:
/* must deal with WM_TAKE_FOCUS clients now, if
we're not in TitleFocus mode */
if(!(Scr->TitleFocus) &&
(Tmp_win->protocols & DoesWmTakeFocus))
{
/* locally active clients need help from WM
to get the input focus */
if(Tmp_win->wmhints->input) {
SetFocus(Tmp_win, ewp->time);
}
/* for both locally & globally active clnts */
SendTakeFocusMessage(Tmp_win, ewp->time);
}
We have nothing to do with DoesWmTakeFocus so this whole fragment is
never executed. I re-ordered it like below, and the results are a lot
better.
if(!Scr->TitleFocus) {
if(Tmp_win->wmhints->input) {
SetFocus(Tmp_win, ewp->time);
}
if (Tmp_win->protocols & DoesWmTakeFocus) {
SendTakeFocusMessage(Tmp_win, ewp->time);
}
}
This doesn't bring both cases (entering frame and w) in perfect
agreement but it is at least closer.
I've been wondering about the use of SynthesiseFocusIn().
SetFocus() does mostly the same as what HandleFocusOut() followed by
HandleFocusIn() does, plus an actual call to XSetInputFocus(). And those
are the exact functions that get called to handle the synthetic focus
messages. It would be cleaner perhaps to have either one method or the
other but not both.
The code as is may call both SynthesiseFocusIn() and SetFocus(). It
won't hurt since code will check if focus is already set, but I wonder
about the usefulness of SynthesiseFocusIn() in general, and if it is
useful, if it shouldn't always have been a full SetFocus().
I'm also uncertain about what is meant with "both locally & globally
active clients".
A branch with this change (and possibly more as the situation develops)
is at lp:~rhialto/ctwm/fix-sloppy-notitlefocus or
https://code.launchpad.net/~rhialto/ctwm/fix-sloppy-notitlefocus, and a
diff of the change above is attached. I'd like to get some feedback if
this seems a sensible route to take.
-Olaf.
--
___ Q: "What's an anagram of Banach-Tarski?" -- Olaf "Rhialto" Seibert
\X/ A: "Banach-Tarski Banach-Tarski." -- rhialto at falu dot nl
------------------------------------------------------------ revno: 676 committer: Olaf 'Rhialto' Seibert <[email protected]> branch nick: fix-sloppy-notitlefocus timestamp: Thu 2021-03-04 22:52:41 +0100 message: Attempt to fix the situation where SloppyFocus is on and TitleFocus is OFF. This causes that the de-focusing code of the previous window is never called. diff: === modified file 'event_handlers.c' --- event_handlers.c 2019-07-21 21:43:31 +0000 +++ event_handlers.c 2021-03-04 21:52:41 +0000 @@ -3337,19 +3337,16 @@ /* must deal with WM_TAKE_FOCUS clients now, if we're not in TitleFocus mode */ - if(!(Scr->TitleFocus) && - (Tmp_win->protocols & DoesWmTakeFocus)) { - - /* locally active clients need help from WM - to get the input focus */ - + if(!Scr->TitleFocus) { if(Tmp_win->wmhints->input) { SetFocus(Tmp_win, ewp->time); } - - /* for both locally & globally active clnts */ - - SendTakeFocusMessage(Tmp_win, ewp->time); + if(Tmp_win->protocols & DoesWmTakeFocus) { + /* locally active clients need help from WM + to get the input focus */ + /* for both locally & globally active clnts */ + SendTakeFocusMessage(Tmp_win, ewp->time); + } } } } /* end if Tmp_win->mapped */
signature.asc
Description: PGP signature
