Subject: bug#21333: 25.0.50; window-size-change-functions not called after mini-window resize

From: Eli Zaretskii <[email-masked]>
Date: Fri, 28 Aug 2015 16:13:44 +0300

> Date: Fri, 28 Aug 2015 12:34:53 +0000
> From: Pip Cet <[email-masked]>
> Cc: [email-masked], [email-masked]
> 
>     . both window-size-change-functions and pre-redisplay-function is
>     being discussed, although it should be clear their purpose is
>     different,
> 
> What's the huge difference? As far as I can tell:
> pre-redisplay-function: "I'm about to redisplay these windows, and they might
> have changed size or content"
> window-size-change-functions: "I'm about to redisplay windows on this frame,
> and some of them might have changed size"

There are at least 2 differences.  (1) pre-redisplay-function _must_
be run before the bulk of the redisplay code, because it is meant for
functions that want to affect the current redisplay cycle.  (2) The
place where window-size-change-functions is currently called is too
early, if it is supposed to pick up all of the resizes during this
redisplay cycle, because later code that's part of redisplay could
decide it wants to resize mini-window.

More generally, if window-size-change-functions is supposed to be able
to access the changed sizes, it must be called closer to the end of
redisplay cycle.

>     > Wish #1: a way of knowing "when" windows are resized or moved, even
>     > temporarily. Whether that "when" is "just before" or "just after" doesn't
>     > really matter, but it should be one of those.
>     
>     This wish needs to be described in more detail. Resizing of a window
>     is done in several distinct steps:
>     
>     . some function (resize_mini_window, if we are talking about the
>     mini-window) decides whether a window should be resized, and if so,
>     computes its start position;
>     
>     . redisplay_window, called by redisplay_internal, computes the
>     "desired" contents of the window on screen;
>     
>     . update_window, called by update_frame, actually delivers the needed
>     changes to the glass
>     
> 
> Wish #1 is for the hook to be called at any of the following points:
> - between steps 1 and 2
> - between steps 2 and 3
> - shortly after step 3.

But then the results of resizing will be incomplete for the first two
alternatives.  That might not be important for your wish, but could be
important in other use cases.

>     In addition, it is not clear whether your hook will care if the window
>     actually didn't change at all.
> 
> The hook function must be able to deal with that case, for wish #1 and wish #2.
> I see no way around that complication.

I do: redisplay knows that, so it could tell the hook, if we called
the hook at the right place.

>     > Wish #1, assuming something like my proposed changes go in and this bug
>     is
>     > closed, has been granted; there's a race condition, but I might just have
>     to
>     > live with that.
>     
>     Do you still think it has been granted?
> 
> If I'm not allowed to use pre-redisplay-function, no.

Of course you are allowed.  I'm just saying it's not the good place
for what I think you want to do.

>     > The function update_frame only reflects on the glass what its
>     > redisplay cycle computed to be the desired display. If redisplay
>     > didn't recompute the window contents, update_frame will change
>     > nothing.
>     >
>     > That's not what I seeing running x_sync manually.
>     
>     I don't understand what that means
> 
> Let me explain (I think you know all this, of course, but I might have it
> wrong):
> When update_frame returns, it's possible that it has made Xlib calls to change
> the screen content but that Xlib has not yet sent out messages to the X server
> to install those changes. In this case, the screen will still show the
> pre-redisplay state even though redisplay() is about to exit. Calling x_sync
> manually ensures that that doesn't happen.
> 
> IOW, there are several ideas of what the screen looks like:
> 1. the glyph matrix etc.
> 2. what Xlib has been told the screen should look like
> 3. what the screen actually looks like.
> 
> update_frame synchronizes (2) with (1). x_sync synchronizes (3) with (2).

Yes, I know.  But how does that let you know what update_frame
actually did?  It could do very little or nothing at all, and you need
to put a breakpoint at the right place (like the call to the
draw_glyphs method of the display interface) to see which parts are
being actually redrawn.

> I omitted some steps. How about (again, this is a description of the typical
> case that I'm actually seeing here):
> 1. user input
> 2. command loop handles user input
> 3. command loop calls redisplay 

I think step 1 should be omitted.  It doesn't add any information, and
is inaccurate (because input that triggers step 2 could come from
other sources).

> 4. prepare_menu_bars called
> 5. pre-redisplay-function called
> 6. window-size-change-functions NOT called.
> 7. grow_mini_window called, calculates new window size
> 8. redisplay_windows/redisplay_window_1 called, compute data for update_frame
> based on the new window sizes
> 9. update_frame is called, writes the new, enlarged mini-window to the glass
> 10. control returns to command loop
> 11. redisplay is called again
> 12. prepare_menu_bars called
> 13. prepare-redisplay-function called
> 14. window-size-change-functions not called on unmodified Emacs, called with my
> initial suggested patch.

Agreed.  Which is why I said that your proposed change will cause
window-size-change-functions to be called on the next redisplay cycle,
not the one which actually resized the windows.

> Are you suggesting a hook between steps 8 and 9?

If we want window-size-change-functions to be able to say whether any
windows were resized by the current redisplay cycle, I don't see how
any other place would do.