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)))