diff --git a/src/xdisp.c b/src/xdisp.c index 8649507..a60eb2d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -540,6 +540,14 @@ static bool message_cleared_p; +/* True means redisplay must not retry. */ + +static bool must_finish; + +/* True means redisplay has to redisplay the miniwindow. */ + +static bool update_miniwindow_p; + /* A scratch glyph row with contents used for generating truncation glyphs. Also used in direct_output_for_insert. */ @@ -11758,6 +11766,44 @@ static void ATTRIBUTE_FORMAT_PRINTF (1, 0) } } + +/* Redisplay echo_area if needed. Checking message_cleared_p captures + the case that the echo area should be cleared. + + Return true if we did redisplay the echo area. */ + +static bool +echo_area_redisplay (void) +{ + if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p) + || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p) + || (message_cleared_p + && minibuf_level == 0 + /* If the mini-window is currently selected, this means the + echo-area doesn't show through. */ + && !MINI_WINDOW_P (XWINDOW (selected_window)))) + { + echo_area_display (false); + + if (message_cleared_p) + update_miniwindow_p = true; + + must_finish = true; + + /* If we don't display the current message, don't clear the + message_cleared_p flag, because, if we did, we wouldn't clear + the echo area in the next redisplay which doesn't preserve + the echo area. */ + if (!display_last_displayed_message_p) + message_cleared_p = false; + + return true; + } + else + return false; +} + + /* True if W's buffer was changed but not saved. */ static bool @@ -13936,7 +13982,7 @@ static void debug_method_add (struct window *, char const *, ...) struct window *sw; struct frame *fr; bool pending; - bool must_finish = false, match_p; + bool match_p; struct text_pos tlbufpos, tlendpos; int number_of_visible_frames; ptrdiff_t count; @@ -13962,11 +14008,11 @@ static void debug_method_add (struct window *, char const *, ...) frames. False, only selected_window is considered. */ bool consider_all_windows_p; - /* True means redisplay has to redisplay the miniwindow. */ - bool update_miniwindow_p = false; - TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p)); + must_finish = false; + update_miniwindow_p = false; + /* No redisplay if running in batch mode or frame is not yet fully initialized, or redisplay is explicitly turned off by setting Vinhibit_redisplay. */ @@ -14117,31 +14163,10 @@ static void debug_method_add (struct window *, char const *, ...) the update may have been preempted, so display the echo area again here. Checking message_cleared_p captures the case that the echo area should be cleared. */ - if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p) - || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p) - || (message_cleared_p - && minibuf_level == 0 - /* If the mini-window is currently selected, this means the - echo-area doesn't show through. */ - && !MINI_WINDOW_P (XWINDOW (selected_window)))) - { - echo_area_display (false); - - if (message_cleared_p) - update_miniwindow_p = true; - - must_finish = true; - - /* If we don't display the current message, don't clear the - message_cleared_p flag, because, if we did, we wouldn't clear - the echo area in the next redisplay which doesn't preserve - the echo area. */ - if (!display_last_displayed_message_p) - message_cleared_p = false; - } - else if (EQ (selected_window, minibuf_window) - && (current_buffer->clip_changed || window_outdated (w)) - && resize_mini_window (w, false)) + if (!echo_area_redisplay () + && EQ (selected_window, minibuf_window) + && (current_buffer->clip_changed || window_outdated (w)) + && resize_mini_window (w, false)) { /* Resized active mini-window to fit the size of what it is showing if its contents might have changed. */ @@ -14153,6 +14178,16 @@ static void debug_method_add (struct window *, char const *, ...) clear_garbaged_frames (); } + if (!NILP (Vrun_hooks)) + { + run_window_change_functions (); + + /* With multiple frames any do_switch_frame run by a window change + function may have shrunk the echo area. Rerun echo_area_display + to guard against this. See Bug#34179.*/ + echo_area_redisplay (); + } + if (windows_or_buffers_changed && !update_mode_lines) /* Code that sets windows_or_buffers_changed doesn't distinguish whether only the windows's contents needs to be refreshed, or whether the @@ -14332,18 +14367,6 @@ static void debug_method_add (struct window *, char const *, ...) && (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; - } - /* 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) @@ -14707,18 +14730,6 @@ static void debug_method_add (struct window *, char const *, ...) && (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