From d012c62b91b0f8f549563db81fbbfabaf030c56c Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Mon, 12 Jun 2006 22:32:47 +0000 Subject: 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. --- src/dispnew.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 4 deletions(-) (limited to 'src/dispnew.c') diff --git a/src/dispnew.c b/src/dispnew.c index cbe0e3fb52..e205105536 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -192,6 +192,28 @@ struct window *frame_row_to_window P_ ((struct window *, int)); 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 @@ update_frame (f, force_p, inhibit_hairy_id_p) 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 @@ update_single_window (w, force_p) /* 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 @@ update_window (w, force_p) { 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 @@ update_window (w, force_p) /* 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 @@ update_window (w, force_p) 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 @@ update_frame_1 (f, force_p, inhibit_id_p) 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 @@ update_frame_1 (f, force_p, inhibit_id_p) } } - 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 @@ See `buffer-display-table' for more information. */); 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 -- cgit v1.2.3 From f222369e0aa7afbea32c037c40eb84da809744f2 Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Tue, 13 Jun 2006 22:06:22 +0000 Subject: (sit_for): Undo 2006-06-01 change. Instead, a negative time forces redisplay even when input is available. (Fsit_for): Doc fix. --- src/dispnew.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/dispnew.c') diff --git a/src/dispnew.c b/src/dispnew.c index e205105536..43f86a32f4 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -6495,15 +6495,22 @@ Lisp_Object sit_for (sec, usec, reading, display, initial_display) int sec, usec, reading, display, initial_display; { + int preempt = (sec >= 0) || (sec == 0 && usec >= 0); + swallow_events (display); - if ((detect_input_pending_run_timers (display) - && !redisplay_dont_pause) + if ((detect_input_pending_run_timers (display) && preempt) || !NILP (Vexecuting_kbd_macro)) return Qnil; if (initial_display) - redisplay_preserve_echo_area (2); + { + int count = SPECPDL_INDEX (); + if (!preempt) + specbind (Qredisplay_dont_pause, Qt); + redisplay_preserve_echo_area (2); + unbind_to (count, Qnil); + } if (sec == 0 && usec == 0) return Qt; @@ -6529,8 +6536,7 @@ Redisplay is preempted as always if input arrives, and does not happen if input is available before it starts. Value is t if waited the full time with no input arriving. -Redisplay will occur even when input is available if you bind -`redisplay-dont-pause' to a non-nil value. +Redisplay will occur even when input is available if SECONDS is negative. An obsolete but still supported form is \(sit-for SECONDS &optional MILLISECONDS NODISP) -- cgit v1.2.3 From 993d4ab6ee5272848d7011f1bbf3c8f5709c36ed Mon Sep 17 00:00:00 2001 From: "Kim F. Storm" Date: Sat, 17 Jun 2006 00:11:59 +0000 Subject: (update_frame): Check for input pending on entry. (update_window, update_frame_1): Break loop if input is detected. --- src/dispnew.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/dispnew.c') diff --git a/src/dispnew.c b/src/dispnew.c index 43f86a32f4..df92fc395d 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -3849,6 +3849,12 @@ update_frame (f, force_p, inhibit_hairy_id_p) double p = XFLOATINT (Vredisplay_preemption_period); int sec, usec; + if (detect_input_pending_ignore_squeezables ()) + { + paused_p = 1; + goto do_pause; + } + sec = (int) p; usec = (p - sec) * 1000000; @@ -3936,6 +3942,7 @@ update_frame (f, force_p, inhibit_hairy_id_p) #endif } + do_pause: /* Reset flags indicating that a window should be updated. */ set_window_update_flags (root_window, 0); @@ -4262,7 +4269,8 @@ update_window (w, force_p) if (EMACS_TIME_NEG_P (dif)) { EMACS_ADD_TIME (preemption_next_check, tm, preemption_period); - detect_input_pending_ignore_squeezables (); + if (detect_input_pending_ignore_squeezables ()) + break; } } #else @@ -5288,7 +5296,8 @@ update_frame_1 (f, force_p, inhibit_id_p) if (EMACS_TIME_NEG_P (dif)) { EMACS_ADD_TIME (preemption_next_check, tm, preemption_period); - detect_input_pending_ignore_squeezables (); + if (detect_input_pending_ignore_squeezables ()) + break; } } #else -- cgit v1.2.3