Mercurial > vim
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. |