Add "Suppress Repeats" prefix for hotkeys

Propose new features and changes
User avatar
evilC
Posts: 4341
Joined: 27 Feb 2014, 12:30

Add "Suppress Repeats" prefix for hotkeys

02 Mar 2018, 08:43

Littered throughout the documentation, I see examples like this:

Code: Select all

*#up::MouseMove, 0, -10, 0, R  ; Win+UpArrow hotkey => Move cursor upward
*#Down::MouseMove, 0, 10, 0, R  ; Win+DownArrow => Move cursor downward
*#Left::MouseMove, -10, 0, 0, R  ; Win+LeftArrow => Move cursor to the left
*#Right::MouseMove, 10, 0, 0, R  ; Win+RightArrow => Move cursor to the right

*<#RCtrl::  ; LeftWin + RightControl => Left-click (hold down Control/Shift to Control-Click or Shift-Click).
SendEvent {Blind}{LButton down}
KeyWait RCtrl  ; Prevents keyboard auto-repeat from repeating the mouse click.
SendEvent {Blind}{LButton up}
return

*<#AppsKey::  ; LeftWin + AppsKey => Right-click
SendEvent {Blind}{RButton down}
KeyWait AppsKey  ; Prevents keyboard auto-repeat from repeating the mouse click.
SendEvent {Blind}{RButton up}
return
The issue I have is with this line: KeyWait RCtrl ; Prevents keyboard auto-repeat from repeating the mouse click.
Yes, it does do that, but is also has other significant side-effects (It does not work when two hotkeys do this).
I have long been campaigning to alter the documentation to advise people to avoid KeyWait or GetKeyState loops in hotkeys, and this seems to be the only case where doing KeyWait inside a hotkey serves a valid use.

In order to do the above code without a KeyWait (And keeping the repeat suppression), you would need to do this:

Code: Select all

rcState := 0
akState := 0

*#up::MouseMove, 0, -10, 0, R  ; Win+UpArrow hotkey => Move cursor upward
*#Down::MouseMove, 0, 10, 0, R  ; Win+DownArrow => Move cursor downward
*#Left::MouseMove, -10, 0, 0, R  ; Win+LeftArrow => Move cursor to the left
*#Right::MouseMove, 10, 0, 0, R  ; Win+RightArrow => Move cursor to the right

*<#RCtrl::  ; LeftWin + RightControl => Left-click (hold down Control/Shift to Control-Click or Shift-Click).
if (rcState)
	return	; Suppress repeats
rcState := 1
SendEvent {Blind}{LButton down}
return

*<#RCtrl up:: 
SendEvent {Blind}{LButton up}
rcState := 0
return

*<#AppsKey::  ; LeftWin + AppsKey => Right-click
if (akState)
	return
akState := 1
SendEvent {Blind}{RButton down}
return

*<#AppsKey up::
SendEvent {Blind}{RButton up}
akState := 0
return
Which is obviously a little confusing, as you are introducing a new concept (Repeat suppression) whilst trying to explain another concept.

So if we added a repeat suppression prefix (eg @1::), then this would remove the need for KeyWait to do repeat suppression, meaning that we can more easily remove these examples from the docs, without affecting the functionality of the code.

My ultimate goal here is to remove all the examples which suggest that using a blocking wait inside a hotkey is a good idea, I am getting really sick of having to explain how hotkey threads work to noobs, because they blindly follow the examples in the documentation (Which gives them no warnings that the technique it is showing them is fundamentally flawed), and which work for the sample code in isolation, but once you try to use it in your script (Which has more than one hotkey), they stop working properly. I am literally having to explain this multiple times a day at times. It's ridiculous.
guest3456
Posts: 2419
Joined: 09 Oct 2013, 10:31

Re: Add "Suppress Repeats" prefix for hotkeys

02 Mar 2018, 10:06

evilC wrote:because they blindly follow the examples in the documentation (Which gives them no warnings that the technique it is showing them is fundamentally flawed), and which work for the sample code in isolation, but once you try to use it in your script (Which has more than one hotkey), they stop working properly.
Can you describe the current problem better? I'm not seeing how/why KeyWait is such this big problem for you. Can you post an example script and give us the steps to reproduce the error, and what you expect or want to happen instead?

guest3456
Posts: 2419
Joined: 09 Oct 2013, 10:31

Re: Add "Suppress Repeats" prefix for hotkeys

02 Mar 2018, 12:16

that thread talks about detecting keyup events, not repeat supression
evilC wrote:My ultimate goal here is to remove all the examples which suggest that using a blocking wait inside a hotkey is a good idea, I am getting really sick of having to explain how hotkey threads work to noobs
no one is forcing you to explain anything to anybody. using a blocking wait inside a hotkey can be a good idea, and it can also backfire. i agree with the user in your linked thread who said that different methods are appropriate for different situations. it just requires the author to think a bit more deeply about exactly what they want their script to accomplish, and learn that AHK is single threaded.
evilC wrote:So if we added a repeat suppression prefix (eg @1::), then this would remove the need for KeyWait to do repeat suppression
you haven't quite made your case. how do you expect this repeat supression functionality to work? in the example in your OP, how is AHK supposed to know that you want the keywait between the lbutton down and up lines? or are you suggesting the interpreter internally break the hotkey into up/down hotkeys, but in that case, how is the interpreter supposed to know which code goes in each?

User avatar
evilC
Posts: 4341
Joined: 27 Feb 2014, 12:30

Re: Add "Suppress Repeats" prefix for hotkeys

02 Mar 2018, 12:49

I can find no other valid use-case for KeyWait inside a hotkey than the repeat suppression example.
All the other examples I can find can better be done (Work the same, with no down-sides) with up event hotkeys.

