Timing of `write` vs. `tapKeySeq`?

My question:

What is different in how the UHK firmware produces keystrokes between the write and tapKeySeq commands?


Let’s configure three macros:


suppressMods tapKeySeq m h a j f d c h


suppressMods write mhajfdch


I have bound these macros to fn+1, fn+2, and fn+3.

In $onInit, I have set:

set keystrokeDelay 30

All three macros produce the same result when used directly with a Windows laptop. They type my username mhantsch on a Colemak keyboard (using weird letters because of reverse Colemak translation).

Now, I have activated home-row mods using Kanata on my Windows host. Amongst other things, Kanata analyses the timing of key-presses and -releases to figure out whether I am intending to activate mods (secondary), or type letters (primary).

When I use the macros to type my username, some macros trigger homerow mods. Fine, I might expect that. But they are not activated for the macro that uses tapKeySeq. Why is that different? fn+1 types the word mhantsch fine. The other two macros type a few characters and also start popping up menu items or dialogues, so they clearly activate some Ctrl or Alt combinations.

This leads me to my question:

What is different between write and tapKeySeq how the UHK firmware produces keystrokes? There must be a subtle timing difference.

Why don’t you look into the source code? :innocent:

Note that addScancode is stateful, so especially in the write command (but in tapKeySeq too with the p/r MODMASKs) multiple scancodes can be active at one time.

There must be a subtle timing difference.

I wouldn’t say it is exactly a subtle one :-). (And it is not really a timing difference. Different sequences of reports are produced. Timing is regular.)

1 Like

Shouldn’t a reasonably large keystrokeDelay result in the same reports? I would expect the write then to turn into single individual keypresses and releases… :thinking::question:

No, or at least not necessarily.

And keystrokeDelay has nothing to do with it, as it slows down both sequences in exactly the same way.

If I am just sending a simple sequence of characters, with no specific press and release instructions that generate overlapping key presses, and only use maybe the occasional shift modifier on some of the characters, I don’t understand why that would not create the same reports.

I’m not an expert on the USB HID protocols, and I believe I should not need to be one just to understand and use the UHK macro programming.

In my simple view of the UHK as a black box (which means refusing to look into the code too deeply :imp:), I would think that given keystrokeDelay 500 the two commands

tapKeySeq a b c d


write abcd

should produce 1 character every half second, i.e. a tap every 500ms. Why would their USB reports differ?

In my simple view of the UHK as a black box (which means refusing to look into the code too deeply :imp:)

I am sorry, but your demands are ridiculously high. When they are so much higher than those of the creators of the black box (and of other users), it is necessarily the time to stop treating it as a black box.

Or at least that’s what I had done in that situation :unamused:.

should produce 1 character every half second, i.e. a tap every 500ms.

The part you are getting wrong is that they should produce one usb report every half second, not character.

I am not sure whether tapKeySeq will produce empty reports inbetween the a b c d.

As for write action, it is implemented so that it adds keys into the report as long as it can (either the report is full, or a repeated character occurs).

I.e., for tapKeySeq a b c d the sequence may be either [a], [b], [c], [d] or [a], [], [b], [], [c], [], [d], [].

Write action will produce [a], [ab], [abc], [abcd].

If you want to know why Eric implemented it that way, you will have to ask him. I have no idea.

Thanks, @kareltucek, for the explanation. Now I understand that keystrokeDelay actually means usbReportDelay. (I guess it’s intended to slow down the USB report rate, not slow down the (virtual) typing speed.) And I’ve also learned that my assumption that write just translates the text into the corresponding tapKeySeq was also not correct.

It would be nice to have something like tapWrite This is a string I want tapped., but with that I’ll stop getting on your nerves now with my ridiculous demands. I appreciate your patience.

1 Like