Search code examples
autohotkey

How to workaround/prevent hotkey firing when key is released


I'm trying to get a hotkey to perform two functions - one if it is pressed quickly, below a time threshold (400ms in my code), and another if the key is held for longer than that time.

I do want it to fire the short press function immediately when the key is lifted, ie not to wait until 400ms is up.

Here's the code I've come up with:

LongPress := 400
F22::{
Loop
    {
    if (A_TimeSinceThisHotkey > LongPress) {
            ToolTip("LONG press detected - " . A_TimeSinceThisHotkey . "ms")
            break
        }
    if not GetKeyState(A_ThisHotkey, "P") {
            ToolTip("SHORT press detected - " . A_TimeSinceThisHotkey . "ms")
            break 
        }
    }

    return
}

I'm seeing two types of unexpected behavior that I would like to prevent.

  1. When I release the hotkey, it often shows a short press detected with a very short time, sometimes 0ms. I tried adding if not GetKeyState(A_ThisHotkey, "P") return before the loop, which I would have hoped to just exit the hotkey function immediately when it's activated on key release, but that didn't change the behavior.
  2. When I'm holding the hotkey down for a very long time, it seems to fire the "long press detected" over and over, ie I see "LONG press detected" with a changing number of ms afterwards, 402ms, 410ms, etc.

I want the hotkey to fire only once for each press of the hotkey, either a short or a long press, but not over and over, and also not to fire the extra short press when the key is released.

How can I achieve both of these?


Solution

  • Thanks to @user3419297 for the hint to use Keywait. I'm using ahk v2 so had to convert it a bit.

    Here's the final code I went with:

    LongPress := 0.3 ; 300ms
    
    F22::{
        waitvar := (Keywait(A_ThisHotkey, "T" LongPress)) ; waits 0.3 seconds maximally for F22 to be released
        if waitvar
        {
            ToolTip("waitvar = " waitvar "`n" "SHORT press detected: " . A_TimeSinceThisHotkey . " ms")
            SetTimer () => ToolTip(), -2000 ; remove the ToolTip
        }
        else
            ToolTip("waitvar = " waitvar "`nLONG press detected: " A_TimeSinceThisHotkey " ms")
            SetTimer () => ToolTip(), -2000 ; remove the ToolTip
        KeyWait A_ThisHotkey  ; waits for F22 to be released (stops key repeat from retriggering)
        return
    }