unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#32720: term-mode ignores certain window size changes
@ 2018-09-12 12:09 Gary Fredericks
  2018-09-13  8:07 ` martin rudalics
  2018-11-04  9:56 ` martin rudalics
  0 siblings, 2 replies; 46+ messages in thread
From: Gary Fredericks @ 2018-09-12 12:09 UTC (permalink / raw)
  To: 32720

[-- Attachment #1: Type: text/plain, Size: 1277 bytes --]

*Affects*: version 26 (git-bisected to commit 8e7712c7afc)

Note: I have only tried this on --without-x emacs

*Steps to reproduce*

   1. start emacs
   2. start a term buffer with M-x term
   3. run `seq 1000` at the bash prompt to fill the screen
   4. enlarge the terminal window that emacs is running in, so that the
   window size changes as well
   5. run `seq 1000` again, and observe that the new space at the bottom of
   the buffer is not being used

*Analysis notes*

term-mode *does* pick up changes after more explicit window configurations,
like splits; my workaround for months has been to split and join the
terminal window whenever I've resized it.

As best I can tell, term-mode subscribes to window size changes by adding
advice to the window-adjust-process-window-size-function variable, and the
8e7712c7afc reduced the set of situations in which that function is called.

I've developed a more automated workaround with a term-load-hook of this
form:

(add-hook 'window-size-change-functions (lambda (_frame)
(window--adjust-process-windows)))

It might be that adding this line to the term-mode setup steps would be
sufficient, but I'm not familiar enough with the window.el code to have a
guess whether that's actually a good approach.

Gary Fredericks

[-- Attachment #2: Type: text/html, Size: 1797 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-09-12 12:09 bug#32720: term-mode ignores certain window size changes Gary Fredericks
@ 2018-09-13  8:07 ` martin rudalics
  2018-09-13 14:06   ` Eli Zaretskii
  2018-11-04  9:56 ` martin rudalics
  1 sibling, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-09-13  8:07 UTC (permalink / raw)
  To: 32720

> *Affects*: version 26 (git-bisected to commit 8e7712c7afc)
>
> Note: I have only tried this on --without-x emacs
>
> *Steps to reproduce*
>
>     1. start emacs
>     2. start a term buffer with M-x term
>     3. run `seq 1000` at the bash prompt to fill the screen
>     4. enlarge the terminal window that emacs is running in, so that the
>     window size changes as well
>     5. run `seq 1000` again, and observe that the new space at the bottom of
>     the buffer is not being used
>
> *Analysis notes*
>
> term-mode *does* pick up changes after more explicit window configurations,
> like splits; my workaround for months has been to split and join the
> terminal window whenever I've resized it.
>
> As best I can tell, term-mode subscribes to window size changes by adding
> advice to the window-adjust-process-window-size-function variable, and the
> 8e7712c7afc reduced the set of situations in which that function is called.
>
> I've developed a more automated workaround with a term-load-hook of this
> form:
>
> (add-hook 'window-size-change-functions (lambda (_frame)
> (window--adjust-process-windows)))
>
> It might be that adding this line to the term-mode setup steps would be
> sufficient, but I'm not familiar enough with the window.el code to have a
> guess whether that's actually a good approach.

Emacs no more runs 'window-configuration-change-hook' when the frame
size changes so your workaround should indeed work around that case.
But you should see a similar problem before commit 8e7712c7afc with a
frame containing a window showing process output and that window's
size gets changed.

In its current form, 'window--adjust-process-windows' is a gross hack.
Putting a function by default on 'window-configuration-change-hook'
(or 'window-size-change-functions') is a bad idea IMO.  There should
be no place for such functions in window.el - a special mode should
take care of them.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-09-13  8:07 ` martin rudalics
@ 2018-09-13 14:06   ` Eli Zaretskii
  2018-09-14  8:32     ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Eli Zaretskii @ 2018-09-13 14:06 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

> Date: Thu, 13 Sep 2018 10:07:06 +0200
> From: martin rudalics <rudalics@gmx.at>
> 
> In its current form, 'window--adjust-process-windows' is a gross hack.
> Putting a function by default on 'window-configuration-change-hook'
> (or 'window-size-change-functions') is a bad idea IMO.

Can you elaborate on why do you think these are bad ideas?





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-09-13 14:06   ` Eli Zaretskii
@ 2018-09-14  8:32     ` martin rudalics
  0 siblings, 0 replies; 46+ messages in thread
From: martin rudalics @ 2018-09-14  8:32 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 32720

 >> In its current form, 'window--adjust-process-windows' is a gross hack.
 >> Putting a function by default on 'window-configuration-change-hook'
 >> (or 'window-size-change-functions') is a bad idea IMO.
 >
 > Can you elaborate on why do you think these are bad ideas?

(1) Preempting a hook is like preempting an option.  And options
should be pristine when starting Emacs.  Users who never run any
processes should not be obliged to remove anything from a hook to
obtain a clean run.  Even if we say that it does not matter much in
the case at hand, this code sets a precedent which others may follow.

(2) I don't know what a "logical" window size is.  Reading the
doc-string of 'window-adjust-process-window-size-function', I
understand that the function this variable is set to should pass the
size of some window showing output of a process to that process.  If
this interpretation is correct, then not hooking into
'window-size-change-functions' will fail to capture explicit resizing
of any such window - usually the most prominent case when a window
size changes.  So what's the aim of 'window--adjust-process-windows'?

In either case, it should not be the task of window.el to find process
windows.  It does not find "Man" or "Info" windows either and calls a
hook in a hook when resizing them although someone might find that
convenient - compare Bug#32536.  Window groups are the most prominent
other example of code that usurpated window.el.  I never understood
why code which pertains to 'follow-mode' was added to window.el.
Adding such code makes the already largest code file in the Lisp
directory more and more difficult to navigate.

BTW, the info text "When windows that display buffers associated with
process change their dimensions, the affected processes should be told
about these changes" seems to lack an "a" before "process".

And the text "If the process has the `adjust-window-size-function'
property (*note Process Information::), its value overrides the global
and buffer-local values of
`window-adjust-process-window-size-function'." is misleading.  Section
38.6 Process Information does not mention any such property and I have
no idea what it's supposed to accomplish.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-09-12 12:09 bug#32720: term-mode ignores certain window size changes Gary Fredericks
  2018-09-13  8:07 ` martin rudalics
@ 2018-11-04  9:56 ` martin rudalics
  2018-11-16 12:15   ` Gary Fredericks
  1 sibling, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-11-04  9:56 UTC (permalink / raw)
  To: Gary Fredericks, 32720

[-- Attachment #1: Type: text/plain, Size: 1748 bytes --]

 > *Affects*: version 26 (git-bisected to commit 8e7712c7afc)
 >
 > Note: I have only tried this on --without-x emacs
 >
 > *Steps to reproduce*
 >
 >     1. start emacs
 >     2. start a term buffer with M-x term
 >     3. run `seq 1000` at the bash prompt to fill the screen
 >     4. enlarge the terminal window that emacs is running in, so that the
 >     window size changes as well
 >     5. run `seq 1000` again, and observe that the new space at the bottom of
 >     the buffer is not being used
 >
 > *Analysis notes*
 >
 > term-mode *does* pick up changes after more explicit window configurations,
 > like splits; my workaround for months has been to split and join the
 > terminal window whenever I've resized it.
 >
 > As best I can tell, term-mode subscribes to window size changes by adding
 > advice to the window-adjust-process-window-size-function variable, and the
 > 8e7712c7afc reduced the set of situations in which that function is called.
 >
 > I've developed a more automated workaround with a term-load-hook of this
 > form:
 >
 > (add-hook 'window-size-change-functions (lambda (_frame)
 > (window--adjust-process-windows)))
 >
 > It might be that adding this line to the term-mode setup steps would be
 > sufficient, but I'm not familiar enough with the window.el code to have a
 > guess whether that's actually a good approach.

While all you write above is correct and I agree with the fix you
propose, I tend to restore the old behavior as with the attached
patch.  The reason is that I have no idea in how many more yet
unrevealed occasions my commit had adverse effects so I'd rather be on
the safe side for Emacs 26.2.  Please try the patch and tell me
whether it indeed restores the old behavior.

Thanks, martin

[-- Attachment #2: run-window-configuration-change.diff --]
[-- Type: text/plain, Size: 1849 bytes --]

diff --git a/src/frame.c b/src/frame.c
index 0a6ca26..8076eba 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -779,6 +779,8 @@ struct frame *
 
   unblock_input ();
 
+  run_window_configuration_change_hook (f);
+
 #ifdef HAVE_WINDOW_SYSTEM
   {
     /* Adjust size of F's child frames.  */
diff --git a/src/window.c b/src/window.c
index 9026a7b..ef88fde 100644
--- a/src/window.c
+++ b/src/window.c
@@ -57,7 +57,6 @@ static bool foreach_window_1 (struct window *,
 static bool window_resize_check (struct window *, bool);
 static void window_resize_apply (struct window *, bool);
 static void select_window_1 (Lisp_Object, bool);
-static void run_window_configuration_change_hook (struct frame *);
 
 static struct window *set_window_fringes (struct window *, Lisp_Object,
 					  Lisp_Object, Lisp_Object);
@@ -3319,7 +3318,7 @@ depends on the value of (window-start WINDOW), so if calling this
     Fselect_frame (frame, Qt);
 }
 
-static void
+void
 run_window_configuration_change_hook (struct frame *f)
 {
   ptrdiff_t count = SPECPDL_INDEX ();
diff --git a/src/window.h b/src/window.h
index 629283a..bc6d8ab 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1016,6 +1016,7 @@ extern Lisp_Object window_from_coordinates (struct frame *, int, int,
 extern void shrink_mini_window (struct window *, bool);
 extern int window_relative_x_coord (struct window *, enum window_part, int);
 
+void run_window_configuration_change_hook (struct frame *f);
 void run_window_size_change_functions (Lisp_Object);
 
 /* Make WINDOW display BUFFER.  RUN_HOOKS_P means it's allowed
diff --git a/src/xfns.c b/src/xfns.c
index 1381fee..574f0bb 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -1599,4 +1599,5 @@ struct mouse_cursor_data {
     }
 #endif /* not USE_X_TOOLKIT && not USE_GTK */
   adjust_frame_glyphs (f);
+  run_window_configuration_change_hook (f);
 }

^ permalink raw reply related	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-04  9:56 ` martin rudalics
@ 2018-11-16 12:15   ` Gary Fredericks
  2018-11-16 12:57     ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-11-16 12:15 UTC (permalink / raw)
  To: rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 2038 bytes --]

Yep, it seems to work with the patch applied.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Sun, Nov 4, 2018 at 3:56 AM martin rudalics <rudalics@gmx.at> wrote:

>  > *Affects*: version 26 (git-bisected to commit 8e7712c7afc)
>  >
>  > Note: I have only tried this on --without-x emacs
>  >
>  > *Steps to reproduce*
>  >
>  >     1. start emacs
>  >     2. start a term buffer with M-x term
>  >     3. run `seq 1000` at the bash prompt to fill the screen
>  >     4. enlarge the terminal window that emacs is running in, so that the
>  >     window size changes as well
>  >     5. run `seq 1000` again, and observe that the new space at the
> bottom of
>  >     the buffer is not being used
>  >
>  > *Analysis notes*
>  >
>  > term-mode *does* pick up changes after more explicit window
> configurations,
>  > like splits; my workaround for months has been to split and join the
>  > terminal window whenever I've resized it.
>  >
>  > As best I can tell, term-mode subscribes to window size changes by
> adding
>  > advice to the window-adjust-process-window-size-function variable, and
> the
>  > 8e7712c7afc reduced the set of situations in which that function is
> called.
>  >
>  > I've developed a more automated workaround with a term-load-hook of this
>  > form:
>  >
>  > (add-hook 'window-size-change-functions (lambda (_frame)
>  > (window--adjust-process-windows)))
>  >
>  > It might be that adding this line to the term-mode setup steps would be
>  > sufficient, but I'm not familiar enough with the window.el code to have
> a
>  > guess whether that's actually a good approach.
>
> While all you write above is correct and I agree with the fix you
> propose, I tend to restore the old behavior as with the attached
> patch.  The reason is that I have no idea in how many more yet
> unrevealed occasions my commit had adverse effects so I'd rather be on
> the safe side for Emacs 26.2.  Please try the patch and tell me
> whether it indeed restores the old behavior.
>
> Thanks, martin
>

[-- Attachment #2: Type: text/html, Size: 2851 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-16 12:15   ` Gary Fredericks
@ 2018-11-16 12:57     ` martin rudalics
  2018-11-16 13:15       ` Gary Fredericks
  2018-11-16 14:45       ` Eli Zaretskii
  0 siblings, 2 replies; 46+ messages in thread
From: martin rudalics @ 2018-11-16 12:57 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > Yep, it seems to work with the patch applied.

Thanks for the feedback.  But after more carefully looking into the
'window-adjust-process-windows' code I am now almost convinced that
your original proposal is the way to go.  That is, I nowhere found in
that code anything that depends on the change of the window
configuration.  The only thing that code is interested in is tracing
window size changes which 'window-configuration-change-hook' does not
handle particularly well.

So if you already have run Emacs for some time with your

(add-hook
  'window-size-change-functions
  (lambda (_frame) (window--adjust-process-windows)))

and did not see any adversary effects I am inclined to install that
for Emacs 26.2.  For Emacs 27 I would then (after the release of Emacs
26.2) remove the

(add-hook 'window-configuration-change-hook 'window--adjust-process-windows)

call.

Eli would that be OK with you as well?  I'd still have to amend the
doc of 'window-configuration-change-hook' but the net change would be
considerably smaller than the one I proposed in the other thread.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-16 12:57     ` martin rudalics
@ 2018-11-16 13:15       ` Gary Fredericks
  2018-11-18  9:22         ` martin rudalics
  2018-11-16 14:45       ` Eli Zaretskii
  1 sibling, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-11-16 13:15 UTC (permalink / raw)
  To: rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 1437 bytes --]

Confirmed that I've been using that add-hook call for a while (ever since I
originally reported this) and haven't noticed any adverse effects.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Fri, Nov 16, 2018 at 6:58 AM martin rudalics <rudalics@gmx.at> wrote:

>  > Yep, it seems to work with the patch applied.
>
> Thanks for the feedback.  But after more carefully looking into the
> 'window-adjust-process-windows' code I am now almost convinced that
> your original proposal is the way to go.  That is, I nowhere found in
> that code anything that depends on the change of the window
> configuration.  The only thing that code is interested in is tracing
> window size changes which 'window-configuration-change-hook' does not
> handle particularly well.
>
> So if you already have run Emacs for some time with your
>
> (add-hook
>   'window-size-change-functions
>   (lambda (_frame) (window--adjust-process-windows)))
>
> and did not see any adversary effects I am inclined to install that
> for Emacs 26.2.  For Emacs 27 I would then (after the release of Emacs
> 26.2) remove the
>
> (add-hook 'window-configuration-change-hook
> 'window--adjust-process-windows)
>
> call.
>
> Eli would that be OK with you as well?  I'd still have to amend the
> doc of 'window-configuration-change-hook' but the net change would be
> considerably smaller than the one I proposed in the other thread.
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 2096 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-16 12:57     ` martin rudalics
  2018-11-16 13:15       ` Gary Fredericks
@ 2018-11-16 14:45       ` Eli Zaretskii
  2018-11-17  9:20         ` martin rudalics
  1 sibling, 1 reply; 46+ messages in thread
From: Eli Zaretskii @ 2018-11-16 14:45 UTC (permalink / raw)
  To: martin rudalics; +Cc: fredericksgary, 32720

> Date: Fri, 16 Nov 2018 13:57:51 +0100
> From: martin rudalics <rudalics@gmx.at>
> CC: 32720@debbugs.gnu.org, "eliz@gnu.org" <eliz@gnu.org>
> 
> So if you already have run Emacs for some time with your
> 
> (add-hook
>   'window-size-change-functions
>   (lambda (_frame) (window--adjust-process-windows)))
> 
> and did not see any adversary effects I am inclined to install that
> for Emacs 26.2.  For Emacs 27 I would then (after the release of Emacs
> 26.2) remove the
> 
> (add-hook 'window-configuration-change-hook 'window--adjust-process-windows)
> 
> call.
> 
> Eli would that be OK with you as well?

I don't think I have a clear idea of what is being proposed for
emacs-26.





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-16 14:45       ` Eli Zaretskii
@ 2018-11-17  9:20         ` martin rudalics
  2018-11-17  9:43           ` Eli Zaretskii
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-11-17  9:20 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: fredericksgary, 32720

[-- Attachment #1: Type: text/plain, Size: 121 bytes --]

 > I don't think I have a clear idea of what is being proposed for
 > emacs-26.

I propose the attached changes.

martin

[-- Attachment #2: window-configuration-change-hook.diff --]
[-- Type: text/plain, Size: 3221 bytes --]

diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index e9bd0c7..46f1068 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -6016,26 +6016,24 @@ Window Hooks
 @code{window-pixel-height} for that window (@pxref{Window Sizes}).
 
 These function are usually only called when at least one window was
-added or has changed size since the last time this hook was run for the
-associated frame.  In some rare cases this hook also runs when a window
-that was added intermittently has been deleted afterwards.  In these
-cases none of the windows on the frame will appear to have changed its
-size.
-
-You may use @code{save-selected-window} in these functions
-(@pxref{Selecting Windows}).  However, do not use
-@code{save-window-excursion} (@pxref{Window Configurations}); exiting
-that macro counts as a size change, which would cause these functions to
-be called again.
+added or has changed size since the last time this hook was run for
+the associated frame.  In some rare cases this hook also runs when a
+window that was added intermittently has been deleted afterwards.  In
+these cases none of the windows on the frame will appear to have
+changed its size.
 @end defvar
 
 @defvar window-configuration-change-hook
-A normal hook that is run every time the window configuration of a frame
-changes.  Window configuration changes include splitting and deleting
-windows, and the display of a different buffer in a window.  Resizing the
-frame or individual windows do not count as configuration changes.  Use
-@code{window-size-change-functions}, see above, when you want to track
-size changes that are not caused by the deletion or creation of windows.
+A normal hook that is run every time the window configuration of a
+frame changes.  Window configuration changes include splitting and
+deleting windows, and the display of a different buffer in a window.
+
+The hook can be also used for tracking changes of window sizes.  It
+is, however, not run when the size of a frame changes or automatic
+resizing of a minibuffer window (@pxref{Minibuffer Windows}) changes
+the size of another window.  As a rule, adding a function to
+@code{window-size-change-functions}, see above, is the recommended way
+for reliably tracking size changes of any window.
 
 The buffer-local value of this hook is run once for each window on the
 affected frame, with the relevant window selected and its buffer
diff --git a/lisp/window.el b/lisp/window.el
index 92cd8c2..f4e6f14 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -9287,8 +9287,18 @@ window--adjust-process-windows
               (when size
                 (set-process-window-size process (cdr size) (car size))))))))))
 