"using a blocking wait inside a hotkey can be a good idea" - can you provide an example where it is better to do this instead of using an up event hotkey?

"and learn that AHK is single threaded" - this is my whole point. By encouraging the use of blocking waits (I can find a bunch of examples of this in the documentation, I can find only one example of an up event hotkey in the docs, in the documentation for up event hotkeys), you force people to understand threading if they want to understand when a blocking wait will work and when it will break. If, instead, we recommend using up event hotkeys in the docs, then they can remain blissfully ignorant of threading.

"how do you expect this repeat supression functionality to work?"
@1:: will not fire again until 1 has been released.

ie, it is shorthand for:

Code: Select all

1_state := 0

1::
	if (1_state)
		return
	[body of hotkey here]
	return

1 up::
	1_state := 0
	[body of up event hotkey here (if it exists)]
"i agree with the user in your linked thread who said that different methods are appropriate for different situations"
I find it hard to agree with what he says, because he does not seem to understand that there is any problem at all, and he makes a bunch of factually inaccurate statements to back up his viewpoint (eg "A while loop is more accurate that SetTimer, and less prone to interruptions", when the exact opposite is true, as my examples demonstrate).
guest3456
Posts: 2419
Joined: 09 Oct 2013, 10:31

Re: Add "Suppress Repeats" prefix for hotkeys

02 Mar 2018, 13:51

evilC wrote: "using a blocking wait inside a hotkey can be a good idea" - can you provide an example where it is better to do this instead of using an up event hotkey?
you admit that everything works fine when there is only one hotkey thread active. i personally find it much more readable and easier to understand the code when i see a KeyWait command, rather than having to seach for the associated Up hotkey label to see what is supposed to be processed after. clearer and more readable code is always a 'good idea' in my opinion
evilC wrote: "and learn that AHK is single threaded" - this is my whole point..If, instead, we recommend using up event hotkeys in the docs, then they can remain blissfully ignorant of threading.
yeah i think you might right. but are you just suggesting changing the docs? this is in wish list forum, and i thought the purpose of the thread was your new syntax:
evilC wrote: "how do you expect this repeat supression functionality to work?"
@1:: will not fire again until 1 has been released.

ie, it is shorthand for:

Code: Select all

1_state := 0

1::
	if (1_state)
		return
	[body of hotkey here]
	return

1 up::
	1_state := 0
	[body of up event hotkey here (if it exists)]
but there is no "body of up event"

what youre suggesting is this syntax, right?

Code: Select all

@1::
   SendEvent {Blind}{LButton down}
   ;KeyWait 1   ; unnecessary since we have used the @ prefix modifier
   SendEvent {Blind}{LButton up}
return
how is the interpreter supposed to know where to break the down/up events to split into each 'body'?

what if this was the code

Code: Select all

@1::
   ;line 1
   ;line 2
   ;KeyWait 1   ; unnecessary since we have used the @ prefix modifier
   ;line 4
   ;line 5
   ;line 6
return

User avatar
evilC
Posts: 4341
Joined: 27 Feb 2014, 12:30

Re: Add "Suppress Repeats" prefix for hotkeys

02 Mar 2018, 15:15

guest3456 wrote:what youre suggesting is this syntax, right?

Code: Select all

@1::
   SendEvent {Blind}{LButton down}
   ;KeyWait 1   ; unnecessary since we have used the @ prefix modifier
   SendEvent {Blind}{LButton up}
return
No, I am suggesting we change it to

Code: Select all

@1::
   SendEvent {Blind}{LButton down}
   return
   
@1 up::
   SendEvent {Blind}{LButton up}
   return
That way, the code gets simpler (No need to introduce the concept of repeat suppression), the functionality remains identical, and the code pattern works in all instances.
guest3456
Posts: 2419
Joined: 09 Oct 2013, 10:31

Re: Add "Suppress Repeats" prefix for hotkeys

02 Mar 2018, 15:28

evilC wrote: No, I am suggesting we change it to

Code: Select all

@1::
   SendEvent {Blind}{LButton down}
   return
   
@1 up::
   SendEvent {Blind}{LButton up}
   return
That way, the code gets simpler (No need to introduce the concept of repeat suppression), the functionality remains identical, and the code pattern works in all instances.
ok, you are suggesting the above, as opposed to this:

Code: Select all

1_state := 0

1::
   if (1_state)
      return
   1_state := 1
   SendEvent {Blind}{LButton down}
return
   
1 up::
   1_state := 0
   SendEvent {Blind}{LButton up}
return

but then i don't see what this has to do with KeyWait or any other blocking command. you are simply suggesting saving 5 lines of overhead code and changing it to a hotkey prefix char

User avatar
evilC
Posts: 4341
Joined: 27 Feb 2014, 12:30

Re: Add "Suppress Repeats" prefix for hotkeys

02 Mar 2018, 17:39

The only example in the AHK docs that I can find where a blocking wait does something that would not be achieved solely through switching to an up event hotkey is the example I cited.
If we had a repeat suppression prefix, then this example could be replaced with code that was both shorter and more reliable. Without it, in order to replace the example with something more reliable, we need to replace it with code that requires the end-user to create a global variable plus 5 lines of code per hotkey that he wishes to do this with.
lexikos
Posts: 6176
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: Add "Suppress Repeats" prefix for hotkeys

05 Mar 2018, 04:02

As an aside, there is a shorter workaround:

Code: Select all

1::
   Hotkey 1, Off
   SendEvent {Blind}{LButton down}
return
   
1 up::
   Hotkey 1, On
   SendEvent {Blind}{LButton up}
return
However, "Hotkey, If" may cause issues with it in v1.

Return to “Wish List”

Who is online

Users browsing this forum: No registered users and 6 guests