Unmatched Combo prefix KEYDOWN/KEYUP detection and recover, how to? - autohotkey

I am facing a subtle problem, on Autohotkey 1.1.36. Please see this Esc1.ahk :
~Esc & 1:: Esc1()
Esc1()
{
static s_count := 0
s_count++
tooltip, % "Esc1 #" s_count
}
The purpose of this script is: When I press combo-key Esc & 1, a tooltip appears indicating that combo-key is triggered.
Now do the following operation:
Press down Esc when Notepad (or any text editor, EmEditor in my own case) on the host machine is the active window.
Mouse click inside a VMware Workstation VM window.
Release Esc.
Mouse click EmEditor, making it host-machine active window again.
Press key 1, one or more times.
Now, surprising thing happens, tooltip Esc1 #2, Esc1 #3 etc appears, and the letter '1' does NOT get typed into the text editor -- although we have already released Esc.
We can easily imagine what has happened: When we deliberately release Esc not from the host machine but from inside the VM, Autohotkey engine running on the host machine does not get Esc's KEYUP event, so in step 5 above, Autohotkey still thinks the Esc key is being pressed down. This weird behavior persists until we press and release Esc again, from a non-VM window.
So my question is: Is it possible to detect this exceptional situation from our own AHK script, and, what AHK statements can be used to recover from this? By saying "exceptional", I mean: when the physical key-state is actually UP, while Autohotkey engine thinks it is DOWN.
When this mismatch symptom happens, GetKeyState("Esc", "P") returns 1, which means "key pressed", but the physical key state is released. No luck yet.

Related

Is there a way to always stay at the searched-for Symbol location when using vscode and pressing `esc` key?

