comparison src/ui.c @ 15653:59a1ff689b4d v8.1.0834

patch 8.1.0834: GUI may wait too long before dealing with messages commit https://github.com/vim/vim/commit/e40b9d47bf8f8f716d3ef5a95c8ecbbdc0a501f9 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jan 27 16:55:47 2019 +0100 patch 8.1.0834: GUI may wait too long before dealing with messages Problem: GUI may wait too long before dealing with messages. Returning early may cause a mapping to time out. Solution: Use the waiting loop from Unix also for the GUI. (closes #3817, closes #3824)
author Bram Moolenaar <Bram@vim.org>
date Sun, 27 Jan 2019 17:00:07 +0100
parents 6f1c7e9a6393
children 2202ab00e9f9
comparison
equal deleted inserted replaced
15652:e987698f1397 15653:59a1ff689b4d
176 * it set got_int when it was mapped. */ 176 * it set got_int when it was mapped. */
177 if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state()) 177 if ((mapped_ctrl_c | curbuf->b_mapped_ctrl_c) & get_real_state())
178 ctrl_c_interrupts = FALSE; 178 ctrl_c_interrupts = FALSE;
179 } 179 }
180 180
181 /*
182 * Here we call gui_inchar() or mch_inchar(), the GUI or machine-dependent
183 * input function. The functionality they implement is like this:
184 *
185 * while (not timed out)
186 * {
187 * handle-resize;
188 * parse-queued-messages;
189 * if (waited for 'updatetime')
190 * trigger-cursorhold;
191 * ui_wait_for_chars_or_timer()
192 * if (character available)
193 * break;
194 * }
195 *
196 * ui_wait_for_chars_or_timer() does:
197 *
198 * while (not timed out)
199 * {
200 * if (any-timer-triggered)
201 * invoke-timer-callback;
202 * wait-for-character();
203 * if (character available)
204 * break;
205 * }
206 *
207 * wait-for-character() does:
208 * while (not timed out)
209 * {
210 * Wait for event;
211 * if (something on channel)
212 * read/write channel;
213 * else if (resized)
214 * handle_resize();
215 * else if (system event)
216 * deal-with-system-event;
217 * else if (character available)
218 * break;
219 * }
220 *
221 */
222
181 #ifdef FEAT_GUI 223 #ifdef FEAT_GUI
182 if (gui.in_use) 224 if (gui.in_use)
183 retval = gui_inchar(buf, maxlen, wtime, tb_change_cnt); 225 retval = gui_inchar(buf, maxlen, wtime, tb_change_cnt);
184 #endif 226 #endif
185 #ifndef NO_CONSOLE 227 #ifndef NO_CONSOLE
202 if (do_profiling == PROF_YES && wtime != 0) 244 if (do_profiling == PROF_YES && wtime != 0)
203 prof_inchar_exit(); 245 prof_inchar_exit();
204 #endif 246 #endif
205 return retval; 247 return retval;
206 } 248 }
249
250 #if defined(UNIX) || defined(FEAT_GUI) || defined(PROTO)
251 /*
252 * Common code for mch_inchar() and gui_inchar(): Wait for a while or
253 * indefinitely until characters are available, dealing with timers and
254 * messages on channels.
255 *
256 * "buf" may be NULL if the available characters are not to be returned, only
257 * check if they are available.
258 *
259 * Return the number of characters that are available.
260 * If "wtime" == 0 do not wait for characters.
261 * If "wtime" == n wait a short time for characters.
262 * If "wtime" == -1 wait forever for characters.
263 */
264 int
265 inchar_loop(
266 char_u *buf,
267 int maxlen,
268 long wtime, // don't use "time", MIPS cannot handle it
269 int tb_change_cnt,
270 int (*wait_func)(long wtime, int *interrupted, int ignore_input),
271 int (*resize_func)(int check_only))
272 {
273 int len;
274 int interrupted = FALSE;
275 int did_start_blocking = FALSE;
276 long wait_time;
277 long elapsed_time = 0;
278 #ifdef ELAPSED_FUNC
279 elapsed_T start_tv;
280
281 ELAPSED_INIT(start_tv);
282 #endif
283
284 /* repeat until we got a character or waited long enough */
285 for (;;)
286 {
287 /* Check if window changed size while we were busy, perhaps the ":set
288 * columns=99" command was used. */
289 if (resize_func != NULL)
290 resize_func(FALSE);
291
292 #ifdef MESSAGE_QUEUE
293 // Only process messages when waiting.
294 if (wtime != 0)
295 {
296 parse_queued_messages();
297 // If input was put directly in typeahead buffer bail out here.
298 if (typebuf_changed(tb_change_cnt))
299 return 0;
300 }
301 #endif
302 if (wtime < 0 && did_start_blocking)
303 // blocking and already waited for p_ut
304 wait_time = -1;
305 else
306 {
307 if (wtime >= 0)
308 wait_time = wtime;
309 else
310 // going to block after p_ut
311 wait_time = p_ut;
312 #ifdef ELAPSED_FUNC
313 elapsed_time = ELAPSED_FUNC(start_tv);
314 #endif
315 wait_time -= elapsed_time;
316 if (wait_time <= 0)
317 {
318 if (wtime >= 0)
319 // no character available within "wtime"
320 return 0;
321
322 // No character available within 'updatetime'.
323 did_start_blocking = TRUE;
324 if (trigger_cursorhold() && maxlen >= 3
325 && !typebuf_changed(tb_change_cnt))
326 {
327 // Put K_CURSORHOLD in the input buffer or return it.
328 if (buf == NULL)
329 {
330 char_u ibuf[3];
331
332 ibuf[0] = CSI;
333 ibuf[1] = KS_EXTRA;
334 ibuf[2] = (int)KE_CURSORHOLD;
335 add_to_input_buf(ibuf, 3);
336 }
337 else
338 {
339 buf[0] = K_SPECIAL;
340 buf[1] = KS_EXTRA;
341 buf[2] = (int)KE_CURSORHOLD;
342 }
343 return 3;
344 }
345
346 // There is no character available within 'updatetime' seconds:
347 // flush all the swap files to disk. Also done when
348 // interrupted by SIGWINCH.
349 before_blocking();
350 continue;
351 }
352 }
353
354 #ifdef FEAT_JOB_CHANNEL
355 if (wait_time < 0 || wait_time > 100L)
356 {
357 // Checking if a job ended requires polling. Do this at least
358 // every 100 msec.
359 if (has_pending_job())
360 wait_time = 100L;
361
362 // If there is readahead then parse_queued_messages() timed out and
363 // we should call it again soon.
364 if (channel_any_readahead())
365 wait_time = 10L;
366 }
367 #endif
368 #ifdef FEAT_BEVAL_GUI
369 if (p_beval && wait_time > 100L)
370 // The 'balloonexpr' may indirectly invoke a callback while waiting
371 // for a character, need to check often.
372 wait_time = 100L;
373 #endif
374
375 // Wait for a character to be typed or another event, such as the winch
376 // signal or an event on the monitored file descriptors.
377 if (wait_func(wait_time, &interrupted, FALSE))
378 {
379 // If input was put directly in typeahead buffer bail out here.
380 if (typebuf_changed(tb_change_cnt))
381 return 0;
382
383 // We might have something to return now.
384 if (buf == NULL)
385 // "buf" is NULL, we were just waiting, not actually getting
386 // input.
387 return input_available();
388
389 len = read_from_input_buf(buf, (long)maxlen);
390 if (len > 0)
391 return len;
392 continue;
393 }
394 // Timed out or interrupted with no character available.
395
396 #ifndef ELAPSED_FUNC
397 // estimate the elapsed time
398 elapsed_time += wait_time;
399 #endif
400
401 if ((resize_func != NULL && resize_func(TRUE))
402 #ifdef FEAT_CLIENTSERVER
403 || server_waiting()
404 #endif
405 #ifdef MESSAGE_QUEUE
406 || interrupted
407 #endif
408 || wait_time > 0
409 || (wtime < 0 && !did_start_blocking))
410 // no character available, but something to be done, keep going
411 continue;
412
413 // no character available or interrupted, return zero
414 break;
415 }
416 return 0;
417 }
418 #endif
207 419
208 #if defined(FEAT_TIMERS) || defined(PROTO) 420 #if defined(FEAT_TIMERS) || defined(PROTO)
209 /* 421 /*
210 * Wait for a timer to fire or "wait_func" to return non-zero. 422 * Wait for a timer to fire or "wait_func" to return non-zero.
211 * Returns OK when something was read. 423 * Returns OK when something was read.