Subject: Re: bug#77039: 31.0.50; Flickering on macOS

From: Eli Zaretskii <[email-masked]>
Date: Sun, 23 Mar 2025 12:13:10 +0200

> Cc: [email-masked], [email-masked], [email-masked]
> From: "Aaron Jensen" <[email-masked]>
> Date: Sun, 23 Mar 2025 08:16:18 +0000
> 
> 
> On Sun, Mar 23, 2025 at 12:59 AM, Eli Zaretskii <[email-masked]> wrote:
> 
>  From: Aaron Jensen <[email-masked]> 
>  Date: Sat, 22 Mar 2025 17:38:01 -0400 
>  Cc: Eli Zaretskii <[email-masked]>, [email-masked], [email-masked]
> 
>  It's global-display-line-numbers-mode. 
> 
>  Repro from emacs -Q: 
> 
>  (defun foo () 
>  (Interactive) 
>  (global-display-line-numbers-mode) 
>  (term "/usr/bin/yes") 
>  (switch-to-buffer "*scratch*"))
> 
>  If you set display-line-numbers-mode to 'visual globally, does the problem go away?
> 
> No, nor does disabling blink cursor mode or commenting out the lines you referenced.
> 
> I'm using this, please double check I'm not doing something wrong.
> 
> (defun foo ()
>   (interactive)
>   (blink-cursor-mode -1)
>   (global-display-line-numbers-mode)
>   (setq-default display-line-numbers-mode 'visual)
>  (term "/usr/bin/yes")
> (switch-to-buffer "*scratch*"))

My testing indicates that setting display-line-numbers-mode to
'visual' does stop redisplay of the selected window.  I did that with
a simple "M-x set-variable", not with the globalized mode.

And I did misinterpret the code in redisplay_internal: when
display-line-numbers-mode is not nil and not 'visual', we currently go
ahead with calling redisplay_window, and there I think we use the
method marked with "1" here:

      /* Try to redisplay starting at same place as before.
         If point has not moved off frame, accept the results.  */
      if (!current_matrix_up_to_date_p
	  /* Don't use try_window_reusing_current_matrix in this case
	     because a window scroll function can have changed the
	     buffer.  */
	  || !NILP (Vwindow_scroll_functions)
	  || MINI_WINDOW_P (w)
	  || !(used_current_matrix_p
	       = try_window_reusing_current_matrix (w)))
	{
	  IF_DEBUG (debug_method_add (w, "1"));  <<<<<<<<<<<<<<<<<<<
	  clear_glyph_matrix (w->desired_matrix);
	  if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
	    /* -1 means we need to scroll.
	       0 means we need new matrices, but fonts_changed
	       is set in that case, so we will detect it below.  */
	    goto try_to_scroll;
	}

because try_window_reusing_current_matrix also gives up when
line-numbers are shown.

So in summary, I don't see anything abnormal here.  If we want to keep
the only-current-line-changed optimization in redisplay_internal,
someone will have to come up with a smarter test for when line numbers
are shown.  I think the underlying problem is that when the line
number of the current line becomes large enough to require more
columns for line-number display, we must redraw the entire window to
avoid the problem with shifting or line number described in
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=54091#5 .