Macro syntax for esc/mouse where esc ONLY if tap is <200ms

Hi, I used the GUI to have the mouse key function as escape if pressed alone, and mouse if with any other keys. I have some issues:
When I use the mouse key to navigate eg in an application it generally works as expected, but if I press the key in preparation to use it as a mouse key, but then change my mind and release the key without having used any other key, the key acts as escape, regardless of how long I have held the key down. This results in undesired behaviour where a window may disappear for example. I have tried reading the documentation, and asking chatGPT4o (which was useless even after telling it to read the docs).

What I am wanting is to have the key function as escape ONLY if it is pressed quickly (tapped, I suppose), and otherwise it should act as the mouse key, including doing nothing if I press it for longer than a specified short amount of time (would 200 ms be about right?).

Any help greatly appreciated.

You don’t even need a macro for that.

In Agent, go to the Typing behaviour section, and change the settings for Secondary roles. Set the Resolution strategy to Advanced, the Timeout action to Secondary, and choose your Timeout.

1 Like

Perfect, thank you, it works nicely now.

BTW, if you really wanted to separate the three different actions

  • (short) tap
  • (long) hold
  • pressing a second key while holding (but before the long hold time elapses)

you could achieve that with a macro like this:

setLedTxt 0 'KEY'
delayUntilReleaseMax 500
ifInterrupted final setLedTxt 999 '2ND'
ifPlaytime 450 final setLedTxt 999 'HLD'
setLedTxt 999 'TAP'

Bind it to a key and then try tap, hold, and hold-while-tapping-another-key. You’ll see KEY light up as soon as you press the key, and then the display will change to TAP or HLD or 2ND depending on what you do next.

Thanks @maexxx
I’m genuinely wondering how one acquires this knowledge. I have read the docs on github and in the agent, but really would not have been able to arrive at this understanding, indeed it doesn’t even count as understanding since all would be able to do with what you have given is what you have illustrated.

For example, I am trying to add the the usual functions of the single/double quotes key, that if I double-tap it, it will give me an @ sign. This was my attempt:

holdKey ’

delayUntil 200

ifDoubletap tapKey @

ifNotDoubletap tapKey ’

which produced, on double-tap, two single-quotes (this may be due to the editor doing the second automatically… I’m testing in Obsidian), and then the @ sign.

Can you let me know what I should be doing, and even better, where I might find this out?

With many thanks.

40 years of software development experience in multiple programming languages and various operating systems. The UHK macro language is then just another language to learn… :wink:

That one - detecting the double tap without producing a character on the first press - is a bit tricky. I only know this because I’ve been following a number of conversations with @kareltucek here on the forum.

Here is what you have to do:

ifGesture timeoutIn 200 $thisKeyId final tapKey S-2
tapKey apostropheAndQuote

The ifGesture holds processing and waits for more keystrokes (up to the timeoutIn value in milliseconds). It then checks if the next key typed is $thisKeyId, which refers to the same key as the one this macro was started with; effectively this means checking for a double tap. If that condition matches, then the final command will be executed and the macro ends. The final command tapKey S-2 taps Shift-2, resulting in an @ output.

If the ifGesture did not detect a double tap, then the normal apostropheAndQuote key is tapped, resulting in an ' output (or " if tapped with shift).

Note: with this macro, the key will no longer autorepeat.

BTW, here’s my enhanced test macro that shows off these different choices:

setLedTxt 0 'KEY'
ifGesture timeoutIn 200 $thisKeyId final setLedTxt 999 'GST'
ifDoubletap final setLedTxt 999 'DBL'
delayUntilReleaseMax 500
ifInterrupted final setLedTxt 999 '2ND'
ifPlaytime 450 final setLedTxt 999 'HLD'
setLedTxt 999 'TAP'

It always starts by displaying KEY as soon as you press the key.
Double-tap it fast (within 200 ms) and you see GST.
Double-tap it slower (between 200 and ~400 ms) and you see a brief flash of TAP (from the first press), then followed by KEY (very briefly) and finally DBL.
Hold it and you see HLD (after 500 ms).
Tap it (once) and you see ‘TAP’.
Hold it and press another key simultaneously (within 500 ms), and you see ‘2ND’.

1 Like

Thanks again @maexxx, much appreciated. It is strangely reassuring to hear that 40 years of developing experience is part of why you know these things. And in the absence of a usable tutorial, and perhaps better anyway, is the fantastic help on the forum. It just means that if I want to learn this stuff, I might get back to my amateur learning of JavaScript first, to learn the basic principles. However when someone does have the time and inclination to make a no-prior-knowledge tutorial, this would be brilliant.

As it happens, I now understand the ‘shift’ layer such that am using the number row permanently shifted to the symbols, but the ? is where the @ would normally be. The forward-slash non-shifted function of the ? key is assigned to a different layer that makes a number of symbols easier to reach, and that means I can use the shift layer to assign shift-? (formerly @) back into @. So I won’t need to use your solution for this, but it is still very helpful to understand more so I could use this for another action.