This shouldn't be here:
Code: Select all
A2 01D i d 0.00 LControl
A2 01D i u 0.01 LControl
I traced the LCtrl-down to some AltGr-unaware code that was intended to release the Alt or Win key, but ends up putting LCtrl back down after the OS releases it due to the RAlt-up. (It's a bug.)
The issue applies to any character which is mapped to an AltGr combo and followed by a non-AltGr combo.
Although it's not shown by KeyHistory, events generated by a script can be split into the following mutually exclusive possibilities:
- SendLevel 0 to 100. It won't directly trigger a hook hotkey if it doesn't exceed #InputLevel, but it can still affect the hotkey modifier state.
- KEY_IGNORE: Unlike standard SendLevel 0 events, hotkey modifier state is not updated. So for instance, #t::SendEvent {Raw}%a_long_string% would release LWin/RWin and possibly press Shift or AltGr temporarily, but still only #-modified hook hotkeys would fire unless the user physically presses or releases other modifiers during the send.
- KEY_PHYS_IGNORE: This is used in rare cases to notify other instances of the keyboard hook that the recorded physical state of the key should be updated even though the event is generated by AutoHotkey.
In this case, the LCtrl-down is marked with SendLevel 0, putting LCtrl into the "pressed" state for hotkeys.
LCtrl-up is marked with KEY_IGNORE, so it gets stuck down for hotkeys while the actual logical state is released.
To avoid the problem, we need one of
three four things:
- Eliminate the LCtrl down/up.
- Send both with a SendLevel, so the hotkey modifier state is changed and then changed back.
- Send both with KEY_IGNORE, so the hotkey modifier state is not changed.
- Send something that doesn't depend on modifiers being pushed down.
In general, when Send implicitly puts modifiers into (or out of) effect for each explicitly sent key, it uses KEY_IGNORE,
unless SendLevel is non-zero, in which case it uses that. (But prior to sending a special key such as {ASC nnnnn}, {U+nnnn} or any character which cannot be translated to a key combination, modifiers are
released using KEY_IGNORE and never SendLevel.) When the modifiers are restored at the end, it uses SendLevel 0.
So the workarounds are:
Code: Select all
; Affect the SendLevel of LCtrl-up prior to "
SendLevel, 1
SendInput, {Raw}"{"
Code: Select all
; "When the modifiers are restored at the end, it uses SendLevel 0."
SendInput, {Raw}"{
SendInput, "
Code: Select all
; Avoid the extra LCtrl by using LAlt (DEPENDENT ON KEYBOARD LAYOUT)
SendInput, ^!7"
Code: Select all
; Send a Unicode packet
SendInput, "{U+7B}"
Code: Select all
; Use Unicode packet mode (i.e. Text mode)
SendInput, {Text}"{"
Text mode is nearly always better than Raw mode when sending text (which is generally what Raw mode is used for). Unlike Raw mode and normal mode, Text mode is not dependent on the keyboard layout. Although modifiers are released for the duration of the Send (for maximum compatibility), no other modifier key presses or releases are generated. There is no translation to or from key codes, so you always get the right character (or nothing, in theory, if the application is incompatible). CapsLock has no effect, so it is not turned off or on.
Leli196 wrote:I replaced #InputLevel 1 by #UseHook and it changes nothing
I expected it to change nothing; i.e. for #UseHook and #InputLevel 1 to have the same effect. #InputLevel 1 implies #UseHook. The use of the keyboard hook vs. RegisterHotkey is what matters here, not #InputLevel.
Or so I thought. I was wrong, and you were not making sense. You used
#InputLevel 1 in the F1 script. It does not matter at all whether F1 uses the hook or not, or even whether you use a hotkey at all. What matters is
SendLevel, and #InputLevel affects the default SendLevel of the hotkey thread. If you "replaced
#InputLevel 1 by
#UseHook", it would in fact change the default SendLevel (put it back to 0 rather than 1), so it would change the result from "problem does not occur" to "problem occurs"--so "it changes nothing" would be
false. Perhaps what you meant was that "having #UseHook
vs. not having #UseHook makes no difference, the problem still occurs in the same way", but that's not how it came out.
it only applies for numbers
The key is "stuck" only in the hook modifier state. I suspect that all of your
hook hotkeys which required Ctrl were numeric. If you had other hotkeys, perhaps they were using RegisterHotkey, not the hook. Which method a hotkey uses sometimes depends on whether some other program or the system has registered that hotkey already. I do not believe that which OS you are on or whether the keys are numeric matters directly.