Search code examples
autohotkeydetectionspace

Why are spacebar events suppressed when running this script?


I made a script to tile windows with my left hand in windows 10, using a dvorak keyboard layout. It works as expected except, it keeps the spacebar events from getting to any program other than the script itself. This is the keyboard log when running the script:

20  039 s   d   0.09    Space           
20  039 s   u   0.08    Space           
20  039 s   d   0.08    Space           
20  039 s   u   0.08    Space           
20  039 s   d   0.08    Space           
20  039 s   u   0.09    Space           
20  039 s   d   0.08    Space           
20  039 s   u   0.09    Space           
20  039 s   d   31.14   Space           
20  039 s   u   0.11    Space           
20  039 s   d   0.09    Space           
20  039 s   u   0.11    Space

Both space events are detected correctly, but remain suppressed. Terminating the script manually solves the problem.

  #MaxThreads 255 ; for the purpose of troubleshooting

    #e::return      
    #.::return 
    #o::return          
    #u::return       

    Space & u::  
    Space & .::
    Space & o::
    Space & e::
    send {LWin Down}
    spcup()       
    exit

    spcup()                                                                          
    {
    while GetKeyState("Space", "P") {
    rite := GetKeyState("u", "P")
    left := GetKeyState("o", "P")
    up := GetKeyState(".", "P") 
    down := GetKeyState("e", "P")           
    if (rite=1) {
        Sleep 75
        Send {Right}
        Sleep 75
        }
        else if (left=1) {
            Sleep 75
            Send {Left}
            Sleep 75 
            }   
        else if (up=1) {
            Sleep 75
            Send {Up}
            Sleep 75  
            }
        else if (down=1) {
            Sleep 75
            Send {Down}
            Sleep 75
            }
        else if !GetKeyState("Space", "P") { 
            sleep 75
            Send {LWinUp}
            exit
            }
    }
    }

PS, I used space because my left windows key is physically damaged. Binding Space to itself adding a "Space::Space" line, works partially, only the up event is registered as a hotkey, so it fires only on release of spacebar producing this:

20  039 s   d   0.25    Space           
20  039 h   u   0.16    Space           
20  039 i   d   0.00    Space           
20  039 i   u   0.00    Space   

s=suppressed
h=hotkey
i=ignored(sent by autohotkey itself)

"Solved", kind of. No way for a prefix key to maintain it's original function without ~, hence sending it to the active window, which is unwanted.

isWindowFullScreen()
{
    ;checks if the specified window is full screen
    ;use WinExist of another means to get the Unique ID (HWND) of the desired window

    if  WinExist("A") {
    WinGet, style, Style, A
    WinGetPos ,,,winW,winH, A
    ; 0x800000 is WS_BORDER.
    ; 0x20000000 is WS_MINIMIZE.
    ; no border and not minimized
    retVal := ((style & 0x20800000) or winH < A_ScreenHeight or winW < A_ScreenWidth) ? 0 : 1
    Return, retVal
}
else {
return
}
}

#if isWindowFullScreen() = 0
#e::return       
#.::return 
#o::return          
#u::return
#Space::return 
Space::Space             
Space & u::                                                        
Space & .::
Space & o::
Space & e::
send {LWin Down}
spcup()       
exit



spcup()                                                                                   
{
while GetKeyState("Space", "P") {
loop {
rite := GetKeyState("u", "P")
left := GetKeyState("o", "P")
up := GetKeyState(".", "P") 
down := GetKeyState("e", "P")           
if (left=1) {
    Sleep 75
    Send {Left}
    Sleep 75 
    }   
    else if (up=1) {
        Sleep 75
        Send {Up}
        Sleep 75  
        }
    else if (down=1) {
        Sleep 75
        Send {Down}
        Sleep 75
        }
    else if (rite=1) {
        Sleep 75
        Send {Right}
        Sleep 75
        }
} until !GetKeyState("Space", "P") 
Sleep 75
Send {LWinUp}
exit
}
}

Solution

  • From the help documentation:

    Numpad0 & Numpad1::MsgBox You pressed Numpad1 while holding down Numpad0.
    Numpad0 & Numpad2::Run Notepad
    

    The prefix key loses its native function: In the above example, Numpad0 becomes a prefix key; but this also causes Numpad0 to lose its original/native function when it is pressed by itself. To avoid this, a script may configure Numpad0 to perform a new action such as one of the following:

    Numpad0::WinMaximize A   ; Maximize the active/foreground window.
    Numpad0::Send {Numpad0}  ; Make the release of Numpad0 produce a
    Numpad0 keystroke. See comment below.
    

    Fire on release: The presence of one of the above custom combination hotkeys causes the release of Numpad0 to perform the indicated action, but only if you did not press any other keys while Numpad0 was being held down. [v1.1.14+]: This behaviour can be avoided by applying the tilde prefix to either hotkey.

    Adding a tilde prefix ~ to each of your Space & hotkeys should make it behave as you expect. Alternatively, you could add ~Space::Return.

    Note that this will always send a space, which may have unintended consequences in different applications. For instance, in a browser it will scroll down similar to pressing the page down key.

    Here is a condensed version of your code that I used for testing:

    ~Space & u::
    ~Space & .::
    ~Space & o::
    ~Space & e::
    aReplace := [[ "u" , "Right" ] , [ "o" , "Left" ] , [ "." , "Up" ] , [ "e" , "Down" ]]
    Loop , % aReplace.Length()
        sReplace := ( SubStr( A_ThisHotkey , 0 , 1 ) = aReplace[ A_Index , 1 ] ) ? aReplace[ A_Index , 2 ] : sReplace
    Send , #{%sReplace%}
    Return