[comp.windows.x] Emacs 18.57 X focus/cursor weirdness with twm R4?

warsaw@nlm.nih.gov (Barry A. Warsaw) (03/05/91)

[Note, my original article, partially cited here as "Me>" was posted
to gnu.emacs.help. I have more information on the problem and am now
cross posting this followup to gnu.emacs.bug and comp.windows.x -baw]

	Me> I've noticed a change in the way emacs interacts with R4 twm.
	Me> In particular, when getting and giving up focus, the block
	Me> cursor will not always change color correctly.

Okay, here's some more details on the problem. For the record:

Emacs 18.57
Sun SS1+, SunOS 4.1
MIT X11R4.18 Server w/ X11R4.18 TWM window manager

Under this configuration, using the mouse to move the cursor into and
out of the emacs window works fine. Moving the mouse into the window
generates an EnterNotify event, but no FocusIn event. Moving the mouse
out of the window generates a LeaveNotify event but no FocusOut event.
The problem comes when using a twm command such as f.warpring to move
into or out of the window.

To recreate the problem, put the following in your .twmrc file (at the
appropriate place):

#NoRaiseOnWarp (i.e. you want raise-on-warp)
WindowRing { "Emacs" "XTerm" }
"n" = s|c      	: all   	: f.warpring "next"
"p" = s|c      	: all   	: f.warpring "prev"

The effect of these is that you should be able to warp the cursor
between all your mapped xterm and emacs windows just by hitting
ctrl-shift-n and ctrl-shift-p. First, make the above modifications to
your .twmrc file and restart twm. Then bring up two emacs windows and
an xterm window.  Put the cursor (using the mouse) in an 18.57 emacs
window, then hit ctrl-shift-n.  One of the other emacs/xterm windows
should be raised, and the cursor will move into that window, but the
cursor-block of the original emacs window should remain solid. The
reason for this is that the emacs window will receive the following 5
X events during the execution of f.warpring "next":

	1. FocusOut
	2. FocusIn
	3. FocusOut
	4. FocusIn
	5. LeaveNotify

At this point, hitting ctrl-shift-p warps the cursor back to the emacs
window, but no Focus* events are generated. I don't know why these
events in this order are sent to the emacs window when warping out of
or into the window, however, looking at the code in x11term.c, its
pretty clear why this sequence of events will mess up emacs'
cursor-block (and why 18.55 did not exhibit the same problem).  I
don't know if this is a twm problem, but I'm planning to cross post
this message to comp.windows.x to see if anyone has any further
information.  Also note that doing the same thing to the xterm window
does not mess up its cursor block. This is because xterm ignores the
Focus(In/Out) events and just toggles its cursor solidness on
(Enter/Leave)Notify events (see xterm's misc.c file).

So anyway, the patch below changes emacs so that it will also ignore
Focus(In/Out) events and just toggle the cursor on (Enter/Leave)Notify
events.  Whether this behavior is "correct" or not according to ICCCM,
I can't say.  But emacs' cursor now seems to behave properly when
entering or leaving the window using either f.warpring or the mouse.

I'd be interested in hearing from other twm users who cannot recreate
the problem by following the steps I outline above. I suppose it is
possible that some thing else in my .twmrc file or my general X
environment is affecting this behavior. Be sure you're using emacs
18.57, since version 18.55 does not exhibit this behavior.

-Barry

NAME:  Barry A. Warsaw         INET: warsaw@nlm.nih.gov
TELE:  (301) 496-1936          UUCP: uunet!nlm.nih.gov!warsaw

*** x11term.c.orig	Mon Mar  4 16:24:13 1991
--- x11term.c	Mon Mar  4 16:24:30 1991
***************
*** 1377,1400 ****
        break;
  
-     case FocusIn:
-       x_focus_flag = 1;
      case EnterNotify:
-       if (event.type == FocusIn || (!x_focus_flag && event.xcrossing.focus))
- 	{
  	  CursorToggle ();
  	  CursorOutline = 0;
  	  CursorToggle ();
- 	}
        break;
  
-     case FocusOut:
-       x_focus_flag = 0;
      case LeaveNotify:
-       if (event.type == FocusOut || (!x_focus_flag && event.xcrossing.focus))
- 	{
  	  CursorToggle ();
  	  CursorOutline = 1;
  	  CursorToggle ();
- 	}
        break;
  			
--- 1377,1390 ----

mouse@lightning.mcrcim.mcgill.EDU (der Mouse) (03/06/91)

> I've noticed a change in the way emacs interacts with R4 twm.  In
> particular, when getting and giving up focus, the block cursor will
> not always change color correctly.

For a program to determine whether or not it has keyboard focus is not
a trivial matter.  As far as I can tell, the program must ask for
EnterNotify/LeaveNotify events on its own window and FocusIn/FocusOut
events on both its window and the root window, and keep a state
variable to tell whether or not PointerRoot focus is in use.

The algorithm is, basically:

	EnterNotify:
		if PointerRoot focus is in use, we now have focus.

	LeaveNotify:
		if PointerRoot focus is in use, we now don't have focus.

	FocusIn:
		if mode is neither NotifyNormal nor NotifyWhileGrabbed,
		   or detail is NotifyInferior,
			ignore the event entirely.
		else, if the window is the root,
			if detail is NotifyPointerRoot,
				PointerRoot focus is now in use.
			if detail is NotifyDetailNone,
				PointerRoot focus is now not in use.
		else, if the window is the our top-level window,
			we now have focus.

	FocusOut:
		if mode is neither NotifyNormal nor NotifyWhileGrabbed,
		   or detail is NotifyInferior,
			ignore the event entirely.
		else, if the window is the root,
			if detail is NotifyPointerRoot,
				PointerRoot focus is now not in use.
		else, if the window is the our top-level window,
			we now don't have focus.

If anyone can construct a case which breaks this, or if someone can
point out any unnecessary complexity, I'd love to hear about it....

> [D]oing the same thing to the xterm window does not mess up its
> cursor block.  This is because xterm ignores the Focus(In/Out) events
> and just toggles its cursor solidness on (Enter/Leave)Notify events
> (see xterm's misc.c file).

It can't be quite that simple.  On the rare occasions when I run xterm,
I see its cursor track focus correctly whether or not that focus is
related to the pointer position.  (My window manager doesn't do
focus-follows-pointer.)  In particular, merely entering the window with
the pointer does not highlight the cursor when focus is not thereby
transferred, and correspondingly for leaving the window.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu