AutoHotkey - Windows key, home row arrow keys, mouse shortcuts
And other hacks for Windows productivity
October 15, 2020 Ā· Felipe Vogel Ā·- SharpKeys for key remapping
- AutoHotkey: opening apps with the Windows key
- AutoHotkey: mouse shortcuts
- AutoHotkey: home row arrow keys
- AutoHotkey: modifier functions
- The upshot
UPDATE, 2021: For more keyboard adventures, see my more recent posts Learning Colemak and The Keyboardio Atreus.
Constantly switching between your keyboard and mouse can be frustrating, especially once you start paying attention to just how much you do it every day. (And now that Iāve made you start thinking about it, you wonāt be able to stop. Itās the pink elephant game all over again. Youāre welcome.)
So Iāve been on a quest to use my keyboard and mouse more efficiently, and hereās what I have so far.
SharpKeys for key remapping
In Windows, AutoHotkey is the Swiss Army knife of productivity. But I use SharpKeys for lower-level key remapping, and my AutoHotkey scripts only make sense in the context of those remappings, so letās start there.
In SharpKeys Iāve remapped the following keys:
- Caps Lock to Backspace
- Right Shift to Delete
- Backspace to Calculator
- Left Windows to F13
The first two are to bring Backspace and Delete closer to the home row. (I hardly ever used Caps Lock and Right Shift anyway.) The third is just to make use of the now-replaced Backspace key. Or you could remap it to F14 and make a script for F14 in AutoHotkey (see below).
The last remapping in the list disables Windows shortcuts, which are more annoying than useful, and in the process you gain a whole new modifier key. Weāll now use this wiped-clean Windows key to set up app hotkeys on the left side of the keyboard, and home row arrow keys on the right side.
AutoHotkey: opening apps with the Windows key
Previously Iāve shared how to set up a Windows Terminal hotkey using this same technique of remapping the Windows key. Here are some other essential hotkeys for our wiped-clean Windows key. You can also add hotkeys for favorite apps: for example, for work apps I have several āRunā lines under F13 & w::
(i.e. Win + W).
#CommentFlag //
#NoEnv
SendMode Input
// so that the right-click menu is not shown after using the
// right button as modifier (see mouse shortcuts below)
blockContextMenu := false
// = = = = = = = PROGRAMS = = = = = = =
// LWin is remapped to F13 in SharpKeys, to avoid Windows shortcuts
F13 & q::Send ^{Esc} // start menu
F13 & e::Run explore "C:\Users\User1\Downloads" // open Explorer
F13 & t::Run "C:\Program Files\Microsoft VS Code\Code.exe" "C:\Users\User1\Dropbox\.archive\.bin\Felipe-hotkeys.ahk"
// make AutoHotkey reload this script (do it right after saving the file)
F13 & s::Reload
return
// = = = = = = = USABILITY = = = = = = =
// context menu
RWin::Send {AppsKey}
return
// Esc closer to home row (and closes frequently-used apps)
// CapsLock is remapped to Backspace in Sharpkeys
F13 & Backspace::
WinGet, active_proc, ProcessName, A
if (active_proc = "explorer.exe"
|| active_proc = "cloudapp.exe"
|| active_proc = "jpegview64.exe")
Send !{F4}
else if !CloseBeeftext()
Send {Esc}
return
More keyboard shortcuts shortly, but first letās switch over to the mouse.
AutoHotkey: mouse shortcuts
A lot of power users scorn the mouse. Yes, it is far from ideal for many tasks. If Iām typing an email and I want to check on something in another tab, itās quicker to hop over with keyboard shortcutsāVimium makes it even easier. But Iām going to side with the masses and say that the mouse was a wonderful invention. Itās indispensable for browsing the web, photo editing, and many other tasks.
Maybe the reason I love my mouse is that itās so much more convenient now that Iāve given it some AutoHotkey love. The key is to cram useful navigation functions into the mouse buttons. I use a very basic mouse, but now its 7 buttons can do wonders. In particular, I constantly use the side buttons (XButton1
and XButton2
below) to switch windows and close tabs.
Thereās a lot going on in the snippet below, so hereās a visual summary of my mouse shortcuts:
// = = = = = = = MOUSE SHORTCUTS = = = = = = =
// mouse buttons to switch windows and tabs
XButton1:: // back button
// left or right button modifier: browser back
if (GetKeyState("LButton", "P")) {
Send !{Left}
} else if (GetKeyState("RButton", "P")) {
blockContextMenu := true
Send !{Left}
} else { // no mouse modifier: switch window
Send {LAlt Down}{Tab}
}
return
// allows back button to be pressed for Alt+Tab window menu to stay up
XButton1 Up::
if !(GetKeyState("LButton", "P") || GetKeyState("RButton", "P")) {
Send {LAlt Up}
}
return
XButton2:: // forward button
// left or right button modifier: refresh
if (GetKeyState("LButton", "P")) {
Send {F5}
} else if (GetKeyState("RButton", "P")) {
blockContextMenu := true
Send {F5}
// no mouse modifier: close tab or window
} else {
WinGet, active_proc, ProcessName, A
if (active_proc = "chrome.exe"
|| active_proc = "firefox.exe"
|| active_proc = "Code.exe")
Send ^{F4}
else if !CloseBeeftext()
Send !{F4}
}
return
MButton::
if !(WinActive("ahk_class CabinetWClass"))
{
// left or right button modifier: browser forward
if (GetKeyState("LButton", "P")) {
Send !{Right}
} else if (GetKeyState("RButton", "P")) {
blockContextMenu := true
Send !{Right}
} else // no mouse modifier
Send {MButton}
// delete in Explorer (best combined with Explorer's single-click mode)
} else {
Send {MButton}
Sleep 50
Send {Delete}
Sleep 50
Send {Space}
}
return
WheelLeft::
if !(WinActive("ahk_class CabinetWClass"))
Send ^+{Tab} // switch tabs left
else
Send !{Up} // up one level in Explorer
return
WheelRight::
if !(WinActive("ahk_class CabinetWClass"))
Send ^{Tab} // switch tabs right
else
// back in Explorer (i.e. down one level if went up one level)
Send !{Left}
return
// right click as wheel modifier: mega scroll
// the simpler method RButton & WheelUp causes problems with click state
WheelUp::
if (GetKeyState("RButton", "P")) {
blockContextMenu := true
Send {WheelUp 15}
} else
Send {WheelUp}
return
WheelDown::
if (GetKeyState("RButton", "P")) {
blockContextMenu := true
Send {WheelDown 15}
} else
Send {WheelDown}
return
// do not show context menu if mega scrolled
RButton Up::
if (blockContextMenu)
blockContextMenu := false
else
Send {RButton}
return
AutoHotkey: home row arrow keys
The more you use the keyboard instead of the mouse, the more youāll be annoyed with another common switch: from the home row down to the arrow keys. There is the traditional way of doing this with hjkl, but Iāve opted for my own setup: ijkl for arrow keys, plus h and ; for Home and End, plus u and o for Page Up and Page Down. All of these are activated with our faux Windows key pressed down. See the next section for an explanation of the modifier functions Shift()
, Alt()
, etc.
Hereās a summary of all my keyboard shortcuts and remappings, with a friendly wizard denoting our transformed Windows key. The icons on letter keys are for when the Windows key is pressed.
// = = = = = = = HOME ROW ARROW KEYS + home/end, page up/down = = = = = = =
F13 & j::
if Shift()
Send +{Left}
else if Alt()
Send !{Left}
else if Ctrl()
Send ^{Left}
else if CtrlShift()
Send ^+{Left}
else if AltShift()
Send !+{Left}
else if CtrlAlt()
Send ^!{Left}
else if CtrlAltShift()
Send ^!+{Left}
else Send {Left}
return
F13 & l::
if Shift()
Send +{Right}
else if Alt()
Send !{Right}
else if Ctrl()
Send ^{Right}
else if CtrlShift()
Send ^+{Right}
else if AltShift()
Send !+{Right}
else if CtrlAlt()
Send ^!{Right}
else if CtrlAltShift()
Send ^!+{Right}
else Send {Right}
return
F13 & i::
if Shift()
Send +{Up}
else if Alt()
Send !{Up}
else if Ctrl()
Send ^{Up}
else if CtrlShift()
Send ^+{Up}
else if AltShift()
Send !+{Up}
else if CtrlAlt()
Send ^!{Up}
else if CtrlAltShift()
Send ^!+{Up}
else Send {Up}
return
F13 & k::
if Shift()
Send +{Down}
else if Alt()
Send !{Down}
else if Ctrl()
Send ^{Down}
else if CtrlShift()
Send ^+{Down}
else if AltShift()
Send !+{Down}
else if CtrlAlt()
Send ^!{Down}
else if CtrlAltShift()
Send ^!+{Down}
else Send {Down}
return
F13 & h::
if Shift()
Send +{Home}
else Send {Home}
return
F13 & `;::
if Shift()
Send +{End}
else Send {End}
return
F13 & u::
if Shift()
Send +{PgUp}
else Send {PgUp}
return
F13 & o::
if Shift()
Send +{PgDn}
else Send {PgDn}
return
AutoHotkey: modifier functions
Weāve been using AutoHotkeyās custom combinations feature to make our remapped Windows key act like a modifier, so that F13 & j
is analogous to #j
(where #
is the regular Windows key). The limitation of this feature is that it doesnāt accept any additional modifiers: F13 & ^j
doesnāt work, nor does F13 & Ctrl & j
. So Iāve made functions that check for each modifier.
// = = = = = MODIFIERS FOR F13 (LWIN REMAPPED) = = = = =
Ctrl() {
if (GetKeyState("LAlt") || GetKeyState("LShift"))
return 0
else return GetKeyState("LCtrl")
}
Alt() {
if (GetKeyState("LCtrl") || GetKeyState("LShift"))
return 0
else return GetKeyState("LAlt")
}
Shift() {
if (GetKeyState("LCtrl") || GetKeyState("LAlt"))
return 0
else return GetKeyState("LShift")
}
CtrlAlt() {
if (GetKeyState("LShift"))
return 0
else return (GetKeyState("LCtrl") && GetKeyState("LAlt"))
}
CtrlShift() {
if (GetKeyState("LAlt"))
return 0
else return (GetKeyState("LCtrl") && GetKeyState("LShift"))
}
AltShift() {
if (GetKeyState("LCtrl"))
return 0
else return (GetKeyState("LAlt") && GetKeyState("LShift"))
}
CtrlAltShift() {
return (GetKeyState("LCtrl") && GetKeyState("LAlt") && GetKeyState("LShift"))
}
The upshot
Is this yet another case of spending more time than I save? Or getting sidetracked by automation? I donāt think so. Actually the time spent writing these scripts is trivial compared to how long it takes to train myself to use the dang shortcuts. But once you do, navigating windows, tabs, text, and the web is entirely different. Your fingers are like lightningānay, ātempestuous as the sea, and stronger than the foundations of the earth!āāto borrow the words of a similarly empowered person.
Wellā¦ just donāt let it get to your head, thatās all.