From: Alan Mackenzie <acm@muc.de>
To: 21869@debbugs.gnu.org
Cc: pipcet@gmail.com, 21333@debbugs.gnu.org
Subject: bug#21333: bug#21869: [Patch] Redisplay: after echo area diminishes in size, Follow Mode windows aren't resynchronised.
Date: Tue, 17 Nov 2015 17:56:23 +0000 [thread overview]
Message-ID: <20151117175623.GA5077@acm.fritz.box> (raw)
In-Reply-To: <20151116150357.GA7344@acm.fritz.box>
On Mon, Nov 16, 2015 at 03:03:57PM +0000, Alan Mackenzie wrote:
> On Mon, Nov 09, 2015 at 10:50:57PM +0200, Eli Zaretskii wrote:
> > > Date: Mon, 9 Nov 2015 19:42:00 +0000
> > > From: Alan Mackenzie <acm@muc.de>
> > > Cc: 21869@debbugs.gnu.org, Pip Cet <pipcet@gmail.com>
> > > > Probably bug#830 and bug#21333.
> Quick summary of the bug: with Follow Mode active, with a multi-line
> display in the echo area, do C-f. The echo area resizes to one line,
> but the Follow Mode windows don't get resynchronised.
> Quick summary of the cause: redisplay_internal calls prepare_menu_bars
> (which invokes the window-size-change-functions hook) before it calls
> echo_area_display (which resizes the echo area). Thus changes to the
> echo area size aren't yet in place when window-size-change-functions is
> invoked.
> I propose the following strategy to fix the bug:
> 1. Call resize_mini_window from redisplay_internal before the call to
> prepare_menu_bars.
> 2. Remove the call to resize_mini_window from display_echo_area_1, and
> make that function of type void.
> 3. Change the contract of echo_area_display, such that the echo area
> must have been set to the correct height before calling it.
> 4. Adapt message3_nolog (the only other function which calls
> echo_area_display) to call resize_mini_window.
> As a result of these changes, any change in the size of the echo area
> would be taken into account when invoking window-size-change-functions.
> An advantage of this change is that a recursive invocation of
> redisplay_internal inside echo_area_display could be removed, improving
> performance.
No it couldn't. That invocation is not a recursive one, it's the main
call of redisplay_internal for the message functions.
Here is a patch implementing the above scheme. It should also fix
bug#21333 (or, at least, go a long way towards fixing it):
Invoke window-size-change-functions after changing echo area height.
Fixes bug #21869 and probably bug #21333. Separate the resizing of the echo
area from the displaying of text in it. This allows
window-size-change-functions to be invoked after the former, but before the
latter, according to its specification.
src/xdisp.c (message3_nolog): Invoke resize_mini_window_1 before calling
echo_area_display.
(display_echo_area): Change type to (static) void. Change contract such that
the echo area must have been resized, if nec., before calling, and that this
function doesn't resize.
(display_echo_area_1): Now always return false, since the function never
resizes.
(echo_area_display): Add extra parameter `window_height_changed_p', replacing
a local of the same name. The function no longer resizes the echo area.
(redisplay_internal): Invoke resize_mini_window_1 before calling
prepare_menu_bars (which invokes window-size-change-functions).
diff --git a/src/xdisp.c b/src/xdisp.c
index 30dfac5..68e56b7 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -800,6 +800,9 @@ static int redisplay_mode_lines (Lisp_Object, bool);
static void handle_line_prefix (struct it *);
static void handle_stop_backwards (struct it *, ptrdiff_t);
+static bool with_echo_area_buffer (struct window *, int,
+ bool (*)(ptrdiff_t, Lisp_Object),
+ ptrdiff_t, Lisp_Object);
static void unwind_with_echo_area_buffer (Lisp_Object);
static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
static bool current_message_1 (ptrdiff_t, Lisp_Object);
@@ -815,7 +818,7 @@ static void push_it (struct it *, struct text_pos *);
static void iterate_out_of_display_property (struct it *);
static void pop_it (struct it *);
static void redisplay_internal (void);
-static void echo_area_display (bool);
+static void echo_area_display (bool, bool);
static void redisplay_windows (Lisp_Object);
static void redisplay_window (Lisp_Object, bool);
static Lisp_Object redisplay_window_error (Lisp_Object);
@@ -10234,8 +10237,10 @@ message3_nolog (Lisp_Object m)
/* Get the frame containing the mini-buffer
that the selected frame is using. */
Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
+ struct window *mw = XWINDOW (mini_window);
Lisp_Object frame = XWINDOW (mini_window)->frame;
struct frame *f = XFRAME (frame);
+ bool window_height_changed_p;
if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
Fmake_frame_visible (frame);
@@ -10253,7 +10258,12 @@ message3_nolog (Lisp_Object m)
clear_message (true, true);
do_pending_window_change (false);
- echo_area_display (true);
+ if (window_height_changed_p =
+ with_echo_area_buffer (mw, display_last_displayed_message_p,
+ resize_mini_window_1,
+ (intptr_t) mw, Qt))
+ FRAME_WINDOW_SIZES_CHANGED (sf) = true;
+ echo_area_display (true, window_height_changed_p);
do_pending_window_change (false);
if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
(*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
@@ -10711,15 +10721,15 @@ setup_echo_area_for_printing (bool multibyte_p)
}
-/* Display an echo area message in window W. Value is true if W's
- height is changed. If display_last_displayed_message_p,
- display the message that was last displayed, otherwise
- display the current message. */
+/* Display an echo area message in window W. If
+ display_last_displayed_message_p, display the message that was last
+ displayed, otherwise display the current message. The window
+ height of W must already have been set for the message. */
-static bool
+static void
display_echo_area (struct window *w)
{
- bool no_message_p, window_height_changed_p;
+ bool no_message_p;
/* Temporarily disable garbage collections while displaying the echo
area. This is done because a GC can print a message itself.
@@ -10735,24 +10745,22 @@ display_echo_area (struct window *w)
bool i = display_last_displayed_message_p;
no_message_p = NILP (echo_area_buffer[i]);
- window_height_changed_p
- = with_echo_area_buffer (w, display_last_displayed_message_p,
- display_echo_area_1,
- (intptr_t) w, Qnil);
+ with_echo_area_buffer (w, display_last_displayed_message_p,
+ display_echo_area_1,
+ (intptr_t) w, Qnil);
if (no_message_p)
echo_area_buffer[i] = Qnil;
unbind_to (count, Qnil);
- return window_height_changed_p;
}
/* Helper for display_echo_area. Display the current buffer which
contains the current echo area message in window W, a mini-window,
- a pointer to which is passed in A1. A2..A4 are currently not used.
- Change the height of W so that all of the message is displayed.
- Value is true if height of W was changed. */
+ a pointer to which is passed in A1. The height of W must already
+ have been set to the correct height for the message. Always
+ returns false. */
static bool
display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2)
@@ -10767,11 +10775,6 @@ display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2)
here. */
forget_escape_and_glyphless_faces ();
- /* Do this before displaying, so that we have a large enough glyph
- matrix for the display. If we can't get enough space for the
- whole text, display the last N lines. That works by setting w->start. */
- bool window_height_changed_p = resize_mini_window (w, false);
-
/* Use the starting position chosen by resize_mini_window. */
SET_TEXT_POS_FROM_MARKER (start, w->start);
@@ -10780,7 +10783,7 @@ display_echo_area_1 (ptrdiff_t a1, Lisp_Object a2)
XSETWINDOW (window, w);
try_window (window, start, 0);
- return window_height_changed_p;
+ return false;
}
@@ -11196,16 +11199,17 @@ clear_garbaged_frames (void)
}
-/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P, update
- selected_frame. */
+/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P,
+ update selected_frame. WINDOW_HEIGHT_CHANGED_P states whether the
+ echo area's height has just been changed. It is ignored unless
+ UPDATE_FRAME_P is true. */
static void
-echo_area_display (bool update_frame_p)
+echo_area_display (bool update_frame_p, bool window_height_changed_p)
{
Lisp_Object mini_window;
struct window *w;
struct frame *f;
- bool window_height_changed_p = false;
struct frame *sf = SELECTED_FRAME ();
mini_window = FRAME_MINIBUF_WINDOW (sf);
@@ -11230,7 +11234,7 @@ echo_area_display (bool update_frame_p)
if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
{
echo_area_window = mini_window;
- window_height_changed_p = display_echo_area (w);
+ display_echo_area (w);
w->must_be_updated_p = true;
/* Update the display, unless called from redisplay_internal.
@@ -13497,6 +13501,19 @@ redisplay_internal (void)
/* Clear frames marked as garbaged. */
clear_garbaged_frames ();
+ /* Resize the echo area, if needed, before the invocation of
+ window-size-change-functions. */
+ {
+ Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
+ struct window *mw = XWINDOW (mini_window);
+
+ if (!MINI_WINDOW_P (XWINDOW (selected_window))
+ && with_echo_area_buffer (mw, display_last_displayed_message_p,
+ resize_mini_window_1,
+ (intptr_t) mw, Qnil))
+ FRAME_WINDOW_SIZES_CHANGED (sf) = true;
+ }
+
/* Build menubar and tool-bar items. */
if (NILP (Vmemory_full))
prepare_menu_bars ();
@@ -13534,7 +13551,7 @@ redisplay_internal (void)
echo-area doesn't show through. */
&& !MINI_WINDOW_P (XWINDOW (selected_window))))
{
- echo_area_display (false);
+ echo_area_display (false, false);
if (message_cleared_p)
update_miniwindow_p = true;
--
Alan Mackenzie (Nuremberg, Germany).
next prev parent reply other threads:[~2015-11-17 17:56 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <mailman.1986.1447061708.7904.bug-gnu-emacs@gnu.org>
2015-11-09 9:35 ` bug#21869: Redisplay: after echo area diminishes in size, Follow Mode windows aren't resynchronised Alan Mackenzie
2015-11-09 10:04 ` martin rudalics
2015-11-09 11:15 ` Alan Mackenzie
2015-11-09 16:10 ` Eli Zaretskii
2015-11-09 19:42 ` bug#21869: [Patch] " Alan Mackenzie
2015-11-09 20:50 ` Eli Zaretskii
2015-11-10 13:49 ` Alan Mackenzie
2015-11-16 15:03 ` Alan Mackenzie
2015-11-17 17:56 ` Alan Mackenzie [this message]
2015-11-09 18:18 ` bug#21869: " Alan Mackenzie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20151117175623.GA5077@acm.fritz.box \
--to=acm@muc.de \
--cc=21333@debbugs.gnu.org \
--cc=21869@debbugs.gnu.org \
--cc=pipcet@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).