* src/keyboard.c (input_was_pending): New var.

(read_char): Use it to make sure we only skip redisplay when we can't
keep up with the repeat rate.
This commit is contained in:
Stefan Monnier 2014-12-17 21:03:30 -05:00
parent ec10ba2792
commit 9e77c1b7bc
2 changed files with 58 additions and 1 deletions

View file

@ -1,3 +1,9 @@
2014-12-18 Stefan Monnier <monnier@iro.umontreal.ca>
* keyboard.c (input_was_pending): New var.
(read_char): Use it to make sure we only skip redisplay when we can't
keep up with the repeat rate.
2014-12-17 Stefan Monnier <monnier@iro.umontreal.ca>
* keyboard.c (swallow_events): Don't redisplay if there's input pending.

View file

@ -273,6 +273,54 @@ static FILE *dribble;
/* True if input is available. */
bool input_pending;
/* True if more input was available last time we read an event.
Since redisplay can take a significant amount of time and is not
indispensible to perform the user's commands, when input arrives
"too fast", Emacs skips redisplay. More specifically, if the next
command has already been input when we finish the previous command,
we skip the intermediate redisplay.
This is useful to try and make sure Emacs keeps up with fast input
rates, such as auto-repeating keys. But in some cases, this proves
too conservative: we may end up disabling redisplay for the whole
duration of a key repetition, even though we could afford to
redisplay every once in a while.
So we "sample" the input_pending flag before running a command and
use *that* value after running the command to decide whether to
skip redisplay or not. This way, we only skip redisplay if we
really can't keep up with the repeat rate.
This only makes a difference if the next input arrives while running the
command, which is very unlikely if the command is executed quickly.
IOW this tends to avoid skipping redisplay after a long running command
(which is a case where skipping redisplay is not very useful since the
redisplay time is small compared to the time it took to run the command).
A typical use case is when scrolling. Scrolling time can be split into:
- Time to do jit-lock on the newly displayed portion of buffer.
- Time to run the actual scroll command.
- Time to perform the redisplay.
Jit-lock can happen either during the command or during the redisplay.
In the most painful cases, the jit-lock time is the one that dominates.
Also jit-lock can be tweaked (via jit-lock-defer) to delay its job, at the
cost of temporary inaccuracy in display and scrolling.
So without input_was_pending, what typically happens is the following:
- when the command starts, there's no pending input (yet).
- the scroll command triggers jit-lock.
- during the long jit-lock time the next input arrives.
- at the end of the command, we check input_pending and hence decide to
skip redisplay.
- we read the next input and start over.
End result: all the hard work of jit-locking is "wasted" since redisplay
doesn't actually happens (at least not before the input rate slows down).
With input_was_pending redisplay is still skipped if Emacs can't keep up
with the input rate, but if it can keep up just enough that there's no
input_pending when we begin the command, then redisplay is not skipped
which results in better feedback to the user. */
static bool input_was_pending;
/* Circular buffer for pre-read keyboard input. */
static struct input_event kbd_buffer[KBD_BUFFER_SIZE];
@ -2585,8 +2633,10 @@ read_char (int commandflag, Lisp_Object map,
swallow_events (false); /* May clear input_pending. */
/* Redisplay if no pending input. */
while (!input_pending)
while (!(input_pending
&& (input_was_pending || !redisplay_dont_pause)))
{
input_was_pending = input_pending;
if (help_echo_showing_p && !EQ (selected_window, minibuf_window))
redisplay_preserve_echo_area (5);
else
@ -3255,6 +3305,7 @@ read_char (int commandflag, Lisp_Object map,
exit:
RESUME_POLLING;
input_was_pending = input_pending;
RETURN_UNGCPRO (c);
}