Feedback needed: key timing, latency, delays

I would like to ask on opinions and experiences with the following problem(s).

Some advanced features of UHK, such as macros, write text actions, composite shortcuts or secondary roles cause UHK to produce compact sequences of key/scancode activations, that are sent in rapid sequences (i.e., just 1 millisecond apart), which is a frequent cause of problems since various programs don’t expect input that fast. This causes programs to either ignore some keypresses entirelly, or receive them in wrong order.

This can be alleviated either by inserting explicit delays into macros (press Ctrl, wait for 50 ms, then press C), or globally by setting keystrokeDelay 10 (which makes firmware wait 10 milliseconds whenever a USB report (any key action) is produced before producing next USB report).

Some cases:

  • RDP, or remote desktop protocol often misses modifiers from UHK mappings like Ctrl+c. Setting set keystrokeDelay 10 should solve this problem.

  • When actions are sent over different USB interfaces they often arrive in wrong order. For example Ctrl + mouse click. (This is probably a problem with Windows. I can’t reproduce this on Linux. More info needed.)

  • Garbled write action output, write "test" command output, or printStatus output. Some characters are missed, modifiers sometimes arrive in wrong order therefore affecting also previous or next character. In rare cases this produces a totally garbled output. Setting set keystrokeDelay 10 produces fairly reliable output.

  • Linux ignores mouse releases shorter than ~15 ms. Probably to cover up switch malfunctions or bouncing. This is a problem for touchpad doubletap and doubletap-to-hold features since touchpad needs to prolong presses to distinguish and properly apply these two actions. Currently, we add artificial delay of 20ms to solve this problem.

  • Games often just sample key states instead of queuing them and processing them in order. This is probably to account for various tapping speeds as a means to input various intensities. (Typically steering in a racing game controlled via a mechanical keyboard. Varying pressure of the taps while maintaining tapping frequency will vary the proportion of time the key is active or inactive, producing various degrees of steer.) This is a problem for secondary roles or macro tapKey events, as short 1 ms key activations are often missed. From my experience as much as 50ms are needed for a key (typically esc on a secondary role key) to be reliably registered.

I am writing this entire thing because I have been wondering if we should implement one of the following means of alleviating these problems:

  • Set keystrokeDelay to some reasonable value by default, e.g., 10 ms. (This clearly does not cover some of the cases as 10 ms is not sufficient.)

  • Implement some new mechanism that would prevent key activations shorter than a determined time, e.g., 50ms. (What exactly should this do? Affect just regular secondary roles? Or something else too?)(This clearly does not work for macros, as we clearly don’t want to slow down write actions to such a slow output. This would therefore be mostly useful for secondary roles.)

  • Something else? E.g., adding parameters to specific commands to make it easier to manually input needed delays in commands?

Some relevant technical aspects:

  • Setting keystrokeDelay to too high value can produce significant latency as it causes all pending actions to queue up if input is too fast. A 100 wmp typist can produce 100*5*2/60=17 usb report changes per second, meaning that UHK should not get overwhelmed with a keystrokeDelay set to up to some 50 ms, although at that value it will be already delaying some characters significantly in order to spread them evenly in time.

  • KeystrokeDelay values significantly higher than 10ms tend to slow down macroes (especially write action) too much.

  • Despite 1000 hz polling rate of the keyboard, real latency is around 15 ms due to delays on I2C communication, so setting keystrokeDelay to 10 ms should not be a too big a deal.

I don’t see a strong technical reason to not set keystrokeDelay to 10 ms by default. On the other hand, artificially slowing down the keyboard seems to me as a controversial thing to do, as some user groups (extremely fast typists, gamers) may be put off by this for entirelly subjective/psychological reasons.

So questions for you are:

  • What do you guys think about this?

  • Have you some experience with the above problems?

  • Do hou have keystrokeDelay set in your $onInit? Or do you have it deliberately not set?


Personally I think firmware should set as much as possible options, if they are consistent, implicitly, i.e. as default. Thus allowing customizing commands with parameters (third option) is a no go. How would I know which delay for command should I set? Also if it might depend on specific application (as I undersand) even this will not be enough.

So I think as first step is to set default keystrokeDelay to sane default. I already case across with this problem and have set keystrokeDelay 10 (can’t find issue, but this was your advise, problem with terminal, while it was considered fastest - kitty).

But as a final goal I see second option (implement some new mechanism that would prevent …). So I vote for second option, and first option as temporary solution (to not answer for new issues again and again to set keystrokeDelay to 10).

1 Like

Do you have any insight regarding what exactly the second option should do? I.e., to which features it should apply?

Good question :slight_smile: I, frankly speaking, don’t know. I thought you already have some draft solution in mind. For me personally keystrokeDelay 10 I think is enough (don’t play games or use RDP).

I don’t see some general solution. The best way I can come up with is to run code on UHK agent which will test delays in USB reports (whatever this means :slight_smile: ) against UHK keyboard (so agent kind of emulates applications). Then agent automatically adjust keystrokeDelay to appropriate values which will work reliably (on this computer with this USB slot).

