ianhenderson.org / 2024 september 10
For a recent project, I found myself wanting to send keyboard events over UDP. Since UDP doesn't guarantee delivery, sending each event as a UDP message isn't sufficient: keystrokes can be lost. Even worse, if a key down event is transmitted but the corresponding key up event is lost, a key can get "stuck down" until the key is pressed again.
The solution I arrived at is to send a fixed-length queue of events in each UDP message. New events appear at the front of the queue, and older events are shifted off of the end. Event timestamps allow the receiver to tell which events it hasn't seen yet.
Key down events are treated specially—they remain in the queue until the key is released. This lets the receiver compare the keys it thinks are held with the keys that are held according to the incoming queue, dispatching key up events for any discrepancies. Keeping key down events in the queue prevents key up events from being sent while the key is still held.
The sender maintains a single queue. When a key is pressed, the sender adds the event to the queue and sends the queue as a UDP message. The steps for adding an event are described below. The process is complicated slightly by the need to ensure lone key down events are kept in the queue. The fixed queue length will be denoted N. The queue is initialized with events that are neither key up events nor key down events and that have a timestamp in the past.
The sender adds an event being added to the queue by following these steps:
On the receiving side, the previous queue is kept and compared with the incoming queue as it arrives over the network. To dispatch key events from the incoming queue, key up events are first generated for previously-held keys which do not have any events in the incoming queue. Then any newly-seen events in the incoming queue are dispatched.
More precisely, the receiver dispatches events by following these steps:
Note that it's possible for multiple key down events to be dispatched without a key up in between. This can happen when you hold down a key with key repeat enabled. If you want to have truly balanced events, check the held keycodes set before dispatching key down events. If the sender is always sending balanced events, this situation can only happen if the receiver missed a key up event, so it would also be possible to generate the missing event in this case.
Here is a JavaScript implementation you can play around with. Pressing keys will add them to the sender's buffer. The buffer is sent every 100ms.
|
|
|