+;; Remove the following call in Emacs 27, running
+;; 'window-size-change-functions' should suffice.
 (add-hook 'window-configuration-change-hook 'window--adjust-process-windows)
 
+;; Catch any size changes not handled by
+;; 'window-configuration-change-hook' (Bug#32720, "another issue" in
+;; Bug#33230).
+(add-hook
+ 'window-size-change-functions
+ (lambda (_frame)
+   (window--adjust-process-windows)))
+
 \f
 ;; Some of these are in tutorial--default-keys, so update that if you
 ;; change these.


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-17  9:20         ` martin rudalics
@ 2018-11-17  9:43           ` Eli Zaretskii
  2018-11-17 18:40             ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Eli Zaretskii @ 2018-11-17  9:43 UTC (permalink / raw)
  To: martin rudalics; +Cc: fredericksgary, 32720

> Date: Sat, 17 Nov 2018 10:20:55 +0100
> From: martin rudalics <rudalics@gmx.at>
> CC: fredericksgary@gmail.com, 32720@debbugs.gnu.org
> 
>  > I don't think I have a clear idea of what is being proposed for
>  > emacs-26.
> 
> I propose the attached changes.

OK (although I don't like putting functions on hooks in the core).

> +;; Remove the following call in Emacs 27, running
> +;; 'window-size-change-functions' should suffice.
>  (add-hook 'window-configuration-change-hook 'window--adjust-process-windows)

Why not do that now?





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-17  9:43           ` Eli Zaretskii
@ 2018-11-17 18:40             ` martin rudalics
  2018-11-18  3:30               ` Eli Zaretskii
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-11-17 18:40 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: fredericksgary, 32720

 > OK (although I don't like putting functions on hooks in the core).

Neither do I.

 >> +;; Remove the following call in Emacs 27, running
 >> +;; 'window-size-change-functions' should suffice.
 >>   (add-hook 'window-configuration-change-hook 'window--adjust-process-windows)
 >
 > Why not do that now?

Because Gary has not tested it ;-)

More seriously: I have no idea how 'adjust-window-size-function' and
the function specified by 'window-adjust-process-window-size-function'
work in practice.  If they rely on anything beyond a window's
dimensions (for example, on which other buffers are displayed on a
frame), then not calling 'window--adjust-process-windows' for
'window-configuration-change-hook' might miss something.  I'd rather
reserve such subtleties for Emacs 27.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-17 18:40             ` martin rudalics
@ 2018-11-18  3:30               ` Eli Zaretskii
  2018-11-18  9:22                 ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Eli Zaretskii @ 2018-11-18  3:30 UTC (permalink / raw)
  To: martin rudalics; +Cc: fredericksgary, 32720

> Date: Sat, 17 Nov 2018 19:40:01 +0100
> From: martin rudalics <rudalics@gmx.at>
> CC: fredericksgary@gmail.com, 32720@debbugs.gnu.org
> 
>  >> +;; Remove the following call in Emacs 27, running
>  >> +;; 'window-size-change-functions' should suffice.
>  >>   (add-hook 'window-configuration-change-hook 'window--adjust-process-windows)
>  >
>  > Why not do that now?
> 
> Because Gary has not tested it ;-)
> 
> More seriously: I have no idea how 'adjust-window-size-function' and
> the function specified by 'window-adjust-process-window-size-function'
> work in practice.  If they rely on anything beyond a window's
> dimensions (for example, on which other buffers are displayed on a
> frame), then not calling 'window--adjust-process-windows' for
> 'window-configuration-change-hook' might miss something.  I'd rather
> reserve such subtleties for Emacs 27.

I agree with doing this for Emacs 27, I'm asking why not do this now
on master?





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-16 13:15       ` Gary Fredericks
@ 2018-11-18  9:22         ` martin rudalics
  0 siblings, 0 replies; 46+ messages in thread
From: martin rudalics @ 2018-11-18  9:22 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

fixed 32720 26.2

 > Confirmed that I've been using that add-hook call for a while (ever since I
 > originally reported this) and haven't noticed any adverse effects.

I pushed your fix now to the release branch as commit
88762b4063a42a69234bda74b1626b646734715a.  If you are interested in
the further development of this, please run Emacs with the line

(add-hook 'window-configuration-change-hook 'window--adjust-process-windows)

removed and tell us whether it causes any problems.

Closing this bug (hopefully).

Thanks, martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-18  3:30               ` Eli Zaretskii
@ 2018-11-18  9:22                 ` martin rudalics
  2018-11-18 15:21                   ` Eli Zaretskii
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-11-18  9:22 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: fredericksgary, 32720

 > I agree with doing this for Emacs 27, I'm asking why not do this now
 > on master?

Because most people run master and I'm interested in testing whether
the interaction between 'window-configuration-change-hook' and
'window-size-change-functions' could cause any problems.  As soon as
Emacs 26.2 is released (and if Gary doesn't see any problems in the
meantime) I make the change on master.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-18  9:22                 ` martin rudalics
@ 2018-11-18 15:21                   ` Eli Zaretskii
  2018-11-18 19:37                     ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Eli Zaretskii @ 2018-11-18 15:21 UTC (permalink / raw)
  To: martin rudalics; +Cc: fredericksgary, 32720

> Date: Sun, 18 Nov 2018 10:22:40 +0100
> From: martin rudalics <rudalics@gmx.at>
> CC: fredericksgary@gmail.com, 32720@debbugs.gnu.org
> 
>  > I agree with doing this for Emacs 27, I'm asking why not do this now
>  > on master?
> 
> Because most people run master and I'm interested in testing whether
> the interaction between 'window-configuration-change-hook' and
> 'window-size-change-functions' could cause any problems.

Indeed, doing this on master now will allow us to collect testing
experience sooner, so I think it's a win.





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-18 15:21                   ` Eli Zaretskii
@ 2018-11-18 19:37                     ` martin rudalics
  2018-11-18 20:10                       ` Eli Zaretskii
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-11-18 19:37 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: fredericksgary, 32720

 >> Because most people run master and I'm interested in testing whether
 >> the interaction between 'window-configuration-change-hook' and
 >> 'window-size-change-functions' could cause any problems.
 >
 > Indeed, doing this on master now will allow us to collect testing
 > experience sooner, so I think it's a win.

You mean doing what on master?  Remove 'window--adjust-process-windows'
from 'window-configuration-change-hook'?  But then nobody will test
the way we do that on the release branch now.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-18 19:37                     ` martin rudalics
@ 2018-11-18 20:10                       ` Eli Zaretskii
  2018-11-19  9:41                         ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Eli Zaretskii @ 2018-11-18 20:10 UTC (permalink / raw)
  To: martin rudalics; +Cc: fredericksgary, 32720

> Date: Sun, 18 Nov 2018 20:37:07 +0100
> From: martin rudalics <rudalics@gmx.at>
> CC: fredericksgary@gmail.com, 32720@debbugs.gnu.org
> 
>  >> Because most people run master and I'm interested in testing whether
>  >> the interaction between 'window-configuration-change-hook' and
>  >> 'window-size-change-functions' could cause any problems.
>  >
>  > Indeed, doing this on master now will allow us to collect testing
>  > experience sooner, so I think it's a win.
> 
> You mean doing what on master?  Remove 'window--adjust-process-windows'
> from 'window-configuration-change-hook'?

Yes.

> But then nobody will test the way we do that on the release branch
> now.

Those who use Emacs 26 will.





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-18 20:10                       ` Eli Zaretskii
@ 2018-11-19  9:41                         ` martin rudalics
  2018-11-19 15:04                           ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-11-19  9:41 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: fredericksgary, 32720

 >> You mean doing what on master?  Remove 'window--adjust-process-windows'
 >> from 'window-configuration-change-hook'?
 >
 > Yes.

OK.  I'll do it in a week or so.  Maybe Gary can test it till then.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-19  9:41                         ` martin rudalics
@ 2018-11-19 15:04                           ` Gary Fredericks
  2018-11-19 15:14                             ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-11-19 15:04 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 329 bytes --]

What should I be testing exactly?

On Mon, Nov 19, 2018, 03:41 martin rudalics <rudalics@gmx.at wrote:

>  >> You mean doing what on master?  Remove 'window--adjust-process-windows'
>  >> from 'window-configuration-change-hook'?
>  >
>  > Yes.
>
> OK.  I'll do it in a week or so.  Maybe Gary can test it till then.
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 633 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-19 15:04                           ` Gary Fredericks
@ 2018-11-19 15:14                             ` martin rudalics
  2018-12-22 22:53                               ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-11-19 15:14 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 281 bytes --]

 > What should I be testing exactly?

In window.el remove the

;; Remove the following call in Emacs 27, running
;; 'window-size-change-functions' should suffice.
(add-hook 'window-configuration-change-hook 'window--adjust-process-windows)

lines as in the attached patch.

martin

[-- Attachment #2: use-size-change-functions-only.diff --]
[-- Type: text/plain, Size: 591 bytes --]

diff --git a/lisp/window.el b/lisp/window.el
index f252b0e..a5a865e 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -9287,10 +9287,6 @@ window--adjust-process-windows
               (when size
                 (set-process-window-size process (cdr size) (car size))))))))))
 
-;; Remove the following call in Emacs 27, running
-;; 'window-size-change-functions' should suffice.
-(add-hook 'window-configuration-change-hook 'window--adjust-process-windows)
-
 ;; Catch any size changes not handled by
 ;; 'window-configuration-change-hook' (Bug#32720, "another issue" in
 ;; Bug#33230).


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-11-19 15:14                             ` martin rudalics
@ 2018-12-22 22:53                               ` Gary Fredericks
  2018-12-23  9:38                                 ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-12-22 22:53 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 535 bytes --]

My apologies, I only started testing this patch today.

Seems to work fine so far.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Mon, Nov 19, 2018 at 9:14 AM martin rudalics <rudalics@gmx.at> wrote:

>  > What should I be testing exactly?
>
> In window.el remove the
>
> ;; Remove the following call in Emacs 27, running
> ;; 'window-size-change-functions' should suffice.
> (add-hook 'window-configuration-change-hook
> 'window--adjust-process-windows)
>
> lines as in the attached patch.
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 1144 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-22 22:53                               ` Gary Fredericks
@ 2018-12-23  9:38                                 ` martin rudalics
  2018-12-23 13:16                                   ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-12-23  9:38 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > My apologies, I only started testing this patch today.
 >
 > Seems to work fine so far.

Did you rebuild Emacs?  It might have problems when you show a process
buffer in an existing window whose size you never change thereafter.

Anyway, don't bother too much about it.  I'm currently trying to
redesign window change hooks completely in a way this issue will be
hopefully not relevant afterwards.

Thanks, martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-23  9:38                                 ` martin rudalics
@ 2018-12-23 13:16                                   ` Gary Fredericks
  2018-12-23 13:40                                     ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-12-23 13:16 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 930 bytes --]

I did rebuild emacs (which I don't normally do, which is why it took me a
while) -- it didn't build until I did "make bootstrap".

I don't quite understand "It might have problems when you show a process
buffer in an existing window whose size you never change thereafter."

If you'd like me to try something, please be a bit more explicit.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Sun, Dec 23, 2018 at 3:38 AM martin rudalics <rudalics@gmx.at> wrote:

>  > My apologies, I only started testing this patch today.
>  >
>  > Seems to work fine so far.
>
> Did you rebuild Emacs?  It might have problems when you show a process
> buffer in an existing window whose size you never change thereafter.
>
> Anyway, don't bother too much about it.  I'm currently trying to
> redesign window change hooks completely in a way this issue will be
> hopefully not relevant afterwards.
>
> Thanks, martin
>

[-- Attachment #2: Type: text/html, Size: 1591 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-23 13:16                                   ` Gary Fredericks
@ 2018-12-23 13:40                                     ` martin rudalics
  2018-12-23 13:47                                       ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-12-23 13:40 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > I don't quite understand "It might have problems when you show a process
 > buffer in an existing window whose size you never change thereafter."

I've been only guessing.  'window-size-change-functions' triggers only
after a window is created or changed size.  It doesn't trigger when a
window gets another buffer.  So for example the following scenario
should fail:

(1) Show process output in a window.

(2) Display another buffer in that window.

(3) Change the width of the window.

(4) Show the process output again in that window.

I suppose (4) fails to communicate the new window width to the
process.  If you now do

(5) Change the window width again.

everything should be OK.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-23 13:40                                     ` martin rudalics
@ 2018-12-23 13:47                                       ` Gary Fredericks
  2018-12-23 18:02                                         ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-12-23 13:47 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 1005 bytes --]

Yes, that does seem to fail.

You're anticipating this will be fixed by the broader changes you alluded
to earlier?

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Sun, Dec 23, 2018 at 7:40 AM martin rudalics <rudalics@gmx.at> wrote:

>  > I don't quite understand "It might have problems when you show a process
>  > buffer in an existing window whose size you never change thereafter."
>
> I've been only guessing.  'window-size-change-functions' triggers only
> after a window is created or changed size.  It doesn't trigger when a
> window gets another buffer.  So for example the following scenario
> should fail:
>
> (1) Show process output in a window.
>
> (2) Display another buffer in that window.
>
> (3) Change the width of the window.
>
> (4) Show the process output again in that window.
>
> I suppose (4) fails to communicate the new window width to the
> process.  If you now do
>
> (5) Change the window width again.
>
> everything should be OK.
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 1667 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-23 13:47                                       ` Gary Fredericks
@ 2018-12-23 18:02                                         ` martin rudalics
  2018-12-23 18:54                                           ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-12-23 18:02 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > Yes, that does seem to fail.
 >
 > You're anticipating this will be fixed by the broader changes you alluded
 > to earlier?

Yes.  So please remove that one-line change from Emacs 26.  I'll post
the new patch here in a few days, against Emacs 27.  Maybe you can
upgrade then.

Thanks for testing, martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-23 18:02                                         ` martin rudalics
@ 2018-12-23 18:54                                           ` Gary Fredericks
  2018-12-25  9:51                                             ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-12-23 18:54 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 594 bytes --]

Now that you mention it, I was probably testing against emacs27 -- I just
applied the change to the master branch.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Sun, Dec 23, 2018 at 12:03 PM martin rudalics <rudalics@gmx.at> wrote:

>  > Yes, that does seem to fail.
>  >
>  > You're anticipating this will be fixed by the broader changes you
> alluded
>  > to earlier?
>
> Yes.  So please remove that one-line change from Emacs 26.  I'll post
> the new patch here in a few days, against Emacs 27.  Maybe you can
> upgrade then.
>
> Thanks for testing, martin
>

[-- Attachment #2: Type: text/html, Size: 1177 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-23 18:54                                           ` Gary Fredericks
@ 2018-12-25  9:51                                             ` martin rudalics
  2018-12-29 23:23                                               ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-12-25  9:51 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > Now that you mention it, I was probably testing against emacs27 -- I just
 > applied the change to the master branch.

I now posted a patch for running window change hooks on emacs-devel.
See

http://lists.gnu.org/archive/html/emacs-devel/2018-12/msg00430.html

Please try the patch and report any problems.

Thanks, martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-25  9:51                                             ` martin rudalics
@ 2018-12-29 23:23                                               ` Gary Fredericks
  2018-12-30  9:53                                                 ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-12-29 23:23 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 717 bytes --]

How am I supposed to apply the patch? I get this:

$ git apply txtC00XwS8xFx.txt
error: corrupt patch at line 9

I think I had that same issue with your earlier patch, but it was small
enough that I could edit by hand.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Tue, Dec 25, 2018 at 3:51 AM martin rudalics <rudalics@gmx.at> wrote:

>  > Now that you mention it, I was probably testing against emacs27 -- I
> just
>  > applied the change to the master branch.
>
> I now posted a patch for running window change hooks on emacs-devel.
> See
>
> http://lists.gnu.org/archive/html/emacs-devel/2018-12/msg00430.html
>
> Please try the patch and report any problems.
>
> Thanks, martin
>

[-- Attachment #2: Type: text/html, Size: 1501 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-29 23:23                                               ` Gary Fredericks
@ 2018-12-30  9:53                                                 ` martin rudalics
  2018-12-31 12:45                                                   ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-12-30  9:53 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > How am I supposed to apply the patch? I get this:
 >
 > $ git apply txtC00XwS8xFx.txt
 > error: corrupt patch at line 9

Which operating system?  What does

git apply txtC00XwS8xFx.txt --verbose

give?

 > I think I had that same issue with your earlier patch, but it was small
 > enough that I could edit by hand.

Are you sure you are on master?

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-30  9:53                                                 ` martin rudalics
@ 2018-12-31 12:45                                                   ` Gary Fredericks
  2018-12-31 14:16                                                     ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2018-12-31 12:45 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 805 bytes --]

Yes, on master, using an ubuntu of some sort:

$ git show | head -1
commit 792dc36e691b1e4b7735c75d2d402d1b9a8801ce

$ git apply txtC00XwS8xFx.txt --verbose
error: corrupt patch at line 9

$ md5sum txtC00XwS8xFx.txt
0d958ef0f85eef10f0de8e963044278f txtC00XwS8xFx.txt

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Sun, Dec 30, 2018 at 3:53 AM martin rudalics <rudalics@gmx.at> wrote:

>  > How am I supposed to apply the patch? I get this:
>  >
>  > $ git apply txtC00XwS8xFx.txt
>  > error: corrupt patch at line 9
>
> Which operating system?  What does
>
> git apply txtC00XwS8xFx.txt --verbose
>
> give?
>
>  > I think I had that same issue with your earlier patch, but it was small
>  > enough that I could edit by hand.
>
> Are you sure you are on master?
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 1913 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-31 12:45                                                   ` Gary Fredericks
@ 2018-12-31 14:16                                                     ` martin rudalics
  2019-01-01 15:37                                                       ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2018-12-31 14:16 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 527 bytes --]

 > $ git show | head -1
 > commit 792dc36e691b1e4b7735c75d2d402d1b9a8801ce
 >
 > $ git apply txtC00XwS8xFx.txt --verbose
 > error: corrupt patch at line 9
 >
 > $ md5sum txtC00XwS8xFx.txt
 > 0d958ef0f85eef10f0de8e963044278f txtC00XwS8xFx.txt

No idea what happened.  I attach the latest version against today's
master (the same commit you mentioned).

git show | head -1
commit 792dc36e691b1e4b7735c75d2d402d1b9a8801ce

md5sum window-change-functions.diff
619d18ffa7106e21c07992d2b6df302a *window-change-functions.diff

martin

[-- Attachment #2: window-change-functions.diff --]
[-- Type: text/plain, Size: 81803 bytes --]

diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi
index f2f6cd3..c91e438 100644
--- a/doc/lispref/windows.texi
+++ b/doc/lispref/windows.texi
@@ -568,12 +568,6 @@ Window Sizes
 children.
 @end defun
 
-@defun window-pixel-height-before-size-change &optional Lisp_Object &optional window
-This function returns the height of window @var{window} in pixels at the
-time @code{window-size-change-functions} was run for the last time on
-@var{window}'s frame (@pxref{Window Hooks}).
-@end defun
-
 @cindex window pixel width
 @cindex pixel width of a window
 @cindex total pixel width of a window
@@ -588,12 +582,6 @@ Window Sizes
 the screen areas spanned by its children.
 @end defun
 
-@defun window-pixel-width-before-size-change &optional Lisp_Object &optional window
-This function returns the width of window @var{window} in pixels at the
-time @code{window-size-change-functions} was run for the last time on
-@var{window}'s frame (@pxref{Window Hooks}).
-@end defun
-
 @cindex full-width window
 @cindex full-height window
   The following functions can be used to determine whether a given
@@ -5695,10 +5683,6 @@ Window Configurations
 windows might be opened in other frames (@pxref{Choosing Window}), and
 @code{save-window-excursion} only saves and restores the window
 configuration on the current frame.
-
-Do not use this macro in @code{window-size-change-functions}; exiting
-the macro triggers execution of @code{window-size-change-functions},
-leading to an endless loop.
 @end defmac
 
 @defun window-configuration-p object
@@ -5817,10 +5801,10 @@ Window Parameters
 is the selected window.
 @end defun
 
-By default, the functions that save and restore window configurations or the
-states of windows (@pxref{Window Configurations}) do not care about
-window parameters.  This means that when you change the value of a
-parameter within the body of a @code{save-window-excursion}, the
+By default, the functions that save and restore window configurations
+or the states of windows (@pxref{Window Configurations}) do not care
+about window parameters.  This means that when you change the value of
+a parameter within the body of a @code{save-window-excursion}, the
 previous value is not restored when that macro exits.  It also means
 that when you restore via @code{window-state-put} a window state saved
 earlier by @code{window-state-get}, all cloned windows have their
@@ -6009,27 +5993,26 @@ Window Parameters
 versions of Emacs.
 @end table
 
+
 @node Window Hooks
 @section Hooks for Window Scrolling and Changes
 @cindex hooks for window operations
 
-This section describes how a Lisp program can take action whenever a
-window displays a different part of its buffer or a different buffer.
-There are three actions that can change this: scrolling the window,
-switching buffers in the window, and changing the size of the window.
-The first two actions run @code{window-scroll-functions}; the last runs
-@code{window-size-change-functions}.
+This section describes how Lisp programs can take action after a
+window has been scrolled or other window modifications occurred.  We
+first consider the case where a window shows a different part of its
+buffer.
 
 @defvar window-scroll-functions
 This variable holds a list of functions that Emacs should call before
-redisplaying a window with scrolling.  Displaying a different buffer in
-the window also runs these functions.
+redisplaying a window with scrolling.  Displaying a different buffer
+in a window and making a new window also call these functions.
 
-This variable is not a normal hook, because each function is called with
-two arguments: the window, and its new display-start position.  At the
-time of the call, the display-start position of the window argument is
-already set to its new value, and the buffer to be displayed in the
-window is already set as the current buffer.
+This variable is not a normal hook, because each function is called
+with two arguments: the window, and its new display-start position.
+At the time of the call, the display-start position of the argument
+window is already set to its new value, and the buffer to be displayed
+in the window is set as the current buffer.
 
 These functions must take care when using @code{window-end}
 (@pxref{Window Start and End}); if you need an up-to-date value, you
@@ -6040,63 +6023,226 @@ Window Hooks
 work.
 @end defvar
 
-@defun run-window-scroll-functions &optional window
-This function calls @code{window-scroll-functions} for the specified
-@var{window}, which defaults to the selected window.
-@end defun
+In addition, you can use @code{jit-lock-register} to register a Font
+Lock fontification function, which will be called whenever parts of a
+buffer are (re)fontified because a window was scrolled or its size
+changed.  @xref{Other Font Lock Variables}.
+
+@cindex window change functions
+   The remainder of this section covers four hooks that are called at
+the end of redisplay provided a significant, non-scrolling change of a
+window has been detected.  For simplicity, these hooks and the
+functions they call will be collectively referred to as @dfn{window
+change functions}.
+
+@cindex window buffer change
+The first of these hooks is run after a @dfn{window buffer change} is
+detected, which means that a window was created, deleted or assigned
+another buffer.
+
+@defvar window-buffer-change-functions
+This variable specifies functions called at the end of redisplay when
+window buffers have changed.  The value should be a list of functions
+that take one argument.
+
+Functions specified buffer-locally are called for any window showing
+the corresponding buffer if that window has been created or assigned
+that buffer since the last time window change functions were run.  In
+this case the window is passed as argument.
+
+Functions specified by the default value are called for a frame if at
+least one window on that frame has been added, deleted or assigned
+another buffer since the last time window change functions were run.
+In this case the frame is passed as argument.
+@end defvar
+
+@cindex window size change
+The second of these hooks is run after a @dfn{window size change} has
+been detected which means that a window was created, assigned another
+buffer, or changed its total size or that of its text area.
 
 @defvar window-size-change-functions
-This variable holds a list of functions to be called if the size of any
-window changes for any reason.  The functions are called once per
-redisplay, and once for each frame on which size changes have occurred.
-
-Each function receives the frame as its sole argument.  To find out
-whether a specific window has changed size, compare the return values of
-@code{window-pixel-width-before-size-change} and
-@code{window-pixel-width} respectively
-@code{window-pixel-height-before-size-change} and
-@code{window-pixel-height} for that window (@pxref{Window Sizes}).
-
-The buffer-local value of this hook is run once for the buffer and the
-frame in question, provided at least one window showing the buffer on
-that frame has changed its size.  As it still receives the frame as
-its sole argument, any function called on a buffer-local basis will be
-oblivious to which window(s) showing the buffer changed its (their)
-size and has to check out these windows by using the method described
-in the previous paragraph.
-
-These function are usually only called when at least one window was
-added or has changed size since the last time this hook was run for
-the associated frame.  In some rare cases this hook also runs when a
-window that was added intermittently has been deleted afterwards.  In
-these cases none of the windows on the frame will appear to have
-changed its size.
+This variable specifies functions called at the end of redisplay when
+a window size change occurred.  The value should be a list of
+functions that take one argument.
+
+Functions specified buffer-locally are called for any window showing
+the corresponding buffer if that window has been added or assigned
+another buffer, total or body size since the last time window change
+functions were run.  In this case the window is passed as argument.
+
+Functions specified by the default value are called for a frame if at
+least one window on that frame has been added or assigned another
+buffer, total or body size since the last time window change functions
+were run.  In this case the frame is passed as argument.
+@end defvar
+
+@cindex window selection change
+The third of these hooks is run after a @dfn{window selection change}
+has selected another window since the last redisplay.
+
+@defvar window-selection-change-functions
+This variable specifies functions called at the end of redisplay when
+the selected window or a frame's selected window has changed.  The
+value should be a list of functions that take one argument.
+
+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.
+
+Functions specified by the default value are called for a frame if
+that frame has been selected or deselected or the frame's selected
+window has changed since the last time window change functions were
+run.  In this case the frame is passed as argument.
 @end defvar
 
+@cindex window configuration change
+The fourth of these hooks is run when a @dfn{window configuration
+change} has been detected which means that either the buffer or the
+size of a window changed.
+
 @defvar window-configuration-change-hook
-A normal hook that is run every time the window configuration of a
-frame changes.  Window configuration changes include splitting and
-deleting windows, and the display of a different buffer in a window.
-
-The hook can be also used for tracking changes of window sizes.  It
-is, however, not run when the size of a frame changes or automatic
-resizing of a minibuffer window (@pxref{Minibuffer Windows}) changes
-the size of another window.  As a rule, adding a function to
-@code{window-size-change-functions}, see above, is the recommended way
-for reliably tracking size changes of any window.
-
-The buffer-local value of this hook is run once for each window on the
-affected frame, with the relevant window selected and its buffer
-current.  The global value of this hook is run once for the modified
-frame, with that frame selected.
+This variable specifies functions called at the end of redisplay when
+either the buffer or the size of a window has changed.  The value
+should be a list of functions that take no argument.
+
+Functions specified buffer-locally are called for any window showing
+the corresponding buffer if at least one window on that frame has been
+added, deleted or assigned another buffer, total or body size since
+the last time window change functions were run.  Each call is
+performed with the window showing the buffer temporarily selected and
+its buffer current.
+
+Functions specified by the default value are called for each frame if
+at least one window on that frame has been added, deleted or assigned
+another buffer, total or body size since the last time window change
+functions were run.  Each call is performed with the frame temporarily
+selected and the selected window's buffer current.
 @end defvar
 
-@defun run-window-configuration-change-hook &optional frame
-This function runs @code{window-configuration-change-hook} for the
-specified @var{frame}, which defaults to the selected frame.
+Window change functions are called at the end of redisplay for each
+frame as follows: First, any buffer-local window buffer change
+function, window size change function and selected window change
+functions are called in this order.  Next, the default values for
+these functions are called in the same order.  Then any buffer-local
+window configuration change functions are called followed by functions
+specified by the default value of those functions.
+
+   Window change functions are run for a specific frame only if a
+corresponding change was registered for that frame earlier.  Such
+changes include the creation or deletion of a window or the assignment
+of another buffer or size to a window.  Note that even when such a
+change has been registered, this does not mean that any of the hooks
+described above is run.  If, for example, a change was registered
+within the scope of a window excursion (@pxref{Window
+Configurations}), this will trigger a call of window change functions
+only if that excursion still persists at the time change functions are
+run.  If it is exited earlier, hooks will be run only if registered by
+a change outside the scope of that excursion.
+
+   While window change functions are run, the functions described next
+can be called to get more insight into what has changed for a specific
+window or frame since the last redisplay.  All these functions take a
+live window as single, optional argument, defaulting to the selected
+window.
+
+@defun window-old-buffer &optional window
+This function returns the buffer shown in @var{window} at the last
+time window change functions were run for @var{window}'s frame.  If it
+returns @code{nil}, @var{window} has been created after that.  If it
+returns @code{t}, @var{window} was not shown at that time but has been
+restored from a previously saved window configuration afterwards.
+Otherwise, the return value is the buffer shown by @code{window} at
+that time.
 @end defun
 
-  In addition, you can use @code{jit-lock-register} to register a Font
-Lock fontification function, which will be called whenever parts of a
-buffer are (re)fontified because a window was scrolled or its size
-changed.  @xref{Other Font Lock Variables}.
+@defun window-old-pixel-width &optional window
+This function returns the total pixel width of @var{window} the
+last time window change functions found @code{window} live on its
+frame.  It is zero if @code{window} was created after that.
+@end defun
+
+@defun window-old-pixel-height &optional window
+This function returns the total pixel height of @var{window} the last
+time window change functions found @code{window} live on its frame.
+It is zero if @code{window} was created after that.
+@end defun
+
+@defun window-old-body-pixel-width &optional window
+This function returns the pixel width of @var{window}'s text area the
+last time window change functions found @code{window} live on its
+frame.  It is zero if @code{window} was created after that.
+@end defun
+
+@defun window-old-body-pixel-height &optional window
+This function returns the pixel height of @var{window}'s text area the
+last time window change functions found @code{window} live on its
+frame.  It is zero if @code{window} was created after that.
+@end defun
+
+In order to find out which window or frame was selected the last time
+window change functions were run, the following functions can be used:
+
+@defun frame-old-selected-window &optional frame
+This function returns the selected window of @var{frame} at the last
+time window change functions were run.  If omitted or @code{nil}
+@var{frame} defaults to the selected frame.
+@end defun
+
+@defun old-selected-window
+This function returns the selected window at the last time window
+change functions were run.
+@end defun
+
+@defun old-selected-frame
+This function returns the selected frame at the last time window
+change functions were run.
+@end defun
+
+Note that window change functions provide no information about which
+windows have been deleted since the last time they were run.  If
+necessary, an application should remember any window showing a
+specific buffer in a local variable of that buffer and update it in a
+function run by the default value of
+@code{window-buffer-change-functions} or
+@code{window-configuration-change-hook} (the only hooks triggered by
+the deletion of windows).
+
+   The following caveats should be considered when adding a function
+to window change functions:
+
+@itemize @bullet
+@item
+Some operations will not trigger a call of window change functions.
+These include showing another buffer in a minibuffer window or any
+change of a tooltip window.
+
+@item
+Window change functions should not create or delete windows or change
+the buffer, size or selection status of any window because there is no
+guarantee that the information about such a change will be propagated
+to other window change functions.  If at all, any such change should
+be executed only by the last function listed by the default value of
+@code{window-configuration-change-hook}.
+
+@item
+Macros like @code{save-window-excursion}, @code{with-selected-window}
+or @code{with-current-buffer} can be used when running window change
+functions.
+
+@item
+Running window change functions does not save and restore match data.
+Unless running @code{window-configuration-change-hook} it does not
+save or restore the selected window or frame or the current buffer
+either.
+
+@item
+Any redisplay triggering the run of window change functions may be
+aborted.  If the abort occurs before window change functions have run
+to their completion, they will be run again with the previous values,
+that is, as if redisplay had not been performed.  If aborted later,
+they will be run with the new values, that is, as if redisplay had
+been actually performed.
+@end itemize
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index d1f4d4a..5120509 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -640,7 +640,7 @@ erc-window-configuration-change
   (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)))
+    (erc-modified-channels-update)))
 
 (defvar erc-modified-channels-update-inside nil
   "Variable to prevent running `erc-modified-channels-update' multiple
@@ -669,8 +669,7 @@ erc-modified-channels-update
 		  (erc-modified-channels-remove-buffer buffer))))
 	    erc-modified-channels-alist)
       (when removed-channel
-	(erc-modified-channels-display)))
-    (remove-hook 'post-command-hook 'erc-modified-channels-update)))
+	(erc-modified-channels-display)))))
 
 (defvar erc-track-mouse-face (if (featurep 'xemacs)
 				 'modeline-mousable
diff --git a/lisp/frame.el b/lisp/frame.el
index 56b8c54..b722e6f 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -1745,20 +1745,17 @@ frame-size-changed-p
   (let* ((frame (window-normalize-frame frame))
          (root (frame-root-window frame))
          (mini (minibuffer-window frame))
-         (mini-height-before-size-change 0)
+         (mini-old-height 0)
          (mini-height 0))
     ;; FRAME's minibuffer window counts iff it's on FRAME and FRAME is
     ;; not a minibuffer-only frame.
     (when (and (eq (window-frame mini) frame) (not (eq mini root)))
-      (setq mini-height-before-size-change
-            (window-pixel-height-before-size-change mini))
+      (setq mini-old-height (window-old-pixel-height mini))
       (setq mini-height (window-pixel-height mini)))
     ;; Return non-nil when either the width of the root or the sum of
     ;; the heights of root and minibuffer window changed.
-    (or (/= (window-pixel-width-before-size-change root)
-            (window-pixel-width root))
-        (/= (+ (window-pixel-height-before-size-change root)
-               mini-height-before-size-change)
+    (or (/= (window-old-pixel-width root) (window-pixel-width root))
+        (/= (+ (window-old-pixel-height root) mini-old-height)
             (+ (window-pixel-height root) mini-height)))))
 \f
 ;;;; Frame/display capabilities.
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index 0c72e47..33c4f3b 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -2064,9 +2064,7 @@ rcirc-visible-buffers
 (defvar rcirc-visible-buffers nil)
 (defun rcirc-window-configuration-change ()
   (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 'rcirc-window-configuration-change-1)))
+    (rcirc-window-configuration-change-1)))
 
 (defun rcirc-window-configuration-change-1 ()
   ;; clear activity and overlay arrows
@@ -2090,9 +2088,7 @@ rcirc-window-configuration-change-1
 			    rcirc-activity)))
     ;; update the mode-line string
     (unless (equal old-activity rcirc-activity)
-      (rcirc-update-activity-string)))
-
-  (remove-hook 'post-command-hook 'rcirc-window-configuration-change-1))
+      (rcirc-update-activity-string))))
 
 \f
 ;;; buffer name abbreviation
