Skip to content

Instantly share code, notes, and snippets.

@getify
Last active December 25, 2021 15:29
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save getify/e68630f5878fa7d6eaf30cd95e8a2bec to your computer and use it in GitHub Desktop.
Save getify/e68630f5878fa7d6eaf30cd95e8a2bec to your computer and use it in GitHub Desktop.
AutoHotKeys (AHK) script for cycling active focus between a selected ("recorded") set of open windows

Download Icon: https://jumpshare.com/v/T5yuKIP3Zc6Rr29GH5ye

How To Use

  1. While focused on an open window (like a browser or editor), hit the "record" hotkey (default: win+ctrl+shift+?) to add an app to the focus cycle list. Tooltips will pop up notifying you of recorded apps, or if there's an issue recording.

  2. To cycle forward through recorded apps, use the "cycle forward" hotkey (default: win+ctrl+shift+>), or click the system-tray icon, or click the menu Item "Cycle Apps" menu item.

  3. To cycle backward, use the "cycle backward" hotkey (default: win+ctrl+shift+<).

To Compile

Ahk2Exe.exe /in "SwitchAppFocus.ahk" /icon "main.ico"
#SingleInstance force
#WinActivateForce
SetTitleMatchMode RegEx
DetectHiddenWindows, On
apps := []
currentApp := 0
SetupMenu()
; win + ctrl + shift + >
#^+>::
CycleForward()
return
; win + ctrl + shift + <
#^+<::
CycleBackward()
return
; win + ctrl + shift + ?
#^+?::
RecordCurrentActiveApp()
return
; ***************************************
SetupMenu() {
Menu, Tray, Tip, Switch App Focus
Menu, Tray, UseErrorLevel
Menu, Tray, NoMainWindow
; remove all standard menu items
Menu, Tray, NoStandard
; add a cycle-apps-forward menu item (initially disabled)
Menu, Tray, Add, Cycle Apps, CycleForward
Menu, Tray, Disable, Cycle Apps
; add a reset-apps-list menu item
Menu, Tray, Add, Reset Apps List, ResetAppsList
; add a quit menu item
Menu, Tray, Add, Quit, Quit
; set the cycle-apps menu item to be the "default" menu item
Menu, Tray, Default, Cycle Apps
; set single clicks on the tray icon to activate the default menu item
Menu, Tray, Click, 1
SetupAppsList()
}
SetupAppsList() {
global apps
global currentApp
apps := []
currentApp := 0
Menu, Tray, Disable, Cycle Apps
; reset apps menu
try Menu, AppsMenu, DeleteAll
try Menu, Tray, Delete, Apps
Menu, AppsMenu, Add, --, Quit
Menu, Tray, Insert, Cycle Apps, Apps, :AppsMenu
Menu, AppsMenu, DeleteAll
Menu, Tray, Disable, Apps
}
ResetAppsList() {
SetupAppsList()
ShowToolTip("Recorded apps reset.")
}
RecordCurrentActiveApp() {
global apps
WinGetActiveTitle, winTitle
if (winTitle = "") {
ShowToolTip("No app focused!!!")
return
}
; construct pattern for app name
RegExMatch(winTitle,"O)(?:.+- )?(.+)$",winTitleParts)
appName := winTitleParts.Value(1)
StringLower, appNameLower, appName
appNamePattern := % ("i)" appNameLower "$")
; ensure this app isn't already in the list
Loop, % (apps.Length())
{
if (appNamePattern = apps[A_Index].pattern) {
ShowToolTip("App '" appName "' already recorded.")
return
}
}
apps.Push({ "label": appName, "pattern": appNamePattern })
Menu, Tray, Enable, Cycle Apps
Menu, Tray, Enable, Apps
Menu, AppsMenu, Add, %appName%, FocusApp
ShowToolTip("App '" appName "' recorded.")
}
FocusApp(appLabel,selectedApp) {
global apps
global currentApp
currentApp := selectedApp
whichWin := apps[currentApp].pattern
if (!WinActive(whichWin)) {
WinActivate, %whichWin%
}
}
CycleForward() {
global apps
if (apps.Length() > 0) {
CycleApps(1)
}
}
CycleBackward() {
global apps
if (apps.Length() > 0) {
CycleApps(-1)
}
}
CycleApps(cycleDir) {
global apps
global currentApp
numApps := apps.Length()
if (numApps = 0) {
return
}
nextIdx := currentApp
; find next/previous app (that's not currently active) to activate
Loop, %numApps%
{
nextIdx := Mod((nextIdx + cycleDir + numApps - 1),numApps) + 1
if (!WinActive(apps[nextIdx].pattern)) {
FocusApp(apps[nextIdx].label,nextIdx)
return
}
}
}
ShowToolTip(msg) {
; cancel previous timer in case it's still running
try SetTimer,, Off
HideToolTip()
ToolTip, %msg%
; hide the tooltip (once) 1000ms from now
SetTimer, HideToolTip, -1000
}
HideToolTip() {
ToolTip
}
ReloadApp() {
Reload
}
Quit() {
ExitApp
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment