Subject: Re: bug#15045: Point jumps inappropriately around time of Semantic lexing

From: David Engster <[email-masked]>
Date: Fri, 09 Aug 2013 18:10:04 +0200

Eli Zaretskii writes:
>> From: David Engster <[email-masked]>
>> Cc: [email-masked], [email-masked],
>> [email-masked], [email-masked]
>
>> Date: Fri, 09 Aug 2013 07:36:07 +0200
>> 
>> >> However, doing redisplay in timers is not nice.
>> >
>> > Why not?
>> 
>> Because doing redisplay is a user-visible side effect, and in general,
>> timers shouldn't have those.
>
> How else can a timer such as that of display-time do its thing?  IOW,
> when the purpose of a timer is to cause something to be displayed,
> they have no alternative but to force redisplay.

As you know, Emacs does not have strict timers. If you say to Emacs: one
minute from now, say 'foo', and Emacs happens to be busy one minute from
now, nothing will happen until it waits again. So I wonder: with such a
lenient definition of "timer", does the wait for the next redisplay
really matter? After which idle time does redisplay kick in anyway?

>> AFAICS, any function that calls things like
>> `accept-process-output', `input-pending-p' or `sit-for' inside a
>> `save-excursion' might get an unwanted scrolling effect if point is
>> temporarily moved to some invisible location.
>
> You mean, because of timers that might get run and cause redisplay?

Yes.

> Yes, that's possible.  But the way to avoid this is to never call
> these when point is in a place the user won't expect. Forcing the
> Emacs community not to trigger redisplay inside timers is IMO _not_
> the right way, because this is unnecessarily restrictive, and would
> disallow a whole bunch of useful features for no good reason.

I said: "doing redisplay in timers is not nice". I did not say that it
should be forbidden (if that's even possible).

However, I do propose the following:

- Deleting the 'sit-for' in the display-time-event-handler, since I
  would think that it is the most likely suspect for a non-idle timer
  that does redisplay in a usual Emacs session. The
  force-mode-line-update should be enough, and even if it isn't: if the
  minute is updated half a second too late, we can live with that (we
  can already live with a displayed 'load' value that's up to a minute
  old).

- In (info "(elisp) Timers"), the manual already discourages certain
  things in timers, like changing buffer content or waiting with
  `sit-for'. I think we should add something like this:

  "Also, enforcing a redisplay in non-idle timers is problematic, since
  they may run at times when other functions have moved point or
  narrowed the buffer temporarily.  The redisplay would make these
  visible, leading to unwanted scrolling or sudden narrowing and
  subsequent widening of the buffer.  You should rather try if waiting
  for the next redisplay after the timer has run is sufficient for your
  needs.  If you just change the mode-line, use `force-mode-line-update'
  instead of a full redisplay."

- We should add information to the documentation of
  `access-process-output' and `input-pending-p', like

  "Note that timers may run during this function, which may trigger a
  redisplay.  So before calling this function, you should make sure that
  any temporary changes you made to point position or the buffer (like
  narrowing) are undone, as to not make these changes visible."

As a sidenote: What "bunch of useful features" do you have in mind for
non-idle timers that do redisplay? They shouldn't alter buffer content,
so what can they do that would need immediate redisplay? Displaying some
kind of progress/time indicator is pretty much the only thing I can come
up with.

> IOW, it's the caller of input-pending-p etc. that is the fault here,
> not the timers that it inadvertently lets run.

Until yesterday, I was completely unaware that `accept-process-output'
or `input-pending-p' could run timers that do redisplay, and I think I'm
in good company. The doc-strings do not mention it, so there must be
lots of third-party code which does not pay attention to this, so we
should try that this bug triggers as little as possible.

>> In fact, I just understood another bug in speck-mode (which is similar
>> to flycheck). I sometimes had unwanted scrolls there, too, and I now saw
>> that those also happen at every full minute while typing.
>
> Then there's the same bug there, that's all.

Yes. But it shows that this bug is easy to make, and it's hard to track
down. Also, the bug is slightly different in that speck does not only
alter point, but also narrows the buffer, which is even more scary than
unwanted scrolling.

>> I thought that the jit-lock timer is a non-idle timer, but you are
>> right.
>
> There's no jit-lock timer.

Yes. Sorry for being imprecise. I meant the jit-lock defer timer.

-David