keyd: Add a timeout that automatically resolves a tap-hold as a tap when typing
Using overloadt or overloadt2 causes a noticeable delay when typing. I have an idea for being able to use them without having any delay when typing. Create a global timeout (default 0) where keyd immediately registers it as a tap if a character has been tapped for less than that amount of milliseconds. For example, if the value is set to 50, and you push an overloadt or overloadt2 key, and less than 50 milliseconds has passed since the last character was tapped, immediately resolve it as a tap. This would practically eliminate the typing delay with the downside of having to wait that amount of time if you want to use the hold behaviour after typing. It also has the added benefit of significantly decreasing false positives.
About this issue
- Original URL
- State: open
- Created 8 months ago
- Comments: 20 (6 by maintainers)
Commits related to this issue
- Add overloadi (#608) — committed to rvaiya/keyd by rvaiya 6 months ago
I’ve tentatively added
overloadiwhich isoverloadt3described above but with the first two arguments transposed. I’ve also added an alias calledlettermodwhich allows the user to specify an idle and hold timeout more easily in one place (see the man page for details). Feedback is welcome.I briefly did some testing with
keyd monitor -tand here is what I found.Ctrl [to exit insert mode.This probably means that a value of
100milliseconds would eliminate most of the delay while having few false negatives. However, sometimes the time between two key presses will be more than 100 milliseconds so it will not completely get rid of the delay. In addition, I often have short pauses when typing. I have a tendency to type in bursts. This means that in the beginning after each of these pauses, there will always be a delay.If I understand correctly, this is possible with
timeout(). For example:However, completely eliminating the visual delay without losing your balance on false positives remains difficult. (If you have the stomach for it, see also the previous discussions in #34 #81 #125 #138 #278 #309 #310 #320.)
EDIT: Wait, you started with
This is already possible, but you then went on with:
Is what you meant here the time since keydown of the previous key, rather than the current one? If so, that may be interesting. Does the time since the keydown of an earlier key correlate with intent? It probably does somewhat, but does that mean it is a solid basis for disambiguation? I’m skeptical — think we need some data 😛
Just wanted to mention that I’ve had the
lettermodaction on my layout since December. Haven’t had any misfirings because of it and it makes the visual delay much less obnoxious. I still don’t think I will personally keep it forever, because the delay is of course sometimes still present, but I am now convinced that it is a useful feature.Given that, it feels natural to also allow it on chords as @amarakon/@amarakon2 suggested above. Should make those feel snappier too. On the other hand, it’s not a straightforward extension — it would be rather subtle and require new syntax. If there’s genuine demand for it, it’s probably worth a separate issue.
BTW, I’m @amarakon but on a new account because I’m currently in a different country and cannot log in without two-factor authentication. Also, sorry for not responding in a long time, I just had a surgery and am in the process of recovering.
Thanks, it works very well!
I mean a chord that would register as two individual keypresses if the user tapped a key in the previous n milliseconds. I tried the following code but it didn’t work.
It seems like this feature is also implemented in QMK. See this article.
Yes. My understanding is that a visual delay may still occur at the beginning of typing sequence, but after that, everything would show up on keydown (immediately!), as long as you keep going. Is that right?
Sorry, I used it informally (without explanation…). I meant anything that ‘feels’ like you’re typing in a steady flow, which, by grace of the proposed timeout, includes both styles. So
<a down> <b down> <a up> <b up>is unambiguously rolling, but<a down> <a up> <b down> <b up>is also accepted provided that the time between<a up>and<b down>is within our small margin of tolerance.I suspect this is the case for me as well. (I did get curious, though, so I will shut up in this thread until I can show some experimental results 😛)
Hmm, perhaps I am missing something. If the post key timeout is maintained, isn’t the visual delay still present? My understanding is that this pre-key delay is intended to obviate the need for the post key delay.
Is the goal then simply to minimize the delay rather than eliminate it entirely? What about the beginning of words which start with overloaded letters? E.g how is
atdistinguished from<C-t>if it is the first word typed after a long pause? You would still need a reasonably long post key delay to differentiate the cases.I assume by ‘rolling’ you mean something like
<a down> <b down> <a up> <b up>, as opposed to<a down> <a up> <b down> <b up>. The problem is that in practice you (or at least I) will use a mix of these styles, so it can’t reliably serve as the basis for distinguishing between the cases (this caused a lot of accidental layer activations in my tests).I suppose this is the crux of my argument. The internal context switch doesn’t (in my experiments) necessarily translate into a consistent pause between the strokes. I have observed myself type ‘C-[’ in quick succession after typing a string of characters without a meaningful gap between the last letter and the control key. You can run some experiments yourself using the output of
keyd monitor -t.Perhaps this is true. It is certainly possible that a subset of the population naturally does this, though my suspicion is that people are just training themselves to add an additional pause to placate their trigger happy mods. In either event, I am not strictly opposed to adding the functionality if enough people find it useful.
Indeed 😛
I admittedly haven’t read through the rationale. I will take a look.
Sorry for the contradiction. What I meant is the second one:
I think it should be the time since the keyup of an earlier key that was not used with a tap-hold modifier. That way, you can still string together keyboard shortcuts without having to wait. If a character has been pressed and released some milliseconds ago, that indicates that the user is typing. I rarely use modifier keys shortly after typing characters, there is usually a pause before I use keybindings. The only exception is shift, which is used for typing. That’s the reason I don’t use shift as a tap-hold modifier and instead use a dedicated key for it.
urob’s ZMK config has an option called
require-prior-idle-msthat does this. Additionally, you can make the feature off by default so that only people who want to use it will use it.