GWKB2034 : Understanding Keyboard Key Inserts

Product: Window-Eyes
Author: Aaron Smith
Date Added: 08/16/2013
Last Modified: 08/16/2013

Assume a script contains the following instruction:

Sub Test()
 Keyboard.InsertKey vk_H, kmAlt
 End Sub
Set myHotkey = Keyboard.RegisterHotkey("Alt-F1", "Test")

Lets look at what happens when the Alt-F1 hotkey is pressed.

  • The user presses Alt-F1, so both keys are down. This fires the registered hotkey which executes the subroutine Test. Again, both keys are still down at this point.
  • The first line in the subroutine Test is Keyboard.InsertKey vk_H, kmAlt, meaning that Window-Eyes needs to send an Alt-H. So far, so good.
  • Before Window-Eyes sends any fake keys, it first looks at all the modifiers (Control, Shift, Alt, etc.) and if any of them are down, it sends a fake up. In this example, the Alt key is down, so Window-Eyes sends a fake up of the Alt key, and then sends through the Alt-H keystroke. In an application with a Help menu, this would cause the help menu to pop up. So far everything is perfect.
  • Window-Eyes knows that it sent the fake up of the modifier, so it looks to see if it needs to send a fake down. It would only do this if the physical Alt is still being help down by the user. If the user had let go of the physical Alt by the time Window-Eyes needed to see if it should send the fake down, Window-Eyes would abort the fake down to avoid leaving the Alt key stuck in the down position (like a sticky key). Because the script runs so fast, the user can't remove their hands from the initial Alt-F1 keystroke fast enough, so the physical Alt is still down. So Window-Eyes happily, and on cue, sends the fake down to tell Windows to get back in sync with the physical keyboard. Here's the rub: the sending of this fake Alt down cancels the help menu.

All is not lost. The solution is to add the line

Keyboard.WaitForAllKeysUp

as the first line of the Test subroutine. Like this:

Sub Test()
 Keyboard.WaitForAllKeysUp
 Keyboard.InsertKey vk_H, kmAlt
End Sub

WaitForAllKeysUp will tell Window-Eyes to wait until physical fingers let go of the physical Alt-F1 hotkey. Once all keys are up, Window-Eyes will send the fake Alt-H, and since the Alt is no longer physically down, it will not have to send a fake up. And because Window-Eyes did not send a fake up, it will never have to send a fake down.

Keep in mind when inserting keys that the fake ups and downs that happen behind the scenes may be happening, and can cause unexpected side-effects, most notably (at least in this example) closed the menu that was opened, causing speech to be interrupted (because any keypress will interrupt speech by design).

So when should you use WaitForAllKeysUp, and when shouldn't you? Understand that you can't insert keys while others are down without first lifting the other keys. Although Window-Eyes will account for key ups and key downs, it does have to play games with getting all the fake ups and downs of the modifiers correct. In some cases it doesn't matter if Window-Eyes send fake ups and downs. In others it does.

There is no black and white rule that says when you must use WaitForAllKeysUp. It's simply not that simple. You need to be conscious of what you are inserting, in what context, and then think to yourself, "what would happen if Window-Eyes has to send fake ups of modifiers and then fake downs of modifiers?" Then think about how that may or may not interact with what you are trying to accomplish. In general, the main thing to remember is interruptibility. Any down (fake or physical) will, by default, interrupt speech.