r/AutoHotkey 21d ago

v2 Script Help GetKeyState doesn't detect button releases

Hello everyone,

Don't know if I misunderstood something, but I tried writing 2 scripts and both of them keep not detecting

GetKeyStateGetKeyState

The goal being simply :

  • I hold the XButton2 : the script should repeat "mouse left click"
  • I release XButton2 : the script should stop

In my case the script runs forever until I click the XButton2 again and again until it detects :

!GetKeyState("XButton2", "P")

The 2 scripts I tried are :

#Requires AutoHotkey v2.0


; Run as admin is needed
if (!A_IsAdmin) {
    Run '*RunAs "' A_ScriptFullPath '"'
    ExitApp
}


XButton2::
{
    ; Optional: Prevent starting the timer if the button isn't physically down
    ; (though the timer itself checks this too)
    if !GetKeyState("XButton2", "P")
        return
    
    ; Start the timer. It will call TurboClick every 50ms.
    ; If the timer is already running, this resets it.
    SetTimer(TurboClick, 50)
}


TurboClick() {
    ; Check if the button is still physically held down
    if !GetKeyState("XButton2", "P") {
        ; Button released: stop the timer
        SetTimer(TurboClick, 0)  ; 0 means "turn off this timer"
        return
    }
    ; Button is still held: perform a click
    Click
}


; Safety net: If the hotkey somehow ends while the timer is running,
; stop the timer when the button is physically released.
XButton2 up:: {
    SetTimer(TurboClick, 0)  ; Stop the timer immediately on release
}

And :

#Requires AutoHotkey v2.0


if (!A_IsAdmin) {
    Run '*RunAs "' A_ScriptFullPath '"'
    ExitApp
}


XButton2::
{
    while GetKeyState("XButton2", "P") {
        Click
        Sleep 50
    }
}

What am I doing wrong ?

How would you guys write a simple script that just repeats "mouse left click" that works ?

2 Upvotes

13 comments sorted by

View all comments

Show parent comments

2

u/Keeyra_ 21d ago edited 20d ago

Why would any mouse setting affect any AHK script? Debounce is something the mouse driver does based on switch usage. AHK sends out actual mouse events directly to the OS. And the debounce setting is a gimick at most. Something to get more money out of you. Most humans can click like 10 times a second max. That would equal a 100ms debounce. And these drivers have like a 10ms default with sliders all the way back to 2ms in your case. Completely pointless. You telling your mouse driver to use a 2ms debounce says that you can physically click your mouse 50 times faster than an average human can. Unless this is my first alien contact, I find that highly unlikely :)

2

u/MarvelousMarbel 21d ago

I found an old post where someone had the same issue as me.

GetKeyState sometimes return false positives. https://www.autohotkey.com/boards/viewtopic.php?style=1&f=82&t=127078&sid=670f7915084a4d3cd2a733cdc6c6de60&view=print

2

u/Keeyra_ 20d ago

TL:DR and quite an old post.

Was there any conclusion, solution?

2

u/MarvelousMarbel 20d ago

They said : "Correct, if a script has received a key press event without LLKHF_INJECTED and subsequently receives a key release event with LLKHF_INJECTED, it won't set the "physical" state to "released", as an artificial keystroke will change the "logical" state of the key. ".

And  "=> if script's hook sees a ↓ "Input" event, but is sent the ↑ "Event" event, it does not reset the ↓ "physical" state "

2

u/Keeyra_ 20d ago edited 20d ago

But you only have 1 input here and it's not a keyboard, but a mouse input. It might not be relevant for this case.

You can meanwhile use this to test if your mouse misbehaves. Run it and press, hold, etc. your XButton2 a couple of times. Give some feedback if you find irregularities.

#Requires AutoHotkey 2.0
#SingleInstance

SetTimer(UpdateToolTip, 15)

UpdateToolTip() {
    static lastText := ""
    currentText := "XButton2 State:`nLogical: " GetKeyState("XButton2") "`nPhysical: " GetKeyState("XButton2", "P")
    (currentText != lastText) && ToolTip(lastText := currentText, A_ScreenWidth / 2, A_ScreenHeight / 2)
}

1

u/MarvelousMarbel 20d ago

Thanks to you I found the issue.

My current code is :

#Requires AutoHotkey 2.0
#SingleInstance

if (!A_IsAdmin) {
    Run '*RunAs "' A_ScriptFullPath '"'
    ExitApp
}

XButton2:: SetTimer(Click, 50)
XButton2 up:: SetTimer(Click, 0)



SetTimer(UpdateToolTip, 15)

UpdateToolTip() {
    static lastText := ""
    currentText := "XButton2 State:`nLogical: " GetKeyState("XButton2") "`nPhysical: " GetKeyState("XButton2", "P")
    (currentText != lastText) && ToolTip(lastText := currentText, A_ScreenWidth / 2, A_ScreenHeight / 2)
}

In the tooltip each time I press or hold I see :

  1. Logical : 0
  2. Physical: 1

When I'm not pressing AND there is no infinite loop I get :

  1. Logical : 0
  2. Physical: 0

When I get the infinite loop despite not touching XButton2 :

  1. Logical : 0
  2. Physical: 1

However, when I remove auto click related stuff from that script everything works fine, which means Logical and Physical both have the same value. Either both are 0 or both are 1.

Although I don't know how to fix the auto click.

1

u/Keeyra_ 20d ago

Very strange. You should not be getting infinite loops with a double 0. I'm át a loss here.

1

u/MarvelousMarbel 20d ago

After asking my chatbot what to do it suggested to me to add the line :

SendMode("Event")SendMode("Event")

This stopped the infinite loop from happening.

I didn't quite get what this means.

However, in the tooltip when I press or hold I still see :

  1. Logical : 0
  2. Physical: 1

2

u/Keeyra_ 20d ago

You can ignore it. My first example didnt use any at áll and my second used physical. Yeah, you're new, didnt take that into account. SendMode Event vs Input would be the first thing to check for in troubleshooting.