emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Window change functions


From: martin rudalics
Subject: Re: Window change functions
Date: Thu, 27 Dec 2018 10:36:33 +0100

>> (1) 'window-state-change-functions' runs when a window got a new
>>      buffer or was created or deleted since last redisplay.
>
> I'd call it `window-buffer-change-functions` because the notion of
> "window-state" includes much more than just whether it's alive and which
> buffer it displays.

OK.  While deleting a window doesn't really change its buffer, a state
change could be admittedly considered as something more substantial.

>> (2) 'window-size-change-functions' runs when a window was created or
>>      got a new buffer, body or total size since last redisplay.
>>
>> (3) 'window-configuration-change-hook' runs as (1) and (2) together.
>>
>> (4) 'window-selection-change-functions' run when a window got
>>      (de-)selected since last redisplay.
>
> These sound good, thanks.
>
> One question is where they're consulted and run.
> E.g. for (4) one window got deselected and another got selected, so
> I guess it's run twice and is looked up each time in the corresponding
> window's buffer?

Yes.  The buffer local hooks are run for every window the buffer is in
that gets selected or deselected with the respective window passed as
argument.  This means that if a buffer B is shown in two windows W1
and W2 and W1 gets deselected and W2 gets selected, the buffer-local
hook is run twice for the same buffer - once with W1 and once with W2
as argument.

The global hooks are run once for each frame where a selection or
deselection occurred with the frame as argument.  So if a new frame
gets selected there will be two calls of the global hook - once for
the old and once for the now selected frame.

> For 'window-size-change-functions and 'window-state-change-functions
> (and hence window-configuration-change-hook), it's sufficiently rare to
> change the size (or the window's buffer) of a window and revert it
> before the next redisplay that I'm not sure it's beneficial.
>
> Tho, it is clearly normal for a window to change size
> several times within a given command (e.g. balance-windows-area does
> just that to incrementally settle on a balanced result).
>
> Is this delaying done on-purpose for all hooks individually, or is there
> some underlying reason why it's helpful to delay them all?

There are several reasons that favor delaying:

(1) When finishing a window excursion by restoring the previous
    configuration we should run 'window-configuration-change-hook' if
    and only if something really changed.  Telling whether something
    really changed is hard and I doubt current Emacs does it right.

(2) 'balance-windows-area' is a good example for why we should delay
    calling size change functions IMO: Its intermediate steps are not
    really interesting for any client of that hook.

(3) Delaying hooks and running them all in one bunch allows to
    reliably look at possibly related changes by consulting the
    'window-old-...' functions.

(4) Some clients do the delaying themselves by putting an according
    function on 'post-command-hook'.  This won't be needed any more
    with delayed execution.

>> - Some functions on 'window-configuration-change-hook' (notably in
>>    erc-track.el and rcirc.el) put further code on 'post-command-hook'.
>>    This concept will be broken since 'post-command-hook' now runs
>>    before 'window-configuration-change-hook'.
>
> This does sound potentially problematic, indeed.  Looking at those two,
> I don't see why they postpone the work to post-command-hook, tho.
> They use the exact same code, with the exact same comment (erc-track
> copied it from rcirc), but neither clearly explains why they do that.
> The comment just says:
>
>    (unless (minibuffer-window-active-p (minibuffer-window))
>      ;; delay this until command has finished to make sure window is
>      ;; actually visible before clearing activity
>      (add-hook 'post-command-hook #'erc-modified-channels-update)))
>
> I'm wondering which scenario caused problem.

I don't use them and cannot tell.  But since change functions
would now run after 'post-command-hook' running
'erc-modified-channels-update' from 'window-configuration-change-hook'
right away should satisfy the author's intentions.

>>    xterm.el has a bit more convoluted code whose purpose I haven't been
>>    able to figure out yet.  The solution should be similar though.
>
> I don't see anything there that would suffer from being postponed.

Neither do I.

>> address@hidden window-state-change-functions
>> +This variable specifies functions called at the end of redisplay when
>> +window states have changed.  The value should be a list of functions
>> +that take one argument
>
> If it's run "at the end of redisplay", then I think it's too late: those
> hooks will often want to change something visual, and they will want it
> to appear right away, so it should be run just *before* redisplay.

Note that 'window-size-change-functions' are currently already run
right in the middle of redisplay.  Often, window sizes are correct
only *after* redisplay.  Think of minibuffer window resizing or
changes in the fringes, margins or modeline sub-structures.  But a
final word on the location of the call will have to be told by Eli.

> Hmm... so to detect when a specific buffer stops being displayed you
> need to use the global part of the hook and you're not told which was
> the previously displayed buffer, so you need to keep track of
> that yourself.

Correct.  The right position to detect when a "specific buffer stops
being displayed" is (1) 'kill-buffer-hook' and *would be* (2) a
'before-delete-window-hook' because right after its deletion a window
might get GCed immediately and (2) would not have anything else but
the buffer itself to work upon.  So if someone sees a need for (2)
please tell me and I'll add such a hook (it won't cost much but some
lines in the manual).

> The new text doesn't mention the window-pixel-height-before-size-change
> functions any more.  Is it just an oversight or is there a reason
> for that?

It's been renamed to 'window-old-pixel-height' so the 'window-old-'
prefix matches that of its new colleagues.

>> +Functions specified buffer-locally are called for any window showing
>> +the corresponding buffer if that window has been selected or
>> +deselected (among all windows or among all windows on its frame) since
>> +the last time window change functions were run.  In this case the
>> +window is passed as argument.
>
> IIUC this hook is hence also run for changes to frame-selected-window,
> even when that frame is not selected?  I wonder if it's a good idea.
> frame-selected-window is a fairly obscure detail, in my experience.

If someone changes it separately (that is, sets it for a non-selected
frame), there is now a hook to trace that.  Otherwise, any change of
'frame-selected-window' is just a side-effect of changing the selected
window and will not be noticed by clients.

>          Stefan "who hasn't looked at the code"

He could try it though.

martin



reply via email to

[Prev in Thread] Current Thread [Next in Thread]