comparison src/dispnew.c @ 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 623f01d9e470
children a8cbcce39bd0
comparison
equal deleted inserted replaced
71322:35554e4f7699 71323:e882f189c3af
190 for debugging and for a future implementation of EDT-like 190 for debugging and for a future implementation of EDT-like
191 scrolling. */ 191 scrolling. */
192 192
193 int redisplay_dont_pause; 193 int redisplay_dont_pause;
194 194
195 /* Define PERIODIC_PREEMPTION_CHECKING to 1, if micro-second timers
196 are supported, so we can check for input during redisplay at
197 regular intervals. */
198 #ifdef EMACS_HAS_USECS
199 #define PERIODIC_PREEMPTION_CHECKING 1
200 #else
201 #define PERIODIC_PREEMPTION_CHECKING 0
202 #endif
203
204 #if PERIODIC_PREEMPTION_CHECKING
205
206 /* If a number (float), check for user input every N seconds. */
207
208 Lisp_Object Vredisplay_preemption_period;
209
210 /* Redisplay preemption timers. */
211
212 static EMACS_TIME preemption_period;
213 static EMACS_TIME preemption_next_check;
214
215 #endif
216
195 /* Nonzero upon entry to redisplay means do not assume anything about 217 /* Nonzero upon entry to redisplay means do not assume anything about
196 current contents of actual terminal frame; clear and redraw it. */ 218 current contents of actual terminal frame; clear and redraw it. */
197 219
198 int frame_garbaged; 220 int frame_garbaged;
199 221
3818 { 3840 {
3819 /* 1 means display has been paused because of pending input. */ 3841 /* 1 means display has been paused because of pending input. */
3820 int paused_p; 3842 int paused_p;
3821 struct window *root_window = XWINDOW (f->root_window); 3843 struct window *root_window = XWINDOW (f->root_window);
3822 3844
3845 #if PERIODIC_PREEMPTION_CHECKING
3846 if (!force_p && NUMBERP (Vredisplay_preemption_period))
3847 {
3848 EMACS_TIME tm;
3849 double p = XFLOATINT (Vredisplay_preemption_period);
3850 int sec, usec;
3851
3852 sec = (int) p;
3853 usec = (p - sec) * 1000000;
3854
3855 EMACS_GET_TIME (tm);
3856 EMACS_SET_SECS_USECS (preemption_period, sec, usec);
3857 EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
3858 }
3859 #endif
3860
3823 if (FRAME_WINDOW_P (f)) 3861 if (FRAME_WINDOW_P (f))
3824 { 3862 {
3825 /* We are working on window matrix basis. All windows whose 3863 /* We are working on window matrix basis. All windows whose
3826 flag must_be_updated_p is set have to be updated. */ 3864 flag must_be_updated_p is set have to be updated. */
3827 3865
3949 { 3987 {
3950 struct frame *f = XFRAME (WINDOW_FRAME (w)); 3988 struct frame *f = XFRAME (WINDOW_FRAME (w));
3951 3989
3952 /* Record that this is not a frame-based redisplay. */ 3990 /* Record that this is not a frame-based redisplay. */
3953 set_frame_matrix_frame (NULL); 3991 set_frame_matrix_frame (NULL);
3992
3993 #if PERIODIC_PREEMPTION_CHECKING
3994 if (!force_p && NUMBERP (Vredisplay_preemption_period))
3995 {
3996 EMACS_TIME tm;
3997 double p = XFLOATINT (Vredisplay_preemption_period);
3998 int sec, usec;
3999
4000 sec = (int) p;
4001 usec = (p - sec) * 1000000;
4002
4003 EMACS_GET_TIME (tm);
4004 EMACS_SET_SECS_USECS (preemption_period, sec, usec);
4005 EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
4006 }
4007 #endif
3954 4008
3955 /* Update W. */ 4009 /* Update W. */
3956 update_begin (f); 4010 update_begin (f);
3957 update_window (w, force_p); 4011 update_window (w, force_p);
3958 update_end (f); 4012 update_end (f);
4105 struct window *w; 4159 struct window *w;
4106 int force_p; 4160 int force_p;
4107 { 4161 {
4108 struct glyph_matrix *desired_matrix = w->desired_matrix; 4162 struct glyph_matrix *desired_matrix = w->desired_matrix;
4109 int paused_p; 4163 int paused_p;
4164 #if !PERIODIC_PREEMPTION_CHECKING
4110 int preempt_count = baud_rate / 2400 + 1; 4165 int preempt_count = baud_rate / 2400 + 1;
4166 #endif
4111 extern int input_pending; 4167 extern int input_pending;
4112 extern Lisp_Object do_mouse_tracking; 4168 extern Lisp_Object do_mouse_tracking;
4113 #if GLYPH_DEBUG 4169 #if GLYPH_DEBUG
4114 /* Check that W's frame doesn't have glyph matrices. */ 4170 /* Check that W's frame doesn't have glyph matrices. */
4115 xassert (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w)))); 4171 xassert (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))));
4117 #endif 4173 #endif
4118 4174
4119 /* Check pending input the first time so that we can quickly return. */ 4175 /* Check pending input the first time so that we can quickly return. */
4120 if (redisplay_dont_pause) 4176 if (redisplay_dont_pause)
4121 force_p = 1; 4177 force_p = 1;
4122 else 4178 #if PERIODIC_PREEMPTION_CHECKING
4179 else if (NILP (Vredisplay_preemption_period))
4180 force_p = 1;
4181 #else
4182 else if (!force_p)
4123 detect_input_pending_ignore_squeezables (); 4183 detect_input_pending_ignore_squeezables ();
4184 #endif
4124 4185
4125 /* If forced to complete the update, or if no input is pending, do 4186 /* If forced to complete the update, or if no input is pending, do
4126 the update. */ 4187 the update. */
4127 if (force_p || !input_pending || !NILP (do_mouse_tracking)) 4188 if (force_p || !input_pending || !NILP (do_mouse_tracking))
4128 { 4189 {
4190 4251
4191 /* We'll have to play a little bit with when to 4252 /* We'll have to play a little bit with when to
4192 detect_input_pending. If it's done too often, 4253 detect_input_pending. If it's done too often,
4193 scrolling large windows with repeated scroll-up 4254 scrolling large windows with repeated scroll-up
4194 commands will too quickly pause redisplay. */ 4255 commands will too quickly pause redisplay. */
4256 #if PERIODIC_PREEMPTION_CHECKING
4257 if (!force_p)
4258 {
4259 EMACS_TIME tm, dif;
4260 EMACS_GET_TIME (tm);
4261 EMACS_SUB_TIME (dif, preemption_next_check, tm);
4262 if (EMACS_TIME_NEG_P (dif))
4263 {
4264 EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
4265 detect_input_pending_ignore_squeezables ();
4266 }
4267 }
4268 #else
4195 if (!force_p && ++n_updated % preempt_count == 0) 4269 if (!force_p && ++n_updated % preempt_count == 0)
4196 detect_input_pending_ignore_squeezables (); 4270 detect_input_pending_ignore_squeezables ();
4197 4271 #endif
4198 changed_p |= update_window_line (w, vpos, 4272 changed_p |= update_window_line (w, vpos,
4199 &mouse_face_overwritten_p); 4273 &mouse_face_overwritten_p);
4200 4274
4201 /* Mark all rows below the last visible one in the current 4275 /* Mark all rows below the last visible one in the current
4202 matrix as invalid. This is necessary because of 4276 matrix as invalid. This is necessary because of
5143 if (preempt_count <= 0) 5217 if (preempt_count <= 0)
5144 preempt_count = 1; 5218 preempt_count = 1;
5145 5219
5146 if (redisplay_dont_pause) 5220 if (redisplay_dont_pause)
5147 force_p = 1; 5221 force_p = 1;
5222 #if PERIODIC_PREEMPTION_CHECKING
5223 else if (NILP (Vredisplay_preemption_period))
5224 force_p = 1;
5225 #else
5148 else if (!force_p && detect_input_pending_ignore_squeezables ()) 5226 else if (!force_p && detect_input_pending_ignore_squeezables ())
5149 { 5227 {
5150 pause = 1; 5228 pause = 1;
5151 goto do_pause; 5229 goto do_pause;
5152 } 5230 }
5231 #endif
5153 5232
5154 /* If we cannot insert/delete lines, it's no use trying it. */ 5233 /* If we cannot insert/delete lines, it's no use trying it. */
5155 if (!line_ins_del_ok) 5234 if (!line_ins_del_ok)
5156 inhibit_id_p = 1; 5235 inhibit_id_p = 1;
5157 5236
5198 sleep (outq / baud_rate); 5277 sleep (outq / baud_rate);
5199 } 5278 }
5200 } 5279 }
5201 } 5280 }
5202 5281
5203 if ((i - 1) % preempt_count == 0) 5282 #if PERIODIC_PREEMPTION_CHECKING
5283 if (!force_p)
5284 {
5285 EMACS_TIME tm, dif;
5286 EMACS_GET_TIME (tm);
5287 EMACS_SUB_TIME (dif, preemption_next_check, tm);
5288 if (EMACS_TIME_NEG_P (dif))
5289 {
5290 EMACS_ADD_TIME (preemption_next_check, tm, preemption_period);
5291 detect_input_pending_ignore_squeezables ();
5292 }
5293 }
5294 #else
5295 if (!force_p && (i - 1) % preempt_count == 0)
5204 detect_input_pending_ignore_squeezables (); 5296 detect_input_pending_ignore_squeezables ();
5297 #endif
5205 5298
5206 update_frame_line (f, i); 5299 update_frame_line (f, i);
5207 } 5300 }
5208 } 5301 }
5209 5302
6934 7027
6935 DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause, 7028 DEFVAR_BOOL ("redisplay-dont-pause", &redisplay_dont_pause,
6936 doc: /* *Non-nil means update isn't paused when input is detected. */); 7029 doc: /* *Non-nil means update isn't paused when input is detected. */);
6937 redisplay_dont_pause = 0; 7030 redisplay_dont_pause = 0;
6938 7031
6939 /* Initialize `window-system', unless init_display already decided it. */ 7032 #if PERIODIC_PREEMPTION_CHECKING
7033 DEFVAR_LISP ("redisplay-preemption-period", &Vredisplay_preemption_period,
7034 doc: /* *The period in seconds between checking for input during redisplay.
7035 If input is detected, redisplay is pre-empted, and the input is processed.
7036 If nil, never pre-empt redisplay. */);
7037 Vredisplay_preemption_period = make_float (0.10);
7038 #endif
7039
6940 #ifdef CANNOT_DUMP 7040 #ifdef CANNOT_DUMP
6941 if (noninteractive) 7041 if (noninteractive)
6942 #endif 7042 #endif
6943 { 7043 {
6944 Vwindow_system = Qnil; 7044 Vwindow_system = Qnil;