Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Press-and-hold character input delay in full remap of HID remote #87

Open
hmhackmaster opened this issue Mar 14, 2022 · 1 comment
Open

Comments

@hmhackmaster
Copy link

I am attempting to remap a USB wireless remote thingy that, by default, sends single-letter keyboard inputs to the OS and instead sent a "+KEY" input to Windows.
I have successfully ran the monitor and figured out the corresponding key names and scancodes and built out a quick test but I have encountered a problem: When I hold down a key on my remote I am wanting a constant output of keystrokes without the Windows default behavior of inserting a short delay after the first keystroke.

Without the below script running, if I single-press the Up button on my remote, Windows would receive a 'w' key. If I press and hold the up button, I will get a single key, a short pause, then the keys again as if the keyboard character is being held down: "w.....wwwwwwwww" (thanks to Windows' Character Repeat Delay, I reckon)

With the script running, the same delay occurs, but only with my new key.
My assumption prior to drafting this issue was my delay was coming from the inefficient script (the full script will end up having 14 buttons to translate), but now I am beginning to suspect that perhaps Windows is adding the delay before AHK/Interception is able to receive the key inputs.

Do you have any thoughts @evilC?
Thanks!

#SingleInstance force
#Persistent
#include Lib\AutoHotInterception.ahk


global AHI := new AutoHotInterception()
keyboardId := AHI.GetKeyboardId(0x348F, 0x1010) ; HID Keyboard ID for Remote's USB Dongle
AHI.SubscribeKeyboard(keyboardId, true, Func("KeyEvent"))


KeyEvent(code,state){
	;ToolTip % "Keyboard Key - Code: " code ", State: " state
	
	if (code = 2) 
	{
		SendInput t ; for testing
	}
	else if (code = 17) ; key: w
	{
		SendInput !{up} ; send the hotkey ALT + Up arrow
		; SendInput u   ; TESTING: just send a u
	}
	else if (code = 31) ; key: s
	{
		SendInput !{down} ; send the hotkey ALT + Down arrow
	}	
	else if (code = 30) ; key: a
	{
		SendInput !{left} ; send the hotkey ALT + Left arrow
	}	
	else if (code = 32) ; key d
	{
		SendInput !{right} ; send the hotkey ALT + Right arrow
	}
	else if (code = 38) ; key: l
	{
		ExitApp ; Testing: Map a key on the remote to quit the script
	}
	else
	{
		ToolTip % "Keyboard Key - Code: " code ", State: " state ; If input is unrecognized, let's output the code
	}
}

^Esc::
	ExitApp
@evilC
Copy link
Owner

evilC commented Mar 21, 2023

Could do with clarification here
It's the line "With the script running, the same delay occurs, but only with my new key" that is confusing me, specifically the "only with my new key" bit.

Key repeat is a tricky one, and it highly depends on how the application that is receiving inputs behaves.
Key repeat only affects press events - that is, if you hold a key, you (normally) get presss, press, press, press while you hold the key, then one release at the end when you release the key. If your device behaves differently, it is off-spec and more difficult to deal with.

In general though, you can use code like this to morph repeated keys in various ways
ie here is code that will filter key repeats

#SingleInstance force
#Persistent
#include Lib\AutoHotInterception.ahk


global AHI := new AutoHotInterception()
keyboardId := AHI.GetKeyboardId(0x348F, 0x1010) ; HID Keyboard ID for Remote's USB Dongle
AHI.SubscribeKeyboard(keyboardId, true, Func("KeyEvent"))


KeyEvent(code,state){
	static states := {} ; Array used to hold current state of keys. STATIC is important!

	if (state && states[code]){  ; evaluates to true if key is already held
		return ; filter key repeat
	}

	if (code = 2) 
	{
		SendInput t ;
	}
	else if (code = 17) ; key: w
	{
		SendInput !{up}
	}

	 ; Update the states array with the current state of this key
	states[code] := state
}

If you want key repeat, but want to remove the delay, you can use similar code, but add a call to SetTimer to repeatedly send the key while it is held

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants