]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow aborting redisplay stuck in 'parse-partial-sexp'
authorEli Zaretskii <eliz@gnu.org>
Sat, 18 Jun 2022 10:07:20 +0000 (13:07 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sat, 18 Jun 2022 10:07:20 +0000 (13:07 +0300)
* src/xdisp.c (display_working_on_window_p): New global variable.
(unwind_display_working_on_window): New function.
* src/keyboard.c (command_loop_1): Reset
'display_working_on_window_p' before and after executing commands.
* src/window.c (Frecenter, window_scroll, displayed_window_lines):
* src/indent.c (Fvertical_motion): Set
'display_working_on_window_p' before calling 'start_display'.
* src/syntax.c (scan_sexps_forward): Call 'update_redisplay_ticks'
after finishing the loop.

src/dispextern.h
src/indent.c
src/keyboard.c
src/window.c
src/xdisp.c

index 0ea3ac8b07b5bac4f8e0e2f96c15592913337353..8bcd13dbb6d073c0ba2bf9ea229c8a989890985e 100644 (file)
@@ -3407,6 +3407,8 @@ int partial_line_height (struct it *it_origin);
 bool in_display_vector_p (struct it *);
 int frame_mode_line_height (struct frame *);
 extern bool redisplaying_p;
+extern bool display_working_on_window_p;
+extern void unwind_display_working_on_window (void);
 extern bool help_echo_showing_p;
 extern Lisp_Object help_echo_string, help_echo_window;
 extern Lisp_Object help_echo_object, previous_help_echo_string;
index 51f6f414de30b31e623fcfece472443d89aa4c53..7d9f0fe8b0091ce90a26bdd8a063b1a4e4664d8c 100644 (file)
@@ -2177,6 +2177,8 @@ whether or not it is currently displayed in some window.  */)
        line_number_display_width (w, &lnum_width, &lnum_pixel_width);
       SET_TEXT_POS (pt, PT, PT_BYTE);
       itdata = bidi_shelve_cache ();
+      record_unwind_protect_void (unwind_display_working_on_window);
+      display_working_on_window_p = true;
       start_display (&it, w, pt);
       it.lnum_width = lnum_width;
       first_x = it.first_visible_x;
index 7d7dd2dba020c8796a54f36ec76618da44c79fe8..e5a991a8b21e1b3a689fba14294b7796ba3a491e 100644 (file)
@@ -1505,8 +1505,10 @@ command_loop_1 (void)
               executing the command, so that we don't blame the new
               command for the sins of the previous one.  */
            update_redisplay_ticks (0, NULL);
+           display_working_on_window_p = false;
 
             call1 (Qcommand_execute, Vthis_command);
+           display_working_on_window_p = false;
 
 #ifdef HAVE_WINDOW_SYSTEM
          /* Do not check display_hourglass_p here, because
index ac8408a9a971c3ce8708602feebcfbcef56e3826..9f0df6619a31f599b85533443766c58e98073547 100644 (file)
@@ -5568,7 +5568,11 @@ window_scroll (Lisp_Object window, EMACS_INT n, bool whole, bool noerror)
   /* On GUI frames, use the pixel-based version which is much slower
      than the line-based one but can handle varying line heights.  */
   if (FRAME_WINDOW_P (XFRAME (XWINDOW (window)->frame)))
-    window_scroll_pixel_based (window, n, whole, noerror);
+    {
+      record_unwind_protect_void (unwind_display_working_on_window);
+      display_working_on_window_p = true;
+      window_scroll_pixel_based (window, n, whole, noerror);
+    }
   else
     window_scroll_line_based (window, n, whole, noerror);
 
@@ -6496,9 +6500,14 @@ displayed_window_lines (struct window *w)
   CLIP_TEXT_POS_FROM_MARKER (start, w->start);
 
   itdata = bidi_shelve_cache ();
+
+  specpdl_ref count = SPECPDL_INDEX ();
+  record_unwind_protect_void (unwind_display_working_on_window);
+  display_working_on_window_p = true;
   start_display (&it, w, start);
   move_it_vertically (&it, height);
   bottom_y = line_bottom_y (&it);
+  unbind_to (count, Qnil);
   bidi_unshelve_cache (itdata, false);
 
   /* Add in empty lines at the bottom of the window.  */
@@ -6592,6 +6601,10 @@ and redisplay normally--don't erase and redraw the frame.  */)
      data structures might not be set up yet then.  */
   if (!FRAME_INITIAL_P (XFRAME (w->frame)))
     {
+      specpdl_ref count = SPECPDL_INDEX ();
+
+      record_unwind_protect_void (unwind_display_working_on_window);
+      display_working_on_window_p = true;
       if (center_p)
        {
          struct it it;
@@ -6708,6 +6721,7 @@ and redisplay normally--don't erase and redraw the frame.  */)
 
          bidi_unshelve_cache (itdata, false);
        }
+      unbind_to (count, Qnil);
     }
   else
     {
index 1ba9132e8c002b9f35e8517f5f007c9f0b148f77..1d52bbc6c93f8d8c817450a2edeb3d4dba6d8ea8 100644 (file)
@@ -1030,6 +1030,15 @@ static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
 
 bool redisplaying_p;
 
+/* True while some display-engine code is working on layout of some
+   window.
+
+   WARNING: Use sparingly, preferably only in top level of commands
+   and important functions, because using it in nested calls might
+   reset the flag when the inner call returns, behind the back of
+   the callers.  */
+bool display_working_on_window_p;
+
 /* If a string, XTread_socket generates an event to display that string.
    (The display is done in read_char.)  */
 
@@ -10961,6 +10970,7 @@ window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
     max_y = XFIXNUM (y_limit);
 
   itdata = bidi_shelve_cache ();
+
   start_display (&it, w, startp);
 
   int start_y = it.current_y;
@@ -16970,6 +16980,13 @@ unwind_redisplay (void)
   unblock_buffer_flips ();
 }
 
+/* Function registered with record_unwind_protect before calling
+   start_display outside of redisplay_internal.  */
+void
+unwind_display_working_on_window (void)
+{
+  display_working_on_window_p = false;
+}
 
 /* Mark the display of leaf window W as accurate or inaccurate.
    If ACCURATE_P, mark display of W as accurate.
@@ -17199,9 +17216,9 @@ update_redisplay_ticks (int ticks, struct window *w)
       cwindow = w;
       window_ticks = 0;
     }
-  /* Some callers can be run in contexts unrelated to redisplay, so
+  /* Some callers can be run in contexts unrelated to display code, so
      don't abort them and don't update the tick count in those cases.  */
-  if (!w && !redisplaying_p)
+  if (!w && !redisplaying_p && !display_working_on_window_p)
     return;
 
   if (ticks > 0)