Accessibility · Assistive Technology

Debounce, Dwell, and Key-Repeat Filtering

How assistive input systems distinguish a deliberate activation from switch bounce, tremor, and held keys, and how dwell and repeat timing are computed.

A keyboard and a mouse are assumed to be clean: one press is one action, one movement is one intent. Assistive inputs break that assumption. A switch bounces electrically, a muscle tremor presses and releases a button many times in an instant, a held key fires a stream of repeat events, and a gaze point drifts before it settles. The software between the physical input and the application must therefore do signal processing that mainstream input paths take for granted. That processing is built from three primitives: debounce, dwell, and repeat filtering.

Debounce separates one press from many

A mechanical switch does not close cleanly. When its contacts meet, they open and close several times over a few milliseconds before settling, a phenomenon called bounce. If the input layer reported every transition, a single press would register as a burst of press-release pairs, and a switch user would select a scanning target several times in the space of one physical action.

Debounce is the countermeasure, and there are two classic forms. Hardware debounce puts a low-pass filter on the contacts, typically a resistor-capacitor network, so the bouncing transitions are smoothed before they reach a digital input. Software debounce samples the input at intervals and requires the level to be stable for a minimum duration before reporting a change: the input must be continuously closed for, say, 10 to 50 milliseconds before it is accepted as a press, and continuously open for the same duration before it is accepted as a release.

Software debounce has a parameter that hardware fixes, and that parameter is a genuine trade-off. A long debounce interval rejects more bounce but adds latency to every press, because the system waits for stability before acting. A short interval responds faster but risks letting a bounce through as a spurious second press. The interval must be set shorter than the user’s fastest intended double action and longer than the bounce period, and the two bounds are uncomfortably close for a user with a fast single-switch technique.

Debounce also interacts with tremor. A user with a hand tremor produces not microsecond-scale bounce but repeated press-release cycles over hundreds of milliseconds. Pure debounce cannot tell a tremor artifact from a deliberate double press, because both are stable-level changes separated by tens of milliseconds. The next primitive, timing-based filtering, is what distinguishes them.

Dwell turns sustained presence into a click

Dwell is the technique of treating “the pointer stayed still long enough” as a click. A user moves the pointer to a target and holds it there; when the pointer has been stationary within a small radius for a configured dwell time, the system activates the target. Dwell replaces the click, which a user with limited or no button control cannot perform.

The dwell algorithm has two thresholds that must both be met. The first is spatial: the pointer must remain within a radius, often a few to a couple of dozen pixels, for the entire dwell interval. The second is temporal: the interval itself, typically between a fraction of a second and a couple of seconds, must elapse without the pointer leaving the radius. Any movement beyond the radius restarts the timer. The user sees progress feedback, usually a shrinking ring, so the pending activation is predictable and can be cancelled by moving away.

The trade-off in dwell time mirrors the debounce trade-off. A short dwell makes selection fast but risks activating a target the user was merely passing over, because the pointer lingers for a moment en route. A long dwell is safe but slow. The correct value depends on the user’s control accuracy: a user with a precise gaze or head pointer can use a short dwell, while a user with a coarser control needs a longer one to avoid misfires. Dwell is also the mechanism behind gaze-based selection, which a later article examines in detail.

The restart-on-movement rule is the subtle part. It means the dwell timer does not accumulate partial credit; any movement outside the radius discards the accumulated time. This is deliberate, because partial credit would make the activation point depend on the path the pointer took, not on whether it was actually resting on the target. The cost is that a user with a small persistent drift may never accumulate a full dwell interval, which is why the radius and the interval are exposed as separate settings.

Key-repeat filtering distinguishes hold from press

A held key generates a repeat: the operating system emits an initial key-down, then a stream of repeated key-down events at a fixed rate after a delay, until the key is released. For a user typing with a single switch, this is a feature when it means “type this character several times” and a defect when it means “I pressed once but the system thinks I held”. The input layer for assistive use filters repeats so that a single deliberate press cannot multiply into several.

The filter is a combination of a delay and a rate. After a key-down, the system ignores the key for a repeat-delay interval; if the key is still down after that interval, it begins emitting repeats at the repeat rate. For assistive input, both the delay and the rate are lengthened far beyond the defaults, or repeat is disabled entirely, because the user’s physical hold is not reliably distinguishable from a long press caused by difficulty releasing the switch.

The distinction that matters is between a press-and-hold that the user intends as a single long action and a press that was simply slow to release. The filter cannot know intent, so it uses a timeout: a press that outlasts a configured threshold is treated as a hold, and anything shorter as a single activation. This threshold, again, sits between the user’s fastest intentional hold and the slowest accidental lingering release, and it is the same kind of awkward interval as the debounce and dwell times.

The three timers interact

The three primitives are not independent; they are layered, and their thresholds compose. A switch press first passes through debounce, which delays its recognition. Then the recognized press is classified against the hold threshold. Then, if the input drives a scanning or dwell interface, the press triggers a scan selection whose own timing is a further layer. The total latency from physical action to application effect is the sum of all the thresholds in the path, and each threshold is a knob the user or the system has set.

This composition is why tuning an assistive input is hard, and why it is done per user rather than per device. The optimal debounce interval depends on the switch’s electrical behaviour, the optimal hold threshold on the user’s motor control, and the optimal scan or dwell time on the user’s reaction speed. They are orthogonal parameters coupled only by the requirement that the total latency stay tolerable, and a change to one propagates to the perceived speed of the whole path.

Failure modes

A debounce interval too long makes the interface feel sluggish and can eat a quick double activation. A dwell radius too tight makes selection impossible for a drifting pointer. A hold threshold too short turns every slow press into an unintended hold, and one too long makes deliberate holds require an exaggerated press duration. The common root is the same in every case: the system is inferring intent from timing, and timing is the one channel where the user’s physical reality and the system’s assumptions can diverge silently. There is no correctness condition to satisfy, only a trade-off to tune, and the failure is not a bug but a mis-setting.

These timing primitives are the substrate under every higher assistive mechanism. Scanning from the switch-access article runs on debounced presses; gaze selection runs on dwell; and text entry runs on repeat filtering. The three timers are the price of translating a noisy, slow, variable physical signal into the clean discrete events that applications expect.

References

  1. WAI-ARIA 1.2 — W3C
  2. Understanding SC 2.1.1: Keyboard — W3C
  3. Fitts's law — Wikipedia