Subject: bug#34138: 27.0.50; Delayed display of PDF file images

From: Eli Zaretskii <[email-masked]>
Date: Wed, 23 Jan 2019 18:13:41 +0200

> From: Stephen Berman <[email-masked]>
> Cc: [email-masked],  [email-masked],  [email-masked],  [email-masked]
> Date: Tue, 22 Jan 2019 23:00:01 +0100
> 
> > So could you please add the following 2 lines:
> >
> >   fprintf (stderr, "run_window_configuration_change_hook: %p\n", f);
> >   fflush (stderr);
> >
> > into the very beginning of run_window_configuration_change_hook (it is
> > in src/window.c), compile both versions of Emacs, and run the same
> > scenario again.  Then please show the traces, where the above message
> > should be visible somewhere among the other trace messages.
> 
> Attached.  It's striking that in the emacs-26 trace
> run_window_configuration_change_hook is called just once, before the PDF
> (image) is displayed, while in the emacs-master trace it's called once
> before the (raw) PDF is displayed and again immediately after that, but
> not again when the display changes to the image.  Does that accord with
> your theory?

Yes, sort of.  (The first invocation of
run_window_configuration_change_hook is AFAIU not relevant to the
issue at hand, it's about a different buffer, called "manual".  Only
the second call is relevant.)

Here's my theory: in Emacs 26, run_window_configuration_change_hook is
called from various functions in window.c, which are called from Lisp,
i.e. by definition _before_ redisplay.  The recent changes installed
by Martin replace all those calls in window.c by simply setting a
flag, which is then tested in run_window_change_functions, which now
calls run_window_configuration_change_hook.  The crucial aspect of
this change is that run_window_change_functions is called at the very
end of a redisplay cycle, after redisplay_internal already finished
examining all the windows, and after the call to update_frame which
delivers the necessary changes to the glass.

Now, image-mode works by changing an overlay.  Changes in overlays are
examined by the display engine, and windows displaying buffers where
overlays have been changed have the corresponding portions redrawn.
Windows that don't have any overlay changes and whose buffer text
didn't change are skipped by redisplay, on the assumption that nothing
has changed in them that requires displaying some of its part anew.
And since run_window_configuration_change_hook is called only _after_
the display engine already examined the windows, it cannot trigger
redisplay of the window where we show the image of the PDF document.
Thus, the image is shown only upon next more or less thorough
redisplay, which redraws the window in question.

Therefore, a question to Martin: why was the call to
run_window_change_functions put at the very end of redisplay_internal?
Is this intentional, and if so, what were the reasons for that?

If there are good reasons for keeping the call where it is now (e.g.,
moving it to beginning of the redisplay cycle will harm some
legitimate use cases), we will have to come with some complementary
measures to avoid breaking image-mode and its ilk.

> This time with emacs-master about 25 seconds elapsed
> between the raw PDF appearing in the buffer and the image appearing
> (again without keyboard intervention).  Immediately after that, the
> trace stopped for a number of seconds (I didn't time it but I guess
> 5-10), then it printed:
>  redisplay_preserve_echo_area (8)
>  redisplay_internal 0

These two traces are not in the trace you posted, right?  Because the
Emacs 27 trace ends with this:

> redisplay_preserve_echo_area (9)
> redisplay_internal 0
> 0x2a01550 (R-admin.pdf): same window start
> 0x2a01550 (R-admin.pdf): 1

which I believe is the first redisplay cycle which shows the image.
Right?

> and then I killed the buffer.  As the emacs-26 trace shows, after the
> PDF image appeared (which it did without the raw PDF being displayed),
> the trace rapidly produced another 50 lines of output (included in the
> attachment) before pausing, after which I killed emacs.

Most of the traces come from the code that invokes timers, so I think
you have timers running which eventually trigger redisplay, something
that doesn't happen on Andreas's machine.  That might explain why you
see the image after a short delay, while Andreas needs to manually
trigger redisplay for that.

Thanks.