Subject: bug#32839: 27.0.50; recenter doesn't redisplay

From: Juri Linkov <[email-masked]>
Date: Fri, 28 Sep 2018 01:59:04 +0300

>>      (recenter 0 t)
>>
>>    Despite its REDISPLAY argument set to t, the frame is not redisplayed.
>
> This is how 'recenter' is documented to behave:
>
>   If ARG is omitted or nil, then recenter with point on the middle line
>   of the selected window; if REDISPLAY & ‘recenter-redisplay’ are
>   non-nil, also erase the entire frame and redraw it [...]
>
> IOW, the frame is redrawn only when ARG is nil and REDISPLAY is
> non-nil.

Then why REDISPLAY is non-nil, if it doesn't redisplay the frame?

I still don't understand the logic: `recenter-redisplay' is non-nil,
the arg REDISPLAY is non-nil, and yet no redisplay, this makes no sense
and looks like a bug.

Maybe the problem lies in the name of the new arg REDISPLAY -
from its current behavior a more correct name would be:
`recenter-redisplay-only-when-another-arg-is-nil'.

But such a long name indicates broken logic.  It would make sense
for a nil value of the REDISPLAY arg not to redisplay, and
for a non-nil - to redisplay, or to take a special value like

  (recenter 0 'force)

>> 2. The second problem is that after the call to (recenter -1 t),
>>    window-scroll-functions is called only when recenter moves the current
>>    buffer line to the second-last window line (when the last window line is
>>    partially visible).  But when the last window line is fully visible,
>>    window-scroll-functions is not called after (recenter -1 t).
>
> Depending on the exact dimensions of the window and the size of your
> font, this can legitimately happen.
>
> You see, the way 'recenter' works, it sets a couple of fields in the
> window object which instruct the display engine to change the
> window-start point.  The actual recentering happens during the very
> next redisplay cycle, at which time the display engine sees these
> fields and acts accordingly.  To redisplay a window, the display
> engine has several methods at its disposal; starting with the cheapest
> one, it attempts to find the first applicable one, and then uses it.
> Only some of the methods are considered to use "scrolling", others
> aren't.  So that's why window-scroll-functions might not be called
> when the text was "scrolled" by 'recenter' and its derivatives.

I thought that scrolling for the sake of window-scroll-functions
implies the changes in the value of window-start, i.e. when
an old value of window-start is not the same as its new value,
this guarantees the call of window-scroll-functions.

The docstring of window-scroll-functions says:

  These functions are called whenever the ‘window-start’ marker is modified,
  either to point into another buffer (e.g. via ‘set-window-buffer’) or another
  place in the same buffer.

(recenter -1 t) definitely modifies the value of window-start,
so it's expected that window-scroll-functions should be called.

Maybe it will be called in the new hook window-state-change-functions
proposed by Martin.