diff --git a/lisp/window.el b/lisp/window.el
index f1e5664..eb3e468 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -2041,6 +2041,8 @@ window-resizable-p
 ;; Aliases of functions defined in window.c.
 (defalias 'window-height 'window-total-height)
 (defalias 'window-width 'window-body-width)
+(defalias 'window-pixel-width-before-size-change 'window-old-pixel-width)
+(defalias 'window-pixel-height-before-size-change 'window-old-pixel-height)
 
 (defun window-full-height-p (&optional window)
   "Return t if WINDOW is as high as its containing frame.
@@ -2757,8 +2759,7 @@ window--resize-mini-window
 	;; The following routine catches the case where we want to resize
 	;; a minibuffer-only frame.
 	(when (resize-mini-window-internal window)
-	  (window--pixel-to-total frame)
-	  (run-window-configuration-change-hook frame))))))
+	  (window--pixel-to-total frame))))))
 
 (defun window--resize-apply-p (frame &optional horizontal)
   "Return t when a window on FRAME shall be resized vertically.
@@ -2856,9 +2857,7 @@ window-resize
 	(window--resize-siblings window delta horizontal ignore))
       (when (window--resize-apply-p frame horizontal)
 	(if (window-resize-apply frame horizontal)
-	    (progn
-	      (window--pixel-to-total frame horizontal)
-	      (run-window-configuration-change-hook frame))
+	    (window--pixel-to-total frame horizontal)
 	  (error "Failed to apply resizing %s" window))))
      (t
       (error "Cannot resize window %s" window)))))
