Skip to content

Instantly share code, notes, and snippets.

@necaran
Last active March 30, 2024 22:31
Show Gist options
  • Save necaran/61e296025b8aed3c904fe66bedb2ca6c to your computer and use it in GitHub Desktop.
Save necaran/61e296025b8aed3c904fe66bedb2ca6c to your computer and use it in GitHub Desktop.
Stop Alt key from focusing menu and more with AutoHotkey

Stop Alt key from focusing menu and more with AutoHotkey

TL;DR

  • Should be less likely to have side effects such as PowerShell/PSReadLine#2036.
  • Do not reduce the code to *Alt:: and ~*Alt up::, which can behave wired with RAlt.
*LAlt::SetKeyDelay(-1), Send("{LAlt down}{Shift}"), KeyWait("LAlt")
~*LAlt up::SetKeyDelay(-1), Send("{Blind}{LAlt up}")

*RAlt::SetKeyDelay(-1), Send("{RAlt down}{Shift}"), KeyWait("RAlt")
~*RAlt up::SetKeyDelay(-1), Send("{Blind}{RAlt up}")
  • Disable Alt+Shift to switch input language/layout if you have not.
reg add "HKCU\Keyboard Layout\Toggle" /v "Hotkey" /t REG_SZ /d "3" /f
reg add "HKCU\Keyboard Layout\Toggle" /v "Language Hotkey" /t REG_SZ /d "3" /f
reg add "HKCU\Keyboard Layout\Toggle" /v "Layout Hotkey" /t REG_SZ /d "3" /f

Explanation

Internal remapping

  • When a script is launched, each remapping is translated by AHK into a pair of hotkeys.
  • From
LAlt::LCtrl
  • To
*LAlt::{
	SetKeyDelay -1
	Send "{Blind}{LCtrl DownR}"
}
*LAlt up::{
	SetKeyDelay -1
	Send "{Blind}{LCtrl Up}"
}

Modified remapping

  • A modified remapping is a mapping explicitly declared with tweaks.

A modified LAlt::LAlt for example

  • The {Shift} between keydown and keyup should prevent most programs from focusing menu. Without {Blind} at keydown, Shift should be pushed back when needed.
  • The KeyWait might prevent side effects due to repeated keydown. But it does not affect the behavior when you are physically holding Alt down. For example in Explorer, you can still hold Alt and drag a file to crate a shortcut. And in Firefox, you can still hold Alt and select the text of hyperlinks without opening them.
  • I might not have covered all the possibilities, so feel free to try your own modifications with programs you use.
*LAlt::{
	SetKeyDelay -1
	Send "{LAlt down}{Shift}"
	KeyWait "LAlt"
}
~*LAlt up::{
	SetKeyDelay -1
	Send "{Blind}{LAlt up}"
}

Deprecated

  • In case you have issue with Alt+Shift with the current approach.
  • The {Ctrl up} between keydown and keyup should prevent most programs from focusing menu. Note that {Ctrl up} is better than {Ctrl} because of less keystrokes and less possibility of side effects.
  • In some programs such as Task Manager, you need {vkFF up} immediately after keydown to suppress keytips.
  • Sending {Ctrl up} here might cause issues for hotkeys with Ctrl (e.g. !a::Send "^a"), so a {vkFF up} instead.
  • On the other hand, sending {vkFF up} at keydown generally may cause other issues. For example if you have a hotkey !c::Send "^{Ins}" and try to select and copy text form a terminal with a remote session, sending a {vkFF up} at keydown might refresh the output and thus cancel the selection before C is even pressed.
*LAlt::SetKeyDelay(-1), Send("{Blind}{LAlt down}"), KeyWait("LAlt")
~*LAlt up::SetKeyDelay(-1), Send("{Blind}{Ctrl up}{LAlt up}")

*RAlt::SetKeyDelay(-1), Send("{Blind}{RAlt down}"), KeyWait("RAlt")
~*RAlt up::SetKeyDelay(-1), Send("{Blind}{Ctrl up}{RAlt up}")

#HotIf WinActive("ahk_exe Taskmgr.exe")
*LAlt::SetKeyDelay(-1), Send("{Blind}{LAlt down}{vkFF up}"), KeyWait("LAlt")
*RAlt::SetKeyDelay(-1), Send("{Blind}{RAlt down}{vkFF up}"), KeyWait("RAlt")
#HotIf

Advanced

  • Now that your Alt keys are free. You can make good use of them.

Switch input language when shortly pressed alone

  • A good example is to use them to switch input language.
  • The Lang() function
    • Switch input language by sending WM_INPUTLANGCHANGEREQUEST(0x50).
    • Make sure CpasLock is always off with SetCapsLockState "AlwaysOff".
  • This example uses LAlt for English (1033), and RAlt for Japanese (1041). Find your LANGID here.
  • You need KeyWait at keydown for proper A_TimeSincePriorHotkey. The threshold here is 200 ms. You can change the number or omit the condition as you wish.
  • If you use CapsLock as a custom modifier, add || GetKeyState("CapsLock","P") inside !().
  • For Japanese, send ^{vkF2} to ensure Hiragana mode after switching. You can also send !{vkF1} for Katakana. If you use other languages, this statement can be safely omitted.
Lang(id){
	try PostMessage 0x50,,id,, ControlGetFocus("A") || "A"
	SetCapsLockState "AlwaysOff"
}

*LAlt::SetKeyDelay(-1), Send("{LAlt down}{Shift}"), KeyWait("LAlt")
*RAlt::SetKeyDelay(-1), Send("{RAlt down}{Shift}"), KeyWait("RAlt")

~*LAlt up::{
	SetKeyDelay -1
	Send "{Blind}{LAlt up}"
	if ("*" A_PriorKey)=A_PriorHotkey && A_TimeSincePriorHotkey<200 && !(GetKeyState("Shift","P") || GetKeyState("Ctrl","P") || GetKeyState("Alt","P") || GetKeyState("LWin","P"))
		Lang(1033)
}

~*RAlt up::{
	SetKeyDelay -1
	Send "{Blind}{RAlt up}"
	if ("*" A_PriorKey)=A_PriorHotkey && A_TimeSincePriorHotkey<200 && !(GetKeyState("Shift","P") || GetKeyState("Ctrl","P") || GetKeyState("Alt","P") || GetKeyState("LWin","P")) {
		Lang(1041)
		Send "^{vkF2}"
	}
}
@eugenesvk
Copy link

Just a tip: to guard against a nonexisting active window you might want to fallback to shortcuts

  if not WinExist("A") { ; no window to post message to, use shortcuts (must be set in the OS settings "Text Services and Input Language")
    if        target = 'en' { ; this is from a general layout toggle function, for you more narrow case can just use specific shortcut in each LAlt/RAlt
      SendInput('+!6')
    } else if target = 'jap' {
      SendInput('+!7')
    } else { ; not needed for your specific case, but for a general layout switching function that can also toggle
      SendInput('#{Space}')
    }
    return
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment