]> git.eshelyaron.com Git - emacs.git/commitdiff
* src/keyboard.c (input_was_pending): New var.
authorStefan Monnier <monnier@iro.umontreal.ca>
Thu, 18 Dec 2014 02:03:30 +0000 (21:03 -0500)
committerStefan Monnier <monnier@iro.umontreal.ca>
Thu, 18 Dec 2014 02:03:30 +0000 (21:03 -0500)
(read_char): Use it to make sure we only skip redisplay when we can't
keep up with the repeat rate.

src/ChangeLog
src/keyboard.c

index 01653de22eda9193c737181d187056c77e56bec3..16e99aec99aba0b1f99d1547de296f08359b5af2 100644 (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.
index 9e12f590c57912028d37980c8547681e725f27d1..d76a8fcb78397c9a852d6b0574fe2e094a7fa481 100644 (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);
 }