Author Topic: Selectively allow keypress when 'Do not allow key to be passed' is set?  (Read 4113 times)

Starblue7

  • Full Member
  • ***
  • Posts: 131
Another opportunity for @Pfeil to bonk me on the head!   :-[

Is there some way where, when setting the 'Do not allow key to be passed' option in a command, to only make sure it's not passed to the target application of the command?

I have it set in the command itself to 'Send command to this target' with specifying the game process.
The command is set to 'Stop command if target window focus is lost'.

This in itself made me hope that if I tab out to another window, I'll lose the process focus and be able to us the 'C' key normally without being blocked by Voice Attack.

But apparently this isn't enough.

My goal is to allow the user to hit the 'C' key and block it from being sent to the target application (game), running the command instead.  Yet, when the user tabs out of the game, they'll be able to use their C key without issue.

I'm sure this must be something simple..

Addition:
It kinda would be nice to have an option in Voice Attack to handle this case.
Such that the user can specify that the keybind is only blocked if the target application (either set in the command or at profile level) has the focus.
I suppose within the command itself, I could check if the target application has the focus or not, and if not, have Voice Attack press the 'C' key and only do that and not run the rest of the command.
Though, it seems this way may take a greater hit on performance than if Voice Attack natively allowed that option outside of command processing.
« Last Edit: March 22, 2024, 05:53:22 PM by Starblue7 »

Starblue7

  • Full Member
  • ***
  • Posts: 131
I guess I'll answer my own question, but please correct me if I'm wrong, Gary, Pfeil.

Voice Attack currently doesn't support natively to selectively only block a key bind to be used only for a particular target application (that's focused).

Two options I see is to detect within a command if the target application has the focus or not by using the {PROCESSFOREGROUND:key} token within the command itself.
*Take an unacceptable hit on performance

Or, do something like from this post:

https://forum.voiceattack.com/smf/index.php?topic=4061.msg18607#msg18607


If there's some elementary way to handle this that I'm missing, please let me know.

If Gary/Voice Attack could consider allowing something explicit in the VA Options of the command to block that keystroke ONLY for the particular application (without the need to use the above token and take a performance hit, potentially), then that would be welcome.

Thanks!

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4767
  • RTFM
The simplest method of achieving what you're describing would likely be to use automatic profile switching, configured so that when the target application loses focus, a profile that doesn't block the relevant keys is loaded.

The feasibility of that would depend on the loading time for your profiles, and whether there is a need to keep commands running in the background, as all commands will be stopped when switching profiles.


The method you linked of monitoring the foreground process and using that to disable keyboard shortcuts should be quite effective, and has fewer caveats than the above (or below).


Alternatively, the "Wait For Key Press" action was recently added, and it can intercept keypresses only when said action is running, meaning it is now possible to stop a keypress from being passed through while still retaining the ability to detect said keypress.
This would likely only be relevant if you only want to stop certain keypresses from being intercepted, while retaining the option of triggering (other) commands using the keyboard. Otherwise disabling keyboard shortcuts entirely would be simpler and more efficient.

E.G. a structure like this could be used:
Monitor foreground process
Code: [Select]
Set text [~targetProcess] to 'notepad'
Start Indefinite Loop
    Begin Text Compare : [{PROCESSFOREGROUND:~targetProcess}] Equals '1'
        Write [Green] 'Gained focus' to log
        Execute command, 'Intercept C key'
        Start Loop While : [{PROCESSFOREGROUND:~targetProcess}] Equals '1'
            Pause 0.1 seconds
        End Loop
        Write [Red] 'Lost focus' to log
        Kill command, 'Intercept C key'
    End Condition
    Pause 0.1 seconds
End Loop

Intercept C key
Code: [Select]
Start Indefinite Loop
    Wait for key press [C]
    Execute command, 'Command to be triggered by C'
End Loop
OR
Intercept C key
Code: [Select]
Start Indefinite Loop
    Wait for key press [C]
End Loop

The latter would apply if you only want to toggle whether the keypress is intercepted, but still allow the command to execute when the target application doesn't have focus, in which case you'd use the "When I press keys" option for that command, but with its "Do not allow key to be passed through" option unchecked.
For the former, the "When I press keys" option would not be used.

There are caveats to this:
If you have a lot of commands you want to toggle, this will not scale well, especially depending on the performance of your machine, as all of those commands will need to be started and stopped.
On my machine, 40 commands performed well, but 100 commands caused a delay of about a second before all commands were fully stopped.

In theory, for singular keypresses (I.E. not key combinations), you could use a single "Wait For Key Press" action for all of them, and use a condition tree to perform a specific action for each key.
This could help mitigate the above.
If the condition tree is quite long, you could consider doing the processing in a separate command to have the "Wait For Key Press" action running again as soon as possible.
Using the "Resource balance offset" option could also help with this, however keep in mind that this is quite advanced, and can cause issues if you're not diligent about adding pauses where needed.

Stopping all commands would obviously also stop the monitoring command; this applied to any solution using a command, of course.

Adding additional commands to this system is obviously more hassle than just using the "When I press keys" option.

Because keys being intercepted depends on the action actively running, if you're mashing a key as fast as possible, some keypresses may slip through.
On my machine, this is not an issue at my normal typing speed; YMMV.

