An answer to another question suggests that supplying a timeout of 0.0 to read-event
(as the
optional SECONDS
parameter) will always return nil
immediately, and, if I'm reading the code in
Emacs' keyboard.c
correctly, even a (very) very small non-zero timeout could return nil
without
checking everywhere for an existing event.
Because input-pending-p
can return false positives, calling read-event
with a non-zero value for
SECONDS
to try to get that (nonexistant event) could cause a delay and still return nil
.
Practically, it seems like using a millisecond or two for SECONDS
should be fine, but it does feel
less tidy than if read-event
returned any available events even with a timout of 0.0.
Short of a locall Emacs build, is there a solution a particularly particular user might prefer?
The code @phils gave with his answer demonstrates this is not correct if "unread" events are
available in any of 3 queues. I've added code that suggests yet another event-queue is checked by
input-pending-p
that is skipped by read-event
when SECONDS
is 0.0.
My polling loop below is more complicated than I'd like, but I wanted to record all the relative event times. The quit key (C-g) will terminate.
The code starts calling read-event
with a SECONDS
value of 0.0, increasing it after 5 seconds.
It records when input-pending-p
first returns true, and then the time and SECONDS
value when
read-event
first returns non-nil.
For me, pressing a key before 5 seconds is up demonstrates that input-pending-p
can be true, but
until SECONDS
is increased to at least a little above 0.0, read-event
consistently returns
nil
.
(let* ((input-at) (read-at) (wait-to-try 0.0) (deadline (+ (float-time) 5.0)) (past-due))
(while 't
(setq past-due (- (float-time) deadline))
(when (and (not input-at) (input-pending-p)) (setq input-at past-due))
(when (not read-at)
(when (> past-due 0.0) (setq wait-to-try (* 0.001 past-due)))
(when (read-event nil nil wait-to-try) (setq read-at past-due)))
(message "past: %f in-p: %s in-at: %s wait: %s read-at %s"
past-due (input-pending-p) input-at wait-to-try read-at)
(redisplay)))
(or (read-event nil nil 0) (and (input-pending-p) (read-event nil nil 0.1)))
? Or maybe just theand
form. But I guess that's what you were playing with to begin with, when discussing the possibility of false-positives incurring the full delay. Hopefully someone with more knowledge than me will chip in.