changeset 71323:e882f189c3af

Modify preemptive redisplay to be based on periodic checks for input. (PERIODIC_PREEMPTION_CHECKING): Define to 1 iff EMACS_HAS_USECS. (Vredisplay_preemption_period): New variable. (syms_of_display): DEFVAR_LISP and initialize it. (preemption_period, preemption_next_check): New variables. (update_frame, update_single_window): Initialize them based on Vredisplay_preemption_period if !force_p. (update_window, update_frame_1): Use them to determine when to check for input.
author Kim F. Storm <storm@cua.dk>
date Mon, 12 Jun 2006 22:32:47 +0000
parents 35554e4f7699
children 52c2a53933f8
files src/dispnew.c
diffstat 1 files changed, 104 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/dispnew.c	Mon Jun 12 07:52:05 2006 +0000
+++ b/src/dispnew.c	Mon Jun 12 22:32:47 2006 +0000
@@ -192,6 +192,28 @@
 
 int redisplay_dont_pause;
 
+/* Define PERIODIC_PREEMPTION_CHECKING to 1, if micro-second timers
+   are supported, so we can check for input during redisplay at
+   regular intervals.  */
+#ifdef EMACS_HAS_USECS
+#define PERIODIC_PREEMPTION_CHECKING 1
+#else
+#define PERIODIC_PREEMPTION_CHECKING 0
+#endif
+
+#if PERIODIC_PREEMPTION_CHECKING
+
+/* If a number (float), check for user input every N seconds.  */
+
+Lisp_Object Vredisplay_preemption_period;
+
+/* Redisplay preemption timers.  */
+
+static EMACS_TIME preemption_period;
+static EMACS_TIME preemption_next_check;
+
+#endif
+
 /* Nonzero upon entry to redisplay means do not assume anything about
    current contents of actual terminal frame; clear and redraw it.  */
 
@@ -3820,6 +3842,22 @@
   int paused_p;
   struct window *root_window = XWINDOW (f->root_window);
 
+#if PERIODIC_PREEMPTION_CHECKING
+  if (!force_p && NUMBERP (Vredisplay_preemption_period))
+    {
+      EMACS_TIME tm;
+      double p = XFLOATINT (Vredisplay_preemption_period);
+      int sec, usec;
+
+      sec = (int) p;
+      usec = (p - sec) * 1000000;
+
+      EMACS_GET_TIME (tm);
+      EMACS_SET_SECS_USECS (preemption_period, sec, usec);
+      EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+    }
+#endif
+
   if (FRAME_WINDOW_P (f))
     {
       /* We are working on window matrix basis.  All windows whose
@@ -3952,6 +3990,22 @@
       /* Record that this is not a frame-based redisplay.  */
       set_frame_matrix_frame (NULL);
 
+#if PERIODIC_PREEMPTION_CHECKING
+      if (!force_p && NUMBERP (Vredisplay_preemption_period))
+	{
+	  EMACS_TIME tm;
+	  double p = XFLOATINT (Vredisplay_preemption_period);
+	  int sec, usec;
+
+	  sec = (int) p;
+	  usec = (p - sec) * 1000000;
+
+	  EMACS_GET_TIME (tm);
+	  EMACS_SET_SECS_USECS (preemption_period, sec, usec);
+	  EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+	}
+#endif
+
       /* Update W.  */
       update_begin (f);
       update_window (w, force_p);
@@ -4107,7 +4161,9 @@
 {
   struct glyph_matrix *desired_matrix = w->desired_matrix;
   int paused_p;
+#if !PERIODIC_PREEMPTION_CHECKING
   int preempt_count = baud_rate / 2400 + 1;
+#endif
   extern int input_pending;
   extern Lisp_Object do_mouse_tracking;
 #if GLYPH_DEBUG
@@ -4119,8 +4175,13 @@
   /* Check pending input the first time so that we can quickly return.  */
   if (redisplay_dont_pause)
     force_p = 1;
-  else
+#if PERIODIC_PREEMPTION_CHECKING
+  else if (NILP (Vredisplay_preemption_period))
+    force_p = 1;
+#else
+  else if (!force_p)
     detect_input_pending_ignore_squeezables ();
+#endif
 
   /* If forced to complete the update, or if no input is pending, do
      the update.  */
@@ -4192,9 +4253,22 @@
 	       detect_input_pending.  If it's done too often,
 	       scrolling large windows with repeated scroll-up
 	       commands will too quickly pause redisplay.  */
+#if PERIODIC_PREEMPTION_CHECKING
+	    if (!force_p)
+	      {
+		EMACS_TIME tm, dif;
+		EMACS_GET_TIME (tm);
+		EMACS_SUB_TIME (dif, preemption_next_check, tm);
+		if (EMACS_TIME_NEG_P (dif))
+		  {
+		    EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+		    detect_input_pending_ignore_squeezables ();
+		  }
+	      }
+#else
 	    if (!force_p && ++n_updated % preempt_count == 0)
 	      detect_input_pending_ignore_squeezables ();
-
+#endif
 	    changed_p |= update_window_line (w, vpos,
 					     &mouse_face_overwritten_p);
 
@@ -5145,11 +5219,16 @@
 
   if (redisplay_dont_pause)
     force_p = 1;
+#if PERIODIC_PREEMPTION_CHECKING
+  else if (NILP (Vredisplay_preemption_period))
+    force_p = 1;
+#else
   else if (!force_p && detect_input_pending_ignore_squeezables ())
     {
       pause = 1;
       goto do_pause;
     }
+#endif
 
   /* If we cannot insert/delete lines, it's no use trying it.  */
   if (!line_ins_del_ok)
@@ -5200,8 +5279,22 @@
 		}
 	    }
 
-	  if ((i - 1) % preempt_count == 0)
+#if PERIODIC_PREEMPTION_CHECKING
+	  if (!force_p)
+	    {
+	      EMACS_TIME tm, dif;
+	      EMACS_GET_TIME (tm);
+	      EMACS_SUB_TIME (dif, preemption_next_check, tm);
+	      if (EMACS_TIME_NEG_P (dif))
+		{
+		  EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
+		  detect_input_pending_ignore_squeezables ();
+		}
+	    }
+#else
+	  if (!force_p && (i - 1) % preempt_count == 0)
 	    detect_input_pending_ignore_squeezables ();
+#endif
 
 	  update_frame_line (f, i);
 	}
@@ -6936,7 +7029,14 @@
 	       doc: /* *Non-nil means update isn't paused when input is detected.  */);
   redisplay_dont_pause = 0;
 
-  /* Initialize `window-system', unless init_display already decided it.  */
+#if PERIODIC_PREEMPTION_CHECKING
+  DEFVAR_LISP ("redisplay-preemption-period", &Vredisplay_preemption_period,
+	       doc: /* *The period in seconds between checking for input during redisplay.
+If input is detected, redisplay is pre-empted, and the input is processed.
+If nil, never pre-empt redisplay.  */);
+  Vredisplay_preemption_period = make_float (0.10);
+#endif
+
 #ifdef CANNOT_DUMP
   if (noninteractive)
 #endif