@@ -3577,9 +3576,7 @@ adjust-window-trailing-edge
 	;; Don't report an error in the standard case.
 	(when (window--resize-apply-p frame horizontal)
 	  (if (window-resize-apply frame horizontal)
-	      (progn
-		(window--pixel-to-total frame horizontal)
-		(run-window-configuration-change-hook frame))
+	      (window--pixel-to-total frame horizontal)
 	    ;; But do report an error if applying the changes fails.
 	    (error "Failed adjusting window %s" window))))))))
 
@@ -4110,7 +4107,6 @@ delete-window
 	  ;; `delete-window-internal' has selected a window that should
 	  ;; not be selected, fix this here.
 	  (other-window -1 frame))
-	(run-window-configuration-change-hook frame)
 	(window--check frame)
 	;; Always return nil.
 	nil))))
@@ -4196,7 +4192,6 @@ delete-other-windows
       ;; If WINDOW is the main window of its frame do nothing.
       (unless (eq window main)
 	(delete-other-windows-internal window main)
-	(run-window-configuration-change-hook frame)
 	(window--check frame))
       ;; Always return nil.
       nil)))
@@ -5184,7 +5179,6 @@ split-window
 	  (unless size
             (window--sanitize-window-sizes horizontal))
 
-	  (run-window-configuration-change-hook frame)
 	  (run-window-scroll-functions new)
 	  (window--check frame)
 	  ;; Always return the new window.
@@ -5415,15 +5409,13 @@ balance-windows
     (balance-windows-1 window)
     (when (window--resize-apply-p frame)
       (window-resize-apply frame)
-      (window--pixel-to-total frame)
-      (run-window-configuration-change-hook frame))
+      (window--pixel-to-total frame))
     ;; Balance horizontally.
     (window--resize-reset (window-frame window) t)
     (balance-windows-1 window t)
     (when (window--resize-apply-p frame t)
       (window-resize-apply frame t)
-      (window--pixel-to-total frame t)
-      (run-window-configuration-change-hook frame))))
+      (window--pixel-to-total frame t))))
 
 (defun window-fixed-size-p (&optional window direction)
   "Return t if WINDOW cannot be resized in DIRECTION.
@@ -9411,15 +9403,7 @@ window--adjust-process-windows
               (when size
                 (set-process-window-size process (cdr size) (car size))))))))))
 
-;; Remove the following call in Emacs 27, running
-;; 'window-size-change-functions' should suffice.
 (add-hook 'window-configuration-change-hook 'window--adjust-process-windows)
-
-;; Catch any size changes not handled by
-;; 'window-configuration-change-hook' (Bug#32720, "another issue" in
-;; Bug#33230).
-(add-hook 'window-size-change-functions (lambda (_frame)
-                                          (window--adjust-process-windows)))
 \f
 ;; Some of these are in tutorial--default-keys, so update that if you
 ;; change these.
diff --git a/src/frame.c b/src/frame.c
index 4371ef7..985e2a8 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -55,9 +55,11 @@
 #endif
 
 /* The currently selected frame.  */
-
 Lisp_Object selected_frame;
 
+/* The selected frame the last time window change functions were run.  */
+Lisp_Object old_selected_frame;
+
 /* A frame which is not just a mini-buffer, or NULL if there are no such
    frames.  This is usually the most recent such frame that was selected.  */
 
@@ -855,7 +857,8 @@ struct frame *
   f->ns_transparent_titlebar = false;
 #endif
 #endif
-
+  /* This one should never be zero.  */
+  f->change_stamp = 1;
   root_window = make_window ();
   rw = XWINDOW (root_window);
   if (mini_p)
@@ -1451,7 +1454,8 @@ of them (the selected terminal frame) is actually displayed.
   return do_switch_frame (frame, 1, 0, norecord);
 }
 
-DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
+DEFUN ("handle-switch-frame", Fhandle_switch_frame,
+       Shandle_switch_frame, 1, 1, "^e",
        doc: /* Handle a switch-frame event EVENT.
 Switch-frame events are usually bound to this function.
 A switch-frame event is an event Emacs sends itself to
@@ -1471,6 +1475,18 @@ of them (the selected terminal frame) is actually displayed.
 {
   return selected_frame;
 }
+
+DEFUN ("old-selected-frame", Fold_selected_frame,
+       Sold_selected_frame, 0, 0, 0,
+       doc: /* Return the old selected FRAME.
+FRAME must be a live frame and defaults to the selected one.
+
+The return value is the frame selected the last time window change
+functions were run.  */)
+  (void)
+{
+  return old_selected_frame;
+}
 \f
 DEFUN ("frame-list", Fframe_list, Sframe_list,
        0, 0, 0,
@@ -6098,9 +6114,10 @@ This variable is effective only with the X toolkit (and there only when
   defsubr (&Swindow_system);
   defsubr (&Sframe_windows_min_size);
   defsubr (&Smake_terminal_frame);
-  defsubr (&Shandle_switch_frame);
   defsubr (&Sselect_frame);
+  defsubr (&Shandle_switch_frame);
   defsubr (&Sselected_frame);
+  defsubr (&Sold_selected_frame);
   defsubr (&Sframe_list);
   defsubr (&Sframe_parent);
   defsubr (&Sframe_ancestor_p);
diff --git a/src/frame.h b/src/frame.h
index ad7376a..707be77 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -125,6 +125,10 @@ struct frame
      The selected window of the selected frame is Emacs's selected window.  */
   Lisp_Object selected_window;
 
+  /* This frame's selected window when run_window_change_functions was
+     called the last time on this frame.  */
+  Lisp_Object old_selected_window;
+
   /* This frame's minibuffer window.
      Most frames have their own minibuffer windows,
      but only the selected frame's minibuffer window
@@ -321,9 +325,14 @@ struct frame
      cleared.  */
   bool_bf explicit_name : 1;
 
-  /* True if configuration of windows on this frame has changed since
-     last call of run_window_size_change_functions.  */
-  bool_bf window_configuration_changed : 1;
+  /* True if at least one window on this frame changed since the last
+     call of run_window_change_functions.  Changes are either "state
+     changes" (a window has been created, deleted or got assigned
+     another buffer) or "size changes" (the total or body size of a
+     window changed).  run_window_change_functions exits early unless
+     either this flag is true or a window selection happened on this
+     frame.  */
+  bool_bf window_change : 1;
 
   /* True if the mouse has moved on this display device
      since the last time we checked.  */
@@ -406,6 +415,20 @@ struct frame
 
   /* Bitfield area ends here.  */
 
+  /* This frame's change stamp, set the last time window change
+     functions were run for this frame.  Should never be 0 because
+     that's the change stamp of a new window.  A window was not on a
+     frame the last run_window_change_functions was called on it if
+     it's change stamp differs from that of its frame.  */
+  int change_stamp;
+
+  /* This frame's number of windows, set the last time window change
+     functions were run for this frame.  Should never be 0 even for
+     minibuffer-only frames.  If no window has been added, this allows
+     to detect whether a window was deleted on this frame since the
+     last time run_window_change_functions was called on it.  */
+  ptrdiff_t number_of_windows;
+
   /* Number of lines (rounded up) of tool bar.  REMOVE THIS  */
   int tool_bar_lines;
 
@@ -662,6 +685,11 @@ struct frame
   f->selected_window = val;
 }
 INLINE void
+fset_old_selected_window (struct frame *f, Lisp_Object val)
+{
+  f->old_selected_window = val;
+}
+INLINE void
 fset_title (struct frame *f, Lisp_Object val)
 {
   f->title = val;
@@ -908,10 +936,9 @@ struct frame
    are frozen on frame F.  */
 #define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts
 
-/* True if the frame's window configuration has changed since last call
-   of run_window_size_change_functions.  */
-#define FRAME_WINDOW_CONFIGURATION_CHANGED(f)	\
-  (f)->window_configuration_changed
+/* True if at least one window changed on frame F since the last time
+   window change functions were run on F.  */
+#define FRAME_WINDOW_CHANGE(f) (f)->window_change
 
 /* The minibuffer window of frame F, if it has one; otherwise nil.  */
 #define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window
@@ -919,8 +946,10 @@ struct frame
 /* The root window of the window tree of frame F.  */
 #define FRAME_ROOT_WINDOW(f) f->root_window
 
-/* The currently selected window of the window tree of frame F.  */
+/* The currently selected window of frame F.  */
 #define FRAME_SELECTED_WINDOW(f) f->selected_window
+/* The old selected window of frame F.  */
+#define FRAME_OLD_SELECTED_WINDOW(f) f->old_selected_window
 
 #define FRAME_INSERT_COST(f) (f)->insert_line_cost
 #define FRAME_DELETE_COST(f) (f)->delete_line_cost
@@ -1215,6 +1244,7 @@ struct frame
   (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i))
 
 extern Lisp_Object selected_frame;
+extern Lisp_Object old_selected_frame;
 
 #if ! (defined USE_GTK || defined HAVE_NS)
 extern int frame_default_tool_bar_height;
diff --git a/src/window.c b/src/window.c
index a69b115..2ae58e9 100644
--- a/src/window.c
+++ b/src/window.c
@@ -77,6 +77,11 @@ static struct window *set_window_scroll_bars (struct window *, Lisp_Object,
    FRAME_SELECTED_WINDOW (selected_frame).  */
 Lisp_Object selected_window;
 
+/* The value of selected_window at the last time window change
+   functions were run.  This is always the same as
+   FRAME_OLD_SELECTED_WINDOW (old_selected_frame).  */
+Lisp_Object old_selected_window;
+
 /* A list of all windows for use by next_window and Fwindow_list.
    Functions creating or deleting windows should invalidate this cache
    by setting it to nil.  */
@@ -304,6 +309,12 @@ struct window *
   adjust_window_count (w, 1);
 }
 
+static void
+wset_old_buffer (struct window *w, Lisp_Object val)
+{
+  w->old_buffer = val;
+}
+
 DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
        doc: /* Return t if OBJECT is a window and nil otherwise.  */)
   (Lisp_Object object)
@@ -428,6 +439,22 @@ struct window *
   return window;
 }
 
+DEFUN ("frame-old-selected-window", Fframe_old_selected_window,
+       Sframe_old_selected_window, 0, 1, 0,
+       doc: /* Return old selected window of FRAME.
+FRAME must be a live frame and defaults to the selected one.
+
+The return value is the window selected on FRAME the last time window
+change functions were run for FRAME.  */)
+  (Lisp_Object frame)
+{
+  if (NILP (frame))
+    frame = selected_frame;
+  CHECK_LIVE_FRAME (frame);
+
+  return XFRAME (frame)->old_selected_window;
+}
+
 DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
        Sset_frame_selected_window, 2, 3, 0,
        doc: /* Set selected window of FRAME to WINDOW.
@@ -465,6 +492,16 @@ struct window *
   return selected_window;
 }
 
+DEFUN ("old-selected-window", Fold_selected_window,
+       Sold_selected_window, 0, 0, 0,
+       doc: /* Return the old selected window.
+The return value is the window selected the last time window change
+functions were run.  */)
+  (void)
+{
+  return old_selected_window;
+}
+
 EMACS_INT window_select_count;
 
 /* If select_window is called with inhibit_point_swap true it will
@@ -597,9 +634,33 @@ struct window *
   (Lisp_Object window)
 {
   struct window *w = decode_any_window (window);
+
   return WINDOW_LEAF_P (w) ? w->contents : Qnil;
 }
 
+DEFUN ("window-old-buffer", Fwindow_old_buffer, Swindow_old_buffer, 0, 1, 0,
+       doc: /* Return the old buffer displayed by WINDOW.
+WINDOW must be a live window and defaults to the selected one.
+
+The return value is the buffer shown in WINDOW at the last time window
+change functions were run.  It is nil if WINDOW was created after
+that.  It is t if WINDOW has been restored from a window configuration
+after that.  */)
+  (Lisp_Object window)
+{
+  struct window *w = decode_live_window (window);
+
+  return (NILP (w->old_buffer)
+	  /* A new window.  */
+	  ? Qnil
+	  : (w->change_stamp != WINDOW_XFRAME (w)->change_stamp)
+	  /* A window restored from a configuration.  */
+	  ? Qt
+	  /* A window that was live the last time seen by window
+	     change functions.  */
+	  : w->old_buffer);
+}
+
 DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
        doc: /* Return the parent window of window WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
@@ -723,34 +784,32 @@ WINDOW are never (re-)combined with WINDOW's siblings.  */)
   return make_fixnum (decode_valid_window (window)->pixel_height);
 }
 
-DEFUN ("window-pixel-width-before-size-change",
-       Fwindow_pixel_width_before_size_change,
-       Swindow_pixel_width_before_size_change, 0, 1, 0,
-       doc: /* Return pixel width of window WINDOW before last size changes.
+DEFUN ("window-old-pixel-width", Fwindow_old_pixel_width,
+       Swindow_old_pixel_width, 0, 1, 0,
+       doc: /* Return old total pixel width of WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
 
-The return value is the pixel width of WINDOW at the last time
-`window-size-change-functions' was run.  It's zero if WINDOW was made
-after that.  */)
+The return value is the total pixel width of WINDOW after the last
+time window change functions found WINDOW live on its frame.  It is
+zero if WINDOW was created after that.  */)
   (Lisp_Object window)
 {
   return (make_fixnum
-	  (decode_valid_window (window)->pixel_width_before_size_change));
+	  (decode_valid_window (window)->old_pixel_width));
 }
 
