Subject: bug#7464: 24.0.50; mouse highlighting vanishes upon unsplitting window

From: Eli Zaretskii <[email-masked]>
Date: Thu, 29 Mar 2012 20:47:09 +0200

> From: Stephen Berman <[email-masked]>
> Cc: [email-masked],  [email-masked]
> Date: Thu, 29 Mar 2012 09:57:53 +0200
> 
> openSUSE's 23.3 has GTK scroll bars, while I built 23.4 like I build 24,
> i.e., without toolkit scroll bars.  So I rebuilt 23.4 with GTK scroll
> bars, did the bug recipe and sure enough, now the mouse highlighting
> remained, i.e., no bug.  Then I disabled the scroll bars in that build,
> tested again, and got the bug again.  Then I rebuilt Emacs 24 with GTK
> scroll bars, and now did not see the bug with them enabled but did see
> it with them disabled.  So the answers to my questions above appear to
> involve the presence vs. absence of GTK scroll bars.  (I guess Chong
> Yidong also builds Emacs 24 with GTK scroll bars and tested the recipe
> with them enabled, so that's why he did not observe the bug.)

Unfortunately, I know almost nothing about how GTK in general and GTK
scroll bars in particular are integrated into Emacs, and what, if
anything, they change in how the Emacs display engine works.

> After these tests, I ran both Emacs 24 builds (i.e., with and without
> GTK scroll bars) under gdb, and in both cases, the value of
> (w->current_matrix->rows+1)->mouse_face_p is 0 both at the breakpoint
> and after the call to free_window_matrices (and of course after
> adjust_glyphs).  I also ran 23.4 under gdb, with the same result:
> (w->current_matrix->rows+1)->mouse_face_p is already 0 before
> adjust_glyphs.  Do you have any idea why, or any further debugging
> suggestions?

The other piece of info I can share is how the mouse_face_p flag that
is reset clears the mouse highlight.  This happens in
update_window_line:

      /* Update the display of the text area.  */
      if (update_text_area (w, vpos))
	{
	  changed_p = 1;
	  if (current_row->mouse_face_p)
	    *mouse_face_overwritten_p = 1;
	}
  ...
  /* Update current_row from desired_row.  */
  make_current (w->desired_matrix, w->current_matrix, vpos);

And in make_current we see this:

  struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
  struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
  int mouse_face_p = current_row->mouse_face_p;

  /* Do current_row = desired_row.  This exchanges glyph pointers
     between both rows, and does a structure assignment otherwise.  */
  assign_row (current_row, desired_row);

  /* Enable current_row to mark it as valid.  */
  current_row->enabled_p = 1;
  current_row->mouse_face_p = mouse_face_p;

So if the mouse_face_p flag is reset in the current glyph matrix, it
will be forcibly reset in the desired matrix, and also, the
display-specific update_end_hook function will be called with
mouse_face_overwritten_p arg set to zero, and will not redraw the
mouse-highlighted characters:

      rif->update_window_end_hook (w, !paused_p, mouse_face_overwritten_p);

Perhaps you could step through these functions and see what happens
there with and without GTK scroll bars.  To do so, put a breakpoint
inside Fdelete_other_windows_internal, do the recipe, and when the
breakpoint breaks, put a breakpoint in redisplay_internal and
continue.  When the breakpoint in redisplay_internal breaks, put a
breakpoint in update_window, and step through the loop which updates
the screen lines:

      /* Update the rest of the lines.  */
      for (; row < end && (force_p || !input_pending); ++row)

This loop calls update_window_line:

	    changed_p |= update_window_line (w, vpos,
					     &mouse_face_overwritten_p);

Does the mouse_face_overwritten_p flag return being set when the line
with highlight is updated?