Starblue7

  • Full Member
  • ***
  • Posts: 131
Thanks Pfeil.

I'll digest this.  Likely I'll find some use for this in other cases.

I do have a monitoring command in my profile.  Though it's set not to stop if the target window loses focus and it doesn't utilize/need any voice or hotkeys.

So alt-tab'ing out with the linked solution above seems an OK method for now..

Though again, for simplicity's sake, it would just be wonderful I could check off a box underneath the
▣  'Do not allow key to be passed through'
     ▣  'Only to command's specified target'  <---

By doing this, Voice Attack can only care to block the key for the specified command's target application and not trap the key for any other application the user may be tabbed out to at the time.

Thanks


ADDITION:
Though.. If the game has in-game chat, then that's another bucket of worms to consider, as I wouldn't want to block the C key from being typed in the game's chat window...


iceblast

  • Sr. Member
  • ****
  • Posts: 372
Code: [Select]
Begin Text Compare : [{ACTIVEWINDOWTITLE}] Equals 'Game'
    Run a command for game.
End Condition - Exit when condition met
Press and release C key

Starblue7

  • Full Member
  • ***
  • Posts: 131
Code: [Select]
Begin Text Compare : [{ACTIVEWINDOWTITLE}] Equals 'Game'
    Run a command for game.
End Condition - Exit when condition met
Press and release C key

The problem is with this method is one of performance. 
It's possible that the typed 'c' won't be in order because the keypress is going thru VA.
So if I type:  confused, then it'll come out like  onfcused.

iceblast

  • Sr. Member
  • ****
  • Posts: 372
You were looking for away to have a profile for a game, and still be able to use the keyboard normally when the game isn't the active window. This will do that.

I have many commands like this, and the majority of the time, there really is no delay as you are saying. I don't know if you tried this, are just assuming it will work like that, but VA is usually much faster than people give it credit for.

Also, since you're the creator of the profile, you can always keep in mind, when you hit C, you might need to pause a split second, before going to the next key.

I have commands with 30+ Begin, and End stacks in it, and VA always instantly finds the proper Active Window command, and runs the command, otherwise, and goes all the way to the bottom of the command stack, and runs the default command for that key, and you literally can't tell it had to process through 30+ commands first before it ran the very last one.
I have a main Profile, and the majority of my games I play are in this profile, with commands set up like this. No need to switch profiles. It finds the Proper Active Window command out of the stack, and runs it instantly.

The only issue is if you are playing a fast trigger game, and your rapid firing constantly. This might or might not work, and if it does, then VA might eventually crash, or might not. If your playing a game this way, I would recommend it's own profile, or using macros built into you keyboard, or mouse, or both, and use VA in a less demanding way. VA is incredible, and I use it all day everyday with little issue. It's an extremely stable program, but there are limits to everything.

Update.

I just created that command, and it types instantly. I would never know VA was controlling the C key. I even rapidly hit cccccccccccccccccccccccccccccccccccccccccccccc. That line was created by hitting the C key as fast as I could and there was no delay.

Starblue7

  • Full Member
  • ***
  • Posts: 131
You were looking for away to have a profile for a game, and still be able to use the keyboard normally when the game isn't the active window. This will do that.

I have many commands like this, and the majority of the time, there really is no delay as you are saying. I don't know if you tried this, are just assuming it will work like that, but VA is usually much faster than people give it credit for.

Also, since you're the creator of the profile, you can always keep in mind, when you hit C, you might need to pause a split second, before going to the next key.

I have commands with 30+ Begin, and End stacks in it, and VA always instantly finds the proper Active Window command, and runs the command, otherwise, and goes all the way to the bottom of the command stack, and runs the default command for that key, and you literally can't tell it had to process through 30+ commands first before it ran the very last one.
I have a main Profile, and the majority of my games I play are in this profile, with commands set up like this. No need to switch profiles. It finds the Proper Active Window command out of the stack, and runs it instantly.

The only issue is if you are playing a fast trigger game, and your rapid firing constantly. This might or might not work, and if it does, then VA might eventually crash, or might not. If your playing a game this way, I would recommend it's own profile, or using macros built into you keyboard, or mouse, or both, and use VA in a less demanding way. VA is incredible, and I use it all day everyday with little issue. It's an extremely stable program, but there are limits to everything.

Update.

I just created that command, and it types instantly. I would never know VA was controlling the C key. I even rapidly hit cccccccccccccccccccccccccccccccccccccccccccccc. That line was created by hitting the C key as fast as I could and there was no delay.

Ice,  I appreciate your help/advice.

For me, I was trapping the C key with VA, and then having the command press the key after verifying a few Boolean states before doing so (if at all).
So this was generating the performance lag when typing in other applications.

I've recently just decided to give up with this approach and choose a key bind for the game function with a modifier combination, i.e. RCTRL + C

Maybe some of the delay I was encountering was with having the VA debug window open on the screen at the same time I was running the command.  As, I've noticed that if I run a command with the VA window open on screen (not minimized) that I also got performance hit with my mouse movement.  i.e.  moving the mouse at the same time as running the command caused mouse stutter, but when VA was minimized, I didn't really have that.
And on top of that I was calling(executing) another command from the original command.  That also could have been the cause of some of the performance issue.