Let's say I use Go to Symbol in Editor. Let's further say I have a function def run(): (this is Python) that I want to jump to.
If I type #run in the Symbol search dropbox, the viewport will shift to def run in the source code.
So far, so I good. I have found what I want!
At that point, if I press esc I jump back to my starting location, rather than staying at def run() in the source. I have to remember to press Enter to get out of Go to Symbol in Editor... and stay at my location.
How can I make it so esc, by itself, always leaves me where I have found the symbol in the text?
I.e. I want to get more the behavior I get from using Edit, Find where esc leaves at the pattern location. And pressing Enter when in Find mode jumps me to the next pattern hit, if any.
environment: macos, vscode 1.63.2 (latest as of now)
p.s. You also get the same behavior from a Go to Line/Column... dialog, esc will yank you back to your starting point, Enter will leave you at the new location.
I'm afraid it's not currently possible. I've tried to unbind every single keyboard shortcut bound to Escape key so it should basically become a dead key, yet even with this setting symbol suggest highlight were cancelled by pressing the Escape, so no luck.
Unbinding the primary action is normally prerequisite for changing default behaviour -- in your case for mapping it to "accept highlighted symbol" action (which I haven't found either) -- so it seems that Enter/Escape behaviour of symbol palette is not exposed for remapping.

WinActivate does not work as expected. Re-activating focus to the starting window

I am having some serious struggles fully grasping the control on activating windows and forcing their focus and foremost position.
In order to debug a larger script I made a separate script to test the use of WinActivate and again I am observing frustrating behaviour as it either all together ignores the title I have defined or is failing in some other way. In the smaller test script I am simply requesting that the window in which the hotkey was triggered be set as active after another action, specifically an input box
Below is the simple code for testing:
F10::
SetTitleMatchMode, 1
DetectHiddenWindows, Off
WinGetTitle, startTitle, A
msgbox % "Start Title = <" . startTitle . ">"
;WinActivate, startTitle
inputbox, mode, Test box, Testing,,260,160
sleep 500
WinActivate, startTitle
Return
This code does not properly activate the starting window. For example I execute the hotkey in an empty notepad window and upon submitting blank into the input box the focus becomes notepad++ on my second monitor. The second time I press the hotkey from within notepad (or another application) notepad does not lose focus. In a third execution I begin from notepad again and after the input box appears I switch the focus to another window. I again submit blank to the inputbox but that new window remains the focus and notepad is not activated or brought to the foremost position.
Can someone please explain to me what is going on with WinActivate?
I was having similar frustration with unexpected results making a windows script host file and I think I must be missing some fundamental detail in windows.
You are trying to activate a window that start with the literal text "startTitle".
You forgot(?) to either enter expression syntax with % or use the legacy way of referring to a variable %startTitle% (please don't use legacy).
Extra stuff:
You shouldn't specify SetTitleMatchMode and DetectHiddenWindows inside your hotkey statement. There is no need (unless there actually is) to set those every time you hit the hotkey. Just specify them at the top of your script once.
Both of them are useless for you though, below I'll show why. Also DetectHiddenWindows is already off by default.
WinGetTitle is not good to use for this. What you actually want to do is get the hwnd of the window you wish by using e.g. WinExist().
And then refer to the window by its hwnd. Much better than working with window titles, and impossible to match the wrong window as well. To refer to a window by its hwnd, you specify ahk_id followed by the hwnd on a WinTitle parameter.
And lastly, the concatenation operator . is redundant. Of course you may prefer to use it, but in case you didn't know, it can just be left out.
Here's your revised code:
F10::
_HWND := WinExist("A")
MsgBox, % "Start hwnd = <" _HWND ">"
InputBox, mode, Test box, Testing,,260,160
Sleep, 500
WinActivate, % "ahk_id " _HWND
Return

How do I force Windows to ignore an AutoHotKey and instead pass that hotkey directly to the active window?

My cPanel has a text editor that allows multi-cursor functionality using Ctrl-Alt-Up, Ctrl-Alt-Down, Ctrl-Alt-Right, and Ctrl-Alt-Left. Unfortunately, Windows has default hotkeys for these key combinations that rotate the display on your screen. When I try to use these key combinations in the text editor, Windows hijacks them before they can get to the active window.
I first searched to see if there's any reasonably easy way to turn off specific Windows default hotkeys. My search only turned up results that turn off all hotkeys. I then decided to download AutoHotKeys and see if I could write a script to achieve what I was looking to do. Below are some examples; I'll stick with Ctrl-Alt-Right just to select one out of the four:
First block of code is the same in all 4 attempts:
#NoEnv
SendMode Input
SetWorkingDir %A_ScriptDir%
SetTitleMatchMode, 2 ;this and the next line should only perform the scripted
#IfWinActive Opera ;hotkey if the active window's title contains 'Opera'
Attempt 1: Hotkey correctly bypasses Windows default display-rotating action, and sends the keystrokes to the text editor in Opera. However, the text editor enters the string "ight" wherever the cursor is. There is no Ctrl-Alt-R hotkey in the text editor, and it must not be a Windows default hotkey either. So it sends Ctrl-Alt-R to Opera, which does nothing. Then it sends "ight" which is typed out. (This is the "most successful" of the 4 attempts, but definitely does not achieve the desired outcome):
^!Right::
Send, ^!Right
return
Attempt 2: Only differs from #1 with SendPlay instead of Send. The Hotkey again correctly bypasses Windows default display-rotating action. However, the text editor does not appear to do anything at all:
^!Right::
SendPlay, ^!Right
return
Attempt 3: Back to just Send, but now with curly braces around the second "Right". Now the hotkey doesn't even bypass Windows default display-rotating action (this truly boggles my mind because I would have thought that the result of Attempt #1 proves that the active Opera window was found and the keystroke Ctrl-Alt-Right is correctly being read by the ^!Right in the first line. I'm so confused why adding the curly braces in the 2nd line is negating these things that seem as if they should already have occurred):
^!Right::
Send, ^!{Right}
return
Attempt 4: Only differs from #3 with SendPlay instead of Send. The Hotkey again correctly bypasses Windows default display-rotating action. However, the text editor does not appear to do anything at all:
^!Right::
SendPlay, ^!{Right}
return
To summarize:
----------| Curly Braces | No Curly Braces |
----------|------------------|-----------------------------|
Send | Win Dflt Action | types "ight" in text editor |
SendPlay | no action | no action |
So here's the final question, based on this table, it would appear to me that Send is definitely the way to go. If (as Attempt 3 appears to indicate) the curly brace is causing the display-rotation, how do I send this keystroke to the active window without Windows hijacking it? Obviously, #IfWinActive Opera is working correctly when the curly braces aren't used. Perhaps there is another directive that prevents or bypasses Windows' default action entirely?
If you don't wish to have the screen rotation functionality, this can be disabled in your graphics panel. I believe it's associated with Intel graphics application. It might be something like, right-click the desktop, select graphics options, choose hotkeys, then click disable. This is just guessing as I don't have that on the computer I'm using, but I've encountered it on others' computers before.
As for your hotkeys, you need the curly braces around the word "right" or it will just send the individual characters, just like actually typing it. Another issue is that you need a $ in front of your hotkey since it is self-referencing; that is, it's sending the same keystrokes that activate it.
If you haven't had a chance to check out the help file, I definitely recommend it.
https://www.autohotkey.com/docs/Hotkeys.htm#Symbols

Trying to recognize Fn + V on my keyboard

I hate that when I'm using my laptop on its own I often type FN+v when I mean to paste. So I decided to solve my problem with AHK. I installed a keyboard hook in my main script,and used that to extract the fn keys value, 163. My initial test worked, but adding the & to make it a modifier does not. What am I overlooking?
So this doesn't work
SC163 & v::
MsgBox, %A_ThisHotkey% was pressed.
return
but this did work
SC163::
MsgBox, %A_ThisHotkey% was pressed.
return
When you hit the FN key, it might be remapping the "v" to something else (like "Media_Play_Pause" button) in the keyboard driver. Therefore the key code wouldn't be SC163 & v but something like SC159.
The Special Keys section for mentions a method to get the Scan code:
Ensure that at least one script is running that is using the keyboard hook. You can tell if a script has the keyboard hook by opening its main window and selecting "View->Key history" from the menu bar.
Double-click that script's tray icon to open its main window.
Press one of the "mystery keys" on your keyboard.
Select the menu item "View->Key history"
Scroll down to the bottom of the page. Somewhere near the bottom are the key-down and key-up events for your key. NOTE: Some keys do not generate events and thus will not be visible here. If this is the case, you cannot directly make that particular key a hotkey because your keyboard driver or hardware handles it at a level too low for AutoHotkey to access. For possible solutions, see Special Keys.
If your key is detectable, make a note of the 3-digit hexadecimal value in the second column of the list (e.g. 159).

AutoHotKey stopped working after plugging new keyboard, even if I restart computer

I upgraded my keyboard. Problem is that now all the scripts stopped working. Even simple scripts from the tutorials don't work.
This happens in all applications, and ever if I plug in my old keyboard and restart the computer, autohotkey just does not work any more even in my previous configuration. I've tried also running in administrator mode.
What I do see however is the following, that the script works only once each time autohotkey is relaunced. For example:
^j::
Send, My First Script
Return
This works the first time ctrl-j is pressed, however afterwards it does not work again until I restart autohotkey.
Any ideas? I have Windows 10 x64, 1.1.23.05. I did not install any new drivers with the new keyboard (it's a standard usb keyboard, though a mechanical type).
Here are some more examples of simple scripts that don't work:
SetCapslockState AlwaysOff
In this case the first time I press the capslock, it's indeed ignored, but all the next times I click it works normally.
a::return
Again, same behaviour: a is ignored the first time, but next time it works normally, until I restart AHK (and again then it works only the first time).
Note that in all cases I'm running AHK only with the single line scripts you see; nothing else.
Below is the Key History and last lines when pressing Ctrl-J (of the first example)
Window: C:\Files\Tools\AutoHotKey\1.ahk - AutoHotkey v1.1.23.05
Keybd hook: yes
Mouse hook: no
Enabled Timers: 0 of 0 ()
Interrupted threads: 0
Paused threads: 0 of 0 (0 layers)
Modifiers (GetKeyState() now) =
Modifiers (Hook's Logical) =
Modifiers (Hook's Physical) =
Prefix key is down: no
NOTE: To disable the key history shown below, add the line "#KeyHistory 0" anywhere in the script. The same method can be used to change the size of the history buffer. For example: #KeyHistory 100 (Default is 40, Max is 500)
The oldest are listed first. VK=Virtual Key, SC=Scan Code, Elapsed=Seconds since the previous event. Types: h=Hook Hotkey, s=Suppressed (blocked), i=Ignored because it was generated by an AHK script, a=Artificial, #=Disabled via #IfWinActive/Exist, U=Unicode character (SendInput).
VK SC Type Up/Dn Elapsed Key Window
-------------------------------------------------------------------------------------------------------------
74 03F d 11.94 F5 C:\Files\Tools\AutoHotKey\1.ahk - AutoHotkey v1.1.23.05
A2 01D d 3.09 LControl *c:\Files\Tools\AutoHotKey\1.ahk - Notepad++
74 03F d 1.99 F5 C:\Files\Tools\AutoHotKey\1.ahk - AutoHotkey v1.1.23.05
Press [F5] to refresh.
Lines
001: Return (15.77)
003: if ( GetKeyState( "Control" , "P" ) )
007: Return (150.50)