The quesion is how to determine which app is running (have keyboard focus). I think it’s possible to have and even adjust keystrokeDelay per app (for example for game set 50ms). Probably this should be some kind of demon. But this definitely goes beyond firmware responsibitily. And not even sure that UHK have to try to solve these (not theirs) bugs.

Well, I would very much prefer to remain conservative. Setting global keystrokeDelay to values higher 10 ms, or change it adaptively depending on focused window is out of questions as far as my conscience goes.

As to specific proposal, It seems to me that simple secondary roles should have programmed in a 50 ms delay. Advanced secondary role should additionally trigger debouncing mode, therefore ensuring at least 50ms press length.

As to implementation details, it seems to me that this should probably be realised in a way which allows other keys to get ahead of such releases in the queue. (This means allowing events submitted into postponer queue to specify time in future, and then sort in all the appended events according to the submission time.)

Above means that macros would remain entirely untreated when it comes to the gaming scenario.

1 Like

I’m unaffected by this problem, and I’m fine with a default keystrokeDelay that isn’t zero as long as it aligns with user expectations and doesn’t disadvantage users such as quick typists.

1 Like

I only had the problem with the error log and personally would prefer to fix the problems only where they appear and not (potentially) introduce new ones due a workaround affecting every keypress.

In the case of the error log a new Agent version will offer a nicer way to show errors and warnings, so I personally would not introduce a general delay.

1 Like

It sounds to me you actually want aggregate statistics on how people use their keyboard, or at least how they have configured it. You could have Agent collect some data on the configuration of each keyboard (for values such as keystrokeDelay), and report them back (anonymised, and after asking users for permission, of course).

Asking in the forum will only get you a sample of users who actively participate here. It’s a start.

Well, asking may give me a small and strongly biased sample, but at least it tells me what the people actually think and why. I don’t think an aggregate statistic would be useful in this particular case at all.

From a wider perspective, I have been thinking about collecting feedback in some systematic fashion, either via surveys, or via collecting some analytic data, but:

  • never had a sufficiently strong reason to justify the effort. (It seems to me it would take quite a lot of effort.)
  • I don’t like the idea of just gathering data in the background. (Even if users are explicitly asked for a consent.)

Opt-in telemetry can be useful, and we may implement it in Agent eventually, but it’s not our priority.

The problem with consent is that is can be easily ‘forgotten to apply’, there were numerous cases when data where gathered even from users who directly opt-out this.

Also it is very easy to turn it on hiddenly (once the feature itsefl it implemented), on update, etc.
ESPECIALLY when it comes to keyboard! It’s ready spyware and key logger.

So if this feature will be implemented it must be thought very deeply beforehand.


I’m wondering if there is a such problem (I see it on my WezTerminal) with weird symbols appear (so I have to set keystrokeDelay) why I don’t see any such problems on my usual keyboard?

I expect I should see the same problem with any keyboard if type fast, but I dont.

You mean weird symbols appearing out of nowhere? Or appearing as a consequence of a garbled (e.g.) ALT code macro?

Former case should definitely not be happening. If the latter case, then do all your keyboards (or even fingers) emit scancodes (press keys) at a pace of 1 scancode (key) every 1 ms?

I hold key E which triggers secondary role Fn3 and press (.
If I press multiple ( times (while holding E) I get sometimes 9.

I don’t even know where that 9 comes from. Didn’t experience that previously.

I think the second case. I initially run (macro?) by pressing key and then press another key. Seems to me like a bug? That’s my onInit. Or am I doing something wrong again?))))

set emergencyKey 64
set keystrokeDelay 5

set keystroke backspace
set keystroke delete

set module.keycluster.navigationMode.base media

set autoRepeatDelay 500
set autoRepeatRate 20

set secondaryRole.defaultStrategy advanced
set secondaryRole.advanced.timeout 500
set secondaryRole.advanced.timeoutAction secondary
set secondaryRole.advanced.safetyMargin 0
set secondaryRole.advanced.triggerByRelease 1
set secondaryRole.advanced.doubletapToPrimary 0

switchKeymap EXP
exec configureTrackpoint

You know, ( on english keyboard corresponds to press shift, tap 9 key, release shift. UHK does this with just 1 ms inbetween these actions (or keystrokeDelay ms, if keystrokeDelay is non-zero), so if the software is not capable of processing these three usb reports fast enough and in correct order, it sometimes misses the shift and produces just 9.

That is expected, and yes that’s exactly what this thread is about.

Now I only don’t understand that part about other keyboards: do your other keyboards support macros or key combos so that they can send shortcuts like shift-9 with a single key tap?

I got
Screenshot from 2023-10-06 19-26-16
for this

It’s like something wrong with ifShif or suppressMods, at least previously it worked fine.

Got it! Thanks for insights! Will increase keystrokeDelay

1 Like

If you wish to test the above hypothesis on this case, then please change the macro to:

ifShift suppressMods tapkey a 
ifNotShift tapKey :

and retest.

(The hypothesis predicts that now you will still be getting just ;s and :s, no as in there, and therefore ifShift is fine.)

No, just usual keyboard. I thought it should be reproducible on usual keyboard if fast typing.
From your answer I understand that’s not the case.

1 Like