-DEFUN ("window-pixel-height-before-size-change",
-       Fwindow_pixel_height_before_size_change,
-       Swindow_pixel_height_before_size_change, 0, 1, 0,
-       doc: /* Return pixel height of window WINDOW before last size changes.
+DEFUN ("window-old-pixel-height", Fwindow_old_pixel_height,
+       Swindow_old_pixel_height, 0, 1, 0,
+       doc: /* Return old total pixel height of WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
 
-The return value is the pixel height of WINDOW at the last time
-`window-size-change-functions' was run.  It's zero if WINDOW was made
-after that.  */)
+The return value is the total pixel height of WINDOW after the last
+time window change functions found WINDOW live on its frame.  It is
+zero if WINDOW was created after that.  */)
   (Lisp_Object window)
 {
   return (make_fixnum
-	  (decode_valid_window (window)->pixel_height_before_size_change));
+	  (decode_valid_window (window)->old_pixel_height));
 }
 
 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
@@ -984,6 +1043,26 @@ horizontally combined (a window that has a left or right sibling) is
 	      0);
 }
 
+DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
+       doc: /* Return the width of WINDOW's text area.
+WINDOW must be a live window and defaults to the selected one.  Optional
+argument PIXELWISE non-nil means return the width in pixels.  The return
+value does not include any vertical dividers, fringes or marginal areas,
+or scroll bars.
+
+If PIXELWISE is nil, return the largest integer smaller than WINDOW's
+pixel width divided by the character width of WINDOW's frame.  This
+means that if a column at the right of the text area is only partially
+visible, that column is not counted.
+
+Note that the returned value includes the column reserved for the
+continuation glyph.  */)
+  (Lisp_Object window, Lisp_Object pixelwise)
+{
+  return make_fixnum (window_body_width (decode_live_window (window),
+					 !NILP (pixelwise)));
+}
+
 DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
        doc: /* Return the height of WINDOW's text area.
 WINDOW must be a live window and defaults to the selected one.  Optional
@@ -1001,24 +1080,34 @@ horizontally combined (a window that has a left or right sibling) is
 					  !NILP (pixelwise)));
 }
 
-DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
-       doc: /* Return the width of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.  Optional
-argument PIXELWISE non-nil means return the width in pixels.  The return
-value does not include any vertical dividers, fringes or marginal areas,
-or scroll bars.
+DEFUN ("window-old-body-pixel-width",
+       Fwindow_old_body_pixel_width,
+       Swindow_old_body_pixel_width, 0, 1, 0,
+       doc: /* Return old width of WINDOW's text area in pixels.
+WINDOW must be a live window and defaults to the selected one.
 
-If PIXELWISE is nil, return the largest integer smaller than WINDOW's
-pixel width divided by the character width of WINDOW's frame.  This
-means that if a column at the right of the text area is only partially
-visible, that column is not counted.
+The return value is the pixel width of WINDOW's text area after the
+last time window change functions found WINDOW live on its frame.  It
+is zero if WINDOW was created after that.  */)
+  (Lisp_Object window)
+{
+  return (make_fixnum
+	  (decode_live_window (window)->old_body_pixel_width));
+}
 
-Note that the returned value includes the column reserved for the
-continuation glyph.  */)
-  (Lisp_Object window, Lisp_Object pixelwise)
+DEFUN ("window-old-body-pixel-height",
+       Fwindow_old_body_pixel_height,
+       Swindow_old_body_pixel_height, 0, 1, 0,
+       doc: /* Return old height of WINDOW's text area in pixels.
+WINDOW must be a live window and defaults to the selected one.
+
+The return value is the pixel height of WINDOW's text area after the
+last time window change functions found WINDOW live on its frame.  It
+is zero if WINDOW was created after that.  */)
+  (Lisp_Object window)
 {
-  return make_fixnum (window_body_width (decode_live_window (window),
-					 !NILP (pixelwise)));
+  return (make_fixnum
+	  (decode_live_window (window)->old_body_pixel_height));
 }
 
 DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
@@ -3264,7 +3353,7 @@ depends on the value of (window-start WINDOW), so if calling this
   adjust_frame_glyphs (f);
   unblock_input ();
 
-  run_window_configuration_change_hook (f);
+  FRAME_WINDOW_CHANGE (f) = true;
 
   return Qnil;
 }
@@ -3318,6 +3407,15 @@ depends on the value of (window-start WINDOW), so if calling this
     Fselect_frame (frame, Qt);
 }
 
+/**
+ * run_window_configuration_change_hook:
+ *
+ * Run any functions on 'window-configuration-change-hook' for the
+ * frame specified by F.  The buffer-local values are run with the
+ * window showing the buffer selected.  The default value is run with
+ * the frame specified by F selected.  All functions are called with
+ * the selected window's buffer current.
+ */
 static void
 run_window_configuration_change_hook (struct frame *f)
 {
@@ -3371,7 +3469,10 @@ depends on the value of (window-start WINDOW), so if calling this
 DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
        Srun_window_configuration_change_hook, 0, 1, 0,
        doc: /* Run `window-configuration-change-hook' for FRAME.
-If FRAME is omitted or nil, it defaults to the selected frame.  */)
+If FRAME is omitted or nil, it defaults to the selected frame.
+
+This function should not be needed any more and will be therefore
+considered obsolete.  */)
   (Lisp_Object frame)
 {
   run_window_configuration_change_hook (decode_live_frame (frame));
@@ -3381,130 +3482,388 @@ depends on the value of (window-start WINDOW), so if calling this
 DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
        Srun_window_scroll_functions, 0, 1, 0,
        doc: /* Run `window-scroll-functions' for WINDOW.
-If WINDOW is omitted or nil, it defaults to the selected window.  */)
+If WINDOW is omitted or nil, it defaults to the selected window.
+
+This function is curently only called by 'split-window' for the new
+window after it has established the size of the new window.  */)
   (Lisp_Object window)
 {
-  if (! NILP (Vwindow_scroll_functions))
+  struct window *w = decode_live_window (window);
+  ptrdiff_t count = SPECPDL_INDEX ();
+
+  record_unwind_current_buffer ();
+  Fset_buffer (w->contents);
+  if (!NILP (Vwindow_scroll_functions))
     run_hook_with_args_2 (Qwindow_scroll_functions, window,
-			  Fmarker_position (decode_live_window (window)->start));
+			  Fmarker_position (w->start));
+  unbind_to (count, Qnil);
+
   return Qnil;
 }
 
 
-/* Compare old and present pixel sizes of windows in tree rooted at W.
-   Return true iff any of these windows differs in size.  */
-
-static bool
-window_size_changed (struct window *w)
+/**
+ * window_sub_list:
+ *
+ * Return list of live windows constructed by traversing any window
+ * sub-tree rooted at WINDOW in preorder followed by right siblings of
+ * WINDOW.  Called from outside with second argument WINDOWS nil.  The
+ * returned list is in reverse order.
+ */
+static Lisp_Object
+window_sub_list (Lisp_Object window, Lisp_Object windows)
 {
-  if (w->pixel_width != w->pixel_width_before_size_change
-      || w->pixel_height != w->pixel_height_before_size_change)
-    return true;
 
-  if (WINDOW_INTERNAL_P (w))
+  struct window *w = XWINDOW (window);
+
+  while (w)
     {
-      w = XWINDOW (w->contents);
-      while (w)
-	{
-	  if (window_size_changed (w))
-	    return true;
+      if (WINDOW_INTERNAL_P (w))
+	windows = window_sub_list (w->contents, windows);
+      else
+	windows = Fcons (window, windows);
 
-	  w = NILP (w->next) ? 0 : XWINDOW (w->next);
-	}
+      window = w->next;
+      w = NILP (window) ? 0 : XWINDOW (window);
     }
 
-  return false;
+  return windows;
 }
 
-/* Set before size change pixel sizes of windows in tree rooted at W to
-   their present pixel sizes.  */
 
-static void
-window_set_before_size_change_sizes (struct window *w)
+/**
+ * window_change_record_windows:
+ *
+ * Record changes for all live windows found by traversing any window
+ * sub-tree rooted at WINDOW in preorder followed by any right
+ * siblings of WINDOW.  This sets the old buffer, old pixel and old
+ * body pixel sizes of each live window found to the respective
+ * current values.  It also sets the change stamp of each window found
+ * to STAMP.  Return the number of live windows found.
+ *
+ * When not called by itself recursively, WINDOW is its frame's root
+ * window, STAMP is the current change stamp of WINDOW's frame and
+ * NUMBER is 0.
+ */
+static ptrdiff_t
+window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number)
 {
-  w->pixel_width_before_size_change = w->pixel_width;
-  w->pixel_height_before_size_change = w->pixel_height;
+  struct window *w = XWINDOW (window);
 
-  if (WINDOW_INTERNAL_P (w))
+  while (w)
     {
-      w = XWINDOW (w->contents);
-      while (w)
+      if (WINDOW_INTERNAL_P (w))
+	number = window_change_record_windows (w->contents, stamp, number);
+      else
 	{
-	  window_set_before_size_change_sizes (w);
-	  w = NILP (w->next) ? 0 : XWINDOW (w->next);
+	  number += 1;
+	  w->change_stamp = stamp;
+	  wset_old_buffer (w, w->contents);
+	  w->old_pixel_width = w->pixel_width;
+	  w->old_pixel_height = w->pixel_height;
+	  w->old_body_pixel_width = window_body_width (w, true);
+	  w->old_body_pixel_height = window_body_height (w, true);
 	}
+
+      w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
+
+  return number;
 }
 
 
-void
-run_window_size_change_functions (Lisp_Object frame)
+/**
+ * window_change_record_frame:
+ *
+ * Record changes for FRAME.  This records FRAME's selected window,
+ * updates FRAME's change stamp, records the states of all live
+ * windows of FRAME via window_change_record_windows and resets
+ * FRAME's window_change flag.
+ */
+static void
+window_change_record_frame (Lisp_Object frame)
 {
   struct frame *f = XFRAME (frame);
-  struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
 
-  if (NILP (Vrun_hooks)
-      || !(f->can_x_set_window_size)
-      || !(f->after_make_frame))
-    return;
+  /* Record selected window.  */
+  fset_old_selected_window (f, FRAME_SELECTED_WINDOW (f));
+
+  /* Bump up FRAME's change stamp.  If this wraps, make it 1 to avoid
+     that a new window (whose change stamp is always set to 0) gets
+     reported as "existing before".  */
+  f->change_stamp += 1;
+  if (f->change_stamp == 0)
+    f->change_stamp = 1;
+
+  /* Bump up the change stamps of all live windows on this frame so
+     the next call of this function can tell whether any of them
+     "existed before" and record state for each of these windows.  */
+  f->number_of_windows
+    = window_change_record_windows (f->root_window, f->change_stamp, 0);
+
+  /* Reset our flag.  */
+  FRAME_WINDOW_CHANGE (f) = false;
+}
+
+
+/**
+ * window_change_record:
+ *
+ * Record selected window in old_selected_window and selected frame in
+ * old_selected_frame.
+ */
+static void
+window_change_record (void)
+{
+  /* Strictly spoken we don't need old_selected_window at all - its
+     value is the old selected window of old_selected_frame.  */
+  old_selected_window = selected_window;
+  old_selected_frame = selected_frame;
+}
 
-  if (FRAME_WINDOW_CONFIGURATION_CHANGED (f)
-      /* Here we implicitly exclude the possibility that the height of
-	 FRAME and its minibuffer window both change leaving the height
-	 of FRAME's root window alone.  */
-      || window_size_changed (r))
+
+/**
+ * run_window_change_functions_1:
+ *
+ * Run window change functions specified by SYMBOL with argument
+ * WINDOW_OR_FRAME.  If BUFFER is nil, WINDOW_OR_FRAME specifies a
+ * frame.  In this case, run the default value of SYMBOL.  Otherwise,
+ * WINDOW_OR_FRAME denotes a window showing BUFFER.  In this case, run
+ * the buffer local value of SYMBOL in BUFFER, if any.
+ */
+static void
+run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer,
+			       Lisp_Object window_or_frame)
+{
+  Lisp_Object funs = Qnil;
+
+  if (NILP (buffer))
+    funs = Fdefault_value (symbol);
+  else if (Fassoc (symbol, BVAR (XBUFFER (buffer), local_var_alist), Qnil))
+    /* Don't run global value buffer-locally.  */
+    funs = buffer_local_value (symbol, buffer);
+
+  while (CONSP (funs))
     {
-      Lisp_Object globals = Fdefault_value (Qwindow_size_change_functions);
-      Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
-      /* The buffers for which the local hook was already run.  */
-      Lisp_Object buffers = Qnil;
+      if (!EQ (XCAR (funs), Qt))
+	safe_call1 (XCAR (funs), window_or_frame);
+      funs = XCDR (funs);
+    }
+}
+
 
