From a850e695bec8fcf88fafb8142d8d130d5e82348c Mon Sep 17 00:00:00 2001 From: Cynthia Foxwell Date: Thu, 31 Aug 2023 22:13:42 -0600 Subject: [PATCH] backlog, dos2unix pass --- src/Bar.ahk | 1658 ++++++++++++------------- src/Config.ahk | 1080 ++++++++--------- src/Debug.ahk | 324 ++--- src/Main.ahk | 390 +++--- src/Manager.ahk | 2532 ++++++++++++++++++++------------------- src/Monitor.ahk | 746 ++++++------ src/ResourceMonitor.ahk | 380 +++--- src/Tiler.ahk | 143 ++- src/View.ahk | 868 +++++++------- tools/hul.ahk | 374 +++--- 10 files changed, 4301 insertions(+), 4194 deletions(-) diff --git a/src/Bar.ahk b/src/Bar.ahk index 4452d72..35ed113 100644 --- a/src/Bar.ahk +++ b/src/Bar.ahk @@ -1,823 +1,835 @@ -/* - bug.n -- tiling window management - Copyright (c) 2010-2019 Joshua Fuhs, joten - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - @license GNU General Public License version 3 - ../LICENSE.md or - - @version 9.1.0 -*/ - -Bar_init(m) { - Local appBarMsg, anyText, color, color0, GuiN, h1, h2, i, id, id0, text, text0, titleWidth, trayWndId, w, wndId, wndTitle, wndWidth, x1, x2, y1, y2 - - If (SubStr(Config_barWidth, 0) = "%") { - StringTrimRight, wndWidth, Config_barWidth, 1 - wndWidth := Round(Monitor_#%m%_width * wndWidth / 100) - } Else - wndWidth := Config_barWidth - - wndWidth := Round(wndWidth / mmngr1.monitors[m].scaleX) - If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) { - Bar_ctrlHeight := Round(Bar_ctrlHeight / mmngr1.monitors[m].scaleY) - Bar_height := Round(Bar_height / mmngr1.monitors[m].scaleY) - } - - Monitor_#%m%_barWidth := wndWidth - titleWidth := wndWidth - h1 := Bar_ctrlHeight - x1 := Config_barItemSpacing - x2 := wndWidth - y1 := 0 - y2 := (Bar_ctrlHeight - Bar_textHeight) / 2 - h2 := Bar_textHeight - - ;; Create the GUI window - wndTitle := "bug.n_BAR_" m - GuiN := (m - 1) + 1 - Debug_logMessage("DEBUG[6] Bar_init(): Gui, " . GuiN . ": Default", 6) - Gui, %GuiN%: Default - Gui, Destroy - Gui, -Caption +LabelBar_Gui +LastFound +ToolWindow - Gui, Color, %Config_backColor_#1_#3% - Gui, Font, c%Config_fontColor_#1_#3% s%Config_fontSize%, %Config_fontName% - - ;; Views - Loop, % Config_viewCount { - w := Bar_getTextWidth(Config_viewNames_#%A_Index%) - Bar_addElement(m, "view_#" A_Index, " " Config_viewNames_#%A_Index%, x1, y1, w, Config_backColor_#1_#1, Config_foreColor_#1_#1, Config_fontColor_#1_#1) - titleWidth -= w - x1 += w + Config_barItemSpacing - } - ;; Layout - w := Bar_getTextWidth("??????") - Bar_addElement(m, "layout", "??????", x1, y1, w, Config_backColor_#1_#2, Config_foreColor_#1_#2, Config_fontColor_#1_#2) - titleWidth -= w - x1 += w + Config_barItemSpacing - - ;; The x-position and width of the sub-windows right of the window title are set from the right. - ;; ;;;<shebang>;<time>;<date>;<anyText>;<battery>;<volumeLevel> - ;color := "4" - ;id := "shebang" - ;text := " #! " - color := "" - id := "" - text := "" - If Config_readinTime { - color .= "4" - id .= "time" - text .= "" . Config_readinTimeFormat - } - If (Config_readinDate And !Config_combineDateAndTime) { - color .= ";5" - id .= ";date" - text .= ";" . Config_readinDateFormat - } - If Config_readinVolume { - color .= ";9" - id .= ";volume" - text .= ";???%" - } - If Config_readinRam { - color .= ";6" - id .= ";ram" - text .= ";" . ResourceMonitor_getRamText() - } - If Config_readinCpu { - color .= ";7" - id .= ";cpu" - text .= ";" . ResourceMonitor_getCpuText() - } - If Config_readinBat { - color .= ";8" - id .= ";battery" - text .= ";???%" - } - If Config_readinMusic { - color .= ";10" - id .= ";music" - text .= ";" . MusicBee_GetNowPlaying() - } - StringSplit, color, color, `; - StringSplit, id, id, `; - StringSplit, text, text, `; - Loop, % id0 { - elemId := id%A_Index% - If (elemId = "shebang") - Gui, -Disabled - w := Bar_getTextWidth(text%A_Index%) - x2 -= w - titleWidth -= w - i := color%A_Index% - iconIndex := i - 3 - icon := Config_barIcon_#%iconIndex% - iconId := % elemId "_icon" - Bar_addElement(m, elemId, text%A_Index%, x2, y1, wndWidth, Config_backColor_#1_#%i%, Config_foreColor_#1_#%i%, Config_fontColor_#1_#%i%) - Bar_addElement(m, iconId, icon, x2, y1, wndWidth, Config_backColor_#1_#%i%, Config_foreColor_#1_#%i%, Config_fontColor_#1_#%i%, Config_iconFontSize, Config_iconFontName) - If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) { - trayWndId := WinExist("ahk_class " Monitor_#%m%_taskBarClass) - ControlGet, TrayRoot, Hwnd, , TrayNotifyWnd1, ahk_id %trayWndId% - - DllCall("SetParent", "UInt", HwndBar_#%m%_%elemId%_hwnd, "UInt", TrayRoot) - DllCall("SetParent", "UInt", HwndBar_#%m%_%iconId%_hwnd, "UInt", TrayRoot) - } - GuiControl, -Center, Bar_#%m%_%elemId% - GuiControl, -Center, Bar_#%m%_%iconId% - } - - ;; Window title (remaining space) - If Not Config_singleRowBar { - titleWidth := wndWidth - x1 := 0 - y1 += h1 - y2 += h1 - } - If Config_readinTitle - Bar_addElement(m, "title", "", x1, y1, titleWidth, Config_backColor_#1_#3, Config_foreColor_#1_#3, Config_fontColor_#1_#3) - - If (Config_horizontalBarPos = "left") - x1 := 0 - Else If (Config_horizontalBarPos = "right") - x1 := Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX - Else If (Config_horizontalBarPos = "center") - x1 := (Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX) / 2 - Else If (Config_horizontalBarPos >= 0) - x1 := Config_horizontalBarPos - Else If (Config_horizontalBarPos < 0) - x1 := Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX + Config_horizontalBarPos - If Not (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) - x1 += Monitor_#%m%_x - x1 := Round(x1) - - Bar_#%m%_titleWidth := titleWidth - Monitor_#%m%_barX := x1 - y1 := Monitor_#%m%_barY - - If Monitor_#%m%_showBar - Gui, Show, NoActivate x%x1% y%y1% w%wndWidth% h%Bar_height%, %wndTitle% - Else - Gui, Show, NoActivate Hide x%x1% y%y1% w%wndWidth% h%Bar_height%, %wndTitle% - WinSet, Transparent, %Config_barTransparency%, %wndTitle% - wndId := WinExist(wndTitle) - Bar_appBarData := "" - If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) { - trayWndId := WinExist("ahk_class " Monitor_#%m%_taskBarClass) - - ; FIXME: find a specific ReBarWindow32 named a certain thing instead of first one - ControlGet, ToolbarRoot, Hwnd, , ReBarWindow321, ahk_id %trayWndId% - ControlGet, Toolbar, Hwnd, , ToolbarWindow321, ahk_id %ToolbarRoot% - DllCall("SetParent", "UInt", wndId, "UInt", Toolbar) - If (Config_barTaskbarBlend) { - Gui, Color, 000000, %wndTitle% - } - - If (Config_classicThemeTaskbar) { - WinSet, Style, -0x40000, ahk_id %trayWndId% ; WS_THICKFRAME - WinSet, Style, +0x80, ahk_id %trayWndId% ; DS_MODALFRAME - WinSet, Style, +0x0004, ahk_id %trayWndId% ; DS_3DLOOK - - WinSet, ExStyle, +0x1, ahk_id %trayWndId% ; WS_EX_DLGMODALFRAME - WinSet, ExStyle, +0x20000, ahk_id %trayWndId% ; WS_EX_STATICEDGE - } - } Else { - appBarMsg := DllCall("RegisterWindowMessage", Str, "AppBarMsg") - - ;; appBarData: http://msdn2.microsoft.com/en-us/library/ms538008.aspx - VarSetCapacity(Bar_appBarData, 36, 0) - offset := NumPut( 36, Bar_appBarData) - offset := NumPut( wndId, offset+0) - offset := NumPut( appBarMsg, offset+0) - offset := NumPut( 1, offset+0) - offset := NumPut( x1, offset+0) - offset := NumPut( y1, offset+0) - offset := NumPut( x1 + wndWidth, offset+0) - offset := NumPut(y1 + Bar_height, offset+0) - offset := NumPut( 1, offset+0) - - DllCall("Shell32.dll\SHAppBarMessage", "UInt", (ABM_NEW := 0x0) , "UInt", &Bar_appBarData) - DllCall("Shell32.dll\SHAppBarMessage", "UInt", (ABM_QUERYPOS := 0x2), "UInt", &Bar_appBarData) - DllCall("Shell32.dll\SHAppBarMessage", "UInt", (ABM_SETPOS := 0x3) , "UInt", &Bar_appBarData) - ;; SKAN: Crazy Scripting : Quick Launcher for Portable Apps (http://www.autohotkey.com/forum/topic22398.html) - } - - Bar_BinaryClockChars := ["⠀","⠈","⠐","⠘","⠠","⠨","⠰","⠸","⢀","⢈","⠁","⠉","⠑","⠙","⠡","⠩","⠱","⠹","⢁","⢉","⠂","⠊","⠒","⠚","⠢","⠪","⠲","⠺","⢂","⢊","⠃","⠋","⠓","⠛","⠣","⠫","⠳","⠻","⢃","⢋","⠄","⠌","⠔","⠜","⠤","⠬","⠴","⠼","⢄","⢌","⠅","⠍","⠕","⠝","⠥","⠭","⠵","⠽","⢅","⢍"] - Bar_TimeDateState := 0 -} - -Bar_initCmdGui() -{ - Global Bar_#0_#0, Bar_#0_#0H, Bar_#0_#0W, Bar_#0_#1, Bar_cmdGuiIsVisible, Config_barCommands, Config_fontName, Config_fontSize - Global Config_backColor_#1_#3, Config_fontColor_#1_#3, Config_foreColor_#1_#3 - - Bar_#0_#0 := "" - Bar_cmdGuiIsVisible := False - wndTitle := "bug.n_BAR_0" - Gui, 99: Default - Gui, +LabelBar_cmdGui - IfWinExist, %wndTitle% - Gui, Destroy - Gui, +LastFound -Caption +ToolWindow +AlwaysOnTop +Delimiter`; - Gui, Color, Default - Gui, Font, s%Config_fontSize%, %Config_fontName% - StringSplit, cmd, Config_barCommands, `; - Gui, Add, ComboBox, x10 y10 r%cmd0% w300 Background%Config_backColor_#1_#3% c%Config_fontColor_#1_#3% Simple vBar_#0_#0 gBar_cmdGuiEnter, % Config_barCommands - Gui, Add, Edit, Y0 w300 Hidden vBar_#0_#1 gBar_cmdGuiEnter - Gui, Add, Button, Y0 Hidden Default gBar_cmdGuiEnter, OK - GuiControlGet, Bar_#0_#0, Pos - Bar_#0_#0H += 20 - Bar_#0_#0W += 20 - Gui, Show, Hide w%Bar_#0_#0W% h%Bar_#0_#0H%, %wndTitle% -} - -Bar_addElement(m, id, text, x, y1, width, backColor, foreColor, fontColor, fontSize="", fontName="") { - Local y2 - - if (fontSize == "") { - fontSize = %Config_fontSize% - } - if (fontName == "") { - fontName = %Config_fontName% - } - - y2 := y1 + (Bar_ctrlHeight - Bar_textHeight) / 2 - - Gui, Add, Text, x%x% y%y1% w%width% h%Bar_ctrlHeight% BackgroundTrans vBar_#%m%_%id%_event gBar_GuiClick, - ;Gui, Add, Progress, x%x% y%y1% w%width% h%Bar_ctrlHeight% Background%backColor% c%foreColor% vBar_#%m%_%id%_highlighted - ;GuiControl, , Bar_#%m%_%id%_highlighted, 100 - Gui, Font, c%fontColor% s%fontSize%, %fontName% - Gui, Add, Text, x%x% y%y2% w%width% h%Bar_textHeight% BackgroundTrans Center vBar_#%m%_%id% HwndBar_#%m%_%id%_hwnd, %text% -} - -Bar_cmdGuiEnter: - If (A_GuiControl = "OK") Or (A_GuiControl = "Bar_#0_#0" And A_GuiControlEvent = "DoubleClick") { - Gui, Submit, NoHide - Bar_cmdGuiIsVisible := False - Gui, Cancel - WinActivate, ahk_id %Bar_aWndId% - Main_evalCommand(Bar_#0_#0) - Bar_#0_#0 := "" - } Else If (A_GuiControl = "Bar_#0_#1") { - Gui, Submit, NoHide - Debug_logMessage("DEBUG[6] Bar_cmdGuiEnter; command: " . Bar_#0_#1, 6) - Loop, Parse, Bar_#0_#1, `n, `r - Main_evalCommand(A_LoopField) - } -Return - -Bar_cmdGuiEscape: - Bar_cmdGuiIsVisible := False - Gui, Cancel - WinActivate, ahk_id %Bar_aWndId% -Return - -Bar_getHeight() -{ - Global Bar_#0_#1, Bar_#0_#1H, Bar_#0_#2, Bar_#0_#2H, Bar_ctrlHeight, Bar_height, Bar_textHeight - Global Config_fontName, Config_fontSize, Config_singleRowBar, Config_spaciousBar, Config_verticalBarPos, Config_classicThemeFixes - - wndTitle := "bug.n_BAR_0" - Gui, 99: Default - Gui, Font, s%Config_fontSize%, %Config_fontName% - Gui, Add, Text, x0 y0 vBar_#0_#1, | - GuiControlGet, Bar_#0_#1, Pos - Bar_textHeight := Bar_#0_#1H - If Config_spaciousBar - { - Gui, Add, ComboBox, r9 x0 y0 vBar_#0_#2, | - GuiControlGet, Bar_#0_#2, Pos - Bar_ctrlHeight := Bar_#0_#2H - } - Else - Bar_ctrlHeight := Bar_textHeight - Gui, Destroy - - Bar_height := Bar_ctrlHeight - If Not Config_singleRowBar - Bar_height *= 2 - If (Config_verticalBarPos = "tray") - { - WinGetPos, , , , buttonH, Start ahk_class Button - WinGetPos, , , , barH, ahk_class Shell_TrayWnd - If WinExist("Start ahk_class Button") And (buttonH < barH) - Bar_height := buttonH - Else - Bar_height := barH - Bar_ctrlHeight := Bar_height - If Not Config_singleRowBar - Bar_ctrlHeight := Bar_height / 2 - - If (Config_classicThemeFixes) { - Bar_height := 22 - Bar_ctrlHeight := 22 - } - } -} - -Bar_getTextWidth(x, reverse=False) -{ - Global Config_fontSize - - If reverse - { ;; 'reverse' calculates the number of characters to a given width. - w := x - i := w / (Config_fontSize - 1) - If (Config_fontSize = 7 Or (Config_fontSize > 8 And Config_fontSize < 13)) - i := w / (Config_fontSize - 2) - Else If (Config_fontSize > 12 And Config_fontSize < 18) - i := w / (Config_fontSize - 3) - Else If (Config_fontSize > 17) - i := w / (Config_fontSize - 4) - textWidth := i - } - Else - { ;; 'else' calculates the width to a given string. - textWidth := StrLen(x) * (Config_fontSize - 1) - If (Config_fontSize = 7 Or (Config_fontSize > 8 And Config_fontSize < 13)) - textWidth := StrLen(x) * (Config_fontSize - 2) - Else If (Config_fontSize > 12 And Config_fontSize < 18) - textWidth := StrLen(x) * (Config_fontSize - 3) - Else If (Config_fontSize > 17) - textWidth := StrLen(x) * (Config_fontSize - 4) - } - - Return, textWidth -} - -Bar_getTrueTextWidth(controlHwnd, newText) { - dc := DllCall("GetDC", "Ptr", controlHwnd) - - ; 0x31 = WM_GETFONT - SendMessage 0x31,,,, ahk_id %controlHwnd% - hFont := ErrorLevel - oldFont := 0 - if (hFont != "FAIL") - oldFont := DllCall("SelectObject", "Ptr", dc, "Ptr", hFont) - - VarSetCapacity(rect, 16, 0) - ; 0x440 = DT_CALCRECT | DT_EXPANDTABS - h := DllCall("DrawText", "Ptr", dc, "Ptr", &newText, "Int", -1, "Ptr", &rect, "UInt", 0x440) - ; width = rect.right - rect.left - w := NumGet(rect, 8, "Int") - NumGet(rect, 0, "Int") - - if oldFont - DllCall("SelectObject", "Ptr", dc, "Ptr", oldFont) - DllCall("ReleaseDC", "Ptr", controlHwnd, "Ptr", dc) - - return w -} - -Bar_GuiClick: - Manager_winActivate(Bar_aWndId) - If (A_GuiEvent = "Normal") { - ;If (SubStr(A_GuiControl, -13) = "_shebang_event") { - ; If Not Bar_cmdGuiIsVisible - ; If Not (SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6) = Manager_aMonitor) - ; Manager_activateMonitor(SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6)) - ; Bar_toggleCommandGui() - ;} Else - If (SubStr(A_GuiControl, -10) = "_time_event") { - If (Config_combineDateAndTime) { - If (Bar_TimeDateState == 0) { - Bar_TimeDateState := 1 - } Else { - Bar_TimeDateState := 0 - } - } - } Else { - If Not (SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6) = Manager_aMonitor) - Manager_activateMonitor(SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6)) - If (SubStr(A_GuiControl, -12) = "_layout_event") - View_setLayout(-1) - Else If InStr(A_GuiControl, "_view_#") And (SubStr(A_GuiControl, -5) = "_event") - Monitor_activateView(SubStr(A_GuiControl, InStr(A_GuiControl, "_view_#", False, 0) + 7, 1)) - } - } -Return - -Bar_GuiContextMenu: - Manager_winActivate(Bar_aWndId) - If (A_GuiEvent = "RightClick") { - If (SubStr(A_GuiControl, -12) = "_layout_event") { - If Not (SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6) = Manager_aMonitor) - Manager_activateMonitor(SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6)) - View_setLayout(0, +1) - } Else If InStr(A_GuiControl, "_view_#") And (SubStr(A_GuiControl, -5) = "_event") { - If Not (SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6) = Manager_aMonitor) - Manager_setWindowMonitor(SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6)) - Monitor_setWindowTag(SubStr(A_GuiControl, InStr(A_GuiControl, "_view_#", False, 0) + 7, 1)) - } - } -Return - -Bar_loop: - Bar_updateStatus() -Return - -Bar_move(m) -{ - Local wndTitle, x, y - - x := Monitor_#%m%_barX - y := Monitor_#%m%_barY - - wndTitle := "bug.n_BAR_" m - WinMove, %wndTitle%, , %x%, %y% -} - -Bar_toggleCommandGui() { - Local wndId, x, y - - Gui, 99: Default - If Bar_cmdGuiIsVisible { - Bar_cmdGuiIsVisible := False - Gui, Cancel - Manager_winActivate(Bar_aWndId) - } Else { - Bar_cmdGuiIsVisible := True - - If (Config_verticalBarPos = "tray") - x := Monitor_#%Manager_aMonitor%_x + Monitor_#%Manager_aMonitor%_barX + Monitor_#%Manager_aMonitor%_barWidth - Bar_#0_#0W - Else - x := Monitor_#%Manager_aMonitor%_barX + Monitor_#%Manager_aMonitor%_barWidth - Bar_#0_#0W ;; x := mX + (mBarX - mX) + mBarW - w - - If (Config_verticalBarPos = "top") Or (Config_verticalBarPos = "tray") And (Monitor_#%Manager_aMonitor%_taskBarPos = "top" Or Not Monitor_#%Manager_aMonitor%_taskBarClass) - y := Monitor_#%Manager_aMonitor%_y - Else - y := Monitor_#%Manager_aMonitor%_y + Monitor_#%Manager_aMonitor%_height - Bar_#0_#0H - - Gui, Show - WinGet, wndId, ID, bug.n_BAR_0 - WinMove, ahk_id %wndId%, , %x%, %y% - Window_set(wndId, "AlwaysOnTop", "On") - GuiControl, Focus, % Bar_#0_#0 - } -} - -Bar_toggleVisibility(m) -{ - Local GuiN - - GuiN := (m - 1) + 1 - If Monitor_#%m%_showBar - { - If Not (GuiN = 99) Or Bar_cmdGuiIsVisible - Gui, %GuiN%: Show - } - Else - Gui, %GuiN%: Cancel -} - -Bar_updateLayout(m) { - Local aView, GuiN - - aView := Monitor_#%m%_aView_#1 - GuiN := (m - 1) + 1 - GuiControl, %GuiN%: , Bar_#%m%_layout, % View_#%m%_#%aView%_layoutSymbol -} - -Bar_updateStatic(m) { - Local GuiN - - GuiN := (m - 1) + 1 - GuiControl, %GuiN%: , Bar_#%m%_shebang, #! -} - -Bar_updateStatus() { - Local bat1, bat2, bat3, GuiN, m, mute, time, vol, hours, minutes, seconds, text, textWidth, statusWidth, iconWidth, iconY - - iconY := (Bar_ctrlHeight - Bar_textHeight) / 2 - %Config_iconFontYOffset% - - If Config_readinBat { - ResourceMonitor_getBatteryStatus(bat1, bat2) - bat3 := bat1 - } - If Config_readinVolume { - SoundGet, vol, MASTER, VOLUME - SoundGet, mute, MASTER, MUTE - vol := Round(vol) - } - - Loop, % Manager_monitorCount { - m := A_Index - GuiN := (m - 1) + 1 - Debug_logMessage("DEBUG[6] Bar_updateStatus(): Gui, " . GuiN . ": Default", 6) - Gui, %GuiN%: Default - - statusWidth := Monitor_#%m%_barWidth - statusWidth -= Config_barItemSpacing - - If Config_readinTime { - If Config_readinTimeBinary { - FormatTime, hours,, H - FormatTime, minutes,, m - FormatTime, seconds,, s - If (Config_combineDateAndTime) { - If (Bar_TimeDateState == 0) { - time := % Bar_BinaryClockChars[hours + 1] " " Bar_BinaryClockChars[minutes + 1] " " Bar_BinaryClockChars[seconds + 1] - } Else { - FormatTime, time, , % Config_readinDateFormat - } - } else { - time := % Bar_BinaryClockChars[hours + 1] " " Bar_BinaryClockChars[minutes + 1] " " Bar_BinaryClockChars[seconds + 1] - } - } Else { - If (Config_combineDateAndTime) { - If (Bar_TimeDateState == 0) { - FormatTime, time, , % Config_readinTimeFormat - } Else { - FormatTime, time, , % Config_readinDateFormat - } - } else { - FormatTime, time, , % Config_readinTimeFormat - } - } - textWidth := Bar_getTrueTextWidth(Bar_#%m%_time_hwnd, time) - statusWidth -= textWidth - - GuiControl,, Bar_#%m%_time, % time - GuiControl, Move, Bar_#%m%_time, % "w" textWidth " x" statusWidth - GuiControl, Move, Bar_#%m%_time_event, % "w" textWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_time_highlighted, % "w" textWidth " x" statusWidth - - statusWidth -= Config_barIconSpacing - - If (Config_combineDateAndTime) { - If (Bar_TimeDateState == 0) { - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_time_icon_hwnd, Config_barIcon_#1) - } Else { - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_time_icon_hwnd, Config_barIcon_#2) - } - } Else { - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_time_icon_hwnd, Config_barIcon_#1) - } - statusWidth -= iconWidth - - If (Config_combineDateAndTime) { - If (Bar_TimeDateState == 0) { - GuiControl,, Bar_#%m%_time_icon, %Config_barIcon_#1% - } Else { - GuiControl,, Bar_#%m%_time_icon, %Config_barIcon_#2% - } - } Else { - GuiControl,, Bar_#%m%_time_icon, %Config_barIcon_#1% - } - GuiControl, Move, Bar_#%m%_time_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY - GuiControl, Move, Bar_#%m%_time_icon_event, % "w" iconWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_time_icon_highlighted, % "w" iconWidth " x" statusWidth - - statusWidth -= Config_barItemSpacing - } - If Config_readinDate And !Config_combineDateAndTime { - FormatTime, time, , % Config_readinDateFormat - textWidth := Bar_getTrueTextWidth(Bar_#%m%_date_hwnd, time) - statusWidth -= textWidth - - GuiControl,, Bar_#%m%_date, % time - GuiControl, Move, Bar_#%m%_date, % "w" textWidth " x" statusWidth - GuiControl, Move, Bar_#%m%_date_event, % "w" textWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_date_highlighted, % "w" textWidth " x" statusWidth - - statusWidth -= Config_barIconSpacing - - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_date_icon_hwnd, Config_barIcon_#2) - statusWidth -= iconWidth - - GuiControl,, Bar_#%m%_date_icon, %Config_barIcon_#2% - GuiControl, Move, Bar_#%m%_date_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY - GuiControl, Move, Bar_#%m%_date_icon_event, % "w" iconWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_date_icon_highlighted, % "w" iconWidth " x" statusWidth - - statusWidth -= Config_barItemSpacing - } - If Config_readinVolume { - If (mute = "On") { - ;; Change the color, if the mute is on - ;GuiControl, +Background%Config_backColor_#1_#9% +c%Config_foreColor_#1_#9%, Bar_#%m%_volume_highlighted - GuiControl, +c%Config_fontColor_#2_#9%, Bar_#%m%_volume - GuiControl, +c%Config_fontColor_#2_#9%, Bar_#%m%_volume_icon - } Else { - ;GuiControl, +Background%Config_backColor_#2_#9% +c%Config_foreColor_#2_#9%, Bar_#%m%_volume_highlighted - GuiControl, +c%Config_fontColor_#1_#9%, Bar_#%m%_volume - GuiControl, +c%Config_fontColor_#1_#9%, Bar_#%m%_volume_icon - } - - text := % vol "%" - textWidth := Bar_getTrueTextWidth(Bar_#%m%_volume_hwnd, text) - statusWidth -= textWidth - - GuiControl,, Bar_#%m%_volume, % text - GuiControl, Move, Bar_#%m%_volume, % "w" textWidth " x" statusWidth - GuiControl, Move, Bar_#%m%_volume_event, % "w" textWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_volume_highlighted, % "w" textWidth " x" statusWidth - - statusWidth -= Config_barIconSpacing - - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_volume_icon_hwnd, Config_barIcon_#6) - statusWidth -= iconWidth - - GuiControl,, Bar_#%m%_volume_icon, %Config_barIcon_#6% - GuiControl, Move, Bar_#%m%_volume_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY - GuiControl, Move, Bar_#%m%_volume_icon_event, % "w" iconWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_volume_icon_highlighted, % "w" iconWidth " x" statusWidth - - statusWidth -= Config_barItemSpacing - } - If Config_readinRam { - text := ResourceMonitor_getRamText() - textWidth := Bar_getTrueTextWidth(Bar_#%m%_ram_hwnd, text) - statusWidth -= textWidth - - GuiControl,, Bar_#%m%_ram, % text - GuiControl, Move, Bar_#%m%_ram, % "w" textWidth " x" statusWidth - GuiControl, Move, Bar_#%m%_ram_event, % "w" textWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_ram_highlighted, % "w" textWidth " x" statusWidth - - statusWidth -= Config_barIconSpacing - - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_ram_icon_hwnd, Config_barIcon_#3) - statusWidth -= iconWidth - - GuiControl,, Bar_#%m%_ram_icon, %Config_barIcon_#3% - GuiControl, Move, Bar_#%m%_ram_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY - GuiControl, Move, Bar_#%m%_ram_icon_event, % "w" iconWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_ram_icon_highlighted, % "w" iconWidth " x" statusWidth - - statusWidth -= Config_barItemSpacing - } - If Config_readinCpu { - text := ResourceMonitor_getCpuText() - textWidth := Bar_getTrueTextWidth(Bar_#%m%_cpu_hwnd, text) - statusWidth -= textWidth - - GuiControl,, Bar_#%m%_cpu, % text - GuiControl, Move, Bar_#%m%_cpu, % "w" textWidth " x" statusWidth - GuiControl, Move, Bar_#%m%_cpu_event, % "w" textWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_cpu_highlighted, % "w" textWidth " x" statusWidth - - statusWidth -= Config_barIconSpacing - - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_cpu_icon_hwnd, Config_barIcon_#4) - statusWidth -= iconWidth - - GuiControl,, Bar_#%m%_cpu_icon, %Config_barIcon_#4% - GuiControl, Move, Bar_#%m%_cpu_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY - GuiControl, Move, Bar_#%m%_cpu_icon_event, % "w" iconWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_cpu_icon_highlighted, % "w" iconWidth " x" statusWidth - - statusWidth -= Config_barItemSpacing - } - If Config_readinBat { - If (bat1 < 10) And (bat2 = "off") { - ;; Change the color, if the battery level is below 10% - ;GuiControl, +Background%Config_backColor_#3_#8% +c%Config_foreColor_#3_#8%, Bar_#%m%_battery_highlighted - GuiControl, +c%Config_fontColor_#3_#8%, Bar_#%m%_battery - } Else If (bat2 = "off") { - ;; Change the color, if the pc is not plugged in - ;GuiControl, +Background%Config_backColor_#2_#8% +c%Config_foreColor_#2_#8%, Bar_#%m%_battery_highlighted - GuiControl, +c%Config_fontColor_#2_#8%, Bar_#%m%_battery - } Else { - ;GuiControl, +Background%Config_backColor_#1_#8% +c%Config_foreColor_#1_#8%, Bar_#%m%_battery_highlighted - GuiControl, +c%Config_fontColor_#1_#8%, Bar_#%m%_battery - } - - text := % bat3 "%" - textWidth := Bar_getTrueTextWidth(Bar_#%m%_battery_hwnd, text) - statusWidth -= textWidth - - GuiControl,, Bar_#%m%_battery, % text - GuiControl, Move, Bar_#%m%_battery, % "w" textWidth " x" statusWidth - GuiControl, Move, Bar_#%m%_battery_event, % "w" textWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_battery_highlighted, % "w" textWidth " x" statusWidth - - statusWidth -= Config_barIconSpacing - - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_battery_icon_hwnd, Config_barIcon_#5) - statusWidth -= iconWidth - - GuiControl,, Bar_#%m%_battery_icon, %Config_barIcon_#5% - GuiControl, Move, Bar_#%m%_battery_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY - GuiControl, Move, Bar_#%m%_battery_icon_event, % "w" iconWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_battery_icon_highlighted, % "w" iconWidth " x" statusWidth - - statusWidth -= Config_barItemSpacing - } - If Config_readinMusic { - text := MusicBee_GetNowPlaying() - textWidth := Bar_getTrueTextWidth(Bar_#%m%_music_hwnd, text) - statusWidth -= textWidth - - GuiControl,, Bar_#%m%_music, % text - GuiControl, Move, Bar_#%m%_music, % "w" textWidth " x" statusWidth - GuiControl, Move, Bar_#%m%_music_event, % "w" textWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_music_highlighted, % "w" textWidth " x" statusWidth - - statusWidth -= Config_barIconSpacing - - if (text == "") { - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_music_icon_hwnd, "") - } else { - iconWidth := Bar_getTrueTextWidth(Bar_#%m%_music_icon_hwnd, Config_barIcon_#7) - } - statusWidth -= iconWidth - - GuiControl,, Bar_#%m%_music_icon, %Config_barIcon_#7% - GuiControl, Move, Bar_#%m%_music_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY - GuiControl, Move, Bar_#%m%_music_icon_event, % "w" iconWidth " x" statusWidth - ;GuiControl, Move, Bar_#%m%_music_icon_highlighted, % "w" iconWidth " x" statusWidth - - statusWidth -= Config_barItemSpacing - } - - ; set this in update loop because OpenShell likes to revert it when you change settings - If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass And Config_classicThemeTaskbar) { - trayWndId := WinExist("ahk_class " Monitor_#%m%_taskBarClass) - WinSet, Style, -0x40000, ahk_id %trayWndId% ; WS_THICKFRAME - WinSet, Style, +0x80, ahk_id %trayWndId% ; DS_MODALFRAME - WinSet, Style, +0x0004, ahk_id %trayWndId% ; DS_3DLOOK - - WinSet, ExStyle, +0x1, ahk_id %trayWndId% ; WS_EX_DLGMODALFRAME - WinSet, ExStyle, +0x20000, ahk_id %trayWndId% ; WS_EX_STATICEDGE - } - } -} - -Bar_updateTitle() { - Local aWndId, aWndTitle, content, GuiN, i, title, titleWidth, barWidth, titleX - - WinGet, aWndId, ID, A - WinGetTitle, aWndTitle, ahk_id %aWndId% - If InStr(Bar_hideTitleWndIds, aWndId ";") Or (aWndTitle = "bug.n_BAR_0") - aWndTitle := "" - If aWndId And InStr(Manager_managedWndIds, aWndId . ";") And Window_#%aWndId%_isFloating - aWndTitle := "~ " aWndTitle - If (Manager_monitorCount > 1) - aWndTitle := "[" Manager_aMonitor "] " aWndTitle - - title := aWndTitle - - if (StrLen(title) > 48) { - ;; Shorten the window title if its length exceeds the width of the bar - title := SubStr(title, 1, 48) . "…" - } - StringReplace, title, title, &, &&, All ;; Special character '&', which would underline the next letter. - - - Loop, % Manager_monitorCount { - barWidth := Monitor_#%A_Index%_barWidth - titleWidth := Bar_getTrueTextWidth(Bar_#%A_Index%_title_hwnd, title) - titleX := barWidth / 2 - titleWidth / 2 - - GuiN := (A_Index - 1) + 1 - If (Config_readinTitle) { - Debug_logMessage("DEBUG[6] Bar_updateTitle(): Gui, " . GuiN . ": Default", 6) - Gui, %GuiN%: Default - GuiControlGet, content, , Bar_#%A_Index%_title - If (A_Index = Manager_aMonitor) { - If Not (content = title) - GuiControl,, Bar_#%A_Index%_title, % title - GuiControl, Move, Bar_#%A_Index%_title, % "w" titleWidth "x" titleX - GuiControl, Move, Bar_#%A_Index%_title_event, % "w" titleWidth "x" titleX - GuiControl, Move, Bar_#%A_Index%_title_highlighted, % "w" titleWidth "x" titleX - } Else If Not (content = "") - GuiControl, , Bar_#%A_Index%_title, - } - } - Bar_aWndId := aWndId -} - -Bar_updateView(m, v) { - Local managedWndId0, wndId0, wndIds - - GuiN := (m - 1) + 1 - Gui, %GuiN%: Default - Debug_logMessage("DEBUG[6] Bar_updateView(): m: " . m . "; Gui, " . GuiN . ": Default", 6) - - StringTrimRight, wndIds, Manager_managedWndIds, 1 - StringSplit, managedWndId, wndIds, `; - - If (v = Monitor_#%m%_aView_#1) { - ;; Set foreground/background colors if the view is the current view. - ;GuiControl, +Background%Config_backColor_#2_#1% +c%Config_foreColor_#2_#1%, Bar_#%m%_view_#%v%_highlighted - GuiControl, +c%Config_fontColor_#2_#1%, Bar_#%m%_view_#%v% - } Else { - ;; Set foreground/background colors. - ;GuiControl, +Background%Config_backColor_#1_#1% +c%Config_foreColor_#1_#1%, Bar_#%m%_view_#%v%_highlighted - GuiControl, +c%Config_fontColor_#1_#1%, Bar_#%m%_view_#%v% - } - - Loop, % Config_viewCount { - StringTrimRight, wndIds, View_#%m%_#%A_Index%_wndIds, 1 - StringSplit, wndId, wndIds, `; - TagPercent := wndId0 / managedWndId0 * 100 - If (TagPercent > 0 and v != A_Index) { - GuiControl, +c%Config_fontColor_#3_#1%, Bar_#%m%_view_#%A_Index% - } - ;GuiControl, , Bar_#%m%_view_#%A_Index%_highlighted, % wndId0 / managedWndId0 * 100 ;; Update the percentage fill for the view. - GuiControl, , Bar_#%m%_view_#%A_Index%, % Config_viewNames_#%A_Index% ;; Refresh the number on the bar. - } -} +/* + bug.n -- tiling window management + Copyright (c) 2010-2019 Joshua Fuhs, joten + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + @license GNU General Public License version 3 + ../LICENSE.md or <http://www.gnu.org/licenses/> + + @version 9.1.0 +*/ + +Bar_init(m) { + Local appBarMsg, anyText, color, color0, GuiN, h1, h2, i, id, id0, text, text0, titleWidth, trayWndId, w, wndId, wndTitle, wndWidth, x1, x2, y1, y2 + + If (SubStr(Config_barWidth, 0) = "%") { + StringTrimRight, wndWidth, Config_barWidth, 1 + wndWidth := Round(Monitor_#%m%_width * wndWidth / 100) + } Else + wndWidth := Config_barWidth + + wndWidth := Round(wndWidth / mmngr1.monitors[m].scaleX) + If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) { + Bar_ctrlHeight := Round(Bar_ctrlHeight / mmngr1.monitors[m].scaleY) + Bar_height := Round(Bar_height / mmngr1.monitors[m].scaleY) + } + + Monitor_#%m%_barWidth := wndWidth + titleWidth := wndWidth + h1 := Bar_ctrlHeight + x1 := Config_barItemSpacing + x2 := wndWidth + y1 := 0 + y2 := (Bar_ctrlHeight - Bar_textHeight) / 2 + h2 := Bar_textHeight + + ;; Create the GUI window + wndTitle := "bug.n_BAR_" m + GuiN := (m - 1) + 1 + Debug_logMessage("DEBUG[6] Bar_init(): Gui, " . GuiN . ": Default", 6) + Gui, %GuiN%: Default + Gui, Destroy + Gui, -Caption +LabelBar_Gui +LastFound +ToolWindow + Gui, Color, %Config_backColor_#1_#3% + Gui, Font, c%Config_fontColor_#1_#3% s%Config_fontSize%, %Config_fontName% + + ;; Views + Loop, % Config_viewCount { + w := Bar_getTextWidth(Config_viewNames_#%A_Index%) + Bar_addElement(m, "view_#" A_Index, " " Config_viewNames_#%A_Index%, x1, y1, w, Config_backColor_#1_#1, Config_foreColor_#1_#1, Config_fontColor_#1_#1) + titleWidth -= w + x1 += w + Config_barItemSpacing + } + ;; Layout + ;w := Bar_getTextWidth("??????") + ;Bar_addElement(m, "layout", "??????", x1, y1, w, Config_backColor_#1_#2, Config_foreColor_#1_#2, Config_fontColor_#1_#2) + ;titleWidth -= w + ;x1 += w + Config_barItemSpacing + + ;; The x-position and width of the sub-windows right of the window title are set from the right. + ;; <view>;<layout>;<title>;<shebang>;<time>;<date>;<anyText>;<battery>;<volumeLevel> + ;color := "4" + ;id := "shebang" + ;text := " #! " + color := "" + id := "" + text := "" + If Config_readinTime { + color .= "4" + id .= "time" + text .= "" . Config_readinTimeFormat + } + If (Config_readinDate And !Config_combineDateAndTime) { + color .= ";5" + id .= ";date" + text .= ";" . Config_readinDateFormat + } + If Config_readinVolume { + color .= ";9" + id .= ";volume" + text .= ";???%" + } + If Config_readinRam { + color .= ";6" + id .= ";ram" + text .= ";" . ResourceMonitor_getRamText() + } + If Config_readinCpu { + color .= ";7" + id .= ";cpu" + text .= ";" . ResourceMonitor_getCpuText() + } + If Config_readinBat { + color .= ";8" + id .= ";battery" + text .= ";???%" + } + If Config_readinMusic { + color .= ";10" + id .= ";music" + text .= ";" . MusicBee_GetNowPlaying() + } + StringSplit, color, color, `; + StringSplit, id, id, `; + StringSplit, text, text, `; + Loop, % id0 { + elemId := id%A_Index% + If (elemId = "shebang") + Gui, -Disabled + w := Bar_getTextWidth(text%A_Index%) + x2 -= w + titleWidth -= w + i := color%A_Index% + iconIndex := i - 3 + icon := Config_barIcon_#%iconIndex% + iconId := % elemId "_icon" + Bar_addElement(m, elemId, text%A_Index%, x2, y1, wndWidth, Config_backColor_#1_#%i%, Config_foreColor_#1_#%i%, Config_fontColor_#1_#%i%) + Bar_addElement(m, iconId, icon, x2, y1, wndWidth, Config_backColor_#1_#%i%, Config_foreColor_#1_#%i%, Config_fontColor_#1_#%i%, Config_iconFontSize, Config_iconFontName) + If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) { + trayWndId := WinExist("ahk_class " Monitor_#%m%_taskBarClass) + ControlGet, TrayRoot, Hwnd, , TrayNotifyWnd1, ahk_id %trayWndId% + + DllCall("SetParent", "UInt", HwndBar_#%m%_%elemId%_hwnd, "UInt", TrayRoot) + DllCall("SetParent", "UInt", HwndBar_#%m%_%iconId%_hwnd, "UInt", TrayRoot) + } + GuiControl, -Center, Bar_#%m%_%elemId% + GuiControl, -Center, Bar_#%m%_%iconId% + } + + ;; Window title (remaining space) + If Not Config_singleRowBar { + titleWidth := wndWidth + x1 := 0 + y1 += h1 + y2 += h1 + } + If Config_readinTitle + Bar_addElement(m, "title", "", x1, y1, titleWidth, Config_backColor_#1_#3, Config_foreColor_#1_#3, Config_fontColor_#1_#3) + + If (Config_horizontalBarPos = "left") + x1 := 0 + Else If (Config_horizontalBarPos = "right") + x1 := Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX + Else If (Config_horizontalBarPos = "center") + x1 := (Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX) / 2 + Else If (Config_horizontalBarPos >= 0) + x1 := Config_horizontalBarPos + Else If (Config_horizontalBarPos < 0) + x1 := Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX + Config_horizontalBarPos + If Not (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) + x1 += Monitor_#%m%_x + x1 := Round(x1) + + Bar_#%m%_titleWidth := titleWidth + Monitor_#%m%_barX := x1 + y1 := Monitor_#%m%_barY + + If Monitor_#%m%_showBar + Gui, Show, NoActivate x%x1% y%y1% w%wndWidth% h%Bar_height%, %wndTitle% + Else + Gui, Show, NoActivate Hide x%x1% y%y1% w%wndWidth% h%Bar_height%, %wndTitle% + WinSet, Transparent, %Config_barTransparency%, %wndTitle% + wndId := WinExist(wndTitle) + Bar_appBarData := "" + If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) { + trayWndId := WinExist("ahk_class " Monitor_#%m%_taskBarClass) + + ControlGet, ToolbarRoot, Hwnd, , ReBarWindow321, ahk_id %trayWndId% + ControlGet, Toolbar, Hwnd, , ToolbarWindow321, ahk_id %ToolbarRoot%, bug.n-bar + DllCall("SetParent", "UInt", wndId, "UInt", Toolbar) + If (Config_barTaskbarBlend) { + Gui, Color, 000000, %wndTitle% + } + + If (Config_classicThemeTaskbar) { + WinSet, Style, -0x40000, ahk_id %trayWndId% ; WS_THICKFRAME + WinSet, Style, +0x80, ahk_id %trayWndId% ; DS_MODALFRAME + WinSet, Style, +0x0004, ahk_id %trayWndId% ; DS_3DLOOK + + WinSet, ExStyle, -0x1, ahk_id %trayWndId% ; WS_EX_DLGMODALFRAME + WinSet, ExStyle, +0x20000, ahk_id %trayWndId% ; WS_EX_STATICEDGE + + Sleep 100 + WinSet, ExStyle, +0x1, ahk_id %trayWndId% ; WS_EX_DLGMODALFRAME + Sleep 100 + WinSet, ExStyle, -0x1, ahk_id %trayWndId% ; WS_EX_DLGMODALFRAME + + Sleep 100 + WinSet, Style, +0x800000, ahk_id %ToolbarRoot% + Sleep 100 + WinSet, Style, -0x800000, ahk_id %ToolbarRoot% + } + } Else { + appBarMsg := DllCall("RegisterWindowMessage", Str, "AppBarMsg") + + ;; appBarData: http://msdn2.microsoft.com/en-us/library/ms538008.aspx + VarSetCapacity(Bar_appBarData, 36, 0) + offset := NumPut( 36, Bar_appBarData) + offset := NumPut( wndId, offset+0) + offset := NumPut( appBarMsg, offset+0) + offset := NumPut( 1, offset+0) + offset := NumPut( x1, offset+0) + offset := NumPut( y1, offset+0) + offset := NumPut( x1 + wndWidth, offset+0) + offset := NumPut(y1 + Bar_height, offset+0) + offset := NumPut( 1, offset+0) + + DllCall("Shell32.dll\SHAppBarMessage", "UInt", (ABM_NEW := 0x0) , "UInt", &Bar_appBarData) + DllCall("Shell32.dll\SHAppBarMessage", "UInt", (ABM_QUERYPOS := 0x2), "UInt", &Bar_appBarData) + DllCall("Shell32.dll\SHAppBarMessage", "UInt", (ABM_SETPOS := 0x3) , "UInt", &Bar_appBarData) + ;; SKAN: Crazy Scripting : Quick Launcher for Portable Apps (http://www.autohotkey.com/forum/topic22398.html) + } + + Bar_BinaryClockChars := ["⠀","⠈","⠐","⠘","⠠","⠨","⠰","⠸","⢀","⢈","⠁","⠉","⠑","⠙","⠡","⠩","⠱","⠹","⢁","⢉","⠂","⠊","⠒","⠚","⠢","⠪","⠲","⠺","⢂","⢊","⠃","⠋","⠓","⠛","⠣","⠫","⠳","⠻","⢃","⢋","⠄","⠌","⠔","⠜","⠤","⠬","⠴","⠼","⢄","⢌","⠅","⠍","⠕","⠝","⠥","⠭","⠵","⠽","⢅","⢍"] + Bar_TimeDateState := 0 +} + +Bar_initCmdGui() +{ + Global Bar_#0_#0, Bar_#0_#0H, Bar_#0_#0W, Bar_#0_#1, Bar_cmdGuiIsVisible, Config_barCommands, Config_fontName, Config_fontSize + Global Config_backColor_#1_#3, Config_fontColor_#1_#3, Config_foreColor_#1_#3 + + Bar_#0_#0 := "" + Bar_cmdGuiIsVisible := False + wndTitle := "bug.n_BAR_0" + Gui, 99: Default + Gui, +LabelBar_cmdGui + IfWinExist, %wndTitle% + Gui, Destroy + Gui, +LastFound -Caption +ToolWindow +AlwaysOnTop +Delimiter`; + Gui, Color, Default + Gui, Font, s%Config_fontSize%, %Config_fontName% + StringSplit, cmd, Config_barCommands, `; + Gui, Add, ComboBox, x10 y10 r%cmd0% w300 Background%Config_backColor_#1_#3% c%Config_fontColor_#1_#3% Simple vBar_#0_#0 gBar_cmdGuiEnter, % Config_barCommands + Gui, Add, Edit, Y0 w300 Hidden vBar_#0_#1 gBar_cmdGuiEnter + Gui, Add, Button, Y0 Hidden Default gBar_cmdGuiEnter, OK + GuiControlGet, Bar_#0_#0, Pos + Bar_#0_#0H += 20 + Bar_#0_#0W += 20 + Gui, Show, Hide w%Bar_#0_#0W% h%Bar_#0_#0H%, %wndTitle% +} + +Bar_addElement(m, id, text, x, y1, width, backColor, foreColor, fontColor, fontSize="", fontName="") { + Local y2 + + if (fontSize == "") { + fontSize = %Config_fontSize% + } + if (fontName == "") { + fontName = %Config_fontName% + } + + y2 := y1 + (Bar_ctrlHeight - Bar_textHeight) / 2 + + Gui, Add, Text, x%x% y%y1% w%width% h%Bar_ctrlHeight% BackgroundTrans vBar_#%m%_%id%_event gBar_GuiClick, + ;Gui, Add, Progress, x%x% y%y1% w%width% h%Bar_ctrlHeight% Background%backColor% c%foreColor% vBar_#%m%_%id%_highlighted + ;GuiControl, , Bar_#%m%_%id%_highlighted, 100 + Gui, Font, c%fontColor% s%fontSize%, %fontName% + Gui, Add, Text, x%x% y%y2% w%width% h%Bar_textHeight% BackgroundTrans Center vBar_#%m%_%id% HwndBar_#%m%_%id%_hwnd, %text% +} + +Bar_cmdGuiEnter: + If (A_GuiControl = "OK") Or (A_GuiControl = "Bar_#0_#0" And A_GuiControlEvent = "DoubleClick") { + Gui, Submit, NoHide + Bar_cmdGuiIsVisible := False + Gui, Cancel + WinActivate, ahk_id %Bar_aWndId% + Main_evalCommand(Bar_#0_#0) + Bar_#0_#0 := "" + } Else If (A_GuiControl = "Bar_#0_#1") { + Gui, Submit, NoHide + Debug_logMessage("DEBUG[6] Bar_cmdGuiEnter; command: " . Bar_#0_#1, 6) + Loop, Parse, Bar_#0_#1, `n, `r + Main_evalCommand(A_LoopField) + } +Return + +Bar_cmdGuiEscape: + Bar_cmdGuiIsVisible := False + Gui, Cancel + WinActivate, ahk_id %Bar_aWndId% +Return + +Bar_getHeight() +{ + Global Bar_#0_#1, Bar_#0_#1H, Bar_#0_#2, Bar_#0_#2H, Bar_ctrlHeight, Bar_height, Bar_textHeight + Global Config_fontName, Config_fontSize, Config_singleRowBar, Config_spaciousBar, Config_verticalBarPos, Config_classicThemeFixes + + wndTitle := "bug.n_BAR_0" + Gui, 99: Default + Gui, Font, s%Config_fontSize%, %Config_fontName% + Gui, Add, Text, x0 y0 vBar_#0_#1, | + GuiControlGet, Bar_#0_#1, Pos + Bar_textHeight := Bar_#0_#1H + If Config_spaciousBar + { + Gui, Add, ComboBox, r9 x0 y0 vBar_#0_#2, | + GuiControlGet, Bar_#0_#2, Pos + Bar_ctrlHeight := Bar_#0_#2H + } + Else + Bar_ctrlHeight := Bar_textHeight + Gui, Destroy + + Bar_height := Bar_ctrlHeight + If Not Config_singleRowBar + Bar_height *= 2 + If (Config_verticalBarPos = "tray") + { + WinGetPos, , , , buttonH, Start ahk_class Button + WinGetPos, , , , barH, ahk_class Shell_TrayWnd + If WinExist("Start ahk_class Button") And (buttonH < barH) + Bar_height := buttonH + Else + Bar_height := barH + Bar_height := Bar_height - 2 + + Bar_ctrlHeight := Bar_height + If Not Config_singleRowBar + Bar_ctrlHeight := Bar_height / 2 + + If (Config_classicThemeFixes) { + Bar_height := 22 + Bar_ctrlHeight := 22 + } + } +} + +Bar_getTextWidth(x, reverse=False) +{ + Global Config_fontSize + + If reverse + { ;; 'reverse' calculates the number of characters to a given width. + w := x + i := w / (Config_fontSize - 1) + If (Config_fontSize = 7 Or (Config_fontSize > 8 And Config_fontSize < 13)) + i := w / (Config_fontSize - 2) + Else If (Config_fontSize > 12 And Config_fontSize < 18) + i := w / (Config_fontSize - 3) + Else If (Config_fontSize > 17) + i := w / (Config_fontSize - 4) + textWidth := i + } + Else + { ;; 'else' calculates the width to a given string. + textWidth := StrLen(x) * (Config_fontSize - 1) + If (Config_fontSize = 7 Or (Config_fontSize > 8 And Config_fontSize < 13)) + textWidth := StrLen(x) * (Config_fontSize - 2) + Else If (Config_fontSize > 12 And Config_fontSize < 18) + textWidth := StrLen(x) * (Config_fontSize - 3) + Else If (Config_fontSize > 17) + textWidth := StrLen(x) * (Config_fontSize - 4) + } + + Return, textWidth +} + +Bar_getTrueTextWidth(controlHwnd, newText) { + dc := DllCall("GetDC", "Ptr", controlHwnd) + + ; 0x31 = WM_GETFONT + SendMessage 0x31,,,, ahk_id %controlHwnd% + hFont := ErrorLevel + oldFont := 0 + if (hFont != "FAIL") + oldFont := DllCall("SelectObject", "Ptr", dc, "Ptr", hFont) + + VarSetCapacity(rect, 16, 0) + ; 0x440 = DT_CALCRECT | DT_EXPANDTABS + h := DllCall("DrawText", "Ptr", dc, "Ptr", &newText, "Int", -1, "Ptr", &rect, "UInt", 0x440) + ; width = rect.right - rect.left + w := NumGet(rect, 8, "Int") - NumGet(rect, 0, "Int") + + if oldFont + DllCall("SelectObject", "Ptr", dc, "Ptr", oldFont) + DllCall("ReleaseDC", "Ptr", controlHwnd, "Ptr", dc) + + return w +} + +Bar_GuiClick: + Manager_winActivate(Bar_aWndId) + If (A_GuiEvent = "Normal") { + ;If (SubStr(A_GuiControl, -13) = "_shebang_event") { + ; If Not Bar_cmdGuiIsVisible + ; If Not (SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6) = Manager_aMonitor) + ; Manager_activateMonitor(SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6)) + ; Bar_toggleCommandGui() + ;} Else + If (SubStr(A_GuiControl, -10) = "_time_event") { + If (Config_combineDateAndTime) { + If (Bar_TimeDateState == 0) { + Bar_TimeDateState := 1 + } Else { + Bar_TimeDateState := 0 + } + } + } Else { + If Not (SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6) = Manager_aMonitor) + Manager_activateMonitor(SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6)) + ;If (SubStr(A_GuiControl, -12) = "_layout_event") + ; View_setLayout(-1) + Else If InStr(A_GuiControl, "_view_#") And (SubStr(A_GuiControl, -5) = "_event") + Monitor_activateView(SubStr(A_GuiControl, InStr(A_GuiControl, "_view_#", False, 0) + 7, 1)) + } + } +Return + +Bar_GuiContextMenu: + Manager_winActivate(Bar_aWndId) + If (A_GuiEvent = "RightClick") { + ;If (SubStr(A_GuiControl, -12) = "_layout_event") { + ; If Not (SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6) = Manager_aMonitor) + ; Manager_activateMonitor(SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6)) + ; View_setLayout(0, +1) + ;} Else + If InStr(A_GuiControl, "_view_#") And (SubStr(A_GuiControl, -5) = "_event") { + If Not (SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6) = Manager_aMonitor) + Manager_setWindowMonitor(SubStr(A_GuiControl, 6, InStr(A_GuiControl, "_", False, 6) - 6)) + Monitor_setWindowTag(SubStr(A_GuiControl, InStr(A_GuiControl, "_view_#", False, 0) + 7, 1)) + } + } +Return + +Bar_loop: + Bar_updateStatus() +Return + +Bar_move(m) +{ + Local wndTitle, x, y + + x := Monitor_#%m%_barX + y := Monitor_#%m%_barY + + wndTitle := "bug.n_BAR_" m + WinMove, %wndTitle%, , %x%, %y% +} + +Bar_toggleCommandGui() { + Local wndId, x, y + + Gui, 99: Default + If Bar_cmdGuiIsVisible { + Bar_cmdGuiIsVisible := False + Gui, Cancel + Manager_winActivate(Bar_aWndId) + } Else { + Bar_cmdGuiIsVisible := True + + If (Config_verticalBarPos = "tray") + x := Monitor_#%Manager_aMonitor%_x + Monitor_#%Manager_aMonitor%_barX + Monitor_#%Manager_aMonitor%_barWidth - Bar_#0_#0W + Else + x := Monitor_#%Manager_aMonitor%_barX + Monitor_#%Manager_aMonitor%_barWidth - Bar_#0_#0W ;; x := mX + (mBarX - mX) + mBarW - w + + If (Config_verticalBarPos = "top") Or (Config_verticalBarPos = "tray") And (Monitor_#%Manager_aMonitor%_taskBarPos = "top" Or Not Monitor_#%Manager_aMonitor%_taskBarClass) + y := Monitor_#%Manager_aMonitor%_y + Else + y := Monitor_#%Manager_aMonitor%_y + Monitor_#%Manager_aMonitor%_height - Bar_#0_#0H + + Gui, Show + WinGet, wndId, ID, bug.n_BAR_0 + WinMove, ahk_id %wndId%, , %x%, %y% + Window_set(wndId, "AlwaysOnTop", "On") + GuiControl, Focus, % Bar_#0_#0 + } +} + +Bar_toggleVisibility(m) +{ + Local GuiN + + GuiN := (m - 1) + 1 + If Monitor_#%m%_showBar + { + If Not (GuiN = 99) Or Bar_cmdGuiIsVisible + Gui, %GuiN%: Show + } + Else + Gui, %GuiN%: Cancel +} + +Bar_updateLayout(m) { + Local aView, GuiN + + aView := Monitor_#%m%_aView_#1 + GuiN := (m - 1) + 1 + GuiControl, %GuiN%: , Bar_#%m%_layout, % View_#%m%_#%aView%_layoutSymbol +} + +Bar_updateStatic(m) { + Local GuiN + + GuiN := (m - 1) + 1 + GuiControl, %GuiN%: , Bar_#%m%_shebang, #! +} + +Bar_updateStatus() { + Local bat1, bat2, bat3, GuiN, m, mute, time, vol, hours, minutes, seconds, text, textWidth, statusWidth, iconWidth, iconY + + iconY := (Bar_ctrlHeight - Bar_textHeight) / 2 - %Config_iconFontYOffset% + + If Config_readinBat { + ResourceMonitor_getBatteryStatus(bat1, bat2) + bat3 := bat1 + } + If Config_readinVolume { + SoundGet, vol, MASTER, VOLUME + SoundGet, mute, MASTER, MUTE + vol := Round(vol) + } + + Loop, % Manager_monitorCount { + m := A_Index + GuiN := (m - 1) + 1 + Debug_logMessage("DEBUG[6] Bar_updateStatus(): Gui, " . GuiN . ": Default", 6) + Gui, %GuiN%: Default + + statusWidth := Monitor_#%m%_barWidth + statusWidth -= Config_barItemSpacing + + If Config_readinTime { + If Config_readinTimeBinary { + FormatTime, hours,, H + FormatTime, minutes,, m + FormatTime, seconds,, s + If (Config_combineDateAndTime) { + If (Bar_TimeDateState == 0) { + time := % Bar_BinaryClockChars[hours + 1] " " Bar_BinaryClockChars[minutes + 1] " " Bar_BinaryClockChars[seconds + 1] + } Else { + FormatTime, time, , % Config_readinDateFormat + } + } else { + time := % Bar_BinaryClockChars[hours + 1] " " Bar_BinaryClockChars[minutes + 1] " " Bar_BinaryClockChars[seconds + 1] + } + } Else { + If (Config_combineDateAndTime) { + If (Bar_TimeDateState == 0) { + FormatTime, time, , % Config_readinTimeFormat + } Else { + FormatTime, time, , % Config_readinDateFormat + } + } else { + FormatTime, time, , % Config_readinTimeFormat + } + } + textWidth := Bar_getTrueTextWidth(Bar_#%m%_time_hwnd, time) + statusWidth -= textWidth + + GuiControl,, Bar_#%m%_time, % time + GuiControl, Move, Bar_#%m%_time, % "w" textWidth " x" statusWidth + GuiControl, Move, Bar_#%m%_time_event, % "w" textWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_time_highlighted, % "w" textWidth " x" statusWidth + + statusWidth -= Config_barIconSpacing + + If (Config_combineDateAndTime) { + If (Bar_TimeDateState == 0) { + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_time_icon_hwnd, Config_barIcon_#1) + } Else { + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_time_icon_hwnd, Config_barIcon_#2) + } + } Else { + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_time_icon_hwnd, Config_barIcon_#1) + } + statusWidth -= iconWidth + + If (Config_combineDateAndTime) { + If (Bar_TimeDateState == 0) { + GuiControl,, Bar_#%m%_time_icon, %Config_barIcon_#1% + } Else { + GuiControl,, Bar_#%m%_time_icon, %Config_barIcon_#2% + } + } Else { + GuiControl,, Bar_#%m%_time_icon, %Config_barIcon_#1% + } + GuiControl, Move, Bar_#%m%_time_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY + GuiControl, Move, Bar_#%m%_time_icon_event, % "w" iconWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_time_icon_highlighted, % "w" iconWidth " x" statusWidth + + statusWidth -= Config_barItemSpacing + } + If Config_readinDate And !Config_combineDateAndTime { + FormatTime, time, , % Config_readinDateFormat + textWidth := Bar_getTrueTextWidth(Bar_#%m%_date_hwnd, time) + statusWidth -= textWidth + + GuiControl,, Bar_#%m%_date, % time + GuiControl, Move, Bar_#%m%_date, % "w" textWidth " x" statusWidth + GuiControl, Move, Bar_#%m%_date_event, % "w" textWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_date_highlighted, % "w" textWidth " x" statusWidth + + statusWidth -= Config_barIconSpacing + + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_date_icon_hwnd, Config_barIcon_#2) + statusWidth -= iconWidth + + GuiControl,, Bar_#%m%_date_icon, %Config_barIcon_#2% + GuiControl, Move, Bar_#%m%_date_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY + GuiControl, Move, Bar_#%m%_date_icon_event, % "w" iconWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_date_icon_highlighted, % "w" iconWidth " x" statusWidth + + statusWidth -= Config_barItemSpacing + } + If Config_readinVolume { + If (mute = "On") { + ;; Change the color, if the mute is on + ;GuiControl, +Background%Config_backColor_#1_#9% +c%Config_foreColor_#1_#9%, Bar_#%m%_volume_highlighted + GuiControl, +c%Config_fontColor_#2_#9%, Bar_#%m%_volume + GuiControl, +c%Config_fontColor_#2_#9%, Bar_#%m%_volume_icon + } Else { + ;GuiControl, +Background%Config_backColor_#2_#9% +c%Config_foreColor_#2_#9%, Bar_#%m%_volume_highlighted + GuiControl, +c%Config_fontColor_#1_#9%, Bar_#%m%_volume + GuiControl, +c%Config_fontColor_#1_#9%, Bar_#%m%_volume_icon + } + + text := % vol "%" + textWidth := Bar_getTrueTextWidth(Bar_#%m%_volume_hwnd, text) + statusWidth -= textWidth + + GuiControl,, Bar_#%m%_volume, % text + GuiControl, Move, Bar_#%m%_volume, % "w" textWidth " x" statusWidth + GuiControl, Move, Bar_#%m%_volume_event, % "w" textWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_volume_highlighted, % "w" textWidth " x" statusWidth + + statusWidth -= Config_barIconSpacing + + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_volume_icon_hwnd, Config_barIcon_#6) + statusWidth -= iconWidth + + GuiControl,, Bar_#%m%_volume_icon, %Config_barIcon_#6% + GuiControl, Move, Bar_#%m%_volume_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY + GuiControl, Move, Bar_#%m%_volume_icon_event, % "w" iconWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_volume_icon_highlighted, % "w" iconWidth " x" statusWidth + + statusWidth -= Config_barItemSpacing + } + If Config_readinRam { + text := ResourceMonitor_getRamText() + textWidth := Bar_getTrueTextWidth(Bar_#%m%_ram_hwnd, text) + statusWidth -= textWidth + + GuiControl,, Bar_#%m%_ram, % text + GuiControl, Move, Bar_#%m%_ram, % "w" textWidth " x" statusWidth + GuiControl, Move, Bar_#%m%_ram_event, % "w" textWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_ram_highlighted, % "w" textWidth " x" statusWidth + + statusWidth -= Config_barIconSpacing + + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_ram_icon_hwnd, Config_barIcon_#3) + statusWidth -= iconWidth + + GuiControl,, Bar_#%m%_ram_icon, %Config_barIcon_#3% + GuiControl, Move, Bar_#%m%_ram_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY + GuiControl, Move, Bar_#%m%_ram_icon_event, % "w" iconWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_ram_icon_highlighted, % "w" iconWidth " x" statusWidth + + statusWidth -= Config_barItemSpacing + } + If Config_readinCpu { + text := ResourceMonitor_getCpuText() + textWidth := Bar_getTrueTextWidth(Bar_#%m%_cpu_hwnd, text) + statusWidth -= textWidth + + GuiControl,, Bar_#%m%_cpu, % text + GuiControl, Move, Bar_#%m%_cpu, % "w" textWidth " x" statusWidth + GuiControl, Move, Bar_#%m%_cpu_event, % "w" textWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_cpu_highlighted, % "w" textWidth " x" statusWidth + + statusWidth -= Config_barIconSpacing + + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_cpu_icon_hwnd, Config_barIcon_#4) + statusWidth -= iconWidth + + GuiControl,, Bar_#%m%_cpu_icon, %Config_barIcon_#4% + GuiControl, Move, Bar_#%m%_cpu_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY + GuiControl, Move, Bar_#%m%_cpu_icon_event, % "w" iconWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_cpu_icon_highlighted, % "w" iconWidth " x" statusWidth + + statusWidth -= Config_barItemSpacing + } + If Config_readinBat { + If (bat1 < 10) And (bat2 = "off") { + ;; Change the color, if the battery level is below 10% + ;GuiControl, +Background%Config_backColor_#3_#8% +c%Config_foreColor_#3_#8%, Bar_#%m%_battery_highlighted + GuiControl, +c%Config_fontColor_#3_#8%, Bar_#%m%_battery + } Else If (bat2 = "off") { + ;; Change the color, if the pc is not plugged in + ;GuiControl, +Background%Config_backColor_#2_#8% +c%Config_foreColor_#2_#8%, Bar_#%m%_battery_highlighted + GuiControl, +c%Config_fontColor_#2_#8%, Bar_#%m%_battery + } Else { + ;GuiControl, +Background%Config_backColor_#1_#8% +c%Config_foreColor_#1_#8%, Bar_#%m%_battery_highlighted + GuiControl, +c%Config_fontColor_#1_#8%, Bar_#%m%_battery + } + + text := % bat3 "%" + textWidth := Bar_getTrueTextWidth(Bar_#%m%_battery_hwnd, text) + statusWidth -= textWidth + + GuiControl,, Bar_#%m%_battery, % text + GuiControl, Move, Bar_#%m%_battery, % "w" textWidth " x" statusWidth + GuiControl, Move, Bar_#%m%_battery_event, % "w" textWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_battery_highlighted, % "w" textWidth " x" statusWidth + + statusWidth -= Config_barIconSpacing + + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_battery_icon_hwnd, Config_barIcon_#5) + statusWidth -= iconWidth + + GuiControl,, Bar_#%m%_battery_icon, %Config_barIcon_#5% + GuiControl, Move, Bar_#%m%_battery_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY + GuiControl, Move, Bar_#%m%_battery_icon_event, % "w" iconWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_battery_icon_highlighted, % "w" iconWidth " x" statusWidth + + statusWidth -= Config_barItemSpacing + } + If Config_readinMusic { + text := MusicBee_GetNowPlaying() + textWidth := Bar_getTrueTextWidth(Bar_#%m%_music_hwnd, text) + statusWidth -= textWidth + + GuiControl,, Bar_#%m%_music, % text + GuiControl, Move, Bar_#%m%_music, % "w" textWidth " x" statusWidth + GuiControl, Move, Bar_#%m%_music_event, % "w" textWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_music_highlighted, % "w" textWidth " x" statusWidth + + statusWidth -= Config_barIconSpacing + + if (text == "") { + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_music_icon_hwnd, "") + } else { + iconWidth := Bar_getTrueTextWidth(Bar_#%m%_music_icon_hwnd, Config_barIcon_#7) + } + statusWidth -= iconWidth + + GuiControl,, Bar_#%m%_music_icon, %Config_barIcon_#7% + GuiControl, Move, Bar_#%m%_music_icon, % "w" iconWidth " x" statusWidth " h" Bar_ctrlHeight " y" iconY + GuiControl, Move, Bar_#%m%_music_icon_event, % "w" iconWidth " x" statusWidth + ;GuiControl, Move, Bar_#%m%_music_icon_highlighted, % "w" iconWidth " x" statusWidth + + statusWidth -= Config_barItemSpacing + } + + ; set this in update loop because OpenShell likes to revert it when you change settings + If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass And Config_classicThemeTaskbar) { + trayWndId := WinExist("ahk_class " Monitor_#%m%_taskBarClass) + WinSet, Style, -0x40000, ahk_id %trayWndId% ; WS_THICKFRAME + WinSet, Style, +0x80, ahk_id %trayWndId% ; DS_MODALFRAME + WinSet, Style, +0x0004, ahk_id %trayWndId% ; DS_3DLOOK + + ;WinSet, ExStyle, +0x1, ahk_id %trayWndId% ; WS_EX_DLGMODALFRAME + WinSet, ExStyle, +0x20000, ahk_id %trayWndId% ; WS_EX_STATICEDGE + } + } +} + +Bar_updateTitle() { + Local aWndId, aWndTitle, content, GuiN, i, title, titleWidth, barWidth, titleX + + WinGet, aWndId, ID, A + WinGetTitle, aWndTitle, ahk_id %aWndId% + If InStr(Bar_hideTitleWndIds, aWndId ";") Or (aWndTitle = "bug.n_BAR_0") + aWndTitle := "" + If aWndId And InStr(Manager_managedWndIds, aWndId . ";") And Window_#%aWndId%_isFloating + aWndTitle := "~ " aWndTitle + If (Manager_monitorCount > 1) + aWndTitle := "[" Manager_aMonitor "] " aWndTitle + + title := aWndTitle + + if (StrLen(title) > 48) { + ;; Shorten the window title if its length exceeds the width of the bar + title := SubStr(title, 1, 48) . "…" + } + StringReplace, title, title, &, &&, All ;; Special character '&', which would underline the next letter. + + + Loop, % Manager_monitorCount { + barWidth := Monitor_#%A_Index%_barWidth + titleWidth := Bar_getTrueTextWidth(Bar_#%A_Index%_title_hwnd, title) + titleX := barWidth / 2 - titleWidth / 2 + + GuiN := (A_Index - 1) + 1 + If (Config_readinTitle) { + Debug_logMessage("DEBUG[6] Bar_updateTitle(): Gui, " . GuiN . ": Default", 6) + Gui, %GuiN%: Default + GuiControlGet, content, , Bar_#%A_Index%_title + If (A_Index = Manager_aMonitor) { + If Not (content = title) + GuiControl,, Bar_#%A_Index%_title, % title + GuiControl, Move, Bar_#%A_Index%_title, % "w" titleWidth "x" titleX + GuiControl, Move, Bar_#%A_Index%_title_event, % "w" titleWidth "x" titleX + GuiControl, Move, Bar_#%A_Index%_title_highlighted, % "w" titleWidth "x" titleX + } Else If Not (content = "") + GuiControl, , Bar_#%A_Index%_title, + } + } + Bar_aWndId := aWndId +} + +Bar_updateView(m, v) { + Local managedWndId0, wndId0, wndIds + + GuiN := (m - 1) + 1 + Gui, %GuiN%: Default + Debug_logMessage("DEBUG[6] Bar_updateView(): m: " . m . "; Gui, " . GuiN . ": Default", 6) + + StringTrimRight, wndIds, Manager_managedWndIds, 1 + StringSplit, managedWndId, wndIds, `; + + If (v = Monitor_#%m%_aView_#1) { + ;; Set foreground/background colors if the view is the current view. + ;GuiControl, +Background%Config_backColor_#2_#1% +c%Config_foreColor_#2_#1%, Bar_#%m%_view_#%v%_highlighted + GuiControl, +c%Config_fontColor_#2_#1%, Bar_#%m%_view_#%v% + } Else { + ;; Set foreground/background colors. + ;GuiControl, +Background%Config_backColor_#1_#1% +c%Config_foreColor_#1_#1%, Bar_#%m%_view_#%v%_highlighted + GuiControl, +c%Config_fontColor_#1_#1%, Bar_#%m%_view_#%v% + } + + Loop, % Config_viewCount { + StringTrimRight, wndIds, View_#%m%_#%A_Index%_wndIds, 1 + StringSplit, wndId, wndIds, `; + TagPercent := wndId0 / managedWndId0 * 100 + If (TagPercent > 0 and v != A_Index) { + GuiControl, +c%Config_fontColor_#3_#1%, Bar_#%m%_view_#%A_Index% + } + ;GuiControl, , Bar_#%m%_view_#%A_Index%_highlighted, % wndId0 / managedWndId0 * 100 ;; Update the percentage fill for the view. + GuiControl, , Bar_#%m%_view_#%A_Index%, % Config_viewNames_#%A_Index% ;; Refresh the number on the bar. + } +} diff --git a/src/Config.ahk b/src/Config.ahk index 80e9d3d..cc5c9fe 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -1,540 +1,540 @@ -/* - bug.n -- tiling window management - Copyright (c) 2010-2019 Joshua Fuhs, joten - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - @license GNU General Public License version 3 - ../LICENSE.md or <http://www.gnu.org/licenses/> - - @version 9.1.0 -*/ - -Config_init() { - Local i, key, layout0, layout1, layout2, vNames0, vNames1, vNames2, vNames3, vNames4, vNames5, vNames6, vNames7, vNames8, vNames9 - - ;; Status bar - Config_showBar := True - Config_horizontalBarPos := "left" - Config_verticalBarPos := "top" - Config_barWidth := "100%" - Config_singleRowBar := True - Config_spaciousBar := False - Config_fontName := "Lucida Console" - Config_fontSize := - Config_largeFontSize := 24 - Loop, 3 { - Config_backColor_#%A_Index% := - Config_foreColor_#%A_Index% := - Config_fontColor_#%A_Index% := - } - Config_barTransparency := "off" - Config_barCommands := "Run, explore " Main_docDir ";Monitor_toggleBar();Reload;ExitApp" - Config_barTaskbarBlend := False - Config_readinBat := False - Config_readinCpu := False - Config_readinDate := True - Config_readinDateFormat := "ddd, dd. MMM. yyyy" - Config_readinRam := False - Config_readinMusic := False - Config_readinTime := True - Config_readinTimeBinary := False - Config_readinTimeFormat := "HH:mm" - Config_readinVolume := False - Config_readinInterval := 30000 - Config_readinTitle := True - Config_barItemSpacing := 8 - Config_barIconSpacing := 4 - Config_iconFontYOffset := 3 - - ;; Windows ui elements - Config_bbCompatibility := False - Config_borderWidth := 0 - Config_borderPadding := -1 - Config_showTaskBar := False - Config_showBorder := True - Config_selBorderColor := "" - Config_scalingFactor := 1 ;; Undocumented. The value is retrieved by `Config_getSystemSettings()` from the registry. - ;; It should not be set manually by the user, - ;; but is dependant on the setting in the `Display control panel` of Windows under `Appearance and Personalization`. - Config_classicThemeFixes := False - Config_classicThemeTaskbar := False - - ;; Window arrangement - Config_viewNames := "1;2;3;4;5;6;7;8;9" - Config_layout_#1 := "[]=;tile" - Config_layout_#2 := "[M];monocle" - Config_layout_#3 := "><>;" - Config_layoutCount := 3 - Config_layoutAxis_#1 := 1 - Config_layoutAxis_#2 := 2 - Config_layoutAxis_#3 := 2 - Config_layoutGapWidth := 0 - Config_layoutMFactor := 0.6 - Config_areaTraceTimeout := 1000 - Config_continuouslyTraceAreas := False - Config_dynamicTiling := True - Config_ghostWndSubString := " (Not Responding)" - Config_mFactCallInterval := 700 - Config_mouseFollowsFocus := True - Config_newWndPosition := "top" - Config_onActiveHiddenWnds := "view" - Config_shellMsgDelay := 350 - Config_syncMonitorViews := 0 - Config_viewFollowsTagged := False - Config_viewMargins := "0;0;0;0" - Config_hideTitleBars := True - - ;; Config_rule_#<i> := "<class>;<title>;<function name>;<is managed>;<m>;<tags>;<is floating>;<is decorated>;<hide title>;<action>" - Config_rule_#1 := ".*;.*;;1;0;0;0;0;0;" - Config_rule_#2 := ".*;.*;Window_isChild;0;0;0;1;1;1;" - Config_rule_#3 := ".*;.*;Window_isPopup;0;0;0;1;1;1;" - Config_rule_#4 := "QWidget;.*;;1;0;0;0;0;0;" - Config_rule_#5 := "SWT_Window0;.*;;1;0;0;0;0;0;" - Config_rule_#6 := "Xming;.*;;1;0;0;0;0;0;" - Config_rule_#7 := "MsiDialog(No)?CloseClass;.*;;1;0;0;1;1;0;" - Config_rule_#8 := "AdobeFlashPlayerInstaller;.*;;1;0;0;1;0;0;" - Config_rule_#9 := "CalcFrame;.*;;1;0;0;1;1;0;" - Config_rule_#10 := "CabinetWClass;.*;;1;0;0;0;1;0;" - Config_rule_#11 := "OperationStatusWindow;.*;;0;0;0;1;1;0;" - Config_rule_#12 := "Chrome_WidgetWin_1;.*;;1;0;0;0;1;0;" - Config_rule_#13 := "Chrome_WidgetWin_1;.*;Window_isPopup;0;0;0;1;1;0;" - Config_rule_#14 := "Chrome_RenderWidgetHostHWND;.*;;0;0;0;1;1;0;" - Config_rule_#15 := "IEFrame;.*Internet Explorer;;1;0;0;0;1;0;" - Config_rule_#16 := "MozillaWindowClass;.*Mozilla Firefox;;1;0;0;0;1;0;" - Config_rule_#17 := "MozillaDialogClass;.*;;1;0;0;1;1;0;" - Config_rule_#18 := "ApplicationFrameWindow;.*Edge;;1;0;0;0;1;0;" - Config_ruleCount := 18 ;; This variable has to be set to the total number of active rules above. - - ;; Configuration management - Config_autoSaveSession := "auto" ;; "off" | "auto" | "ask" - Config_maintenanceInterval := 5000 - Config_monitorDisplayChangeMessages := "ask" ;; "off" | "on" | "ask" - - Config_hotkeyCount := 0 - Config_restoreConfig(Config_filePath) - ;If (SubStr(A_OSVersion, 1, 3) = "10.") { - ; Config_borderWidth := 0 - ; Config_borderPadding := -1 - ; Config_showBorder := True - ; Config_selBorderColor := "" - ;} - - Config_getSystemSettings() - Config_initColors() - Config_initBarIcons() - Loop, % Config_layoutCount { - StringSplit, layout, Config_layout_#%A_Index%, `; - Config_layoutFunction_#%A_Index% := layout2 - Config_layoutSymbol_#%A_Index% := layout1 - } - StringSplit, vNames, Config_viewNames, `; - If vNames0 > 9 - Config_viewCount := 9 - Else - Config_viewCount := vNames0 - Loop, % Config_viewCount - Config_viewNames_#%A_Index% := vNames%A_Index% -} - -Config_initColors() { - Global - - Loop, 3 { - StringReplace, Config_backColor_#%A_Index%, Config_backColor_#%A_Index%, `;0`;, `;000000`;, All - Config_backColor_#%A_Index% := RegExReplace(Config_backColor_#%A_Index%, "^0;", "000000;") - Config_backColor_#%A_Index% := RegExReplace(Config_backColor_#%A_Index%, ";0$", ";000000") - StringSplit, Config_backColor_#%A_Index%_#, Config_backColor_#%A_Index%, `; - - StringReplace, Config_foreColor_#%A_Index%, Config_foreColor_#%A_Index%, `;0`;, `;000000`;, All - Config_foreColor_#%A_Index% := RegExReplace(Config_foreColor_#%A_Index%, "^0;", "000000;") - Config_foreColor_#%A_Index% := RegExReplace(Config_foreColor_#%A_Index%, ";0$", ";000000") - StringSplit, Config_foreColor_#%A_Index%_#, Config_foreColor_#%A_Index%, `; - - StringReplace, Config_fontColor_#%A_Index%, Config_fontColor_#%A_Index%, `;0`;, `;000000`;, All - Config_fontColor_#%A_Index% := RegExReplace(Config_fontColor_#%A_Index%, "^0;", "000000;") - Config_fontColor_#%A_Index% := RegExReplace(Config_fontColor_#%A_Index%, ";0$", ";000000") - StringSplit, Config_fontColor_#%A_Index%_#, Config_fontColor_#%A_Index%, `; - } -} - -Config_initBarIcons() { - Global - - StringSplit, Config_barIcon_#, Config_barIcons, `; -} - -Config_convertSystemColor(systemColor) -{ ;; systemColor format: 0xBBGGRR - rr := SubStr(systemColor, 7, 2) - gg := SubStr(systemColor, 5, 2) - bb := SubStr(systemColor, 3, 2) - - Return, rr gg bb -} - -Config_edit() { - Global Config_filePath - - If Not FileExist(Config_filePath) - Config_UI_saveSession() - Run, edit %Config_filePath% -} - -Config_getSystemSettings() { - Global Config_backColor_#1, Config_foreColor_#1, Config_fontColor_#1 - Global Config_backColor_#2, Config_foreColor_#2, Config_fontColor_#2 - Global Config_backColor_#3, Config_foreColor_#3, Config_fontColor_#3 - Global Config_fontName, Config_fontSize, Config_scalingFactor - - If Not Config_fontName { - ncmSize := VarSetCapacity(ncm, 4 * (A_OSVersion = "WIN_VISTA" ? 11 : 10) + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), 0) - NumPut(ncmSize, ncm, 0, "UInt") - DllCall("SystemParametersInfo", "UInt", 0x0029, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) - - VarSetCapacity(lf, 28 + 32 * (A_IsUnicode ? 2 : 1), 0) - DllCall("RtlMoveMemory", "Str", lf, "UInt", &ncm + 24, "UInt", 28 + 32 * (A_IsUnicode ? 2 : 1)) - VarSetCapacity(Config_fontName, 32 * (A_IsUnicode ? 2 : 1), 0) - DllCall("RtlMoveMemory", "Str", Config_fontName, "UInt", &lf + 28, "UInt", 32 * (A_IsUnicode ? 2 : 1)) - ;; maestrith: Script Writer (http://www.autohotkey.net/~maestrith/Script Writer/) - } - If Not Config_fontSize { - ncmSize := VarSetCapacity(ncm, 4 * (A_OSVersion = "WIN_VISTA" ? 11 : 10) + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), 0) - NumPut(ncmSize, ncm, 0, "UInt") - DllCall("SystemParametersInfo", "UInt", 0x0029, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) - - lfSize := VarSetCapacity(lf, 28 + 32 * (A_IsUnicode ? 2 : 1), 0) - NumPut(lfSize, lf, 0, "UInt") - DllCall("RtlMoveMemory", "Str", lf, "UInt", &ncm + 24, "UInt", 28 + 32 * (A_IsUnicode ? 2 : 1)) - - lfHeightSize := VarSetCapacity(lfHeight, 4, 0) - NumPut(lfHeightSize, lfHeight, 0, "Int") - lfHeight := NumGet(lf, 0, "Int") - - lfPixelsY := DllCall("GetDeviceCaps", "UInt", DllCall("GetDC", "UInt", 0), "UInt", 90) ;; LOGPIXELSY - Config_fontSize := -DllCall("MulDiv", "Int", lfHeight, "Int", 72, "Int", lfPixelsY) - ;; maestrith: Script Writer (http://www.autohotkey.net/~maestrith/Script Writer/) - } - SetFormat, Integer, hex - If Not (Config_backColor_#1 And Config_foreColor_#1 And Config_fontColor_#1 - And Config_backColor_#2 And Config_foreColor_#2 And Config_fontColor_#2 - And Config_backColor_#3 And Config_foreColor_#3 And Config_fontColor_#3) { - COLOR_ACTIVECAPTION := Config_convertSystemColor(DllCall("GetSysColor", "Int", 2)) - COLOR_CAPTIONTEXT := Config_convertSystemColor(DllCall("GetSysColor", "Int", 9)) - COLOR_GRADIENTACTIVECAPTION := Config_convertSystemColor(DllCall("GetSysColor", "Int", 27)) - COLOR_GRADIENTINACTIVECAPTION := Config_convertSystemColor(DllCall("GetSysColor", "Int", 28)) - COLOR_HIGHLIGHT := Config_convertSystemColor(DllCall("GetSysColor", "Int", 13)) - COLOR_INACTIVECAPTION := Config_convertSystemColor(DllCall("GetSysColor", "Int", 3)) - COLOR_INACTIVECAPTIONTEXT := Config_convertSystemColor(DllCall("GetSysColor", "Int", 19)) - COLOR_MENU := Config_convertSystemColor(DllCall("GetSysColor", "Int", 4)) - COLOR_MENUTEXT := Config_convertSystemColor(DllCall("GetSysColor", "Int", 7)) - ;; <view>;<layout>;<title>;<shebang>;<time>;<date>;<anyText>;<batteryStatus>;<volumeLevel> - If Not Config_backColor_#1 { - Config_backColor_#1 := COLOR_GRADIENTINACTIVECAPTION ";" COLOR_ACTIVECAPTION ";" COLOR_MENU ";" COLOR_ACTIVECAPTION ";" COLOR_MENU ";" COLOR_ACTIVECAPTION ";" - Config_backColor_#1 .= COLOR_GRADIENTINACTIVECAPTION ";" COLOR_GRADIENTACTIVECAPTION ";" COLOR_GRADIENTACTIVECAPTION - } - If Not Config_backColor_#2 - Config_backColor_#2 := COLOR_GRADIENTACTIVECAPTION ";;;;;;;" COLOR_MENU ";" COLOR_MENU - If Not Config_backColor_#3 - Config_backColor_#3 := ";;;;;;;ff8040;" - - If Not Config_foreColor_#1 { - Config_foreColor_#1 := COLOR_INACTIVECAPTION ";" COLOR_ACTIVECAPTION ";" COLOR_MENU ";" COLOR_ACTIVECAPTION ";" COLOR_MENU ";" COLOR_ACTIVECAPTION ";" - Config_foreColor_#1 .= COLOR_INACTIVECAPTION ";" COLOR_ACTIVECAPTION ";" COLOR_GRADIENTINACTIVECAPTION - } - If Not Config_foreColor_#2 - Config_foreColor_#2 := COLOR_ACTIVECAPTION ";;;;;;;" COLOR_HIGHLIGHT ";" COLOR_HIGHLIGHT - If Not Config_foreColor_#3 - Config_foreColor_#3 := ";;;;;;;" COLOR_INACTIVECAPTION ";" - - If Not Config_fontColor_#1 { - Config_fontColor_#1 := COLOR_INACTIVECAPTIONTEXT ";" COLOR_CAPTIONTEXT ";" COLOR_MENUTEXT ";" COLOR_CAPTIONTEXT ";" COLOR_MENUTEXT ";" COLOR_CAPTIONTEXT ";" - Config_fontColor_#1 .= COLOR_INACTIVECAPTIONTEXT ";" COLOR_CAPTIONTEXT ";" COLOR_INACTIVECAPTIONTEXT - } - If Not Config_fontColor_#2 - Config_fontColor_#2 := COLOR_CAPTIONTEXT ";;;;;;;" COLOR_MENUTEXT ";" COLOR_MENUTEXT - If Not Config_fontColor_#3 - Config_fontColor_#3 := ";;;;;;;" COLOR_INACTIVECAPTIONTEXT ";" - } - SetFormat, Integer, d - - RegRead, appliedDPI, HKEY_CURRENT_USER, Control Panel\Desktop\WindowMetrics, AppliedDPI - If (ErrorLevel = 0) - Config_scalingFactor := 96 / appliedDPI -} - -Config_hotkeyLabel: - Config_redirectHotkey(A_ThisHotkey) -Return - -Config_readinAny() { - ;; Add information to the variable 'text' in this function to display it in the status bar. - Global Config_readinCpu, Config_readinDiskLoad, Config_readinMemoryUsage, Config_readinNetworkLoad - - text := "" - If (Config_readinCpu Or Config_readinDiskLoad Or Config_readinMemoryUsage Or Config_readinNetworkLoad) - text .= ResourceMonitor_getText() - - Return, text -} - -Config_redirectHotkey(key) -{ - Global - - Loop, % Config_hotkeyCount - { - If (key = Config_hotkey_#%A_index%_key) - { - Debug_logMessage("DEBUG[1] Config_redirectHotkey: Found " Config_hotkey_#%A_index%_key " -> " Config_hotkey_#%A_index%_command, 1) - Main_evalCommand(Config_hotkey_#%A_index%_command) - Break - } - } -} - -Config_restoreConfig(filename) -{ - Local cmd, i, key, type, val, var - - If Not FileExist(filename) - Return - - Loop, READ, %filename% - If (SubStr(A_LoopReadLine, 1, 7) = "Config_") - { - ;Log_msg("Processing line: " . A_LoopReadLine) - i := InStr(A_LoopReadLine, "=") - var := SubStr(A_LoopReadLine, 1, i - 1) - val := SubStr(A_LoopReadLine, i + 1) - type := SubStr(var, 1, 13) - If (type = "Config_hotkey") - { - Debug_logMessage("Processing configured hotkey: " . A_LoopReadLine, 0) - i := InStr(val, "::") - key := SubStr(val, 1, i - 1) - cmd := SubStr(val, i + 2) - If Not cmd - Hotkey, %key%, Off - Else - { - Debug_logMessage(" Hotkey: " . key . " -> " . cmd, 0) - Config_hotkeyCount += 1 - Config_hotkey_#%Config_hotkeyCount%_key := key - Config_hotkey_#%Config_hotkeyCount%_command := cmd - Hotkey, %key%, Config_hotkeyLabel - } - } - Else If (type = "Config_rule") - { - i := 0 - If InStr(var, "Config_rule_#") - i := SubStr(var, 14) - If (i = 0 Or i > Config_ruleCount) - { - Config_ruleCount += 1 - i := Config_ruleCount - } - var := "Config_rule_#" i - } - %var% := val - } -} - -Config_restoreLayout(filename, m) { - Local i, var, val - - If Not FileExist(filename) - Return - - Loop, READ, %filename% - If (SubStr(A_LoopReadLine, 1, 10 + StrLen(m)) = "Monitor_#" m "_" Or SubStr(A_LoopReadLine, 1, 8 + StrLen(m)) = "View_#" m "_#") { - i := InStr(A_LoopReadLine, "=") - var := SubStr(A_LoopReadLine, 1, i - 1) - val := SubStr(A_LoopReadLine, i + 1) - %var% := val - } -} - -Config_saveSession(original, target) -{ - Local m, text, tmpfilename - - tmpfilename := target . ".tmp" - FileDelete, %tmpfilename% - - text := "; bug.n - tiling window management`n; @version " VERSION "`n`n" - If FileExist(original) - { - Loop, READ, %original% - { - If (SubStr(A_LoopReadLine, 1, 7) = "Config_") - text .= A_LoopReadLine "`n" - } - text .= "`n" - } - - Loop, % Manager_monitorCount - { - m := A_Index - If Not (Monitor_#%m%_aView_#1 = 1) - text .= "Monitor_#" m "_aView_#1=" Monitor_#%m%_aView_#1 "`n" - If Not (Monitor_#%m%_aView_#2 = 1) - text .= "Monitor_#" m "_aView_#2=" Monitor_#%m%_aView_#2 "`n" - If Not (Monitor_#%m%_showBar = Config_showBar) - text .= "Monitor_#" m "_showBar=" Monitor_#%m%_showBar "`n" - Loop, % Config_viewCount - { - If Not (View_#%m%_#%A_Index%_layout_#1 = 1) - text .= "View_#" m "_#" A_Index "_layout_#1=" View_#%m%_#%A_Index%_layout_#1 "`n" - If Not (View_#%m%_#%A_Index%_layout_#2 = 1) - text .= "View_#" m "_#" A_Index "_layout_#2=" View_#%m%_#%A_Index%_layout_#2 "`n" - If Not (View_#%m%_#%A_Index%_layoutAxis_#1 = Config_layoutAxis_#1) - text .= "View_#" m "_#" A_Index "_layoutAxis_#1=" View_#%m%_#%A_Index%_layoutAxis_#1 "`n" - If Not (View_#%m%_#%A_Index%_layoutAxis_#2 = Config_layoutAxis_#2) - text .= "View_#" m "_#" A_Index "_layoutAxis_#2=" View_#%m%_#%A_Index%_layoutAxis_#2 "`n" - If Not (View_#%m%_#%A_Index%_layoutAxis_#3 = Config_layoutAxis_#3) - text .= "View_#" m "_#" A_Index "_layoutAxis_#3=" View_#%m%_#%A_Index%_layoutAxis_#3 "`n" - If Not (View_#%m%_#%A_Index%_layoutGapWidth = Config_layoutGapWidth) - text .= "View_#" m "_#" A_Index "_layoutGapWidth=" View_#%m%_#%A_Index%_layoutGapWidth "`n" - If Not (View_#%m%_#%A_Index%_layoutMFact = Config_layoutMFactor) - text .= "View_#" m "_#" A_Index "_layoutMFact=" View_#%m%_#%A_Index%_layoutMFact "`n" - If Not (View_#%m%_#%A_Index%_layoutMX = 1) - text .= "View_#" m "_#" A_Index "_layoutMX=" View_#%m%_#%A_Index%_layoutMX "`n" - If Not (View_#%m%_#%A_Index%_layoutMY = 1) - text .= "View_#" m "_#" A_Index "_layoutMY=" View_#%m%_#%A_Index%_layoutMY "`n" - } - } - - ;; The FileMove below is an all-or-nothing replacement of the file. - ;; We don't want to leave this half-finished. - FileAppend, %text%, %tmpfilename% - If ErrorLevel And Not (original = Config_filePath And target = Config_filePath And Not FileExist(original)) { - If FileExist(tmpfilename) - FileDelete, %tmpfilename% - } Else - FileMove, %tmpfilename%, %target%, 1 -} - -Config_UI_saveSession() { - Global Config_filePath - - Config_saveSession(Config_filePath, Config_filePath) -} - -#MaxHotkeysPerInterval 200 - -;; Key definitions -;; Window management -#Down::View_activateWindow(0, +1) -#Up::View_activateWindow(0, -1) -#+Down::View_shuffleWindow(0, +1) -#+Up::View_shuffleWindow(0, -1) -#+Enter::View_shuffleWindow(1) -#c::Manager_closeWindow() -#+d::Window_toggleDecor() -#+f::View_toggleFloatingWindow() -#+m::Manager_moveWindow() -#^m::Manager_minimizeWindow() -#+s::Manager_sizeWindow() -#+x::Manager_maximizeWindow() -#i::Manager_getWindowInfo() -#+i::Manager_getWindowList() -!Down::View_moveWindow(0, +1) -!Up::View_moveWindow(0, -1) -!+Enter::Manager_maximizeWindow() -!1::View_moveWindow(1) -!2::View_moveWindow(2) -!3::View_moveWindow(3) -!4::View_moveWindow(4) -!5::View_moveWindow(5) -!6::View_moveWindow(6) -!7::View_moveWindow(7) -!8::View_moveWindow(8) -!9::View_moveWindow(9) -!0::View_moveWindow(10) -!BackSpace::View_toggleStackArea() - -;; Window debugging -#^i::Debug_logViewWindowList() -#^+i::Debug_logManagedWindowList() -#^h::Debug_logHelp() -#^d::Debug_setLogLevel(0, -1) -#^+d::Debug_setLogLevel(0, +1) - -;; Layout management -#Tab::View_setLayout(-1) -#f::View_setLayout(3) -#m::View_setLayout(2) -#t::View_setLayout(1) -#Left::View_setLayoutProperty("MFactor", 0, -0.05) -#Right::View_setLayoutProperty("MFactor", 0, +0.05) -#^t::View_setLayoutProperty("Axis", 0, +1, 1) -#^Enter::View_setLayoutProperty("Axis", 0, +2, 1) -#^Tab::View_setLayoutProperty("Axis", 0, +1, 2) -#^+Tab::View_setLayoutProperty("Axis", 0, +1, 3) -#^Up::View_setLayoutProperty("MY", 0, +1) -#^Down::View_setLayoutProperty("MY", 0, -1) -#^Right::View_setLayoutProperty("MX", 0, +1) -#^Left::View_setLayoutProperty("MX", 0, -1) -#+Left::View_setLayoutProperty("GapWidth", 0, -2) -#+Right::View_setLayoutProperty("GapWidth", 0, +2) -#^Backspace::View_resetTileLayout() - -;; View/Tag management -#+n::View_toggleMargins() -#BackSpace::Monitor_activateView(-1) -#+0::Monitor_setWindowTag(10) -#1::Monitor_activateView(1) -#+1::Monitor_setWindowTag(1) -#^1::Monitor_toggleWindowTag(1) -#2::Monitor_activateView(2) -#+2::Monitor_setWindowTag(2) -#^2::Monitor_toggleWindowTag(2) -#3::Monitor_activateView(3) -#+3::Monitor_setWindowTag(3) -#^3::Monitor_toggleWindowTag(3) -#4::Monitor_activateView(4) -#+4::Monitor_setWindowTag(4) -#^4::Monitor_toggleWindowTag(4) -#5::Monitor_activateView(5) -#+5::Monitor_setWindowTag(5) -#^5::Monitor_toggleWindowTag(5) -#6::Monitor_activateView(6) -#+6::Monitor_setWindowTag(6) -#^6::Monitor_toggleWindowTag(6) -#7::Monitor_activateView(7) -#+7::Monitor_setWindowTag(7) -#^7::Monitor_toggleWindowTag(7) -#8::Monitor_activateView(8) -#+8::Monitor_setWindowTag(8) -#^8::Monitor_toggleWindowTag(8) -#9::Monitor_activateView(9) -#+9::Monitor_setWindowTag(9) -#^9::Monitor_toggleWindowTag(9) -~WheelUp::Manager_activateViewByMouse(-1) -~WheelDown::Manager_activateViewByMouse(+1) - -;; Monitor management -#.::Manager_activateMonitor(0, +1) -#,::Manager_activateMonitor(0, -1) -#+.::Manager_setWindowMonitor(0, +1) -#+,::Manager_setWindowMonitor(0, -1) -#^+.::Manager_setViewMonitor(0, +1) -#^+,::Manager_setViewMonitor(0, -1) - -;; GUI management -#+Space::Monitor_toggleBar() -#Space::Monitor_toggleTaskBar() -#y::Bar_toggleCommandGui() -#+y::Monitor_toggleNotifyIconOverflowWindow() -!+y::View_traceAreas() - -;; Administration -#^e::Config_edit() -#^s::Config_UI_saveSession() -#^r::Reload -#^q::ExitApp +/* + bug.n -- tiling window management + Copyright (c) 2010-2019 Joshua Fuhs, joten + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + @license GNU General Public License version 3 + ../LICENSE.md or <http://www.gnu.org/licenses/> + + @version 9.1.0 +*/ + +Config_init() { + Local i, key, layout0, layout1, layout2, vNames0, vNames1, vNames2, vNames3, vNames4, vNames5, vNames6, vNames7, vNames8, vNames9 + + ;; Status bar + Config_showBar := True + Config_horizontalBarPos := "left" + Config_verticalBarPos := "top" + Config_barWidth := "100%" + Config_singleRowBar := True + Config_spaciousBar := False + Config_fontName := "Lucida Console" + Config_fontSize := + Config_largeFontSize := 24 + Loop, 3 { + Config_backColor_#%A_Index% := + Config_foreColor_#%A_Index% := + Config_fontColor_#%A_Index% := + } + Config_barTransparency := "off" + Config_barCommands := "Run, explore " Main_docDir ";Monitor_toggleBar();Reload;ExitApp" + Config_barTaskbarBlend := False + Config_readinBat := False + Config_readinCpu := False + Config_readinDate := True + Config_readinDateFormat := "ddd, dd. MMM. yyyy" + Config_readinRam := False + Config_readinMusic := False + Config_readinTime := True + Config_readinTimeBinary := False + Config_readinTimeFormat := "HH:mm" + Config_readinVolume := False + Config_readinInterval := 30000 + Config_readinTitle := True + Config_barItemSpacing := 8 + Config_barIconSpacing := 4 + Config_iconFontYOffset := 3 + + ;; Windows ui elements + Config_bbCompatibility := False + Config_borderWidth := 0 + Config_borderPadding := -1 + Config_showTaskBar := False + Config_showBorder := True + Config_selBorderColor := "" + Config_scalingFactor := 1 ;; Undocumented. The value is retrieved by `Config_getSystemSettings()` from the registry. + ;; It should not be set manually by the user, + ;; but is dependant on the setting in the `Display control panel` of Windows under `Appearance and Personalization`. + Config_classicThemeFixes := False + Config_classicThemeTaskbar := False + + ;; Window arrangement + Config_viewNames := "1;2;3;4;5;6;7;8;9" + Config_layout_#1 := "[]=;tile" + Config_layout_#2 := "[M];monocle" + Config_layout_#3 := "><>;" + Config_layoutCount := 3 + Config_layoutAxis_#1 := 1 + Config_layoutAxis_#2 := 2 + Config_layoutAxis_#3 := 2 + Config_layoutGapWidth := 0 + Config_layoutMFactor := 0.6 + Config_areaTraceTimeout := 1000 + Config_continuouslyTraceAreas := False + Config_dynamicTiling := True + Config_ghostWndSubString := " (Not Responding)" + Config_mFactCallInterval := 700 + Config_mouseFollowsFocus := True + Config_newWndPosition := "top" + Config_onActiveHiddenWnds := "view" + Config_shellMsgDelay := 350 + Config_syncMonitorViews := 0 + Config_viewFollowsTagged := False + Config_viewMargins := "0;0;0;0" + Config_hideTitleBars := True + + ;; Config_rule_#<i> := "<class>;<title>;<function name>;<is managed>;<m>;<tags>;<is floating>;<is decorated>;<hide title>;<action>" + Config_rule_#1 := ".*;.*;;1;0;0;0;0;0;" + Config_rule_#2 := ".*;.*;Window_isChild;0;0;0;1;1;1;" + Config_rule_#3 := ".*;.*;Window_isPopup;0;0;0;1;1;1;" + Config_rule_#4 := "QWidget;.*;;1;0;0;0;0;0;" + Config_rule_#5 := "SWT_Window0;.*;;1;0;0;0;0;0;" + Config_rule_#6 := "Xming;.*;;1;0;0;0;0;0;" + Config_rule_#7 := "MsiDialog(No)?CloseClass;.*;;1;0;0;1;1;0;" + Config_rule_#8 := "AdobeFlashPlayerInstaller;.*;;1;0;0;1;0;0;" + Config_rule_#9 := "CalcFrame;.*;;1;0;0;1;1;0;" + Config_rule_#10 := "CabinetWClass;.*;;1;0;0;0;1;0;" + Config_rule_#11 := "OperationStatusWindow;.*;;0;0;0;1;1;0;" + Config_rule_#12 := "Chrome_WidgetWin_1;.*;;1;0;0;0;1;0;" + Config_rule_#13 := "Chrome_WidgetWin_1;.*;Window_isPopup;0;0;0;1;1;0;" + Config_rule_#14 := "Chrome_RenderWidgetHostHWND;.*;;0;0;0;1;1;0;" + Config_rule_#15 := "IEFrame;.*Internet Explorer;;1;0;0;0;1;0;" + Config_rule_#16 := "MozillaWindowClass;.*Mozilla Firefox;;1;0;0;0;1;0;" + Config_rule_#17 := "MozillaDialogClass;.*;;1;0;0;1;1;0;" + Config_rule_#18 := "ApplicationFrameWindow;.*Edge;;1;0;0;0;1;0;" + Config_ruleCount := 18 ;; This variable has to be set to the total number of active rules above. + + ;; Configuration management + Config_autoSaveSession := "auto" ;; "off" | "auto" | "ask" + Config_maintenanceInterval := 5000 + Config_monitorDisplayChangeMessages := "ask" ;; "off" | "on" | "ask" + + Config_hotkeyCount := 0 + Config_restoreConfig(Config_filePath) + ;If (SubStr(A_OSVersion, 1, 3) = "10.") { + ; Config_borderWidth := 0 + ; Config_borderPadding := -1 + ; Config_showBorder := True + ; Config_selBorderColor := "" + ;} + + Config_getSystemSettings() + Config_initColors() + Config_initBarIcons() + Loop, % Config_layoutCount { + StringSplit, layout, Config_layout_#%A_Index%, `; + Config_layoutFunction_#%A_Index% := layout2 + Config_layoutSymbol_#%A_Index% := layout1 + } + StringSplit, vNames, Config_viewNames, `; + If vNames0 > 9 + Config_viewCount := 9 + Else + Config_viewCount := vNames0 + Loop, % Config_viewCount + Config_viewNames_#%A_Index% := vNames%A_Index% +} + +Config_initColors() { + Global + + Loop, 3 { + StringReplace, Config_backColor_#%A_Index%, Config_backColor_#%A_Index%, `;0`;, `;000000`;, All + Config_backColor_#%A_Index% := RegExReplace(Config_backColor_#%A_Index%, "^0;", "000000;") + Config_backColor_#%A_Index% := RegExReplace(Config_backColor_#%A_Index%, ";0$", ";000000") + StringSplit, Config_backColor_#%A_Index%_#, Config_backColor_#%A_Index%, `; + + StringReplace, Config_foreColor_#%A_Index%, Config_foreColor_#%A_Index%, `;0`;, `;000000`;, All + Config_foreColor_#%A_Index% := RegExReplace(Config_foreColor_#%A_Index%, "^0;", "000000;") + Config_foreColor_#%A_Index% := RegExReplace(Config_foreColor_#%A_Index%, ";0$", ";000000") + StringSplit, Config_foreColor_#%A_Index%_#, Config_foreColor_#%A_Index%, `; + + StringReplace, Config_fontColor_#%A_Index%, Config_fontColor_#%A_Index%, `;0`;, `;000000`;, All + Config_fontColor_#%A_Index% := RegExReplace(Config_fontColor_#%A_Index%, "^0;", "000000;") + Config_fontColor_#%A_Index% := RegExReplace(Config_fontColor_#%A_Index%, ";0$", ";000000") + StringSplit, Config_fontColor_#%A_Index%_#, Config_fontColor_#%A_Index%, `; + } +} + +Config_initBarIcons() { + Global + + StringSplit, Config_barIcon_#, Config_barIcons, `; +} + +Config_convertSystemColor(systemColor) +{ ;; systemColor format: 0xBBGGRR + rr := SubStr(systemColor, 7, 2) + gg := SubStr(systemColor, 5, 2) + bb := SubStr(systemColor, 3, 2) + + Return, rr gg bb +} + +Config_edit() { + Global Config_filePath + + If Not FileExist(Config_filePath) + Config_UI_saveSession() + Run, edit %Config_filePath% +} + +Config_getSystemSettings() { + Global Config_backColor_#1, Config_foreColor_#1, Config_fontColor_#1 + Global Config_backColor_#2, Config_foreColor_#2, Config_fontColor_#2 + Global Config_backColor_#3, Config_foreColor_#3, Config_fontColor_#3 + Global Config_fontName, Config_fontSize, Config_scalingFactor + + If Not Config_fontName { + ncmSize := VarSetCapacity(ncm, 4 * (A_OSVersion = "WIN_VISTA" ? 11 : 10) + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), 0) + NumPut(ncmSize, ncm, 0, "UInt") + DllCall("SystemParametersInfo", "UInt", 0x0029, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) + + VarSetCapacity(lf, 28 + 32 * (A_IsUnicode ? 2 : 1), 0) + DllCall("RtlMoveMemory", "Str", lf, "UInt", &ncm + 24, "UInt", 28 + 32 * (A_IsUnicode ? 2 : 1)) + VarSetCapacity(Config_fontName, 32 * (A_IsUnicode ? 2 : 1), 0) + DllCall("RtlMoveMemory", "Str", Config_fontName, "UInt", &lf + 28, "UInt", 32 * (A_IsUnicode ? 2 : 1)) + ;; maestrith: Script Writer (http://www.autohotkey.net/~maestrith/Script Writer/) + } + If Not Config_fontSize { + ncmSize := VarSetCapacity(ncm, 4 * (A_OSVersion = "WIN_VISTA" ? 11 : 10) + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), 0) + NumPut(ncmSize, ncm, 0, "UInt") + DllCall("SystemParametersInfo", "UInt", 0x0029, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) + + lfSize := VarSetCapacity(lf, 28 + 32 * (A_IsUnicode ? 2 : 1), 0) + NumPut(lfSize, lf, 0, "UInt") + DllCall("RtlMoveMemory", "Str", lf, "UInt", &ncm + 24, "UInt", 28 + 32 * (A_IsUnicode ? 2 : 1)) + + lfHeightSize := VarSetCapacity(lfHeight, 4, 0) + NumPut(lfHeightSize, lfHeight, 0, "Int") + lfHeight := NumGet(lf, 0, "Int") + + lfPixelsY := DllCall("GetDeviceCaps", "UInt", DllCall("GetDC", "UInt", 0), "UInt", 90) ;; LOGPIXELSY + Config_fontSize := -DllCall("MulDiv", "Int", lfHeight, "Int", 72, "Int", lfPixelsY) + ;; maestrith: Script Writer (http://www.autohotkey.net/~maestrith/Script Writer/) + } + SetFormat, Integer, hex + If Not (Config_backColor_#1 And Config_foreColor_#1 And Config_fontColor_#1 + And Config_backColor_#2 And Config_foreColor_#2 And Config_fontColor_#2 + And Config_backColor_#3 And Config_foreColor_#3 And Config_fontColor_#3) { + COLOR_ACTIVECAPTION := Config_convertSystemColor(DllCall("GetSysColor", "Int", 2)) + COLOR_CAPTIONTEXT := Config_convertSystemColor(DllCall("GetSysColor", "Int", 9)) + COLOR_GRADIENTACTIVECAPTION := Config_convertSystemColor(DllCall("GetSysColor", "Int", 27)) + COLOR_GRADIENTINACTIVECAPTION := Config_convertSystemColor(DllCall("GetSysColor", "Int", 28)) + COLOR_HIGHLIGHT := Config_convertSystemColor(DllCall("GetSysColor", "Int", 13)) + COLOR_INACTIVECAPTION := Config_convertSystemColor(DllCall("GetSysColor", "Int", 3)) + COLOR_INACTIVECAPTIONTEXT := Config_convertSystemColor(DllCall("GetSysColor", "Int", 19)) + COLOR_MENU := Config_convertSystemColor(DllCall("GetSysColor", "Int", 4)) + COLOR_MENUTEXT := Config_convertSystemColor(DllCall("GetSysColor", "Int", 7)) + ;; <view>;<layout>;<title>;<shebang>;<time>;<date>;<anyText>;<batteryStatus>;<volumeLevel> + If Not Config_backColor_#1 { + Config_backColor_#1 := COLOR_GRADIENTINACTIVECAPTION ";" COLOR_ACTIVECAPTION ";" COLOR_MENU ";" COLOR_ACTIVECAPTION ";" COLOR_MENU ";" COLOR_ACTIVECAPTION ";" + Config_backColor_#1 .= COLOR_GRADIENTINACTIVECAPTION ";" COLOR_GRADIENTACTIVECAPTION ";" COLOR_GRADIENTACTIVECAPTION + } + If Not Config_backColor_#2 + Config_backColor_#2 := COLOR_GRADIENTACTIVECAPTION ";;;;;;;" COLOR_MENU ";" COLOR_MENU + If Not Config_backColor_#3 + Config_backColor_#3 := ";;;;;;;ff8040;" + + If Not Config_foreColor_#1 { + Config_foreColor_#1 := COLOR_INACTIVECAPTION ";" COLOR_ACTIVECAPTION ";" COLOR_MENU ";" COLOR_ACTIVECAPTION ";" COLOR_MENU ";" COLOR_ACTIVECAPTION ";" + Config_foreColor_#1 .= COLOR_INACTIVECAPTION ";" COLOR_ACTIVECAPTION ";" COLOR_GRADIENTINACTIVECAPTION + } + If Not Config_foreColor_#2 + Config_foreColor_#2 := COLOR_ACTIVECAPTION ";;;;;;;" COLOR_HIGHLIGHT ";" COLOR_HIGHLIGHT + If Not Config_foreColor_#3 + Config_foreColor_#3 := ";;;;;;;" COLOR_INACTIVECAPTION ";" + + If Not Config_fontColor_#1 { + Config_fontColor_#1 := COLOR_INACTIVECAPTIONTEXT ";" COLOR_CAPTIONTEXT ";" COLOR_MENUTEXT ";" COLOR_CAPTIONTEXT ";" COLOR_MENUTEXT ";" COLOR_CAPTIONTEXT ";" + Config_fontColor_#1 .= COLOR_INACTIVECAPTIONTEXT ";" COLOR_CAPTIONTEXT ";" COLOR_INACTIVECAPTIONTEXT + } + If Not Config_fontColor_#2 + Config_fontColor_#2 := COLOR_CAPTIONTEXT ";;;;;;;" COLOR_MENUTEXT ";" COLOR_MENUTEXT + If Not Config_fontColor_#3 + Config_fontColor_#3 := ";;;;;;;" COLOR_INACTIVECAPTIONTEXT ";" + } + SetFormat, Integer, d + + RegRead, appliedDPI, HKEY_CURRENT_USER, Control Panel\Desktop\WindowMetrics, AppliedDPI + If (ErrorLevel = 0) + Config_scalingFactor := 96 / appliedDPI +} + +Config_hotkeyLabel: + Config_redirectHotkey(A_ThisHotkey) +Return + +Config_readinAny() { + ;; Add information to the variable 'text' in this function to display it in the status bar. + Global Config_readinCpu, Config_readinDiskLoad, Config_readinMemoryUsage, Config_readinNetworkLoad + + text := "" + If (Config_readinCpu Or Config_readinDiskLoad Or Config_readinMemoryUsage Or Config_readinNetworkLoad) + text .= ResourceMonitor_getText() + + Return, text +} + +Config_redirectHotkey(key) +{ + Global + + Loop, % Config_hotkeyCount + { + If (key = Config_hotkey_#%A_index%_key) + { + Debug_logMessage("DEBUG[1] Config_redirectHotkey: Found " Config_hotkey_#%A_index%_key " -> " Config_hotkey_#%A_index%_command, 1) + Main_evalCommand(Config_hotkey_#%A_index%_command) + Break + } + } +} + +Config_restoreConfig(filename) +{ + Local cmd, i, key, type, val, var + + If Not FileExist(filename) + Return + + Loop, READ, %filename% + If (SubStr(A_LoopReadLine, 1, 7) = "Config_") + { + ;Log_msg("Processing line: " . A_LoopReadLine) + i := InStr(A_LoopReadLine, "=") + var := SubStr(A_LoopReadLine, 1, i - 1) + val := SubStr(A_LoopReadLine, i + 1) + type := SubStr(var, 1, 13) + If (type = "Config_hotkey") + { + Debug_logMessage("Processing configured hotkey: " . A_LoopReadLine, 0) + i := InStr(val, "::") + key := SubStr(val, 1, i - 1) + cmd := SubStr(val, i + 2) + If Not cmd + Hotkey, %key%, Off + Else + { + Debug_logMessage(" Hotkey: " . key . " -> " . cmd, 0) + Config_hotkeyCount += 1 + Config_hotkey_#%Config_hotkeyCount%_key := key + Config_hotkey_#%Config_hotkeyCount%_command := cmd + Hotkey, %key%, Config_hotkeyLabel + } + } + Else If (type = "Config_rule") + { + i := 0 + If InStr(var, "Config_rule_#") + i := SubStr(var, 14) + If (i = 0 Or i > Config_ruleCount) + { + Config_ruleCount += 1 + i := Config_ruleCount + } + var := "Config_rule_#" i + } + %var% := val + } +} + +Config_restoreLayout(filename, m) { + Local i, var, val + + If Not FileExist(filename) + Return + + Loop, READ, %filename% + If (SubStr(A_LoopReadLine, 1, 10 + StrLen(m)) = "Monitor_#" m "_" Or SubStr(A_LoopReadLine, 1, 8 + StrLen(m)) = "View_#" m "_#") { + i := InStr(A_LoopReadLine, "=") + var := SubStr(A_LoopReadLine, 1, i - 1) + val := SubStr(A_LoopReadLine, i + 1) + %var% := val + } +} + +Config_saveSession(original, target) +{ + Local m, text, tmpfilename + + tmpfilename := target . ".tmp" + FileDelete, %tmpfilename% + + text := "; bug.n - tiling window management`n; @version " VERSION "`n`n" + If FileExist(original) + { + Loop, READ, %original% + { + If (SubStr(A_LoopReadLine, 1, 7) = "Config_") + text .= A_LoopReadLine "`n" + } + text .= "`n" + } + + Loop, % Manager_monitorCount + { + m := A_Index + If Not (Monitor_#%m%_aView_#1 = 1) + text .= "Monitor_#" m "_aView_#1=" Monitor_#%m%_aView_#1 "`n" + If Not (Monitor_#%m%_aView_#2 = 1) + text .= "Monitor_#" m "_aView_#2=" Monitor_#%m%_aView_#2 "`n" + If Not (Monitor_#%m%_showBar = Config_showBar) + text .= "Monitor_#" m "_showBar=" Monitor_#%m%_showBar "`n" + Loop, % Config_viewCount + { + If Not (View_#%m%_#%A_Index%_layout_#1 = 1) + text .= "View_#" m "_#" A_Index "_layout_#1=" View_#%m%_#%A_Index%_layout_#1 "`n" + If Not (View_#%m%_#%A_Index%_layout_#2 = 1) + text .= "View_#" m "_#" A_Index "_layout_#2=" View_#%m%_#%A_Index%_layout_#2 "`n" + If Not (View_#%m%_#%A_Index%_layoutAxis_#1 = Config_layoutAxis_#1) + text .= "View_#" m "_#" A_Index "_layoutAxis_#1=" View_#%m%_#%A_Index%_layoutAxis_#1 "`n" + If Not (View_#%m%_#%A_Index%_layoutAxis_#2 = Config_layoutAxis_#2) + text .= "View_#" m "_#" A_Index "_layoutAxis_#2=" View_#%m%_#%A_Index%_layoutAxis_#2 "`n" + If Not (View_#%m%_#%A_Index%_layoutAxis_#3 = Config_layoutAxis_#3) + text .= "View_#" m "_#" A_Index "_layoutAxis_#3=" View_#%m%_#%A_Index%_layoutAxis_#3 "`n" + If Not (View_#%m%_#%A_Index%_layoutGapWidth = Config_layoutGapWidth) + text .= "View_#" m "_#" A_Index "_layoutGapWidth=" View_#%m%_#%A_Index%_layoutGapWidth "`n" + If Not (View_#%m%_#%A_Index%_layoutMFact = Config_layoutMFactor) + text .= "View_#" m "_#" A_Index "_layoutMFact=" View_#%m%_#%A_Index%_layoutMFact "`n" + If Not (View_#%m%_#%A_Index%_layoutMX = 1) + text .= "View_#" m "_#" A_Index "_layoutMX=" View_#%m%_#%A_Index%_layoutMX "`n" + If Not (View_#%m%_#%A_Index%_layoutMY = 1) + text .= "View_#" m "_#" A_Index "_layoutMY=" View_#%m%_#%A_Index%_layoutMY "`n" + } + } + + ;; The FileMove below is an all-or-nothing replacement of the file. + ;; We don't want to leave this half-finished. + FileAppend, %text%, %tmpfilename% + If ErrorLevel And Not (original = Config_filePath And target = Config_filePath And Not FileExist(original)) { + If FileExist(tmpfilename) + FileDelete, %tmpfilename% + } Else + FileMove, %tmpfilename%, %target%, 1 +} + +Config_UI_saveSession() { + Global Config_filePath + + Config_saveSession(Config_filePath, Config_filePath) +} + +#MaxHotkeysPerInterval 200 + +;; Key definitions +;; Window management +#Down::View_activateWindow(0, +1) +#Up::View_activateWindow(0, -1) +#+Down::View_shuffleWindow(0, +1) +#+Up::View_shuffleWindow(0, -1) +#+Enter::View_shuffleWindow(1) +#c::Manager_closeWindow() +#+d::Window_toggleDecor() +#+f::View_toggleFloatingWindow() +#+m::Manager_moveWindow() +#^m::Manager_minimizeWindow() +#+s::Manager_sizeWindow() +#+x::Manager_maximizeWindow() +#i::Manager_getWindowInfo() +#+i::Manager_getWindowList() +!Down::View_moveWindow(0, +1) +!Up::View_moveWindow(0, -1) +!+Enter::Manager_maximizeWindow() +!1::View_moveWindow(1) +!2::View_moveWindow(2) +!3::View_moveWindow(3) +!4::View_moveWindow(4) +!5::View_moveWindow(5) +!6::View_moveWindow(6) +!7::View_moveWindow(7) +!8::View_moveWindow(8) +!9::View_moveWindow(9) +!0::View_moveWindow(10) +!BackSpace::View_toggleStackArea() + +;; Window debugging +#^i::Debug_logViewWindowList() +#^+i::Debug_logManagedWindowList() +#^h::Debug_logHelp() +#^d::Debug_setLogLevel(0, -1) +#^+d::Debug_setLogLevel(0, +1) + +;; Layout management +#Tab::View_setLayout(-1) +#f::View_setLayout(3) +#m::View_setLayout(2) +#t::View_setLayout(1) +#Left::View_setLayoutProperty("MFactor", 0, -0.05) +#Right::View_setLayoutProperty("MFactor", 0, +0.05) +#^t::View_setLayoutProperty("Axis", 0, +1, 1) +#^Enter::View_setLayoutProperty("Axis", 0, +2, 1) +#^Tab::View_setLayoutProperty("Axis", 0, +1, 2) +#^+Tab::View_setLayoutProperty("Axis", 0, +1, 3) +#^Up::View_setLayoutProperty("MY", 0, +1) +#^Down::View_setLayoutProperty("MY", 0, -1) +#^Right::View_setLayoutProperty("MX", 0, +1) +#^Left::View_setLayoutProperty("MX", 0, -1) +#+Left::View_setLayoutProperty("GapWidth", 0, -2) +#+Right::View_setLayoutProperty("GapWidth", 0, +2) +#^Backspace::View_resetTileLayout() + +;; View/Tag management +#+n::View_toggleMargins() +#BackSpace::Monitor_activateView(-1) +#+0::Monitor_setWindowTag(10) +#1::Monitor_activateView(1) +#+1::Monitor_setWindowTag(1) +#^1::Monitor_toggleWindowTag(1) +#2::Monitor_activateView(2) +#+2::Monitor_setWindowTag(2) +#^2::Monitor_toggleWindowTag(2) +#3::Monitor_activateView(3) +#+3::Monitor_setWindowTag(3) +#^3::Monitor_toggleWindowTag(3) +#4::Monitor_activateView(4) +#+4::Monitor_setWindowTag(4) +#^4::Monitor_toggleWindowTag(4) +#5::Monitor_activateView(5) +#+5::Monitor_setWindowTag(5) +#^5::Monitor_toggleWindowTag(5) +#6::Monitor_activateView(6) +#+6::Monitor_setWindowTag(6) +#^6::Monitor_toggleWindowTag(6) +#7::Monitor_activateView(7) +#+7::Monitor_setWindowTag(7) +#^7::Monitor_toggleWindowTag(7) +#8::Monitor_activateView(8) +#+8::Monitor_setWindowTag(8) +#^8::Monitor_toggleWindowTag(8) +#9::Monitor_activateView(9) +#+9::Monitor_setWindowTag(9) +#^9::Monitor_toggleWindowTag(9) +~WheelUp::Manager_activateViewByMouse(-1) +~WheelDown::Manager_activateViewByMouse(+1) + +;; Monitor management +#.::Manager_activateMonitor(0, +1) +#,::Manager_activateMonitor(0, -1) +#+.::Manager_setWindowMonitor(0, +1) +#+,::Manager_setWindowMonitor(0, -1) +#^+.::Manager_setViewMonitor(0, +1) +#^+,::Manager_setViewMonitor(0, -1) + +;; GUI management +#+Space::Monitor_toggleBar() +#Space::Monitor_toggleTaskBar() +#y::Bar_toggleCommandGui() +#+y::Monitor_toggleNotifyIconOverflowWindow() +!+y::View_traceAreas() + +;; Administration +#^e::Config_edit() +#^s::Config_UI_saveSession() +#^r::Reload +#^q::ExitApp diff --git a/src/Debug.ahk b/src/Debug.ahk index e010103..083108b 100644 --- a/src/Debug.ahk +++ b/src/Debug.ahk @@ -1,162 +1,162 @@ -/* - bug.n -- tiling window management - Copyright (c) 2010-2019 Joshua Fuhs, joten - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - @license GNU General Public License version 3 - ../LICENSE.md or <http://www.gnu.org/licenses/> - - @version 9.1.0 -*/ - -Debug_initLog(filename, level = 0, truncateFile = True) -{ - Global Debug_logFilename, Debug_logLevel - - Debug_logFilename := filename - Debug_logLevel := level - If truncateFile - If FileExist(Debug_logFilename) - FileDelete, %Debug_logFilename% -} - -Debug_logHelp() -{ - Debug_logMessage("Help Display", 0) - Debug_logMessage("Window list columns", 0, False) - Debug_logMessage(" ID - Windows ID. Unique, OS-assigned ID", 0, False) - Debug_logMessage(" H - Hidden. Whether bug.n thinks this window is hidden.", 0, False) - Debug_logMessage(" W - Windows active. This window is active according to Windows.", 0, False) - Debug_logMessage(" A - View active. This window is active according to bug.n.", 0, False) - Debug_logMessage(" F - Floating. This window should not be positioned and resized by the layout.", 0, False) - Debug_logMessage(" D - Decorated. Does the window have a title bar?", 0, False) - Debug_logMessage(" R - Responsive. Is responding to messages?", 0, False) - Debug_logMessage(" G - Ghost. Is this window a ghost of another hung window?", 0, False) - Debug_logMessage(" M - Monitor number.", 0, False) - Debug_logMessage(" Tags - Bit-mask of the views in which the window is active.", 0, False) - Debug_logMessage(" X - Windows X position.", 0, False) - Debug_logMessage(" Y - Windows Y position.", 0, False) - Debug_logMessage(" W - Windows width.", 0, False) - Debug_logMessage(" H - Windows height.", 0, False) - Debug_logMessage(" Style - Windows style.", 0, False) - Debug_logMessage(" Proc / Class / Title - Process/Class/Title of the window.", 0, False) -} - -Debug_logManagedWindowList() -{ - Local wndIds - - Debug_logMessage("Window dump for manager") - Debug_logMessage("ID`t`tH W A F D R G M`tTags`tX`tY`tW`tH`tStyle`t`tProc / Class / Title", 0, False) - - StringTrimRight, wndIds, Manager_managedWndIds, 1 - Loop, PARSE, wndIds, `; - { - Debug_logWindowInfo(A_LoopField) - } -} - -Debug_logMessage(text, level = 1, includeTimestamp = True) -{ - Global Debug_logFilename, Debug_logLevel - - If (Debug_logLevel >= level) - { - If includeTimestamp - { - FormatTime, time, , yyyy-MM-dd HH:mm:ss - text := time " " text - } - Else - text := " " text - FileAppend, %text%`r`n, %Debug_logFilename% - } -} - -Debug_logViewWindowList() -{ - Local v, wndIds - - v := Monitor_#%Manager_aMonitor%_aView_#1 - Debug_logMessage("Window dump for active view (" . Manager_aMonitor . ", " . v . ")") - Debug_logMessage("ID`t`tH W A F D R G M`tTags`tX`tY`tW`tH`tStyle`t`tProc / Class / Title", 0, False) - - StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 - Loop, PARSE, wndIds, `; - { - Debug_logWindowInfo(A_LoopField) - } -} - -Debug_logWindowInfo(wndId) { - Local aWndId, detectHidden, text, v - Local isBugnActive, isDecorated, isFloating, isGhost, isHidden, isResponsive, isWinFocus - Local wndClass, wndH, wndPId, wndPName, wndStyle, wndTitle, wndW, wndX, wndY - - detectHidden := A_DetectHiddenWindows - DetectHiddenWindows, On - WinGet, aWndId, ID, A - If aWndId = %wndId% - isWinFocus := "*" - Else - isWinFocus := " " - v := Monitor_#%Manager_aMonitor%_aView_#1 - If (View_getActiveWindow(Manager_aMonitor, v) = wndId) - isBugnActive := "*" - Else - isBugnActive := " " - WinGetTitle, wndTitle, ahk_id %wndId% - WinGetClass, wndClass, ahk_id %wndId% - WinGet, wndPName, ProcessName, ahk_id %wndId% - WinGet, wndPId, PID, ahk_id %wndId% - If InStr(Bar_hideTitleWndIds, wndId . ";") - isHidden := "*" - Else - isHidden := " " - If InStr(Manager_managedWndIds, wndId . ";") Or Window_#%wndId%_isFloating - isFloating := "*" - Else - isFloating := " " - If Window_#%wndId%_isDecorated - isDecorated := "*" - Else - isDecorated := " " - WinGet, wndStyle, Style, ahk_id %wndId% - WinGetPos, wndX, wndY, wndW, wndH, ahk_id %wndId% - If Window_isGhost(wndId) - isGhost := "*" - Else - isGhost := " " - DetectHiddenWindows, %detectHidden% - - ;; Intentionally don't detect hidden windows here to see what Manager_hungTest does - If Window_isHung(wndId) - isResponsive := " " - Else - isResponsive := "*" - - text := wndId "`t" - text .= isHidden " " isWinFocus " " isBugnActive " " isFloating " " isDecorated " " isResponsive " " isGhost " " - text .= Window_#%wndId%_monitor "`t" Window_#%wndId%_tags "`t" - text .= wndX "`t" wndY "`t" wndW "`t" wndH "`t" wndStyle "`t" wndPName " [" wndPId "] / " wndClass " / " wndTitle - Debug_logMessage(text , 0, False) -} - -Debug_setLogLevel(i, d) { - Global Debug_logLevel - - If (i = 0) - i := Debug_logLevel - i += d - If (i >= 0) And (i != Debug_logLevel) { - Debug_logLevel := i - If (i = 0) - Debug_logMessage("Logging disabled.", 0) - Else - Debug_logMessage("Log level set to " i ".") - } -} +/* + bug.n -- tiling window management + Copyright (c) 2010-2019 Joshua Fuhs, joten + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + @license GNU General Public License version 3 + ../LICENSE.md or <http://www.gnu.org/licenses/> + + @version 9.1.0 +*/ + +Debug_initLog(filename, level = 0, truncateFile = True) +{ + Global Debug_logFilename, Debug_logLevel + + Debug_logFilename := filename + Debug_logLevel := level + If truncateFile + If FileExist(Debug_logFilename) + FileDelete, %Debug_logFilename% +} + +Debug_logHelp() +{ + Debug_logMessage("Help Display", 0) + Debug_logMessage("Window list columns", 0, False) + Debug_logMessage(" ID - Windows ID. Unique, OS-assigned ID", 0, False) + Debug_logMessage(" H - Hidden. Whether bug.n thinks this window is hidden.", 0, False) + Debug_logMessage(" W - Windows active. This window is active according to Windows.", 0, False) + Debug_logMessage(" A - View active. This window is active according to bug.n.", 0, False) + Debug_logMessage(" F - Floating. This window should not be positioned and resized by the layout.", 0, False) + Debug_logMessage(" D - Decorated. Does the window have a title bar?", 0, False) + Debug_logMessage(" R - Responsive. Is responding to messages?", 0, False) + Debug_logMessage(" G - Ghost. Is this window a ghost of another hung window?", 0, False) + Debug_logMessage(" M - Monitor number.", 0, False) + Debug_logMessage(" Tags - Bit-mask of the views in which the window is active.", 0, False) + Debug_logMessage(" X - Windows X position.", 0, False) + Debug_logMessage(" Y - Windows Y position.", 0, False) + Debug_logMessage(" W - Windows width.", 0, False) + Debug_logMessage(" H - Windows height.", 0, False) + Debug_logMessage(" Style - Windows style.", 0, False) + Debug_logMessage(" Proc / Class / Title - Process/Class/Title of the window.", 0, False) +} + +Debug_logManagedWindowList() +{ + Local wndIds + + Debug_logMessage("Window dump for manager") + Debug_logMessage("ID`t`tH W A F D R G M`tTags`tX`tY`tW`tH`tStyle`t`tProc / Class / Title", 0, False) + + StringTrimRight, wndIds, Manager_managedWndIds, 1 + Loop, PARSE, wndIds, `; + { + Debug_logWindowInfo(A_LoopField) + } +} + +Debug_logMessage(text, level = 1, includeTimestamp = True) +{ + Global Debug_logFilename, Debug_logLevel + + If (Debug_logLevel >= level) + { + If includeTimestamp + { + FormatTime, time, , yyyy-MM-dd HH:mm:ss + text := time " " text + } + Else + text := " " text + FileAppend, %text%`r`n, %Debug_logFilename% + } +} + +Debug_logViewWindowList() +{ + Local v, wndIds + + v := Monitor_#%Manager_aMonitor%_aView_#1 + Debug_logMessage("Window dump for active view (" . Manager_aMonitor . ", " . v . ")") + Debug_logMessage("ID`t`tH W A F D R G M`tTags`tX`tY`tW`tH`tStyle`t`tProc / Class / Title", 0, False) + + StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 + Loop, PARSE, wndIds, `; + { + Debug_logWindowInfo(A_LoopField) + } +} + +Debug_logWindowInfo(wndId) { + Local aWndId, detectHidden, text, v + Local isBugnActive, isDecorated, isFloating, isGhost, isHidden, isResponsive, isWinFocus + Local wndClass, wndH, wndPId, wndPName, wndStyle, wndTitle, wndW, wndX, wndY + + detectHidden := A_DetectHiddenWindows + DetectHiddenWindows, On + WinGet, aWndId, ID, A + If aWndId = %wndId% + isWinFocus := "*" + Else + isWinFocus := " " + v := Monitor_#%Manager_aMonitor%_aView_#1 + If (View_getActiveWindow(Manager_aMonitor, v) = wndId) + isBugnActive := "*" + Else + isBugnActive := " " + WinGetTitle, wndTitle, ahk_id %wndId% + WinGetClass, wndClass, ahk_id %wndId% + WinGet, wndPName, ProcessName, ahk_id %wndId% + WinGet, wndPId, PID, ahk_id %wndId% + If InStr(Bar_hideTitleWndIds, wndId . ";") + isHidden := "*" + Else + isHidden := " " + If InStr(Manager_managedWndIds, wndId . ";") Or Window_#%wndId%_isFloating + isFloating := "*" + Else + isFloating := " " + If Window_#%wndId%_isDecorated + isDecorated := "*" + Else + isDecorated := " " + WinGet, wndStyle, Style, ahk_id %wndId% + WinGetPos, wndX, wndY, wndW, wndH, ahk_id %wndId% + If Window_isGhost(wndId) + isGhost := "*" + Else + isGhost := " " + DetectHiddenWindows, %detectHidden% + + ;; Intentionally don't detect hidden windows here to see what Manager_hungTest does + If Window_isHung(wndId) + isResponsive := " " + Else + isResponsive := "*" + + text := wndId "`t" + text .= isHidden " " isWinFocus " " isBugnActive " " isFloating " " isDecorated " " isResponsive " " isGhost " " + text .= Window_#%wndId%_monitor "`t" Window_#%wndId%_tags "`t" + text .= wndX "`t" wndY "`t" wndW "`t" wndH "`t" wndStyle "`t" wndPName " [" wndPId "] / " wndClass " / " wndTitle + Debug_logMessage(text , 0, False) +} + +Debug_setLogLevel(i, d) { + Global Debug_logLevel + + If (i = 0) + i := Debug_logLevel + i += d + If (i >= 0) And (i != Debug_logLevel) { + Debug_logLevel := i + If (i = 0) + Debug_logMessage("Logging disabled.", 0) + Else + Debug_logMessage("Log level set to " i ".") + } +} diff --git a/src/Main.ahk b/src/Main.ahk index 8034bc1..1269454 100644 --- a/src/Main.ahk +++ b/src/Main.ahk @@ -1,195 +1,195 @@ -/* - bug.n -- tiling window management - Copyright (c) 2010-2019 Joshua Fuhs, joten - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - @license GNU General Public License version 3 - ../LICENSE.md or <http://www.gnu.org/licenses/> - - @version 9.1.0 -*/ - -NAME := "bug.n" -VERSION := "9.1.0" - -;; Script settings -OnExit, Main_cleanup -SetBatchLines, -1 -SetTitleMatchMode, 3 -SetTitleMatchMode, fast -SetWinDelay, 10 -#NoEnv -#SingleInstance force -;#Warn ; Enable warnings to assist with detecting common errors. -#WinActivateForce - -;; Pseudo main function - Main_appDir := "" - If 0 = 1 - Main_appDir = %1% - - Main_setup() - - Debug_initLog(Main_logFile, 0, False) - - Debug_logMessage("====== Initializing ======", 0) - Config_filePath := Main_appDir "\Config.ini" - Config_init() - - Menu, Tray, Tip, %NAME% %VERSION% - If A_IsCompiled - Menu, Tray, Icon, %A_ScriptFullPath%, -159 - If FileExist(A_ScriptDir . "\logo.ico") - Menu, Tray, Icon, % A_ScriptDir . "\logo.ico" - Menu, Tray, NoStandard - Menu, Tray, Add, Toggle bar, Main_toggleBar - Menu, Tray, Add, Help, Main_help - Menu, Tray, Add, - Menu, Tray, Add, Exit, Main_quit - - ResourceMonitor_init() - Manager_init() - Debug_logMessage("====== Running ======", 0) -Return ;; end of the auto-execute section - -;; Function & label definitions -Main_cleanup: - Debug_logMessage("====== Cleaning up ======", 0) - ;; Config_autoSaveSession as False is deprecated. - If Not (Config_autoSaveSession = "off") And Not (Config_autoSaveSession = "False") - Manager_saveState() - Manager_cleanup() - ResourceMonitor_cleanup() - Debug_logMessage("====== Exiting bug.n ======", 0) -ExitApp - -Main_evalCommand(command) -{ - type := SubStr(command, 1, 5) - If (type = "Run, ") - { - parameters := SubStr(command, 6) - If InStr(parameters, ", ") - { - StringSplit, parameter, parameters, `, - If (parameter0 = 2) - { - StringTrimLeft, parameter2, parameter2, 1 - Run, %parameter1%, %parameter2% - } - Else If (parameter0 > 2) - { - StringTrimLeft, parameter2, parameter2, 1 - StringTrimLeft, parameter3, parameter3, 1 - Run, %parameter1%, %parameter2%, %parameter3% - } - } - Else - Run, %parameters% - } - Else If (type = "Send ") - Send % SubStr(command, 6) - Else If (command = "Reload") - Reload - Else If (command = "ExitApp") - ExitApp - Else - { - i := InStr(command, "(") - j := InStr(command, ")", False, i) - If i And j - { - functionName := SubStr(command, 1, i - 1) - functionArguments := SubStr(command, i + 1, j - (i + 1)) - StringReplace, functionArguments, functionArguments, %A_SPACE%, , All - StringSplit, functionArgument, functionArguments, `, - Debug_logMessage("DEBUG[1] Main_evalCommand: " functionName "(" functionArguments ")", 1) - If (functionArgument0 = 0) - %functionName%() - Else If (functionArgument0 = 1) - %functionName%(functionArguments) - Else If (functionArgument0 = 2) - %functionName%(functionArgument1, functionArgument2) - Else If (functionArgument0 = 3) - %functionName%(functionArgument1, functionArgument2, functionArgument3) - Else If (functionArgument0 = 4) - %functionName%(functionArgument1, functionArgument2, functionArgument3, functionArgument4) - } - } -} - -Main_help: - Run, explore %Main_docDir% -Return - -;; Create bug.n-specific directories. -Main_makeDir(dirName) { - IfNotExist, %dirName% - { - FileCreateDir, %dirName% - If ErrorLevel - { - MsgBox, Error (%ErrorLevel%) when creating '%dirName%'. Aborting. - ExitApp - } - } - Else - { - FileGetAttrib, attrib, %dirName% - IfNotInString, attrib, D - { - MsgBox, The file path '%dirName%' already exists and is not a directory. Aborting. - ExitApp - } - } -} - -Main_quit: - ExitApp -Return - -Main_setup() { - Local winAppDir - - Main_docDir := A_ScriptDir - If (SubStr(A_ScriptDir, -3) = "\src") - Main_docDir .= "\.." - Main_docDir .= "\doc" - - Main_logFile := "" - Main_dataDir := "" - Main_autoLayout := "" - Main_autoWindowState := "" - - EnvGet, winAppDir, APPDATA - - If (Main_appDir = "") - Main_appDir := winAppDir . "\bug.n" - Main_logFile := Main_appDir . "\log.txt" - Main_dataDir := Main_appDir . "\data" - Main_autoLayout := Main_dataDir . "\_Layout.ini" - Main_autoWindowState := Main_dataDir . "\_WindowState.ini" - - Main_makeDir(Main_appDir) - Main_makeDir(Main_dataDir) -} - -Main_toggleBar: - Monitor_toggleBar() -Return - -#Include Bar.ahk -#Include Config.ahk -#Include Debug.ahk -#Include Manager.ahk -#Include Monitor.ahk -#Include ResourceMonitor.ahk -#Include Tiler.ahk -#Include View.ahk -#Include Window.ahk -#Include MonitorManager.ahk -#Include MusicBee.ahk +/* + bug.n -- tiling window management + Copyright (c) 2010-2019 Joshua Fuhs, joten + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + @license GNU General Public License version 3 + ../LICENSE.md or <http://www.gnu.org/licenses/> + + @version 9.1.0 +*/ + +NAME := "bug.n" +VERSION := "9.1.0" + +;; Script settings +OnExit, Main_cleanup +SetBatchLines, -1 +SetTitleMatchMode, 3 +SetTitleMatchMode, fast +SetWinDelay, 10 +#NoEnv +#SingleInstance force +;#Warn ; Enable warnings to assist with detecting common errors. +#WinActivateForce + +;; Pseudo main function + Main_appDir := "" + If 0 = 1 + Main_appDir = %1% + + Main_setup() + + Debug_initLog(Main_logFile, 0, False) + + Debug_logMessage("====== Initializing ======", 0) + Config_filePath := Main_appDir "\Config.ini" + Config_init() + + Menu, Tray, Tip, %NAME% %VERSION% + If A_IsCompiled + Menu, Tray, Icon, %A_ScriptFullPath%, -159 + If FileExist(A_ScriptDir . "\logo.ico") + Menu, Tray, Icon, % A_ScriptDir . "\logo.ico" + Menu, Tray, NoStandard + Menu, Tray, Add, Toggle bar, Main_toggleBar + Menu, Tray, Add, Help, Main_help + Menu, Tray, Add, + Menu, Tray, Add, Exit, Main_quit + + ResourceMonitor_init() + Manager_init() + Debug_logMessage("====== Running ======", 0) +Return ;; end of the auto-execute section + +;; Function & label definitions +Main_cleanup: + Debug_logMessage("====== Cleaning up ======", 0) + ;; Config_autoSaveSession as False is deprecated. + If Not (Config_autoSaveSession = "off") And Not (Config_autoSaveSession = "False") + Manager_saveState() + Manager_cleanup() + ResourceMonitor_cleanup() + Debug_logMessage("====== Exiting bug.n ======", 0) +ExitApp + +Main_evalCommand(command) +{ + type := SubStr(command, 1, 5) + If (type = "Run, ") + { + parameters := SubStr(command, 6) + If InStr(parameters, ", ") + { + StringSplit, parameter, parameters, `, + If (parameter0 = 2) + { + StringTrimLeft, parameter2, parameter2, 1 + Run, %parameter1%, %parameter2% + } + Else If (parameter0 > 2) + { + StringTrimLeft, parameter2, parameter2, 1 + StringTrimLeft, parameter3, parameter3, 1 + Run, %parameter1%, %parameter2%, %parameter3% + } + } + Else + Run, %parameters% + } + Else If (type = "Send ") + Send % SubStr(command, 6) + Else If (command = "Reload") + Reload + Else If (command = "ExitApp") + ExitApp + Else + { + i := InStr(command, "(") + j := InStr(command, ")", False, i) + If i And j + { + functionName := SubStr(command, 1, i - 1) + functionArguments := SubStr(command, i + 1, j - (i + 1)) + StringReplace, functionArguments, functionArguments, %A_SPACE%, , All + StringSplit, functionArgument, functionArguments, `, + Debug_logMessage("DEBUG[1] Main_evalCommand: " functionName "(" functionArguments ")", 1) + If (functionArgument0 = 0) + %functionName%() + Else If (functionArgument0 = 1) + %functionName%(functionArguments) + Else If (functionArgument0 = 2) + %functionName%(functionArgument1, functionArgument2) + Else If (functionArgument0 = 3) + %functionName%(functionArgument1, functionArgument2, functionArgument3) + Else If (functionArgument0 = 4) + %functionName%(functionArgument1, functionArgument2, functionArgument3, functionArgument4) + } + } +} + +Main_help: + Run, explore %Main_docDir% +Return + +;; Create bug.n-specific directories. +Main_makeDir(dirName) { + IfNotExist, %dirName% + { + FileCreateDir, %dirName% + If ErrorLevel + { + MsgBox, Error (%ErrorLevel%) when creating '%dirName%'. Aborting. + ExitApp + } + } + Else + { + FileGetAttrib, attrib, %dirName% + IfNotInString, attrib, D + { + MsgBox, The file path '%dirName%' already exists and is not a directory. Aborting. + ExitApp + } + } +} + +Main_quit: + ExitApp +Return + +Main_setup() { + Local winAppDir + + Main_docDir := A_ScriptDir + If (SubStr(A_ScriptDir, -3) = "\src") + Main_docDir .= "\.." + Main_docDir .= "\doc" + + Main_logFile := "" + Main_dataDir := "" + Main_autoLayout := "" + Main_autoWindowState := "" + + EnvGet, winAppDir, APPDATA + + If (Main_appDir = "") + Main_appDir := winAppDir . "\bug.n" + Main_logFile := Main_appDir . "\log.txt" + Main_dataDir := Main_appDir . "\data" + Main_autoLayout := Main_dataDir . "\_Layout.ini" + Main_autoWindowState := Main_dataDir . "\_WindowState.ini" + + Main_makeDir(Main_appDir) + Main_makeDir(Main_dataDir) +} + +Main_toggleBar: + Monitor_toggleBar() +Return + +#Include Bar.ahk +#Include Config.ahk +#Include Debug.ahk +#Include Manager.ahk +#Include Monitor.ahk +#Include ResourceMonitor.ahk +#Include Tiler.ahk +#Include View.ahk +#Include Window.ahk +#Include MonitorManager.ahk +#Include MusicBee.ahk diff --git a/src/Manager.ahk b/src/Manager.ahk index 76a8f38..e2d6570 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -1,1252 +1,1280 @@ -/* - bug.n -- tiling window management - Copyright (c) 2010-2019 Joshua Fuhs, joten - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - @license GNU General Public License version 3 - ../LICENSE.md or <http://www.gnu.org/licenses/> - - @version 9.1.0 -*/ - -Manager_init() -{ - Local doRestore - - Manager_setWindowBorders() - Bar_getHeight() - ; axes, dimensions, percentage, flipped, gapWidth - Manager_layoutDirty := 0 - ; New/closed windows, active changed, - Manager_windowsDirty := 0 - Manager_aMonitor := 1 - View_tiledWndId0 := 0 - - doRestore := 0 - If (Config_autoSaveSession = "ask") - { - MsgBox, 0x4, , Would you like to restore an auto-saved session? - IfMsgBox Yes - doRestore := 1 - } - Else If (Config_autoSaveSession = "auto") - { - doRestore := 1 - } - - mmngr1 := New MonitorManager() - mmngr2 := "" - SysGet, Manager_monitorCount, MonitorCount - Debug_logMessage("DEBUG[0] Manager_init: Found " . Manager_monitorCount . " monitor" . (Manager_monitorCount != 1 ? "s" . "") . ".", 0) - Loop, % Manager_monitorCount - { - Sleep, % Config_shellMsgDelay - Monitor_init(A_Index, doRestore) - Debug_logMessage("DEBUG[6] MonitorW: " . Monitor_#%A_Index%_width . ", MMW1: " . mmngr1.monitors[A_Index].width . ", MM1dpiX: " . mmngr1.monitors[A_Index].dpiX . ", MM1scaleX: " . mmngr1.monitors[A_Index].scaleX, 6) - } - Bar_initCmdGui() - - Manager_hideShow := False - Bar_hideTitleWndIds := "" - Manager_allWndIds := "" - Manager_managedWndIds := "" - Manager_initial_sync(doRestore) - - Bar_updateStatus() - Bar_updateTitle() - Loop, % Manager_monitorCount - { - View_arrange(A_Index, Monitor_#%A_Index%_aView_#1) - Bar_updateView(A_Index, Monitor_#%A_Index%_aView_#1) - } - - Manager_registerShellHook() - SetTimer, Manager_doMaintenance, %Config_maintenanceInterval% - SetTimer, Bar_loop, %Config_readinInterval% -} - -Manager_activateMonitor(i, d = 0) { - Local aView, aWndHeight, aWndId, aWndWidth, aWndX, aWndY, v, wndId - - If (Manager_monitorCount > 1) { - aView := Monitor_#%Manager_aMonitor%_aView_#1 - WinGet, aWndId, ID, A - If WinExist("ahk_id" aWndId) And InStr(View_#%Manager_aMonitor%_#%aView%_wndIds, aWndId ";") And Window_isProg(aWndId) { - WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %aWndId% - If (Monitor_get(aWndX + aWndWidth / 2, aWndY + aWndHeight / 2) = Manager_aMonitor) - View_setActiveWindow(Manager_aMonitor, aView, aWndId) - } - - ;; Manually set the active monitor. - If (i = 0) - i := Manager_aMonitor - Manager_aMonitor := Manager_loop(i, d, 1, Manager_monitorCount) - v := Monitor_#%Manager_aMonitor%_aView_#1 - wndId := View_getActiveWindow(Manager_aMonitor, v) - Debug_logMessage("DEBUG[1] Manager_activateMonitor: Manager_aMonitor: " Manager_aMonitor ", i: " i ", d: " d ", wndId: " wndId, 1) - Manager_winActivate(wndId) - } -} - -Manager_applyRules(wndId, ByRef isManaged, ByRef m, ByRef tags, ByRef isFloating, ByRef isDecorated, ByRef hideTitle, ByRef action) { - Local i, wndClass, wndTitle - Local rule0, rule1, rule2, rule3, rule4, rule5, rule6, rule7, rule8, rule9, rule10 - - isManaged := True - m := 0 - tags := 0 - isFloating := False - isDecorated := False - hideTitle := False - action := "" - - WinGetClass, wndClass, ahk_id %wndId% - WinGetTitle, wndTitle, ahk_id %wndId% - If (wndClass Or wndTitle) { - Loop, % Config_ruleCount { - ;; The rules are traversed in reverse order. - i := Config_ruleCount - A_Index + 1 - StringSplit, rule, Config_rule_#%i%, `; - If RegExMatch(wndClass . ";" . wndTitle, rule1 . ";" . rule2) And (rule3 = "" Or %rule3%(wndId)) { - isManaged := rule4 - m := rule5 - tags := rule6 - isFloating := rule7 - isDecorated := rule8 - hideTitle := rule9 - action := rule10 - ;; The first matching rule is returned, i. e. the last in the original rder of Config_rule. - Break - } - } - Debug_logMessage("DEBUG[1] Manager_applyRules: class: " wndClass ", title: " wndTitle ", wndId: " wndId ", rule #: " i, 1) - } Else { - isManaged := False - If wndTitle - hideTitle := True - } -} - -Manager_cleanup() -{ - Local aWndId, m, ncmSize, ncm, wndIds - - WinGet, aWndId, ID, A - - Manager_restoreWindowBorders() - - ;; Show borders and title bars. - StringTrimRight, wndIds, Manager_managedWndIds, 1 - Manager_hideShow := True - Loop, PARSE, wndIds, `; - { - Window_show(A_LoopField) - If Not Config_showBorder - Window_set(A_LoopField, "Style", "+0x40000") - Window_set(A_LoopField, "Style", "+0xC00000") - } - - ;; Show the task bar. - WinShow, Start ahk_class Button - WinShow, ahk_class Shell_TrayWnd - Manager_hideShow := False - - ;; Restore window positions and sizes. - Loop, % Manager_monitorCount - { - m := A_Index - Monitor_#%m%_showBar := False - Monitor_#%m%_showTaskBar := True - Monitor_getWorkArea(m) - Loop, % Config_viewCount - { - View_arrange(m, A_Index, True) - } - } - Window_set(aWndId, "AlwaysOnTop", "On") - Window_set(aWndId, "AlwaysOnTop", "Off") - - DllCall("Shell32.dll\SHAppBarMessage", "UInt", (ABM_REMOVE := 0x1), "UInt", &Bar_appBarData) - ;; SKAN: Crazy Scripting : Quick Launcher for Portable Apps (http://www.autohotkey.com/forum/topic22398.html) -} - -Manager_closeWindow() { - Local aWndId - - WinGet, aWndId, ID, A - If Window_isProg(aWndId) - Window_close(aWndId) -} - -; Asynchronous management of various WM properties. -; We want to make sure that we can recover the layout and windows in the event of -; unexpected problems. -; Periodically check for changes to these things and save them somewhere (not over -; user-defined files). -Manager_doMaintenance: - Critical - - ;; @TODO: Manager_sync? - If Not (Config_autoSaveSession = "off") And Not (Config_autoSaveSession = "False") - Manager_saveState() -Return - -Manager_getWindowInfo() { - Local aWndClass, aWndHeight, aWndId, aWndPId, aWndPName, aWndStyle, aWndTitle, aWndWidth, aWndX, aWndY, detectHiddenWnds, isHidden, text, v - - detectHiddenWnds := A_DetectHiddenWindows - DetectHiddenWindows, On - WinGet, aWndId, ID, A - DetectHiddenWindows, %detectHiddenWnds% - isHidden := Window_getHidden(aWndId, aWndClass, aWndTitle) - WinGet, aWndPName, ProcessName, ahk_id %aWndId% - WinGet, aWndPId, PID, ahk_id %aWndId% - WinGet, aWndStyle, Style, ahk_id %aWndId% - WinGet, aWndMinMax, MinMax, ahk_id %aWndId% - WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %aWndId% - text := "ID: " aWndId (isHidden ? " [hidden]" : "") "`nclass:`t" aWndClass "`ntitle:`t" aWndTitle - If InStr(Bar_hideTitleWndIds, aWndId ";") - text .= " [hidden]" - text .= "`nprocess:`t" aWndPName " [" aWndPId "]`nstyle:`t" aWndStyle "`nmetrics:`tx: " aWndX ", y: " aWndY ", width: " aWndWidth ", height: " aWndHeight - If InStr(Manager_managedWndIds, aWndId ";") { - text .= "`ntags:`t" Window_#%aWndId%_tags - If Window_#%aWndId%_isFloating - text .= " [floating]" - } Else - text .= "`ntags:`t--" - text .= "`n`nConfig_rule=" aWndClass ";" aWndTitle ";;" Manager_getWindowRule(aWndId) - MsgBox, 260, bug.n: Window Information, % text "`n`nCopy text to clipboard?" - IfMsgBox Yes - Clipboard := text -} - -Manager_getWindowList() -{ - Local text, v, aWndId, aWndTitle, wndIds, wndTitle - - v := Monitor_#%Manager_aMonitor%_aView_#1 - aWndId := View_getActiveWindow(Manager_aMonitor, v) - WinGetTitle, aWndTitle, ahk_id %aWndId% - text := "Active Window`n" aWndId ":`t" aWndTitle - - StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 - text .= "`n`nWindow List" - Loop, PARSE, wndIds, `; - { - WinGetTitle, wndTitle, ahk_id %A_LoopField% - text .= "`n" A_LoopField ":`t" wndTitle - } - - MsgBox, 260, bug.n: Window List, % text "`n`nCopy text to clipboard?" - IfMsgBox Yes - Clipboard := text -} - -Manager_getWindowRule(wndId) { - Local rule, wndMinMax - - rule := "" - WinGet, wndMinMax, MinMax, ahk_id %wndId% - If InStr(Manager_managedWndIds, wndId ";") { - rule .= "1;" - If (Window_#%wndId%_monitor = "") - rule .= "0;" - Else - rule .= Window_#%wndId%_monitor ";" - If (Window_#%wndId%_tags = "") - rule .= "0;" - Else - rule .= Window_#%wndId%_tags ";" - If Window_#%wndId%_isFloating - rule .= "1;" - Else - rule .= "0;" - If Window_#%wndId%_isDecorated - rule .= "1;" - Else - rule .= "0;" - } Else - rule .= "0;;;;;" - If InStr(Bar_hideTitleWndIds, wndId ";") - rule .= "1;" - Else - rule .= "0;" - If (wndMinMax = 1) - rule .= "maximize" - - Return, rule -} - -Manager_lockWorkStation() -{ - Global Config_shellMsgDelay - - RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Policies\System, DisableLockWorkstation, 0 - Sleep, % Config_shellMsgDelay - DllCall("LockWorkStation") - Sleep, % 4 * Config_shellMsgDelay - RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Policies\System, DisableLockWorkstation, 1 -} -;; Unambiguous: Re-use WIN+L as a hotkey in bug.n (http://www.autohotkey.com/community/viewtopic.php?p=500903&sid=eb3c7a119259b4015ff045ef80b94a81#p500903) - -Manager_loop(index, increment, lowerBound, upperBound) { - If (upperBound <= 0) Or (upperBound < lowerBound) Or (upperBound = 0) - Return, 0 - - numberOfIndexes := upperBound - lowerBound + 1 - lowerBoundBasedIndex := index - lowerBound - lowerBoundBasedIndex := Mod(lowerBoundBasedIndex + increment, numberOfIndexes) - If (lowerBoundBasedIndex < 0) - lowerBoundBasedIndex += numberOfIndexes - - Return, lowerBound + lowerBoundBasedIndex -} - -Manager__setWinProperties(wndId, isManaged, m, tags, isDecorated, isFloating, hideTitle, action = "") { - Local a := False - - If Not InStr(Manager_allWndIds, wndId ";") - Manager_allWndIds .= wndId ";" - - If (isManaged) { - If (action = "close" Or action = "maximize" Or action = "restore") - Window_%action%(wndId) - - If Not InStr(Manager_managedWndIds, wndId ";") - Manager_managedWndIds .= wndId ";" - Window_#%wndId%_monitor := m - Window_#%wndId%_tags := tags - Window_#%wndId%_isDecorated := isDecorated - Window_#%wndId%_isFloating := isFloating - Window_#%wndId%_isMinimized := False - Window_#%wndId%_area := 0 - - If Not Config_showBorder - Window_set(wndId, "Style", "-0x40000") - if (not Window_#%wndId%_isDecorated and Config_hideTitleBars) { - Window_set(wndId, "Style", "-0xC00000") - } - - a := Window_#%wndId%_tags & (1 << (Monitor_#%m%_aView_#1 - 1)) - If a { - ;; A newly created window defines the active monitor, if it is visible. - Manager_aMonitor := m - Manager_winActivate(wndId) - } Else { - Manager_hideShow := True - Window_hide(wndId) - Manager_hideShow := False - } - } - If hideTitle And Not InStr(Bar_hideTitleWndIds, wndId ";") - Bar_hideTitleWndIds .= wndId . ";" - - Return, a -} - -;; Accept a window to be added to the system for management. -;; Provide a monitor and view preference, but don't override the config. -Manager_manage(preferredMonitor, preferredView, wndId, rule = "") { - Local a, action, c0, hideTitle, i, isDecorated, isFloating, isManaged, l, m, n, replace, search, tags, body - Local rule0, rule1, rule2, rule3, rule4, rule5, rule6, rule7 - Local wndControlList0, wndId0, wndIds, wndX, wndY, wndWidth, wndHeight - - ;; Manage any window only once. - If InStr(Manager_allWndIds, wndId ";") And (rule = "") - Return - - body := 0 - If Window_isGhost(wndId) { - Debug_logMessage("DEBUG[2] A window has given up the ghost (Ghost wndId: " . wndId . ")", 2) - body := Window_findHung(wndId) - If body { - isManaged := InStr(Manager_managedWndIds, body ";") - m := Window_#%body%_monitor - tags := Window_#%body%_tags - isDecorated := Window_#%body%_isDecorated - isFloating := Window_#%body%_isFloating - hideTitle := InStr(Bar_hideTitleWndIds, body ";") - action := "" - } Else - Debug_logMessage("DEBUG[1] No body could be found for ghost wndId: " . wndId, 1) - } - - ;; Apply rules if the window is either a normal window or a ghost without a body. - If (body = 0) { - Manager_applyRules(wndId, isManaged, m, tags, isFloating, isDecorated, hideTitle, action) - If Not (rule = "") { - StringSplit, rule, rule, `; - isManaged := rule1 - m := rule2 - tags := rule3 - isFloating := rule4 - isDecorated := rule5 - hideTitle := rule6 - action := rule7 - } - If (m = 0) - m := preferredMonitor - If (m < 0) - m := 1 - If (m > Manager_monitorCount) ;; If the specified monitor is out of scope, set it to the max. monitor. - m := Manager_monitorCount - If (tags = 0) - tags := 1 << (preferredView - 1) - } - - a := Manager__setWinProperties(wndId, isManaged, m, tags, isDecorated, isFloating, hideTitle, action) - - ; Do view placement. - If isManaged { - Loop, % Config_viewCount - If (Window_#%wndId%_tags & (1 << (A_Index - 1))) { - If (body) { - ; Try to position near the body. - View_ghostWindow(m, A_Index, body, wndId) - } - Else - View_addWindow(m, A_Index, wndId) - } - } - - Return, a -} - -Manager_maximizeWindow() { - Local aWndId - - WinGet, aWndId, ID, A - If InStr(Manager_managedWndIds, aWndId ";") And Not Window_#%aWndId%_isFloating - View_toggleFloatingWindow(aWndId) - Window_set(aWndId, "Top", "") - - Window_move(aWndId, Monitor_#%Manager_aMonitor%_x, Monitor_#%Manager_aMonitor%_y, Monitor_#%Manager_aMonitor%_width, Monitor_#%Manager_aMonitor%_height) -} - -Manager_minimizeWindow() { - Local aView, aWndId - - WinGet, aWndId, ID, A - aView := Monitor_#%Manager_aMonitor%_aView_#1 - StringReplace, View_#%Manager_aMonitor%_#%aView%_aWndIds, View_#%Manager_aMonitor%_#%aView%_aWndIds, % aWndId ";",, All - If InStr(Manager_managedWndIds, aWndId ";") And Not Window_#%aWndId%_isFloating - View_toggleFloatingWindow(aWndId) - Window_set(aWndId, "Bottom", "") - - Window_minimize(aWndId) -} - -Manager_moveWindow() { - Local aWndId, SC_MOVE, WM_SYSCOMMAND - - WinGet, aWndId, ID, A - If InStr(Manager_managedWndIds, aWndId . ";") And Not Window_#%aWndId%_isFloating - View_toggleFloatingWindow(aWndId) - Window_set(aWndId, "Top", "") - - WM_SYSCOMMAND = 0x112 - SC_MOVE = 0xF010 - SendMessage, WM_SYSCOMMAND, SC_MOVE, , , ahk_id %aWndId% -} - -Manager_onDisplayChange(a, wParam, uMsg, lParam) { - Local doChange := (Config_monitorDisplayChangeMessages = "on") - - Debug_logMessage("DEBUG[1] Manager_onDisplayChange( a: " . a . ", uMsg: " . uMsg . ", wParam: " . wParam . ", lParam: " . lParam . " )", 1) - If !(Config_monitorDisplayChangeMessages = "on" || Config_monitorDisplayChangeMessages = "off" || Config_monitorDisplayChangeMessages = 0) { - MsgBox, 291, , % "Would you like to reset the monitor configuration?`n'No' will only rearrange all active views.`n'Cancel' will result in no change." - IfMsgBox Yes - doChange := True - Else IfMsgBox No - { - Loop, % Manager_monitorCount { - View_arrange(A_Index, Monitor_#%A_Index%_aView_#1) - Bar_updateView(A_Index, Monitor_#%A_Index%_aView_#1) - } - Bar_updateStatus() - Bar_updateTitle() - } - } - If (doChange) { - Manager_resetMonitorConfiguration() - } -} - -/* - Possible indications for a ... - new window: 1 (started by Windows Explorer) or 6 (started by cmd, shell or Win+E). - There doesn't seem to be a reliable way to get all application starts. - closed window: 2 (always?) or 13 (ghost) - focus change: 4 or 32772 - title change: 6 or 32774 -*/ -Manager_onShellMessage(wParam, lParam) { - Local a, isChanged, aWndClass, aWndHeight, aWndId, aWndTitle, aWndWidth, aWndX, aWndY, i, m, t, wndClass, wndId, wndId0, wndIds, wndIsDesktop, wndIsHidden, wndTitle, x, y - ;; HSHELL_* become global. - - ;; MESSAGE NAME AND ... NUMBER COMMENTS, POSSIBLE EVENTS - HSHELL_WINDOWCREATED := 1 ;; window shown - HSHELL_WINDOWDESTROYED := 2 ;; window hidden, destroyed or deactivated - HSHELL_ACTIVATESHELLWINDOW := 3 - HSHELL_WINDOWACTIVATED := 4 ;; window title changed, window activated (by mouse, Alt+Tab or hotkey); alternative message: 32772 - HSHELL_GETMINRECT := 5 - HSHELL_REDRAW := 6 ;; window title changed - HSHELL_TASKMAN := 7 - HSHELL_LANGUAGE := 8 - HSHELL_SYSMENU := 9 - HSHELL_ENDTASK := 10 - HSHELL_ACCESSIBILITYSTATE := 11 - HSHELL_APPCOMMAND := 12 - ;; The following two are seen when a hung window recovers. - HSHELL_WINDOWREPLACED := 13 ;; hung window recovered and replaced the ghost window (lParam indicates the ghost window.) - HSHELL_WINDOWREPLACING := 14 ;; hung window recovered (lParam indicates the previously hung and now recovered window.) - HSHELL_HIGHBIT := 32768 ;; 0x8000 - HSHELL_FLASH := 32774 ;; (HSHELL_REDRAW|HSHELL_HIGHBIT); window signalling an application update (The window is flashing due to some event, one message for each flash.) - HSHELL_RUDEAPPACTIVATED := 32772 ;; (HSHELL_WINDOWACTIVATED|HSHELL_HIGHBIT); full-screen app or root-privileged window activated? alternative message: 4 - ;; Any message may be missed, if bug.n is hung or they come in too quickly. - - SetFormat, Integer, hex - lParam := lParam + 0 - SetFormat, Integer, d - - Debug_logMessage("DEBUG[2] Manager_onShellMessage( wParam: " . wParam . ", lParam: " . lParam . " )", 2) - - wndIsHidden := Window_getHidden(lParam, wndClass, wndTitle) - If wndIsHidden { - ;; If there is no window class or title, it is assumed that the window is not identifiable. - ;; The problem was, that i. a. claws-mail triggers Manager_sync, but the application window - ;; would not be ready for being managed, i. e. class and title were not available. Therefore more - ;; attempts were needed. - Return - } - - wndIsDesktop := (lParam = 0) - If wndIsDesktop { - WinGetClass, wndClass, A - WinGetTitle, wndTitle, A - } - WinGet, aWndId, ID, A - WinGetClass, aWndClass, ahk_id %aWndId% - WinGetTitle, aWndTitle, ahk_id %aWndId% - If ((wParam = 4 Or wParam = 32772) And (aWndClass = "WorkerW" And aWndTitle = "" Or lParam = 0 And aWndClass = "Progman" And aWndTitle = "Program Manager")) - { - MouseGetPos, x, y - m := Monitor_get(x, y) - ;; The current position of the mouse cursor defines the active monitor, if the desktop has been activated. - If m - Manager_aMonitor := m - Bar_updateTitle() - } - - ;; This was previously inactive due to `HSHELL_WINDOWREPLACED` not being defined in this function. - ;; Afterwards it caused problems managing new windows, when messages come in too quickly. -; If (wParam = HSHELL_WINDOWREPLACED) -; { ;; This shouldn't need a redraw because the window was supposedly replaced. -; Manager_unmanage(lParam) -; } - -; If (wParam = 14) -; { ;; Window recovered from being hung. Maybe force a redraw. -; } - - ;; @todo: There are two problems with the use of Manager_hideShow: - ;; 1) If Manager_hideShow is set when we hit this block, we won't take some actions that should eventually be taken. - ;; This _may_ explain why some windows never get picked up when spamming Win+E - ;; 2) There is a race condition between the time that Manager_hideShow is checked and any other action which we are - ;; trying to protect against. If another process (hotkey) enters a hideShow block after Manager_hideShow has - ;; been checked here, bad things could happen. I've personally observed that windows may be permanently hidden. - ;; Look into the use of AHK synchronization primitives. - If (wParam = 1 Or wParam = 2 Or wParam = 4 Or wParam = 6 Or wParam = 32772) And lParam And Not Manager_hideShow - { - Sleep, % Config_shellMsgDelay - wndIds := "" - a := isChanged := Manager_sync(wndIds) - If wndIds - isChanged := False - - If isChanged - { - If Config_dynamicTiling - View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) - Bar_updateView(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) - } - - If (Manager_monitorCount > 1 And a > -1) - { - WinGet, aWndId, ID, A - WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %aWndId% - m := Monitor_get(aWndX + aWndWidth / 2, aWndY + aWndHeight / 2) - Debug_logMessage("DEBUG[1] Manager_onShellMessage: Manager_monitorCount: " Manager_monitorCount ", Manager_aMonitor: " Manager_aMonitor ", m: " m ", aWndId: " aWndId, 1) - ;; The currently active window defines the active monitor. - If m - Manager_aMonitor := m - } - - If wndIds - { ;; If there are new (unrecognized) windows, which are hidden ... - If (Config_onActiveHiddenWnds = "view") - { ;; ... change the view to show the first hidden window - wndId := SubStr(wndIds, 1, InStr(wndIds, ";") - 1) - Loop, % Config_viewCount - { - If (Window_#%wndId%_tags & 1 << A_Index - 1) - { - Debug_logMessage("DEBUG[3] Switching views because " . wndId . " is considered hidden and active", 3) - ;; A newly created window defines the active monitor, if it is visible. - Manager_aMonitor := Window_#%wndId%_monitor - Monitor_activateView(A_Index) - Break - } - } - } - Else - { ;; ... re-hide them - StringTrimRight, wndIds, wndIds, 1 - StringSplit, wndId, wndIds, `; - If (Config_onActiveHiddenWnds = "hide") - { - Loop, % wndId0 - { - Window_hide(wndId%A_Index%) - } - } - Else If (Config_onActiveHiddenWnds = "tag") - { - ;; ... or tag all of them for the current view. - t := Monitor_#%Manager_aMonitor%_aView_#1 - Loop, % wndId0 - { - wndId := wndId%A_Index% - View_#%Manager_aMonitor%_#%t%_wndIds := wndId ";" View_#%Manager_aMonitor%_#%t%_wndIds - View_setActiveWindow(Manager_aMonitor, t, wndId) - Window_#%wndId%_tags += 1 << t - 1 - } - Bar_updateView(Manager_aMonitor, t) - If Config_dynamicTiling - View_arrange(Manager_aMonitor, t) - } - } - } - - If InStr(Manager_managedWndIds, lParam ";") { - WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %lParam% - If (Monitor_get(aWndX + aWndWidth / 2, aWndY + aWndHeight / 2) = Manager_aMonitor) - View_setActiveWindow(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1, lParam) - Else - Manager_winActivate(View_getActiveWindow(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1)) - If Window_#%lParam%_isMinimized { - Window_#%lParam%_isFloating := False - Window_#%lParam%_isMinimized := False - View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) - } - } - - ;; This is a workaround for a redrawing problem of the bug.n bar, which - ;; seems to get lost, when windows are created or destroyed under the - ;; following conditions. - If (Manager_monitorCount > 1) And (Config_verticalBarPos = "tray") { - Loop, % (Manager_monitorCount - 1) { - i := A_Index + 1 - Bar_updateLayout(i) - Bar_updateStatic(i) - Loop, % Config_viewCount - Bar_updateView(i, A_Index) - } - Bar_updateStatus() - } - Bar_updateTitle() - } -} - -Manager_override(rule = "") { - Local aWndId, aWndMinMax - - WinGet, aWndId, ID, A - If (rule = "") { - rule := Manager_getWindowRule(aWndId) - InputBox, rule, bug.n: Override, % "Which rule should be applied?`n`n<is managed>;<m>;<tags>;<is floating>;<is decorated>;<hide title>;<action>",, 483, 152,,,,, % rule - If Not (ErrorLevel = 0) - Return - } - Manager_manage(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1, aWndId, rule) - If Config_dynamicTiling - View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) - Bar_updateView(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) -} - -Manager_registerShellHook() { - Global Config_monitorDisplayChangeMessages - - WM_DISPLAYCHANGE := 126 ;; This message is sent when the display resolution has changed. - Gui, +LastFound - hWnd := WinExist() - WinGetClass, wndClass, ahk_id %hWnd% - WinGetTitle, wndTitle, ahk_id %hWnd% - DllCall("RegisterShellHookWindow", "UInt", hWnd) ;; Minimum operating systems: Windows 2000 (http://msdn.microsoft.com/en-us/library/ms644989(VS.85).aspx) - Debug_logMessage("DEBUG[1] Manager_registerShellHook; hWnd: " . hWnd . ", wndClass: " . wndClass . ", wndTitle: " . wndTitle, 1) - msgNum := DllCall("RegisterWindowMessage", "Str", "SHELLHOOK") - OnMessage(msgNum, "Manager_onShellMessage") - If !(Config_monitorDisplayChangeMessages = "off" || Config_monitorDisplayChangeMessages = 0) - OnMessage(WM_DISPLAYCHANGE, "Manager_onDisplayChange") -} -;; SKAN: How to Hook on to Shell to receive its messages? (http://www.autohotkey.com/forum/viewtopic.php?p=123323#123323) - -Manager_resetMonitorConfiguration() { - Local GuiN, hWnd, i, j, m, mPrimary, wndClass, wndIds, wndTitle - - m := Manager_monitorCount - SysGet, Manager_monitorCount, MonitorCount - If (Manager_monitorCount < m) { - ;; A monitor has been disconnected. Which one? - i := Monitor_find(-1, m) - If (i > 0) { - SysGet, mPrimary, MonitorPrimary - GuiN := (m - 1) + 1 - Gui, %GuiN%: Destroy - Loop, % Config_viewCount { - If View_#%i%_#%A_Index%_wndIds { - View_#%mPrimary%_#%A_Index%_wndIds .= View_#%i%_#%A_Index%_wndIds - StringTrimRight, wndIds, View_#%i%_#%A_Index%_wndIds, 1 - Loop, PARSE, wndIds, `; - { - Window_#%A_LoopField%_monitor := mPrimary - } - If (Manager_aMonitor = i) - Manager_aMonitor := mPrimary - } - } - Loop, % m - i { - j := i + A_Index - Monitor_moveToIndex(j, j - 1) - Monitor_getWorkArea(j - 1) - Bar_init(j - 1) - } - } - } Else If (Manager_monitorCount > m) { - ;; A monitor has been connected. Where has it been put? - i := Monitor_find(+1, Manager_monitorCount) - If (i > 0) { - Loop, % Manager_monitorCount - i { - j := Manager_monitorCount - A_Index - Monitor_moveToIndex(j, j + 1) - Monitor_getWorkArea(j + 1) - Bar_init(j + 1) - } - Monitor_init(i, True) - } - } Else { - ;; Has the resolution of a monitor been changed? - mmngr2 := New MonitorManager() - Loop, % Manager_monitorCount { - Monitor_getWorkArea(A_Index) - Debug_logMessage("DEBUG[6] MonitorW: " . Monitor_#%A_Index%_width . ", MMW1: " . mmngr1.monitors[A_Index].width . ", MM1dpiX: " . mmngr1.monitors[A_Index].dpiX . ", MM1scaleX: " . mmngr1.monitors[A_Index].scaleX . ", MMW2: " . mmngr2.monitors[A_Index].width . ", MM2dpiX: " . mmngr2.monitors[A_Index].dpiX . ", MM2scaleX: " . mmngr2.monitors[A_Index].scaleX, 6) - Bar_init(A_Index) - } - } - Manager_saveState() - Loop, % Manager_monitorCount { - View_arrange(A_Index, Monitor_#%A_Index%_aView_#1) - Bar_updateView(A_Index, Monitor_#%A_Index%_aView_#1) - } - Manager__restoreWindowState(Main_autoWindowState) - Bar_updateStatus() - Bar_updateTitle() - - Gui, +LastFound - hWnd := WinExist() - WinGetClass, wndClass, ahk_id %hWnd% - WinGetTitle, wndTitle, ahk_id %hWnd% - DllCall("RegisterShellHookWindow", "UInt", hWnd) ;; Minimum operating systems: Windows 2000 (http://msdn.microsoft.com/en-us/library/ms644989(VS.85).aspx) - Debug_logMessage("DEBUG[1] Manager_registerShellHook; hWnd: " . hWnd . ", wndClass: " . wndClass . ", wndTitle: " . wndTitle, 1) -} - -Manager_restoreWindowBorders() -{ - Local ncm, ncmSize - - If Config_selBorderColor - DllCall("SetSysColors", "Int", 1, "Int*", 10, "UInt*", Manager_normBorderColor) - If (Config_borderWidth > 0) Or (Config_borderPadding >= 0 And A_OSVersion = "WIN_VISTA") - { - ncmSize := VarSetCapacity(ncm, 4 * (A_OSVersion = "WIN_VISTA" ? 11 : 10) + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), 0) - NumPut(ncmSize, ncm, 0, "UInt") - DllCall("SystemParametersInfo", "UInt", 0x0029, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) - If (Config_borderWidth > 0) - NumPut(Manager_borderWidth, ncm, 4, "Int") - If (Config_borderPadding >= 0 And A_OSVersion = "WIN_VISTA") - NumPut(Manager_borderPadding, ncm, 40 + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), "Int") - DllCall("SystemParametersInfo", "UInt", 0x002a, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) - } -} - -;; Restore previously saved window state. -;; If the state is completely different, this function won't do much. However, if restoring from a crash -;; or simply restarting bug.n, it should completely recover the window state. -Manager__restoreWindowState(filename) { - Local vidx, widx, i, j, m, v, candidate_set, detectHidden, view_set, excluded_view_set, view_m0, view_v0, view_list0, wnds0, items0, wndPName, view_var, isManaged, isFloating, isDecorated, hideTitle - - If Not FileExist(filename) - Return - - widx := 1 - vidx := 1 - - view_set := "" - excluded_view_set := "" - - ;; Read all interesting things from the file. - Loop, READ, %filename% - { - If (SubStr(A_LoopReadLine, 1, 5) = "View_") { - i := InStr(A_LoopReadLine, "#") - j := InStr(A_LoopReadLine, "_", false, i) - m := SubStr(A_LoopReadLine, i + 1, j - i - 1) - i := InStr(A_LoopReadLine, "#", false, j) - j := InStr(A_LoopReadLine, "_", false, i) - v := SubStr(A_LoopReadLine, i + 1, j - i - 1) - - i := InStr(A_LoopReadLine, "=", j + 1) - - - If (m <= Manager_monitorCount) And ( v <= Config_viewCount ) { - view_list%vidx% := SubStr(A_LoopReadLine, i + 1) - view_m%vidx% := m - view_v%vidx% := v - view_set := view_set . view_list%vidx% - vidx := vidx + 1 - } Else { - excluded_view_set := excluded_view_set . view_list%vidx% - Debug_logMessage("View (" . m . ", " . v . ") is no longer available (" . vidx . ")", 0) - } - } Else If (SubStr(A_LoopReadLine, 1, 7) = "Window ") { - wnds%widx% := SubStr(A_LoopReadLine, 8) - widx := widx + 1 - } - } - - ;Debug_logMessage("view_set: " . view_set, 1) - ;Debug_logMessage("excluded_view_set: " . excluded_view_set, 1) - - candidate_set := "" - - ; Scan through all defined windows. Create a candidate set of windows based on whether the properties of existing windows match. - Loop, % (widx - 1) { - StringSplit, items, wnds%A_Index%, `; - If (items0 < 9) { - Debug_logMessage("Window '" . wnds%A_Index% . "' could not be processed due to parse error", 0) - Continue - } - - i := 1 - i := items%i% - j := 2 - - detectHidden := A_DetectHiddenWindows - DetectHiddenWindows, On - WinGet, wndPName, ProcessName, ahk_id %i% - DetectHiddenWindows, %detectHidden% - If Not ( items%j% = wndPName ) { - Debug_logMessage("Window ahk_id " . i . " process '" . wndPName . "' doesn't match expected '" . items%j% . "', forgetting this window", 0) - Continue - } - - j := 8 - isManaged := items%j% - - ; If Managed - If ( items%j% ) { - If ( InStr(view_set, i) = 0) { - If ( InStr(excluded_view_set, i) ) - Debug_logMessage("Window ahk_id " . i . " is being ignored because it no longer belongs to an active view", 0) - Else - Debug_logMessage("Window ahk_id " . i . " is being ignored because it doesn't exist in any views", 0) - Continue - } - } - - ; Set up the window. - - j := 3 - m := items%j% - j := 4 - v := items%j% - j := 5 - isFloating := items%j% - j := 6 - isDecorated := items%j% - j := 7 - hideTitle := items%j% - - Manager__setWinProperties(i, isManaged, m, v, isDecorated, isFloating, hideTitle ) - ;Window_hide(i) - - candidate_set := candidate_set . i . ";" - } - - ;Debug_logMessage("candidate_set: " . candidate_set, 1) - - ; Set up all views. Must filter the window list by those from the candidate set. - Loop, % (vidx - 1) { - StringSplit, items, view_list%A_Index%, `; - view_set := "" - Loop, % (items0 - 1) { - If ( InStr(candidate_set, items%A_Index% ) > 0 ) - view_set := view_set . items%A_Index% . ";" - } - view_var := "View_#" . view_m%A_Index% . "_#" . view_v%A_Index% . "_wndIds" - %view_var% := view_set - } -} - -Manager_saveState() { - Critical - Global Config_filePath, Config_viewCount, Main_autoLayout, Main_autoWindowState, Manager_layoutDirty, Manager_monitorCount, Manager_windowsDirty - - Debug_logMessage("DEBUG[2] Manager_saveState", 2) - - ;; @TODO: Check for changes to the layout. - ;If Manager_layoutDirty { - Debug_logMessage("DEBUG[2] Manager_saveState: " Main_autoLayout, 2) - Config_saveSession(Config_filePath, Main_autoLayout) - Manager_layoutDirty := 0 - ;} - - ;; @TODO: Check for changes to windows. - ;If Manager_windowsDirty { - Debug_logMessage("DEBUG[2] Manager_saveState: " Main_autoWindowState, 2) - Manager_saveWindowState(Main_autoWindowState, Manager_monitorCount, Config_viewCount) - Manager_windowsDirty := 0 - ;} -} - -Manager_saveWindowState(filename, nm, nv) { - Local allWndId0, allWndIds, detectHidden, wndPName, title, text, monitor, wndId, view, isManaged, isTitleHidden - - text := "; bug.n - tiling window management`n; @version " VERSION "`n`n" - - tmpfname := filename . ".tmp" - FileDelete, %tmpfname% - - ; Dump window ID and process name. If these two don't match an existing process, we won't try - ; to recover that window. - StringTrimRight, allWndIds, Manager_allWndIds, 1 - StringSplit, allWndId, allWndIds, `; - detectHidden := A_DetectHiddenWindows - DetectHiddenWindows, On - Loop, % allWndId0 { - wndId := allWndId%A_Index% - WinGet, wndPName, ProcessName, ahk_id %wndId% - ; Include title for informative reasons. - WinGetTitle, title, ahk_id %wndId% - - ; wndId;processName;Tags;Floating;Decorated;HideTitle;Managed;Title - - isManaged := InStr(Manager_managedWndIds, wndId . ";") - isTitleHidden := InStr(Bar_hideTitleWndIds, wndId . ";") - - text .= "Window " . wndId . ";" . wndPName . ";" - If isManaged - text .= Window_#%wndId%_monitor . ";" . Window_#%wndId%_tags . ";" . Window_#%wndId%_isFloating . ";" . Window_#%wndId%_isDecorated . ";" - Else - text .= ";;;;" - text .= isTitleHidden . ";" . isManaged . ";" . title . "`n" - } - DetectHiddenWindows, %detectHidden% - - text .= "`n" - - ;; Dump window arrangements on every view. If some views or monitors have disappeared, leave their - ;; corresponding windows alone. - - Loop, % nm { - monitor := A_Index - Loop, % nv { - view := A_Index - ;; Dump all view window lists - text .= "View_#" . monitor . "_#" . view . "_wndIds=" . View_#%monitor%_#%view%_wndIds . "`n" - } - } - - FileAppend, %text%, %tmpfname% - If ErrorLevel { - If FileExist(tmpfname) - FileDelete, %tmpfname% - } Else - FileMove, %tmpfname%, %filename%, 1 -} - -Manager_setCursor(wndId) { - Local wndHeight, wndWidth, wndX, wndY - - If Config_mouseFollowsFocus { - If wndId { - WinGetPos, wndX, wndY, wndWidth, wndHeight, ahk_id %wndId% - DllCall("SetCursorPos", "Int", Round(wndX + wndWidth / 2), "Int", Round(wndY + wndHeight / 2)) - } Else - DllCall("SetCursorPos", "Int", Round(Monitor_#%Manager_aMonitor%_x + Monitor_#%Manager_aMonitor%_width / 2), "Int", Round(Monitor_#%Manager_aMonitor%_y + Monitor_#%Manager_aMonitor%_height / 2)) - } -} - -Manager_setViewMonitor(i, d = 0) { - Local aView, aWndId, v, wndIds - - aView := Monitor_#%Manager_aMonitor%_aView_#1 - If (Manager_monitorCount > 1) And View_#%Manager_aMonitor%_#%aView%_wndIds { - If (i = 0) - i := Manager_aMonitor - i := Manager_loop(i, d, 1, Manager_monitorCount) - v := Monitor_#%i%_aView_#1 - View_#%i%_#%v%_wndIds := View_#%Manager_aMonitor%_#%aView%_wndIds View_#%i%_#%v%_wndIds - - StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%aView%_wndIds, 1 - Loop, PARSE, wndIds, `; - { - Loop, % Config_viewCount { - StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, %A_LoopField%`;, - StringReplace, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, %A_LoopField%`;, - } - Window_#%A_LoopField%_monitor := i - Window_#%A_LoopField%_tags := 1 << v - 1 - } - View_arrange(Manager_aMonitor, aView) - Loop, % Config_viewCount { - Bar_updateView(Manager_aMonitor, A_Index) - } - - ;; Manually set the active monitor. - Manager_aMonitor := i - View_arrange(i, v) - WinGet, aWndId, ID, A - Manager_winActivate(aWndId) - Bar_updateView(i, v) - } -} - -Manager_setWindowBorders() -{ - Local ncm, ncmSize - - If Config_selBorderColor - { - SetFormat, Integer, hex - Manager_normBorderColor := DllCall("GetSysColor", "Int", 10) - SetFormat, Integer, d - DllCall("SetSysColors", "Int", 1, "Int*", 10, "UInt*", Config_selBorderColor) - } - If (Config_borderWidth > 0) Or (Config_borderPadding >= 0 And A_OSVersion = "WIN_VISTA") - { - ncmSize := VarSetCapacity(ncm, 4 * (A_OSVersion = "WIN_VISTA" ? 11 : 10) + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), 0) - NumPut(ncmSize, ncm, 0, "UInt") - DllCall("SystemParametersInfo", "UInt", 0x0029, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) - Manager_borderWidth := NumGet(ncm, 4, "Int") - Manager_borderPadding := NumGet(ncm, 40 + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), "Int") - If (Config_borderWidth > 0) - NumPut(Config_borderWidth, ncm, 4, "Int") - If (Config_borderPadding >= 0 And A_OSVersion = "WIN_VISTA") - NumPut(Config_borderPadding, ncm, 40 + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), "Int") - DllCall("SystemParametersInfo", "UInt", 0x002a, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) - } -} - -Manager_setWindowMonitor(i, d = 0) { - Local aWndId, v - - WinGet, aWndId, ID, A - If (Manager_monitorCount > 1 And InStr(Manager_managedWndIds, aWndId ";")) { - Loop, % Config_viewCount { - StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, %aWndId%`;, - StringReplace, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, %aWndId%`;, All - Bar_updateView(Manager_aMonitor, A_Index) - } - If Config_dynamicTiling - View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) - - ;; Manually set the active monitor. - If (i = 0) - i := Manager_aMonitor - Manager_aMonitor := Manager_loop(i, d, 1, Manager_monitorCount) - Window_#%aWndId%_monitor := Manager_aMonitor - v := Monitor_#%Manager_aMonitor%_aView_#1 - Window_#%aWndId%_tags := 1 << v - 1 - View_#%Manager_aMonitor%_#%v%_wndIds := aWndId ";" View_#%Manager_aMonitor%_#%v%_wndIds - View_setActiveWindow(Manager_aMonitor, v, aWndId) - If Config_dynamicTiling - View_arrange(Manager_aMonitor, v) - Manager_winActivate(aWndId) - Bar_updateView(Manager_aMonitor, v) - } -} - -Manager_sizeWindow() { - Local aWndId, SC_SIZE, WM_SYSCOMMAND - - WinGet, aWndId, ID, A - If InStr(Manager_managedWndIds, aWndId . ";") And Not Window_#%aWndId%_isFloating - View_toggleFloatingWindow(aWndId) - Window_set(aWndId, "Top", "") - - WM_SYSCOMMAND = 0x112 - SC_SIZE = 0xF000 - SendMessage, WM_SYSCOMMAND, SC_SIZE, , , ahk_id %aWndId% -} - -;; No windows are known to the system yet. -;; Try to do something smart with the initial layout. -Manager_initial_sync(doRestore) { - Local wndId, wndId0, wnd, wndX, wndY, wndW, wndH, x, y, m, len - - ;; Initialize lists - ;; Note that these variables make this function non-reentrant. - Loop, % Manager_monitorCount - Manager_initial_sync_m#%A_Index%_wndList := "" - - ;; Use saved window placement settings to first determine - ;; which monitor/view a window should be attached to. - If doRestore - Manager__restoreWindowState(Main_autoWindowState) - - ;; Check all remaining visible windows against the known windows - WinGet, wndId, List, , , - Loop, % wndId { - ;; Based on some analysis here, determine which monitors and layouts would best - ;; serve existing windows. Do not override configuration settings. - - ;; Which monitor is it on? - wnd := wndId%A_Index% - WinGetPos, wndX, wndY, wndW, wndH, ahk_id %wnd% - - x := wndX + wndW/2 - y := wndY + wndH/2 - - m := Monitor_get(x, y) - If m > 0 - Manager_initial_sync_m#%m%_wndList .= wndId%A_Index% ";" - - } - - Loop, % Manager_monitorCount { - m := A_Index - StringTrimRight, wndIds, Manager_initial_sync_m#%m%_wndList, 1 - StringSplit, wndId, wndIds, `; - Loop, % wndId0 - Manager_manage(m, 1, wndId%A_Index%) - } -} - -;; @todo: This constantly tries to re-add windows that are never going to be manageable. -;; Manager_manage should probably ignore all windows that are already in Manager_allWndIds. -;; The problem was, that i. a. claws-mail triggers Manager_sync, but the application window -;; would not be ready for being managed, i. e. class and title were not available. Therefore more -;; attempts were needed. -;; Perhaps this method can be refined by not adding any window to Manager_allWndIds, but only -;; those, which have at least a title or class. -Manager_sync(ByRef wndIds = "") -{ - Local a, flag, shownWndIds, v, visibleWndIds, wndId - a := 0 - - shownWndIds := "" - Loop, % Manager_monitorCount - { - v := Monitor_#%A_Index%_aView_#1 - shownWndIds .= View_#%A_Index%_#%v%_wndIds - } - ;; Check all visible windows against the known windows - visibleWndIds := "" - WinGet, wndId, List, , , - Loop, % wndId - { - If Not InStr(shownWndIds, wndId%A_Index% ";") - { - If Not InStr(Manager_managedWndIds, wndId%A_Index% ";") - { - flag := Manager_manage(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1, wndId%A_Index%) - If flag - a := 1 - } - Else If Not Window_isHung(wndId%A_Index%) - { - ;; This is a window that is already managed but was brought into focus by something. - ;; Maybe it would be useful to do something with it. - wndIds .= wndId%A_Index% ";" - } - } - visibleWndIds := visibleWndIds wndId%A_Index% ";" - } - - ;; @todo-future: Find out why this unmanage code exists and if it's still needed. - ;; check, if a window, that is known to be visible, is actually not visible - StringTrimRight, shownWndIds, shownWndIds, 1 - Loop, PARSE, shownWndIds, `; - { - If Not InStr(visibleWndIds, A_LoopField) - { - flag := Manager_unmanage(A_LoopField) - If (flag And a = 0) - a := -1 - } - } - - Return, a -} - -Manager_unmanage(wndId) { - Local a, aView - - aView := Monitor_#%Manager_aMonitor%_aView_#1 - - a := Window_#%wndId%_tags & 1 << aView - 1 - Loop, % Config_viewCount { - If (Window_#%wndId%_tags & 1 << A_Index - 1) { - StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, % wndId ";",, All - StringReplace, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, % wndId ";",, All - Bar_updateView(Manager_aMonitor, A_Index) - } - } - Window_#%wndId%_monitor := - Window_#%wndId%_tags := - Window_#%wndId%_isDecorated := - Window_#%wndId%_isFloating := - Window_#%wndId%_area := - StringReplace, Bar_hideTitleWndIds, Bar_hideTitleWndIds, %wndId%`;, - StringReplace, Manager_allWndIds, Manager_allWndIds, %wndId%`;, - StringReplace, Manager_managedWndIds, Manager_managedWndIds, %wndId%`;, , All - - Return, a -} - -Manager_winActivate(wndId) { - Global Manager_aMonitor - - Manager_setCursor(wndId) - Debug_logMessage("DEBUG[1] Activating window: " wndId, 1) - If Not wndId { - wndId := WinExist("bug.n_BAR_" . Manager_aMonitor) - Debug_logMessage("DEBUG[1] Activating Desktop: " wndId, 1) - } - - If Window_activate(wndId) - Return, 1 - Else { - Bar_updateTitle() - Return 0 - } -} - -Manager_windowNotMaximized(width, height) { - Global - Return, (width < 0.99 * Monitor_#%Manager_aMonitor%_width Or height < 0.99 * Monitor_#%Manager_aMonitor%_height) -} - -Manager_activateViewByMouse(d) { - Local mousePositionX, mousePositionY, window, windowTitle - MouseGetPos, mousePositionX, mousePositionY, window - WinGetTitle windowTitle, ahk_id %Window% - if( InStr(windowTitle, "bug.n_BAR_") = 1 ) { - Monitor_activateView(0, d) - } -} +/* + bug.n -- tiling window management + Copyright (c) 2010-2019 Joshua Fuhs, joten + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + @license GNU General Public License version 3 + ../LICENSE.md or <http://www.gnu.org/licenses/> + + @version 9.1.0 +*/ + +Manager_init() +{ + Local doRestore + + Manager_setWindowBorders() + Bar_getHeight() + ; axes, dimensions, percentage, flipped, gapWidth + Manager_layoutDirty := 0 + ; New/closed windows, active changed, + Manager_windowsDirty := 0 + Manager_aMonitor := 1 + View_tiledWndId0 := 0 + + doRestore := 0 + If (Config_autoSaveSession = "ask") + { + MsgBox, 0x4, , Would you like to restore an auto-saved session? + IfMsgBox Yes + doRestore := 1 + } + Else If (Config_autoSaveSession = "auto") + { + doRestore := 1 + } + + mmngr1 := New MonitorManager() + mmngr2 := "" + SysGet, Manager_monitorCount, MonitorCount + Debug_logMessage("DEBUG[0] Manager_init: Found " . Manager_monitorCount . " monitor" . (Manager_monitorCount != 1 ? "s" . "") . ".", 0) + Loop, % Manager_monitorCount + { + Sleep, % Config_shellMsgDelay + Monitor_init(A_Index, doRestore) + Debug_logMessage("DEBUG[6] MonitorW: " . Monitor_#%A_Index%_width . ", MMW1: " . mmngr1.monitors[A_Index].width . ", MM1dpiX: " . mmngr1.monitors[A_Index].dpiX . ", MM1scaleX: " . mmngr1.monitors[A_Index].scaleX, 6) + } + Bar_initCmdGui() + + Manager_hideShow := False + Bar_hideTitleWndIds := "" + Manager_allWndIds := "" + Manager_managedWndIds := "" + Manager_initial_sync(doRestore) + + Bar_updateStatus() + Bar_updateTitle() + Loop, % Manager_monitorCount + { + View_arrange(A_Index, Monitor_#%A_Index%_aView_#1) + Bar_updateView(A_Index, Monitor_#%A_Index%_aView_#1) + } + + Manager_registerShellHook() + SetTimer, Manager_doMaintenance, %Config_maintenanceInterval% + SetTimer, Bar_loop, %Config_readinInterval% +} + +Manager_activateMonitor(i, d = 0) { + Local aView, aWndHeight, aWndId, aWndWidth, aWndX, aWndY, v, wndId + + If (Manager_monitorCount > 1) { + aView := Monitor_#%Manager_aMonitor%_aView_#1 + WinGet, aWndId, ID, A + If WinExist("ahk_id" aWndId) And InStr(View_#%Manager_aMonitor%_#%aView%_wndIds, aWndId ";") And Window_isProg(aWndId) { + WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %aWndId% + If (Monitor_get(aWndX + aWndWidth / 2, aWndY + aWndHeight / 2) = Manager_aMonitor) + View_setActiveWindow(Manager_aMonitor, aView, aWndId) + } + + ;; Manually set the active monitor. + If (i = 0) + i := Manager_aMonitor + Manager_aMonitor := Manager_loop(i, d, 1, Manager_monitorCount) + v := Monitor_#%Manager_aMonitor%_aView_#1 + wndId := View_getActiveWindow(Manager_aMonitor, v) + Debug_logMessage("DEBUG[1] Manager_activateMonitor: Manager_aMonitor: " Manager_aMonitor ", i: " i ", d: " d ", wndId: " wndId, 1) + Manager_winActivate(wndId) + } +} + +Manager_applyRules(wndId, ByRef isManaged, ByRef m, ByRef tags, ByRef isFloating, ByRef isDecorated, ByRef hideTitle, ByRef action) { + Local i, wndClass, wndTitle + Local rule0, rule1, rule2, rule3, rule4, rule5, rule6, rule7, rule8, rule9, rule10 + + isManaged := True + m := 0 + tags := 0 + isFloating := False + isDecorated := False + hideTitle := False + action := "" + + WinGetClass, wndClass, ahk_id %wndId% + WinGetTitle, wndTitle, ahk_id %wndId% + If (wndClass Or wndTitle) { + Loop, % Config_ruleCount { + ;; The rules are traversed in reverse order. + i := Config_ruleCount - A_Index + 1 + StringSplit, rule, Config_rule_#%i%, `; + If RegExMatch(wndClass . ";" . wndTitle, rule1 . ";" . rule2) And (rule3 = "" Or %rule3%(wndId)) { + isManaged := rule4 + m := rule5 + tags := rule6 + isFloating := rule7 + isDecorated := rule8 + hideTitle := rule9 + action := rule10 + ;; The first matching rule is returned, i. e. the last in the original rder of Config_rule. + Break + } + } + Debug_logMessage("DEBUG[1] Manager_applyRules: class: " wndClass ", title: " wndTitle ", wndId: " wndId ", rule #: " i, 1) + } Else { + isManaged := False + If wndTitle + hideTitle := True + } +} + +Manager_cleanup() +{ + Local aWndId, m, ncmSize, ncm, wndIds + + WinGet, aWndId, ID, A + + Manager_restoreWindowBorders() + + ;; Show borders and title bars. + StringTrimRight, wndIds, Manager_managedWndIds, 1 + Manager_hideShow := True + Loop, PARSE, wndIds, `; + { + Window_show(A_LoopField) + If Not Config_showBorder + Window_set(A_LoopField, "Style", "+0x40000") + Window_set(A_LoopField, "Style", "+0xC00000") + } + + ;; Show the task bar. + WinShow, Start ahk_class Button + WinShow, ahk_class Shell_TrayWnd + Manager_hideShow := False + + ;; Restore window positions and sizes. + Loop, % Manager_monitorCount + { + m := A_Index + Monitor_#%m%_showBar := False + Monitor_#%m%_showTaskBar := True + Monitor_getWorkArea(m) + Loop, % Config_viewCount + { + View_arrange(m, A_Index, True) + } + } + Window_set(aWndId, "AlwaysOnTop", "On") + Window_set(aWndId, "AlwaysOnTop", "Off") + + DllCall("Shell32.dll\SHAppBarMessage", "UInt", (ABM_REMOVE := 0x1), "UInt", &Bar_appBarData) + ;; SKAN: Crazy Scripting : Quick Launcher for Portable Apps (http://www.autohotkey.com/forum/topic22398.html) +} + +Manager_closeWindow() { + Local aWndId + + WinGet, aWndId, ID, A + If Window_isProg(aWndId) + Window_close(aWndId) +} + +; Asynchronous management of various WM properties. +; We want to make sure that we can recover the layout and windows in the event of +; unexpected problems. +; Periodically check for changes to these things and save them somewhere (not over +; user-defined files). +Manager_doMaintenance: + Critical + + ;; @TODO: Manager_sync? + If Not (Config_autoSaveSession = "off") And Not (Config_autoSaveSession = "False") + Manager_saveState() +Return + +Manager_getWindowInfo() { + Local aWndClass, aWndHeight, aWndId, aWndPId, aWndPName, aWndStyle, aWndTitle, aWndWidth, aWndX, aWndY, detectHiddenWnds, isHidden, text, v + + detectHiddenWnds := A_DetectHiddenWindows + DetectHiddenWindows, On + WinGet, aWndId, ID, A + DetectHiddenWindows, %detectHiddenWnds% + isHidden := Window_getHidden(aWndId, aWndClass, aWndTitle) + WinGet, aWndPName, ProcessName, ahk_id %aWndId% + WinGet, aWndPId, PID, ahk_id %aWndId% + WinGet, aWndStyle, Style, ahk_id %aWndId% + WinGet, aWndMinMax, MinMax, ahk_id %aWndId% + WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %aWndId% + text := "ID: " aWndId (isHidden ? " [hidden]" : "") "`nclass:`t" aWndClass "`ntitle:`t" aWndTitle + If InStr(Bar_hideTitleWndIds, aWndId ";") + text .= " [hidden]" + text .= "`nprocess:`t" aWndPName " [" aWndPId "]`nstyle:`t" aWndStyle "`nmetrics:`tx: " aWndX ", y: " aWndY ", width: " aWndWidth ", height: " aWndHeight + If InStr(Manager_managedWndIds, aWndId ";") { + text .= "`ntags:`t" Window_#%aWndId%_tags + If Window_#%aWndId%_isFloating + text .= " [floating]" + } Else + text .= "`ntags:`t--" + text .= "`n`nConfig_rule=" aWndClass ";" aWndTitle ";;" Manager_getWindowRule(aWndId) + MsgBox, 260, bug.n: Window Information, % text "`n`nCopy text to clipboard?" + IfMsgBox Yes + Clipboard := text +} + +Manager_getWindowList() +{ + Local text, v, aWndId, aWndTitle, wndIds, wndTitle + + v := Monitor_#%Manager_aMonitor%_aView_#1 + aWndId := View_getActiveWindow(Manager_aMonitor, v) + WinGetTitle, aWndTitle, ahk_id %aWndId% + text := "Active Window`n" aWndId ":`t" aWndTitle + + StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 + text .= "`n`nWindow List" + Loop, PARSE, wndIds, `; + { + WinGetTitle, wndTitle, ahk_id %A_LoopField% + text .= "`n" A_LoopField ":`t" wndTitle + } + + MsgBox, 260, bug.n: Window List, % text "`n`nCopy text to clipboard?" + IfMsgBox Yes + Clipboard := text +} + +Manager_getWindowRule(wndId) { + Local rule, wndMinMax + + rule := "" + WinGet, wndMinMax, MinMax, ahk_id %wndId% + If InStr(Manager_managedWndIds, wndId ";") { + rule .= "1;" + If (Window_#%wndId%_monitor = "") + rule .= "0;" + Else + rule .= Window_#%wndId%_monitor ";" + If (Window_#%wndId%_tags = "") + rule .= "0;" + Else + rule .= Window_#%wndId%_tags ";" + If Window_#%wndId%_isFloating + rule .= "1;" + Else + rule .= "0;" + If Window_#%wndId%_isDecorated + rule .= "1;" + Else + rule .= "0;" + } Else + rule .= "0;;;;;" + If InStr(Bar_hideTitleWndIds, wndId ";") + rule .= "1;" + Else + rule .= "0;" + If (wndMinMax = 1) + rule .= "maximize" + + Return, rule +} + +Manager_lockWorkStation() +{ + Global Config_shellMsgDelay + + RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Policies\System, DisableLockWorkstation, 0 + Sleep, % Config_shellMsgDelay + DllCall("LockWorkStation") + Sleep, % 4 * Config_shellMsgDelay + RegWrite, REG_DWORD, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Policies\System, DisableLockWorkstation, 1 +} +;; Unambiguous: Re-use WIN+L as a hotkey in bug.n (http://www.autohotkey.com/community/viewtopic.php?p=500903&sid=eb3c7a119259b4015ff045ef80b94a81#p500903) + +Manager_loop(index, increment, lowerBound, upperBound) { + If (upperBound <= 0) Or (upperBound < lowerBound) Or (upperBound = 0) + Return, 0 + + numberOfIndexes := upperBound - lowerBound + 1 + lowerBoundBasedIndex := index - lowerBound + lowerBoundBasedIndex := Mod(lowerBoundBasedIndex + increment, numberOfIndexes) + If (lowerBoundBasedIndex < 0) + lowerBoundBasedIndex += numberOfIndexes + + Return, lowerBound + lowerBoundBasedIndex +} + +Manager__setWinProperties(wndId, isManaged, m, tags, isDecorated, isFloating, hideTitle, action = "") { + Local a := False + + If Not InStr(Manager_allWndIds, wndId ";") + Manager_allWndIds .= wndId ";" + + If (isManaged) { + If (action = "close" Or action = "maximize" Or action = "restore") + Window_%action%(wndId) + + If Not InStr(Manager_managedWndIds, wndId ";") + Manager_managedWndIds .= wndId ";" + Window_#%wndId%_monitor := m + Window_#%wndId%_tags := tags + Window_#%wndId%_isDecorated := isDecorated + Window_#%wndId%_isFloating := isFloating + Window_#%wndId%_isMinimized := False + Window_#%wndId%_area := 0 + + If Not Config_showBorder + Window_set(wndId, "Style", "-0x40000") + if (not Window_#%wndId%_isDecorated and Config_hideTitleBars) { + Window_set(wndId, "Style", "-0xC00000") + } + + a := Window_#%wndId%_tags & (1 << (Monitor_#%m%_aView_#1 - 1)) + If a { + ;; A newly created window defines the active monitor, if it is visible. + Manager_aMonitor := m + Manager_winActivate(wndId) + } Else { + Manager_hideShow := True + Window_hide(wndId) + Manager_hideShow := False + } + } + If hideTitle And Not InStr(Bar_hideTitleWndIds, wndId ";") + Bar_hideTitleWndIds .= wndId . ";" + + Return, a +} + +;; Accept a window to be added to the system for management. +;; Provide a monitor and view preference, but don't override the config. +Manager_manage(preferredMonitor, preferredView, wndId, rule = "") { + Local a, action, c0, hideTitle, i, isDecorated, isFloating, isManaged, l, m, n, replace, search, tags, body + Local rule0, rule1, rule2, rule3, rule4, rule5, rule6, rule7 + Local wndControlList0, wndId0, wndIds, wndX, wndY, wndWidth, wndHeight + + ;; Manage any window only once. + If InStr(Manager_allWndIds, wndId ";") And (rule = "") + Return + + body := 0 + If Window_isGhost(wndId) { + Debug_logMessage("DEBUG[2] A window has given up the ghost (Ghost wndId: " . wndId . ")", 2) + body := Window_findHung(wndId) + If body { + isManaged := InStr(Manager_managedWndIds, body ";") + m := Window_#%body%_monitor + tags := Window_#%body%_tags + isDecorated := Window_#%body%_isDecorated + isFloating := Window_#%body%_isFloating + hideTitle := InStr(Bar_hideTitleWndIds, body ";") + action := "" + } Else + Debug_logMessage("DEBUG[1] No body could be found for ghost wndId: " . wndId, 1) + } + + ;; Apply rules if the window is either a normal window or a ghost without a body. + If (body = 0) { + Manager_applyRules(wndId, isManaged, m, tags, isFloating, isDecorated, hideTitle, action) + If Not (rule = "") { + StringSplit, rule, rule, `; + isManaged := rule1 + m := rule2 + tags := rule3 + isFloating := rule4 + isDecorated := rule5 + hideTitle := rule6 + action := rule7 + } + If (m = 0) + m := preferredMonitor + If (m < 0) + m := 1 + If (m > Manager_monitorCount) ;; If the specified monitor is out of scope, set it to the max. monitor. + m := Manager_monitorCount + If (tags = 0) + tags := 1 << (preferredView - 1) + } + + a := Manager__setWinProperties(wndId, isManaged, m, tags, isDecorated, isFloating, hideTitle, action) + + ; Do view placement. + If isManaged { + Loop, % Config_viewCount + If (Window_#%wndId%_tags & (1 << (A_Index - 1))) { + If (body) { + ; Try to position near the body. + View_ghostWindow(m, A_Index, body, wndId) + } + Else + View_addWindow(m, A_Index, wndId) + } + } + + Return, a +} + +Manager_maximizeWindow() { + Local aWndId + + WinGet, aWndId, ID, A + If InStr(Manager_managedWndIds, aWndId ";") And Not Window_#%aWndId%_isFloating + View_toggleFloatingWindow(aWndId) + Window_set(aWndId, "Top", "") + + Window_move(aWndId, Monitor_#%Manager_aMonitor%_x, Monitor_#%Manager_aMonitor%_y, Monitor_#%Manager_aMonitor%_width, Monitor_#%Manager_aMonitor%_height) +} + +Manager_minimizeWindow() { + Local aView, aWndId + + WinGet, aWndId, ID, A + aView := Monitor_#%Manager_aMonitor%_aView_#1 + StringReplace, View_#%Manager_aMonitor%_#%aView%_aWndIds, View_#%Manager_aMonitor%_#%aView%_aWndIds, % aWndId ";",, All + If InStr(Manager_managedWndIds, aWndId ";") And Not Window_#%aWndId%_isFloating + View_toggleFloatingWindow(aWndId) + Window_set(aWndId, "Bottom", "") + + Window_minimize(aWndId) +} + +Manager_moveWindow() { + Local aWndId, SC_MOVE, WM_SYSCOMMAND + + WinGet, aWndId, ID, A + If InStr(Manager_managedWndIds, aWndId . ";") And Not Window_#%aWndId%_isFloating + View_toggleFloatingWindow(aWndId) + Window_set(aWndId, "Top", "") + + WM_SYSCOMMAND = 0x112 + SC_MOVE = 0xF010 + SendMessage, WM_SYSCOMMAND, SC_MOVE, , , ahk_id %aWndId% +} + +Manager_onDisplayChange(a, wParam, uMsg, lParam) { + Local doChange := (Config_monitorDisplayChangeMessages = "on") + + Debug_logMessage("DEBUG[1] Manager_onDisplayChange( a: " . a . ", uMsg: " . uMsg . ", wParam: " . wParam . ", lParam: " . lParam . " )", 1) + If !(Config_monitorDisplayChangeMessages = "on" || Config_monitorDisplayChangeMessages = "off" || Config_monitorDisplayChangeMessages = 0) { + MsgBox, 291, , % "Would you like to reset the monitor configuration?`n'No' will only rearrange all active views.`n'Cancel' will result in no change." + IfMsgBox Yes + doChange := True + Else IfMsgBox No + { + Loop, % Manager_monitorCount { + View_arrange(A_Index, Monitor_#%A_Index%_aView_#1) + Bar_updateView(A_Index, Monitor_#%A_Index%_aView_#1) + } + Bar_updateStatus() + Bar_updateTitle() + } + } + If (doChange) { + Manager_resetMonitorConfiguration() + } +} + +/* + Possible indications for a ... + new window: 1 (started by Windows Explorer) or 6 (started by cmd, shell or Win+E). + There doesn't seem to be a reliable way to get all application starts. + closed window: 2 (always?) or 13 (ghost) + focus change: 4 or 32772 + title change: 6 or 32774 +*/ +Manager_onShellMessage(wParam, lParam) { + Local a, isChanged, aWndClass, aWndHeight, aWndId, aWndTitle, aWndWidth, aWndX, aWndY, i, m, t, wndClass, wndId, wndId0, wndIds, wndIsDesktop, wndIsHidden, wndTitle, x, y + ;; HSHELL_* become global. + + ;; MESSAGE NAME AND ... NUMBER COMMENTS, POSSIBLE EVENTS + HSHELL_WINDOWCREATED := 1 ;; window shown + HSHELL_WINDOWDESTROYED := 2 ;; window hidden, destroyed or deactivated + HSHELL_ACTIVATESHELLWINDOW := 3 + HSHELL_WINDOWACTIVATED := 4 ;; window title changed, window activated (by mouse, Alt+Tab or hotkey); alternative message: 32772 + HSHELL_GETMINRECT := 5 + HSHELL_REDRAW := 6 ;; window title changed + HSHELL_TASKMAN := 7 + HSHELL_LANGUAGE := 8 + HSHELL_SYSMENU := 9 + HSHELL_ENDTASK := 10 + HSHELL_ACCESSIBILITYSTATE := 11 + HSHELL_APPCOMMAND := 12 + ;; The following two are seen when a hung window recovers. + HSHELL_WINDOWREPLACED := 13 ;; hung window recovered and replaced the ghost window (lParam indicates the ghost window.) + HSHELL_WINDOWREPLACING := 14 ;; hung window recovered (lParam indicates the previously hung and now recovered window.) + HSHELL_HIGHBIT := 32768 ;; 0x8000 + HSHELL_FLASH := 32774 ;; (HSHELL_REDRAW|HSHELL_HIGHBIT); window signalling an application update (The window is flashing due to some event, one message for each flash.) + HSHELL_RUDEAPPACTIVATED := 32772 ;; (HSHELL_WINDOWACTIVATED|HSHELL_HIGHBIT); full-screen app or root-privileged window activated? alternative message: 4 + ;; Any message may be missed, if bug.n is hung or they come in too quickly. + + SetFormat, Integer, hex + lParam := lParam + 0 + SetFormat, Integer, d + + Debug_logMessage("DEBUG[2] Manager_onShellMessage( wParam: " . wParam . ", lParam: " . lParam . " )", 2) + + wndIsHidden := Window_getHidden(lParam, wndClass, wndTitle) + If wndIsHidden { + ;; If there is no window class or title, it is assumed that the window is not identifiable. + ;; The problem was, that i. a. claws-mail triggers Manager_sync, but the application window + ;; would not be ready for being managed, i. e. class and title were not available. Therefore more + ;; attempts were needed. + Return + } + + wndIsDesktop := (lParam = 0) + If wndIsDesktop { + WinGetClass, wndClass, A + WinGetTitle, wndTitle, A + } + WinGet, aWndId, ID, A + WinGetClass, aWndClass, ahk_id %aWndId% + WinGetTitle, aWndTitle, ahk_id %aWndId% + If ((wParam = 4 Or wParam = 32772) And (aWndClass = "WorkerW" And aWndTitle = "" Or lParam = 0 And aWndClass = "Progman" And aWndTitle = "Program Manager")) + { + MouseGetPos, x, y + m := Monitor_get(x, y) + ;; The current position of the mouse cursor defines the active monitor, if the desktop has been activated. + If m + Manager_aMonitor := m + Bar_updateTitle() + } + + ;; This was previously inactive due to `HSHELL_WINDOWREPLACED` not being defined in this function. + ;; Afterwards it caused problems managing new windows, when messages come in too quickly. +; If (wParam = HSHELL_WINDOWREPLACED) +; { ;; This shouldn't need a redraw because the window was supposedly replaced. +; Manager_unmanage(lParam) +; } + +; If (wParam = 14) +; { ;; Window recovered from being hung. Maybe force a redraw. +; } + + ;; @todo: There are two problems with the use of Manager_hideShow: + ;; 1) If Manager_hideShow is set when we hit this block, we won't take some actions that should eventually be taken. + ;; This _may_ explain why some windows never get picked up when spamming Win+E + ;; 2) There is a race condition between the time that Manager_hideShow is checked and any other action which we are + ;; trying to protect against. If another process (hotkey) enters a hideShow block after Manager_hideShow has + ;; been checked here, bad things could happen. I've personally observed that windows may be permanently hidden. + ;; Look into the use of AHK synchronization primitives. + If (wParam = 1 Or wParam = 2 Or wParam = 4 Or wParam = 6 Or wParam = 32772) And lParam And Not Manager_hideShow + { + Sleep, % Config_shellMsgDelay + wndIds := "" + a := isChanged := Manager_sync(wndIds) + If wndIds + isChanged := False + + If isChanged + { + If Config_dynamicTiling + View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) + Bar_updateView(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) + } + + If (Manager_monitorCount > 1 And a > -1) + { + WinGet, aWndId, ID, A + WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %aWndId% + m := Monitor_get(aWndX + aWndWidth / 2, aWndY + aWndHeight / 2) + Debug_logMessage("DEBUG[1] Manager_onShellMessage: Manager_monitorCount: " Manager_monitorCount ", Manager_aMonitor: " Manager_aMonitor ", m: " m ", aWndId: " aWndId, 1) + ;; The currently active window defines the active monitor. + If m + Manager_aMonitor := m + } + + If wndIds + { ;; If there are new (unrecognized) windows, which are hidden ... + If (Config_onActiveHiddenWnds = "view") + { ;; ... change the view to show the first hidden window + wndId := SubStr(wndIds, 1, InStr(wndIds, ";") - 1) + Loop, % Config_viewCount + { + If (Window_#%wndId%_tags & 1 << A_Index - 1) + { + Debug_logMessage("DEBUG[3] Switching views because " . wndId . " is considered hidden and active", 3) + ;; A newly created window defines the active monitor, if it is visible. + Manager_aMonitor := Window_#%wndId%_monitor + Monitor_activateView(A_Index) + Break + } + } + } + Else + { ;; ... re-hide them + StringTrimRight, wndIds, wndIds, 1 + StringSplit, wndId, wndIds, `; + If (Config_onActiveHiddenWnds = "hide") + { + Loop, % wndId0 + { + Window_hide(wndId%A_Index%) + } + } + Else If (Config_onActiveHiddenWnds = "tag") + { + ;; ... or tag all of them for the current view. + t := Monitor_#%Manager_aMonitor%_aView_#1 + Loop, % wndId0 + { + wndId := wndId%A_Index% + View_#%Manager_aMonitor%_#%t%_wndIds := wndId ";" View_#%Manager_aMonitor%_#%t%_wndIds + View_setActiveWindow(Manager_aMonitor, t, wndId) + Window_#%wndId%_tags += 1 << t - 1 + } + Bar_updateView(Manager_aMonitor, t) + If Config_dynamicTiling + View_arrange(Manager_aMonitor, t) + } + } + } + + If InStr(Manager_managedWndIds, lParam ";") { + WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %lParam% + If (Monitor_get(aWndX + aWndWidth / 2, aWndY + aWndHeight / 2) = Manager_aMonitor) + View_setActiveWindow(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1, lParam) + Else + Manager_winActivate(View_getActiveWindow(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1)) + If Window_#%lParam%_isMinimized { + Window_#%lParam%_isFloating := False + Window_#%lParam%_isMinimized := False + View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) + } + } + + ;; This is a workaround for a redrawing problem of the bug.n bar, which + ;; seems to get lost, when windows are created or destroyed under the + ;; following conditions. + If (Manager_monitorCount > 1) And (Config_verticalBarPos = "tray") { + Loop, % (Manager_monitorCount - 1) { + i := A_Index + 1 + ;Bar_updateLayout(i) + Bar_updateStatic(i) + Loop, % Config_viewCount + Bar_updateView(i, A_Index) + } + Bar_updateStatus() + } + Bar_updateTitle() + } +} + +Manager_override(rule = "") { + Local aWndId, aWndMinMax + + WinGet, aWndId, ID, A + If (rule = "") { + rule := Manager_getWindowRule(aWndId) + InputBox, rule, bug.n: Override, % "Which rule should be applied?`n`n<is managed>;<m>;<tags>;<is floating>;<is decorated>;<hide title>;<action>",, 483, 152,,,,, % rule + If Not (ErrorLevel = 0) + Return + } + Manager_manage(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1, aWndId, rule) + If Config_dynamicTiling + View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) + Bar_updateView(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) +} + +Manager_registerShellHook() { + Global Config_monitorDisplayChangeMessages + + WM_DISPLAYCHANGE := 126 ;; This message is sent when the display resolution has changed. + Gui, +LastFound + hWnd := WinExist() + WinGetClass, wndClass, ahk_id %hWnd% + WinGetTitle, wndTitle, ahk_id %hWnd% + DllCall("RegisterShellHookWindow", "UInt", hWnd) ;; Minimum operating systems: Windows 2000 (http://msdn.microsoft.com/en-us/library/ms644989(VS.85).aspx) + Debug_logMessage("DEBUG[1] Manager_registerShellHook; hWnd: " . hWnd . ", wndClass: " . wndClass . ", wndTitle: " . wndTitle, 1) + msgNum := DllCall("RegisterWindowMessage", "Str", "SHELLHOOK") + OnMessage(msgNum, "Manager_onShellMessage") + If !(Config_monitorDisplayChangeMessages = "off" || Config_monitorDisplayChangeMessages = 0) + OnMessage(WM_DISPLAYCHANGE, "Manager_onDisplayChange") +} +;; SKAN: How to Hook on to Shell to receive its messages? (http://www.autohotkey.com/forum/viewtopic.php?p=123323#123323) + +Manager_resetMonitorConfiguration() { + Local GuiN, hWnd, i, j, m, mPrimary, wndClass, wndIds, wndTitle + + m := Manager_monitorCount + SysGet, Manager_monitorCount, MonitorCount + If (Manager_monitorCount < m) { + ;; A monitor has been disconnected. Which one? + i := Monitor_find(-1, m) + If (i > 0) { + SysGet, mPrimary, MonitorPrimary + GuiN := (m - 1) + 1 + Gui, %GuiN%: Destroy + Loop, % Config_viewCount { + If View_#%i%_#%A_Index%_wndIds { + View_#%mPrimary%_#%A_Index%_wndIds .= View_#%i%_#%A_Index%_wndIds + StringTrimRight, wndIds, View_#%i%_#%A_Index%_wndIds, 1 + Loop, PARSE, wndIds, `; + { + Window_#%A_LoopField%_monitor := mPrimary + } + If (Manager_aMonitor = i) + Manager_aMonitor := mPrimary + } + } + Loop, % m - i { + j := i + A_Index + Monitor_moveToIndex(j, j - 1) + Monitor_getWorkArea(j - 1) + Bar_init(j - 1) + } + } + } Else If (Manager_monitorCount > m) { + ;; A monitor has been connected. Where has it been put? + i := Monitor_find(+1, Manager_monitorCount) + If (i > 0) { + Loop, % Manager_monitorCount - i { + j := Manager_monitorCount - A_Index + Monitor_moveToIndex(j, j + 1) + Monitor_getWorkArea(j + 1) + Bar_init(j + 1) + } + Monitor_init(i, True) + } + } Else { + ;; Has the resolution of a monitor been changed? + mmngr2 := New MonitorManager() + Loop, % Manager_monitorCount { + Monitor_getWorkArea(A_Index) + Debug_logMessage("DEBUG[6] MonitorW: " . Monitor_#%A_Index%_width . ", MMW1: " . mmngr1.monitors[A_Index].width . ", MM1dpiX: " . mmngr1.monitors[A_Index].dpiX . ", MM1scaleX: " . mmngr1.monitors[A_Index].scaleX . ", MMW2: " . mmngr2.monitors[A_Index].width . ", MM2dpiX: " . mmngr2.monitors[A_Index].dpiX . ", MM2scaleX: " . mmngr2.monitors[A_Index].scaleX, 6) + Bar_init(A_Index) + } + } + Manager_saveState() + Loop, % Manager_monitorCount { + View_arrange(A_Index, Monitor_#%A_Index%_aView_#1) + Bar_updateView(A_Index, Monitor_#%A_Index%_aView_#1) + } + Manager__restoreWindowState(Main_autoWindowState) + Bar_updateStatus() + Bar_updateTitle() + + Gui, +LastFound + hWnd := WinExist() + WinGetClass, wndClass, ahk_id %hWnd% + WinGetTitle, wndTitle, ahk_id %hWnd% + DllCall("RegisterShellHookWindow", "UInt", hWnd) ;; Minimum operating systems: Windows 2000 (http://msdn.microsoft.com/en-us/library/ms644989(VS.85).aspx) + Debug_logMessage("DEBUG[1] Manager_registerShellHook; hWnd: " . hWnd . ", wndClass: " . wndClass . ", wndTitle: " . wndTitle, 1) +} + +Manager_restoreWindowBorders() +{ + Local ncm, ncmSize + + If Config_selBorderColor + DllCall("SetSysColors", "Int", 1, "Int*", 10, "UInt*", Manager_normBorderColor) + If (Config_borderWidth > 0) Or (Config_borderPadding >= 0 And A_OSVersion = "WIN_VISTA") + { + ncmSize := VarSetCapacity(ncm, 4 * (A_OSVersion = "WIN_VISTA" ? 11 : 10) + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), 0) + NumPut(ncmSize, ncm, 0, "UInt") + DllCall("SystemParametersInfo", "UInt", 0x0029, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) + If (Config_borderWidth > 0) + NumPut(Manager_borderWidth, ncm, 4, "Int") + If (Config_borderPadding >= 0 And A_OSVersion = "WIN_VISTA") + NumPut(Manager_borderPadding, ncm, 40 + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), "Int") + DllCall("SystemParametersInfo", "UInt", 0x002a, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) + } +} + +;; Restore previously saved window state. +;; If the state is completely different, this function won't do much. However, if restoring from a crash +;; or simply restarting bug.n, it should completely recover the window state. +Manager__restoreWindowState(filename) { + Local vidx, widx, i, j, m, v, candidate_set, detectHidden, view_set, excluded_view_set, view_m0, view_v0, view_list0, wnds0, items0, wndPName, view_var, isManaged, isFloating, isDecorated, hideTitle + + If Not FileExist(filename) + Return + + widx := 1 + vidx := 1 + + view_set := "" + excluded_view_set := "" + + ;; Read all interesting things from the file. + Loop, READ, %filename% + { + If (SubStr(A_LoopReadLine, 1, 5) = "View_") { + i := InStr(A_LoopReadLine, "#") + j := InStr(A_LoopReadLine, "_", false, i) + m := SubStr(A_LoopReadLine, i + 1, j - i - 1) + i := InStr(A_LoopReadLine, "#", false, j) + j := InStr(A_LoopReadLine, "_", false, i) + v := SubStr(A_LoopReadLine, i + 1, j - i - 1) + + i := InStr(A_LoopReadLine, "=", j + 1) + + + If (m <= Manager_monitorCount) And ( v <= Config_viewCount ) { + view_list%vidx% := SubStr(A_LoopReadLine, i + 1) + view_m%vidx% := m + view_v%vidx% := v + view_set := view_set . view_list%vidx% + vidx := vidx + 1 + } Else { + excluded_view_set := excluded_view_set . view_list%vidx% + Debug_logMessage("View (" . m . ", " . v . ") is no longer available (" . vidx . ")", 0) + } + } Else If (SubStr(A_LoopReadLine, 1, 7) = "Window ") { + wnds%widx% := SubStr(A_LoopReadLine, 8) + widx := widx + 1 + } + } + + ;Debug_logMessage("view_set: " . view_set, 1) + ;Debug_logMessage("excluded_view_set: " . excluded_view_set, 1) + + candidate_set := "" + + ; Scan through all defined windows. Create a candidate set of windows based on whether the properties of existing windows match. + Loop, % (widx - 1) { + StringSplit, items, wnds%A_Index%, `; + If (items0 < 9) { + Debug_logMessage("Window '" . wnds%A_Index% . "' could not be processed due to parse error", 0) + Continue + } + + i := 1 + i := items%i% + j := 2 + + detectHidden := A_DetectHiddenWindows + DetectHiddenWindows, On + WinGet, wndPName, ProcessName, ahk_id %i% + DetectHiddenWindows, %detectHidden% + If Not ( items%j% = wndPName ) { + Debug_logMessage("Window ahk_id " . i . " process '" . wndPName . "' doesn't match expected '" . items%j% . "', forgetting this window", 0) + Continue + } + + j := 8 + isManaged := items%j% + + ; If Managed + If ( items%j% ) { + If ( InStr(view_set, i) = 0) { + If ( InStr(excluded_view_set, i) ) + Debug_logMessage("Window ahk_id " . i . " is being ignored because it no longer belongs to an active view", 0) + Else + Debug_logMessage("Window ahk_id " . i . " is being ignored because it doesn't exist in any views", 0) + Continue + } + } + + ; Set up the window. + + j := 3 + m := items%j% + j := 4 + v := items%j% + j := 5 + isFloating := items%j% + j := 6 + isDecorated := items%j% + j := 7 + hideTitle := items%j% + + Manager__setWinProperties(i, isManaged, m, v, isDecorated, isFloating, hideTitle ) + ;Window_hide(i) + + candidate_set := candidate_set . i . ";" + } + + ;Debug_logMessage("candidate_set: " . candidate_set, 1) + + ; Set up all views. Must filter the window list by those from the candidate set. + Loop, % (vidx - 1) { + StringSplit, items, view_list%A_Index%, `; + view_set := "" + Loop, % (items0 - 1) { + If ( InStr(candidate_set, items%A_Index% ) > 0 ) + view_set := view_set . items%A_Index% . ";" + } + view_var := "View_#" . view_m%A_Index% . "_#" . view_v%A_Index% . "_wndIds" + %view_var% := view_set + } +} + +Manager_saveState() { + Critical + Global Config_filePath, Config_viewCount, Main_autoLayout, Main_autoWindowState, Manager_layoutDirty, Manager_monitorCount, Manager_windowsDirty + + Debug_logMessage("DEBUG[2] Manager_saveState", 2) + + ;; @TODO: Check for changes to the layout. + ;If Manager_layoutDirty { + Debug_logMessage("DEBUG[2] Manager_saveState: " Main_autoLayout, 2) + Config_saveSession(Config_filePath, Main_autoLayout) + Manager_layoutDirty := 0 + ;} + + ;; @TODO: Check for changes to windows. + ;If Manager_windowsDirty { + Debug_logMessage("DEBUG[2] Manager_saveState: " Main_autoWindowState, 2) + Manager_saveWindowState(Main_autoWindowState, Manager_monitorCount, Config_viewCount) + Manager_windowsDirty := 0 + ;} +} + +Manager_saveWindowState(filename, nm, nv) { + Local allWndId0, allWndIds, detectHidden, wndPName, title, text, monitor, wndId, view, isManaged, isTitleHidden + + text := "; bug.n - tiling window management`n; @version " VERSION "`n`n" + + tmpfname := filename . ".tmp" + FileDelete, %tmpfname% + + ; Dump window ID and process name. If these two don't match an existing process, we won't try + ; to recover that window. + StringTrimRight, allWndIds, Manager_allWndIds, 1 + StringSplit, allWndId, allWndIds, `; + detectHidden := A_DetectHiddenWindows + DetectHiddenWindows, On + Loop, % allWndId0 { + wndId := allWndId%A_Index% + WinGet, wndPName, ProcessName, ahk_id %wndId% + ; Include title for informative reasons. + WinGetTitle, title, ahk_id %wndId% + + ; wndId;processName;Tags;Floating;Decorated;HideTitle;Managed;Title + + isManaged := InStr(Manager_managedWndIds, wndId . ";") + isTitleHidden := InStr(Bar_hideTitleWndIds, wndId . ";") + + text .= "Window " . wndId . ";" . wndPName . ";" + If isManaged + text .= Window_#%wndId%_monitor . ";" . Window_#%wndId%_tags . ";" . Window_#%wndId%_isFloating . ";" . Window_#%wndId%_isDecorated . ";" + Else + text .= ";;;;" + text .= isTitleHidden . ";" . isManaged . ";" . title . "`n" + } + DetectHiddenWindows, %detectHidden% + + text .= "`n" + + ;; Dump window arrangements on every view. If some views or monitors have disappeared, leave their + ;; corresponding windows alone. + + Loop, % nm { + monitor := A_Index + Loop, % nv { + view := A_Index + ;; Dump all view window lists + text .= "View_#" . monitor . "_#" . view . "_wndIds=" . View_#%monitor%_#%view%_wndIds . "`n" + } + } + + FileAppend, %text%, %tmpfname% + If ErrorLevel { + If FileExist(tmpfname) + FileDelete, %tmpfname% + } Else + FileMove, %tmpfname%, %filename%, 1 +} + +Manager_setCursor(wndId) { + Local wndHeight, wndWidth, wndX, wndY + + If Config_mouseFollowsFocus { + If wndId { + WinGetPos, wndX, wndY, wndWidth, wndHeight, ahk_id %wndId% + DllCall("SetCursorPos", "Int", Round(wndX + wndWidth / 2), "Int", Round(wndY + wndHeight / 2)) + } Else + DllCall("SetCursorPos", "Int", Round(Monitor_#%Manager_aMonitor%_x + Monitor_#%Manager_aMonitor%_width / 2), "Int", Round(Monitor_#%Manager_aMonitor%_y + Monitor_#%Manager_aMonitor%_height / 2)) + } +} + +Manager_setViewMonitor(i, d = 0) { + Local aView, aWndId, v, wndIds + + aView := Monitor_#%Manager_aMonitor%_aView_#1 + If (Manager_monitorCount > 1) And View_#%Manager_aMonitor%_#%aView%_wndIds { + If (i = 0) + i := Manager_aMonitor + i := Manager_loop(i, d, 1, Manager_monitorCount) + v := Monitor_#%i%_aView_#1 + View_#%i%_#%v%_wndIds := View_#%Manager_aMonitor%_#%aView%_wndIds View_#%i%_#%v%_wndIds + + StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%aView%_wndIds, 1 + Loop, PARSE, wndIds, `; + { + Loop, % Config_viewCount { + StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, %A_LoopField%`;, + StringReplace, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, %A_LoopField%`;, + } + Window_#%A_LoopField%_monitor := i + Window_#%A_LoopField%_tags := 1 << v - 1 + } + View_arrange(Manager_aMonitor, aView) + Loop, % Config_viewCount { + Bar_updateView(Manager_aMonitor, A_Index) + } + + ;; Manually set the active monitor. + Manager_aMonitor := i + View_arrange(i, v) + WinGet, aWndId, ID, A + Manager_winActivate(aWndId) + Bar_updateView(i, v) + } +} + +Manager_setWindowBorders() +{ + Local ncm, ncmSize + + If Config_selBorderColor + { + SetFormat, Integer, hex + Manager_normBorderColor := DllCall("GetSysColor", "Int", 10) + SetFormat, Integer, d + DllCall("SetSysColors", "Int", 1, "Int*", 10, "UInt*", Config_selBorderColor) + } + If (Config_borderWidth > 0) Or (Config_borderPadding >= 0 And A_OSVersion = "WIN_VISTA") + { + ncmSize := VarSetCapacity(ncm, 4 * (A_OSVersion = "WIN_VISTA" ? 11 : 10) + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), 0) + NumPut(ncmSize, ncm, 0, "UInt") + DllCall("SystemParametersInfo", "UInt", 0x0029, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) + Manager_borderWidth := NumGet(ncm, 4, "Int") + Manager_borderPadding := NumGet(ncm, 40 + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), "Int") + If (Config_borderWidth > 0) + NumPut(Config_borderWidth, ncm, 4, "Int") + If (Config_borderPadding >= 0 And A_OSVersion = "WIN_VISTA") + NumPut(Config_borderPadding, ncm, 40 + 5 * (28 + 32 * (A_IsUnicode ? 2 : 1)), "Int") + DllCall("SystemParametersInfo", "UInt", 0x002a, "UInt", ncmSize, "UInt", &ncm, "UInt", 0) + } +} + +Manager_setWindowMonitor(i, d = 0) { + Local aWndId, v + + WinGet, aWndId, ID, A + If (Manager_monitorCount > 1 And InStr(Manager_managedWndIds, aWndId ";")) { + Loop, % Config_viewCount { + StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, %aWndId%`;, + StringReplace, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, %aWndId%`;, All + Bar_updateView(Manager_aMonitor, A_Index) + } + If Config_dynamicTiling + View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) + + ;; Manually set the active monitor. + If (i = 0) + i := Manager_aMonitor + Manager_aMonitor := Manager_loop(i, d, 1, Manager_monitorCount) + Window_#%aWndId%_monitor := Manager_aMonitor + v := Monitor_#%Manager_aMonitor%_aView_#1 + Window_#%aWndId%_tags := 1 << v - 1 + View_#%Manager_aMonitor%_#%v%_wndIds := aWndId ";" View_#%Manager_aMonitor%_#%v%_wndIds + View_setActiveWindow(Manager_aMonitor, v, aWndId) + If Config_dynamicTiling + View_arrange(Manager_aMonitor, v) + Manager_winActivate(aWndId) + Bar_updateView(Manager_aMonitor, v) + } +} + +Manager_sizeWindow() { + Local aWndId, SC_SIZE, WM_SYSCOMMAND + + WinGet, aWndId, ID, A + If InStr(Manager_managedWndIds, aWndId . ";") And Not Window_#%aWndId%_isFloating + View_toggleFloatingWindow(aWndId) + Window_set(aWndId, "Top", "") + + WM_SYSCOMMAND = 0x112 + SC_SIZE = 0xF000 + SendMessage, WM_SYSCOMMAND, SC_SIZE, , , ahk_id %aWndId% +} + +;; No windows are known to the system yet. +;; Try to do something smart with the initial layout. +Manager_initial_sync(doRestore) { + Local wndId, wndId0, wnd, wndX, wndY, wndW, wndH, x, y, m, len + + ;; Initialize lists + ;; Note that these variables make this function non-reentrant. + Loop, % Manager_monitorCount + Manager_initial_sync_m#%A_Index%_wndList := "" + + ;; Use saved window placement settings to first determine + ;; which monitor/view a window should be attached to. + If doRestore + Manager__restoreWindowState(Main_autoWindowState) + + ;; Check all remaining visible windows against the known windows + WinGet, wndId, List, , , + Loop, % wndId { + ;; Based on some analysis here, determine which monitors and layouts would best + ;; serve existing windows. Do not override configuration settings. + + ;; Which monitor is it on? + wnd := wndId%A_Index% + WinGetPos, wndX, wndY, wndW, wndH, ahk_id %wnd% + + x := wndX + wndW/2 + y := wndY + wndH/2 + + m := Monitor_get(x, y) + If m > 0 + Manager_initial_sync_m#%m%_wndList .= wndId%A_Index% ";" + + } + + Loop, % Manager_monitorCount { + m := A_Index + StringTrimRight, wndIds, Manager_initial_sync_m#%m%_wndList, 1 + StringSplit, wndId, wndIds, `; + Loop, % wndId0 + Manager_manage(m, 1, wndId%A_Index%) + } +} + +;; @todo: This constantly tries to re-add windows that are never going to be manageable. +;; Manager_manage should probably ignore all windows that are already in Manager_allWndIds. +;; The problem was, that i. a. claws-mail triggers Manager_sync, but the application window +;; would not be ready for being managed, i. e. class and title were not available. Therefore more +;; attempts were needed. +;; Perhaps this method can be refined by not adding any window to Manager_allWndIds, but only +;; those, which have at least a title or class. +Manager_sync(ByRef wndIds = "") +{ + Local a, flag, shownWndIds, v, visibleWndIds, wndId + a := 0 + + shownWndIds := "" + Loop, % Manager_monitorCount + { + v := Monitor_#%A_Index%_aView_#1 + shownWndIds .= View_#%A_Index%_#%v%_wndIds + } + ;; Check all visible windows against the known windows + visibleWndIds := "" + WinGet, wndId, List, , , + Loop, % wndId + { + If Not InStr(shownWndIds, wndId%A_Index% ";") + { + If Not InStr(Manager_managedWndIds, wndId%A_Index% ";") + { + flag := Manager_manage(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1, wndId%A_Index%) + If flag + a := 1 + } + Else If Not Window_isHung(wndId%A_Index%) + { + ;; This is a window that is already managed but was brought into focus by something. + ;; Maybe it would be useful to do something with it. + wndIds .= wndId%A_Index% ";" + } + } + visibleWndIds := visibleWndIds wndId%A_Index% ";" + } + + ;; @todo-future: Find out why this unmanage code exists and if it's still needed. + ;; check, if a window, that is known to be visible, is actually not visible + StringTrimRight, shownWndIds, shownWndIds, 1 + Loop, PARSE, shownWndIds, `; + { + If Not InStr(visibleWndIds, A_LoopField) + { + flag := Manager_unmanage(A_LoopField) + If (flag And a = 0) + a := -1 + } + } + + Return, a +} + +Manager_unmanage(wndId) { + Local a, aView + + aView := Monitor_#%Manager_aMonitor%_aView_#1 + + a := Window_#%wndId%_tags & 1 << aView - 1 + Loop, % Config_viewCount { + If (Window_#%wndId%_tags & 1 << A_Index - 1) { + StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, % wndId ";",, All + StringReplace, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, View_#%Manager_aMonitor%_#%A_Index%_aWndIds, % wndId ";",, All + Bar_updateView(Manager_aMonitor, A_Index) + } + } + Window_#%wndId%_monitor := + Window_#%wndId%_tags := + Window_#%wndId%_isDecorated := + Window_#%wndId%_isFloating := + Window_#%wndId%_area := + StringReplace, Bar_hideTitleWndIds, Bar_hideTitleWndIds, %wndId%`;, + StringReplace, Manager_allWndIds, Manager_allWndIds, %wndId%`;, + StringReplace, Manager_managedWndIds, Manager_managedWndIds, %wndId%`;, , All + + Return, a +} + +Manager_winActivate(wndId) { + Global Manager_aMonitor + + Manager_setCursor(wndId) + Debug_logMessage("DEBUG[1] Activating window: " wndId, 1) + If Not wndId { + wndId := WinExist("bug.n_BAR_" . Manager_aMonitor) + Debug_logMessage("DEBUG[1] Activating Desktop: " wndId, 1) + } + + If Window_activate(wndId) + Return, 1 + Else { + Bar_updateTitle() + Return 0 + } +} + +Manager_windowNotMaximized(width, height) { + Global + Return, (width < 0.99 * Monitor_#%Manager_aMonitor%_width Or height < 0.99 * Monitor_#%Manager_aMonitor%_height) +} + +Manager_activateViewByMouse(d) { + Local mousePositionX, mousePositionY, window, windowTitle + MouseGetPos, mousePositionX, mousePositionY, window + WinGetTitle windowTitle, ahk_id %Window% + if( InStr(windowTitle, "bug.n_BAR_") = 1 ) { + Monitor_activateView(0, d) + } +} + +Manager_toggleManage(wndId = 0) { + Local v, m, hideTitle, tags, isDecorated, isFloating + + If (wndId = 0) + WinGet, wndId, ID, A + + m := Manager_aMonitor + v := Monitor_#%Manager_aMonitor%_aView_#1 + + if (InStr(Manager_managedWndIds, wndId . ";")) { + hideTitle := InStr(Bar_hideTitleWndIds, wndId ";") + tags := Window_#%wndId%_tags + isDecorated := Window_#%wndId%_isDecorated + isFloating := Window_#%wndId%_isFloating + + Manager_unmanage(wndId) + Manager__setWinProperties(wndId, false, m, tags, isDecorated, isFloating, hideTitle) + } else { + Manager_unmanage(wndId) + Manager_managedWndIds .= wndId ";" + Window_#%wndId%_monitor := m + Window_#%wndId%_tags := v + Manager_manage(m, v, wndId) + View_addWindow(m, v, wndId) + } + View_arrange(m, v) +} \ No newline at end of file diff --git a/src/Monitor.ahk b/src/Monitor.ahk index bb6ed77..96e705b 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -1,373 +1,373 @@ -/* - bug.n -- tiling window management - Copyright (c) 2010-2019 Joshua Fuhs, joten - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - @license GNU General Public License version 3 - ../LICENSE.md or <http://www.gnu.org/licenses/> - - @version 9.1.0 -*/ - -Monitor_init(m, doRestore) { - Global - - Monitor_#%m%_aView_#1 := 1 - Monitor_#%m%_aView_#2 := 1 - Monitor_#%m%_showBar := Config_showBar - Monitor_#%m%_showTaskBar := Config_showTaskBar - Monitor_#%m%_taskBarClass := "" - Monitor_#%m%_taskBarPos := "" - Loop, % Config_viewCount - View_init(m, A_Index) - If doRestore - Config_restoreLayout(Main_autoLayout, m) - Else - Config_restoreLayout(Config_filePath, m) - SysGet, Monitor_#%m%_name, MonitorName, %m% - Monitor_getWorkArea(m) - Debug_logMessage("DEBUG[0] Monitor_init: #" . m . ", name: " . Monitor_#%m%_name . ", x: " . Monitor_#%m%_x . ", y: " . Monitor_#%m%_y . ", w: " . Monitor_#%m%_w . ", h: " . Monitor_#%m%_h . ".", 0) - If Not Monitor_#%m%_showTaskBar { - Monitor_#%m%_showTaskBar := True - Monitor_toggleTaskBar(m) - } - Bar_init(m) -} - -Monitor_activateView(i, d = 0) { - Local aMonitor, aView, aWndId, detectHidden, m, n, wndId, wndIds - - aMonitor := Manager_aMonitor - If (i = -1) - i := Monitor_#%aMonitor%_aView_#2 - Else If (i = 0) - i := Monitor_#%aMonitor%_aView_#1 - i := Manager_loop(i, d, 1, Config_viewCount) - - Debug_logMessage("DEBUG[1] Monitor_activateView; i: " . i . ", d: " . d . ", Manager_aMonitor: " . aMonitor . ", wndIds: " . View_#%Manager_aMonitor%_#%i%_wndIds, 1) - If (i <= 0) Or (i > Config_viewCount) Or Manager_hideShow - Return - ;; Re-arrange the windows on the active view. - If (i = Monitor_#%aMonitor%_aView_#1) { - View_arrange(aMonitor, i) - Return - } - - aView := Monitor_#%aMonitor%_aView_#1 - WinGet, aWndId, ID, A - If WinExist("ahk_id" aWndId) And InStr(View_#%aMonitor%_#%aView%_wndIds, aWndId ";") And Window_isProg(aWndId) - View_setActiveWindow(aMonitor, aView, aWndId) - - n := Config_syncMonitorViews - If (n = 1) - n := Manager_monitorCount - Else If (n < 1) - n := 1 - Loop, % n { - If (n = 1) - m := aMonitor - Else - m := A_Index - - Monitor_#%m%_aView_#2 := aView - Monitor_#%m%_aView_#1 := i - Manager_hideShow := True - SetWinDelay, 0 - StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 - Loop, PARSE, wndIds, `; - { - If A_LoopField And Not (Window_#%A_LoopField%_tags & (1 << i - 1)) - Window_hide(A_LoopField) - } - SetWinDelay, 10 - detectHidden := A_DetectHiddenWindows - DetectHiddenWindows, On - wndId := View_getActiveWindow(m, i) - If wndId - Window_set(wndId, "AlwaysOnTop", "On") - View_arrange(m, i) - DetectHiddenWindows, %detectHidden% - StringTrimRight, wndIds, View_#%m%_#%i%_wndIds, 1 - SetWinDelay, 0 - Loop, PARSE, wndIds, `; - { - Window_show(A_LoopField) - } - Window_set(wndId, "AlwaysOnTop", "Off") - SetWinDelay, 10 - Manager_hideShow := False - - Bar_updateView(m, aView) - Bar_updateView(m, i) - } - - wndId := View_getActiveWindow(aMonitor, i) - Manager_winActivate(wndId) -} - -Monitor_find(d, n) { - Local mName - - If (d < 0 Or d > 0) { - Loop, % n { - SysGet, mName, MonitorName, %A_Index% - If Not (mName = Monitor_#%A_Index%_name) - Return, A_Index - } - } - Return, 0 -} - -Monitor_get(x, y) -{ - Local m - - m := 0 - Loop, % Manager_monitorCount - { ;; Check if the window is on this monitor. - If (x >= Monitor_#%A_Index%_x && x <= Monitor_#%A_Index%_x+Monitor_#%A_Index%_width && y >= Monitor_#%A_Index%_y && y <= Monitor_#%A_Index%_y+Monitor_#%A_Index%_height) - { - m := A_Index - Break - } - } - - Return, m -} - -Monitor_getWorkArea(m) { - Local bHeight, bTop, x, y - Local monitor, monitorBottom, monitorLeft, monitorRight, monitorTop - Local wndClasses, wndHeight, wndId, wndWidth, wndX, wndY - - SysGet, monitor, Monitor, %m% - Debug_logMessage("DEBUG[0] Monitor_getWorkArea: #" . m . ", l: " . monitorLeft . ", r: " . monitorRight . ", t: " . monitorTop . ", b: " . monitorBottom . ".", 0) - - wndClasses := "Shell_TrayWnd;Shell_SecondaryTrayWnd" - ;; @TODO What about third and so forth TrayWnd? - If Config_bbCompatibility - wndClasses .= ";bbLeanBar;bbSlit;BBToolbar;SystemBarEx" - Loop, PARSE, wndClasses, `; - { - wndId := WinExist("ahk_class " A_LoopField) - If wndId { - WinGetPos, wndX, wndY, wndWidth, wndHeight, ahk_id %wndId% - x := wndX + wndWidth / 2 - y := wndY + wndHeight / 2 - If (x >= monitorLeft && x <= monitorRight && y >= monitorTop && y <= monitorBottom) { - If (A_LoopField = "Shell_TrayWnd") Or (A_LoopField = "Shell_SecondaryTrayWnd") - Monitor_#%m%_taskBarClass := A_LoopField - - Debug_logMessage("DEBUG[3] Monitor_getWorkArea: #" . m . ", window class: " . A_LoopField . ", x: " . wndX . ", y: " . wndY . ", w: " . wndWidth . ", h: " . wndHeight . ".", 3) - If (wndHeight < wndWidth) { - ;; Horizontal - If (wndY <= monitorTop) { - ;; Top - wndHeight += wndY - monitorTop - monitorTop += wndHeight - If (A_LoopField = "Shell_TrayWnd") Or (A_LoopField = "Shell_SecondaryTrayWnd") - Monitor_#%m%_taskBarPos := "top" - } Else { - ;; Bottom - wndHeight := monitorBottom - wndY - monitorBottom -= wndHeight - } - } Else { - ;; Vertical - If (wndX <= monitorLeft) { - ;; Left - wndWidth += wndX - monitorLeft += wndWidth - } Else { - ;; Right - wndWidth := monitorRight - wndX - monitorRight -= wndWidth - } - } - } - } - } - bHeight := Round(Bar_height / Config_scalingFactor) - bTop := 0 - If (Config_verticalBarPos = "top") Or (Config_verticalBarPos = "tray") And Not Monitor_#%m%_taskBarClass { - bTop := monitorTop - If Monitor_#%m%_showBar - monitorTop += bHeight - } Else If (Config_verticalBarPos = "bottom") { - bTop := monitorBottom - bHeight - If Monitor_#%m%_showBar - monitorBottom -= bHeight - } - - Monitor_#%m%_height := monitorBottom - monitorTop - Monitor_#%m%_width := monitorRight - monitorLeft - Monitor_#%m%_x := monitorLeft - Monitor_#%m%_y := monitorTop - Monitor_#%m%_barY := bTop - - Monitor_setWorkArea(monitorLeft, monitorTop, monitorRight, monitorBottom) -} - -Monitor_moveToIndex(m, n) { - Global - - Monitor_#%n%_aView_#1 := Monitor_#%m%_aView_#1 - Monitor_#%n%_aView_#2 := Monitor_#%m%_aView_#2 - Monitor_#%n%_name := Monitor_#%m%_name - Monitor_#%n%_showBar := Monitor_#%m%_showBar - Monitor_#%n%_showTaskBar := Monitor_#%m%_showTaskBar - Monitor_#%n%_taskBarClass := Monitor_#%m%_taskBarClass - Monitor_#%n%_taskBarPos := Monitor_#%m%_taskBarPos - Monitor_#%n%_height := Monitor_#%m%_height - Monitor_#%n%_width := Monitor_#%m%_width - Monitor_#%n%_x := Monitor_#%m%_x - Monitor_#%n%_y := Monitor_#%m%_y - Monitor_#%n%_barY := Monitor_#%m%_barY - Loop, % Config_viewCount - View_moveToIndex(m, A_Index, n, A_Index) -} - -Monitor_setWindowTag(i, d = 0) { - Local aView, aWndId, wndId - - If (i = 0) - i := Monitor_#%Manager_aMonitor%_aView_#1 - If Not (i = 10) - i := Manager_loop(i, d, 1, Config_viewCount) - - WinGet, aWndId, ID, A - If InStr(Manager_managedWndIds, aWndId ";") And (i > 0) And (i <= Config_viewCount Or i = 10) { - If (i = 10) { - Loop, % Config_viewCount { - If Not (Window_#%aWndId%_tags & (1 << A_Index - 1)) { - View_#%Manager_aMonitor%_#%A_Index%_wndIds := aWndId ";" View_#%Manager_aMonitor%_#%A_Index%_wndIds - View_setActiveWindow(Manager_aMonitor, A_Index, aWndId) - Bar_updateView(Manager_aMonitor, A_Index) - Window_#%aWndId%_tags += 1 << A_Index - 1 - } - } - } Else { - Loop, % Config_viewCount { - If Not (A_index = i) { - StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, %aWndId%`;, - View_setActiveWindow(Manager_aMonitor, A_Index, 0) - Bar_updateView(Manager_aMonitor, A_Index) - } - } - - If Not (Window_#%aWndId%_tags & (1 << i - 1)) - View_#%Manager_aMonitor%_#%i%_wndIds := aWndId ";" View_#%Manager_aMonitor%_#%i%_wndIds - View_setActiveWindow(Manager_aMonitor, i, aWndId) - Window_#%aWndId%_tags := 1 << i - 1 - - aView := Monitor_#%Manager_aMonitor%_aView_#1 - If Not (i = aView) { - Manager_hideShow := True - wndId := SubStr(View_#%Manager_aMonitor%_#%aView%_wndIds, 1, InStr(View_#%Manager_aMonitor%_#%aView%_wndIds, ";") - 1) - Manager_winActivate(wndId) - Manager_hideShow := False - If Config_viewFollowsTagged - Monitor_activateView(i) - Else { - Manager_hideShow := True - Window_hide(aWndId) - Manager_hideShow := False - If Config_dynamicTiling - View_arrange(Manager_aMonitor, aView) - Bar_updateView(Manager_aMonitor, i) - } - } - } - } -} - -Monitor_setWorkArea(left, top, right, bottom) { - VarSetCapacity(area, 16) - NumPut(left, area, 0) - NumPut(top, area, 4) - NumPut(right, area, 8) - NumPut(bottom, area, 12) - DllCall("SystemParametersInfo", UInt, 0x2F, UInt, 0, UInt, &area, UInt, 0) ; 0x2F = SPI_SETWORKAREA -} -;; flashkid: Send SetWorkArea to second Monitor (http://www.autohotkey.com/board/topic/42564-send-setworkarea-to-second-monitor/) - -Monitor_toggleBar() -{ - Global - - Monitor_#%Manager_aMonitor%_showBar := Not Monitor_#%Manager_aMonitor%_showBar - Bar_toggleVisibility(Manager_aMonitor) - Monitor_getWorkArea(Manager_aMonitor) - View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) - Manager_winActivate(Bar_aWndId) -} - -Monitor_toggleNotifyIconOverflowWindow() { - Static wndId - - If Not WinExist("ahk_class NotifyIconOverflowWindow") { - WinGet, wndId, ID, A - detectHidden := A_DetectHiddenWindows - DetectHiddenWindows, On - WinShow, ahk_class NotifyIconOverflowWindow - WinActivate, ahk_class NotifyIconOverflowWindow - DetectHiddenWindows, %detectHidden% - } Else { - WinHide, ahk_class NotifyIconOverflowWindow - WinActivate, ahk_id %wndId% - } -} - -Monitor_toggleTaskBar(m := 0) { - Global - - m := m ? m : Manager_aMonitor - If Monitor_#%m%_taskBarClass { - Monitor_#%m%_showTaskBar := Not Monitor_#%m%_showTaskBar - Manager_hideShow := True - If Not Monitor_#%m%_showTaskBar { - WinHide, Start ahk_class Button - WinHide, % "ahk_class " Monitor_#%m%_taskBarClass - } Else { - WinShow, Start ahk_class Button - WinShow, % "ahk_class " Monitor_#%m%_taskBarClass - } - Manager_hideShow := False - Monitor_getWorkArea(m) - Bar_move(m) - View_arrange(m, Monitor_#%m%_aView_#1) - } -} - -Monitor_toggleWindowTag(i, d = 0) { - Local aWndId, wndId - - WinGet, aWndId, ID, A - If (InStr(Manager_managedWndIds, aWndId ";") And i >= 0 And i <= Config_viewCount) { - If (Window_#%aWndId%_tags & (1 << i - 1)) { - If Not ((Window_#%aWndId%_tags - (1 << i - 1)) = 0) { - Window_#%aWndId%_tags -= 1 << i - 1 - StringReplace, View_#%Manager_aMonitor%_#%i%_wndIds, View_#%Manager_aMonitor%_#%i%_wndIds, %aWndId%`;, - Bar_updateView(Manager_aMonitor, i) - If (i = Monitor_#%Manager_aMonitor%_aView_#1) { - Manager_hideShow := True - Window_hide(aWndId) - Manager_hideShow := False - wndId := SubStr(View_#%Manager_aMonitor%_#%i%_wndIds, 1, InStr(View_#%Manager_aMonitor%_#%i%_wndIds, ";")-1) - Manager_winActivate(wndId) - If Config_dynamicTiling - View_arrange(Manager_aMonitor, i) - } - } - } Else { - View_#%Manager_aMonitor%_#%i%_wndIds := aWndId ";" View_#%Manager_aMonitor%_#%i%_wndIds - View_setActiveWindow(Manager_aMonitor, i, aWndId) - Bar_updateView(Manager_aMonitor, i) - Window_#%aWndId%_tags += 1 << i - 1 - } - } -} +/* + bug.n -- tiling window management + Copyright (c) 2010-2019 Joshua Fuhs, joten + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + @license GNU General Public License version 3 + ../LICENSE.md or <http://www.gnu.org/licenses/> + + @version 9.1.0 +*/ + +Monitor_init(m, doRestore) { + Global + + Monitor_#%m%_aView_#1 := 1 + Monitor_#%m%_aView_#2 := 1 + Monitor_#%m%_showBar := Config_showBar + Monitor_#%m%_showTaskBar := Config_showTaskBar + Monitor_#%m%_taskBarClass := "" + Monitor_#%m%_taskBarPos := "" + Loop, % Config_viewCount + View_init(m, A_Index) + If doRestore + Config_restoreLayout(Main_autoLayout, m) + Else + Config_restoreLayout(Config_filePath, m) + SysGet, Monitor_#%m%_name, MonitorName, %m% + Monitor_getWorkArea(m) + Debug_logMessage("DEBUG[0] Monitor_init: #" . m . ", name: " . Monitor_#%m%_name . ", x: " . Monitor_#%m%_x . ", y: " . Monitor_#%m%_y . ", w: " . Monitor_#%m%_w . ", h: " . Monitor_#%m%_h . ".", 0) + If Not Monitor_#%m%_showTaskBar { + Monitor_#%m%_showTaskBar := True + Monitor_toggleTaskBar(m) + } + Bar_init(m) +} + +Monitor_activateView(i, d = 0) { + Local aMonitor, aView, aWndId, detectHidden, m, n, wndId, wndIds + + aMonitor := Manager_aMonitor + If (i = -1) + i := Monitor_#%aMonitor%_aView_#2 + Else If (i = 0) + i := Monitor_#%aMonitor%_aView_#1 + i := Manager_loop(i, d, 1, Config_viewCount) + + Debug_logMessage("DEBUG[1] Monitor_activateView; i: " . i . ", d: " . d . ", Manager_aMonitor: " . aMonitor . ", wndIds: " . View_#%Manager_aMonitor%_#%i%_wndIds, 1) + If (i <= 0) Or (i > Config_viewCount) Or Manager_hideShow + Return + ;; Re-arrange the windows on the active view. + If (i = Monitor_#%aMonitor%_aView_#1) { + View_arrange(aMonitor, i) + Return + } + + aView := Monitor_#%aMonitor%_aView_#1 + WinGet, aWndId, ID, A + If WinExist("ahk_id" aWndId) And InStr(View_#%aMonitor%_#%aView%_wndIds, aWndId ";") And Window_isProg(aWndId) + View_setActiveWindow(aMonitor, aView, aWndId) + + n := Config_syncMonitorViews + If (n = 1) + n := Manager_monitorCount + Else If (n < 1) + n := 1 + Loop, % n { + If (n = 1) + m := aMonitor + Else + m := A_Index + + Monitor_#%m%_aView_#2 := aView + Monitor_#%m%_aView_#1 := i + Manager_hideShow := True + SetWinDelay, 0 + StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 + Loop, PARSE, wndIds, `; + { + If A_LoopField And Not (Window_#%A_LoopField%_tags & (1 << i - 1)) + Window_hide(A_LoopField) + } + SetWinDelay, 10 + detectHidden := A_DetectHiddenWindows + DetectHiddenWindows, On + wndId := View_getActiveWindow(m, i) + If wndId + Window_set(wndId, "AlwaysOnTop", "On") + View_arrange(m, i) + DetectHiddenWindows, %detectHidden% + StringTrimRight, wndIds, View_#%m%_#%i%_wndIds, 1 + SetWinDelay, 0 + Loop, PARSE, wndIds, `; + { + Window_show(A_LoopField) + } + Window_set(wndId, "AlwaysOnTop", "Off") + SetWinDelay, 10 + Manager_hideShow := False + + Bar_updateView(m, aView) + Bar_updateView(m, i) + } + + wndId := View_getActiveWindow(aMonitor, i) + Manager_winActivate(wndId) +} + +Monitor_find(d, n) { + Local mName + + If (d < 0 Or d > 0) { + Loop, % n { + SysGet, mName, MonitorName, %A_Index% + If Not (mName = Monitor_#%A_Index%_name) + Return, A_Index + } + } + Return, 0 +} + +Monitor_get(x, y) +{ + Local m + + m := 0 + Loop, % Manager_monitorCount + { ;; Check if the window is on this monitor. + If (x >= Monitor_#%A_Index%_x && x <= Monitor_#%A_Index%_x+Monitor_#%A_Index%_width && y >= Monitor_#%A_Index%_y && y <= Monitor_#%A_Index%_y+Monitor_#%A_Index%_height) + { + m := A_Index + Break + } + } + + Return, m +} + +Monitor_getWorkArea(m) { + Local bHeight, bTop, x, y + Local monitor, monitorBottom, monitorLeft, monitorRight, monitorTop + Local wndClasses, wndHeight, wndId, wndWidth, wndX, wndY + + SysGet, monitor, Monitor, %m% + Debug_logMessage("DEBUG[0] Monitor_getWorkArea: #" . m . ", l: " . monitorLeft . ", r: " . monitorRight . ", t: " . monitorTop . ", b: " . monitorBottom . ".", 0) + + wndClasses := "Shell_TrayWnd;Shell_SecondaryTrayWnd" + ;; @TODO What about third and so forth TrayWnd? + If Config_bbCompatibility + wndClasses .= ";bbLeanBar;bbSlit;BBToolbar;SystemBarEx" + Loop, PARSE, wndClasses, `; + { + wndId := WinExist("ahk_class " A_LoopField) + If wndId { + WinGetPos, wndX, wndY, wndWidth, wndHeight, ahk_id %wndId% + x := wndX + wndWidth / 2 + y := wndY + wndHeight / 2 + If (x >= monitorLeft && x <= monitorRight && y >= monitorTop && y <= monitorBottom) { + If (A_LoopField = "Shell_TrayWnd") Or (A_LoopField = "Shell_SecondaryTrayWnd") + Monitor_#%m%_taskBarClass := A_LoopField + + Debug_logMessage("DEBUG[3] Monitor_getWorkArea: #" . m . ", window class: " . A_LoopField . ", x: " . wndX . ", y: " . wndY . ", w: " . wndWidth . ", h: " . wndHeight . ".", 3) + If (wndHeight < wndWidth) { + ;; Horizontal + If (wndY <= monitorTop) { + ;; Top + wndHeight += wndY - monitorTop + monitorTop += wndHeight + If (A_LoopField = "Shell_TrayWnd") Or (A_LoopField = "Shell_SecondaryTrayWnd") + Monitor_#%m%_taskBarPos := "top" + } Else { + ;; Bottom + wndHeight := monitorBottom - wndY + monitorBottom -= wndHeight + } + } Else { + ;; Vertical + If (wndX <= monitorLeft) { + ;; Left + wndWidth += wndX + monitorLeft += wndWidth + } Else { + ;; Right + wndWidth := monitorRight - wndX + monitorRight -= wndWidth + } + } + } + } + } + bHeight := Round(Bar_height / Config_scalingFactor) + bTop := 0 + If (Config_verticalBarPos = "top") Or (Config_verticalBarPos = "tray") And Not Monitor_#%m%_taskBarClass { + bTop := monitorTop + If Monitor_#%m%_showBar + monitorTop += bHeight + } Else If (Config_verticalBarPos = "bottom") { + bTop := monitorBottom - bHeight + If Monitor_#%m%_showBar + monitorBottom -= bHeight + } + + Monitor_#%m%_height := monitorBottom - monitorTop + Monitor_#%m%_width := monitorRight - monitorLeft + Monitor_#%m%_x := monitorLeft + Monitor_#%m%_y := monitorTop + Monitor_#%m%_barY := bTop + + Monitor_setWorkArea(monitorLeft, monitorTop, monitorRight, monitorBottom) +} + +Monitor_moveToIndex(m, n) { + Global + + Monitor_#%n%_aView_#1 := Monitor_#%m%_aView_#1 + Monitor_#%n%_aView_#2 := Monitor_#%m%_aView_#2 + Monitor_#%n%_name := Monitor_#%m%_name + Monitor_#%n%_showBar := Monitor_#%m%_showBar + Monitor_#%n%_showTaskBar := Monitor_#%m%_showTaskBar + Monitor_#%n%_taskBarClass := Monitor_#%m%_taskBarClass + Monitor_#%n%_taskBarPos := Monitor_#%m%_taskBarPos + Monitor_#%n%_height := Monitor_#%m%_height + Monitor_#%n%_width := Monitor_#%m%_width + Monitor_#%n%_x := Monitor_#%m%_x + Monitor_#%n%_y := Monitor_#%m%_y + Monitor_#%n%_barY := Monitor_#%m%_barY + Loop, % Config_viewCount + View_moveToIndex(m, A_Index, n, A_Index) +} + +Monitor_setWindowTag(i, d = 0) { + Local aView, aWndId, wndId + + If (i = 0) + i := Monitor_#%Manager_aMonitor%_aView_#1 + If Not (i = 10) + i := Manager_loop(i, d, 1, Config_viewCount) + + WinGet, aWndId, ID, A + If InStr(Manager_managedWndIds, aWndId ";") And (i > 0) And (i <= Config_viewCount Or i = 10) { + If (i = 10) { + Loop, % Config_viewCount { + If Not (Window_#%aWndId%_tags & (1 << A_Index - 1)) { + View_#%Manager_aMonitor%_#%A_Index%_wndIds := aWndId ";" View_#%Manager_aMonitor%_#%A_Index%_wndIds + View_setActiveWindow(Manager_aMonitor, A_Index, aWndId) + Bar_updateView(Manager_aMonitor, A_Index) + Window_#%aWndId%_tags += 1 << A_Index - 1 + } + } + } Else { + Loop, % Config_viewCount { + If Not (A_index = i) { + StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, %aWndId%`;, + View_setActiveWindow(Manager_aMonitor, A_Index, 0) + Bar_updateView(Manager_aMonitor, A_Index) + } + } + + If Not (Window_#%aWndId%_tags & (1 << i - 1)) + View_#%Manager_aMonitor%_#%i%_wndIds := aWndId ";" View_#%Manager_aMonitor%_#%i%_wndIds + View_setActiveWindow(Manager_aMonitor, i, aWndId) + Window_#%aWndId%_tags := 1 << i - 1 + + aView := Monitor_#%Manager_aMonitor%_aView_#1 + If Not (i = aView) { + Manager_hideShow := True + wndId := SubStr(View_#%Manager_aMonitor%_#%aView%_wndIds, 1, InStr(View_#%Manager_aMonitor%_#%aView%_wndIds, ";") - 1) + Manager_winActivate(wndId) + Manager_hideShow := False + If Config_viewFollowsTagged + Monitor_activateView(i) + Else { + Manager_hideShow := True + Window_hide(aWndId) + Manager_hideShow := False + If Config_dynamicTiling + View_arrange(Manager_aMonitor, aView) + Bar_updateView(Manager_aMonitor, i) + } + } + } + } +} + +Monitor_setWorkArea(left, top, right, bottom) { + VarSetCapacity(area, 16) + NumPut(left, area, 0) + NumPut(top, area, 4) + NumPut(right, area, 8) + NumPut(bottom, area, 12) + DllCall("SystemParametersInfo", UInt, 0x2F, UInt, 0, UInt, &area, UInt, 0) ; 0x2F = SPI_SETWORKAREA +} +;; flashkid: Send SetWorkArea to second Monitor (http://www.autohotkey.com/board/topic/42564-send-setworkarea-to-second-monitor/) + +Monitor_toggleBar() +{ + Global + + Monitor_#%Manager_aMonitor%_showBar := Not Monitor_#%Manager_aMonitor%_showBar + Bar_toggleVisibility(Manager_aMonitor) + Monitor_getWorkArea(Manager_aMonitor) + View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) + Manager_winActivate(Bar_aWndId) +} + +Monitor_toggleNotifyIconOverflowWindow() { + Static wndId + + If Not WinExist("ahk_class NotifyIconOverflowWindow") { + WinGet, wndId, ID, A + detectHidden := A_DetectHiddenWindows + DetectHiddenWindows, On + WinShow, ahk_class NotifyIconOverflowWindow + WinActivate, ahk_class NotifyIconOverflowWindow + DetectHiddenWindows, %detectHidden% + } Else { + WinHide, ahk_class NotifyIconOverflowWindow + WinActivate, ahk_id %wndId% + } +} + +Monitor_toggleTaskBar(m := 0) { + Global + + m := m ? m : Manager_aMonitor + If Monitor_#%m%_taskBarClass { + Monitor_#%m%_showTaskBar := Not Monitor_#%m%_showTaskBar + Manager_hideShow := True + If Not Monitor_#%m%_showTaskBar { + WinHide, Start ahk_class Button + WinHide, % "ahk_class " Monitor_#%m%_taskBarClass + } Else { + WinShow, Start ahk_class Button + WinShow, % "ahk_class " Monitor_#%m%_taskBarClass + } + Manager_hideShow := False + Monitor_getWorkArea(m) + Bar_move(m) + View_arrange(m, Monitor_#%m%_aView_#1) + } +} + +Monitor_toggleWindowTag(i, d = 0) { + Local aWndId, wndId + + WinGet, aWndId, ID, A + If (InStr(Manager_managedWndIds, aWndId ";") And i >= 0 And i <= Config_viewCount) { + If (Window_#%aWndId%_tags & (1 << i - 1)) { + If Not ((Window_#%aWndId%_tags - (1 << i - 1)) = 0) { + Window_#%aWndId%_tags -= 1 << i - 1 + StringReplace, View_#%Manager_aMonitor%_#%i%_wndIds, View_#%Manager_aMonitor%_#%i%_wndIds, %aWndId%`;, + Bar_updateView(Manager_aMonitor, i) + If (i = Monitor_#%Manager_aMonitor%_aView_#1) { + Manager_hideShow := True + Window_hide(aWndId) + Manager_hideShow := False + wndId := SubStr(View_#%Manager_aMonitor%_#%i%_wndIds, 1, InStr(View_#%Manager_aMonitor%_#%i%_wndIds, ";")-1) + Manager_winActivate(wndId) + If Config_dynamicTiling + View_arrange(Manager_aMonitor, i) + } + } + } Else { + View_#%Manager_aMonitor%_#%i%_wndIds := aWndId ";" View_#%Manager_aMonitor%_#%i%_wndIds + View_setActiveWindow(Manager_aMonitor, i, aWndId) + Bar_updateView(Manager_aMonitor, i) + Window_#%aWndId%_tags += 1 << i - 1 + } + } +} diff --git a/src/ResourceMonitor.ahk b/src/ResourceMonitor.ahk index da56044..1c6675c 100644 --- a/src/ResourceMonitor.ahk +++ b/src/ResourceMonitor.ahk @@ -1,191 +1,191 @@ -/* - bug.n -- tiling window management - Copyright (c) 2010-2019 Joshua Fuhs, joten - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - @license GNU General Public License version 3 - ../LICENSE.md or <http://www.gnu.org/licenses/> - - @version 9.1.0 -*/ - -ResourceMonitor_init() { - Global Config_readinDiskLoad, Config_readinNetworkLoad, ResourceMonitor_hDrive - - If Config_readinDiskLoad - ResourceMonitor_hDrive := DllCall("CreateFile", "Str", "\\.\PhysicalDrive0", "UInt", 0, "UInt", 3, "UInt", 0, "UInt", 3, "UInt", 0, "UInt", 0) - ;; This call may lead to bug.n hanging (bug 019005). - If Config_readinNetworkLoad - ResourceMonitor_getNetworkInterface() -} - -ResourceMonitor_cleanup() { - Global Config_readinDiskLoad, ResourceMonitor_hDrive - - If Config_readinDiskLoad - DllCall("CloseHandle", "UInt", ResourceMonitor_hDrive) ;; used in ResourceMonitor_getDiskLoad -} - -ResourceMonitor_bytesToString(b) { - If (b > 1047527424) { - b /= 1024 * 1024 * 1024 - unit := "GB" - } Else If (b > 1022976) { - b /= 1024 * 1024 - unit := "MB" - } Else If (b > 999) { - b /= 1024 - unit := "kB" - } Else { - unit := " B" - } - b := Round(b, 1) - If (b > 99.9 Or unit = " B") - b := Round(b, 0) - Return, SubStr(" " b, -3) . unit -} - -ResourceMonitor_getBatteryStatus(ByRef batteryLifePercent, ByRef acLineStatus) { - VarSetCapacity(powerStatus, (1 + 1 + 1 + 1 + 4 + 4)) - success := DllCall("GetSystemPowerStatus", "UInt", &powerStatus) - If (ErrorLevel != 0 Or success = 0) { - MsgBox 16, Power Status, Can't get the power status... - Return - } - acLineStatus := NumGet(powerStatus, 0, "Char") - batteryLifePercent := NumGet(powerStatus, 2, "Char") - - If acLineStatus = 0 - acLineStatus = off - Else If acLineStatus = 1 - acLineStatus = on - Else If acLineStatus = 255 - acLineStatus = ? - - If batteryLifePercent = 255 - batteryLifePercent = ??? -} -;; PhiLho: AC/Battery status (http://www.autohotkey.com/forum/topic7633.html) - -ResourceMonitor_getDiskLoad(ByRef readLoad, ByRef writeLoad) { - Global ResourceMonitor_hDrive - Static oldReadCount, oldWriteCount - - nReturn := oldReadCount := oldWriteCount := 0 - dpSize := 5 * 8 + 4 + 4 + 4 + 4 + 8 + 4 + 8 * (A_IsUnicode ? 2 : 1) + 12 ;; 88? - VarSetCapacity(dp, dpSize) - DllCall("DeviceIoControl", "UInt", ResourceMonitor_hDrive, "UInt", 0x00070020, "UInt", 0, "UInt", 0, "UInt", &dp, "UInt", dpSize, "UIntP", nReturn, "UInt", 0) ;; IOCTL_DISK_PERFORMANCE - - newReadCount := NumGet(dp, 40) - newWriteCount := NumGet(dp, 44) - readLoad := SubStr(" " Round((1 - 1 / (1 + newReadCount - oldReadCount)) * 100), -2) - writeLoad := SubStr(" " Round((1 - 1 / (1 + newWriteCount - oldWriteCount)) * 100), -2) - oldReadCount := newReadCount - oldWriteCount := newWriteCount -} -;; fures: System + Network monitor - with net history graph (http://www.autohotkey.com/community/viewtopic.php?p=260329) -;; SKAN: HDD Activity Monitoring LED (http://www.autohotkey.com/community/viewtopic.php?p=113890&sid=64d9824fdf252697ff4d5026faba91f8#p113890) - -ResourceMonitor_getMemoryUsage() { - VarSetCapacity(memoryStatus, 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4) - DllCall("kernel32.dll\GlobalMemoryStatus", "UInt", &memoryStatus) - Return, SubStr(" " Round(*(&memoryStatus + 4)), -2) ;; LS byte is enough, 0..100 -} -;; fures: System + Network monitor - with net history graph (http://www.autohotkey.com/community/viewtopic.php?p=260329) - -ResourceMonitor_getNetworkInterface() { - Global Config_readinNetworkLoad, ResourceMonitor_networkInterface - - objWMIService := ComObjGet("winmgmts:{impersonationLevel=impersonate}!\\" . A_ComputerName . "\root\cimv2") - WQLQuery := "SELECT * FROM Win32_PerfFormattedData_Tcpip_NetworkInterface WHERE Name LIKE '%" . Config_readinNetworkLoad . "%'" - ResourceMonitor_networkInterface := objWMIService.ExecQuery(WQLQuery).ItemIndex(0) -} -;; Pillus: System monitor (HDD/Wired/Wireless) using keyboard LEDs (http://www.autohotkey.com/board/topic/65308-system-monitor-hddwiredwireless-using-keyboard-leds/) - -ResourceMonitor_getNetworkLoad(ByRef upLoad, ByRef dnLoad) { - Global ResourceMonitor_networkInterface - - ResourceMonitor_networkInterface.Refresh_ - dnLoad := ResourceMonitor_bytesToString(ResourceMonitor_networkInterface.BytesReceivedPerSec) . "/s" - upLoad := ResourceMonitor_bytesToString(ResourceMonitor_networkInterface.BytesSentPerSec) . "/s" -} -;; Pillus: System monitor (HDD/Wired/Wireless) using keyboard LEDs (http://www.autohotkey.com/board/topic/65308-system-monitor-hddwiredwireless-using-keyboard-leds/) - -ResourceMonitor_getSystemTimes() { - ;; Total CPU Load - Static oldIdleTime, oldKrnlTime, oldUserTime - Static newIdleTime, newKrnlTime, newUserTime - - newIdleTime := newKrnlTime := newUserTime := 0 - oldIdleTime := newIdleTime - oldKrnlTime := newKrnlTime - oldUserTime := newUserTime - - DllCall("GetSystemTimes", "Int64P", newIdleTime, "Int64P", newKrnlTime, "Int64P", newUserTime) - sysTime := Round((1 - (newIdleTime - oldIdleTime) / (newKrnlTime - oldKrnlTime+newUserTime - oldUserTime)) * 100) - Return, sysTime ;; system time in percent -} -;; Sean: CPU LoadTimes (http://www.autohotkey.com/forum/topic18913.html) - -ResourceMonitor_getText() { - Global Config_readinCpu, Config_readinDiskLoad, Config_readinMemoryUsage, Config_readinNetworkLoad - - text := "" - If Config_readinCpu - text .= " CPU: " ResourceMonitor_getSystemTimes() "% " - If Config_readinMemoryUsage { - If (Config_readinCpu) - text .= "|" - text .= " RAM: " ResourceMonitor_getMemoryUsage() "% " - } - If Config_readinDiskLoad { - If (Config_readinCpu Or Config_readinMemoryUsage) - text .= "|" - ResourceMonitor_getDiskLoad(rLoad, wLoad) - text .= " Dr: " rLoad "% | Dw: " wLoad "% " - } - If Config_readinNetworkLoad { - If (Config_readinCpu Or Config_readinMemoryUsage Or Config_readinDiskLoad) - text .= "|" - ResourceMonitor_getNetworkLoad(upLoad, dnLoad) - text .= " UP: " upLoad " | dn: " dnLoad " " - } - - Return, text -} - -ResourceMonitor_getSystemTimes2(ByRef IdleTime) { - DllCall("GetSystemTimes", "Int64P", IdleTime, "Int64P", KernelTime, "Int64P", UserTime) - Return KernelTime + UserTime -} - -ResourceMonitor_getCpuLoad(period := 500) { - total := ResourceMonitor_getSystemTimes2(idle) - Sleep, % period - total2 := ResourceMonitor_getSystemTimes2(idle2) - Return 100*(1 - (idle2 - idle)/(total2 - total)) -} - -ResourceMonitor_getCpuText() { - Return, Floor(ResourceMonitor_getCpuLoad()) . "%" -} - -ResourceMonitor_GlobalMemoryStatusEx() -{ - static MSEX, init := NumPut(VarSetCapacity(MSEX, 64, 0), MSEX, "uint") - if !(DllCall("GlobalMemoryStatusEx", "ptr", &MSEX)) - throw Exception("Call to GlobalMemoryStatusEx failed: " A_LastError, -1) - return { MemoryLoad: NumGet(MSEX, 4, "uint"), TotalPhys: NumGet(MSEX, 8, "uint64"), AvailPhys: NumGet(MSEX, 16, "uint64") } -} - -ResourceMonitor_getRamText() { - GMSEx := ResourceMonitor_GlobalMemoryStatusEx() - TotalMem := GMSEx.TotalPhys - AvailMem := GMSEx.AvailPhys - mem := RegExReplace(Floor((TotalMem - AvailMem) / 1048576), "(\d)(?=(?:\d{3})+(?:\.|$))", "$1,") - Return, mem . " MB" +/* + bug.n -- tiling window management + Copyright (c) 2010-2019 Joshua Fuhs, joten + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + @license GNU General Public License version 3 + ../LICENSE.md or <http://www.gnu.org/licenses/> + + @version 9.1.0 +*/ + +ResourceMonitor_init() { + Global Config_readinDiskLoad, Config_readinNetworkLoad, ResourceMonitor_hDrive + + If Config_readinDiskLoad + ResourceMonitor_hDrive := DllCall("CreateFile", "Str", "\\.\PhysicalDrive0", "UInt", 0, "UInt", 3, "UInt", 0, "UInt", 3, "UInt", 0, "UInt", 0) + ;; This call may lead to bug.n hanging (bug 019005). + If Config_readinNetworkLoad + ResourceMonitor_getNetworkInterface() +} + +ResourceMonitor_cleanup() { + Global Config_readinDiskLoad, ResourceMonitor_hDrive + + If Config_readinDiskLoad + DllCall("CloseHandle", "UInt", ResourceMonitor_hDrive) ;; used in ResourceMonitor_getDiskLoad +} + +ResourceMonitor_bytesToString(b) { + If (b > 1047527424) { + b /= 1024 * 1024 * 1024 + unit := "GB" + } Else If (b > 1022976) { + b /= 1024 * 1024 + unit := "MB" + } Else If (b > 999) { + b /= 1024 + unit := "kB" + } Else { + unit := " B" + } + b := Round(b, 1) + If (b > 99.9 Or unit = " B") + b := Round(b, 0) + Return, SubStr(" " b, -3) . unit +} + +ResourceMonitor_getBatteryStatus(ByRef batteryLifePercent, ByRef acLineStatus) { + VarSetCapacity(powerStatus, (1 + 1 + 1 + 1 + 4 + 4)) + success := DllCall("GetSystemPowerStatus", "UInt", &powerStatus) + If (ErrorLevel != 0 Or success = 0) { + MsgBox 16, Power Status, Can't get the power status... + Return + } + acLineStatus := NumGet(powerStatus, 0, "Char") + batteryLifePercent := NumGet(powerStatus, 2, "Char") + + If acLineStatus = 0 + acLineStatus = off + Else If acLineStatus = 1 + acLineStatus = on + Else If acLineStatus = 255 + acLineStatus = ? + + If batteryLifePercent = 255 + batteryLifePercent = ??? +} +;; PhiLho: AC/Battery status (http://www.autohotkey.com/forum/topic7633.html) + +ResourceMonitor_getDiskLoad(ByRef readLoad, ByRef writeLoad) { + Global ResourceMonitor_hDrive + Static oldReadCount, oldWriteCount + + nReturn := oldReadCount := oldWriteCount := 0 + dpSize := 5 * 8 + 4 + 4 + 4 + 4 + 8 + 4 + 8 * (A_IsUnicode ? 2 : 1) + 12 ;; 88? + VarSetCapacity(dp, dpSize) + DllCall("DeviceIoControl", "UInt", ResourceMonitor_hDrive, "UInt", 0x00070020, "UInt", 0, "UInt", 0, "UInt", &dp, "UInt", dpSize, "UIntP", nReturn, "UInt", 0) ;; IOCTL_DISK_PERFORMANCE + + newReadCount := NumGet(dp, 40) + newWriteCount := NumGet(dp, 44) + readLoad := SubStr(" " Round((1 - 1 / (1 + newReadCount - oldReadCount)) * 100), -2) + writeLoad := SubStr(" " Round((1 - 1 / (1 + newWriteCount - oldWriteCount)) * 100), -2) + oldReadCount := newReadCount + oldWriteCount := newWriteCount +} +;; fures: System + Network monitor - with net history graph (http://www.autohotkey.com/community/viewtopic.php?p=260329) +;; SKAN: HDD Activity Monitoring LED (http://www.autohotkey.com/community/viewtopic.php?p=113890&sid=64d9824fdf252697ff4d5026faba91f8#p113890) + +ResourceMonitor_getMemoryUsage() { + VarSetCapacity(memoryStatus, 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4) + DllCall("kernel32.dll\GlobalMemoryStatus", "UInt", &memoryStatus) + Return, SubStr(" " Round(*(&memoryStatus + 4)), -2) ;; LS byte is enough, 0..100 +} +;; fures: System + Network monitor - with net history graph (http://www.autohotkey.com/community/viewtopic.php?p=260329) + +ResourceMonitor_getNetworkInterface() { + Global Config_readinNetworkLoad, ResourceMonitor_networkInterface + + objWMIService := ComObjGet("winmgmts:{impersonationLevel=impersonate}!\\" . A_ComputerName . "\root\cimv2") + WQLQuery := "SELECT * FROM Win32_PerfFormattedData_Tcpip_NetworkInterface WHERE Name LIKE '%" . Config_readinNetworkLoad . "%'" + ResourceMonitor_networkInterface := objWMIService.ExecQuery(WQLQuery).ItemIndex(0) +} +;; Pillus: System monitor (HDD/Wired/Wireless) using keyboard LEDs (http://www.autohotkey.com/board/topic/65308-system-monitor-hddwiredwireless-using-keyboard-leds/) + +ResourceMonitor_getNetworkLoad(ByRef upLoad, ByRef dnLoad) { + Global ResourceMonitor_networkInterface + + ResourceMonitor_networkInterface.Refresh_ + dnLoad := ResourceMonitor_bytesToString(ResourceMonitor_networkInterface.BytesReceivedPerSec) . "/s" + upLoad := ResourceMonitor_bytesToString(ResourceMonitor_networkInterface.BytesSentPerSec) . "/s" +} +;; Pillus: System monitor (HDD/Wired/Wireless) using keyboard LEDs (http://www.autohotkey.com/board/topic/65308-system-monitor-hddwiredwireless-using-keyboard-leds/) + +ResourceMonitor_getSystemTimes() { + ;; Total CPU Load + Static oldIdleTime, oldKrnlTime, oldUserTime + Static newIdleTime, newKrnlTime, newUserTime + + newIdleTime := newKrnlTime := newUserTime := 0 + oldIdleTime := newIdleTime + oldKrnlTime := newKrnlTime + oldUserTime := newUserTime + + DllCall("GetSystemTimes", "Int64P", newIdleTime, "Int64P", newKrnlTime, "Int64P", newUserTime) + sysTime := Round((1 - (newIdleTime - oldIdleTime) / (newKrnlTime - oldKrnlTime+newUserTime - oldUserTime)) * 100) + Return, sysTime ;; system time in percent +} +;; Sean: CPU LoadTimes (http://www.autohotkey.com/forum/topic18913.html) + +ResourceMonitor_getText() { + Global Config_readinCpu, Config_readinDiskLoad, Config_readinMemoryUsage, Config_readinNetworkLoad + + text := "" + If Config_readinCpu + text .= " CPU: " ResourceMonitor_getSystemTimes() "% " + If Config_readinMemoryUsage { + If (Config_readinCpu) + text .= "|" + text .= " RAM: " ResourceMonitor_getMemoryUsage() "% " + } + If Config_readinDiskLoad { + If (Config_readinCpu Or Config_readinMemoryUsage) + text .= "|" + ResourceMonitor_getDiskLoad(rLoad, wLoad) + text .= " Dr: " rLoad "% | Dw: " wLoad "% " + } + If Config_readinNetworkLoad { + If (Config_readinCpu Or Config_readinMemoryUsage Or Config_readinDiskLoad) + text .= "|" + ResourceMonitor_getNetworkLoad(upLoad, dnLoad) + text .= " UP: " upLoad " | dn: " dnLoad " " + } + + Return, text +} + +ResourceMonitor_getSystemTimes2(ByRef IdleTime) { + DllCall("GetSystemTimes", "Int64P", IdleTime, "Int64P", KernelTime, "Int64P", UserTime) + Return KernelTime + UserTime +} + +ResourceMonitor_getCpuLoad(period := 500) { + total := ResourceMonitor_getSystemTimes2(idle) + Sleep, % period + total2 := ResourceMonitor_getSystemTimes2(idle2) + Return 100*(1 - (idle2 - idle)/(total2 - total)) +} + +ResourceMonitor_getCpuText() { + Return, Floor(ResourceMonitor_getCpuLoad()) . "%" +} + +ResourceMonitor_GlobalMemoryStatusEx() +{ + static MSEX, init := NumPut(VarSetCapacity(MSEX, 64, 0), MSEX, "uint") + if !(DllCall("GlobalMemoryStatusEx", "ptr", &MSEX)) + throw Exception("Call to GlobalMemoryStatusEx failed: " A_LastError, -1) + return { MemoryLoad: NumGet(MSEX, 4, "uint"), TotalPhys: NumGet(MSEX, 8, "uint64"), AvailPhys: NumGet(MSEX, 16, "uint64") } +} + +ResourceMonitor_getRamText() { + GMSEx := ResourceMonitor_GlobalMemoryStatusEx() + TotalMem := GMSEx.TotalPhys + AvailMem := GMSEx.AvailPhys + mem := RegExReplace(Floor((TotalMem - AvailMem) / 1048576), "(\d)(?=(?:\d{3})+(?:\.|$))", "$1,") + Return, mem . " MB" } \ No newline at end of file diff --git a/src/Tiler.ahk b/src/Tiler.ahk index d08aca6..9b47e5c 100644 --- a/src/Tiler.ahk +++ b/src/Tiler.ahk @@ -114,7 +114,7 @@ Tiler_isActive(m, v) { Tiler_layoutTiles(m, v, x, y, w, h, type = "") { Local axis1, axis2, axis3, gapW, hasStackArea, mFact, mSplit, mXSet, mYSet, mYActual, n - Local h1, h2, mWndCount, stackLen, subAreaCount, subAreaWndCount, subH1, subW1, subX1, subY1, w1, w2, x1, x2, y1, y2 + Local h1, h2, mWndCount, indexMod, leftArray, leftArrayCount, rightArray, rightArrayCount, stackLen, subAreaCount, subAreaWndCount, subH1, subW1, subX1, subY1, w1, w2, x1, x2, y1, y2 axis1 := Abs(View_#%m%_#%v%_layoutAxis_#1) axis2 := View_#%m%_#%v%_layoutAxis_#2 @@ -140,53 +140,89 @@ Tiler_layoutTiles(m, v, x, y, w, h, type = "") { mSplit := View_tiledWndId0 } - ;; Areas (master and stack) x1 := x y1 := y w1 := w h1 := h - If hasStackArea { + + leftArray := [] + leftArrayCount := 0 + rightArray := [] + rightArrayCount := 0 + + if hasStackArea { + ;; split in half If (View_#%m%_#%v%_layoutAxis_#1 < 0) Tiler_splitArea(axis1 - 1, 1 - mFact, x1, y1, w1, h1, gapW, x2, y2, w2, h2, x1, y1, w1, h1) Else Tiler_splitArea(axis1 - 1, mFact, x1, y1, w1, h1, gapW, x1, y1, w1, h1, x2, y2, w2, h2) + + indexMod := false + Loop % View_tiledWndId0 { + if indexMod { + leftArrayCount += 1 + leftArray[leftArrayCount] := View_tiledWndId%A_Index% + indexMod := false + } else { + rightArrayCount += 1 + rightArray[rightArrayCount] := View_tiledWndId%A_Index% + indexMod := true + } + } + + Tiler_stackArrayTiles(m, v, rightArray, rightArrayCount, +1, 2, x2, y2, w2, h2, gapW, type) + Tiler_stackArrayTiles(m, v, leftArray, leftArrayCount, +1, 2, x1, y1, w1, h1, gapW, type) + } else { + Tiler_stackTiles(m, v, 1, 1, +1, axis2, x1, y1, w1, h1, 0, type) } + ; Areas (master and stack) + ;x1 := x + ;y1 := y + ;w1 := w + ;h1 := h + ;If hasStackArea { + ; If (View_#%m%_#%v%_layoutAxis_#1 < 0) + ; Tiler_splitArea(axis1 - 1, 1 - mFact, x1, y1, w1, h1, gapW, x2, y2, w2, h2, x1, y1, w1, h1) + ; Else + ; Tiler_splitArea(axis1 - 1, mFact, x1, y1, w1, h1, gapW, x1, y1, w1, h1, x2, y2, w2, h2) + ;} + ;; Master - If (axis2 = 3) - Tiler_stackTiles(m, v, 1, mSplit, +1, 3, x1, y1, w1, h1, 0, type) - Else { - mYActual := (type = "blank") ? mYSet : Ceil(mSplit / mXSet) - subAreaCount := mYActual - mWndCount := mSplit - Loop, % mYActual { - Tiler_splitArea(Not (axis2 - 1), 1 / subAreaCount, x1, y1, w1, h1, gapW, subX1, subY1, subW1, subH1, x1, y1, w1, h1) - subAreaWndCount := mXSet - If (mWndCount < subAreaWndCount) - subAreaWndCount := mWndCount - Debug_logMessage("DEBUG[2] Tiler_layoutTiles: Master subArea #" A_Index, 2) - Tiler_stackTiles(m, v, mSplit - mWndCount + 1, subAreaWndCount, +1, axis2, subX1, subY1, subW1, subH1, gapW, type) - mWndCount -= subAreaWndCount - subAreaCount -= 1 - } - } - - ;; Stack - If hasStackArea { - If (type = "blank") { - Debug_logMessage("DEBUG[2] Tiler_layoutTiles: Stack subArea #" A_Index, 2) - Tiler_stackTiles(m, v, mSplit + 1, 1, +1, 3, x2, y2, w2, h2, 0, type) - } Else { - stackLen := View_tiledWndId0 - mSplit - ;; 161 is the minimal width of an Windows-Explorer window, below which it cannot be resized. - ;; The minimal height is 243, but this seems too high for being a limit here; - ;; therefor '2 * Bar_height' is used for the minimal height of a window. - If (axis3 = 3 Or (axis3 = 1 And (w2 - (stackLen - 1) * gapW) / stackLen < 161) Or (axis3 = 2 And (h2 - (stackLen - 1) * gapW) / stackLen < 2 * Bar_height)) - Tiler_stackTiles(m, v, mSplit + 1, stackLen, +1, 3, x2, y2, w2, h2, 0, type) - Else - Tiler_stackTiles(m, v, mSplit + 1, stackLen, +1, axis3, x2, y2, w2, h2, gapW, type) - } - } + ;If (axis2 = 3) + ; Tiler_stackTiles(m, v, 1, mSplit, +1, 3, x1, y1, w1, h1, 0, type) + ;Else { + ; mYActual := (type = "blank") ? mYSet : Ceil(mSplit / mXSet) + ; subAreaCount := mYActual + ; mWndCount := mSplit + ; Loop, % mYActual { + ; Tiler_splitArea(Not (axis2 - 1), 1 / subAreaCount, x1, y1, w1, h1, gapW, subX1, subY1, subW1, subH1, x1, y1, w1, h1) + ; subAreaWndCount := mXSet + ; If (mWndCount < subAreaWndCount) + ; subAreaWndCount := mWndCount + ; Debug_logMessage("DEBUG[2] Tiler_layoutTiles: Master subArea #" A_Index, 2) + ; Tiler_stackTiles(m, v, mSplit - mWndCount + 1, subAreaWndCount, +1, axis2, subX1, subY1, subW1, subH1, gapW, type) + ; mWndCount -= subAreaWndCount + ; subAreaCount -= 1 + ; } + ;} +; + ;;; Stack + ;If hasStackArea { + ; If (type = "blank") { + ; Debug_logMessage("DEBUG[2] Tiler_layoutTiles: Stack subArea #" A_Index, 2) + ; Tiler_stackTiles(m, v, mSplit + 1, 1, +1, 3, x2, y2, w2, h2, 0, type) + ; } Else { + ; stackLen := View_tiledWndId0 - mSplit + ; ;; 161 is the minimal width of an Windows-Explorer window, below which it cannot be resized. + ; ;; The minimal height is 243, but this seems too high for being a limit here; + ; ;; therefor '2 * Bar_height' is used for the minimal height of a window. + ; If (axis3 = 3 Or (axis3 = 1 And (w2 - (stackLen - 1) * gapW) / stackLen < 161) Or (axis3 = 2 And (h2 - (stackLen - 1) * gapW) / stackLen < 2 * Bar_height)) + ; Tiler_stackTiles(m, v, mSplit + 1, stackLen, +1, 3, x2, y2, w2, h2, 0, type) + ; Else + ; Tiler_stackTiles(m, v, mSplit + 1, stackLen, +1, axis3, x2, y2, w2, h2, gapW, type) + ; } + ;} } Tiler_setAxis(m, v, id, d) { @@ -332,6 +368,39 @@ Tiler_stackTiles(m, v, i, len, d, axis, x, y, w, h, padding, type = "") { } } +Tiler_stackArrayTiles(m, v, arr, len, d, axis, x, y, w, h, padding, type = "") { + Local i, dx, dy, tileH, tileW, tileX, tileY + + tileX := x + tileY := y + tileW := w + tileH := h + dx := 0 + dy := 0 + dw := (w - (len - 1) * padding) / len + dh := (h - (len - 1) * padding) / len + If (axis = 1) { + tileW := (w - (len - 1) * padding) / len + dx := tileW + padding + } Else If (axis = 2) { + tileH := (h - (len - 1) * padding) / len + dy := tileH + padding + } + ;; Else (axis = 3) and nothing to do + + Debug_logMessage("DEBUG[2] Tiler_stackArrayTiles: start = " i ", length = " len, 2) + i := 1 + Loop, % len { + If (type = "blank") + Tiler_addSubArea(m, v, i, tileX, tileY, tileW, tileH) + Else + Window_move(arr[i], tileX, tileY, tileW, tileH) + i += d + tileX += dx + tileY += dy + } +} + Tiler_toggleStackArea(m ,v) { Global diff --git a/src/View.ahk b/src/View.ahk index 342dfbc..f55bfbf 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -1,435 +1,433 @@ -/* - bug.n -- tiling window management - Copyright (c) 2010-2019 Joshua Fuhs, joten - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - @license GNU General Public License version 3 - ../LICENSE.md or <http://www.gnu.org/licenses/> - - @version 9.1.0 -*/ - -View_init(m, v) -{ - Global - - View_#%m%_#%v%_area_#0 := 0 - View_#%m%_#%v%_aWndIds := "0;" - View_#%m%_#%v%_layout_#1 := 1 - View_#%m%_#%v%_layout_#2 := 1 - View_#%m%_#%v%_layoutAxis_#1 := Config_layoutAxis_#1 - View_#%m%_#%v%_layoutAxis_#2 := Config_layoutAxis_#2 - View_#%m%_#%v%_layoutAxis_#3 := Config_layoutAxis_#3 - View_#%m%_#%v%_layoutGapWidth := Config_layoutGapWidth - View_#%m%_#%v%_layoutMFact := Config_layoutMFactor - View_#%m%_#%v%_layoutMX := 1 - View_#%m%_#%v%_layoutMY := 1 - View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#1 - View_#%m%_#%v%_margins := "0;0;0;0" - View_#%m%_#%v%_showStackArea := True - StringSplit, View_#%m%_#%v%_margin, View_#%m%_#%v%_margins, `; - View_#%m%_#%v%_wndIds := "" -} - -View_activateWindow(i, d = 0) { - Local aWndId, direction, failure, j, v, wndId, wndId0, wndIds - - Debug_logMessage("DEBUG[1] View_activateWindow(" . i . ", " . d . ")", 1) - If (i = 0) And (d = 0) - Return - - WinGet, aWndId, ID, A - Debug_logMessage("DEBUG[2] Active Windows ID: " . aWndId, 2, False) - v := Monitor_#%Manager_aMonitor%_aView_#1 - Debug_logMessage("DEBUG[2] View (" . v . ") wndIds: " . View_#%Manager_aMonitor%_#%v%_wndIds, 2, False) - StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 - StringSplit, wndId, wndIds, `; - Debug_logMessage("DEBUG[2] wndId count: " . wndId0, 2, False) - If (i > 0) And (i <= wndId0) And (d = 0) { - wndId := wndId%i% - Window_set(wndId, "AlwaysOnTop", "On") - Window_set(wndId, "AlwaysOnTop", "Off") - Window_#%wndId%_isMinimized := False - Manager_winActivate(wndId) - } Else If (wndId0 > 1) { - If Not InStr(Manager_managedWndIds, aWndId . ";") Or Window_#%aWndId%_isFloating - Window_set(aWndId, "Bottom", "") - Loop, % wndId0 { - If (wndId%A_Index% = aWndId) { - j := A_Index - Break - } - } - Debug_logMessage("DEBUG[2] Current wndId index: " . j, 2, False) - - If (d > 0) - direction = 1 - Else - direction = -1 - i := Manager_loop(j, d, 1, wndId0) - Loop, % wndId0 { - Debug_logMessage("DEBUG[2] Next wndId index: " . i, 2, False) - wndId := wndId%i% - If Not Window_#%wndId%_isMinimized { - Window_set(wndId, "AlwaysOnTop", "On") - Window_set(wndId, "AlwaysOnTop", "Off") - - ;; If there are hung windows on the screen, we still want to be able to cycle through them. - failure := Manager_winActivate(wndId) - If Not failure - Break - } - i := Manager_loop(i, direction, 1, wndId0) - } - } -} - -View_addWindow(m, v, wndId) { - Local i, mSplit, n, replace, search - - StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, % wndId ";",, All - If Tiler_isActive(m, v) And ((Config_newWndPosition = "masterBottom") Or (Config_newWndPosition = "stackTop")) { - n := View_getTiledWndIds(m, v) - mSplit := View_#%m%_#%v%_layoutMX * View_#%m%_#%v%_layoutMY - If (mSplit = 1 And Config_newWndPosition = "masterBottom") - View_#%m%_#%v%_wndIds := wndId ";" . View_#%m%_#%v%_wndIds - Else If ((Config_newWndPosition = "masterBottom" And n < mSplit) Or (Config_newWndPosition = "stackTop" And n <= mSplit)) - View_#%m%_#%v%_wndIds .= wndId ";" - Else { - If (Config_newWndPosition = "masterBottom") - i := mSplit - 1 - Else - i := mSplit - search := View_tiledWndId%i% ";" - replace := search wndId ";" - StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, %search%, %replace% - } - } - Else If (Config_newWndPosition = "bottom") - View_#%m%_#%v%_wndIds .= wndId ";" - Else - View_#%m%_#%v%_wndIds := wndId ";" View_#%m%_#%v%_wndIds -} - -View_arrange(m, v, setLayout = False) { - Local fn, h, l, w, x, y - - Debug_logMessage("DEBUG[1] View_arrange(" . m . ", " . v . ")", 1) - - l := View_#%m%_#%v%_layout_#1 - fn := Config_layoutFunction_#%l% - If fn { - x := Monitor_#%m%_x + View_#%m%_#%v%_layoutGapWidth + View_#%m%_#%v%_margin4 - y := Monitor_#%m%_y + View_#%m%_#%v%_layoutGapWidth + View_#%m%_#%v%_margin1 - w := Monitor_#%m%_width - 2 * View_#%m%_#%v%_layoutGapWidth - View_#%m%_#%v%_margin4 - View_#%m%_#%v%_margin2 - h := Monitor_#%m%_height - 2 * View_#%m%_#%v%_layoutGapWidth - View_#%m%_#%v%_margin1 - View_#%m%_#%v%_margin3 - - ;; All window actions are performed on independent windows. A delay won't help. - SetWinDelay, 0 - If Config_dynamicTiling Or setLayout { - View_getTiledWndIds(m, v) - If (fn = "monocle") { - ;; 'View_getLayoutSymbol_monocle' - View_#%m%_#%v%_layoutSymbol := "[" View_tiledWndId0 "]" - ;; 'View_arrange_monocle' - Tiler_stackTiles(0, 0, 1, View_tiledWndId0, +1, 3, x, y, w, h, 0) - } Else ;; (fn = "tile") - Tiler_layoutTiles(m, v, x, y, w, h) - } Else If (fn = "tile") { - Tiler_layoutTiles(m, v, x, y, w, h, "blank") - If Config_continuouslyTraceAreas - View_traceAreas(True) - } - SetWinDelay, 10 - } - Else ;; floating layout (no 'View_arrange_', following is 'View_getLayoutSymbol_')' - View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#%l% - - Bar_updateLayout(m) -} - -View_getActiveWindow(m, v) { - Local listId, listIds, wndId - - listIds := "aWndIds;wndIds" - wndId := 0 - Loop, Parse, listIds, `; - { - listId := A_LoopField - Loop, Parse, View_#%m%_#%v%_%listId%, `; - { - If Not A_LoopField - Break - Else If Not WinExist("ahk_id" A_LoopField) Or Window_#%A_LoopField%_isMinimized - Continue - Else { - wndId := A_LoopField - Break - } - } - If wndId { - If (listId = "wndIds") - View_setActiveWindow(m, v, wndId) - Break - } - } - - Return, wndId -} - -View_getTiledWndIds(m, v) -{ - Local n, tiledWndIds, wndIds - - n := 0 - tiledWndIds := "" - StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 - Loop, PARSE, wndIds, `; - { - If A_LoopField And Not Window_#%A_LoopField%_isFloating And WinExist("ahk_id " A_LoopField) and Not Window_isHung(A_LoopField) - { - n += 1 - tiledWndIds .= A_LoopField ";" - } - } - View_tiledWndIds := tiledWndIds - StringTrimRight, tiledWndIds, tiledWndIds, 1 - StringSplit, View_tiledWndId, tiledWndIds, `; - - Return, n -} - -View_ghostWindow(m, v, bodyWndId, ghostWndId) -{ - Local search, replace - - search := bodyWndId ";" - replace := search ghostWndId ";" - StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, %search%, %replace% -} - -View_moveToIndex(m, v, n, w) { - Local wndIds - - View_#%n%_#%w%_area_#0 := View_#%m%_#%v%_area_#0 - View_#%n%_#%w%_aWndIds := View_#%m%_#%v%_aWndIds - View_#%n%_#%w%_layout_#1 := View_#%m%_#%v%_layout_#1 - View_#%n%_#%w%_layout_#2 := View_#%m%_#%v%_layout_#2 - View_#%n%_#%w%_layoutAxis_#1 := View_#%m%_#%v%_layoutAxis_#1 - View_#%n%_#%w%_layoutAxis_#2 := View_#%m%_#%v%_layoutAxis_#2 - View_#%n%_#%w%_layoutAxis_#3 := View_#%m%_#%v%_layoutAxis_#3 - View_#%n%_#%w%_layoutGapWidth := View_#%m%_#%v%_layoutGapWidth - View_#%n%_#%w%_layoutMFact := View_#%m%_#%v%_layoutMFact - View_#%n%_#%w%_layoutMX := View_#%m%_#%v%_layoutMX - View_#%n%_#%w%_layoutMY := View_#%m%_#%v%_layoutMY - View_#%n%_#%w%_layoutSymbol := View_#%m%_#%v%_layoutSymbol - View_#%n%_#%w%_margins := View_#%m%_#%v%_margins - View_#%n%_#%w%_showStackArea := View_#%m%_#%v%_showStackArea - View_#%n%_#%w%_wndIds := View_#%m%_#%v%_wndIds - StringSplit, View_#%n%_#%w%_margin, View_#%n%_#%w%_margins, `; - StringTrimRight, wndIds, View_#%n%_#%w%_wndIds, 1 - Loop, PARSE, wndIds, `; - { - Window_#%A_LoopField%_monitor := n - Window_#%A_LoopField%_tags -= 1 << v - 1 - Window_#%A_LoopField%_tags += 1 << w - 1 - } -} - -; @TODO: Theoretically, something is wrong here. From the hotkeys this should be manual tiling, but the function says otherwise. -View_moveWindow(i=0, d=0) { - Local aWndId, m, v - - WinGet, aWndId, ID, A - m := Manager_aMonitor - v := Monitor_#%m%_aView_#1 - If Tiler_isActive(Manager_aMonitor, v) And InStr(Manager_managedWndIds, aWndId ";") And Not (i = 0 And d = 0) And View_#%m%_#%v%_area_#0 And (i <= View_#%m%_#%v%_area_#0) { - If (i = 0) - i := Manager_loop(Window_#%aWndId%_area, d, 1, View_#%m%_#%v%_area_#0) - Window_move(aWndId, View_#%m%_#%v%_area_#%i%_x, View_#%m%_#%v%_area_#%i%_y, View_#%m%_#%v%_area_#%i%_width, View_#%m%_#%v%_area_#%i%_height) - Window_#%aWndId%_area := i - Manager_setCursor(aWndId) - } -} - -View_resetTileLayout() { - Local m, v - - m := Manager_aMonitor - v := Monitor_#%m%_aView_#1 - - View_#%m%_#%v%_area_#0 := 0 - View_#%m%_#%v%_layout_#2 := View_#%m%_#%v%_layout_#1 - View_#%m%_#%v%_layout_#1 := 1 - View_#%m%_#%v%_layoutAxis_#1 := Config_layoutAxis_#1 - View_#%m%_#%v%_layoutAxis_#2 := Config_layoutAxis_#2 - View_#%m%_#%v%_layoutAxis_#3 := Config_layoutAxis_#3 - View_#%m%_#%v%_layoutGapWidth := Config_layoutGapWidth - View_#%m%_#%v%_layoutMFact := Config_layoutMFactor - View_#%m%_#%v%_layoutMX := 1 - View_#%m%_#%v%_layoutMY := 1 - View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#1 - View_#%m%_#%v%_margins := "0;0;0;0" - View_#%m%_#%v%_showStackArea := True - StringSplit, View_#%m%_#%v%_margin, View_#%m%_#%v%_margins, `; - - If Tiler_isActive(m, v) - View_arrange(m, v) -} - -View_setActiveWindow(m, v, wndId) { - Global - - If wndId { - StringReplace, View_#%m%_#%v%_aWndIds, View_#%m%_#%v%_aWndIds, % wndId ";", All - View_#%m%_#%v%_aWndIds := wndId ";" View_#%m%_#%v%_aWndIds - } -} - -View_setGapWidth(i, d = 0) { - Local v - - v := Monitor_#%Manager_aMonitor%_aView_#1 - If (i = 0) And (d != 0) - i := View_#%Manager_aMonitor%_#%v%_layoutGapWidth - i += d - If (i >= 0 And i < Monitor_#%Manager_aMonitor%_height And i < Monitor_#%Manager_aMonitor%_width) { - i := Ceil(i / 2) * 2 - View_#%Manager_aMonitor%_#%v%_layoutGapWidth := i - Return, 1 - } Else - Return, 0 -} - -View_setLayout(i, d = 0) { - Local v - - v := Monitor_#%Manager_aMonitor%_aView_#1 - If (i = -1) - i := View_#%Manager_aMonitor%_#%v%_layout_#2 - Else If (i = 0) - i := View_#%Manager_aMonitor%_#%v%_layout_#1 - i := Manager_loop(i, d, 1, Config_layoutCount) - If (i > 0) And (i <= Config_layoutCount) { - If Not (i = View_#%Manager_aMonitor%_#%v%_layout_#1) { - View_#%Manager_aMonitor%_#%v%_layout_#2 := View_#%Manager_aMonitor%_#%v%_layout_#1 - View_#%Manager_aMonitor%_#%v%_layout_#1 := i - } - View_arrange(Manager_aMonitor, v, True) - } -} - -View_setLayoutProperty(name, i, d, opt = 0) { - Local a, l, v - - a := False - v := Monitor_#%Manager_aMonitor%_aView_#1 - l := View_#%Manager_aMonitor%_#%v%_layout_#1 - If Tiler_isActive(Manager_aMonitor, v) { - If (name = "Axis") - a := Tiler_setAxis(Manager_aMonitor, v, opt, d) - Else If (name = "MFactor") { - If (opt = 0) - opt := 1 - a := Tiler_setMFactor(Manager_aMonitor, v, i, d, opt) - } Else If (name = "MX") - a := Tiler_setMX(Manager_aMonitor, v, d) - Else If (name = "MY") - a := Tiler_setMY(Manager_aMonitor, v, d) - } - If (name = "GapWidth") And (Tiler_isActive(Manager_aMonitor, v) Or (Config_layoutFunction_#%l% = "monocle")) - a := View_setGapWidth(i, d) - - If a - View_arrange(Manager_aMonitor, v) -} - -View_shuffleWindow(i, d = 0) { - Local aWndId, j, replace, v - - Debug_logMessage("DEBUG[2] View_shuffleWindow(" . i . ", " . d . ")", 2) - v := Monitor_#%Manager_aMonitor%_aView_#1 - If Tiler_isActive(Manager_aMonitor, v) { - View_getTiledWndIds(Manager_aMonitor, v) - WinGet, aWndId, ID, A - If InStr(View_tiledWndIds, aWndId ";") And (View_tiledWndId0 > 1) { - Loop, % View_tiledWndId0 { - If (View_tiledWndId%A_Index% = aWndId) { - j := A_Index - Break - } - } - If (i = 0) - i := j - Else If (i = 1 And j = 1) - i := 2 - i := Manager_loop(i, d, 1, View_tiledWndId0) - Debug_logMessage("DEBUG[2] View_shuffleWindow: " . j . " -> " . i, 2) - If (i != j) { - If (i < j) - replace := aWndId ";" View_tiledWndId%i% ";" - Else - replace := View_tiledWndId%i% ";" aWndId ";" - StringReplace, View_#%Manager_aMonitor%_#%v%_wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, % aWndId ";", - StringReplace, View_#%Manager_aMonitor%_#%v%_wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, % View_tiledWndId%i% ";", %replace% - View_arrange(Manager_aMonitor, v) - Manager_setCursor(aWndId) - } - } - } -} - -View_toggleFloatingWindow(wndId = 0) { - Local l, v - - If (wndId = 0) - WinGet, wndId, ID, A - v := Monitor_#%Manager_aMonitor%_aView_#1 - l := View_#%Manager_aMonitor%_#%v%_layout_#1 - Debug_logMessage("DEBUG[2] View_toggleFloatingWindow; wndId: " . wndId, 2) - If (Config_layoutFunction_#%l% And InStr(Manager_managedWndIds, wndId ";")) { - Window_#%wndId%_isFloating := Not Window_#%wndId%_isFloating - View_arrange(Manager_aMonitor, v) - Bar_updateTitle() - } -} - -View_toggleMargins() -{ - Local v - - - If Not (Config_viewMargins = "0;0;0;0") - { - v := Monitor_#%Manager_aMonitor%_aView_#1 - Debug_logMessage("DEBUG[3] View_toggleMargins(" . View_#%Manager_aMonitor%_#%v%_margin1 . ", " . View_#%Manager_aMonitor%_#%v%_margin2 . ", " . View_#%Manager_aMonitor%_#%v%_margin3 . ", " . View_#%Manager_aMonitor%_#%v%_margin4 . ")", 3) - If (View_#%Manager_aMonitor%_#%v%_margins = "0;0;0;0") - View_#%Manager_aMonitor%_#%v%_margins := Config_viewMargins - Else - View_#%Manager_aMonitor%_#%v%_margins := "0;0;0;0" - StringSplit, View_#%Manager_aMonitor%_#%v%_margin, View_#%Manager_aMonitor%_#%v%_margins, `; - View_arrange(Manager_aMonitor, v) - } -} - -View_toggleStackArea() { - Local v - - v := Monitor_#%Manager_aMonitor%_aView_#1 - If Tiler_isActive(Manager_aMonitor, v) And Not Config_dynamicTiling { - Tiler_toggleStackArea(Manager_aMonitor, v) - View_arrange(Manager_aMonitor, v) - } -} - -View_traceAreas(continuously = False) { - Local v - - v := Monitor_#%Manager_aMonitor%_aView_#1 - If Tiler_isActive(Manager_aMonitor, v) And Not Config_dynamicTiling - Tiler_traceAreas(Manager_aMonitor, v, continuously) -} +/* + bug.n -- tiling window management + Copyright (c) 2010-2019 Joshua Fuhs, joten + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + @license GNU General Public License version 3 + ../LICENSE.md or <http://www.gnu.org/licenses/> + + @version 9.1.0 +*/ + +View_init(m, v) { + Global + + View_#%m%_#%v%_area_#0 := 0 + View_#%m%_#%v%_aWndIds := "0;" + View_#%m%_#%v%_layout_#1 := 1 + View_#%m%_#%v%_layout_#2 := 1 + View_#%m%_#%v%_layoutAxis_#1 := Config_layoutAxis_#1 + View_#%m%_#%v%_layoutAxis_#2 := Config_layoutAxis_#2 + View_#%m%_#%v%_layoutAxis_#3 := Config_layoutAxis_#3 + View_#%m%_#%v%_layoutGapWidth := Config_layoutGapWidth + View_#%m%_#%v%_layoutMFact := Config_layoutMFactor + View_#%m%_#%v%_layoutMX := 1 + View_#%m%_#%v%_layoutMY := 1 + View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#1 + View_#%m%_#%v%_margins := "0;0;0;0" + View_#%m%_#%v%_showStackArea := True + StringSplit, View_#%m%_#%v%_margin, View_#%m%_#%v%_margins, `; + View_#%m%_#%v%_wndIds := "" +} + +View_activateWindow(i, d = 0) { + Local aWndId, direction, failure, j, v, wndId, wndId0, wndIds + + Debug_logMessage("DEBUG[1] View_activateWindow(" . i . ", " . d . ")", 1) + If (i = 0) And (d = 0) + Return + + WinGet, aWndId, ID, A + Debug_logMessage("DEBUG[2] Active Windows ID: " . aWndId, 2, False) + v := Monitor_#%Manager_aMonitor%_aView_#1 + Debug_logMessage("DEBUG[2] View (" . v . ") wndIds: " . View_#%Manager_aMonitor%_#%v%_wndIds, 2, False) + StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 + StringSplit, wndId, wndIds, `; + Debug_logMessage("DEBUG[2] wndId count: " . wndId0, 2, False) + If (i > 0) And (i <= wndId0) And (d = 0) { + wndId := wndId%i% + Window_set(wndId, "AlwaysOnTop", "On") + Window_set(wndId, "AlwaysOnTop", "Off") + Window_#%wndId%_isMinimized := False + Manager_winActivate(wndId) + } Else If (wndId0 > 1) { + If Not InStr(Manager_managedWndIds, aWndId . ";") Or Window_#%aWndId%_isFloating + Window_set(aWndId, "Bottom", "") + Loop, % wndId0 { + If (wndId%A_Index% = aWndId) { + j := A_Index + Break + } + } + Debug_logMessage("DEBUG[2] Current wndId index: " . j, 2, False) + + If (d > 0) + direction = 1 + Else + direction = -1 + i := Manager_loop(j, d, 1, wndId0) + Loop, % wndId0 { + Debug_logMessage("DEBUG[2] Next wndId index: " . i, 2, False) + wndId := wndId%i% + If Not Window_#%wndId%_isMinimized { + Window_set(wndId, "AlwaysOnTop", "On") + Window_set(wndId, "AlwaysOnTop", "Off") + + ;; If there are hung windows on the screen, we still want to be able to cycle through them. + failure := Manager_winActivate(wndId) + If Not failure + Break + } + i := Manager_loop(i, direction, 1, wndId0) + } + } +} + +View_addWindow(m, v, wndId) { + Local i, mSplit, n, replace, search + + StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, % wndId ";",, All + If Tiler_isActive(m, v) And ((Config_newWndPosition = "masterBottom") Or (Config_newWndPosition = "stackTop")) { + n := View_getTiledWndIds(m, v) + mSplit := View_#%m%_#%v%_layoutMX * View_#%m%_#%v%_layoutMY + If (mSplit = 1 And Config_newWndPosition = "masterBottom") + View_#%m%_#%v%_wndIds := wndId ";" . View_#%m%_#%v%_wndIds + Else If ((Config_newWndPosition = "masterBottom" And n < mSplit) Or (Config_newWndPosition = "stackTop" And n <= mSplit)) + View_#%m%_#%v%_wndIds .= wndId ";" + Else { + If (Config_newWndPosition = "masterBottom") + i := mSplit - 1 + Else + i := mSplit + search := View_tiledWndId%i% ";" + replace := search wndId ";" + StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, %search%, %replace% + } + } + Else If (Config_newWndPosition = "bottom") + View_#%m%_#%v%_wndIds .= wndId ";" + Else + View_#%m%_#%v%_wndIds := wndId ";" View_#%m%_#%v%_wndIds +} + +View_arrange(m, v, setLayout = False) { + Local fn, h, l, w, x, y + + Debug_logMessage("DEBUG[1] View_arrange(" . m . ", " . v . ")", 1) + + l := View_#%m%_#%v%_layout_#1 + fn := Config_layoutFunction_#%l% + If fn { + x := Monitor_#%m%_x + View_#%m%_#%v%_layoutGapWidth + View_#%m%_#%v%_margin4 + y := Monitor_#%m%_y + View_#%m%_#%v%_layoutGapWidth + View_#%m%_#%v%_margin1 + w := Monitor_#%m%_width - 2 * View_#%m%_#%v%_layoutGapWidth - View_#%m%_#%v%_margin4 - View_#%m%_#%v%_margin2 + h := Monitor_#%m%_height - 2 * View_#%m%_#%v%_layoutGapWidth - View_#%m%_#%v%_margin1 - View_#%m%_#%v%_margin3 + + ;; All window actions are performed on independent windows. A delay won't help. + SetWinDelay, 0 + If Config_dynamicTiling Or setLayout { + View_getTiledWndIds(m, v) + If (fn = "monocle") { + ;; 'View_getLayoutSymbol_monocle' + View_#%m%_#%v%_layoutSymbol := "[" View_tiledWndId0 "]" + ;; 'View_arrange_monocle' + Tiler_stackTiles(0, 0, 1, View_tiledWndId0, +1, 3, x, y, w, h, 0) + } Else ;; (fn = "tile") + Tiler_layoutTiles(m, v, x, y, w, h) + } Else If (fn = "tile") { + Tiler_layoutTiles(m, v, x, y, w, h, "blank") + If Config_continuouslyTraceAreas + View_traceAreas(True) + } + SetWinDelay, 10 + } + Else ;; floating layout (no 'View_arrange_', following is 'View_getLayoutSymbol_')' + View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#%l% + + ;Bar_updateLayout(m) +} + +View_getActiveWindow(m, v) { + Local listId, listIds, wndId + + listIds := "aWndIds;wndIds" + wndId := 0 + Loop, Parse, listIds, `; + { + listId := A_LoopField + Loop, Parse, View_#%m%_#%v%_%listId%, `; + { + If Not A_LoopField + Break + Else If Not WinExist("ahk_id" A_LoopField) Or Window_#%A_LoopField%_isMinimized + Continue + Else { + wndId := A_LoopField + Break + } + } + If wndId { + If (listId = "wndIds") + View_setActiveWindow(m, v, wndId) + Break + } + } + + Return, wndId +} + +View_getTiledWndIds(m, v) +{ + Local n, tiledWndIds, wndIds + + n := 0 + tiledWndIds := "" + StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 + Loop, PARSE, wndIds, `; + { + If A_LoopField And Not Window_#%A_LoopField%_isFloating And WinExist("ahk_id " A_LoopField) and Not Window_isHung(A_LoopField) + { + n += 1 + tiledWndIds .= A_LoopField ";" + } + } + View_tiledWndIds := tiledWndIds + StringTrimRight, tiledWndIds, tiledWndIds, 1 + StringSplit, View_tiledWndId, tiledWndIds, `; + + Return, n +} + +View_ghostWindow(m, v, bodyWndId, ghostWndId) +{ + Local search, replace + + search := bodyWndId ";" + replace := search ghostWndId ";" + StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, %search%, %replace% +} + +View_moveToIndex(m, v, n, w) { + Local wndIds + + View_#%n%_#%w%_area_#0 := View_#%m%_#%v%_area_#0 + View_#%n%_#%w%_aWndIds := View_#%m%_#%v%_aWndIds + View_#%n%_#%w%_layout_#1 := View_#%m%_#%v%_layout_#1 + View_#%n%_#%w%_layout_#2 := View_#%m%_#%v%_layout_#2 + View_#%n%_#%w%_layoutAxis_#1 := View_#%m%_#%v%_layoutAxis_#1 + View_#%n%_#%w%_layoutAxis_#2 := View_#%m%_#%v%_layoutAxis_#2 + View_#%n%_#%w%_layoutAxis_#3 := View_#%m%_#%v%_layoutAxis_#3 + View_#%n%_#%w%_layoutGapWidth := View_#%m%_#%v%_layoutGapWidth + View_#%n%_#%w%_layoutMFact := View_#%m%_#%v%_layoutMFact + View_#%n%_#%w%_layoutMX := View_#%m%_#%v%_layoutMX + View_#%n%_#%w%_layoutMY := View_#%m%_#%v%_layoutMY + View_#%n%_#%w%_layoutSymbol := View_#%m%_#%v%_layoutSymbol + View_#%n%_#%w%_margins := View_#%m%_#%v%_margins + View_#%n%_#%w%_showStackArea := View_#%m%_#%v%_showStackArea + View_#%n%_#%w%_wndIds := View_#%m%_#%v%_wndIds + StringSplit, View_#%n%_#%w%_margin, View_#%n%_#%w%_margins, `; + StringTrimRight, wndIds, View_#%n%_#%w%_wndIds, 1 + Loop, PARSE, wndIds, `; + { + Window_#%A_LoopField%_monitor := n + Window_#%A_LoopField%_tags -= 1 << v - 1 + Window_#%A_LoopField%_tags += 1 << w - 1 + } +} + +; @TODO: Theoretically, something is wrong here. From the hotkeys this should be manual tiling, but the function says otherwise. +View_moveWindow(i=0, d=0) { + Local aWndId, m, v + + WinGet, aWndId, ID, A + m := Manager_aMonitor + v := Monitor_#%m%_aView_#1 + If Tiler_isActive(Manager_aMonitor, v) And InStr(Manager_managedWndIds, aWndId ";") And Not (i = 0 And d = 0) And View_#%m%_#%v%_area_#0 And (i <= View_#%m%_#%v%_area_#0) { + If (i = 0) + i := Manager_loop(Window_#%aWndId%_area, d, 1, View_#%m%_#%v%_area_#0) + Window_move(aWndId, View_#%m%_#%v%_area_#%i%_x, View_#%m%_#%v%_area_#%i%_y, View_#%m%_#%v%_area_#%i%_width, View_#%m%_#%v%_area_#%i%_height) + Window_#%aWndId%_area := i + Manager_setCursor(aWndId) + } +} + +View_resetTileLayout() { + Local m, v + + m := Manager_aMonitor + v := Monitor_#%m%_aView_#1 + + View_#%m%_#%v%_area_#0 := 0 + View_#%m%_#%v%_layout_#2 := View_#%m%_#%v%_layout_#1 + View_#%m%_#%v%_layout_#1 := 1 + View_#%m%_#%v%_layoutAxis_#1 := Config_layoutAxis_#1 + View_#%m%_#%v%_layoutAxis_#2 := Config_layoutAxis_#2 + View_#%m%_#%v%_layoutAxis_#3 := Config_layoutAxis_#3 + View_#%m%_#%v%_layoutGapWidth := Config_layoutGapWidth + View_#%m%_#%v%_layoutMFact := Config_layoutMFactor + View_#%m%_#%v%_layoutMX := 1 + View_#%m%_#%v%_layoutMY := 1 + View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#1 + View_#%m%_#%v%_margins := "0;0;0;0" + View_#%m%_#%v%_showStackArea := True + StringSplit, View_#%m%_#%v%_margin, View_#%m%_#%v%_margins, `; + + If Tiler_isActive(m, v) + View_arrange(m, v) +} + +View_setActiveWindow(m, v, wndId) { + Global + + If wndId { + StringReplace, View_#%m%_#%v%_aWndIds, View_#%m%_#%v%_aWndIds, % wndId ";", All + View_#%m%_#%v%_aWndIds := wndId ";" View_#%m%_#%v%_aWndIds + } +} + +View_setGapWidth(i, d = 0) { + Local v + + v := Monitor_#%Manager_aMonitor%_aView_#1 + If (i = 0) And (d != 0) + i := View_#%Manager_aMonitor%_#%v%_layoutGapWidth + i += d + If (i >= 0 And i < Monitor_#%Manager_aMonitor%_height And i < Monitor_#%Manager_aMonitor%_width) { + i := Ceil(i / 2) * 2 + View_#%Manager_aMonitor%_#%v%_layoutGapWidth := i + Return, 1 + } Else + Return, 0 +} + +View_setLayout(i, d = 0) { + Local v + + v := Monitor_#%Manager_aMonitor%_aView_#1 + If (i = -1) + i := View_#%Manager_aMonitor%_#%v%_layout_#2 + Else If (i = 0) + i := View_#%Manager_aMonitor%_#%v%_layout_#1 + i := Manager_loop(i, d, 1, Config_layoutCount) + If (i > 0) And (i <= Config_layoutCount) { + If Not (i = View_#%Manager_aMonitor%_#%v%_layout_#1) { + View_#%Manager_aMonitor%_#%v%_layout_#2 := View_#%Manager_aMonitor%_#%v%_layout_#1 + View_#%Manager_aMonitor%_#%v%_layout_#1 := i + } + View_arrange(Manager_aMonitor, v, True) + } +} + +View_setLayoutProperty(name, i, d, opt = 0) { + Local a, l, v + + a := False + v := Monitor_#%Manager_aMonitor%_aView_#1 + l := View_#%Manager_aMonitor%_#%v%_layout_#1 + If Tiler_isActive(Manager_aMonitor, v) { + If (name = "Axis") + a := Tiler_setAxis(Manager_aMonitor, v, opt, d) + Else If (name = "MFactor") { + If (opt = 0) + opt := 1 + a := Tiler_setMFactor(Manager_aMonitor, v, i, d, opt) + } Else If (name = "MX") + a := Tiler_setMX(Manager_aMonitor, v, d) + Else If (name = "MY") + a := Tiler_setMY(Manager_aMonitor, v, d) + } + If (name = "GapWidth") And (Tiler_isActive(Manager_aMonitor, v) Or (Config_layoutFunction_#%l% = "monocle")) + a := View_setGapWidth(i, d) + + If a + View_arrange(Manager_aMonitor, v) +} + +View_shuffleWindow(i, d = 0) { + Local aWndId, j, replace, v + + Debug_logMessage("DEBUG[2] View_shuffleWindow(" . i . ", " . d . ")", 2) + v := Monitor_#%Manager_aMonitor%_aView_#1 + If Tiler_isActive(Manager_aMonitor, v) { + View_getTiledWndIds(Manager_aMonitor, v) + WinGet, aWndId, ID, A + If InStr(View_tiledWndIds, aWndId ";") And (View_tiledWndId0 > 1) { + Loop, % View_tiledWndId0 { + If (View_tiledWndId%A_Index% = aWndId) { + j := A_Index + Break + } + } + If (i = 0) + i := j + Else If (i = 1 And j = 1) + i := 2 + i := Manager_loop(i, d, 1, View_tiledWndId0) + Debug_logMessage("DEBUG[2] View_shuffleWindow: " . j . " -> " . i, 2) + If (i != j) { + If (i < j) + replace := aWndId ";" View_tiledWndId%i% ";" + Else + replace := View_tiledWndId%i% ";" aWndId ";" + StringReplace, View_#%Manager_aMonitor%_#%v%_wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, % aWndId ";", + StringReplace, View_#%Manager_aMonitor%_#%v%_wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, % View_tiledWndId%i% ";", %replace% + View_arrange(Manager_aMonitor, v) + Manager_setCursor(aWndId) + } + } + } +} + +View_toggleFloatingWindow(wndId = 0) { + Local l, v + + If (wndId = 0) + WinGet, wndId, ID, A + v := Monitor_#%Manager_aMonitor%_aView_#1 + l := View_#%Manager_aMonitor%_#%v%_layout_#1 + Debug_logMessage("DEBUG[2] View_toggleFloatingWindow; wndId: " . wndId, 2) + If (Config_layoutFunction_#%l% And InStr(Manager_managedWndIds, wndId ";")) { + Window_#%wndId%_isFloating := Not Window_#%wndId%_isFloating + View_arrange(Manager_aMonitor, v) + Bar_updateTitle() + } +} + +View_toggleMargins() +{ + Local v + + If Not (Config_viewMargins = "0;0;0;0") + { + v := Monitor_#%Manager_aMonitor%_aView_#1 + Debug_logMessage("DEBUG[3] View_toggleMargins(" . View_#%Manager_aMonitor%_#%v%_margin1 . ", " . View_#%Manager_aMonitor%_#%v%_margin2 . ", " . View_#%Manager_aMonitor%_#%v%_margin3 . ", " . View_#%Manager_aMonitor%_#%v%_margin4 . ")", 3) + If (View_#%Manager_aMonitor%_#%v%_margins = "0;0;0;0") + View_#%Manager_aMonitor%_#%v%_margins := Config_viewMargins + Else + View_#%Manager_aMonitor%_#%v%_margins := "0;0;0;0" + StringSplit, View_#%Manager_aMonitor%_#%v%_margin, View_#%Manager_aMonitor%_#%v%_margins, `; + View_arrange(Manager_aMonitor, v) + } +} + +View_toggleStackArea() { + Local v + + v := Monitor_#%Manager_aMonitor%_aView_#1 + If Tiler_isActive(Manager_aMonitor, v) And Not Config_dynamicTiling { + Tiler_toggleStackArea(Manager_aMonitor, v) + View_arrange(Manager_aMonitor, v) + } +} + +View_traceAreas(continuously = False) { + Local v + + v := Monitor_#%Manager_aMonitor%_aView_#1 + If Tiler_isActive(Manager_aMonitor, v) And Not Config_dynamicTiling + Tiler_traceAreas(Manager_aMonitor, v, continuously) +} diff --git a/tools/hul.ahk b/tools/hul.ahk index 1e48aed..2a1ff10 100644 --- a/tools/hul.ahk +++ b/tools/hul.ahk @@ -1,187 +1,187 @@ -/** - * hul! - Find and restore (hidden) windows - * Copyright (c) 2011 joten - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - * - * @version 0.1.0.01 (02.10.2011) - */ - -NAME := "hul!" -VERSION := "0.1.0" -HELP := -(Join -"USAGE`n -`n -Specify one, two or all of the following search criteria:`n -- Type a regular expression in the field next to 'Partial title'.`n -- Type a class name (exact match) in the field next to 'Class name'.`n -- Type a process name (e. g. the name of an exeutable, exact match) in the field next to 'Process name'.`n -`n -The search will be done on typing the search criteria.`n -`n -You may navigate between the input fields by pressing Tab (forward) or Shift+Tab (back).`n -Press Enter to go to the list box, which contains the search results.`n -Select an entry and press Enter again to restore the selected window.`n -`n -Press the Escape (Esc) key to clear all fields and go back to entering the search criteria.`n" -) - -/** - * Script settings - */ -#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. -#NoTrayIcon -#SingleInstance force -SendMode Input ; Recommended for new scripts due to its superior speed and reliability. -SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. -; DetectHiddenWindows, On -; SetFormat, Integer, h - -/** - * Pseudo main function - */ - WinGet, Main_aWndId, ID, A - - ; BEGIN: Init GUI - IfWinExist, %NAME% - Gui, Destroy - Gui, +LastFound +0xCF0000 -0x80000000 - - Gui, Add, Text, yp+11, Partial Title: - Gui, Add, Edit, xp+82 yp-3 w700 gButtonSearch vGui_title, - - Gui, Add, Text, xm, Class Name: - Gui, Add, Edit, xp+82 yp-3 w700 gButtonSearch vGui_class, - - Gui, Add, Text, xm, Process Name: - Gui, Add, Edit, xp+82 yp-3 w700 gButtonSearch vGui_pName, - - ; Gui, Add, Button, xm w800 vGui_search, Search - - Gui, Add, ListBox, +0x100 t36 xm w800 vGui_wnds, - Gui, Add, Button, Default Hidden w800 vGui_restore, Restore - - Gui, Show, AutoSize, %NAME% - Gui_wndId := WinExist() - Main_resize() - ; END: Init GUI -Return ; end of the auto-execute section - -/** - * Hotkeys, function & label definitions - */ -#IfWinActive hul! ahk_class AutoHotkeyGUI -{ - ^h::MsgBox %HELP% -} - -ButtonRestore: - Main_restore() -Return - -ButtonSearch: - Main_search() -Return - -GuiClose: - ExitApp -Return - -GuiEscape: - GuiControl, , Gui_title, - GuiControl, , Gui_class, - GuiControl, , Gui_pName, - GuiControl, , Gui_wnds, | - GuiControl, Focus, Gui_title -Return - -GuiSize: - Main_resize(A_GuiWidth, A_GuiHeight) -Return - -Main_resize(w = 0, h = 0) { - Global Gui_wndId - - If (w = 0 Or h = 0) { - Sleep, 250 - WinGetPos, x, y, w, h, ahk_id %Gui_wndId% - h += 1 - WinMove, ahk_id %Gui_wndId%, , x, y, w, h - } Else { - w -= 2 * 10 - w1 := w - (72 + 10) - h -= 3 * 30 - ; y := 8 + (3 * 30) + h + 8 - GuiControl, Move, Gui_title, w%w1% - GuiControl, Move, Gui_class, w%w1% - GuiControl, Move, Gui_pName, w%w1% - ; GuiControl, Move, Gui_search, w%w% - GuiControl, Move, Gui_wnds, w%w% h%h% - ; GuiControl, Move, Gui_restore, y%y% w%w% - } -} - -Main_restore() { - Global Gui_wnds - - GuiControlGet, wnd, , Gui_wnds - If wnd { - wndId := SubStr(wnd, 1, InStr(wnd, ": ") - 1) - WinShow, ahk_id %wndId% - WinRestore, ahk_id %wndId% - WinSet, AlwaysOnTop, On, ahk_id %wndId% - WinSet, AlwaysOnTop, Off, ahk_id %wndId% - WinMove, ahk_id %wndId%, , 0, 0, 800, 600 - } Else - GuiControl, Focus, Gui_wnds -} - -Main_search() { - Global Gui_class, Gui_pName, Gui_title, Gui_wndId, Gui_wnds - - GuiControl, , Gui_wnds, | - - GuiControlGet, title, , Gui_title - - GuiControlGet, class, , Gui_class - If class - criteria .= " ahk_class " class - - GuiControlGet, pName, , Gui_pName - If pName { - Process, Exist, %pName% - If ErrorLevel - criteria .= " ahk_pid " ErrorLevel - } - - If Not (criteria Or title) - criteria := "A" - - wndListString := "" - DetectHiddenWindows, On - WinGet, wndId, List, % criteria - Loop, % wndId { - WinGetTitle, wndTitle, % "ahk_id " wndId%A_Index% - If Not (wndId%A_Index% = Gui_wndId) And (Not title Or RegExmatch(wndTitle, title)) { - WinGetClass, wndClass, % "ahk_id " wndId%A_Index% - WinGet, wndPName, ProcessName, % "ahk_id " wndId%A_Index% - WinGet, wndStyle, Style, % "ahk_id " wndId%A_Index% - WinGetPos, wndPosX, wndPosY, wndPosW, wndPosH, % "ahk_id " wndId%A_Index% - wndListString .= "|" wndId%A_Index% ": `t" wndTitle " (" wndClass ", " wndPName ", " wndStyle ", " wndPosX ", " wndPosY ", " wndPosW ", " wndPosH ")" - } - } - DetectHiddenWindows, Off - GuiControl, , Gui_wnds, % wndListString -} +/** + * hul! - Find and restore (hidden) windows + * Copyright (c) 2011 joten + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @version 0.1.0.01 (02.10.2011) + */ + +NAME := "hul!" +VERSION := "0.1.0" +HELP := +(Join +"USAGE`n +`n +Specify one, two or all of the following search criteria:`n +- Type a regular expression in the field next to 'Partial title'.`n +- Type a class name (exact match) in the field next to 'Class name'.`n +- Type a process name (e. g. the name of an exeutable, exact match) in the field next to 'Process name'.`n +`n +The search will be done on typing the search criteria.`n +`n +You may navigate between the input fields by pressing Tab (forward) or Shift+Tab (back).`n +Press Enter to go to the list box, which contains the search results.`n +Select an entry and press Enter again to restore the selected window.`n +`n +Press the Escape (Esc) key to clear all fields and go back to entering the search criteria.`n" +) + +/** + * Script settings + */ +#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases. +#NoTrayIcon +#SingleInstance force +SendMode Input ; Recommended for new scripts due to its superior speed and reliability. +SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory. +; DetectHiddenWindows, On +; SetFormat, Integer, h + +/** + * Pseudo main function + */ + WinGet, Main_aWndId, ID, A + + ; BEGIN: Init GUI + IfWinExist, %NAME% + Gui, Destroy + Gui, +LastFound +0xCF0000 -0x80000000 + + Gui, Add, Text, yp+11, Partial Title: + Gui, Add, Edit, xp+82 yp-3 w700 gButtonSearch vGui_title, + + Gui, Add, Text, xm, Class Name: + Gui, Add, Edit, xp+82 yp-3 w700 gButtonSearch vGui_class, + + Gui, Add, Text, xm, Process Name: + Gui, Add, Edit, xp+82 yp-3 w700 gButtonSearch vGui_pName, + + ; Gui, Add, Button, xm w800 vGui_search, Search + + Gui, Add, ListBox, +0x100 t36 xm w800 vGui_wnds, + Gui, Add, Button, Default Hidden w800 vGui_restore, Restore + + Gui, Show, AutoSize, %NAME% + Gui_wndId := WinExist() + Main_resize() + ; END: Init GUI +Return ; end of the auto-execute section + +/** + * Hotkeys, function & label definitions + */ +#IfWinActive hul! ahk_class AutoHotkeyGUI +{ + ^h::MsgBox %HELP% +} + +ButtonRestore: + Main_restore() +Return + +ButtonSearch: + Main_search() +Return + +GuiClose: + ExitApp +Return + +GuiEscape: + GuiControl, , Gui_title, + GuiControl, , Gui_class, + GuiControl, , Gui_pName, + GuiControl, , Gui_wnds, | + GuiControl, Focus, Gui_title +Return + +GuiSize: + Main_resize(A_GuiWidth, A_GuiHeight) +Return + +Main_resize(w = 0, h = 0) { + Global Gui_wndId + + If (w = 0 Or h = 0) { + Sleep, 250 + WinGetPos, x, y, w, h, ahk_id %Gui_wndId% + h += 1 + WinMove, ahk_id %Gui_wndId%, , x, y, w, h + } Else { + w -= 2 * 10 + w1 := w - (72 + 10) + h -= 3 * 30 + ; y := 8 + (3 * 30) + h + 8 + GuiControl, Move, Gui_title, w%w1% + GuiControl, Move, Gui_class, w%w1% + GuiControl, Move, Gui_pName, w%w1% + ; GuiControl, Move, Gui_search, w%w% + GuiControl, Move, Gui_wnds, w%w% h%h% + ; GuiControl, Move, Gui_restore, y%y% w%w% + } +} + +Main_restore() { + Global Gui_wnds + + GuiControlGet, wnd, , Gui_wnds + If wnd { + wndId := SubStr(wnd, 1, InStr(wnd, ": ") - 1) + WinShow, ahk_id %wndId% + WinRestore, ahk_id %wndId% + WinSet, AlwaysOnTop, On, ahk_id %wndId% + WinSet, AlwaysOnTop, Off, ahk_id %wndId% + WinMove, ahk_id %wndId%, , 0, 0, 800, 600 + } Else + GuiControl, Focus, Gui_wnds +} + +Main_search() { + Global Gui_class, Gui_pName, Gui_title, Gui_wndId, Gui_wnds + + GuiControl, , Gui_wnds, | + + GuiControlGet, title, , Gui_title + + GuiControlGet, class, , Gui_class + If class + criteria .= " ahk_class " class + + GuiControlGet, pName, , Gui_pName + If pName { + Process, Exist, %pName% + If ErrorLevel + criteria .= " ahk_pid " ErrorLevel + } + + If Not (criteria Or title) + criteria := "A" + + wndListString := "" + DetectHiddenWindows, On + WinGet, wndId, List, % criteria + Loop, % wndId { + WinGetTitle, wndTitle, % "ahk_id " wndId%A_Index% + If Not (wndId%A_Index% = Gui_wndId) And (Not title Or RegExmatch(wndTitle, title)) { + WinGetClass, wndClass, % "ahk_id " wndId%A_Index% + WinGet, wndPName, ProcessName, % "ahk_id " wndId%A_Index% + WinGet, wndStyle, Style, % "ahk_id " wndId%A_Index% + WinGetPos, wndPosX, wndPosY, wndPosW, wndPosH, % "ahk_id " wndId%A_Index% + wndListString .= "|" wndId%A_Index% ": `t" wndTitle " (" wndClass ", " wndPName ", " wndStyle ", " wndPosX ", " wndPosY ", " wndPosW ", " wndPosH ")" + } + } + DetectHiddenWindows, Off + GuiControl, , Gui_wnds, % wndListString +}