; AutoHotKey script ; ; winii - Improved window management for windows ; Benjamin Cohen - bencoh@notk.org ; ; History: ; - 2011/05/09 : First version. Can only launch/activate some specific winows ; - 2011/05/11 : Now supports window tagging/virtual desktops ; ; Thanks to Christian Schüler for his code from ; DesktopSwitch ; ; -- ; bencoh ; ;------------------------------------------------------------------------------ ; Conf ;------------------------------------------------------------------------------ minttyPath = c:\cygwin\bin\mintty.exe minttyAdminPath = c:\cygwin\bin\mintty-admin.exe.lnk firefoxPath = c:\Program Files (x86)\Mozilla Firefox\firefox.exe resmonPath = c:\Windows\System32\resmon.exe debianWinName = debian [Running] ;------------------------------------------------------------------------------ ; Init ;------------------------------------------------------------------------------ ; DesktopSwitch Init SetBatchLines, -1 ; maximize script speed! SetWinDelay, -1 OnExit, CleanUp ; clean up in case of error (otherwise some windows will get lost) numDesktops := 9 ; maximum number of desktops curDesktop := 1 ; index number of current desktop WinGet, windows1, List ; get list of all currently visible windows Loop %numDesktops% lastActive%A_Index% = 0 ;------------------------------------------------------------------------------ ; Helper functions ;------------------------------------------------------------------------------ ; ; DesktopSwitch helper functions ; ; switch to the desktop with the given index number SwitchToDesktop(newDesktop) { global if (curDesktop <> newDesktop) { GetCurrentWindows(curDesktop) WinGet, lastActive%curDesktop%, ID, A ShowHideWindows(curDesktop, false) ShowHideWindows(newDesktop, true) curDesktop := newDesktop id := % lastActive%curDesktop% if id = 0 Send, {ALT DOWN}{TAB}{ALT UP} ; activate the right window else WinActivate ahk_id %id% } return } ; sends the given window from the current desktop to the given desktop SendToDesktop(windowID, newDesktop, remove) { global ; add window to destination desktop windows%newDesktop% += 1 i := windows%newDesktop% windows%newDesktop%%i% := windowID if ! (windowTagsCount%windowID% > 0) windowTagsCount%windowID% := 1 windowTagsCount%windowID% += 1 if (remove) { RemoveWindowID(curDesktop, windowID) lastActive%newDesktop% = %windowID% } } ; sends the currently active window to the given desktop SendActiveToDesktop(newDesktop) { global if (curDesktop <> newDesktop) { WinGet, id, ID, A SendToDesktop(id, newDesktop, true) } } ; Add the currently active window to the given desktop (and keep it) AddActiveToDesktop(newDesktop) { global if (curDesktop <> newDesktop) { WinGet, id, ID, A SendToDesktop(id, newDesktop, false) } } ; Add the currently active window to every desktop (and keep it) AddActiveToAll() { global Loop, %numDesktops% AddActiveToDesktop(A_Index) } ; Remove the currently active window from the current desktop RemoveCurrentWindow() { global WinGet, id, ID, A RemoveWindowID(curDesktop, id) } ; removes the given window id from the desktop RemoveWindowID(desktopIdx, ID) { global if ! (windowTagsCount%ID% > 0) windowTagsCount%ID% := 1 if ( windowTagsCount%ID% > 1) { windowTagsCount%ID% -= 1 removed := 0 Loop, % windows%desktopIdx% { if (windows%desktopIdx%%A_Index% = ID) { RemoveWindowID_byIndex(desktopIdx, A_Index) WinHide ahk_id %ID% removed := 1 Break } } if (removed = 0) WinHide ahk_id %ID% Send, {ALT DOWN}{TAB}{ALT UP} ; activate the right window } } ; this removes the window id at index from desktop number RemoveWindowID_byIndex(desktopIdx, ID_idx) { global Loop, % windows%desktopIdx% - ID_idx { idx1 := % A_Index + ID_idx - 1 idx2 := % A_Index + ID_idx windows%desktopIdx%%idx1% := windows%desktopIdx%%idx2% } windows%desktopIdx% -= 1 } ; this builds a list of all currently visible windows in stores it in desktop GetCurrentWindows(index) { global WinGet, windows%index%, List,,, Program Manager ; get list of all visible windows ; now remove task bar "window" (is there a simpler way?) Loop, % windows%index% { id := % windows%index%%A_Index% WinGetClass, windowClass, ahk_id %id% if windowClass = Shell_TrayWnd ; remove task bar window id { RemoveWindowID_byIndex(index, A_Index) Break } } } ; if show=true then shows windows of desktop %index%, otherwise hides them ShowHideWindows(index, show) { global Loop, % windows%index% { id := % windows%index%%A_Index% if show WinShow, ahk_id %id% else WinHide, ahk_id %id% } } ; ; General helper functions ; RunOrActivate(Target, WinTitle = "") { ; Get the filename without a path SplitPath, Target, TargetNameOnly Process, Exist, %TargetNameOnly% If ErrorLevel > 0 PID = %ErrorLevel% Else Run, %Target%, , , PID ; At least one app (Seapine TestTrack wouldn't always become the active ; window after using Run), so we always force a window activate. ; Activate by title if given, otherwise use PID. If WinTitle <> { SetTitleMatchMode, 2 WinWait, %WinTitle%, , 3 ; TrayTip, , Activating Window Title "%WinTitle%" (%TargetNameOnly%), 1 WinActivate, %WinTitle% ; WinShow, %WinTitle% } Else { WinWait, ahk_pid %PID%, , 3 ; TrayTip, , Activating PID %PID% (%TargetNameOnly%), 1 WinActivate, ahk_pid %PID% ; WinShow, ahk_pid %PID% } ; SetTimer, RemoveTrayTip, 1000 } RunOrActivateClass(Target, WinClass = "") { ; Get the filename without a path SplitPath, Target, TargetNameOnly Process, Exist, %TargetNameOnly% If ErrorLevel > 0 PID = %ErrorLevel% Else Run, %Target%, , , PID ; At least one app (Seapine TestTrack wouldn't always become the active ; window after using Run), so we always force a window activate. ; Activate by title if given, otherwise use PID. If WinClass <> { ; TrayTip, , Activating Window Class "%WinClass%" (%TargetNameOnly%), 1 WinActivate, ahk_class %WinClass% ; WinShow, ahk_class %WinClass% } Else { ; TrayTip, , Activating Window Class "%TargetNameOnly%", 1 WinActivate, ahk_class %TargetNameOnly% ; WinShow, ahk_class %TargetNameOnly% } ; SetTimer, RemoveTrayTip, 1000 } RunAndActivate(Target) { Run %Target%,,,mypid WinWait ahk_pid %mypid%,,3 WinActivate ahk_pid %mypid% WinShow ahk_pid %mypid% } ShowPIDBox() { InputBox, mypid, Enter pid of the program you want to show if ErrorLevel return TrayTip, , "Activating window of process %ahk_pid%", 1 WinShow ahk_pid %mypid% WinShow ahk_pid %mypid% } RemoveTrayTip: SetTimer, RemoveTrayTip, Off TrayTip return ;------------------------------------------------------------------------------ ; Mapping ;------------------------------------------------------------------------------ !Enter::RunAndActivate(minttyPath) !+Enter::RunAndActivate(minttyAdminPath) !F1::RunOrActivateClass(minttyPath, "mintty") !F2::RunOrActivateClass(firefoxPath, "MozillaWindowClass") !F11::RunOrActivateClass(resmonPath, "WdcWindow") !F8::ShowPIDBox() !F10::WinActivate, ahk_class CommunicatorMainWindowClass !Backspace:: WinShow, %debianWinName% WinActivate, %debianWinName% WinShow, %debianWinName% return !+c::Send !{F4} ; DesktopSwitch hotkeys !1::SwitchToDesktop(1) !2::SwitchToDesktop(2) !3::SwitchToDesktop(3) !4::SwitchToDesktop(4) !5::SwitchToDesktop(5) !6::SwitchToDesktop(6) !7::SwitchToDesktop(7) !8::SwitchToDesktop(8) !9::SwitchToDesktop(9) !+1::SendActiveToDesktop(1) !+2::SendActiveToDesktop(2) !+3::SendActiveToDesktop(3) !+4::SendActiveToDesktop(4) !+5::SendActiveToDesktop(5) !+6::SendActiveToDesktop(6) !+7::SendActiveToDesktop(7) !+8::SendActiveToDesktop(8) !+9::SendActiveToDesktop(9) !+0::AddActiveToAll() !^+1::AddActiveToDesktop(1) !^+2::AddActiveToDesktop(2) !^+3::AddActiveToDesktop(3) !^+4::AddActiveToDesktop(4) !^+5::AddActiveToDesktop(5) !^+6::AddActiveToDesktop(6) !^+7::AddActiveToDesktop(7) !^+8::AddActiveToDesktop(8) !^+9::AddActiveToDesktop(9) !-::RemoveCurrentWindow() ;------------------------------------------------------------------------------ ; Cleanup ;------------------------------------------------------------------------------ ; Show windows from all desktops on exit CleanUp: Loop, %numDesktops% ShowHideWindows(A_Index, true) ExitApp