Subject: bug#42406: Mouse-wheel scrolling can be flickering

From: Eli Zaretskii <[email-masked]>
Date: Thu, 17 Dec 2020 22:36:04 +0200

> From: Stefan Monnier <[email-masked]>
> Cc: [email-masked],  [email-masked],  [email-masked]
> Date: Thu, 17 Dec 2020 14:45:19 -0500
> 
>     src/emacs -Q --eval '(global-set-key "a" (lambda () (interactive) (setq abbrev-mode (not abbrev-mode))))'
> 
> you'll notice that hitting `a` doesn't change the mode line to reflect
> the change in `abbrev-mode`.

That probably just means abbrev-mode should be added to the list at
the end of frame.el.  Or maybe that we need some new mechanism to
trigger update of the lighter on the mode line when a mode is turned
on or off.

And while we are talking about force-mode-line-update: can you explain
why we need to set the prevent_redisplay_optimizations_p flag of the
buffer, in addition to setting update_mode_lines to a magic value?

And btw, redisplaying the mode line in general could mean you need to
redisplay the text area as well, for example when the mode line
changes its height.  So setting update_mode_lines to REDISPLAY_SOME
under the assumption that only the mode line needs to be considered is
not necessarily true and can cause redisplay bugs.

> > We should stop lumping heuristics one on top another, and instead
> > redesign this from scratch and make sure that every flag we set is
> > acted upon as intended, and only in situations we intend them to be
> > acted upon.  E.g., we should be able to set f->redisplay to a value
> > that means "update only the frame title".
> 
> The `redisplay` bit is not supposed to be a heuristic at all.  It just
> tried to keep track more precisely of which part of the redisplay may
> have changed.  `fset_redisplay` marks the frame to be redisplayed at the
> next redisplay, setting `update_mode_lines` to a non-zero value means
> that when redisplaying a window we also redisplay its mode line, so
> the suggested hunk definitely doesn't rely on any kind of heuristic.

Then what is this bit of redisplay_internal about:

  consider_all_windows_p = (update_mode_lines
			    || windows_or_buffers_changed);
  [...]
  if (consider_all_windows_p)
    {
      FOR_EACH_FRAME (tail, frame)
	XFRAME (frame)->updated_p = false;

      propagate_buffer_redisplay ();

      FOR_EACH_FRAME (tail, frame)
	{
   [...]

If the redisplay flag is all we need, how come we must also set
update_mode_lines or windows_or_buffers_changed to get Emacs to
consider anything beyond the selected window?  Why does it have to be
so complicated to say "this frame needs to have all of its windows
reconsidered for redisplay"?

> The main problems I see with my suggested patch are:
> - I don't know if it actually fixes the original problem.

And this is exactly my problem: this is the "heuristic" part I was
talking about.  Instead of knowing exactly which flag does what and
why, we have a combination of flags and global variables, and try
tweaking them until we get the desired result.  This can only work up
to a point, and I think we are well beyond that point.

> - It can cause *more* redisplay work because it will force redisplay of
>   all the windows in the current frame (rather than only their mode
>   lines).

See, we have a single set of conditions that controls when we consider
the frame title, when we consider the mode line, the header-line, the
tab-line, the tool bar, and the menu bar.  It makes very little sense
to me to use the same condition for all of these.

> > I'm not against experimenting with replacing 42 by 32 or by
> > REDISPLAY_SOME etc., but I don't think we should install anything
> > along these lines, except if we need to fix a clear bug (i.e. a
> > redisplay glitch), which this one isn't.
> 
> I don't know what you mean by "along these lines".

"Along these lines" means playing more games with "special" values of
update_mode_lines and windows_or_buffers_changed.