emacs-diffs
[Top][All Lists]
Advanced

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

master e1e0315252 01/14: Initial implementation of "abort-redisplay" fea


From: Eli Zaretskii
Subject: master e1e0315252 01/14: Initial implementation of "abort-redisplay" feature
Date: Fri, 24 Jun 2022 03:54:17 -0400 (EDT)

branch: master
commit e1e0315252d9f09ed061950630fe36b96349124e
Author: Eli Zaretskii <eliz@gnu.org>
Commit: Eli Zaretskii <eliz@gnu.org>

    Initial implementation of "abort-redisplay" feature
    
    * src/xdisp.c (update_redisplay_ticks): New function.
    (init_iterator, set_iterator_to_next): Call
    'update_redisplay_ticks'.
    (syms_of_xdisp) <max_redisplay_ticks>: New variable.
    <list_of_error>: Remove 'void-variable': it is no longer needed,
    since 'calc_pixel_width_or_height' can no longer signal a
    void-variable error, and it gets in the way of aborting
    redisplay via 'redisplay_window_error'.
---
 src/dispextern.h |  2 ++
 src/xdisp.c      | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/src/dispextern.h b/src/dispextern.h
index c7399ca299..a919f364c1 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3505,6 +3505,8 @@ extern unsigned row_hash (struct glyph_row *);
 
 extern bool buffer_flipping_blocked_p (void);
 
+extern void update_redisplay_ticks (int, struct it *);
+
 /* Defined in image.c */
 
 #ifdef HAVE_WINDOW_SYSTEM
diff --git a/src/xdisp.c b/src/xdisp.c
index 2245326b0d..24f3167e7d 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -3222,6 +3222,8 @@ init_iterator (struct it *it, struct window *w,
 
   it->cmp_it.id = -1;
 
+  update_redisplay_ticks (0, it);
+
   /* Extra space between lines (on window systems only).  */
   if (base_face_id == DEFAULT_FACE_ID
       && FRAME_WINDOW_P (it->f))
@@ -8175,6 +8177,8 @@ void
 set_iterator_to_next (struct it *it, bool reseat_p)
 {
 
+  update_redisplay_ticks (1, it);
+
   switch (it->method)
     {
     case GET_FROM_BUFFER:
@@ -16724,9 +16728,14 @@ redisplay_internal (void)
                                 list_of_error,
                                 redisplay_window_error);
       if (update_miniwindow_p)
-       internal_condition_case_1 (redisplay_window_1,
-                                  FRAME_MINIBUF_WINDOW (sf), list_of_error,
-                                  redisplay_window_error);
+       {
+         Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
+
+         displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
+         internal_condition_case_1 (redisplay_window_1, mini_window,
+                                    list_of_error,
+                                    redisplay_window_error);
+       }
 
       /* Compare desired and current matrices, perform output.  */
 
@@ -17156,6 +17165,43 @@ redisplay_window_1 (Lisp_Object window)
     redisplay_window (window, true);
   return Qnil;
 }
+
+
+/***********************************************************************
+                     Aborting runaway redisplay
+ ***********************************************************************/
+
+/* Update the redisplay-tick count for a window, and signal an error
+   if the tick count is above some threshold, indicating that
+   redisplay of the window takes "too long".
+
+   TICKS is the amount of ticks to add to the window's current count;
+   zero means to initialize the count to zero.
+
+   IT is the iterator used for redisplay work; it->w is the window we
+   are working on.  */
+void
+update_redisplay_ticks (int ticks, struct it *it)
+{
+  /* This keeps track of the window on which redisplay is working.  */
+  static struct window *cwindow;
+  static EMACS_INT window_ticks;
+
+  /* We only initialize the count if this is a different window.
+     Otherwise, this is a call from init_iterator for the same window
+     we tracked before, and we should keep the count.  */
+  if (!ticks && it->w != cwindow)
+    {
+      cwindow = it->w;
+      window_ticks = 0;
+    }
+  if (ticks > 0)
+    window_ticks += ticks;
+  if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
+    error ("Window showing buffer %s takes too long to redisplay",
+          SSDATA (BVAR (XBUFFER (it->w->contents), name)));
+}
+
 
 
 /* Set cursor position of W.  PT is assumed to be displayed in ROW.
@@ -35777,7 +35823,7 @@ be let-bound around code that needs to disable messages 
temporarily. */);
 
   DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
 
-  list_of_error = list1 (list2 (Qerror, Qvoid_variable));
+  list_of_error = list1 (Qerror);
   staticpro (&list_of_error);
 
   /* Values of those variables at last redisplay are stored as
@@ -36667,6 +36713,22 @@ and display the most important part of the minibuffer. 
  */);
 This makes it easier to edit character sequences that are
 composed on display.  */);
   composition_break_at_point = false;
+
+  DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
+    doc: /* Maximum number of redisplay ticks before aborting redisplay of a 
window.
+
+This allows to abort the display of a window if the amount of low-level
+redisplay operations exceeds the value of this variable.  When display of
+a window is aborted due to this reason, the buffer shown in that window
+will not have its windows redisplayed until the buffer is modified or until
+you type \\[recenter-top-bottom] with one of its windows selected.
+You can also decide to kill the buffer and visit it in some
+other way, like udner `so-long-mode' or literally.
+
+The default value is zero, which disables this feature.
+The recommended non-zero value is between 50000 and 200000,
+depending on your patience and the speed of your system.  */);
+  max_redisplay_ticks = 0;
 }
 
 



reply via email to

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