commit 27c1da9ac761ab5db30a24dff655dc1c9e1cf35c Author: Damian Guth Date: Mon Aug 11 09:01:33 2025 +0200 Add files. diff --git a/VirtualDesktopAccessor.dll b/VirtualDesktopAccessor.dll new file mode 100644 index 0000000..d6af0ad Binary files /dev/null and b/VirtualDesktopAccessor.dll differ diff --git a/i3.ahk b/i3.ahk new file mode 100644 index 0000000..fce3dbc --- /dev/null +++ b/i3.ahk @@ -0,0 +1,179 @@ +; AutoHotkey v2 script +SetWorkingDir(A_ScriptDir) + +; Path to the DLL, relative to the script +VDA_PATH := A_ScriptDir . "\VirtualDesktopAccessor.dll" +hVirtualDesktopAccessor := DllCall("LoadLibrary", "Str", VDA_PATH, "Ptr") + +GetDesktopCountProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GetDesktopCount", "Ptr") +GoToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GoToDesktopNumber", "Ptr") +GetCurrentDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GetCurrentDesktopNumber", "Ptr") +IsWindowOnCurrentVirtualDesktopProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "IsWindowOnCurrentVirtualDesktop", "Ptr") +IsWindowOnDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "IsWindowOnDesktopNumber", "Ptr") +MoveWindowToDesktopNumberProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "MoveWindowToDesktopNumber", "Ptr") +IsPinnedWindowProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "IsPinnedWindow", "Ptr") +GetDesktopNameProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "GetDesktopName", "Ptr") +SetDesktopNameProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "SetDesktopName", "Ptr") +CreateDesktopProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "CreateDesktop", "Ptr") +RemoveDesktopProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "RemoveDesktop", "Ptr") + +; On change listeners +RegisterPostMessageHookProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "RegisterPostMessageHook", "Ptr") +UnregisterPostMessageHookProc := DllCall("GetProcAddress", "Ptr", hVirtualDesktopAccessor, "AStr", "UnregisterPostMessageHook", "Ptr") + +GetDesktopCount() { + global GetDesktopCountProc + count := DllCall(GetDesktopCountProc, "Int") + return count +} + +MoveCurrentWindowToDesktop(number) { + global MoveWindowToDesktopNumberProc, GoToDesktopNumberProc + activeHwnd := WinGetID("A") + DllCall(MoveWindowToDesktopNumberProc, "Ptr", activeHwnd, "Int", number, "Int") + DllCall(GoToDesktopNumberProc, "Int", number, "Int") +} + +GoToPrevDesktop() { + global GetCurrentDesktopNumberProc, GoToDesktopNumberProc + current := DllCall(GetCurrentDesktopNumberProc, "Int") + last_desktop := GetDesktopCount() - 1 + ; If current desktop is 0, go to last desktop + if (current = 0) { + MoveOrGotoDesktopNumber(last_desktop) + } else { + MoveOrGotoDesktopNumber(current - 1) + } + return +} + +GoToNextDesktop() { + global GetCurrentDesktopNumberProc, GoToDesktopNumberProc + current := DllCall(GetCurrentDesktopNumberProc, "Int") + last_desktop := GetDesktopCount() - 1 + ; If current desktop is last, go to first desktop + if (current = last_desktop) { + MoveOrGotoDesktopNumber(0) + } else { + MoveOrGotoDesktopNumber(current + 1) + } + return +} + +GoToDesktopNumber(num) { + global GoToDesktopNumberProc + global IsWindowOnDesktopNumberProc + global IsPinnedWindowProc + + ; Switch to target desktop + DllCall(GoToDesktopNumberProc, "Int", num, "Int") + + Sleep(150) ; Give Windows a moment to switch + + windows := WinGetList() + largestHwnd := 0 + largestArea := 0 + + for hwnd in windows { + if !WinExist("ahk_id " hwnd) + continue + if WinGetMinMax("ahk_id " hwnd) = -1 ; skip minimized + continue + if !WinGetTitle("ahk_id " hwnd) ; skip untitled + continue + + ; Skip pinned windows + if DllCall(IsPinnedWindowProc, "Ptr", hwnd, "Int") + continue + + ; Only keep windows on the target desktop + if !DllCall(IsWindowOnDesktopNumberProc, "Ptr", hwnd, "Int", num, "Int") + continue + + WinGetPos(&x, &y, &w, &h, "ahk_id " hwnd) + if (w <= 50 || h <= 50) ; skip tiny tool windows + continue + + area := w * h + if (area > largestArea) { + largestArea := area + largestHwnd := hwnd + } + } + + if (largestHwnd) + WinActivate("ahk_id " largestHwnd) + + return +} +MoveOrGotoDesktopNumber(num) { + ; If user is holding down Mouse left button, move the current window also + if (GetKeyState("LButton")) { + MoveCurrentWindowToDesktop(num) + } else { + GoToDesktopNumber(num) + } + return +} +GetDesktopName(num) { + global GetDesktopNameProc + utf8_buffer := Buffer(1024, 0) + ;ran := DllCall(GetDesktopNameProc, "Int", num, "Ptr", utf8_buffer, "Ptr", utf8_buffer.Size, "Int") + name := StrGet(utf8_buffer, 1024, "UTF-8") + return name +} +SetDesktopName(num, name) { + global SetDesktopNameProc + OutputDebug(name) + name_utf8 := Buffer(1024, 0) + StrPut(name, name_utf8, "UTF-8") + ran := DllCall(SetDesktopNameProc, "Int", num, "Ptr", name_utf8, "Int") + return ran +} +CreateDesktop() { + global CreateDesktopProc + ran := DllCall(CreateDesktopProc, "Int") + return ran +} +RemoveDesktop(remove_desktop_number, fallback_desktop_number) { + global RemoveDesktopProc + ran := DllCall(RemoveDesktopProc, "Int", remove_desktop_number, "Int", fallback_desktop_number, "Int") + return ran +} + +; SetDesktopName(0, "It works! 🐱") + +DllCall(RegisterPostMessageHookProc, "Ptr", A_ScriptHwnd, "Int", 0x1400 + 30, "Int") +OnMessage(0x1400 + 30, OnChangeDesktop) +OnChangeDesktop(wParam, lParam, msg, hwnd) { + Critical(1) + OldDesktop := wParam + 1 + NewDesktop := lParam + 1 + Name := GetDesktopName(NewDesktop - 1) + + ; Use Dbgview.exe to checkout the output debug logs + OutputDebug("Desktop changed to " Name " from " OldDesktop " to " NewDesktop) + ; TraySetIcon(".\Icons\icon" NewDesktop ".ico") +} + +!1::GoToDesktopNumber(0) +!2::GoToDesktopNumber(1) +!3::GoToDesktopNumber(2) +!q::GoToDesktopNumber(3) +!w::GoToDesktopNumber(4) +!e::GoToDesktopNumber(5) +!7::GoToDesktopNumber(6) +!8::GoToDesktopNumber(7) +!9::GoToDesktopNumber(8) +!0::GoToDesktopNumber(9) + +!+1::MoveCurrentWindowToDesktop(0) +!+2::MoveCurrentWindowToDesktop(1) +!+3::MoveCurrentWindowToDesktop(2) +!+4::MoveCurrentWindowToDesktop(3) +!+5::MoveCurrentWindowToDesktop(4) +!+6::MoveCurrentWindowToDesktop(5) +!+7::MoveCurrentWindowToDesktop(6) +!+8::MoveCurrentWindowToDesktop(7) +!+9::MoveCurrentWindowToDesktop(8) +!+0::MoveCurrentWindowToDesktop(9) \ No newline at end of file