About fifteen years ago I used a key repeat enhancment program for some version
of DOS called "Hyperkey". It did something both smart and simple that I haven't
seen since, and that I'd like to see again.
The problem is as follows: Imagine you have an X app that is slow to accept
keyboard input. Now, press and hold the "u" key for five seconds. Release "u".
Now, what most people would want is that as soon as you let go of the "u" key,
the app stops printing "u"s. What happens in reality is that X has been
queueing up "u"s for five seconds, and it won't stop delivering the enqueued
"u"s to the app until the app has eaten all of them.
If I've set the key repeat speed to one repetition each 50ms, X will enqueue
20*5=100 "u"s in five secs. If the app eats one "u" per second, I won't be able
to type anything else for about 100 seconds. Bad.
The way Hyperkey worked however was that:
1. If a user types one character, enqueue it unconditionally.
2. If a user presses and holds any key, don't enqueue it at all. Instead, give
the app one of that key when the app asks for it, but no more often than the key
repeat setting allows.
The effect of this is that in the above example, when I press and hold "u" for
five secs, the queue will be empty when I release the "u" key. Thus, the app
behaves as we want.
Having tried this in practice, I can assure you it works very well, well enough
for me to remember it for fifteen years :-).
Created attachment 2740 [details]
Repro: A GTK+ app with a slow text field
Here's a GTK+ app (build instructions within) with a text field that sleeps for
0,5s after each keypress. Run it, activate the "Slow" text field, press and
hold "u" for a while.
Currently the app becomes unusable until it has swallowed all the buffered
With a fix for this Enhancement request in place, the same app should stop
adding "u"s to the text field when I release "u".
Unfortunately, the X server sends the key events to the application as it
generates them and has no way of knowing how fast the application is
processing them. Thus, without a protocol change, I think the only way
to fix this is client-side, though that could possibly be in libX11, the
client toolkit or the client application itself. I'm not sure where the
best place is, though I'd lean towards the toolkits.
When XKB is active, clients can request to have auto-repeat generated
events marked differently, so it could check the timestamps on auto-repeat
events and discard those whose timestamps are beyond a certain threshold
from the current time.
If possible I'd like to put this before the toolkit comes in, as that would make
it work for any toolkit. Client side is fine.
So how does a client ask for the next event? I assume that's where one would
want to put in a filter for this.
Note that I haven't done any hacking on X prior to this, so if I give the
impression that I don't know even basic stuff, that's probably correct.
Sorry about the phenomenal bug spam, guys. Adding xorg-team@ to the QA contact so bugs don't get lost in future.
(In reply to comment #3)
> If possible I'd like to put this before the toolkit comes in, as that would
> it work for any toolkit. Client side is fine.
> So how does a client ask for the next event? I assume that's where one would
> want to put in a filter for this.
> Note that I haven't done any hacking on X prior to this, so if I give the
> impression that I don't know even basic stuff, that's probably correct.
this happens in libx11, with XNextEvent. unfortunately the details are quite abstract, and i can assure you that any attempt would almost certainly collapse the incredibly flimsy house of cards that is our input system. due to the nature (server pushes events out to the clients), there's really not much you can do on an xlib level. the individual toolkits could certainly peek ahead in the event queue, and drop all pending presses as soon as a release hits the queue, but anything you do in xlib is likely to break things horribly.
-> notourbug; recommend taking it up with gtk/qt