Skip to content

Instantly share code, notes, and snippets.

@YosefBayoude
Last active September 13, 2023 15:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YosefBayoude/d2770207aca4c5f8e1cf27af58514153 to your computer and use it in GitHub Desktop.
Save YosefBayoude/d2770207aca4c5f8e1cf27af58514153 to your computer and use it in GitHub Desktop.
AutoHotkey Script to cycle through virtual desktops on Windows 10
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
;Goal
;The goal of this script is to allow, with the push of ONE button, to switch between 2 (or more) Windows Virtual Desktops
;Process
;This code retrieves a list of all VirtualDesktopIDs, a VirtualDesktopIDs is defined in Windows as a REG_BINARY
;This is list is stored into a single variable (= consecutive VirtualDesktopIDs in one variable), knowing the length of a single VirtualDesktopIDs, it cuts the variable into an array of VirtualDesktopIDs
;The script retrieves the current VirtualDesktopID, it looks for its position in the array, and uses that to know in what Virtual Desktop it is currently in
;The script then reacts accordingly
;Notes
;It is recommended to use 2 Virtual Desktops (3 max), however this could work with as many Virtual Desktops as desired
global ID_LENGTH := StrLen(getCurrentDesktopId()) ;Usually 32, but we never know with Windows Updates
F13:: ; <= Desired shortcut goes here*
if WinActive("ahk_exe VirtualBoxVM.exe") { ;When running a VM with VirtualBox, this will escape the character execute the script correctly
SendInput, {RControl up} ;Shortcut to escape VM control
}
if WinActive("ahk_exe vmplayer.exe") { ;When running a VM with VirtualBox, this will escape the character execute the script correctly
MsgBox, test
;SendInput, {Ctrl}{Alt} ;Shortcut to escape VM control
}
If (A_TimeSincePriorHotkey < 500) ;Prevents rapid double click, specifically set for iCue when keyboard changes profiles
Return
desktopCount := getArrayFromVirtualDesktopIds().MaxIndex()
currentDesktop := getCurrentDesktop()
if (currentDesktop = desktopCount) {
Loop, %desktopCount% {
SendInput ^#{Left}
Sleep 75 ;Delay between each press, tweak if you are experiencing issues going back to the first Virtual Desktop
}
return
} else {
SendInput ^#{Right}
return
}
getCurrentDesktop()
{
currentDesktopId := getCurrentDesktopId()
listDesktops := getArrayFromVirtualDesktopIds()
return ObjIndexOf(listDesktops, currentDesktopId)
}
getCurrentDesktopId()
{
sessionId := getSessionId() ;This variable is used to get the current VirtualDesktopID
RegRead, currentDesktopId, HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\SessionInfo\%sessionId%\VirtualDesktops, CurrentVirtualDesktop ;Stores the current VirtualDesktopID in CurrentDesktopId
return currentDesktopId
}
getArrayFromVirtualDesktopIds()
{
RegRead, virtualDesktopIds, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VirtualDesktops, VirtualDesktopIDs
listDesktops := []
while (virtualDesktopIds) { ;This loop will break up all the VirtualDesktopIDs neatly in an array
listDesktops.push(SubStr(virtualDesktopIds, 1 , ID_LENGTH))
StringTrimLeft virtualDesktopIds, virtualDesktopIds, ID_LENGTH
}
return listDesktops
}
ObjIndexOf(obj, item, case_sensitive:=false)
{
for i, val in obj {
if (case_sensitive ? (val == item) : (val = item))
return i
}
}
getSessionId()
{
ProcessId := DllCall("GetCurrentProcessId", "UInt")
if ErrorLevel {
OutputDebug, Error getting current process id: %ErrorLevel%
return
}
OutputDebug, Current Process Id: %ProcessId%
DllCall("ProcessIdToSessionId", "UInt", ProcessId, "UInt*", SessionId)
if ErrorLevel {
OutputDebug, Error getting session id: %ErrorLevel%
return
}
OutputDebug, Current Session Id: %SessionId%
return SessionId
}
@xan2622
Copy link

xan2622 commented Sep 6, 2023

Hi. Thank you for this script.
Do you plan to convert it to AutoHotKey v2 ?

@YosefBayoude
Copy link
Author

Hi. Thank you for this script.
Do you plan to convert it to AutoHotKey v2 ?

My pleasure, however I currently don’t have any plans to convert it to v2 though.

@KSankowicz
Copy link

KSankowicz commented Sep 13, 2023

This looks like it does exactly what I'd like it to do. However, it's not working, and I'm getting an error when I turn on "Warn":
Warning: This variable has not been assigned a value.
Specifically: SessionID (a local variable)
---> 096: DIICall("ProcesIdToSessionld", "Ulnt", Processld, "Ulnt*", Sessionld)

Desktop Cycle ahk Warning

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