+/**
+ * run_window_change_functions:
+ *
+ * Run window change functions for each live frame.  This function
+ * must be called from a "safe" position in redisplay_internal.
+ *
+ * Do not run any functions for a frame whose window_change flag is
+ * nil and where no window selection happened since the last time this
+ * function was called.  Also, skip any tooltip frame.
+ *
+ * The change functions run are, in this order:
+ *
+ * 'window-buffer-change-functions' which are run for a window that
+ * changed its buffer or that was not shown the last time window
+ * change functions were run.  The default value is also run when a
+ * window was deleted since the last time window change functions were
+ * run.
+ *
+ * `window-size-change-functions' run for a window that changed its
+ * body or total size, a window that changed its buffer or a window
+ * that was not shown the last time window change functions were run.
+ *
+ * `window-selected-change-functions' run for a window that was
+ * (de-)selected since the last time window change functions were run.
+ *
+ * A buffer-local value of these functions is run if and only if the
+ * window for which the functions are run, currently shows the buffer.
+ * Each call gets one argument - the window showing the buffer.  This
+ * means that the buffer-local value of these functions may be called
+ * as many times at the buffer is shown on the frame.
+ *
+ * The default value of these functions is called only after all
+ * buffer-local values for all of these functions have been run.  Each
+ * such call receives one argument - the frame for which this function
+ * is run.
+ *
+ * After the three change functions cited above have been run in the
+ * indicated way, functions on 'window-configuration-change-hook' are
+ * run.  A buffer-local value is run if a window shows that buffer and
+ * has either changed its buffer or its body or total size or did not
+ * appear on this frame since the last time window change functions
+ * were run.  The functions are called without argument and the
+ * buffer's window selected.  The default value is run without
+ * argument and the frame for which the function is run selected.
+ *
+ * This function does not save and restore match data.  Any functions
+ * it calls are responsible for doing that themselves.
+ */
+void
+run_window_change_functions (void)
+{
+  Lisp_Object tail, frame;
+  bool selected_frame_change = !EQ (selected_frame, old_selected_frame);
+  ptrdiff_t count_outer = SPECPDL_INDEX ();
+
+  record_unwind_protect_void (window_change_record);
+
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      Lisp_Object root = FRAME_ROOT_WINDOW (f);
+      bool frame_window_change = FRAME_WINDOW_CHANGE (f);
+      bool window_buffer_change, window_size_change;
+      bool frame_buffer_change = false, frame_size_change = false;
+      bool frame_selected_change
+	= (selected_frame_change
+	   && (EQ (frame, old_selected_frame)
+	       || EQ (frame, selected_frame)));
+      bool frame_selected_window_change
+	= !EQ (FRAME_OLD_SELECTED_WINDOW (f), FRAME_SELECTED_WINDOW (f));
+      bool window_deleted = false;
+      Lisp_Object windows;
+      ptrdiff_t number_of_windows;
+      ptrdiff_t count_inner = SPECPDL_INDEX ();
+
+      if (!f->can_x_set_window_size
+	  || !f->after_make_frame
+	  || FRAME_TOOLTIP_P (f)
+	  || !(frame_window_change
+	       || frame_selected_change
+	       || frame_selected_window_change))
+	/* Either we cannot run hooks for this frame yet or no window
+	   change has been reported for this frame since the last time
+	   we ran window change functions on it.  */
+	continue;
+
+      /* Analyze windows and run buffer locals hooks in pre-order.  */
+      windows = Fnreverse (window_sub_list (root, Qnil));
+      number_of_windows = 0;
+
+      record_unwind_protect (window_change_record_frame, frame);
+
+      /* The following loop collects all data needed to tell whether
+	 the default value of a hook shall be run and runs any buffer
+	 local hooks right away.  */
       for (; CONSP (windows); windows = XCDR (windows))
 	{
 	  Lisp_Object window = XCAR (windows);
-	  Lisp_Object buffer = Fwindow_buffer (window);
-
-	  /* Run a buffer-local value only once for that buffer and
-	     only if at least one window showing that buffer on FRAME
-	     actually changed its size.  Note that the function is run
-	     with FRAME as its argument and as such oblivious to the
-	     window checked below.  */
-	  if (window_size_changed (XWINDOW (window))
-	      && !NILP (Flocal_variable_p (Qwindow_size_change_functions, buffer))
-	      && NILP (Fmemq (buffer, buffers)))
-	    {
-	      Lisp_Object locals
-		= Fbuffer_local_value (Qwindow_size_change_functions, buffer);
-
-	      while (CONSP (locals))
-		{
-		  if (!EQ (XCAR (locals), Qt))
-		    safe_call1 (XCAR (locals), frame);
-		  locals = XCDR (locals);
-		}
-
-	      buffers = Fcons (buffer, buffers);
-	    }
+	  struct window *w = XWINDOW (window);
+	  Lisp_Object buffer = WINDOW_BUFFER (w);
+
+	  /* Count this window even if it has been deleted while
+	     running a hook.  */
+	  number_of_windows += 1;
+
+	  if (!WINDOW_LIVE_P (window))
+	    continue;
+
+	  /* A "buffer change" means either the window's buffer
+	     changed or the window was not part of this frame the last
+	     time window change functions were run for it.  */
+	  window_buffer_change =
+	    (frame_window_change
+	     && (!EQ (buffer, w->old_buffer)
+		 || w->change_stamp != f->change_stamp));
+	  /* A "size change" means either a buffer change or that the
+	     total or body size of the window has changed.
+
+	     Note: A buffer change implies a size change because either
+	     this window didn't show the buffer before or this window
+	     didn't show the buffer the last time the window change
+	     functions were run.  In either case, an application
+	     tracing size changes in a buffer-locally fashion might
+	     want to be informed about that change.  */
+	  window_size_change =
+	    (frame_window_change
+	     && (window_buffer_change
+		 || w->pixel_width != w->old_pixel_width
+		 || w->pixel_height != w->old_pixel_height
+		 || window_body_width (w, true) != w->old_body_pixel_width
+		 || window_body_height (w, true) != w->old_body_pixel_height));
+
+	  /* The following two are needed when running the default
+	     values for this frame below.  */
+	  frame_buffer_change = frame_buffer_change || window_buffer_change;
+	  frame_size_change = frame_size_change || window_size_change;
+
+	  if (window_buffer_change)
+	    run_window_change_functions_1
+	      (Qwindow_buffer_change_functions, buffer, window);
+
+	  if (window_size_change && WINDOW_LIVE_P (window))
+	    run_window_change_functions_1
+	      (Qwindow_size_change_functions, buffer, window);
+
+	  /* This window's selection has changed when it it was
+	     (de-)selected as its frame's or the globally selected
+	     window.  */
+	  if (((frame_selected_change
+		&& (EQ (window, old_selected_window)
+		    || EQ (window, selected_window)))
+	       || (frame_selected_window_change
+		   && (EQ (window, FRAME_OLD_SELECTED_WINDOW (f))
+		       || EQ (window, FRAME_SELECTED_WINDOW (f)))))
+	      && WINDOW_LIVE_P (window))
+	    run_window_change_functions_1
+	      (Qwindow_selection_change_functions, buffer, window);
 	}
 
-      while (CONSP (globals))
-	{
-	  if (!EQ (XCAR (globals), Qt))
-	    safe_call1 (XCAR (globals), frame);
-	  globals = XCDR (globals);
-	}
+      /* When the number of windows on a frame has decreased, at least
+	 one window of that frame was deleted.  In that case, we want
+	 to run the default buffer and configuration change hooks.  The
+	 default size change hook is not necessarily run in that case,
+	 but usually will be unless the deletion was "compensated" by
+	 a reduction of the frame size or an increase of a minibuffer
+	 window size.  */
+      window_deleted = number_of_windows < f->number_of_windows;
+      /* A frame changed buffers when one of its windows has changed
+	 its buffer or at least one window was deleted.  */
+      if ((frame_buffer_change || window_deleted) && FRAME_LIVE_P (f))
+	run_window_change_functions_1
+	  (Qwindow_buffer_change_functions, Qnil, frame);
+
+      /* A size change occurred when at least one of the frame's
+	 windows has changed size.  */
+      if (frame_size_change && FRAME_LIVE_P (f))
+	run_window_change_functions_1
+	  (Qwindow_size_change_functions, Qnil, frame);
+
+      /* A frame has changed its window selection when its selected
+	 window has changed or when it was (de-)selected.  */
+      if ((frame_selected_change || frame_selected_window_change)
+	  && FRAME_LIVE_P (f))
+	run_window_change_functions_1
+	  (Qwindow_selection_change_functions, Qnil, frame);
+
+      /* A frame's configuration changed when one of its windows has
+	 changed buffer or size or at least one window was deleted.  */
+      if ((frame_size_change || window_deleted) && FRAME_LIVE_P (f))
+	/* This will run any buffer local window configuration change
+	   hook as well.  */
+	run_window_configuration_change_hook (f);
 
-      window_set_before_size_change_sizes (r);
+      if (!FRAME_LIVE_P (f))
+	continue;
 
-      if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
-	/* Record size of FRAME's minibuffer window too.  */
-	window_set_before_size_change_sizes
-	  (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
+      /* Internal bookkeeping.  */
+      if (frame_window_change)
+	Vwindow_changes =
+	  Fcons (make_fixnum (XFIXNUM (Fcar (Vwindow_changes)) + 1),
+		 make_fixnum (XFIXNUM (Fcdr (Vwindow_changes))
+			      + ((frame_buffer_change || frame_size_change)
+				 ? 1 : 0)));
 
-      FRAME_WINDOW_CONFIGURATION_CHANGED (f) = false;
+      /* Record changes (via window_change_record_frame) for this
+	 frame, even when an unhandled error occurred.  */
+      unbind_to (count_inner, Qnil);
     }
-}
 
+  /* Record selected window and frame.  */
+  unbind_to (count_outer, Qnil);
+}
 
 /* Make WINDOW display BUFFER.  RUN_HOOKS_P means it's allowed
    to run hooks.  See make_frame for a case where it's not allowed.
@@ -3581,14 +3940,18 @@ depends on the value of (window-start WINDOW), so if calling this
       apply_window_adjustment (w);
     }
 
-  if (run_hooks_p)
-    {
-      if (!NILP (Vwindow_scroll_functions))
-	run_hook_with_args_2 (Qwindow_scroll_functions, window,
-			      Fmarker_position (w->start));
-      if (!samebuf)
-	run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
-    }
+  if (run_hooks_p && !NILP (Vwindow_scroll_functions))
+    run_hook_with_args_2 (Qwindow_scroll_functions, window,
+			  Fmarker_position (w->start));
+
+  /* Ensure that window change functions are run later if the buffer
+     differs and the window is neither a mini nor a pseudo window.
+
+     Note: Running window change functions for the minibuffer is noisy
+     and was generally suppressed in the past.  Is there any reason we
+     should run them?  */
+  if (!samebuf && !MINI_WINDOW_P (w) && !WINDOW_PSEUDO_P (w))
+    FRAME_WINDOW_CHANGE (XFRAME (w->frame)) = true;
 
   unbind_to (count, Qnil);
 }
@@ -3828,8 +4191,6 @@ depends on the value of (window-start WINDOW), so if calling this
   w->phys_cursor_width = -1;
 #endif
   w->sequence_number = ++sequence_number;
-  w->pixel_width_before_size_change = 0;
-  w->pixel_height_before_size_change = 0;
   w->scroll_bar_width = -1;
   w->scroll_bar_height = -1;
   w->column_number_displayed = -1;
@@ -4095,6 +4456,9 @@ depends on the value of (window-start WINDOW), so if calling this
   else
     /* Bug#15957.  */
     w->window_end_valid = false;
+
+  if (!WINDOW_PSEUDO_P (w))
+    FRAME_WINDOW_CHANGE (WINDOW_XFRAME (w)) = true;
 }
 
 
@@ -4559,17 +4923,11 @@ SIDE t (or `right') specifies that the new window shall be located on
   block_input ();
   window_resize_apply (p, horflag);
   adjust_frame_glyphs (f);
-  /* Set buffer of NEW to buffer of reference window.  Don't run
-     any hooks.  */
-  set_window_buffer (new, r->contents, false, true);
+  /* Set buffer of NEW to buffer of reference window.  */
+  set_window_buffer (new, r->contents, true, true);
+  FRAME_WINDOW_CHANGE (f) = true;
   unblock_input ();
 
-  /* Maybe we should run the scroll functions in Elisp (which already
-     runs the configuration change hook).  */
-  if (! NILP (Vwindow_scroll_functions))
-    run_hook_with_args_2 (Qwindow_scroll_functions, new,
-			  Fmarker_position (n->start));
-  /* Return NEW.  */
   return new;
 }
 
@@ -4720,6 +5078,8 @@ SIDE t (or `right') specifies that the new window shall be located on
 	}
       else
 	unblock_input ();
+
+      FRAME_WINDOW_CHANGE (f) = true;
     }
   else
     /* We failed: Relink WINDOW into window tree.  */
@@ -6310,7 +6670,6 @@ struct saved_window
 
   Lisp_Object window, buffer, start, pointm, old_pointm;
   Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
-  Lisp_Object pixel_height_before_size_change, pixel_width_before_size_change;
   Lisp_Object left_col, top_line, total_cols, total_lines;
   Lisp_Object normal_cols, normal_lines;
   Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
@@ -6426,12 +6785,6 @@ struct saved_window
       struct window *root_window;
       struct window **leaf_windows;
       ptrdiff_t i, k, n_leaf_windows;
-      /* Records whether a window has been added or removed wrt the
-	 original configuration.  */
-      bool window_changed = false;
-      /* Records whether a window has changed its buffer wrt the
-	 original configuration.  */
-      bool buffer_changed = false;
 
       /* Don't do this within the main loop below: This may call Lisp
 	 code and is thus potentially unsafe while input is blocked.  */
@@ -6441,11 +6794,6 @@ struct saved_window
 	  window = p->window;
 	  w = XWINDOW (window);
 
-	  if (NILP (w->contents))
-	    /* A dead window that will be resurrected, the window
-	       configuration will change.  */
-	    window_changed = true;
-
 	  if (BUFFERP (w->contents)
 	      && !EQ (w->contents, p->buffer)
 	      && BUFFER_LIVE_P (XBUFFER (p->buffer)))
@@ -6530,10 +6878,6 @@ struct saved_window
 	  w->pixel_top = XFIXNAT (p->pixel_top);
 	  w->pixel_width = XFIXNAT (p->pixel_width);
 	  w->pixel_height = XFIXNAT (p->pixel_height);
-	  w->pixel_width_before_size_change
-	    = XFIXNAT (p->pixel_width_before_size_change);
-	  w->pixel_height_before_size_change
-	    = XFIXNAT (p->pixel_height_before_size_change);
 	  w->left_col = XFIXNAT (p->left_col);
 	  w->top_line = XFIXNAT (p->top_line);
 	  w->total_cols = XFIXNAT (p->total_cols);
@@ -6581,9 +6925,6 @@ struct saved_window
 	  if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
 	    /* If saved buffer is alive, install it.  */
 	    {
-	      if (!EQ (w->contents, p->buffer))
-		/* Record buffer configuration change.  */
-		buffer_changed = true;
 	      wset_buffer (w, p->buffer);
 	      w->start_at_line_beg = !NILP (p->start_at_line_beg);
 	      set_marker_restricted (w->start, p->start, w->contents);
@@ -6617,8 +6958,6 @@ struct saved_window
 	  else if (!NILP (w->start))
 	    /* Leaf window has no live buffer, get one.  */
 	    {
-	      /* Record buffer configuration change.  */
-	      buffer_changed = true;
 	      /* Get the buffer via other_buffer_safely in order to
 		 avoid showing an unimportant buffer and, if necessary, to
 		 recreate *scratch* in the course (part of Juanma's bs-show
@@ -6666,10 +7005,7 @@ struct saved_window
       /* Now, free glyph matrices in windows that were not reused.  */
       for (i = 0; i < n_leaf_windows; i++)
 	if (NILP (leaf_windows[i]->contents))
-	  {
-	    free_window_matrices (leaf_windows[i]);
-	    window_changed = true;
-	  }
+	  free_window_matrices (leaf_windows[i]);
 
       /* Allow x_set_window_size again and apply frame size changes if
 	 needed.  */
@@ -6699,35 +7035,10 @@ struct saved_window
 	 selected window.  */
       if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
 	do_switch_frame (data->selected_frame, 0, 0, Qnil);
-
-      if (window_changed)
-	/* At least one window has been added or removed.  Run
-	   `window-configuration-change-hook' and make sure
-	   `window-size-change-functions' get run later.
-
-	   We have to do this in order to capture the following
-	   scenario: Suppose our frame contains two live windows W1 and
-	   W2 and 'set-window-configuration' replaces them by two
-	   windows W3 and W4 that were dead the last time
-	   run_window_size_change_functions was run.  If W3 and W4 have
-	   the same values for their old and new pixel sizes but these
-	   values differ from those of W1 and W2, the sizes of our
-	   frame's two live windows changed but window_size_changed has
-	   no means to detect that fact.
-
-	   Obviously, this will get us false positives, for example,
-	   when we restore the original configuration with W1 and W2
-	   before run_window_size_change_functions gets called.  */
-	{
-	  run_window_configuration_change_hook (f);
-	  FRAME_WINDOW_CONFIGURATION_CHANGED (f) = true;
-	}
-      else if (buffer_changed)
-	/* At least one window has changed its buffer.  Run
-	   `window-configuration-change-hook' only.  */
-	run_window_configuration_change_hook (f);
     }
 
+  FRAME_WINDOW_CHANGE (f) = true;
+
   if (!NILP (new_current_buffer))
     {
       Fset_buffer (new_current_buffer);
@@ -6889,10 +7200,6 @@ struct glyph *
       p->pixel_top = make_fixnum (w->pixel_top);
       p->pixel_width = make_fixnum (w->pixel_width);
       p->pixel_height = make_fixnum (w->pixel_height);
-      p->pixel_width_before_size_change
-	= make_fixnum (w->pixel_width_before_size_change);
-      p->pixel_height_before_size_change
-	= make_fixnum (w->pixel_height_before_size_change);
       p->left_col = make_fixnum (w->left_col);
       p->top_line = make_fixnum (w->top_line);
       p->total_cols = make_fixnum (w->total_cols);
@@ -7583,9 +7890,9 @@ Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
 {
   struct frame *f = make_initial_frame ();
   XSETFRAME (selected_frame, f);
-  Vterminal_frame = selected_frame;
+  old_selected_frame = Vterminal_frame = selected_frame;
   minibuf_window = f->minibuffer_window;
-  selected_window = f->selected_window;
+  old_selected_window = selected_window = f->selected_window;
 }
 
 void
@@ -7606,6 +7913,8 @@ Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
 
   DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
   DEFSYM (Qwindow_size_change_functions, "window-size-change-functions");
+  DEFSYM (Qwindow_buffer_change_functions, "window-buffer-change-functions");
+  DEFSYM (Qwindow_selection_change_functions, "window-selection-change-functions");
   DEFSYM (Qwindowp, "windowp");
   DEFSYM (Qwindow_configuration_p, "window-configuration-p");
   DEFSYM (Qwindow_live_p, "window-live-p");
@@ -7690,24 +7999,66 @@ Value is a list of the form (WIDTH COLUMNS VERTICAL-TYPE HEIGHT LINES
   Vwindow_point_insertion_type = Qnil;
   DEFSYM (Qwindow_point_insertion_type, "window_point_insertion_type");
 
-  DEFVAR_LISP ("window-configuration-change-hook",
-	       Vwindow_configuration_change_hook,
-	       doc: /* Functions to call when window configuration changes.
-The buffer-local value is run once per window, with the relevant window
-selected; while the global value is run only once for the modified frame,
-with the relevant frame selected.  */);
-  Vwindow_configuration_change_hook = Qnil;
+  DEFVAR_LISP ("window-buffer-change-functions", Vwindow_buffer_change_functions,
+	       doc: /* Functions called during redisplay when window buffers have changed.
+The value should be a list of functions that take one argument.
+
+Functions specified buffer-locally are called for each window showing
+the corresponding buffer if and only if that window has been added or
+changed its buffer since the last redisplay.  In this case the window
+is passed as argument.
+
+Functions specified by the default value are called for each frame if
+at least one window on that frame has been added, deleted or changed
+its buffer since the last redisplay.  In this case the frame is passed
+as argument.  */);
+  Vwindow_buffer_change_functions = Qnil;
 
   DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
-    doc: /* Functions called during redisplay, if window sizes have changed.
+	       doc: /* Functions called during redisplay when window sizes have changed.
 The value should be a list of functions that take one argument.
-During the first part of redisplay, for each frame, if any of its windows
-have changed size since the last redisplay, or have been split or deleted,
-all the functions in the list are called, with the frame as argument.
-If redisplay decides to resize the minibuffer window, it calls these
-functions on behalf of that as well.  */);
+
+Functions specified buffer-locally are called for each window showing
+the corresponding buffer if and only if that window has been added or
+changed its buffer or its total or body size since the last redisplay.
+In this case the window is passed as argument.
+
+Functions specified by the default value are called for each frame if
+at least one window on that frame has been added or changed its buffer
+or its total or body size since the last redisplay.  In this case the
+frame is passed as argument.  */);
   Vwindow_size_change_functions = Qnil;
 
+  DEFVAR_LISP ("window-selection-change-functions", Vwindow_selection_change_functions,
+	       doc: /* Functions called during redisplay when the selected window has changed.
+The value should be a list of functions that take one argument.
+
+Functions specified buffer-locally are called for each window showing
+the corresponding buffer if and only if that window has been selected
+or deselected since the last redisplay.  In this case the window is
+passed as argument.
+
+Functions specified by the default value are called for each frame if
+the frame's selected window has changed since the last redisplay.  In
+this case the frame is passed as argument.  */);
+  Vwindow_selection_change_functions = Qnil;
+
+  DEFVAR_LISP ("window-configuration-change-hook", Vwindow_configuration_change_hook,
+	       doc: /* Functions called during redisplay when window configuration has changed.
+The value should be a list of functions that take no argument.
+
+Functions specified buffer-locally are called for each window showing
+the corresponding buffer if at least one window on that frame has been
+added, deleted or changed its buffer or its total or body size since
+the last redisplay.  Each call is performed with the window showing
+the buffer temporarily selected.
+
+Functions specified by the default value are called for each frame if
+at least one window on that frame has been added, deleted or changed
+its buffer or its total or body size since the last redisplay.  Each
+call is performed with the frame temporarily selected.  */);
+  Vwindow_configuration_change_hook = Qnil;
+
   DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
 	       doc: /* Non-nil means `recenter' redraws entire frame.
 If this option is non-nil, then the `recenter' command with a nil
@@ -7818,7 +8169,13 @@ this value for parameters without read syntax (like windows or frames).
 displayed after a scrolling operation to be somewhat inaccurate.  */);
   Vfast_but_imprecise_scrolling = false;
 
+  DEFVAR_LISP ("window-changes",
+	       Vwindow_changes,
+	       doc: /* Cons.  */);
+  Vwindow_changes = Fcons (make_fixnum (0), make_fixnum (0));
+
   defsubr (&Sselected_window);
+  defsubr (&Sold_selected_window);
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);
   defsubr (&Swindowp);
@@ -7828,10 +8185,12 @@ this value for parameters without read syntax (like windows or frames).
   defsubr (&Sframe_root_window);
   defsubr (&Sframe_first_window);
   defsubr (&Sframe_selected_window);
+  defsubr (&Sframe_old_selected_window);
   defsubr (&Sset_frame_selected_window);
   defsubr (&Spos_visible_in_window_p);
   defsubr (&Swindow_line_height);
   defsubr (&Swindow_buffer);
+  defsubr (&Swindow_old_buffer);
   defsubr (&Swindow_parent);
   defsubr (&Swindow_top_child);
   defsubr (&Swindow_left_child);
@@ -7842,8 +8201,10 @@ this value for parameters without read syntax (like windows or frames).
   defsubr (&Swindow_use_time);
   defsubr (&Swindow_pixel_width);
   defsubr (&Swindow_pixel_height);
-  defsubr (&Swindow_pixel_width_before_size_change);
-  defsubr (&Swindow_pixel_height_before_size_change);
+  defsubr (&Swindow_old_pixel_width);
+  defsubr (&Swindow_old_pixel_height);
+  defsubr (&Swindow_old_body_pixel_width);
+  defsubr (&Swindow_old_body_pixel_height);
   defsubr (&Swindow_total_width);
   defsubr (&Swindow_total_height);
   defsubr (&Swindow_normal_size);
diff --git a/src/window.h b/src/window.h
index 4bb6293..a71a8e8 100644
--- a/src/window.h
+++ b/src/window.h
@@ -142,6 +142,11 @@ struct window
        as well.  */
     Lisp_Object contents;
 
+    /* The old buffer of this window, set to this window's buffer by
+       run_window_change_functions every time it sees this window.
+       Unused for internal windows.  */
+    Lisp_Object old_buffer;
+
     /* A marker pointing to where in the text to start displaying.
        BIDI Note: This is the _logical-order_ start, i.e. the smallest
        buffer position visible in the window, not necessarily the
@@ -229,6 +234,14 @@ struct window
     /* Unique number of window assigned when it was created.  */
     EMACS_INT sequence_number;
 
+    /* The change stamp of this window.  Set to 0 when the window is
+       created, it is set to its frame's change stamp every time
+       run_window_change_functions is run on that frame with this
+       window live.  It is left alone when the window exists only
+       within a window configuration.  Not useful for internal
+       windows.  */
+    int change_stamp;
+
     /* The upper left corner pixel coordinates of this window, as
        integers relative to upper left corner of frame = 0, 0.  */
     int pixel_left;
@@ -243,10 +256,13 @@ struct window
     int pixel_width;
     int pixel_height;
 
-    /* The pixel sizes of the window at the last time
-       `window-size-change-functions' was run.  */
-    int pixel_width_before_size_change;
-    int pixel_height_before_size_change;
+    /* The pixel and pixel body sizes of the window at the last time
+       run_window_change_functions was run with this window live.  Not
+       useful for internal windows.  */
+    int old_pixel_width;
+    int old_pixel_height;
+    int old_body_pixel_width;
+    int old_body_pixel_height;
 
     /* The size of the window.  */
     int total_cols;
@@ -1023,6 +1039,7 @@ struct window
    This value is always the same as FRAME_SELECTED_WINDOW (selected_frame).  */
 
 extern Lisp_Object selected_window;
+extern Lisp_Object old_selected_window;
 
 /* This is a time stamp for window selection, so we can find the least
    recently used window.  Its only users are Fselect_window,
@@ -1051,7 +1068,7 @@ extern Lisp_Object window_from_coordinates (struct frame *, int, int,
 extern void shrink_mini_window (struct window *, bool);
 extern int window_relative_x_coord (struct window *, enum window_part, int);
 
-void run_window_size_change_functions (Lisp_Object);
+void run_window_change_functions (void);
 
 /* Make WINDOW display BUFFER.  RUN_HOOKS_P means it's allowed
    to run hooks.  See make_frame for a case where it's not allowed.  */
diff --git a/src/xdisp.c b/src/xdisp.c
index 4cb1050..cce26db 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2786,6 +2786,7 @@ static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
 	       struct glyph_row *row, enum face_id base_face_id)
 {
   enum face_id remapped_base_face_id = base_face_id;
+  int body_width = 0, body_height = 0;
 
   /* Some precondition checks.  */
   eassert (w != NULL && it != NULL);
@@ -2962,7 +2963,7 @@ static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
     {
       /* Mode lines, menu bar in terminal frames.  */
       it->first_visible_x = 0;
-      it->last_visible_x = WINDOW_PIXEL_WIDTH (w);
+      it->last_visible_x = body_width = WINDOW_PIXEL_WIDTH (w);
     }
   else
     {
@@ -2982,8 +2983,12 @@ static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
       else
 	it->first_visible_x =
 	  window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
-      it->last_visible_x = (it->first_visible_x
-			    + window_box_width (w, TEXT_AREA));
+
+      body_width = window_box_width (w, TEXT_AREA);
+      if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
+	  && body_width != w->old_body_pixel_width)
+	FRAME_WINDOW_CHANGE (it->f) = true;
+      it->last_visible_x = it->first_visible_x + body_width;
 
       /* If we truncate lines, leave room for the truncation glyph(s) at
 	 the right margin.  Otherwise, leave room for the continuation
@@ -2997,7 +3002,8 @@ static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
 	}
 
       it->header_line_p = window_wants_header_line (w);
-      it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
+      body_height = WINDOW_HEADER_LINE_HEIGHT (w);
+      it->current_y =  body_height + w->vscroll;
     }
 
   /* Leave room for a border glyph.  */
@@ -3006,6 +3012,10 @@ static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
     it->last_visible_x -= 1;
 
   it->last_visible_y = window_text_bottom_y (w);
+  body_height += it->last_visible_y;
+  if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
+      && body_height != w->old_body_pixel_height)
+    FRAME_WINDOW_CHANGE (it->f) = true;
 
   /* For mode lines and alike, arrange for the first glyph having a
      left box line if the face specifies a box.  */
@@ -12200,8 +12210,6 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
 	      && !XBUFFER (w->contents)->text->redisplay)
 	    continue;
 
-	  run_window_size_change_functions (frame);
-
 	  if (FRAME_PARENT_FRAME (f))
 	    continue;
 
@@ -14119,20 +14127,6 @@ static void debug_method_add (struct window *, char const *, ...)
     {
       echo_area_display (false);
 
-      /* If echo_area_display resizes the mini-window, the redisplay and
-	 window_sizes_changed flags of the selected frame are set, but
-	 it's too late for the hooks in window-size-change-functions,
-	 which have been examined already in prepare_menu_bars.  So in
-	 that case we call the hooks here only for the selected frame.  */
-      if (sf->redisplay)
-	{
-	  ptrdiff_t count1 = SPECPDL_INDEX ();
-
-	  record_unwind_save_match_data ();
-	  run_window_size_change_functions (selected_frame);
-	  unbind_to (count1, Qnil);
-	}
-
       if (message_cleared_p)
 	update_miniwindow_p = true;
 
@@ -14149,15 +14143,6 @@ static void debug_method_add (struct window *, char const *, ...)
 	   && (current_buffer->clip_changed || window_outdated (w))
 	   && resize_mini_window (w, false))
     {
-      if (sf->redisplay)
-	{
-	  ptrdiff_t count1 = SPECPDL_INDEX ();
-
-	  record_unwind_save_match_data ();
-	  run_window_size_change_functions (selected_frame);
-	  unbind_to (count1, Qnil);
-	}
-
       /* Resized active mini-window to fit the size of what it is
          showing if its contents might have changed.  */
       must_finish = true;
@@ -14347,7 +14332,19 @@ static void debug_method_add (struct window *, char const *, ...)
 		  && (w = XWINDOW (selected_window)) != sw)
 		goto retry;
 
-	      /* We used to always goto end_of_redisplay here, but this
+	      if (!NILP (Vrun_hooks))
+		{
+		  run_window_change_functions ();
+
+		  /* If windows or buffers changed or selected_window
+		     changed, redisplay again.  */
+		  if ((windows_or_buffers_changed)
+		      || (WINDOWP (selected_window)
+			  && (w = XWINDOW (selected_window)) != sw))
+		    goto retry;
+		}
+
+		/* We used to always goto end_of_redisplay here, but this
 		 isn't enough if we have a blinking cursor.  */
 	      if (w->cursor_off_p == w->last_cursor_off_p)
 		goto end_of_redisplay;
@@ -14706,9 +14703,22 @@ static void debug_method_add (struct window *, char const *, ...)
   /* If we just did a pending size change, or have additional
      visible frames, or selected_window changed, redisplay again.  */
   if ((windows_or_buffers_changed && !pending)
-      || (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw))
+      || (WINDOWP (selected_window)
+	  && (w = XWINDOW (selected_window)) != sw))
     goto retry;
 
