Subject: bug#50660: 28.0.50; Text artifacting when the cursor moves over text under mouse face that originally displayed a box

From: Eli Zaretskii <[email-masked]>
Date: Mon, 20 Sep 2021 13:51:27 +0300

> From: Po Lu <[email-masked]>
> Cc: [email-masked],  [email-masked]
> Date: Mon, 20 Sep 2021 18:27:02 +0800
> 
> Eli Zaretskii <[email-masked]> writes:
> 
> > So I think all that's needed is to adjust the value of
> > w->phys_cursor.x, when needed, in draw_phys_cursor_glyph, before
> > passing it to draw_glyphs, or perhaps in its callers.  The value of
> > w->phys_cursor.x should stay unaltered, but what we pass to
> > draw_glyphs should be offset if needed.
> 
> Thanks, I'll work on that.

Specifically, I now think the adjustment should happen in this
fragment from show_mouse_face, before we call display_and_set_cursor:

	/* When we've written over the cursor, arrange for it to
	   be displayed again.  */
	if (FRAME_WINDOW_P (f)
	    && phys_cursor_on_p && !w->phys_cursor_on_p)
	  {
  #ifdef HAVE_WINDOW_SYSTEM
	    int hpos = w->phys_cursor.hpos;

	    /* When the window is hscrolled, cursor hpos can legitimately be
	       out of bounds, but we draw the cursor at the corresponding
	       window margin in that case.  */
	    if (!row->reversed_p && hpos < 0)
	      hpos = 0;
	    if (row->reversed_p && hpos >= row->used[TEXT_AREA])
	      hpos = row->used[TEXT_AREA] - 1;

	    block_input ();
	    display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
				    w->phys_cursor.x, w->phys_cursor.y);
	    unblock_input ();
  #endif	/* HAVE_WINDOW_SYSTEM */
	  }

Here we know that if the DRAW argument is DRAW_MOUSE_FACE, we are
displaying the mouse-face, and if it's DRAW_NORMAL_TEXT, we are
removing the mouse face.  We can also know which glyphs are being
redisplayed with/without the mouse highlight, see the loop above that
calculates start_hpos and end_hpos (you can save aside the results
when it does that for the cursor row).  The glyphs in the glyph row
have their original face_id (Not the mouse-face ID!), so you can look
at their left_box_line_p and right_box_line_p attributes, the
face->box attribute, etc.  And the corresponding attributes of the
mouse-face can be accessed via mouse_face_face_id etc.

So you should be able to walk the glyphs from the beginning of the
redrawn area to the cursor glyph and calculate the offset for
w->phys_cursor.x you need.  I think you will need separate loops for
reversed_p rows, where you should loop from the end of the row, not
from the beginning.

A separate function to compute the offset will probably be best.

> > The correct place to fix this is therefore somewhere under
> > note_mouse_highlight, which is where we handle redrawing of the
> > mouse-sensitive face, including the cursor.
> 
> Thanks, I've learned a lot.  I hope I haven't been inconveniencing you
> in any way.

No, not at all.  Thank you for working on this.