+  if (!NILP (Vrun_hooks))
+    {
+      run_window_change_functions ();
+
+      /* If windows or buffers changed or selected_window changed,
+	 redisplay again.  */
+      if ((windows_or_buffers_changed)
+	  || (WINDOWP (selected_window)
+	      && (w = XWINDOW (selected_window)) != sw))
+	goto retry;
+    }
+
   /* Clear the face and image caches.
 
      We used to do this only if consider_all_windows_p.  But the cache


^ permalink raw reply related	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2018-12-31 14:16                                                     ` martin rudalics
@ 2019-01-01 15:37                                                       ` Gary Fredericks
  2019-01-01 17:25                                                         ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2019-01-01 15:37 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 1288 bytes --]

That one worked -- thanks.

I started running the patched version and immediately ran into trouble with
switching away from term-mode buffers, but I suspect it's related to some
custom code I have:

https://github.com/gfredericks/dotfiles/blob/6a6497dd747e92b034549f3aee05d4dc6f0640d5/base/.emacs.d/user/gfredericks-terminals.el.symlink#L63

In particular C-x b doesn't work like it used to; it ends up doing
something weird where it creates a buffer named after the minibuffer buffer
selection text.

I confirmed that I don't have the same issue when using unpatched master.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Mon, Dec 31, 2018 at 8:16 AM martin rudalics <rudalics@gmx.at> wrote:

>  > $ git show | head -1
>  > commit 792dc36e691b1e4b7735c75d2d402d1b9a8801ce
>  >
>  > $ git apply txtC00XwS8xFx.txt --verbose
>  > error: corrupt patch at line 9
>  >
>  > $ md5sum txtC00XwS8xFx.txt
>  > 0d958ef0f85eef10f0de8e963044278f txtC00XwS8xFx.txt
>
> No idea what happened.  I attach the latest version against today's
> master (the same commit you mentioned).
>
> git show | head -1
> commit 792dc36e691b1e4b7735c75d2d402d1b9a8801ce
>
> md5sum window-change-functions.diff
> 619d18ffa7106e21c07992d2b6df302a *window-change-functions.diff
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 2237 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-01 15:37                                                       ` Gary Fredericks
@ 2019-01-01 17:25                                                         ` martin rudalics
  2019-01-01 17:31                                                           ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2019-01-01 17:25 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > I started running the patched version and immediately ran into trouble with
 > switching away from term-mode buffers, but I suspect it's related to some
 > custom code I have:
 >
 > https://github.com/gfredericks/dotfiles/blob/6a6497dd747e92b034549f3aee05d4dc6f0640d5/base/.emacs.d/user/gfredericks-terminals.el.symlink#L63

The only things related to my patch should be

(defun window-size-change-function-for-bug-32720 (_frame)
   (window--adjust-process-windows))

and its activation in 'term-load-hook'.  Would removing these change
something in the behavior you observe?

 > In particular C-x b doesn't work like it used to; it ends up doing
 > something weird where it creates a buffer named after the minibuffer buffer
 > selection text.

Shouldn't C-x b create such a buffer if it does not exist yet?  What
precisely did you want it to do?

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-01 17:25                                                         ` martin rudalics
@ 2019-01-01 17:31                                                           ` Gary Fredericks
  2019-01-01 17:55                                                             ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2019-01-01 17:31 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 1510 bytes --]

I'm sorry, I forgot that code was there -- I had already disabled in when I
ran these tests, so you can disregard it.

C-x b for me starts an ido buffer selector. I forgot that wasn't a default
either.

So the buffer selector did not work -- it would show me a list of other
buffers (in the minibuffer), but I couldn't select one with RET -- it would
end up just creating a new buffer whose (very long) name was the list of
buffer names that ido showed.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Tue, Jan 1, 2019 at 11:25 AM martin rudalics <rudalics@gmx.at> wrote:

>  > I started running the patched version and immediately ran into trouble
> with
>  > switching away from term-mode buffers, but I suspect it's related to
> some
>  > custom code I have:
>  >
>  >
> https://github.com/gfredericks/dotfiles/blob/6a6497dd747e92b034549f3aee05d4dc6f0640d5/base/.emacs.d/user/gfredericks-terminals.el.symlink#L63
>
> The only things related to my patch should be
>
> (defun window-size-change-function-for-bug-32720 (_frame)
>    (window--adjust-process-windows))
>
> and its activation in 'term-load-hook'.  Would removing these change
> something in the behavior you observe?
>
>  > In particular C-x b doesn't work like it used to; it ends up doing
>  > something weird where it creates a buffer named after the minibuffer
> buffer
>  > selection text.
>
> Shouldn't C-x b create such a buffer if it does not exist yet?  What
> precisely did you want it to do?
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 2413 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-01 17:31                                                           ` Gary Fredericks
@ 2019-01-01 17:55                                                             ` martin rudalics
  2019-01-06 22:51                                                               ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2019-01-01 17:55 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > C-x b for me starts an ido buffer selector. I forgot that wasn't a default
 > either.
 >
 > So the buffer selector did not work -- it would show me a list of other
 > buffers (in the minibuffer), but I couldn't select one with RET -- it would
 > end up just creating a new buffer whose (very long) name was the list of
 > buffer names that ido showed.

Does the problem occur with emacs -Q if you just activate 'ido-mode'?
In either case you would have to debug 'ido-buffer-internal' and look
where the strange value for 'buf' comes from.  If it comes from
'ido-read-internal' you would have to look into that one too.  Here I
cannot trigger any problems with 'ido-mode'.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-01 17:55                                                             ` martin rudalics
@ 2019-01-06 22:51                                                               ` Gary Fredericks
  2019-01-07 12:29                                                                 ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2019-01-06 22:51 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 1129 bytes --]

Now that I'm trying harder to isolate the bug, I can't reproduce it anymore.

Perhaps it was a symptom of a dirty build process, as I had switched to a
clean checkout. I thought `make clean; make bootstrap` was sufficient to
clean everything up, but perhaps not.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Tue, Jan 1, 2019 at 11:55 AM martin rudalics <rudalics@gmx.at> wrote:

>  > C-x b for me starts an ido buffer selector. I forgot that wasn't a
> default
>  > either.
>  >
>  > So the buffer selector did not work -- it would show me a list of other
>  > buffers (in the minibuffer), but I couldn't select one with RET -- it
> would
>  > end up just creating a new buffer whose (very long) name was the list of
>  > buffer names that ido showed.
>
> Does the problem occur with emacs -Q if you just activate 'ido-mode'?
> In either case you would have to debug 'ido-buffer-internal' and look
> where the strange value for 'buf' comes from.  If it comes from
> 'ido-read-internal' you would have to look into that one too.  Here I
> cannot trigger any problems with 'ido-mode'.
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 1812 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-06 22:51                                                               ` Gary Fredericks
@ 2019-01-07 12:29                                                                 ` Gary Fredericks
  2019-01-07 16:11                                                                   ` martin rudalics
  2019-01-11  9:24                                                                   ` martin rudalics
  0 siblings, 2 replies; 46+ messages in thread
From: Gary Fredericks @ 2019-01-07 12:29 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 1729 bytes --]

Actually I think I *have* run into the problem again, but this time it
seems to be related to my use of this plugin:
https://github.com/tlh/workgroups.el (in particular, C-x C-f from the
scratch buffer works before setting up a workgroup, but not after -- after
it complains about the minibuffer being active).

I'm going to try not using it for a few days to see if there are any other
issues.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Sun, Jan 6, 2019 at 4:51 PM Gary Fredericks <fredericksgary@gmail.com>
wrote:

> Now that I'm trying harder to isolate the bug, I can't reproduce it
> anymore.
>
> Perhaps it was a symptom of a dirty build process, as I had switched to a
> clean checkout. I thought `make clean; make bootstrap` was sufficient to
> clean everything up, but perhaps not.
>
> Gary Fredericks
> (803)-295-0195
> fredericksgary@gmail.com
> gfredericks.com
>
>
> On Tue, Jan 1, 2019 at 11:55 AM martin rudalics <rudalics@gmx.at> wrote:
>
>>  > C-x b for me starts an ido buffer selector. I forgot that wasn't a
>> default
>>  > either.
>>  >
>>  > So the buffer selector did not work -- it would show me a list of other
>>  > buffers (in the minibuffer), but I couldn't select one with RET -- it
>> would
>>  > end up just creating a new buffer whose (very long) name was the list
>> of
>>  > buffer names that ido showed.
>>
>> Does the problem occur with emacs -Q if you just activate 'ido-mode'?
>> In either case you would have to debug 'ido-buffer-internal' and look
>> where the strange value for 'buf' comes from.  If it comes from
>> 'ido-read-internal' you would have to look into that one too.  Here I
>> cannot trigger any problems with 'ido-mode'.
>>
>> martin
>>
>

[-- Attachment #2: Type: text/html, Size: 2992 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-07 12:29                                                                 ` Gary Fredericks
@ 2019-01-07 16:11                                                                   ` martin rudalics
  2019-01-11  9:24                                                                   ` martin rudalics
  1 sibling, 0 replies; 46+ messages in thread
From: martin rudalics @ 2019-01-07 16:11 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > Actually I think I *have* run into the problem again, but this time it
 > seems to be related to my use of this plugin:
 > https://github.com/tlh/workgroups.el (in particular, C-x C-f from the
 > scratch buffer works before setting up a workgroup, but not after -- after
 > it complains about the minibuffer being active).

AFAICT workgroups.el doesn't care about window changes.  Playing
around with C-z C-f and C-z C-b I did not encounter any problems.  And
C-x C-f runs the usual 'find-file', unrelated to workgroups' bindings.

 > I'm going to try not using it for a few days to see if there are any other
 > issues.

Maybe you can try to distill a minimum setup needed to produce the
problem.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-07 12:29                                                                 ` Gary Fredericks
  2019-01-07 16:11                                                                   ` martin rudalics
@ 2019-01-11  9:24                                                                   ` martin rudalics
  2019-01-16 14:07                                                                     ` Gary Fredericks
  1 sibling, 1 reply; 46+ messages in thread
From: martin rudalics @ 2019-01-11  9:24 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > Actually I think I *have* run into the problem again, but this time it
 > seems to be related to my use of this plugin:
 > https://github.com/tlh/workgroups.el (in particular, C-x C-f from the
 > scratch buffer works before setting up a workgroup, but not after -- after
 > it complains about the minibuffer being active).
 >
 > I'm going to try not using it for a few days to see if there are any other
 > issues.

The changes are on master now so please remove yours before pulling
from master the next time.

And obviously please report any findings you have ASAP.

Thank you, martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-11  9:24                                                                   ` martin rudalics
@ 2019-01-16 14:07                                                                     ` Gary Fredericks
  2019-01-16 17:30                                                                       ` martin rudalics
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2019-01-16 14:07 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 1414 bytes --]

I tracked down my issue to this line in my configuration:

https://github.com/gfredericks/dotfiles/blob/48c503319046517fc1767735d09fbb232ace12ba/base/.emacs.d/user/gfredericks-longrunning.el.symlink#L34

I can see how it's related, since it's adding a
window-configuration-change-hook, but I can't tell at a glance what's wrong
with it. It's a function that tries to save the current window
configuration to a variable each time it changes.

I'm going to use the new emacs[1] for a while with this line commented out
to see if there are any other issues.

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com

[1] Actually running b0b483d714 because I couldn't get master (655badc33e)
to compile


On Fri, Jan 11, 2019 at 3:24 AM martin rudalics <rudalics@gmx.at> wrote:

>  > Actually I think I *have* run into the problem again, but this time it
>  > seems to be related to my use of this plugin:
>  > https://github.com/tlh/workgroups.el (in particular, C-x C-f from the
>  > scratch buffer works before setting up a workgroup, but not after --
> after
>  > it complains about the minibuffer being active).
>  >
>  > I'm going to try not using it for a few days to see if there are any
> other
>  > issues.
>
> The changes are on master now so please remove yours before pulling
> from master the next time.
>
> And obviously please report any findings you have ASAP.
>
> Thank you, martin
>

[-- Attachment #2: Type: text/html, Size: 2428 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-16 14:07                                                                     ` Gary Fredericks
@ 2019-01-16 17:30                                                                       ` martin rudalics
  2019-01-16 17:44                                                                         ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: martin rudalics @ 2019-01-16 17:30 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

 > I tracked down my issue to this line in my configuration:
 >
 > https://github.com/gfredericks/dotfiles/blob/48c503319046517fc1767735d09fbb232ace12ba/base/.emacs.d/user/gfredericks-longrunning.el.symlink#L34
 >
 > I can see how it's related, since it's adding a
 > window-configuration-change-hook, but I can't tell at a glance what's wrong
 > with it. It's a function that tries to save the current window
 > configuration to a variable each time it changes.

...

 >>   > it complains about the minibuffer being active).

The error seems to come from this wg function:

(defun wg-error-on-active-minibuffer ()
   "Throw an error when the minibuffer is active."
   (when (active-minibuffer-window)
     (error "Workgroup operations aren't permitted while the \
minibuffer is active.")))

'window-configuration-change-hook' now conceptually runs after any
resize operation which includes states where the minibuffer window is
active.  FWIW the call sequence you encounter is

stash-my-working-config -> wg-make-wconfig -> wg-ewtree->wtree ->
wg-error-on-active-minibuffer

so maybe you should not stash your working configuration when the
minibuffer is active.

martin





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-16 17:30                                                                       ` martin rudalics
@ 2019-01-16 17:44                                                                         ` Gary Fredericks
  2020-08-22 14:59                                                                           ` Lars Ingebrigtsen
  0 siblings, 1 reply; 46+ messages in thread
From: Gary Fredericks @ 2019-01-16 17:44 UTC (permalink / raw)
  To: martin rudalics; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 1435 bytes --]

That sounds plausible, I'll try that out.

Thanks!

Gary Fredericks
(803)-295-0195
fredericksgary@gmail.com
gfredericks.com


On Wed, Jan 16, 2019 at 11:30 AM martin rudalics <rudalics@gmx.at> wrote:

>  > I tracked down my issue to this line in my configuration:
>  >
>  >
> https://github.com/gfredericks/dotfiles/blob/48c503319046517fc1767735d09fbb232ace12ba/base/.emacs.d/user/gfredericks-longrunning.el.symlink#L34
>  >
>  > I can see how it's related, since it's adding a
>  > window-configuration-change-hook, but I can't tell at a glance what's
> wrong
>  > with it. It's a function that tries to save the current window
>  > configuration to a variable each time it changes.
>
> ...
>
>  >>   > it complains about the minibuffer being active).
>
> The error seems to come from this wg function:
>
> (defun wg-error-on-active-minibuffer ()
>    "Throw an error when the minibuffer is active."
>    (when (active-minibuffer-window)
>      (error "Workgroup operations aren't permitted while the \
> minibuffer is active.")))
>
> 'window-configuration-change-hook' now conceptually runs after any
> resize operation which includes states where the minibuffer window is
> active.  FWIW the call sequence you encounter is
>
> stash-my-working-config -> wg-make-wconfig -> wg-ewtree->wtree ->
> wg-error-on-active-minibuffer
>
> so maybe you should not stash your working configuration when the
> minibuffer is active.
>
> martin
>

[-- Attachment #2: Type: text/html, Size: 2407 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2019-01-16 17:44                                                                         ` Gary Fredericks
@ 2020-08-22 14:59                                                                           ` Lars Ingebrigtsen
  2020-08-22 16:57                                                                             ` Gary Fredericks
  0 siblings, 1 reply; 46+ messages in thread
From: Lars Ingebrigtsen @ 2020-08-22 14:59 UTC (permalink / raw)
  To: Gary Fredericks; +Cc: 32720

Gary Fredericks <fredericksgary@gmail.com> writes:

> That sounds plausible, I'll try that out.

I've just skimmed the bug report, but it seems like the bug in question
was fixed, and the rest was a local configuration issue?  So I'm closing
this bug report.  If there's more to be done here, please respond to the
debbugs address and we'll reopen.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 46+ messages in thread

* bug#32720: term-mode ignores certain window size changes
  2020-08-22 14:59                                                                           ` Lars Ingebrigtsen
@ 2020-08-22 16:57                                                                             ` Gary Fredericks
  0 siblings, 0 replies; 46+ messages in thread
From: Gary Fredericks @ 2020-08-22 16:57 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: 32720

[-- Attachment #1: Type: text/plain, Size: 638 bytes --]

I agree -- I don't think I've experienced the issue since.

Thanks!

Gary Fredericks


On Sat, Aug 22, 2020 at 10:00 AM Lars Ingebrigtsen <larsi@gnus.org> wrote:

> Gary Fredericks <fredericksgary@gmail.com> writes:
>
> > That sounds plausible, I'll try that out.
>
> I've just skimmed the bug report, but it seems like the bug in question
> was fixed, and the rest was a local configuration issue?  So I'm closing
> this bug report.  If there's more to be done here, please respond to the
> debbugs address and we'll reopen.
>
> --
> (domestic pets only, the antidote for overdose, milk.)
>    bloggy blog: http://lars.ingebrigtsen.no
>

[-- Attachment #2: Type: text/html, Size: 1304 bytes --]

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2020-08-22 16:57 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-12 12:09 bug#32720: term-mode ignores certain window size changes Gary Fredericks
2018-09-13  8:07 ` martin rudalics
2018-09-13 14:06   ` Eli Zaretskii
2018-09-14  8:32     ` martin rudalics
2018-11-04  9:56 ` martin rudalics
2018-11-16 12:15   ` Gary Fredericks
2018-11-16 12:57     ` martin rudalics
2018-11-16 13:15       ` Gary Fredericks
2018-11-18  9:22         ` martin rudalics
2018-11-16 14:45       ` Eli Zaretskii
2018-11-17  9:20         ` martin rudalics
2018-11-17  9:43           ` Eli Zaretskii
2018-11-17 18:40             ` martin rudalics
2018-11-18  3:30               ` Eli Zaretskii
2018-11-18  9:22                 ` martin rudalics
2018-11-18 15:21                   ` Eli Zaretskii
2018-11-18 19:37                     ` martin rudalics
2018-11-18 20:10                       ` Eli Zaretskii
2018-11-19  9:41                         ` martin rudalics
2018-11-19 15:04                           ` Gary Fredericks
2018-11-19 15:14                             ` martin rudalics
2018-12-22 22:53                               ` Gary Fredericks
2018-12-23  9:38                                 ` martin rudalics
2018-12-23 13:16                                   ` Gary Fredericks
2018-12-23 13:40                                     ` martin rudalics
2018-12-23 13:47                                       ` Gary Fredericks
2018-12-23 18:02                                         ` martin rudalics
2018-12-23 18:54                                           ` Gary Fredericks
2018-12-25  9:51                                             ` martin rudalics
2018-12-29 23:23                                               ` Gary Fredericks
2018-12-30  9:53                                                 ` martin rudalics
2018-12-31 12:45                                                   ` Gary Fredericks
2018-12-31 14:16                                                     ` martin rudalics
2019-01-01 15:37                                                       ` Gary Fredericks
2019-01-01 17:25                                                         ` martin rudalics
2019-01-01 17:31                                                           ` Gary Fredericks
2019-01-01 17:55                                                             ` martin rudalics
2019-01-06 22:51                                                               ` Gary Fredericks
2019-01-07 12:29                                                                 ` Gary Fredericks
2019-01-07 16:11                                                                   ` martin rudalics
2019-01-11  9:24                                                                   ` martin rudalics
2019-01-16 14:07                                                                     ` Gary Fredericks
2019-01-16 17:30                                                                       ` martin rudalics
2019-01-16 17:44                                                                         ` Gary Fredericks
2020-08-22 14:59                                                                           ` Lars Ingebrigtsen
2020-08-22 16:57                                                                             ` Gary Fredericks

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).