From 65e20770f9e90986ba2b78a322d14950e95406f5 Mon Sep 17 00:00:00 2001 From: joten Date: Sun, 17 Jun 2012 16:32:48 +0200 Subject: [PATCH 01/60] changed hotkeys for View_setGapWidth (compatibility to US-keyboard) --- src/Config.ahk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index f1b6139..a8958e5 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -401,8 +401,8 @@ Config_saveSession() { #^+Tab::View_rotateLayoutAxis(3, +1) ; Rotate the stack axis (i. e. 3 -> 1 = x-axis = horizontal stack, 1 -> 2 = y-axis = vertical stack, 2 -> 3 = z-axis = monocle, only for the "tile" layout). #^Left::View_setMSplit(+1) ; Move the master splitter, i. e. decrease the number of windows in the master area (only for the "tile" layout). #^Right::View_setMSplit(-1) ; Move the master splitter, i. e. increase the number of windows in the master area (only for the "tile" layout). -#<::View_setGapWidth(-2) ; Decrease the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). -#+<::View_setGapWidth(+2) ; Increase the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). +#+Left::View_setGapWidth(-2) ; Decrease the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). +#+Right::View_setGapWidth(+2) ; Increase the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). #BackSpace::Monitor_activateView(-1) ; Activate the previously activated view. You may also use Monitor_activateView("<") or Monitor_activateView(">") for activating the previous or next adjacent view. #+0::Monitor_setWindowTag(0) ; Tag the active window with all tags (1 ... Config_viewCount). You may also use Monitor_setWindowTag("<") or Monitor_setWindowTag(">") for setting the tag of the previous or next adjacent to the current view. From bebe6826e5ee121feed266548f3ddfa3bb856771 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs Date: Sun, 17 Jun 2012 10:35:05 -0400 Subject: [PATCH 02/60] Remove a derived file --- bugn.exe | Bin 224184 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 bugn.exe diff --git a/bugn.exe b/bugn.exe deleted file mode 100644 index 5b7abc7e68d03edfedf355fe965201227b1f1135..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 224184 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 z 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 From 65090c573c95fd1ab0d8b2809db5c4033e10ddc4 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs Date: Sun, 17 Jun 2012 10:35:44 -0400 Subject: [PATCH 03/60] Making some shortcuts more reasonable --- src/Config.ahk | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index f1b6139..b8c6d7f 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -375,8 +375,8 @@ Config_saveSession() { * format: ::() * modifier: ! = Alt (Mod1Mask), ^ = Ctrl (ControlMask), + = Shift (ShiftMask), # = LWin (Mod4Mask) */ -#Down::View_activateWindow(+1) ; Activate the next window in the active view. -#Up::View_activateWindow(-1) ; Activate the previous window in the active view. +#m::View_activateWindow(+1) ; Activate the next window in the active view. +#n::View_activateWindow(-1) ; Activate the previous window in the active view. #+Down::View_shuffleWindow(+1) ; Move the active window to the next position in the window list of the view. #+Up::View_shuffleWindow(-1) ; Move the active window to the previous position in the window list of the view. #+Enter::View_shuffleWindow(0) ; Move the active window to the first position in the window list of the view. @@ -390,9 +390,9 @@ Config_saveSession() { #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). #Tab::View_setLayout(-1) ; Set the previously set layout. You may also use View_setLayout(">") for setting the next layout in the layout array. -#f::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). -#m::View_setLayout(2) ; Set the 2nd defined layout (i. e. monocle layout in the default configuration). -#t::View_setLayout(1) ; Set the 1st defined layout (i. e. tile layout in the default configuration). +#\::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). +#]::View_setLayout(2) ; Set the 2nd defined layout (i. e. monocle layout in the default configuration). +#[::View_setLayout(1) ; Set the 1st defined layout (i. e. tile layout in the default configuration). #Left::View_setMFactor(-0.05) ; Reduce the size of the master area in the active view (only for the "tile" layout). #Right::View_setMFactor(+0.05) ; Enlarge the size of the master area in the active view (only for the "tile" layout). #^t::View_rotateLayoutAxis(1, +1) ; Rotate the layout axis (i. e. 2 -> 1 = vertical layout, 1 -> 2 = horizontal layout, only for the "tile" layout). @@ -449,4 +449,4 @@ Config_saveSession() { #^r::Main_reload() ; Reload bug.n (i. e. the configuration and its dependent settings) without deleting the window lists of bug.n and restoring windows. ; It does not reset internal configuration variables, the tray icon or menu, hotkeys (unless set explicitly in Config.ini), individual window settings like Config_showBorder (since windows might be hidden) or hiding the title bar, the monitor count or views. ; It does not reload functions. Changed rules are only applied to new windows. -#^q::ExitApp ; Quit bug.n, restore the default Windows UI and show all windows. +#Esc::ExitApp ; Quit bug.n, restore the default Windows UI and show all windows. From a82d486a3563775578968425679e7e6856e7fce4 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs Date: Sun, 17 Jun 2012 10:35:57 -0400 Subject: [PATCH 04/60] Added some basic logging --- src/Log.ahk | 25 +++++++++++++++++++++++++ src/Main.ahk | 3 +++ 2 files changed, 28 insertions(+) create mode 100755 src/Log.ahk diff --git a/src/Log.ahk b/src/Log.ahk new file mode 100755 index 0000000..9daef4e --- /dev/null +++ b/src/Log.ahk @@ -0,0 +1,25 @@ +/** + * bug.n - tiling window management + * Copyright (c) 2010-2012 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 . + * + * @version 8.3.0 + */ + +Log_msg( message ) { + FormatTime, CurrentTime, , yyyyMMddHHmmss + FileAppend, %CurrentTime% %message%`r`n, bugn_log.txt +} + \ No newline at end of file diff --git a/src/Main.ahk b/src/Main.ahk index 96db310..085a889 100644 --- a/src/Main.ahk +++ b/src/Main.ahk @@ -32,6 +32,7 @@ SetWinDelay, 10 #WinActivateForce ; pseudo main function + Log_msg("====== Initializing ======") If 0 = 1 Config_filePath = %1% Config_init() @@ -52,6 +53,7 @@ Return ; end of the auto-execute section * function & label definitions */ Main_cleanup: ; The labels with "ExitApp" or "Return" at the end and hotkeys have to be after the auto-execute section. + Log_msg("====== Cleaning up ======") If Config_autoSaveSession Config_saveSession() Manager_cleanup() @@ -129,6 +131,7 @@ Main_toggleBar: Monitor_toggleBar() Return +#Include Log.ahk #Include Bar.ahk #Include Config.ahk #Include Manager.ahk From 60267c33389a9ecb25287618686c9201c6ac0198 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs Date: Thu, 21 Jun 2012 18:48:37 -0400 Subject: [PATCH 05/60] Cleanup/optimization of view update code --- src/Bar.ahk | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/src/Bar.ahk b/src/Bar.ahk index c24cfbc..b70a2f6 100644 --- a/src/Bar.ahk +++ b/src/Bar.ahk @@ -697,28 +697,34 @@ Bar_updateTitle(debugMsg = "") { Bar_aWndId := aWndId } +; Update the view portion of the status bar. Bar_updateView(m, v) { - Local managedWndId0, wndId0, wndIds + Local IdsLen, ViewIdsLen - StringTrimRight, wndIds, Manager_managedWndIds, 1 - StringSplit, managedWndId, wndIds, `; GuiN := (m - 1) + 1 Gui, %GuiN%: Default + + IdsLen := StrLen(Manager_managedWndIds) + + If (v = Monitor_#%m%_aView_#1) { + ; Set foreground/background colors if the view is the current view. + GuiControl, +Background%Config_selBgColor1% +c%Config_selFgColor2%, Bar_#%m%_#%v%_tagged + GuiControl, +c%Config_selFgColor1%, Bar_#%m%_#%v% + } Else If StrLen(View_#%m%_#%v%_wndIds) > 0 { + ; Set foreground/background colors if the view contains windows. + GuiControl, +Background%Config_normBgColor5% +c%Config_normFgColor8%, Bar_#%m%_#%v%_tagged + GuiControl, +c%Config_normFgColor7%, Bar_#%m%_#%v% + } Else { + ; Set foreground/background colors if the view is empty. + GuiControl, +Background%Config_normBgColor1% +c%Config_normFgColor8%, Bar_#%m%_#%v%_tagged + GuiControl, +c%Config_normFgColor1%, Bar_#%m%_#%v% + } + Loop, %Config_viewCount% { - StringTrimRight, wndIds, View_#%m%_#%A_Index%_wndIds, 1 - StringSplit, wndId, wndIds, `; - If (A_Index = v) - If (v = Monitor_#%m%_aView_#1) { - GuiControl, +Background%Config_selBgColor1% +c%Config_selFgColor2%, Bar_#%m%_#%v%_tagged - GuiControl, +c%Config_selFgColor1%, Bar_#%m%_#%v% - } Else If wndId0 { - GuiControl, +Background%Config_normBgColor5% +c%Config_normFgColor8%, Bar_#%m%_#%v%_tagged - GuiControl, +c%Config_normFgColor7%, Bar_#%m%_#%v% - } Else { - GuiControl, +Background%Config_normBgColor1% +c%Config_normFgColor8%, Bar_#%m%_#%v%_tagged - GuiControl, +c%Config_normFgColor1%, Bar_#%m%_#%v% - } - GuiControl, , Bar_#%m%_#%A_Index%_tagged, % wndId0 / managedWndId0 * 100 + ViewIdsLen := StrLen( View_#%m%_#%A_Index%_wndIds ) + ; Update the percentage fill for the view. + GuiControl, , Bar_#%m%_#%A_Index%_tagged, % ViewIdsLen / IdsLen * 100 + ; Refresh the number on the bar. GuiControl, , Bar_#%m%_#%A_Index%, %A_Index% } } From 5276471f4900ed7154490a37f84a726d33c6c2f9 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs Date: Thu, 21 Jun 2012 18:53:03 -0400 Subject: [PATCH 06/60] Spelling corrections and layout consistency --- src/Config.ahk | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index b8c6d7f..efe0763 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -23,11 +23,11 @@ Config_init() { ; status bar Config_showBar := True ; If false, the bar is hidden. It can be made visible or hidden by hotkey (see below). - Config_horizontalBarPos := "left" ; The horizontal position of the bar: "center", "left" or "right" side of the monitor or an offset in pixel (px) from the left (>= 0) or right (< 0). - Config_verticalBarPos := "top" ; The vertical position of the bar: "top" or "bottom" of the monitor, "tray" = sub-window of the task bar. - Config_barWidth := "100%" ; The width of the bar in pixel (px) or with a per cent sign (%) as a percentage. - Config_singleRowBar := True ; If false, the bar will have to rows, one for the window title and one for all other GUI controls. - Config_spaciousBar := False ; If true, the height of the bar will be set to a value equal to the height of an edit control, else it will be set to the text height. + Config_horizontalBarPos := "left" ; The horizontal position of the bar: "center", "left" or "right" side of the monitor or an offset in pixel (px) from the left (>= 0) or right (< 0). + Config_verticalBarPos := "top" ; The vertical position of the bar: "top" or "bottom" of the monitor, "tray" = sub-window of the task bar. + Config_barWidth := "100%" ; The width of the bar in pixel (px) or with a per cent sign (%) as a percentage. + Config_singleRowBar := True ; If false, the bar will have to rows, one for the window title and one for all other GUI controls. + Config_spaciousBar := False ; If true, the height of the bar will be set to a value equal to the height of an edit control, else it will be set to the text height. Config_fontName := "Lucida Console" ; A monospace font is preferable for bug.n to calculate the correct width of the bar and its elements (sub-windows). Config_fontSize := Config_normBgColor := @@ -37,7 +37,7 @@ Config_init() { Config_readinBat := False ; If true, the system battery status is read in and displayed in the status bar. This only makes sense, if you have a system battery (notebook). Config_readinCpu := False ; If true, the current CPU load is read in and displayed in the status bar. Config_readinDate := True ; If true, the current date is read in (format: "WW, DD. MMM. YYYY") and displayed in the status bar. - Config_readinDiskLoad := False ; If true, the current disk load (read and write) is read in and displayed in the status bar. + Config_readinDiskLoad := False ; If true, the current disk load (read and write) is read in and displayed in the status bar. Config_readinMemoryUsage := False ; If true, the system memory usage is read in and displayed in the status bar. Config_readinNetworkLoad := False ; If true, the current network load (up and down) is read in and displayed in the status bar. Config_readinTime := True ; If true, the current time is read in (format: "HH:MM") and displayed in the status bar. @@ -60,13 +60,13 @@ Config_init() { Config_layoutAxis_#1 := 1 ; The layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top. Config_layoutAxis_#2 := 2 ; The master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle). Config_layoutAxis_#3 := 2 ; The stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle). - Config_layoutGapWidth := 0 ; The default gap width in px (only even numbers) of the "tile" layout, i. e. the space between windows and around the layout. + Config_layoutGapWidth := 0 ; The default gap width in px (only even numbers) of the "tile" layout, i. e. the space between windows and around the layout. Config_layoutMFactor := 0.6 ; The factor for the size of the master area, which is multiplied by the monitor size. Config_mouseFollowsFocus := True ; If true, the mouse pointer is set over the focused window, if a window is activated by bug.n. Config_onActiveHiddenWnds := "view" ; The action, which will be taken, if a window e. g. should be activated, but is not visible; "view": show the view accordng to the first tag of the window in question, "tag": add the window in question to the current visible view, "hide": hide the window again ignoring the activation. - Config_newWndPosition := "top" ; The position of a new window in a view; "top": at the beginning of the window list and the master area (default), "masterBottom": at the end of the master area, "stackTop": on top of the stack area, "bottom": at the end of the window list and the stack area. + Config_newWndPosition := "top" ; The position of a new window in a view; "top": at the beginning of the window list and the master area (default), "masterBottom": at the end of the master area, "stackTop": on top of the stack area, "bottom": at the end of the window list and the stack area. Config_shellMsgDelay := 350 ; The time bug.n waits after a shell message (a window is opened, closed or the focus has been changed); if there are any problems recognizing, when windows are opened or closed, try to increase this number. - Config_syncMonitorViews := 0 ; The number of monitors (2 or more), for which views should be activated, when using the accordant hotkey. If set to 1, the views are actiated for all monitors. If set to 0, views are activated independently (only on the active monitor). + Config_syncMonitorViews := 0 ; The number of monitors (2 or more), for which views should be activated, when using the accordant hotkey. If set to 1, the views are activated for all monitors. If set to 0, views are activated independently (only on the active monitor). Config_viewFollowsTagged := False ; If true and a window is tagged with a single tag, the view is correspondingly set to the tag. ; Config_rule_#i := ";;<window style (hexadecimal number or blank)>; From 8e5e42a653ffc847eca0a7f2869e8ca2eb0a2c08 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Thu, 21 Jun 2012 18:54:00 -0400 Subject: [PATCH 07/60] Update the layout of the current view if it is re-activated. --- src/Monitor.ahk | 106 ++++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 49 deletions(-) diff --git a/src/Monitor.ahk b/src/Monitor.ahk index c98187d..5a9e422 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -40,56 +40,64 @@ Monitor_activateView(v) { v := Manager_loop(Monitor_#%Manager_aMonitor%_aView_#1, +1, 1, Config_viewCount) Else If (v = "<") v := Manager_loop(Monitor_#%Manager_aMonitor%_aView_#1, -1, 1, Config_viewCount) - If (v > 0) And (v <= Config_viewCount) And Not Manager_hideShow And Not (v = Monitor_#%Manager_aMonitor%_aView_#1) { - aView := Monitor_#%Manager_aMonitor%_aView_#1 - WinGet, aWndId, ID, A - If WinExist("ahk_id" aWndId) And InStr(View_#%Manager_aMonitor%_#%aView%_wndIds, aWndId ";") { - WinGetClass, aWndClass, ahk_id %aWndId% - WinGetTitle, aWndTitle, ahk_id %aWndId% - If Not (aWndClass = "Progman") And Not (aWndClass = "AutoHotkeyGui" And SubStr(aWndTitle, 1, 10) = "bug.n_BAR_") And Not (aWndClass = "DesktopBackgroundClass") - View_#%Manager_aMonitor%_#%aView%_aWndId := aWndId - } - - n := Config_syncMonitorViews - If (n = 1) - n := Manager_monitorCount - Else If (n < 1) - n := 1 - Loop, % n { - If (n = 1) - m := Manager_aMonitor - Else - m := A_Index - - Monitor_#%m%_aView_#2 := aView - Monitor_#%m%_aView_#1 := v - - Manager_hideShow := True - StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 - Loop, PARSE, wndIds, `; - If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) - WinHide, ahk_id %A_LoopField% - StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 - Loop, PARSE, wndIds, `; - WinShow, ahk_id %A_LoopField% - Manager_hideShow := False - - Bar_updateView(m, aView) - Bar_updateView(m, v) - - View_arrange(m, v) - } - - wndId := View_#%Manager_aMonitor%_#%v%_aWndId - If Not (wndId And WinExist("ahk_id" wndId)) { - If View_#%Manager_aMonitor%_#%v%_wndIds { - wndId := SubStr(View_#%Manager_aMonitor%_#%v%_wndIds, 1, InStr(View_#%Manager_aMonitor%_#%v%_wndIds, ";")-1) - View_#%Manager_aMonitor%_#%v%_aWndId := wndId - } Else - wndId := 0 - } - Manager_winActivate(wndId) + + ;Log_msg("Monitor_activateView(" . v . ") wndIds: " . View_#%m%_#%aView%_wndIds) + + If (v <= 0) Or (v > Config_viewCount) Or Manager_hideShow + Return + ; Re-arrange the windows on the view. + If (v = Monitor_#%Manager_aMonitor%_aView_#1) { + View_arrange(Manager_aMonitor, v) + Return } + + aView := Monitor_#%Manager_aMonitor%_aView_#1 + WinGet, aWndId, ID, A + If WinExist("ahk_id" aWndId) And InStr(View_#%Manager_aMonitor%_#%aView%_wndIds, aWndId ";") { + WinGetClass, aWndClass, ahk_id %aWndId% + WinGetTitle, aWndTitle, ahk_id %aWndId% + If Not (aWndClass = "Progman") And Not (aWndClass = "AutoHotkeyGui" And SubStr(aWndTitle, 1, 10) = "bug.n_BAR_") And Not (aWndClass = "DesktopBackgroundClass") + View_#%Manager_aMonitor%_#%aView%_aWndId := aWndId + } + + n := 1 + If (Config_syncMonitorViews > 0) + n := Manager_monitorCount + Loop, % n { + If (n = 1) + m := Manager_aMonitor + Else + m := A_Index + + Monitor_#%m%_aView_#2 := aView + Monitor_#%m%_aView_#1 := v + + Manager_hideShow := True + StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 + Loop, PARSE, wndIds, `; + If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) + WinHide, ahk_id %A_LoopField% + StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 + DetectHiddenWindows, On + View_arrange(m, v) + DetectHiddenWindows, Off + Loop, PARSE, wndIds, `; + WinShow, ahk_id %A_LoopField% + Manager_hideShow := False + + Bar_updateView(m, aView) + Bar_updateView(m, v) + } + + wndId := View_#%Manager_aMonitor%_#%v%_aWndId + If Not (wndId And WinExist("ahk_id" wndId)) { + If View_#%Manager_aMonitor%_#%v%_wndIds { + wndId := SubStr(View_#%Manager_aMonitor%_#%v%_wndIds, 1, InStr(View_#%Manager_aMonitor%_#%v%_wndIds, ";")-1) + View_#%Manager_aMonitor%_#%v%_aWndId := wndId + } Else + wndId := 0 + } + Manager_winActivate(wndId) } Monitor_get(x, y) { From 917cf2769d2ed7f8d70593df03dcf9679224ae04 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 18:00:55 -0400 Subject: [PATCH 08/60] Hotkey consistency --- src/Config.ahk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index efe0763..54f6fc1 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -60,11 +60,11 @@ Config_init() { Config_layoutAxis_#1 := 1 ; The layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top. Config_layoutAxis_#2 := 2 ; The master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle). Config_layoutAxis_#3 := 2 ; The stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle). - Config_layoutGapWidth := 0 ; The default gap width in px (only even numbers) of the "tile" layout, i. e. the space between windows and around the layout. + Config_layoutGapWidth := -4 ; The default gap width in px (only even numbers) of the "tile" layout, i. e. the space between windows and around the layout. Config_layoutMFactor := 0.6 ; The factor for the size of the master area, which is multiplied by the monitor size. Config_mouseFollowsFocus := True ; If true, the mouse pointer is set over the focused window, if a window is activated by bug.n. Config_onActiveHiddenWnds := "view" ; The action, which will be taken, if a window e. g. should be activated, but is not visible; "view": show the view accordng to the first tag of the window in question, "tag": add the window in question to the current visible view, "hide": hide the window again ignoring the activation. - Config_newWndPosition := "top" ; The position of a new window in a view; "top": at the beginning of the window list and the master area (default), "masterBottom": at the end of the master area, "stackTop": on top of the stack area, "bottom": at the end of the window list and the stack area. + Config_newWndPosition := "bottom" ; The position of a new window in a view; "top": at the beginning of the window list and the master area (default), "masterBottom": at the end of the master area, "stackTop": on top of the stack area, "bottom": at the end of the window list and the stack area. Config_shellMsgDelay := 350 ; The time bug.n waits after a shell message (a window is opened, closed or the focus has been changed); if there are any problems recognizing, when windows are opened or closed, try to increase this number. Config_syncMonitorViews := 0 ; The number of monitors (2 or more), for which views should be activated, when using the accordant hotkey. If set to 1, the views are activated for all monitors. If set to 0, views are activated independently (only on the active monitor). Config_viewFollowsTagged := False ; If true and a window is tagged with a single tag, the view is correspondingly set to the tag. @@ -377,8 +377,8 @@ Config_saveSession() { */ #m::View_activateWindow(+1) ; Activate the next window in the active view. #n::View_activateWindow(-1) ; Activate the previous window in the active view. -#+Down::View_shuffleWindow(+1) ; Move the active window to the next position in the window list of the view. -#+Up::View_shuffleWindow(-1) ; Move the active window to the previous position in the window list of the view. +#+m::View_shuffleWindow(+1) ; Move the active window to the next position in the window list of the view. +#+n::View_shuffleWindow(-1) ; Move the active window to the previous position in the window list of the view. #+Enter::View_shuffleWindow(0) ; Move the active window to the first position in the window list of the view. #c::Manager_closeWindow() ; Close the active window. #+d::Manager_toggleDecor() ; Show / Hide the title bar of the active window. From e06afcd299bedf6718ca3f7e21f635066e8c2db2 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 18:09:54 -0400 Subject: [PATCH 09/60] Hotkey correction --- src/Config.ahk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config.ahk b/src/Config.ahk index 54f6fc1..56a2f5b 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -383,7 +383,7 @@ Config_saveSession() { #c::Manager_closeWindow() ; Close the active window. #+d::Manager_toggleDecor() ; Show / Hide the title bar of the active window. #+f::View_toggleFloating() ; Toggle the floating status of the active window (i. e. dis- / regard it when tiling). -#+m::Manager_moveWindow() ; Move the active window by key (only floating windows). +#+q::Manager_moveWindow() ; Move the active window by key (only floating windows). #+s::Manager_sizeWindow() ; Resize the active window by key (only floating windows). #+x::Manager_maximizeWindow() ; Move and resize the active window to the size of the work area (only floating windows). #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). From b263ba0daf0a1afabff335df4cfacd949afb73f1 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 19:45:39 -0400 Subject: [PATCH 10/60] Added bare logging capability --- src/Config.ahk | 1 + src/Log.ahk | 5 ++++- src/Manager.ahk | 43 +++++++++++++++++++++++++++++++++++++++++++ src/Monitor.ahk | 8 ++++---- 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index 56a2f5b..f5a04d2 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -388,6 +388,7 @@ Config_saveSession() { #+x::Manager_maximizeWindow() ; Move and resize the active window to the size of the work area (only floating windows). #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). +#^i::Manager_logWindowList() #Tab::View_setLayout(-1) ; Set the previously set layout. You may also use View_setLayout(">") for setting the next layout in the layout array. #\::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). diff --git a/src/Log.ahk b/src/Log.ahk index 9daef4e..0785807 100755 --- a/src/Log.ahk +++ b/src/Log.ahk @@ -22,4 +22,7 @@ Log_msg( message ) { FormatTime, CurrentTime, , yyyyMMddHHmmss FileAppend, %CurrentTime% %message%`r`n, bugn_log.txt } - \ No newline at end of file + +Log_bare( message ) { + FileAppend, %message%`r`n, bugn_log.txt +} \ No newline at end of file diff --git a/src/Manager.ahk b/src/Manager.ahk index 78f50ad..1c108bc 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -238,6 +238,48 @@ Manager_getWindowList() { Clipboard := text } +Manager_logWindowInfo( w ) { + Local av, aWndId, aIsWinFocus, aIsBugnActive, aIsFloating, aIsHidden, aWndTitle, aWndStyle, aWndX, aWndY, aWndW, aWndH + + WinGet, aWndId, ID, A + If aWndId = %w% + aIsWinFocus := "*" + Else + aIsWinFocus := " " + av := Monitor_#%Manager_aMonitor%_aView_#1 + If View_#%Manager_aMonitor%_#%av%_aWndId = %w% + aIsBugnActive := "*" + Else + aIsBugnActive := " " + WinGetTitle, aWndTitle, ahk_id %w% + If InStr(Bar_hiddenWndIds, w) + aIsHidden := "*" + Else + aIsHidden := " " + If Manager_#%w%_isFloating + aIsFloating := "*" + Else + aIsFloating := " " + WinGet, aWndStyle, Style, ahk_id %w% + WinGetPos, aWndX, aWndY, aWndW, aWndH, ahk_id %w% + + Log_bare(" " . w . "`t" . aIsBugnActive . " " . aIsFloating . " " . aIsHidden . " " aIsWinFocus . "`t" . aWndX . "`t" . aWndY . "`t" . aWndW . "`t" . aWndH . "`t" . aWndStyle . "`t" . aWndTitle) +} + +Manager_logWindowList() { + Local text, v, aWndId, wndIds, aWndTitle + + v := Monitor_#%Manager_aMonitor%_aView_#1 + Log_msg( "Window dump for active view (" . Manager_aMonitor . ", " . v . ")" ) + Log_bare( " ID`t`tA F H W`tX`tY`tW`tH`tStyle`t`tTitle") + + StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 + Loop, PARSE, wndIds, `; + { + Manager_logWindowInfo( A_LoopField ) + } +} + Manager_lockWorkStation() { Global Config_shellMsgDelay @@ -536,6 +578,7 @@ Manager_sync(ByRef wndIds = "") { shownWndIds .= View_#%A_Index%_#%v%_wndIds } ; check all visible windows against the known windows + ; DetectHiddenWindows, On WinGet, wndId, List, , , Loop, % wndId { If Not InStr(shownWndIds, wndId%A_Index% ";") { diff --git a/src/Monitor.ahk b/src/Monitor.ahk index 5a9e422..b274077 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -73,16 +73,16 @@ Monitor_activateView(v) { Monitor_#%m%_aView_#1 := v Manager_hideShow := True - StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 - Loop, PARSE, wndIds, `; - If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) - WinHide, ahk_id %A_LoopField% StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 DetectHiddenWindows, On View_arrange(m, v) DetectHiddenWindows, Off Loop, PARSE, wndIds, `; WinShow, ahk_id %A_LoopField% + StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 + Loop, PARSE, wndIds, `; + If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) + WinHide, ahk_id %A_LoopField% Manager_hideShow := False Bar_updateView(m, aView) From 0666a89c503677d884570b547f4fa695e87fc5b0 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 19:54:44 -0400 Subject: [PATCH 11/60] Revert previous changeset since it did too much --- src/Config.ahk | 1 - src/Log.ahk | 5 +---- src/Manager.ahk | 43 ------------------------------------------- src/Monitor.ahk | 8 ++++---- 4 files changed, 5 insertions(+), 52 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index f5a04d2..56a2f5b 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -388,7 +388,6 @@ Config_saveSession() { #+x::Manager_maximizeWindow() ; Move and resize the active window to the size of the work area (only floating windows). #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). -#^i::Manager_logWindowList() #Tab::View_setLayout(-1) ; Set the previously set layout. You may also use View_setLayout(">") for setting the next layout in the layout array. #\::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). diff --git a/src/Log.ahk b/src/Log.ahk index 0785807..9daef4e 100755 --- a/src/Log.ahk +++ b/src/Log.ahk @@ -22,7 +22,4 @@ Log_msg( message ) { FormatTime, CurrentTime, , yyyyMMddHHmmss FileAppend, %CurrentTime% %message%`r`n, bugn_log.txt } - -Log_bare( message ) { - FileAppend, %message%`r`n, bugn_log.txt -} \ No newline at end of file + \ No newline at end of file diff --git a/src/Manager.ahk b/src/Manager.ahk index 1c108bc..78f50ad 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -238,48 +238,6 @@ Manager_getWindowList() { Clipboard := text } -Manager_logWindowInfo( w ) { - Local av, aWndId, aIsWinFocus, aIsBugnActive, aIsFloating, aIsHidden, aWndTitle, aWndStyle, aWndX, aWndY, aWndW, aWndH - - WinGet, aWndId, ID, A - If aWndId = %w% - aIsWinFocus := "*" - Else - aIsWinFocus := " " - av := Monitor_#%Manager_aMonitor%_aView_#1 - If View_#%Manager_aMonitor%_#%av%_aWndId = %w% - aIsBugnActive := "*" - Else - aIsBugnActive := " " - WinGetTitle, aWndTitle, ahk_id %w% - If InStr(Bar_hiddenWndIds, w) - aIsHidden := "*" - Else - aIsHidden := " " - If Manager_#%w%_isFloating - aIsFloating := "*" - Else - aIsFloating := " " - WinGet, aWndStyle, Style, ahk_id %w% - WinGetPos, aWndX, aWndY, aWndW, aWndH, ahk_id %w% - - Log_bare(" " . w . "`t" . aIsBugnActive . " " . aIsFloating . " " . aIsHidden . " " aIsWinFocus . "`t" . aWndX . "`t" . aWndY . "`t" . aWndW . "`t" . aWndH . "`t" . aWndStyle . "`t" . aWndTitle) -} - -Manager_logWindowList() { - Local text, v, aWndId, wndIds, aWndTitle - - v := Monitor_#%Manager_aMonitor%_aView_#1 - Log_msg( "Window dump for active view (" . Manager_aMonitor . ", " . v . ")" ) - Log_bare( " ID`t`tA F H W`tX`tY`tW`tH`tStyle`t`tTitle") - - StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 - Loop, PARSE, wndIds, `; - { - Manager_logWindowInfo( A_LoopField ) - } -} - Manager_lockWorkStation() { Global Config_shellMsgDelay @@ -578,7 +536,6 @@ Manager_sync(ByRef wndIds = "") { shownWndIds .= View_#%A_Index%_#%v%_wndIds } ; check all visible windows against the known windows - ; DetectHiddenWindows, On WinGet, wndId, List, , , Loop, % wndId { If Not InStr(shownWndIds, wndId%A_Index% ";") { diff --git a/src/Monitor.ahk b/src/Monitor.ahk index b274077..5a9e422 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -73,16 +73,16 @@ Monitor_activateView(v) { Monitor_#%m%_aView_#1 := v Manager_hideShow := True + StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 + Loop, PARSE, wndIds, `; + If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) + WinHide, ahk_id %A_LoopField% StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 DetectHiddenWindows, On View_arrange(m, v) DetectHiddenWindows, Off Loop, PARSE, wndIds, `; WinShow, ahk_id %A_LoopField% - StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 - Loop, PARSE, wndIds, `; - If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) - WinHide, ahk_id %A_LoopField% Manager_hideShow := False Bar_updateView(m, aView) From 61641abdca82fdc56a1efd90dd1d691d88350278 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 19:55:33 -0400 Subject: [PATCH 12/60] Added bare logging --- src/Log.ahk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Log.ahk b/src/Log.ahk index 9daef4e..0785807 100755 --- a/src/Log.ahk +++ b/src/Log.ahk @@ -22,4 +22,7 @@ Log_msg( message ) { FormatTime, CurrentTime, , yyyyMMddHHmmss FileAppend, %CurrentTime% %message%`r`n, bugn_log.txt } - \ No newline at end of file + +Log_bare( message ) { + FileAppend, %message%`r`n, bugn_log.txt +} \ No newline at end of file From 8c2272bc80f7dc583aee1c7c595ea97174e7bb63 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 19:56:13 -0400 Subject: [PATCH 13/60] Added logging of windows from a view --- src/Manager.ahk | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/Manager.ahk b/src/Manager.ahk index 78f50ad..1c108bc 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -238,6 +238,48 @@ Manager_getWindowList() { Clipboard := text } +Manager_logWindowInfo( w ) { + Local av, aWndId, aIsWinFocus, aIsBugnActive, aIsFloating, aIsHidden, aWndTitle, aWndStyle, aWndX, aWndY, aWndW, aWndH + + WinGet, aWndId, ID, A + If aWndId = %w% + aIsWinFocus := "*" + Else + aIsWinFocus := " " + av := Monitor_#%Manager_aMonitor%_aView_#1 + If View_#%Manager_aMonitor%_#%av%_aWndId = %w% + aIsBugnActive := "*" + Else + aIsBugnActive := " " + WinGetTitle, aWndTitle, ahk_id %w% + If InStr(Bar_hiddenWndIds, w) + aIsHidden := "*" + Else + aIsHidden := " " + If Manager_#%w%_isFloating + aIsFloating := "*" + Else + aIsFloating := " " + WinGet, aWndStyle, Style, ahk_id %w% + WinGetPos, aWndX, aWndY, aWndW, aWndH, ahk_id %w% + + Log_bare(" " . w . "`t" . aIsBugnActive . " " . aIsFloating . " " . aIsHidden . " " aIsWinFocus . "`t" . aWndX . "`t" . aWndY . "`t" . aWndW . "`t" . aWndH . "`t" . aWndStyle . "`t" . aWndTitle) +} + +Manager_logWindowList() { + Local text, v, aWndId, wndIds, aWndTitle + + v := Monitor_#%Manager_aMonitor%_aView_#1 + Log_msg( "Window dump for active view (" . Manager_aMonitor . ", " . v . ")" ) + Log_bare( " ID`t`tA F H W`tX`tY`tW`tH`tStyle`t`tTitle") + + StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 + Loop, PARSE, wndIds, `; + { + Manager_logWindowInfo( A_LoopField ) + } +} + Manager_lockWorkStation() { Global Config_shellMsgDelay @@ -536,6 +578,7 @@ Manager_sync(ByRef wndIds = "") { shownWndIds .= View_#%A_Index%_#%v%_wndIds } ; check all visible windows against the known windows + ; DetectHiddenWindows, On WinGet, wndId, List, , , Loop, % wndId { If Not InStr(shownWndIds, wndId%A_Index% ";") { From 750a281eaceec771d48c73720b6830e7c3ba4ff7 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 19:56:46 -0400 Subject: [PATCH 14/60] Dump info to the log. --- src/Config.ahk | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Config.ahk b/src/Config.ahk index 56a2f5b..f5a04d2 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -388,6 +388,7 @@ Config_saveSession() { #+x::Manager_maximizeWindow() ; Move and resize the active window to the size of the work area (only floating windows). #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). +#^i::Manager_logWindowList() #Tab::View_setLayout(-1) ; Set the previously set layout. You may also use View_setLayout(">") for setting the next layout in the layout array. #\::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). From 32e086c35a09f1aed8be9aa00221625d65bf6fb1 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 23:10:09 -0400 Subject: [PATCH 15/60] Allow for a wider layout description --- src/Bar.ahk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bar.ahk b/src/Bar.ahk index b70a2f6..63a0907 100644 --- a/src/Bar.ahk +++ b/src/Bar.ahk @@ -61,7 +61,7 @@ Bar_init(m) { } ; layout i := Config_viewCount + 1 - text := " ??? " + text := " 1x9|=- " w := Bar_getTextWidth(text) Gui, Add, Text, x%x1% y%y1% w%w% h%h1% BackgroundTrans vBar_#%m%_#%i%_layout gBar_GuiClick, Gui, Add, Progress, x%x1% y%y1% w%w% h%h1% Background%Config_normBgColor2% From 4e7da85ffc83473dfd6bff430d89a4a22f09abaf Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 23:11:52 -0400 Subject: [PATCH 16/60] Cleanup and make consistent the redrawing of views and layout symbols --- src/View.ahk | 126 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 42 deletions(-) diff --git a/src/View.ahk b/src/View.ahk index 4bd9258..4b8cd01 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -57,15 +57,21 @@ View_activateWindow(d) { } } +View_updateLayout(m, v) { + Local fn, l, wndIds + l := View_#%m%_#%v%_layout_#1 + fn := Config_layoutFunction_#%l% + View_updateLayout_%fn%(m, v) +} + View_arrange(m, v) { Local fn, l, wndIds l := View_#%m%_#%v%_layout_#1 fn := Config_layoutFunction_#%l% - If fn And (View_getTiledWndIds(m, v, wndIds) Or fn = "tile") - View_%fn%(m, v, wndIds) - Else - View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#%l% + View_getTiledWndIds(m, v, wndIds) + View_arrange_%fn%(m, v, wndIds) + View_updateLayout(m, v) Bar_updateLayout(m) } @@ -84,14 +90,33 @@ View_getTiledWndIds(m, v, ByRef tiledWndIds) { Return, n } -View_monocle(m, v, wndIds) { - Local wndId0 +View_updateLayout_(m, v) +{ + View_#%m%_#%v%_layoutSymbol := "><>" +} + +View_arrange_(m, v) +{ + ; Place-holder +} + +View_updateLayout_monocle(m, v) +{ + Local wndIds, wndId, wndId0 + StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 + StringSplit, wndId, wndIds, `; + View_#%m%_#%v%_layoutSymbol := "[" wndId0 "]" +} + +View_arrange_monocle(m, v, wndIds) { + Local wndId0, gw + + gw := View_#%m%_#%v%_layoutGapWidth StringTrimRight, wndIds, wndIds, 1 StringSplit, wndId, wndIds, `; Loop, % wndId0 - Manager_winMove(wndId%A_Index%, Monitor_#%m%_x, Monitor_#%m%_y, Monitor_#%m%_width, Monitor_#%m%_height) - View_#%m%_#%v%_layoutSymbol := "[" wndId0 "]" + Manager_winMove(wndId%A_Index%, Monitor_#%m%_x - gw/2, Monitor_#%m%_y - gw/2, Monitor_#%m%_width + gw, Monitor_#%m%_height + gw) } View_rotateLayoutAxis(i, d) { @@ -219,13 +244,59 @@ View_shuffleWindow(d) { } } -View_tile(m, v, wndIds) { - Local axis1, axis2, axis3, gapW, h1, h2, i, mfact, msplit, n1, n2, sym1, sym3, w1, w2, wndId0, x1, x2, y1, y2 +View_updateLayout_tile(m, v) { + Local axis1, axis2, axis3, msplit, sym1, sym3, master_div, master_sym, stack_sym + + ; Main axis + ; 1 - vertical divider, master left + ; 2 - horizontal divider, master top + ; -1 - vertical divider, master right + ; -2 - horizontal divider, master bottom + axis1 := View_#%m%_#%v%_layoutAxis_#1 + ; Master axis + ; 1 - vertical divider + ; 2 - horizontal divider + ; 3 - monocle + axis2 := View_#%m%_#%v%_layoutAxis_#2 + ; Stack axis + ; 1 - vertical divider + ; 2 - horizontal divider + ; 3 - monocle + axis3 := View_#%m%_#%v%_layoutAxis_#3 + msplit := View_#%m%_#%v%_layoutMSplit + + If ( Abs(axis1) = 1 ) + master_div := "|" + Else + master_div := "=" + + If ( axis2 = 1 ) + master_sym := "" . msplit . "x1|" + Else If ( axis2 = 2 ) + master_sym := "1x" . msplit . "-" + Else + master_sym := "[" . msplit . "]" + + If ( axis3 = 1 ) + stack_sym := "|" + Else If ( axis3 = 2 ) + stack_sym := "-" + Else + stack_sym := "o" + + If ( axis1 > 0 ) + View_#%m%_#%v%_layoutSymbol := master_sym . master_div . stack_sym + Else + View_#%m%_#%v%_layoutSymbol := stack_sym . master_div . master_sym +} + +View_arrange_tile(m, v, wndIds) { + Local axis1, axis2, axis3, gapW, h1, h2, i, mfact, msplit, n1, n2, w1, w2, wndId0, x1, x2, y1, y2 axis1 := View_#%m%_#%v%_layoutAxis_#1 axis2 := View_#%m%_#%v%_layoutAxis_#2 axis3 := View_#%m%_#%v%_layoutAxis_#3 - gapW := View_#%m%_#%v%_layoutGapWidth + gapW := View_#%m%_#%v%_layoutGapWidth mfact := View_#%m%_#%v%_layoutMFact msplit := View_#%m%_#%v%_layoutMSplit @@ -233,40 +304,11 @@ View_tile(m, v, wndIds) { StringSplit, wndId, wndIds, `; If (msplit > wndId0) { If (wndId0 < 1) - View_#%m%_#%v%_layoutMSplit := 1 + msplit := 1 Else - View_#%m%_#%v%_layoutMSplit := wndId0 - msplit := View_#%m%_#%v%_layoutMSplit + msplit := wndId0 } - ; layout symbol - sym1 := "=" - If (axis2 = Abs(axis1)) - sym1 := "|" - If (axis2 = 3) - If (wndId0 = 0) - sym1 := 0 - Else - sym1 := msplit - sym3 := "=" - If (axis3 = Abs(axis1)) - sym3 := "|" - If (axis3 = 3) - If (wndId0 = 0) - sym3 := 0 - Else - sym3 := wndId0 - msplit - If (axis1 < 0) - If (msplit = 1) - View_#%m%_#%v%_layoutSymbol := sym3 "[]" - Else - View_#%m%_#%v%_layoutSymbol := sym3 "[" sym1 - Else - If (msplit = 1) - View_#%m%_#%v%_layoutSymbol := "[]" sym3 - Else - View_#%m%_#%v%_layoutSymbol := sym1 "]" sym3 - If (wndId0 > 0) { ; master and stack area h1 := Monitor_#%m%_height - gapW From 043d14a569d977387fe89a14f591306ecbb40715 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 23:27:54 -0400 Subject: [PATCH 17/60] Restoring the original flow of Monitor_activateView until I understand better how to optimize. --- src/Monitor.ahk | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Monitor.ahk b/src/Monitor.ahk index 5a9e422..a0da17a 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -78,15 +78,14 @@ Monitor_activateView(v) { If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) WinHide, ahk_id %A_LoopField% StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 - DetectHiddenWindows, On - View_arrange(m, v) - DetectHiddenWindows, Off Loop, PARSE, wndIds, `; WinShow, ahk_id %A_LoopField% Manager_hideShow := False Bar_updateView(m, aView) Bar_updateView(m, v) + + View_arrange(m, v) } wndId := View_#%Manager_aMonitor%_#%v%_aWndId From cb1566d440a9327bd7b5164eb9ac86bee7474998 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 23:35:32 -0400 Subject: [PATCH 18/60] These changes prevent the user from viewing the resizing of windows from other screens. It may make the interface appear a bit more sluggish, though, since all of the rearranging must happen in the background. --- src/Monitor.ahk | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Monitor.ahk b/src/Monitor.ahk index a0da17a..5a9e422 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -78,14 +78,15 @@ Monitor_activateView(v) { If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) WinHide, ahk_id %A_LoopField% StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 + DetectHiddenWindows, On + View_arrange(m, v) + DetectHiddenWindows, Off Loop, PARSE, wndIds, `; WinShow, ahk_id %A_LoopField% Manager_hideShow := False Bar_updateView(m, aView) Bar_updateView(m, v) - - View_arrange(m, v) } wndId := View_#%Manager_aMonitor%_#%v%_aWndId From 37b4ea24194e173acfd8f2f6839919be1ed8ef6f Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 23:45:09 -0400 Subject: [PATCH 19/60] Correct the sign on monocle layout with gap width. --- src/Monitor.ahk | 13 +++++++------ src/View.ahk | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Monitor.ahk b/src/Monitor.ahk index 5a9e422..f22e2b2 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -73,16 +73,17 @@ Monitor_activateView(v) { Monitor_#%m%_aView_#1 := v Manager_hideShow := True + DetectHiddenWindows, On + View_arrange(m, v) + DetectHiddenWindows, Off + StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 + Loop, PARSE, wndIds, `; + WinShow, ahk_id %A_LoopField% StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 Loop, PARSE, wndIds, `; If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) WinHide, ahk_id %A_LoopField% - StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 - DetectHiddenWindows, On - View_arrange(m, v) - DetectHiddenWindows, Off - Loop, PARSE, wndIds, `; - WinShow, ahk_id %A_LoopField% + Manager_hideShow := False Bar_updateView(m, aView) diff --git a/src/View.ahk b/src/View.ahk index 4b8cd01..02881cc 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -116,7 +116,7 @@ View_arrange_monocle(m, v, wndIds) { StringTrimRight, wndIds, wndIds, 1 StringSplit, wndId, wndIds, `; Loop, % wndId0 - Manager_winMove(wndId%A_Index%, Monitor_#%m%_x - gw/2, Monitor_#%m%_y - gw/2, Monitor_#%m%_width + gw, Monitor_#%m%_height + gw) + Manager_winMove(wndId%A_Index%, Monitor_#%m%_x + gw/2, Monitor_#%m%_y + gw/2, Monitor_#%m%_width - gw, Monitor_#%m%_height - gw) } View_rotateLayoutAxis(i, d) { From a935d8d7cc3742257659200f8497159147cc07cb Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 22 Jun 2012 23:47:59 -0400 Subject: [PATCH 20/60] Make gap width behavior match tile layout. --- src/View.ahk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/View.ahk b/src/View.ahk index 02881cc..83a5b01 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -116,7 +116,7 @@ View_arrange_monocle(m, v, wndIds) { StringTrimRight, wndIds, wndIds, 1 StringSplit, wndId, wndIds, `; Loop, % wndId0 - Manager_winMove(wndId%A_Index%, Monitor_#%m%_x + gw/2, Monitor_#%m%_y + gw/2, Monitor_#%m%_width - gw, Monitor_#%m%_height - gw) + Manager_winMove(wndId%A_Index%, Monitor_#%m%_x + gw, Monitor_#%m%_y + gw, Monitor_#%m%_width - 2*gw, Monitor_#%m%_height - 2*gw) } View_rotateLayoutAxis(i, d) { From 0aa4b31bae18c75b64cac92b6e36119173377e95 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 00:36:00 -0400 Subject: [PATCH 21/60] Simplify some math. --- src/View.ahk | 126 ++++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/src/View.ahk b/src/View.ahk index 83a5b01..5ce8855 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -291,85 +291,87 @@ View_updateLayout_tile(m, v) { } View_arrange_tile(m, v, wndIds) { - Local axis1, axis2, axis3, gapW, h1, h2, i, mfact, msplit, n1, n2, w1, w2, wndId0, x1, x2, y1, y2 - - axis1 := View_#%m%_#%v%_layoutAxis_#1 - axis2 := View_#%m%_#%v%_layoutAxis_#2 - axis3 := View_#%m%_#%v%_layoutAxis_#3 - gapW := View_#%m%_#%v%_layoutGapWidth - mfact := View_#%m%_#%v%_layoutMFact - msplit := View_#%m%_#%v%_layoutMSplit + Local axis1, axis2, axis3, gapW, gapW_2, h1, h2, i, mfact, msplit, n1, n2, w1, w2, wndId0, x1, x2, y1, y2, oriented StringTrimRight, wndIds, wndIds, 1 StringSplit, wndId, wndIds, `; + If (wndId0 = 0) + Return + + axis1 := Abs(View_#%m%_#%v%_layoutAxis_#1) + axis2 := View_#%m%_#%v%_layoutAxis_#2 + axis3 := View_#%m%_#%v%_layoutAxis_#3 + oriented := View_#%m%_#%v%_layoutAxis_#1 > 0 + gapW := View_#%m%_#%v%_layoutGapWidth + gapW_2 := gapW/2 + mfact := View_#%m%_#%v%_layoutMFact + msplit := View_#%m%_#%v%_layoutMSplit + If (msplit > wndId0) { - If (wndId0 < 1) - msplit := 1 - Else - msplit := wndId0 + msplit := wndId0 } - If (wndId0 > 0) { - ; master and stack area - h1 := Monitor_#%m%_height - gapW - h2 := Monitor_#%m%_height - gapW - w1 := Monitor_#%m%_width - gapW - w2 := Monitor_#%m%_width - gapW - x1 := Monitor_#%m%_x + gapW / 2 - x2 := Monitor_#%m%_x + gapW / 2 - y1 := Monitor_#%m%_y + gapW / 2 - y2 := Monitor_#%m%_y + gapW / 2 - If (Abs(axis1) = 1 And wndId0 > msplit) { + ; master and stack area + h1 := Monitor_#%m%_height - gapW + h2 := h1 + w1 := Monitor_#%m%_width - gapW + w2 := w1 + x1 := Monitor_#%m%_x + gapW_2 + x2 := x1 + y1 := Monitor_#%m%_y + gapW_2 + y2 := y1 + If (wndId0 > msplit) { + If (axis1 = 1) { w1 *= mfact w2 -= w1 - If (axis1 < 0) + If (Not oriented) x1 += w2 Else x2 += w1 - } Else If (Abs(axis1) = 2 And wndId0 > msplit) { + } Else If (axis1 = 2) { h1 *= mfact h2 -= h1 - If (axis1 < 0) + If (Not oriented) y1 += h2 Else y2 += h1 - } - - ; master - If (axis2 != 1 Or w1 / msplit < 161) - n1 := 1 - Else - n1 := msplit - If (axis2 != 2 Or h1 / msplit < Bar_height) - n2 := 1 - Else - n2 := msplit - Loop, % msplit { - Manager_winMove(wndId%A_Index%, x1 + gapW / 2, y1 + gapW / 2, w1 / n1 - gapW, h1 / n2 - gapW) - If (n1 > 1) - x1 += w1 / n1 - If (n2 > 1) - y1 += h1 / n2 } - - ; stack - If (wndId0 > msplit) { - If (axis3 != 1 Or w2 / (wndId0 - msplit) < 161) - n1 := 1 - Else - n1 := wndId0 - msplit - If (axis3 != 2 Or h2 / (wndId0 - msplit) < Bar_height) - n2 := 1 - Else - n2 := wndId0 - msplit - Loop, % wndId0 - msplit { - i := msplit + A_Index - Manager_winMove(wndId%i%, x2 + gapW / 2, y2 + gapW / 2, w2 / n1 - gapW, h2 / n2 - gapW) - If (n1 > 1) - x2 += w2 / n1 - If (n2 > 1) - y2 += h2 / n2 - } + } + + ; master + If (axis2 != 1 Or w1 / msplit < 161) + n1 := w1 + Else + n1 := w1/msplit + If (axis2 != 2 Or h1 / msplit < Bar_height) + n2 := h1 + Else + n2 := h1/msplit + Loop, % msplit { + Manager_winMove(wndId%A_Index%, x1 + gapW_2, y1 + gapW_2, n1 - gapW, n2 - gapW) + If (n1 < w1) + x1 += n1 + If (n2 < h1) + y1 += n2 + } + + ; stack + If (wndId0 > msplit) { + If (axis3 != 1 Or w2 / (wndId0 - msplit) < 161) + n1 := w2 + Else + n1 := w2/(wndId0 - msplit) + If (axis3 != 2 Or h2 / (wndId0 - msplit) < Bar_height) + n2 := h2 + Else + n2 := h2/(wndId0 - msplit) + Loop, % wndId0 - msplit { + i := msplit + A_Index + Manager_winMove(wndId%i%, x2 + gapW_2, y2 + gapW_2, n1 - gapW, n2 - gapW) + If (n1 < w2) + x2 += n1 + If (n2 < h2) + y2 += n2 } } } From 10ab86187de448ffdc8017c6ab0764150708f2f0 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 00:43:26 -0400 Subject: [PATCH 22/60] Must hide before show because WinShow does not bring the new window to the top. This results in some odd looking view switches. --- src/Monitor.ahk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Monitor.ahk b/src/Monitor.ahk index f22e2b2..1cd2214 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -73,16 +73,16 @@ Monitor_activateView(v) { Monitor_#%m%_aView_#1 := v Manager_hideShow := True + StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 + Loop, PARSE, wndIds, `; + If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) + WinHide, ahk_id %A_LoopField% DetectHiddenWindows, On View_arrange(m, v) DetectHiddenWindows, Off StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 Loop, PARSE, wndIds, `; WinShow, ahk_id %A_LoopField% - StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 - Loop, PARSE, wndIds, `; - If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) - WinHide, ahk_id %A_LoopField% Manager_hideShow := False From 15b8fc2c84dce3dbaf6b890ade8c86299b2202b1 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 14:04:57 -0400 Subject: [PATCH 23/60] Create debug log --- src/Log.ahk | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/Log.ahk b/src/Log.ahk index 0785807..87f3ddb 100755 --- a/src/Log.ahk +++ b/src/Log.ahk @@ -18,11 +18,42 @@ * @version 8.3.0 */ +Log_init() { + Global + Log_debug_enabled := 0 +} + Log_msg( message ) { FormatTime, CurrentTime, , yyyyMMddHHmmss FileAppend, %CurrentTime% %message%`r`n, bugn_log.txt } Log_bare( message ) { - FileAppend, %message%`r`n, bugn_log.txt + Local padded_message + padded_message := " " . message . "`r`n" + FileAppend, %padded_message% , bugn_log.txt +} + +Log_toggleDebugEnabled() { + Global + If (Log_debug_enabled = 1) + Log_debug_enabled := 0 + Else + Log_debug_enabled := 1 + If (Log_debug_enabled = 1) + Log_msg("Debug log enabled (" . Log_debug_enabled . ")") + Else + Log_msg("Debug log disabled (" . Log_debug_enabled . ")") +} + +Log_dbg_msg( message ) { + Global + If (Log_debug_enabled = 1) + Log_msg( "DEBUG: " . message ) +} + +Log_dbg_bare( message ) { + Global + If (Log_debug_enabled = 1) + Log_msg( "DEBUG: " . message ) } \ No newline at end of file From 5631981e2e70a59a4ac0c7ab929a4d5264da5704 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 14:08:58 -0400 Subject: [PATCH 24/60] More log cleanup. Made switch to enable debug logging. --- src/Config.ahk | 1 + src/Log.ahk | 11 +++++------ src/Manager.ahk | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index f5a04d2..658f77c 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -389,6 +389,7 @@ Config_saveSession() { #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). #^i::Manager_logWindowList() +#^d::Log_toggleDebugEnabled() #Tab::View_setLayout(-1) ; Set the previously set layout. You may also use View_setLayout(">") for setting the next layout in the layout array. #\::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). diff --git a/src/Log.ahk b/src/Log.ahk index 87f3ddb..9e48013 100755 --- a/src/Log.ahk +++ b/src/Log.ahk @@ -18,11 +18,8 @@ * @version 8.3.0 */ -Log_init() { - Global - Log_debug_enabled := 0 -} - + + Log_msg( message ) { FormatTime, CurrentTime, , yyyyMMddHHmmss FileAppend, %CurrentTime% %message%`r`n, bugn_log.txt @@ -34,6 +31,8 @@ Log_bare( message ) { FileAppend, %padded_message% , bugn_log.txt } +Log_debug_enabled := 0 + Log_toggleDebugEnabled() { Global If (Log_debug_enabled = 1) @@ -55,5 +54,5 @@ Log_dbg_msg( message ) { Log_dbg_bare( message ) { Global If (Log_debug_enabled = 1) - Log_msg( "DEBUG: " . message ) + Log_bare( "DEBUG: " . message ) } \ No newline at end of file diff --git a/src/Manager.ahk b/src/Manager.ahk index 1c108bc..ecbeac1 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -263,7 +263,7 @@ Manager_logWindowInfo( w ) { WinGet, aWndStyle, Style, ahk_id %w% WinGetPos, aWndX, aWndY, aWndW, aWndH, ahk_id %w% - Log_bare(" " . w . "`t" . aIsBugnActive . " " . aIsFloating . " " . aIsHidden . " " aIsWinFocus . "`t" . aWndX . "`t" . aWndY . "`t" . aWndW . "`t" . aWndH . "`t" . aWndStyle . "`t" . aWndTitle) + Log_bare(w . "`t" . aIsBugnActive . " " . aIsFloating . " " . aIsHidden . " " aIsWinFocus . "`t" . aWndX . "`t" . aWndY . "`t" . aWndW . "`t" . aWndH . "`t" . aWndStyle . "`t" . aWndTitle) } Manager_logWindowList() { @@ -271,7 +271,7 @@ Manager_logWindowList() { v := Monitor_#%Manager_aMonitor%_aView_#1 Log_msg( "Window dump for active view (" . Manager_aMonitor . ", " . v . ")" ) - Log_bare( " ID`t`tA F H W`tX`tY`tW`tH`tStyle`t`tTitle") + Log_bare( "ID`t`tA F H W`tX`tY`tW`tH`tStyle`t`tTitle") StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 Loop, PARSE, wndIds, `; From de84ea6ac711430863ff32ffcc063288850e65db Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 14:16:17 -0400 Subject: [PATCH 25/60] Fixed up layout symbol construction. Added some debug logging to catch a problem. --- src/View.ahk | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/View.ahk b/src/View.ahk index 5ce8855..8c171dc 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -36,18 +36,23 @@ View_init(m, v) { View_activateWindow(d) { Local aWndId, i, j, v, wndId, wndId0, wndIds - + Log_dbg_msg("View_activateWindow(" . d . ")") WinGet, aWndId, ID, A + Log_dbg_bare("Active Windows ID: " . aWndId) v := Monitor_#%Manager_aMonitor%_aView_#1 + Log_dbg_bare("View (" . v . ") wndIds: " . View_#%Manager_aMonitor%_#%v%_wndIds) StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 StringSplit, wndId, wndIds, `; + Log_dbg_bare("wndId count: " . wndId0) If (wndId0 > 1) { Loop, % wndId0 If (wndId%A_Index% = aWndId) { i := A_Index Break } + Log_dbg_bare("Current wndId index: " . i) j := Manager_loop(i, d, 1, wndId0) + Log_dbg_bare("Next wndId index: " . j) wndId := wndId%j% WinSet, AlwaysOnTop, On, ahk_id %wndId% WinSet, AlwaysOnTop, Off, ahk_id %wndId% @@ -245,7 +250,7 @@ View_shuffleWindow(d) { } View_updateLayout_tile(m, v) { - Local axis1, axis2, axis3, msplit, sym1, sym3, master_div, master_sym, stack_sym + Local axis1, axis2, axis3, msplit, sym1, sym3, master_div, master_dim, master_sym, stack_sym ; Main axis ; 1 - vertical divider, master left @@ -270,10 +275,14 @@ View_updateLayout_tile(m, v) { Else master_div := "=" - If ( axis2 = 1 ) - master_sym := "" . msplit . "x1|" - Else If ( axis2 = 2 ) - master_sym := "1x" . msplit . "-" + If ( axis2 = 1 ) { + master_sym := "|" + master_dim := "" . msplit . "x1" + } + Else If ( axis2 = 2 ) { + master_sym := "-" + master_dim := "1x" . msplit + } Else master_sym := "[" . msplit . "]" @@ -285,9 +294,9 @@ View_updateLayout_tile(m, v) { stack_sym := "o" If ( axis1 > 0 ) - View_#%m%_#%v%_layoutSymbol := master_sym . master_div . stack_sym + View_#%m%_#%v%_layoutSymbol := master_dim . master_sym . master_div . stack_sym Else - View_#%m%_#%v%_layoutSymbol := stack_sym . master_div . master_sym + View_#%m%_#%v%_layoutSymbol := stack_sym . master_div . master_sym . master_dim } View_arrange_tile(m, v, wndIds) { From e28b5862a74e317d8f7f8353cba8cd83b4b35de9 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 16:58:29 -0400 Subject: [PATCH 26/60] Debug logging changes. Allow for multiple logging levels --- src/Config.ahk | 5 +++-- src/Log.ahk | 41 +++++++++++++++++++++++++---------------- src/Manager.ahk | 11 ++++++++++- src/View.ahk | 12 ++++++------ 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index 658f77c..b6a9084 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -389,7 +389,8 @@ Config_saveSession() { #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). #^i::Manager_logWindowList() -#^d::Log_toggleDebugEnabled() +#^d::Log_decDebugLevel() +#^e::Log_incDebugLevel() #Tab::View_setLayout(-1) ; Set the previously set layout. You may also use View_setLayout(">") for setting the next layout in the layout array. #\::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). @@ -446,7 +447,7 @@ Config_saveSession() { #+Space::Monitor_toggleBar() ; Hide / Show the bar (bug.n status bar) on the active monitor. #Space::Monitor_toggleTaskBar() ; Hide / Show the task bar. #y::Bar_toggleCommandGui() ; Open the command GUI for executing programmes or bug.n functions. -#^e::Run, edit %Config_filePath% ; Open the configuration file in the standard text editor. +;#^e::Run, edit %Config_filePath% ; Open the configuration file in the standard text editor. #^s::Config_saveSession() ; Save the current state of monitors, views, layouts to the configuration file. #^r::Main_reload() ; Reload bug.n (i. e. the configuration and its dependent settings) without deleting the window lists of bug.n and restoring windows. ; It does not reset internal configuration variables, the tray icon or menu, hotkeys (unless set explicitly in Config.ini), individual window settings like Config_showBorder (since windows might be hidden) or hiding the title bar, the monitor count or views. diff --git a/src/Log.ahk b/src/Log.ahk index 9e48013..5fef068 100755 --- a/src/Log.ahk +++ b/src/Log.ahk @@ -31,28 +31,37 @@ Log_bare( message ) { FileAppend, %padded_message% , bugn_log.txt } -Log_debug_enabled := 0 +Log_debug_level := 0 -Log_toggleDebugEnabled() { +Log_incDebugLevel() { Global - If (Log_debug_enabled = 1) - Log_debug_enabled := 0 - Else - Log_debug_enabled := 1 - If (Log_debug_enabled = 1) - Log_msg("Debug log enabled (" . Log_debug_enabled . ")") - Else - Log_msg("Debug log disabled (" . Log_debug_enabled . ")") + If ( Log_debug_level < 9 ) + { + Log_debug_level += 1 + Log_msg("Debug logging level incremented to " . Log_debug_level ) + } } -Log_dbg_msg( message ) { +Log_decDebugLevel() { Global - If (Log_debug_enabled = 1) - Log_msg( "DEBUG: " . message ) + If ( Log_debug_level > 0 ) { + Log_debug_level -= 1 + If ( Log_debug_level = 0 ) + Log_msg("Debug logging is disabled") + Else + Log_msg("Debug logging level decremented to " . Log_debug_level) + } } -Log_dbg_bare( message ) { + +Log_dbg_msg( level, message ) { Global - If (Log_debug_enabled = 1) - Log_bare( "DEBUG: " . message ) + If (level > 0 And Log_debug_level >= level) + Log_msg( "DBG " . level . ": " . message ) +} + +Log_dbg_bare( level, message ) { + Global + If (level > 0 And Log_debug_level >= level) + Log_bare( "DBG " . level . ": " . message ) } \ No newline at end of file diff --git a/src/Manager.ahk b/src/Manager.ahk index ecbeac1..bdcc1f4 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -403,9 +403,19 @@ Manager_moveWindow() { SendMessage, WM_SYSCOMMAND, SC_MOVE, , , ahk_id %aWndId% } +HSHELL_WINDOWCREATED := 1 +; Seems to get sent every time +HSHELL_WINDOWDESTROYED := 2 +HSHELL_WINDOWACTIVATED := 4 +HSHELL_REDRAW := 6 +; Full-screen app activated? +HSHELL_RUDEAPPACTIVATED := 32772 + Manager_onShellMessage(wParam, lParam) { Local a, aWndClass, aWndHeight, aWndId, aWndTitle, aWndWidth, aWndX, aWndY, flag, m, t, wndClass, wndId, wndIds, wndPName, wndTitle, x, y + Log_dbg_msg(1, "Manager_onShellMessage(wParam: " . wParam . ", lParam: " . lParam) + SetFormat, Integer, hex lParam := lParam+0 SetFormat, Integer, d @@ -578,7 +588,6 @@ Manager_sync(ByRef wndIds = "") { shownWndIds .= View_#%A_Index%_#%v%_wndIds } ; check all visible windows against the known windows - ; DetectHiddenWindows, On WinGet, wndId, List, , , Loop, % wndId { If Not InStr(shownWndIds, wndId%A_Index% ";") { diff --git a/src/View.ahk b/src/View.ahk index 8c171dc..eb63374 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -36,23 +36,23 @@ View_init(m, v) { View_activateWindow(d) { Local aWndId, i, j, v, wndId, wndId0, wndIds - Log_dbg_msg("View_activateWindow(" . d . ")") + Log_dbg_msg(1, "View_activateWindow(" . d . ")") WinGet, aWndId, ID, A - Log_dbg_bare("Active Windows ID: " . aWndId) + Log_dbg_bare(2, "Active Windows ID: " . aWndId) v := Monitor_#%Manager_aMonitor%_aView_#1 - Log_dbg_bare("View (" . v . ") wndIds: " . View_#%Manager_aMonitor%_#%v%_wndIds) + Log_dbg_bare(2, "View (" . v . ") wndIds: " . View_#%Manager_aMonitor%_#%v%_wndIds) StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 StringSplit, wndId, wndIds, `; - Log_dbg_bare("wndId count: " . wndId0) + Log_dbg_bare(2, "wndId count: " . wndId0) If (wndId0 > 1) { Loop, % wndId0 If (wndId%A_Index% = aWndId) { i := A_Index Break } - Log_dbg_bare("Current wndId index: " . i) + Log_dbg_bare(2, "Current wndId index: " . i) j := Manager_loop(i, d, 1, wndId0) - Log_dbg_bare("Next wndId index: " . j) + Log_dbg_bare(2, "Next wndId index: " . j) wndId := wndId%j% WinSet, AlwaysOnTop, On, ahk_id %wndId% WinSet, AlwaysOnTop, Off, ahk_id %wndId% From e60d23e6beeece1f2e1a8fb3035c67498950b48d Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 17:52:09 -0400 Subject: [PATCH 27/60] Added a debug log message --- src/View.ahk | 1 + 1 file changed, 1 insertion(+) diff --git a/src/View.ahk b/src/View.ahk index eb63374..4e4f23d 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -304,6 +304,7 @@ View_arrange_tile(m, v, wndIds) { StringTrimRight, wndIds, wndIds, 1 StringSplit, wndId, wndIds, `; + Log_dbg_msg(1, "View_arrange_tile: (" . wndId0 . ") " . wndIds) If (wndId0 = 0) Return From 4bf1aef3e6e828db904ff0b47a3f694c1de80cce Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 17:53:25 -0400 Subject: [PATCH 28/60] Speed up view drawing by turning down the window delay time --- src/Monitor.ahk | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Monitor.ahk b/src/Monitor.ahk index 1cd2214..c7bb6d1 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -73,6 +73,10 @@ Monitor_activateView(v) { Monitor_#%m%_aView_#1 := v Manager_hideShow := True + ; Most of the operations here are dispersed to multiple _different_ windows. + ; Delays in this part of the code are extremely noticeable and the users + ; do a lot of view switching. + SetWinDelay, 0 StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 Loop, PARSE, wndIds, `; If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) @@ -83,7 +87,7 @@ Monitor_activateView(v) { StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 Loop, PARSE, wndIds, `; WinShow, ahk_id %A_LoopField% - + SetWinDelay, 10 Manager_hideShow := False Bar_updateView(m, aView) From bce40f67e809dc767cfdfae5326bbebf20668068 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 21:20:12 -0400 Subject: [PATCH 29/60] Separation of responsibilities. Enforce the 'window manipulation doesn't affect layout definition' mantra --- src/Manager.ahk | 21 +-------------------- src/View.ahk | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index bdcc1f4..70c6cfe 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -329,26 +329,7 @@ Manager_manage(wndId) { Loop, % Config_viewCount If (Manager_#%wndId%_tags & 1 << A_Index - 1) { - l := View_#%m%_#%A_Index%_layout_#1 - If (Config_layoutFunction_#%l% = "tile") And ((Config_newWndPosition = "masterBottom") Or (Config_newWndPosition = "stackTop")) { - n := View_getTiledWndIds(m, A_Index, wndIds) - If (n > 1) { - StringSplit, wndId, wndIds, `; - If (wndId0 < View_#%m%_#%A_Index%_layoutMSplit) - View_#%m%_#%A_Index%_layoutMSplit := wndId0 - i := View_#%m%_#%A_Index%_layoutMSplit - search := wndId%i% ";" - replace := search wndId ";" - StringReplace, View_#%m%_#%A_Index%_wndIds, View_#%m%_#%A_Index%_wndIds, %search%, %replace% - } Else - View_#%m%_#%A_Index%_wndIds .= wndId ";" - If (Config_newWndPosition = "masterBottom") And (n > 0) - View_#%m%_#%A_Index%_layoutMSplit += 1 - } Else If (Config_newWndPosition = "bottom") - View_#%m%_#%A_Index%_wndIds .= wndId ";" - Else - View_#%m%_#%A_Index%_wndIds := wndId ";" View_#%m%_#%A_Index%_wndIds - Bar_updateView(m, A_Index) + View_addWnd(m, A_Index, wndId) } If Not Config_showBorder diff --git a/src/View.ahk b/src/View.ahk index 4e4f23d..89b89f7 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -69,6 +69,36 @@ View_updateLayout(m, v) { View_updateLayout_%fn%(m, v) } +View_addWnd(m, v, wndId) { + Local l, msplit, i, wndIds, n + + l := View_#%m%_#%v%_layout_#1 + If (Config_layoutFunction_#%l% = "tile") And ((Config_newWndPosition = "masterBottom") Or (Config_newWndPosition = "stackTop")) { + n := View_getTiledWndIds(m, v, wndIds) + msplit := View_#%m%_#%v%_layoutMSplit + 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 + StringSplit, wndId, wndIds, `; + search := wndId%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) { Local fn, l, wndIds From 1284147a23e1be0b5742c8216bb1619efd7e0ecd Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 22:06:31 -0400 Subject: [PATCH 30/60] More separation of concerns. Improved the window pickup and redraw performance significantly. --- src/Manager.ahk | 48 ++++++++++++++++++++++++------------------------ src/View.ahk | 6 ++++++ 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index 70c6cfe..5f23ec3 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -125,12 +125,6 @@ Manager_applyRules(wndId, ByRef isManaged, ByRef m, ByRef tags, ByRef isFloating hideTitle := rule9 } } - If (m = 0) - m := Manager_aMonitor - 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 << Monitor_#%m%_aView_#1 - 1 } Else { isManaged := False If wndTitle @@ -311,6 +305,15 @@ Manager_manage(wndId) { Manager_allWndIds .= wndId ";" Manager_applyRules(wndId, isManaged, m, tags, isFloating, isDecorated, hideTitle) + If (m = 0) + m := Manager_aMonitor + 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 << Monitor_#%m%_aView_#1 - 1 + WinGet, wndProcessName, ProcessName, ahk_id %wndId% If (wndProcessName = "chrome.exe") { WinGet, wndControlList, ControlList, ahk_id %wndId% @@ -393,7 +396,7 @@ HSHELL_REDRAW := 6 HSHELL_RUDEAPPACTIVATED := 32772 Manager_onShellMessage(wParam, lParam) { - Local a, aWndClass, aWndHeight, aWndId, aWndTitle, aWndWidth, aWndX, aWndY, flag, m, t, wndClass, wndId, wndIds, wndPName, wndTitle, x, y + Local a, isChanged, aWndClass, aWndHeight, aWndId, aWndTitle, aWndWidth, aWndX, aWndY, m, t, wndClass, wndId, wndIds, wndPName, wndTitle, x, y Log_dbg_msg(1, "Manager_onShellMessage(wParam: " . wParam . ", lParam: " . lParam) @@ -426,26 +429,23 @@ Manager_onShellMessage(wParam, lParam) { Sleep, %Config_shellMsgDelay% } - If (wParam = 1 Or wParam = 6) And Not InStr(Manager_allWndIds, lParam ";") And Not InStr(Manager_managedWndIds, lParam ";") - a := Manager_manage(lParam) - Else { - flag := True - a := Manager_sync(wndIds) - If wndIds - a := False - } - If a { + isChanged := Manager_sync(wndIds) + If wndIds + isChanged := False + + If a Or isChanged { + SetWinDelay, 0 View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) + SetWinDelay, 10 Bar_updateView(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) } - If flag - If (Manager_monitorCount > 1) { - WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %aWndId% - m := Monitor_get(aWndX + aWndWidth / 2, aWndY + aWndHeight / 2) - If m - Manager_aMonitor := m - } + If (Manager_monitorCount > 1) { + WinGetPos, aWndX, aWndY, aWndWidth, aWndHeight, ahk_id %aWndId% + m := Monitor_get(aWndX + aWndWidth / 2, aWndY + aWndHeight / 2) + If m + Manager_aMonitor := m + } If wndIds { If (Config_onActiveHiddenWnds = "view") { @@ -613,7 +613,7 @@ Manager_unmanage(wndId) { a := Manager_#%wndId%_tags & 1 << Monitor_#%Manager_aMonitor%_aView_#1 - 1 Loop, % Config_viewCount If (Manager_#%wndId%_tags & 1 << A_Index - 1) { - StringReplace, View_#%Manager_aMonitor%_#%A_Index%_wndIds, View_#%Manager_aMonitor%_#%A_Index%_wndIds, %wndId%`;, + View_delWnd( Manager_aMonitor, A_Index, wndId ) Bar_updateView(Manager_aMonitor, A_Index) } Manager_#%wndId%_tags := diff --git a/src/View.ahk b/src/View.ahk index 89b89f7..b882fea 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -69,6 +69,7 @@ View_updateLayout(m, v) { View_updateLayout_%fn%(m, v) } +; Add a window to the view in question. View_addWnd(m, v, wndId) { Local l, msplit, i, wndIds, n @@ -99,6 +100,11 @@ View_addWnd(m, v, wndId) { View_#%m%_#%v%_wndIds := wndId ";" View_#%m%_#%v%_wndIds } +; Remove a window from the view in question. +View_delWnd(m, v, wndId) { + StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, %wndId%`;, +} + View_arrange(m, v) { Local fn, l, wndIds From 0b8a381846177913fe0977a4efe264da7f3fdb79 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 23 Jun 2012 22:38:26 -0400 Subject: [PATCH 31/60] Cleanup and continue to enforce the separation of layout vs. content --- src/View.ahk | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/View.ahk b/src/View.ahk index b882fea..b88055e 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -220,11 +220,7 @@ View_setMFactor(d) { v := Monitor_#%Manager_aMonitor%_aView_#1 l := View_#%Manager_aMonitor%_#%v%_layout_#1 If (Config_layoutFunction_#%l% = "tile") { - mfact := 0 - If (d >= 1.05) - mfact := d - Else - mfact := View_#%Manager_aMonitor%_#%v%_layoutMFact + d + mfact := View_#%Manager_aMonitor%_#%v%_layoutMFact + d If (mfact >= 0.05 And mfact <= 0.95) { View_#%Manager_aMonitor%_#%v%_layoutMFact := mfact View_arrange(Manager_aMonitor, v) @@ -238,9 +234,11 @@ View_setMSplit(d) { v := Monitor_#%Manager_aMonitor%_aView_#1 l := View_#%Manager_aMonitor%_#%v%_layout_#1 If (Config_layoutFunction_#%l% = "tile") { - n := View_getTiledWndIds(Manager_aMonitor, v, wndIds) - View_#%Manager_aMonitor%_#%v%_layoutMSplit := Manager_loop(View_#%Manager_aMonitor%_#%v%_layoutMSplit, d, 1, n) - View_arrange(Manager_aMonitor, v) + n := View_#%Manager_aMonitor%_#%v%_layoutMSplit + d + If ( n > 0 And n < 10 ) { + View_#%Manager_aMonitor%_#%v%_layoutMSplit := n + View_arrange(Manager_aMonitor, v) + } } } From 9c4e5dd34e3cb8e5a9686026ee099b1f71180a23 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sun, 24 Jun 2012 13:19:15 -0400 Subject: [PATCH 32/60] Further separation of concerns. Manager_manage now accepts a 'suggested' monitor and window. This won't override configuration settings. --- src/Manager.ahk | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index 5f23ec3..3ccc651 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -297,7 +297,12 @@ Manager_loop(index, increment, lowerBound, upperBound) { Return, index } -Manager_manage(wndId) { +; Accept a window to be added to the system for management. +; Provide a monitor, view preference, but don't override the config. +; pm - Preferred monitor +; pv - Preferred view +; wndId - Window to add to the manager. +Manager_manage(pm, pv, wndId) { Local a, c0, hideTitle, i, isDecorated, isFloating, isManaged, l, m, n, replace, search, tags Local wndControlList0, wndId0, wndIds, wndX, wndY, wndWidth, wndHeight, wndProcessName @@ -306,13 +311,13 @@ Manager_manage(wndId) { Manager_applyRules(wndId, isManaged, m, tags, isFloating, isDecorated, hideTitle) If (m = 0) - m := Manager_aMonitor + m := pm 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 << Monitor_#%m%_aView_#1 - 1 + tags := 1 << (pv - 1) WinGet, wndProcessName, ProcessName, ahk_id %wndId% If (wndProcessName = "chrome.exe") { @@ -573,7 +578,7 @@ Manager_sync(ByRef wndIds = "") { Loop, % wndId { If Not InStr(shownWndIds, wndId%A_Index% ";") { If Not InStr(Manager_managedWndIds, wndId%A_Index% ";") { - flag := Manager_manage(wndId%A_Index%) + flag := Manager_manage(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1, wndId%A_Index%) If flag a := flag } Else From fb71e0d7dc06ae4b4e971885d1716918192161c0 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sun, 24 Jun 2012 13:26:45 -0400 Subject: [PATCH 33/60] Improved logging functionality. Different logs may not be specified and the log may be truncated upon initialization. --- src/Log.ahk | 27 +++++++++++++++++++++------ src/Main.ahk | 1 + 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Log.ahk b/src/Log.ahk index 5fef068..47f2435 100755 --- a/src/Log.ahk +++ b/src/Log.ahk @@ -1,6 +1,6 @@ /** - * bug.n - tiling window management - * Copyright (c) 2010-2012 joten + * AHK Debug log implementation + * Copyright (c) 2012 Joshua Fuhs * * 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 @@ -18,23 +18,36 @@ * @version 8.3.0 */ +Log_debug_level := 0 +Log_init(name, truncate) { + Global + If truncate + IfExist, %name% + FileDelete, %name% + Log_name := name +} Log_msg( message ) { + Local CurrentTime + If Not Log_name + Return FormatTime, CurrentTime, , yyyyMMddHHmmss - FileAppend, %CurrentTime% %message%`r`n, bugn_log.txt + FileAppend, %CurrentTime% %message%`r`n, %Log_name% } Log_bare( message ) { Local padded_message + If Not Log_name + Return padded_message := " " . message . "`r`n" - FileAppend, %padded_message% , bugn_log.txt + FileAppend, %padded_message% , %Log_name% } -Log_debug_level := 0 - Log_incDebugLevel() { Global + If Not Log_name + Return If ( Log_debug_level < 9 ) { Log_debug_level += 1 @@ -44,6 +57,8 @@ Log_incDebugLevel() { Log_decDebugLevel() { Global + If Not Log_name + Return If ( Log_debug_level > 0 ) { Log_debug_level -= 1 If ( Log_debug_level = 0 ) diff --git a/src/Main.ahk b/src/Main.ahk index 085a889..c854fb4 100644 --- a/src/Main.ahk +++ b/src/Main.ahk @@ -32,6 +32,7 @@ SetWinDelay, 10 #WinActivateForce ; pseudo main function + Log_init("bugn_log.txt", False) Log_msg("====== Initializing ======") If 0 = 1 Config_filePath = %1% From ac727ad7424b55ba1f45c3dd2fcda3f5ec5be92a Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sun, 24 Jun 2012 13:27:21 -0400 Subject: [PATCH 34/60] List implementation to pull the list manipulation logic out of the codebase --- src/List.ahk | 104 ++++++++++++++++++++++++++++++++++++++++++++++ src/List.test.ahk | 84 +++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 src/List.ahk create mode 100644 src/List.test.ahk diff --git a/src/List.ahk b/src/List.ahk new file mode 100644 index 0000000..bffa5b5 --- /dev/null +++ b/src/List.ahk @@ -0,0 +1,104 @@ +/** + * AHK List implementation + * Copyright (c) 2012 Joshua Fuhs + * + * 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/>. + * + */ + +/** + * This is an admittedly poor list implementation, but I was new to AHK, + * and I had seen several examples of this already used. + * The lists being operated on should not be larger than a few hundred, + * and preferably no larger than one hundred. + */ + + +List_new() { + Global + Return "" +} + +List_prepend( ByRef l, e ) { + l := e . "`;" . l + Return +} + +List_append(ByRef l, e) { + l := l . e . "`;" + Return +} + +; Insert at position immediately preceding index p +List_insert(ByRef l, e, p) { + Local arr, search, replace + If ( p = 0) + return List_prepend(l, e) + StringSplit arr, l, `; + if ( p >= arr0 - 1 ) + return List_append(l, e) + p += 1 + search := arr%p% . ";" + replace := e . ";" . search + StringReplace, l, l, %search%, %replace% +} + +List_remove(ByRef l, e) { + Local search + search := "" . e . ";" + StringReplace, l, l, %search%, + return +} + + +List_removeAt(ByRef l, p) { + Local arr, search + StringSplit arr, l, `; + if( p >= arr0 - 1) + Return + p += 1 + search := arr%p% . ";" + StringReplace, l, l, %search%, +} + +List_find(ByRef l, e) { + Local arr, arr0 + StringSplit arr, l, `; + Loop, % (arr0 - 1) { + If arr%A_Index% = %e% + Return (A_Index - 1) + } + Return -1 +} + +List_dump(l) { + Local result + StringReplace, result, l, `;, %A_Space%, All + Return result +} + +List_get(l, p) { + Local arr + StringSplit arr, l, `; + If( p >= arr0 ) + Return "" + p += 1 + Return arr%p% +} + +List_size(l) { + Local arr, arr0 + StringSplit arr, l, `; + Return (arr0 - 1) +} diff --git a/src/List.test.ahk b/src/List.test.ahk new file mode 100644 index 0000000..b6fb0bc --- /dev/null +++ b/src/List.test.ahk @@ -0,0 +1,84 @@ + +Test_check(Condition, msg) { + Global + If Condition + Return + Log_bare(msg) + Exit, 1 +} + + +Log_init("List.test.txt", True) + +testlist := List_new() +Log_bare("new list: " . List_dump(testlist)) +Test_check(List_dump(testlist) = "", "Test 1 failure") +If Not (List_dump(testlist) = "" ) + Log_bare("Test 1 failure") +List_append(testlist, "abc") +Log_bare("appended 'abc': " . List_dump(testlist)) +If Not (List_dump(testlist) = "abc " ) + Log_bare("Test 2 failure") +List_append(testlist, "def") +Log_bare("appended 'def': " . List_dump(testlist)) +If Not (List_dump(testlist) = "abc def " ) + Log_bare("Test 3 failure") +List_append(testlist, "ghi") +List_remove(testlist, "abc") +Log_bare("removed 'abc': " . List_dump(testlist)) +If Not (List_dump(testlist) = "def ghi " ) + Log_bare("Test 4 failure") +List_append(testlist, "jkl") +List_remove(testlist, "ghi") +Log_bare("add 'jkl', remove 'ghi': " . List_dump(testlist)) +If Not (List_dump(testlist) = "def jkl " ) + Log_bare("Test 5 failure") +List_append(testlist, "mno") +List_remove(testlist, "mno") +Log_bare("add and remove 'mno': " . List_dump(testlist)) +If Not (List_dump(testlist) = "def jkl " ) + Log_bare("Test 6 failure") +List_prepend(testlist, "12345") +Log_bare("prepend '12345': " . List_dump(testlist)) +If Not (List_dump(testlist) = "12345 def jkl ") + Log_bare("Test 7 failure") +List_insert(testlist, "xyz", 0) +List_insert(testlist, "Happy", 1) +List_insert(testlist, "Blah", 5) +List_insert(testlist, "10", 10) +Log_bare("Attempt multiple inserts by index: " . List_dump(testlist)) +If Not (List_dump(testlist) = "xyz Happy 12345 def jkl Blah 10 ") + Log_bare("Test 8 failure") +List_removeAt(testlist, 0) +List_removeAt(testlist, 1) +List_removeAt(testlist, 2) +List_removeAt(testlist, 3) +List_removeAt(testlist, 10) +Log_bare("Attempt multiple removals by index: " . List_dump(testlist)) +If Not (List_dump(testlist) = "Happy def Blah ") + Log_bare("Test 9 failure") +If Not (List_find(testlist, "Happy") = 0) + Log_bare("Test 10 failure") +If Not (List_find(testlist, "def") = 1) + Log_bare("Test 11 failure") +If Not (List_find(testlist, "Blah") = 2) + Log_bare("Test 12 failure") +If Not (List_find(testlist, "nonexistent") = -1) + Log_bare("Test 13 failure") +If Not (List_size(testlist) = 3) + Log_bare("Test 14 failure") +If Not (List_get(testlist, 0) = "Happy") + Log_bare("Test 15 failure") +If Not (List_get(testlist, 1) = "def") + Log_bare("Test 16 failure") +If Not (List_get(testlist, 2) = "Blah") + Log_bare("Test 17 failure") +If Not (List_get(testlist, 3) = "") + Log_bare("Test 18 failure") + + + +Return + +#Include Log.ahk +#Include List.ahk \ No newline at end of file From e4f2915c490909a23e023fec63c8756b7a6fed52 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sun, 24 Jun 2012 16:19:53 -0400 Subject: [PATCH 35/60] Break down rendering of the layouts into distinct drawing components. --- src/View.ahk | 166 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 116 insertions(+), 50 deletions(-) diff --git a/src/View.ahk b/src/View.ahk index b88055e..84775d8 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -150,14 +150,13 @@ View_updateLayout_monocle(m, v) } View_arrange_monocle(m, v, wndIds) { - Local wndId0, gw + Local gw gw := View_#%m%_#%v%_layoutGapWidth StringTrimRight, wndIds, wndIds, 1 - StringSplit, wndId, wndIds, `; - Loop, % wndId0 - Manager_winMove(wndId%A_Index%, Monitor_#%m%_x + gw, Monitor_#%m%_y + gw, Monitor_#%m%_width - 2*gw, Monitor_#%m%_height - 2*gw) + StringSplit, View_arrange_monocle_wndId, wndIds, `; + View_draw_stack("View_arrange_monocle_wndId", 1, View_arrange_monocle_wndId0, 0, Monitor_#%m%_x, Monitor_#%m%_y, Monitor_#%m%_width, Monitor_#%m%_height, gw/2) } View_rotateLayoutAxis(i, d) { @@ -333,38 +332,132 @@ View_updateLayout_tile(m, v) { View_#%m%_#%v%_layoutSymbol := stack_sym . master_div . master_sym . master_dim } +; Stack a bunch of windows on top of each other. +; +; arrName - Name of a globally stored array of windows: +; %arrName%1, %arrName%2, ... +; off - Offset into the array from which to start drawing. +; len - Number of windows from the array to draw. +; dir - Determines the direction through which we traverse arrName +; x - View x-position +; y - View y-position +; w - View width +; h - View height +; margin - Number of pixels to put between the windows. +View_draw_stack( arrName, off, len, dir, x, y, w, h, margin ) { + Local base, inc + If (dir = 0) { + base := off + inc := 1 + } + Else { + base := off + len - 1 + inc := -1 + } + x += margin + y += margin + w -= 2 * margin + h -= 2 * margin + + Loop, % len { + Manager_winMove(%arrName%%base%, x, y, w, h) + base += inc + } +} + +; Draw a row of windows. +; +; arrName - Name of a globally stored array of windows: +; %arrName%1, %arrName%2, ... +; off - Offset into the array from which to start drawing. +; len - Number of windows from the array to draw. +; dir - Determines the direction through which we traverse arrName +; axis - X/Y <=> 0/1 +; x - View x-position +; y - View y-position +; w - View width +; h - View height +; margin - Number of pixels to put between the windows. +View_draw_row( arrName, off, len, dir, axis, x, y, w, h, margin ) { + Local base, inc, x_inc, y_inc, wHeight, wWidth + Log_bare("View_draw_row(" . arrName . ", " . off . ", " . len . ", " . dir . ", " . axis . ", " . x . ", " . y . ", " . w . ", " . h . ", " . margin . ")") + If (dir = 0) { + ; Left-to-right and top-to-bottom, depending on axis + base := off + inc := 1 + } + Else { + ; Right-to-left and bottom-to-top, depending on axis + base := off + len - 1 + inc := -1 + } + If (axis = 0) { + ; Create row along X + x_inc := w / len + y_inc := 0 + wWidth := x_inc - 2 * margin + wHeight := h - 2 * margin + } + Else { + ; Create row along Y + x_inc := 0 + y_inc := h / len + wWidth := w - 2 * margin + wHeight := y_inc - 2 * margin + } + + ; Set original positions with respect to the margins. + x += margin + y += margin + + Loop, % len { + Manager_winMove(%arrName%%base%, x, y, wWidth, wHeight) + x += x_inc + y += y_inc + base += inc + } +} + +View_arrange_tile_action(arrName, off, len, bugn_axis, x, y, w, h, m) { + ; 161 is a magic number determined somewhere. Maybe make this configurable. + ; Same with 2*Bar_height. + If (bugn_axis = 3 Or (bugn_axis = 1 And w/len < 161) Or (bugn_axis = 2 And h/len < (2*Bar_height))) + View_draw_stack(arrName, off, len, 0, x, y, w, h, m) + Else + View_draw_row(arrName, off, len, 0, bugn_axis - 1, x, y, w, h, m) +} + View_arrange_tile(m, v, wndIds) { - Local axis1, axis2, axis3, gapW, gapW_2, h1, h2, i, mfact, msplit, n1, n2, w1, w2, wndId0, x1, x2, y1, y2, oriented + Local axis1, axis2, axis3, gapW_2, h1, h2, i, mfact, msplit, n1, n2, w1, w2, x1, x2, y1, y2, oriented, stack_len StringTrimRight, wndIds, wndIds, 1 - StringSplit, wndId, wndIds, `; - Log_dbg_msg(1, "View_arrange_tile: (" . wndId0 . ") " . wndIds) - If (wndId0 = 0) + StringSplit, View_arrange_tile_wndId, wndIds, `; + Log_dbg_msg(1, "View_arrange_tile: (" . View_arrange_tile_wndId0 . ") " . wndIds) + If (View_arrange_tile_wndId0 = 0) Return axis1 := Abs(View_#%m%_#%v%_layoutAxis_#1) axis2 := View_#%m%_#%v%_layoutAxis_#2 axis3 := View_#%m%_#%v%_layoutAxis_#3 oriented := View_#%m%_#%v%_layoutAxis_#1 > 0 - gapW := View_#%m%_#%v%_layoutGapWidth - gapW_2 := gapW/2 + gapW_2 := View_#%m%_#%v%_layoutGapWidth/2 mfact := View_#%m%_#%v%_layoutMFact msplit := View_#%m%_#%v%_layoutMSplit - If (msplit > wndId0) { - msplit := wndId0 + If (msplit > View_arrange_tile_wndId0) { + msplit := View_arrange_tile_wndId0 } ; master and stack area - h1 := Monitor_#%m%_height - gapW + h1 := Monitor_#%m%_height h2 := h1 - w1 := Monitor_#%m%_width - gapW + w1 := Monitor_#%m%_width w2 := w1 - x1 := Monitor_#%m%_x + gapW_2 + x1 := Monitor_#%m%_x x2 := x1 - y1 := Monitor_#%m%_y + gapW_2 + y1 := Monitor_#%m%_y y2 := y1 - If (wndId0 > msplit) { + If (View_arrange_tile_wndId0 > msplit) { If (axis1 = 1) { w1 *= mfact w2 -= w1 @@ -383,41 +476,14 @@ View_arrange_tile(m, v, wndIds) { } ; master - If (axis2 != 1 Or w1 / msplit < 161) - n1 := w1 - Else - n1 := w1/msplit - If (axis2 != 2 Or h1 / msplit < Bar_height) - n2 := h1 - Else - n2 := h1/msplit - Loop, % msplit { - Manager_winMove(wndId%A_Index%, x1 + gapW_2, y1 + gapW_2, n1 - gapW, n2 - gapW) - If (n1 < w1) - x1 += n1 - If (n2 < h1) - y1 += n2 - } + View_arrange_tile_action("View_arrange_tile_wndId", 1, msplit, axis2, x1, y1, w1, h1, gapW_2) ; stack - If (wndId0 > msplit) { - If (axis3 != 1 Or w2 / (wndId0 - msplit) < 161) - n1 := w2 - Else - n1 := w2/(wndId0 - msplit) - If (axis3 != 2 Or h2 / (wndId0 - msplit) < Bar_height) - n2 := h2 - Else - n2 := h2/(wndId0 - msplit) - Loop, % wndId0 - msplit { - i := msplit + A_Index - Manager_winMove(wndId%i%, x2 + gapW_2, y2 + gapW_2, n1 - gapW, n2 - gapW) - If (n1 < w2) - x2 += n1 - If (n2 < h2) - y2 += n2 - } - } + If (View_arrange_tile_wndId0 <= msplit) + Return + + stack_len := View_arrange_tile_wndId0 - msplit + View_arrange_tile_action("View_arrange_tile_wndId", msplit + 1, stack_len, axis3, x2, y2, w2, h2, gapW_2) } View_toggleFloating() { From ea230027a0e8d77f79ad75b7eda8e6c5939f0126 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sun, 24 Jun 2012 16:30:29 -0400 Subject: [PATCH 36/60] Bumped debug level for shell messages down one --- src/Manager.ahk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index 3ccc651..0530b96 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -403,7 +403,7 @@ HSHELL_RUDEAPPACTIVATED := 32772 Manager_onShellMessage(wParam, lParam) { Local a, isChanged, aWndClass, aWndHeight, aWndId, aWndTitle, aWndWidth, aWndX, aWndY, m, t, wndClass, wndId, wndIds, wndPName, wndTitle, x, y - Log_dbg_msg(1, "Manager_onShellMessage(wParam: " . wParam . ", lParam: " . lParam) + Log_dbg_msg(2, "Manager_onShellMessage(wParam: " . wParam . ", lParam: " . lParam) SetFormat, Integer, hex lParam := lParam+0 From 725b809787fa9e038095383bf6f39aa6c80ac5a5 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sun, 24 Jun 2012 17:56:16 -0400 Subject: [PATCH 37/60] Dump the list to an array --- src/List.ahk | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/List.ahk b/src/List.ahk index bffa5b5..30afbba 100644 --- a/src/List.ahk +++ b/src/List.ahk @@ -102,3 +102,10 @@ List_size(l) { StringSplit arr, l, `; Return (arr0 - 1) } + +List_toArray(l, arrName) { + Local trimmedList + StringTrimRight, trimmedList, l, 1 + StringSplit %arrName%, trimmedList, `; + Return (%arrName%0) +} From ef47899c5dca89cbd39d0c114200d10087d7eade Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sun, 24 Jun 2012 18:04:41 -0400 Subject: [PATCH 38/60] Initialize monitors a little more intelligently by associating currently opened windows with the monitor on which they appear. --- src/Main.ahk | 1 + src/Manager.ahk | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Main.ahk b/src/Main.ahk index c854fb4..3487259 100644 --- a/src/Main.ahk +++ b/src/Main.ahk @@ -133,6 +133,7 @@ Main_toggleBar: Return #Include Log.ahk +#Include List.ahk #Include Bar.ahk #Include Config.ahk #Include Manager.ahk diff --git a/src/Manager.ahk b/src/Manager.ahk index 0530b96..beb465d 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -57,7 +57,7 @@ Manager_init() { Bar_hideTitleWndIds := "" Manager_allWndIds := "" Manager_managedWndIds := "" - Manager_sync() + Manager_initial_sync() Bar_updateStatus() Bar_updateTitle() @@ -601,6 +601,46 @@ Manager_sync(ByRef wndIds = "") { Return, a } +; No windows are known to the system yet. +; Try to do something smart with the initial layout. +Manager_initial_sync() { + Local 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 := List_new() + + ; check all 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 + List_append(Manager_initial_sync_m#%m%_wndList, wndId%A_index%) + + ; @todo: What percentage of the monitor area is it occupying? (Suggest layout) + ; @todo: What part of the monitor is it on? (Ordering of windows) + } + + Loop, % Manager_monitorCount { + m := A_Index + len := List_toArray(Manager_initial_sync_m#%m%_wndList, "Manager_initial_sync_tmpArray") + Loop, % len + Manager_manage(m, 1, Manager_initial_sync_tmpArray%A_Index%) + } +} + Manager_toggleDecor() { Local aWndId From a738956012f85878386411461779d1139b1757f6 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Mon, 25 Jun 2012 00:25:18 -0400 Subject: [PATCH 39/60] Added support for a two-dimensional master area --- src/Bar.ahk | 12 ++-- src/Config.ahk | 16 ++++-- src/View.ahk | 152 +++++++++++++++++++++++++++++++++++-------------- 3 files changed, 128 insertions(+), 52 deletions(-) diff --git a/src/Bar.ahk b/src/Bar.ahk index 63a0907..2717287 100644 --- a/src/Bar.ahk +++ b/src/Bar.ahk @@ -320,10 +320,14 @@ Bar_evaluateCommand() { View_rotateLayoutAxis(3, +1) Else If (Bar_command_#1 = "mirror tile layout") View_rotateLayoutAxis(1, +2) - Else If (Bar_command_#1 = "increase master split") - View_setMSplit(+1) - Else If (Bar_command_#1 = "decrease master split") - View_setMSplit(-1) + Else If (Bar_command_#1 = "increase master X") + View_setMX(+1) + Else If (Bar_command_#1 = "decrease master X") + View_setMX(-1) + Else If (Bar_command_#1 = "increase master Y") + View_setMY(+1) + Else If (Bar_command_#1 = "decrease master Y") + View_setMY(-1) Else If (Bar_command_#1 = "increase master factor") View_setMFactor(+0.05) Else If (Bar_command_#1 = "decrease master factor") diff --git a/src/Config.ahk b/src/Config.ahk index b6a9084..283ec98 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -361,8 +361,10 @@ Config_saveSession() { 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%_layoutMSplit = 1) - text .= "View_#" m "_#" A_Index "_layoutMSplit=" View_#%m%_#%A_Index%_layoutMSplit "`n" + If Not (View_#%m%_#%A_Index%_layoutMPri = 1) + text .= "View_#" m "_#" A_Index "_layoutMPri=" View_#%m%_#%A_Index%_layoutMPri "`n" + If Not (View_#%m%_#%A_Index%_layoutMSec = 1) + text .= "View_#" m "_#" A_Index "_layoutMSec=" View_#%m%_#%A_Index%_layoutMSec "`n" } } @@ -402,10 +404,12 @@ Config_saveSession() { #^Enter::View_rotateLayoutAxis(1, +2) ; Mirror the layout axis (i. e. -1 -> 1 / 1 -> -1 = master on the left / right side, -2 -> 2 / 2 -> -2 = master at top / bottom, only for the "tile" layout). #^Tab::View_rotateLayoutAxis(2, +1) ; Rotate the master axis (i. e. 3 -> 1 = x-axis = horizontal stack, 1 -> 2 = y-axis = vertical stack, 2 -> 3 = z-axis = monocle, only for the "tile" layout). #^+Tab::View_rotateLayoutAxis(3, +1) ; Rotate the stack axis (i. e. 3 -> 1 = x-axis = horizontal stack, 1 -> 2 = y-axis = vertical stack, 2 -> 3 = z-axis = monocle, only for the "tile" layout). -#^Left::View_setMSplit(+1) ; Move the master splitter, i. e. decrease the number of windows in the master area (only for the "tile" layout). -#^Right::View_setMSplit(-1) ; Move the master splitter, i. e. increase the number of windows in the master area (only for the "tile" layout). -#<::View_setGapWidth(-2) ; Decrease the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). -#+<::View_setGapWidth(+2) ; Increase the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). +#^Up::View_setMY(+1) ; Move the master splitter, i. e. decrease the number of windows in the master area (only for the "tile" layout). +#^Down::View_setMY(-1) ; Move the master splitter, i. e. increase the number of windows in the master area (only for the "tile" layout). +#^Right::View_setMX(+1) +#^Left::View_setMX(-1) +#Up::View_setGapWidth(-2) ; Decrease the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). +#Down::View_setGapWidth(+2) ; Increase the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). #BackSpace::Monitor_activateView(-1) ; Activate the previously activated view. You may also use Monitor_activateView("<") or Monitor_activateView(">") for activating the previous or next adjacent view. #+0::Monitor_setWindowTag(0) ; Tag the active window with all tags (1 ... Config_viewCount). You may also use Monitor_setWindowTag("<") or Monitor_setWindowTag(">") for setting the tag of the previous or next adjacent to the current view. diff --git a/src/View.ahk b/src/View.ahk index 84775d8..1edea32 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -29,7 +29,8 @@ View_init(m, v) { View_#%m%_#%v%_layoutAxis_#3 := Config_layoutAxis_#3 View_#%m%_#%v%_layoutGapWidth := Config_layoutGapWidth View_#%m%_#%v%_layoutMFact := Config_layoutMFactor - View_#%m%_#%v%_layoutMSplit := 1 + View_#%m%_#%v%_layoutMPri := 1 + View_#%m%_#%v%_layoutMSec := 1 View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#1 View_#%m%_#%v%_wndIds := "" } @@ -76,7 +77,7 @@ View_addWnd(m, v, wndId) { l := View_#%m%_#%v%_layout_#1 If (Config_layoutFunction_#%l% = "tile") And ((Config_newWndPosition = "masterBottom") Or (Config_newWndPosition = "stackTop")) { n := View_getTiledWndIds(m, v, wndIds) - msplit := View_#%m%_#%v%_layoutMSplit + msplit := View_#%m%_#%v%_layoutMPri * View_#%m%_#%v%_layoutMSec If ( msplit = 1 And Config_newWndPosition="masterBottom" ) { View_#%m%_#%v%_wndIds := wndId ";" . View_#%m%_#%v%_wndIds } @@ -189,7 +190,7 @@ View_setGapWidth(d) { Else d := Ceil(d / 2) * 2 w := View_#%Manager_aMonitor%_#%v%_layoutGapWidth + d - If (w >= 0 And w < Monitor_#%Manager_aMonitor%_height And w < Monitor_#%Manager_aMonitor%_width) { + If (w < Monitor_#%Manager_aMonitor%_height And w < Monitor_#%Manager_aMonitor%_width) { View_#%Manager_aMonitor%_#%v%_layoutGapWidth := w View_arrange(Manager_aMonitor, v) } @@ -227,20 +228,54 @@ View_setMFactor(d) { } } -View_setMSplit(d) { +View_setMPrimary(d) { Local l, n, v, wndIds - + v := Monitor_#%Manager_aMonitor%_aView_#1 l := View_#%Manager_aMonitor%_#%v%_layout_#1 If (Config_layoutFunction_#%l% = "tile") { - n := View_#%Manager_aMonitor%_#%v%_layoutMSplit + d + n := View_#%Manager_aMonitor%_#%v%_layoutMPri + d If ( n > 0 And n < 10 ) { - View_#%Manager_aMonitor%_#%v%_layoutMSplit := n + View_#%Manager_aMonitor%_#%v%_layoutMPri := n View_arrange(Manager_aMonitor, v) } } } +View_setMSecondary(d) { + Local l, n, v, wndIds + + v := Monitor_#%Manager_aMonitor%_aView_#1 + l := View_#%Manager_aMonitor%_#%v%_layout_#1 + If (Config_layoutFunction_#%l% = "tile") { + n := View_#%Manager_aMonitor%_#%v%_layoutMSec + d + If ( n > 0 And n < 10 ) { + View_#%Manager_aMonitor%_#%v%_layoutMSec := n + View_arrange(Manager_aMonitor, v) + } + } +} + +View_setMX(d) { + Local a, v + v := Monitor_#%Manager_aMonitor%_aView_#1 + a := View_#%Manager_aMonitor%_#%v%_layoutAxis_#2 + If ( a = 1 ) + View_setMPrimary(d) + Else + View_setMSecondary(d) +} + +View_setMY(d) { + Local a, v + v := Monitor_#%Manager_aMonitor%_aView_#1 + a := View_#%Manager_aMonitor%_#%v%_layoutAxis_#2 + If ( a = 1 ) + View_setMSecondary(d) + Else + View_setMPrimary(d) +} + View_shuffleWindow(d) { Local aWndHeight, aWndId, aWndWidth, aWndX, aWndY, i, j, l, search, v, wndId0, wndIds @@ -283,7 +318,7 @@ View_shuffleWindow(d) { } View_updateLayout_tile(m, v) { - Local axis1, axis2, axis3, msplit, sym1, sym3, master_div, master_dim, master_sym, stack_sym + Local axis1, axis2, axis3, mp, ms, sym1, sym3, master_div, master_dim, master_sym, stack_sym ; Main axis ; 1 - vertical divider, master left @@ -301,7 +336,8 @@ View_updateLayout_tile(m, v) { ; 2 - horizontal divider ; 3 - monocle axis3 := View_#%m%_#%v%_layoutAxis_#3 - msplit := View_#%m%_#%v%_layoutMSplit + mp := View_#%m%_#%v%_layoutMPri + ms := View_#%m%_#%v%_layoutMSec If ( Abs(axis1) = 1 ) master_div := "|" @@ -310,14 +346,14 @@ View_updateLayout_tile(m, v) { If ( axis2 = 1 ) { master_sym := "|" - master_dim := "" . msplit . "x1" - } + master_dim := mp . "x" . ms + } Else If ( axis2 = 2 ) { master_sym := "-" - master_dim := "1x" . msplit + master_dim := ms . "x" . mp } Else - master_sym := "[" . msplit . "]" + master_sym := "[" . (mp * ms) . "]" If ( axis3 = 1 ) stack_sym := "|" @@ -380,7 +416,7 @@ View_draw_stack( arrName, off, len, dir, x, y, w, h, margin ) { ; margin - Number of pixels to put between the windows. View_draw_row( arrName, off, len, dir, axis, x, y, w, h, margin ) { Local base, inc, x_inc, y_inc, wHeight, wWidth - Log_bare("View_draw_row(" . arrName . ", " . off . ", " . len . ", " . dir . ", " . axis . ", " . x . ", " . y . ", " . w . ", " . h . ", " . margin . ")") + ;Log_bare("View_draw_row(" . arrName . ", " . off . ", " . len . ", " . dir . ", " . axis . ", " . x . ", " . y . ", " . w . ", " . h . ", " . margin . ")") If (dir = 0) { ; Left-to-right and top-to-bottom, depending on axis base := off @@ -427,8 +463,30 @@ View_arrange_tile_action(arrName, off, len, bugn_axis, x, y, w, h, m) { View_draw_row(arrName, off, len, 0, bugn_axis - 1, x, y, w, h, m) } +View_split_region(axis, split_point, x, y, w, h, ByRef x1, ByRef y1, ByRef w1, ByRef h1, ByRef x2, ByRef y2, ByRef w2, ByRef h2) { + x1 := x + y1 := y + If(axis = 0) { + w1 := w * split_point + w2 := w - w1 + h1 := h + h2 := h + x2 := x + w1 + y2 := y + } + Else + { + w1 := w + w2 := w + h1 := h * split_point + h2 := h - h1 + x2 := x + y2 := y + h1 + } +} + View_arrange_tile(m, v, wndIds) { - Local axis1, axis2, axis3, gapW_2, h1, h2, i, mfact, msplit, n1, n2, w1, w2, x1, x2, y1, y2, oriented, stack_len + Local axis1, axis2, axis3, gapW_2, h1, h2, i, mfact, mp, ms, mx2, my2, mw2, mh2, msplit, n1, n2, w1, w2, x1, x2, y1, y2, flipped, stack_len, secondary_areas, areas_remaining, draw_windows StringTrimRight, wndIds, wndIds, 1 StringSplit, View_arrange_tile_wndId, wndIds, `; @@ -439,44 +497,54 @@ View_arrange_tile(m, v, wndIds) { axis1 := Abs(View_#%m%_#%v%_layoutAxis_#1) axis2 := View_#%m%_#%v%_layoutAxis_#2 axis3 := View_#%m%_#%v%_layoutAxis_#3 - oriented := View_#%m%_#%v%_layoutAxis_#1 > 0 + flipped := View_#%m%_#%v%_layoutAxis_#1 < 0 gapW_2 := View_#%m%_#%v%_layoutGapWidth/2 mfact := View_#%m%_#%v%_layoutMFact - msplit := View_#%m%_#%v%_layoutMSplit + mp := View_#%m%_#%v%_layoutMPri + ms := View_#%m%_#%v%_layoutMSec + msplit := mp * ms If (msplit > View_arrange_tile_wndId0) { msplit := View_arrange_tile_wndId0 } ; master and stack area - h1 := Monitor_#%m%_height - h2 := h1 - w1 := Monitor_#%m%_width - w2 := w1 - x1 := Monitor_#%m%_x - x2 := x1 - y1 := Monitor_#%m%_y - y2 := y1 - If (View_arrange_tile_wndId0 > msplit) { - If (axis1 = 1) { - w1 *= mfact - w2 -= w1 - If (Not oriented) - x1 += w2 - Else - x2 += w1 - } Else If (axis1 = 2) { - h1 *= mfact - h2 -= h1 - If (Not oriented) - y1 += h2 - Else - y2 += h1 - } + If( View_arrange_tile_wndId0 > msplit) { + If( flipped = 0) + View_split_region( axis1 - 1, mfact, Monitor_#%m%_x, Monitor_#%m%_y, Monitor_#%m%_width, Monitor_#%m%_height, x1, y1, w1, h1, x2, y2, w2, h2) + Else + View_split_region( axis1 - 1, mfact, Monitor_#%m%_x, Monitor_#%m%_y, Monitor_#%m%_width, Monitor_#%m%_height, x2, y2, w2, h2, x1, y1, w1, h1) + } + Else { + x1 := Monitor_#%m%_x + y1 := Monitor_#%m%_y + w1 := Monitor_#%m%_width + h1 := Monitor_#%m%_height } ; master - View_arrange_tile_action("View_arrange_tile_wndId", 1, msplit, axis2, x1, y1, w1, h1, gapW_2) + ; Number + If( axis2 = 3 ) + { + View_draw_stack("View_arrange_tile_wndId", 1, msplit, 0, x1, y1, w1, h1, gapW_2) + } + Else + { + secondary_areas := Ceil(msplit / mp) + areas_remaining := secondary_areas + windows_remaining := msplit + ;Log_bare("msplit: " . msplit . "; layoutMPri: " . mp . "; secondary_areas: " . secondary_areas . "; areas_remaining: " . areas_remaining . "; windows_remaining: " . windows_remaining) + Loop, % secondary_areas { + View_split_region(Not (axis2 - 1), (1/areas_remaining), x1, y1, w1, h1, mx1, my1, mw1, mh1, x1, y1, w1, h1) + draw_windows := mp + If (windows_remaining < mp) { + draw_windows := windows_remaining + } + View_draw_row("View_arrange_tile_wndId", msplit - windows_remaining + 1, draw_windows, 0, axis2 - 1, mx1, my1, mw1, mh1, gapW_2) + windows_remaining -= draw_windows + areas_remaining -= 1 + } + } ; stack If (View_arrange_tile_wndId0 <= msplit) From 986669f69acfcd71732e397eeb333f930b449c96 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Mon, 25 Jun 2012 12:08:16 -0400 Subject: [PATCH 40/60] [Bug] Flipping along master axis didn't preserve sizes --- src/View.ahk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/View.ahk b/src/View.ahk index 1edea32..da4f2ad 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -513,7 +513,7 @@ View_arrange_tile(m, v, wndIds) { If( flipped = 0) View_split_region( axis1 - 1, mfact, Monitor_#%m%_x, Monitor_#%m%_y, Monitor_#%m%_width, Monitor_#%m%_height, x1, y1, w1, h1, x2, y2, w2, h2) Else - View_split_region( axis1 - 1, mfact, Monitor_#%m%_x, Monitor_#%m%_y, Monitor_#%m%_width, Monitor_#%m%_height, x2, y2, w2, h2, x1, y1, w1, h1) + View_split_region( axis1 - 1, 1 - mfact, Monitor_#%m%_x, Monitor_#%m%_y, Monitor_#%m%_width, Monitor_#%m%_height, x2, y2, w2, h2, x1, y1, w1, h1) } Else { x1 := Monitor_#%m%_x From b36b640aad12fece05ed816ff99290c665009f04 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Mon, 25 Jun 2012 19:13:52 -0400 Subject: [PATCH 41/60] - Keep a reference to each window's expected monitor. Using the screen position can cause windows to switch sides under the right circumstances. - Some comments to help keep the onShellMessage function straight. - Repositioned SetWinDelay calls to get better effect for everything. - Fixed a bug where a windows activation of a window on another monitor would cause weird behavior. --- src/Manager.ahk | 9 +++++++-- src/Monitor.ahk | 16 ++++------------ src/View.ahk | 3 +++ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index beb465d..acc59ce 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -331,6 +331,7 @@ Manager_manage(pm, pv, wndId) { Monitor_moveWindow(m, wndId) Manager_managedWndIds .= wndId ";" + Manager_#%wndId%_monitor := m Manager_#%wndId%_tags := tags Manager_#%wndId%_isDecorated := isDecorated Manager_#%wndId%_isFloating := isFloating @@ -439,9 +440,7 @@ Manager_onShellMessage(wParam, lParam) { isChanged := False If a Or isChanged { - SetWinDelay, 0 View_arrange(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) - SetWinDelay, 10 Bar_updateView(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1) } @@ -454,19 +453,24 @@ Manager_onShellMessage(wParam, lParam) { If wndIds { If (Config_onActiveHiddenWnds = "view") { + ; Grab the first of such windows and make it visible. + ; All others get forgotten (until the next round?) wndId := SubStr(wndIds, 1, InStr(wndIds, ";") - 1) Loop, % Config_viewCount If (Manager_#%wndId%_tags & 1 << A_Index - 1) { + Manager_aMonitor := Manager_#%wndId%_monitor Monitor_activateView(A_Index) Break } } Else { StringTrimRight, wndIds, wndIds, 1 StringSplit, wndId, wndIds, `; + ; Otherwise re-hide them. If (Config_onActiveHiddenWnds = "hide") { Loop, % wndId0 WinHide, % "ahk_id " 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% @@ -661,6 +665,7 @@ Manager_unmanage(wndId) { View_delWnd( Manager_aMonitor, A_Index, wndId ) Bar_updateView(Manager_aMonitor, A_Index) } + Manager_#%wndId%_monitor := Manager_#%wndId%_tags := Manager_#%wndId%_isDecorated := Manager_#%wndId%_isFloating := diff --git a/src/Monitor.ahk b/src/Monitor.ahk index c7bb6d1..bc25e48 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -81,10 +81,12 @@ Monitor_activateView(v) { Loop, PARSE, wndIds, `; If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) WinHide, ahk_id %A_LoopField% + SetWinDelay, 10 DetectHiddenWindows, On View_arrange(m, v) DetectHiddenWindows, Off StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 + SetWinDelay, 0 Loop, PARSE, wndIds, `; WinShow, ahk_id %A_LoopField% SetWinDelay, 10 @@ -177,19 +179,9 @@ Monitor_getWorkArea(m) { } Monitor_moveWindow(m, wndId) { - Local fX, fY, monitor, wndHeight, wndWidth, wndX, wndY + Global - WinGetPos, wndX, wndY, wndWidth, wndHeight, ahk_id %wndId% - monitor := Monitor_get(wndX+wndWidth/2, wndY+wndHeight/2) - If Not (m = monitor) { - ; move the window to the target monitor and scale it, if it does not fit on the monitor - fX := Monitor_#%m%_width / Monitor_#%monitor%_width - fY := Monitor_#%m%_height / Monitor_#%monitor%_height - If (wndX-Monitor_#%monitor%_x+wndWidth > Monitor_#%m%_width) Or (wndY-Monitor_#%monitor%_y+wndHeight > Monitor_#%m%_height) - Manager_winMove(wndId, Monitor_#%m%_x+fX*(wndX-Monitor_#%monitor%_x), Monitor_#%m%_y+fY*(wndY-Monitor_#%monitor%_y), fX*wndWidth, fY*wndHeight) - Else - Manager_winMove(wndId, Monitor_#%m%_x+(wndX-Monitor_#%monitor%_x), Monitor_#%m%_y+(wndY-Monitor_#%monitor%_y), wndWidth, wndHeight) - } + Manager_#%wndId%_monitor = m } Monitor_setWindowTag(t) { diff --git a/src/View.ahk b/src/View.ahk index da4f2ad..2b0b309 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -109,12 +109,15 @@ View_delWnd(m, v, wndId) { View_arrange(m, v) { Local fn, l, wndIds + ; All window actions are performed on independent windows. A delay won't help. + SetWinDelay, 0 l := View_#%m%_#%v%_layout_#1 fn := Config_layoutFunction_#%l% View_getTiledWndIds(m, v, wndIds) View_arrange_%fn%(m, v, wndIds) View_updateLayout(m, v) Bar_updateLayout(m) + SetWinDelay, 10 } View_getTiledWndIds(m, v, ByRef tiledWndIds) { From 315b1bfae4a1f8c7f02b5837b59d30df08dd0214 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Tue, 26 Jun 2012 12:52:44 -0400 Subject: [PATCH 42/60] Lots of logging changes --- src/Config.ahk | 4 +++- src/Manager.ahk | 47 ++++++++++++++++++++++++++++++++++++++++------- src/Monitor.ahk | 2 +- src/View.ahk | 2 +- 4 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index 283ec98..d57bef0 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -390,7 +390,9 @@ Config_saveSession() { #+x::Manager_maximizeWindow() ; Move and resize the active window to the size of the work area (only floating windows). #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). -#^i::Manager_logWindowList() +#^i::Manager_logViewWindowList() +;#+^::Manager_logWindowList() +#^h::Manager_logHelp() #^d::Log_decDebugLevel() #^e::Log_incDebugLevel() diff --git a/src/Manager.ahk b/src/Manager.ahk index acc59ce..d0d3436 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -232,8 +232,12 @@ Manager_getWindowList() { Clipboard := text } +Manager_logViewLayout() { + +} + Manager_logWindowInfo( w ) { - Local av, aWndId, aIsWinFocus, aIsBugnActive, aIsFloating, aIsHidden, aWndTitle, aWndStyle, aWndX, aWndY, aWndW, aWndH + Local av, aWndId, aIsWinFocus, aIsBugnActive, aIsFloating, aIsHidden, aIsDecorated, aWndTitle, aWndStyle, aWndX, aWndY, aWndW, aWndH WinGet, aWndId, ID, A If aWndId = %w% @@ -254,18 +258,25 @@ Manager_logWindowInfo( w ) { aIsFloating := "*" Else aIsFloating := " " + If Manager_#%w%_isDecorated + aIsDecorated := "*" + Else + aIsDecorated := " " WinGet, aWndStyle, Style, ahk_id %w% WinGetPos, aWndX, aWndY, aWndW, aWndH, ahk_id %w% - - Log_bare(w . "`t" . aIsBugnActive . " " . aIsFloating . " " . aIsHidden . " " aIsWinFocus . "`t" . aWndX . "`t" . aWndY . "`t" . aWndW . "`t" . aWndH . "`t" . aWndStyle . "`t" . aWndTitle) + ;Manager_#%wndId%_monitor := m + ;Manager_#%wndId%_tags := tags + ;Manager_#%wndId%_isDecorated := isDecorated + ;Manager_#%wndId%_isFloating := isFloating + Log_bare(w . "`t" . aIsHidden . " " aIsWinFocus . " " . aIsBugnActive . " " . aIsFloating . " " . aIsDecorated . " " . Manager_#%w%_monitor . "`t" . Manager_#%w%_tags . "`t" . aWndX . "`t" . aWndY . "`t" . aWndW . "`t" . aWndH . "`t" . aWndStyle . "`t" . aWndTitle) } -Manager_logWindowList() { +Manager_logViewWindowList() { Local text, v, aWndId, wndIds, aWndTitle v := Monitor_#%Manager_aMonitor%_aView_#1 Log_msg( "Window dump for active view (" . Manager_aMonitor . ", " . v . ")" ) - Log_bare( "ID`t`tA F H W`tX`tY`tW`tH`tStyle`t`tTitle") + Log_bare( "ID`t`tH W A F D M`tTags`tX`tY`tW`tH`tStyle`t`tTitle") StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 Loop, PARSE, wndIds, `; @@ -274,6 +285,25 @@ Manager_logWindowList() { } } +Manager_logHelp() { + Log_msg("Help Display") + Log_bare("Window list columns") + Log_bare(" ID - Windows ID") + Log_bare(" H - Hidden") + Log_bare(" W - Windows active") + Log_bare(" A - View active") + Log_bare(" F - Floating") + Log_bare(" D - Decorated") + Log_bare(" M - Monitor") + Log_bare(" Tags - Bit-mask of the views in which the window is active") + Log_bare(" X - Windows X position") + Log_bare(" Y - Windows Y position") + Log_bare(" W - Windows width") + Log_bare(" H - Windows height") + Log_bare(" Style - Windows style") + Log_bare(" Title - Title of the window") +} + Manager_lockWorkStation() { Global Config_shellMsgDelay @@ -394,12 +424,15 @@ Manager_moveWindow() { } HSHELL_WINDOWCREATED := 1 -; Seems to get sent every time +; Seems to get sent sometimes when windows are deactivated. HSHELL_WINDOWDESTROYED := 2 HSHELL_WINDOWACTIVATED := 4 +; At least title change. HSHELL_REDRAW := 6 -; Full-screen app activated? +; Full-screen app activated? Root-privileged window activated? HSHELL_RUDEAPPACTIVATED := 32772 +; When a window is signalling an application update. +WINDOW_NOTICE := 32774 Manager_onShellMessage(wParam, lParam) { Local a, isChanged, aWndClass, aWndHeight, aWndId, aWndTitle, aWndWidth, aWndX, aWndY, m, t, wndClass, wndId, wndIds, wndPName, wndTitle, x, y diff --git a/src/Monitor.ahk b/src/Monitor.ahk index bc25e48..62d0855 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -41,7 +41,7 @@ Monitor_activateView(v) { Else If (v = "<") v := Manager_loop(Monitor_#%Manager_aMonitor%_aView_#1, -1, 1, Config_viewCount) - ;Log_msg("Monitor_activateView(" . v . ") wndIds: " . View_#%m%_#%aView%_wndIds) + Log_dbg_msg(1, "Monitor_activateView(" . v . ") Manager_aMonitor: " . Manager_aMonitor . "; wndIds: " . View_#%m%_#%aView%_wndIds) If (v <= 0) Or (v > Config_viewCount) Or Manager_hideShow Return diff --git a/src/View.ahk b/src/View.ahk index 2b0b309..2ea7dda 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -108,7 +108,7 @@ View_delWnd(m, v, wndId) { View_arrange(m, v) { Local fn, l, wndIds - + Log_dbg_msg(1, "View_arrange(" . m . ", " . v . ")") ; All window actions are performed on independent windows. A delay won't help. SetWinDelay, 0 l := View_#%m%_#%v%_layout_#1 From 3815956c099b06469b036b73d8eb11c3575c8a21 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Wed, 27 Jun 2012 21:44:45 -0400 Subject: [PATCH 43/60] Create a changelog so that I can keep things straight. --- ChangeLog | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 ChangeLog diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..9a19a56 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,17 @@ +8.2.2 +-------- + +Features + - NxM master area tiling. + - Split windows between multiple monitors on startup based on their + starting positions (has no effect on configured positions). + - Faster view drawing. + - Logging and debug logging capabilities. + - Layout and content are now distinct. View layouts may be manipulated + in the absence of windows. + +Bugs + - Cycling through windows on a view no longer gets stuck. + - Prevent windows from switching to different monitors under odd + circumstances. + - Gap width usage is now consistent between tile and monocle layouts. From 96b3f6af07fda0b1501a133659cf75db67a1cbec Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Wed, 27 Jun 2012 21:51:20 -0400 Subject: [PATCH 44/60] Hanging application for testing purposes. --- test/hang.cpp | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 test/hang.cpp diff --git a/test/hang.cpp b/test/hang.cpp new file mode 100644 index 0000000..7003f6f --- /dev/null +++ b/test/hang.cpp @@ -0,0 +1,87 @@ +/** + * Intended to be built with MinGW. + * + */ + +#include <windows.h> + + +char *AppTitle="Win1"; +LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + + +int WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int nCmdShow) +{ + WNDCLASS wc; + HWND hwnd; + MSG msg; + + wc.style=CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc=WindowProc; + wc.cbClsExtra=0; + wc.cbWndExtra=0; + wc.hInstance=hInst; + wc.hIcon=LoadIcon(NULL,IDI_WINLOGO); + wc.hCursor=LoadCursor(NULL,IDC_ARROW); + wc.hbrBackground=(HBRUSH)COLOR_WINDOWFRAME; + wc.lpszMenuName=NULL; + wc.lpszClassName=AppTitle; + + if (!RegisterClass(&wc)) + return 0; + + hwnd = CreateWindow(AppTitle,AppTitle, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT,CW_USEDEFAULT,100,100, + NULL,NULL,hInst,NULL); + + if (!hwnd) + return 0; + + ShowWindow(hwnd,nCmdShow); + UpdateWindow(hwnd); + + while (GetMessage(&msg,NULL,0,0) > 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +} + + +int maintain_bomb = 30; +int activate_bomb = 5; + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + switch (msg) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC dc; + RECT r; + GetClientRect(hwnd,&r); + dc=BeginPaint(hwnd,&ps); + DrawText(dc,"This window intentionally hangs",-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER); + EndPaint(hwnd,&ps); + break; + } + + case WM_DESTROY: + PostQuitMessage(0); + break; + case WM_SHOWWINDOW: + case WM_ACTIVATE: + if(activate_bomb == 0) + while(maintain_bomb) { + Sleep(1000); + //maintain_bomb--; + } + activate_bomb--; + + default: + return DefWindowProc(hwnd, msg, wparam, lparam); + } + return 0; +} From c76742b25d0ffb83110848718bb11d55d9ab8ac9 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Wed, 27 Jun 2012 21:53:02 -0400 Subject: [PATCH 45/60] Separate quit keys so they're less likely to be hit --- src/Config.ahk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Config.ahk b/src/Config.ahk index d57bef0..68bca41 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -458,4 +458,4 @@ Config_saveSession() { #^r::Main_reload() ; Reload bug.n (i. e. the configuration and its dependent settings) without deleting the window lists of bug.n and restoring windows. ; It does not reset internal configuration variables, the tray icon or menu, hotkeys (unless set explicitly in Config.ini), individual window settings like Config_showBorder (since windows might be hidden) or hiding the title bar, the monitor count or views. ; It does not reload functions. Changed rules are only applied to new windows. -#Esc::ExitApp ; Quit bug.n, restore the default Windows UI and show all windows. +#^Del::ExitApp ; Quit bug.n, restore the default Windows UI and show all windows. From 034c9c007e2e67bbddd2e87e185d158176c58dc3 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Wed, 27 Jun 2012 22:00:32 -0400 Subject: [PATCH 46/60] BID 018641: Prevent a hang of bug.n due to a hang of an underlying window. The layout gets messed up because of the ghost windows, and cycling through the windows doesn't yet work right. --- src/Manager.ahk | 86 ++++++++++++++++++++++++++++++++++++++----------- src/Monitor.ahk | 8 ++--- src/View.ahk | 6 ++-- 3 files changed, 75 insertions(+), 25 deletions(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index d0d3436..7c04ce6 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -156,10 +156,10 @@ Manager_cleanup() { Manager_hideShow := True Loop, PARSE, wndIds, `; { - WinShow, ahk_id %A_LoopField% + Manager_winShow(A_LoopField) If Not Config_showBorder - WinSet, Style, +0x40000, ahk_id %A_LoopField% - WinSet, Style, +0xC00000, ahk_id %A_LoopField% + Manager_winSet("Style", "+0x40000", A_LoopField) + Manager_winSet("Style", "+0xC00000", A_LoopField) } ; Show the task bar. @@ -176,8 +176,8 @@ Manager_cleanup() { Loop, % Config_viewCount View_arrange(m, A_Index) } - WinSet, AlwaysOnTop, On, ahk_id %aWndId% - WinSet, AlwaysOnTop, Off, ahk_id %aWndId% + Manager_winSet("AlwaysOnTop", "On", aWndId) + Manager_winSet("AlwaysOnTop", "Off", aWndId) 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) @@ -188,7 +188,7 @@ Manager_closeWindow() { WinGetClass, aWndClass, ahk_id %aWndId% WinGetTitle, aWndTitle, ahk_id %aWndId% If Not (aWndClass = "AutoHotkeyGUI" And RegExMatch(aWndTitle, "bug.n_BAR_[0-9]+")) - WinClose, ahk_id %aWndId% + Manager_winClose(aWndId) } Manager_getWindowInfo() { @@ -372,9 +372,9 @@ Manager_manage(pm, pv, wndId) { } If Not Config_showBorder - WinSet, Style, -0x40000, ahk_id %wndId% + Manager_winSet("Style", "-0x40000", wndId) If Not Manager_#%wndId%_isDecorated - WinSet, Style, -0xC00000, ahk_id %wndId% + Manager_winSet("Style", "-0xC00000", wndId) a := Manager_#%wndId%_tags & 1 << Monitor_#%m%_aView_#1 - 1 If a { @@ -382,7 +382,7 @@ Manager_manage(pm, pv, wndId) { Manager_winActivate(wndId) } Else { Manager_hideShow := True - WinHide, ahk_id %wndId% + Manager_winHide(wndId) Manager_hideShow := False } } @@ -403,7 +403,7 @@ Manager_maximizeWindow() { l := View_#%Manager_aMonitor%_#%v%_layout_#1 If Not Manager_#%aWndId%_isFloating And Not (Config_layoutFunction_#%l% = "") View_toggleFloating() - WinSet, Top,, ahk_id %aWndId% + Manager_winSet("Top", "", aWndId) Manager_winMove(aWndId, Monitor_#%Manager_aMonitor%_x, Monitor_#%Manager_aMonitor%_y, Monitor_#%Manager_aMonitor%_width, Monitor_#%Manager_aMonitor%_height) } @@ -416,7 +416,7 @@ Manager_moveWindow() { l := View_#%Manager_aMonitor%_#%v%_layout_#1 If Not Manager_#%aWndId%_isFloating And Not (Config_layoutFunction_#%l% = "") View_toggleFloating() - WinSet, Top,, ahk_id %aWndId% + Manager_winSet("Top", "", aWndId) WM_SYSCOMMAND = 0x112 SC_MOVE = 0xF010 @@ -501,7 +501,7 @@ Manager_onShellMessage(wParam, lParam) { ; Otherwise re-hide them. If (Config_onActiveHiddenWnds = "hide") { Loop, % wndId0 - WinHide, % "ahk_id " wndId%A_Index% + Manager_winHide(wndId%A_Index%) } Else If (Config_onActiveHiddenWnds = "tag") { ; Or tag all of them for the current view. t := Monitor_#%Manager_aMonitor%_aView_#1 @@ -596,7 +596,7 @@ Manager_sizeWindow() { l := View_#%Manager_aMonitor%_#%v%_layout_#1 If Not Manager_#%aWndId%_isFloating And Not (Config_layoutFunction_#%l% = "") View_toggleFloating() - WinSet, Top,, ahk_id %aWndId% + Manager_winSet("Top", "", aWndId) WM_SYSCOMMAND = 0x112 SC_SIZE = 0xF000 @@ -684,9 +684,9 @@ Manager_toggleDecor() { WinGet, aWndId, ID, A Manager_#%aWndId%_isDecorated := Not Manager_#%aWndId%_isDecorated If Manager_#%aWndId%_isDecorated - WinSet, Style, +0xC00000, ahk_id %aWndId% + Manager_winSet("Style", "+0xC00000", aWndId) Else - WinSet, Style, -0xC00000, ahk_id %aWndId% + Manager_winSet("Style", "-0xC00000", aWndId) } Manager_unmanage(wndId) { @@ -724,10 +724,60 @@ Manager_winActivate(wndId) { } Manager_winMove(wndId, x, y, width, height) { - WinRestore, ahk_id %wndId% + WM_NULL := 0 + SendMessage, WM_NULL, , , , ahk_id %wndId% + If ErrorLevel + Log_msg("Manager_winMove: Potentially hung window " . wndId) + Else + WinRestore, ahk_id %wndId% WM_ENTERSIZEMOVE = 0x0231 WM_EXITSIZEMOVE = 0x0232 SendMessage, WM_ENTERSIZEMOVE, , , , ahk_id %wndId% - WinMove, ahk_id %wndId%, , %x%, %y%, %width%, %height% - SendMessage, WM_EXITSIZEMOVE, , , , ahk_id %wndId% + tmp_errorlevel := ErrorLevel + If ErrorLevel + Log_msg("Manager_winMove: Potentially hung window " . wndId) + Else { + WinMove, ahk_id %wndId%, , %x%, %y%, %width%, %height% + SendMessage, WM_EXITSIZEMOVE, , , , ahk_id %wndId% + } } + +Manager_winHide(wndId) { + WM_NULL := 0 + SendMessage, WM_NULL, , , , ahk_id %wndId% + If ErrorLevel + Log_msg("Manager_winHide: Potentially hung window " . wndId) + Else { + WinHide, ahk_id %wndId% + } +} + +Manager_winShow(wndId) { + WM_NULL := 0 + SendMessage, WM_NULL, , , , ahk_id %wndId% + If ErrorLevel + Log_msg("Manager_winShow: Potentially hung window " . wndId) + Else { + WinShow, ahk_id %wndId% + } +} + +Manager_winClose(wndId) { + WM_NULL := 0 + SendMessage, WM_NULL, , , , ahk_id %wndId% + If ErrorLevel + Log_msg("Manager_winClose: Potentially hung window " . wndId) + Else { + WinClose, ahk_id %wndId% + } +} + +Manager_winSet(type, value, wndId) { + WM_NULL := 0 + SendMessage, WM_NULL, , , , ahk_id %wndId% + If ErrorLevel + Log_msg("Manager_winSet: Potentially hung window " . wndId) + Else { + WinSet, %type%, %value%, ahk_id %wndId% + } +} \ No newline at end of file diff --git a/src/Monitor.ahk b/src/Monitor.ahk index 62d0855..4447f22 100644 --- a/src/Monitor.ahk +++ b/src/Monitor.ahk @@ -80,7 +80,7 @@ Monitor_activateView(v) { StringTrimRight, wndIds, View_#%m%_#%aView%_wndIds, 1 Loop, PARSE, wndIds, `; If Not (Manager_#%A_LoopField%_tags & (1 << v - 1)) - WinHide, ahk_id %A_LoopField% + Manager_winHide(A_LoopField) SetWinDelay, 10 DetectHiddenWindows, On View_arrange(m, v) @@ -88,7 +88,7 @@ Monitor_activateView(v) { StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 SetWinDelay, 0 Loop, PARSE, wndIds, `; - WinShow, ahk_id %A_LoopField% + Manager_winShow(A_LoopField) SetWinDelay, 10 Manager_hideShow := False @@ -225,7 +225,7 @@ Monitor_setWindowTag(t) { Monitor_activateView(t) Else { Manager_hideShow := True - WinHide, ahk_id %aWndId% + Manager_winHide(aWndId) Manager_hideShow := False View_arrange(Manager_aMonitor, aView) Bar_updateView(Manager_aMonitor, t) @@ -278,7 +278,7 @@ Monitor_toggleWindowTag(t) { Bar_updateView(Manager_aMonitor, t) If (t = Monitor_#%Manager_aMonitor%_aView_#1) { Manager_hideShow := True - WinHide, ahk_id %aWndId% + Manager_winHide(aWndId) Manager_hideShow := False wndId := SubStr(View_#%Manager_aMonitor%_#%t%_wndIds, 1, InStr(View_#%Manager_aMonitor%_#%t%_wndIds, ";")-1) Manager_winActivate(wndId) diff --git a/src/View.ahk b/src/View.ahk index 2ea7dda..4548e53 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -55,10 +55,10 @@ View_activateWindow(d) { j := Manager_loop(i, d, 1, wndId0) Log_dbg_bare(2, "Next wndId index: " . j) wndId := wndId%j% - WinSet, AlwaysOnTop, On, ahk_id %wndId% - WinSet, AlwaysOnTop, Off, ahk_id %wndId% + Manager_winSet("AlwaysOnTop", "On", wndId) + Manager_winSet("AlwaysOnTop", "Off", wndId) If Manager_#%aWndId%_isFloating - WinSet, Bottom, , ahk_id %aWndId% + Manager_winSet("Bottom", "", aWndId) Manager_winActivate(wndId) } } From 937fed87b9c56b8384a13358b137ce224d24cc14 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Wed, 27 Jun 2012 22:35:52 -0400 Subject: [PATCH 47/60] Cycle through windows correctly when there are hung windows --- src/Manager.ahk | 35 ++++++++++++++++++++++++++++------- src/View.ahk | 24 +++++++++++++++++++----- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index 7c04ce6..1be54f3 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -491,6 +491,7 @@ Manager_onShellMessage(wParam, lParam) { wndId := SubStr(wndIds, 1, InStr(wndIds, ";") - 1) Loop, % Config_viewCount If (Manager_#%wndId%_tags & 1 << A_Index - 1) { + Log_dbg_msg(3, "Switching views because " . wndId . " is considered hidden and active") Manager_aMonitor := Manager_#%wndId%_monitor Monitor_activateView(A_Index) Break @@ -719,23 +720,31 @@ Manager_winActivate(wndId) { } 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)) } - WinActivate, ahk_id %wndId% + SendMessage, 0, , , , ahk_id %wndId% + If ErrorLevel + Log_msg("Manager_winActivate: Potentially hung window " . wndId) + Else + WinActivate, ahk_id %wndId% Bar_updateTitle() } Manager_winMove(wndId, x, y, width, height) { WM_NULL := 0 SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel + If ErrorLevel { Log_msg("Manager_winMove: Potentially hung window " . wndId) + Return 1 + } Else WinRestore, ahk_id %wndId% WM_ENTERSIZEMOVE = 0x0231 WM_EXITSIZEMOVE = 0x0232 SendMessage, WM_ENTERSIZEMOVE, , , , ahk_id %wndId% tmp_errorlevel := ErrorLevel - If ErrorLevel + If ErrorLevel { Log_msg("Manager_winMove: Potentially hung window " . wndId) + Return 1 + } Else { WinMove, ahk_id %wndId%, , %x%, %y%, %width%, %height% SendMessage, WM_EXITSIZEMOVE, , , , ahk_id %wndId% @@ -745,39 +754,51 @@ Manager_winMove(wndId, x, y, width, height) { Manager_winHide(wndId) { WM_NULL := 0 SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel + If ErrorLevel { Log_msg("Manager_winHide: Potentially hung window " . wndId) + Return 1 + } Else { WinHide, ahk_id %wndId% + Return 0 } } Manager_winShow(wndId) { WM_NULL := 0 SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel + If ErrorLevel { Log_msg("Manager_winShow: Potentially hung window " . wndId) + Return 1 + } Else { WinShow, ahk_id %wndId% + Return 0 } } Manager_winClose(wndId) { WM_NULL := 0 SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel + If ErrorLevel { Log_msg("Manager_winClose: Potentially hung window " . wndId) + Return 1 + } Else { WinClose, ahk_id %wndId% + Return 0 } } Manager_winSet(type, value, wndId) { WM_NULL := 0 SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel + If ErrorLevel { Log_msg("Manager_winSet: Potentially hung window " . wndId) + Return 1 + } Else { WinSet, %type%, %value%, ahk_id %wndId% + Return 0 } } \ No newline at end of file diff --git a/src/View.ahk b/src/View.ahk index 4548e53..df8858a 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -36,8 +36,13 @@ View_init(m, v) { } View_activateWindow(d) { - Local aWndId, i, j, v, wndId, wndId0, wndIds + Local aWndId, i, j, v, wndId, wndId0, wndIds, success, direction + Log_dbg_msg(1, "View_activateWindow(" . d . ")") + + If (d = 0) + Return + WinGet, aWndId, ID, A Log_dbg_bare(2, "Active Windows ID: " . aWndId) v := Monitor_#%Manager_aMonitor%_aView_#1 @@ -51,12 +56,21 @@ View_activateWindow(d) { i := A_Index Break } + If (d > 0) + direction = 1 + Else + direction = -1 Log_dbg_bare(2, "Current wndId index: " . i) j := Manager_loop(i, d, 1, wndId0) - Log_dbg_bare(2, "Next wndId index: " . j) - wndId := wndId%j% - Manager_winSet("AlwaysOnTop", "On", wndId) - Manager_winSet("AlwaysOnTop", "Off", wndId) + Loop, % wndId0 { + Log_dbg_bare(2, "Next wndId index: " . j) + wndId := wndId%j% + Manager_winSet("AlwaysOnTop", "On", wndId) + success := Manager_winSet("AlwaysOnTop", "Off", wndId) + If (success = 0) + Break + j := Manager_loop(j, direction, 1, wndId0) + } If Manager_#%aWndId%_isFloating Manager_winSet("Bottom", "", aWndId) Manager_winActivate(wndId) From fbbecc71e8863d616067aeaccc85e3b6fcfd0588 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Wed, 27 Jun 2012 23:34:19 -0400 Subject: [PATCH 48/60] Fix a bug where some guarded windows commands couldn't get to windows because they were hidden from the SendMessage command. Add more window logging --- src/Config.ahk | 2 +- src/Manager.ahk | 122 +++++++++++++++++++++++++++++++----------------- 2 files changed, 80 insertions(+), 44 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index 68bca41..ac1a8aa 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -391,7 +391,7 @@ Config_saveSession() { #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). #^i::Manager_logViewWindowList() -;#+^::Manager_logWindowList() +#+^i::Manager_logManagedWindowList() #^h::Manager_logHelp() #^d::Log_decDebugLevel() #^e::Log_incDebugLevel() diff --git a/src/Manager.ahk b/src/Manager.ahk index 1be54f3..396d0dc 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -237,38 +237,51 @@ Manager_logViewLayout() { } Manager_logWindowInfo( w ) { - Local av, aWndId, aIsWinFocus, aIsBugnActive, aIsFloating, aIsHidden, aIsDecorated, aWndTitle, aWndStyle, aWndX, aWndY, aWndW, aWndH + Local v, wndId, isWinFocus, isBugnActive, isFloating, isHidden, isDecorated, isResponsive, wndTitle, wndProc, wndClass, wndStyle, wndX, wndY, wndW, wndH, detect_state - WinGet, aWndId, ID, A - If aWndId = %w% - aIsWinFocus := "*" + detect_state := A_DetectHiddenWindows + DetectHiddenWindows, On + WinGet, wndId, ID, A + If wndId = %w% + isWinFocus := "*" Else - aIsWinFocus := " " - av := Monitor_#%Manager_aMonitor%_aView_#1 - If View_#%Manager_aMonitor%_#%av%_aWndId = %w% - aIsBugnActive := "*" + isWinFocus := " " + v := Monitor_#%Manager_aMonitor%_aView_#1 + If View_#%Manager_aMonitor%_#%v%_aWndId = %w% + isBugnActive := "*" Else - aIsBugnActive := " " - WinGetTitle, aWndTitle, ahk_id %w% + isBugnActive := " " + WinGetTitle, wndTitle, ahk_id %w% + WinGetClass, wndClass, ahk_id %w% + WinGet, wndProc, ProcessName, ahk_id %w% If InStr(Bar_hiddenWndIds, w) - aIsHidden := "*" + isHidden := "*" Else - aIsHidden := " " + isHidden := " " If Manager_#%w%_isFloating - aIsFloating := "*" + isFloating := "*" Else - aIsFloating := " " + isFloating := " " If Manager_#%w%_isDecorated - aIsDecorated := "*" + isDecorated := "*" Else - aIsDecorated := " " - WinGet, aWndStyle, Style, ahk_id %w% - WinGetPos, aWndX, aWndY, aWndW, aWndH, ahk_id %w% - ;Manager_#%wndId%_monitor := m - ;Manager_#%wndId%_tags := tags - ;Manager_#%wndId%_isDecorated := isDecorated - ;Manager_#%wndId%_isFloating := isFloating - Log_bare(w . "`t" . aIsHidden . " " aIsWinFocus . " " . aIsBugnActive . " " . aIsFloating . " " . aIsDecorated . " " . Manager_#%w%_monitor . "`t" . Manager_#%w%_tags . "`t" . aWndX . "`t" . aWndY . "`t" . aWndW . "`t" . aWndH . "`t" . aWndStyle . "`t" . aWndTitle) + isDecorated := " " + WinGet, wndStyle, Style, ahk_id %w% + WinGetPos, wndX, wndY, wndW, wndH, ahk_id %w% + + DetectHiddenWindows, %detect_state% + + ; Intentionally don't detect hidden windows here to see what Manager_hungTest does + If Manager_hungTest(w) + isResponsive := " " + Else + isResponsive := "*" + + Log_bare(w . "`t" . isHidden . " " isWinFocus . " " . isBugnActive . " " . isFloating . " " . isDecorated . " " . isResponsive . " " . Manager_#%w%_monitor . "`t" . Manager_#%w%_tags . "`t" . wndX . "`t" . wndY . "`t" . wndW . "`t" . wndH . "`t" . wndStyle . "`t" . wndProc . " / " . wndClass . " / " . wndTitle) +} + +Manager_logHeader() { + Log_bare( "ID`t`tH W A F D R M`tTags`tX`tY`tW`tH`tStyle`t`tProc / Class / Title") } Manager_logViewWindowList() { @@ -276,7 +289,7 @@ Manager_logViewWindowList() { v := Monitor_#%Manager_aMonitor%_aView_#1 Log_msg( "Window dump for active view (" . Manager_aMonitor . ", " . v . ")" ) - Log_bare( "ID`t`tH W A F D M`tTags`tX`tY`tW`tH`tStyle`t`tTitle") + Manager_logHeader() StringTrimRight, wndIds, View_#%Manager_aMonitor%_#%v%_wndIds, 1 Loop, PARSE, wndIds, `; @@ -285,6 +298,19 @@ Manager_logViewWindowList() { } } +Manager_logManagedWindowList() { + Local wndIds + + Log_msg( "Window dump for manager" ) + Manager_logHeader() + + StringTrimRight, wndIds, Manager_managedWndIds, 1 + Loop, PARSE, wndIds, `; + { + Manager_logWindowInfo( A_LoopField) + } +} + Manager_logHelp() { Log_msg("Help Display") Log_bare("Window list columns") @@ -294,6 +320,7 @@ Manager_logHelp() { Log_bare(" A - View active") Log_bare(" F - Floating") Log_bare(" D - Decorated") + Log_bare(" R - Responsive") Log_bare(" M - Monitor") Log_bare(" Tags - Bit-mask of the views in which the window is active") Log_bare(" X - Windows X position") @@ -301,7 +328,7 @@ Manager_logHelp() { Log_bare(" W - Windows width") Log_bare(" H - Windows height") Log_bare(" Style - Windows style") - Log_bare(" Title - Title of the window") + Log_bare(" Proc / Class / Title - Process/Class/Title of the window") } Manager_lockWorkStation() { @@ -720,8 +747,7 @@ Manager_winActivate(wndId) { } 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)) } - SendMessage, 0, , , , ahk_id %wndId% - If ErrorLevel + If Manager_hungTest(wndId) Log_msg("Manager_winActivate: Potentially hung window " . wndId) Else WinActivate, ahk_id %wndId% @@ -729,9 +755,7 @@ Manager_winActivate(wndId) { } Manager_winMove(wndId, x, y, width, height) { - WM_NULL := 0 - SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel { + If Manager_hungTest(wndId) { Log_msg("Manager_winMove: Potentially hung window " . wndId) Return 1 } @@ -740,7 +764,6 @@ Manager_winMove(wndId, x, y, width, height) { WM_ENTERSIZEMOVE = 0x0231 WM_EXITSIZEMOVE = 0x0232 SendMessage, WM_ENTERSIZEMOVE, , , , ahk_id %wndId% - tmp_errorlevel := ErrorLevel If ErrorLevel { Log_msg("Manager_winMove: Potentially hung window " . wndId) Return 1 @@ -752,9 +775,8 @@ Manager_winMove(wndId, x, y, width, height) { } Manager_winHide(wndId) { - WM_NULL := 0 - SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel { + + If Manager_hungTest(wndId) { Log_msg("Manager_winHide: Potentially hung window " . wndId) Return 1 } @@ -765,9 +787,8 @@ Manager_winHide(wndId) { } Manager_winShow(wndId) { - WM_NULL := 0 - SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel { + + If Manager_hungTest(wndId) { Log_msg("Manager_winShow: Potentially hung window " . wndId) Return 1 } @@ -778,9 +799,8 @@ Manager_winShow(wndId) { } Manager_winClose(wndId) { - WM_NULL := 0 - SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel { + + If Manager_hungTest(wndId) { Log_msg("Manager_winClose: Potentially hung window " . wndId) Return 1 } @@ -791,9 +811,8 @@ Manager_winClose(wndId) { } Manager_winSet(type, value, wndId) { - WM_NULL := 0 - SendMessage, WM_NULL, , , , ahk_id %wndId% - If ErrorLevel { + + If Manager_hungTest(wndId) { Log_msg("Manager_winSet: Potentially hung window " . wndId) Return 1 } @@ -801,4 +820,21 @@ Manager_winSet(type, value, wndId) { WinSet, %type%, %value%, ahk_id %wndId% Return 0 } +} + +; 0 - Not hung +; 1 - Hung +Manager_hungTest(wndId) { + Local result, detect_setting, WM_NULL + WM_NULL := 0 + detect_setting := A_DetectHiddenWindows + DetectHiddenWindows, On + SendMessage, WM_NULL, , , , ahk_id %wndId% + result := ErrorLevel + DetectHiddenWindows, %detect_setting% + + If result + Return 1 + Else + Return 0 } \ No newline at end of file From 0f5f77b7cbf7d495d160e5d362c9b176d3ef2c13 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 29 Jun 2012 22:00:02 -0400 Subject: [PATCH 49/60] Allow the window to recover to test recovery --- test/hang.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hang.cpp b/test/hang.cpp index 7003f6f..c297715 100644 --- a/test/hang.cpp +++ b/test/hang.cpp @@ -49,7 +49,7 @@ int WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,int nCmdShow) } -int maintain_bomb = 30; +int maintain_bomb = 60; int activate_bomb = 5; LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) @@ -76,7 +76,7 @@ LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) if(activate_bomb == 0) while(maintain_bomb) { Sleep(1000); - //maintain_bomb--; + maintain_bomb--; } activate_bomb--; From fcc058b397db3ef74c4dd9ab833d4a9e38c4c444 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Fri, 29 Jun 2012 22:20:15 -0400 Subject: [PATCH 50/60] BID --- src/Manager.ahk | 188 ++++++++++++++++++++++++++++++++++++++---------- src/View.ahk | 27 +++++-- 2 files changed, 172 insertions(+), 43 deletions(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index 396d0dc..de1d25f 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -237,7 +237,7 @@ Manager_logViewLayout() { } Manager_logWindowInfo( w ) { - Local v, wndId, isWinFocus, isBugnActive, isFloating, isHidden, isDecorated, isResponsive, wndTitle, wndProc, wndClass, wndStyle, wndX, wndY, wndW, wndH, detect_state + Local v, wndId, isWinFocus, isBugnActive, isFloating, isHidden, isDecorated, isResponsive, isGhost, wndTitle, wndProc, wndClass, wndStyle, wndX, wndY, wndW, wndH, detect_state detect_state := A_DetectHiddenWindows DetectHiddenWindows, On @@ -269,19 +269,25 @@ Manager_logWindowInfo( w ) { WinGet, wndStyle, Style, ahk_id %w% WinGetPos, wndX, wndY, wndW, wndH, ahk_id %w% + If Manager_isGhost(w) + isGhost := "*" + Else + isGhost := " " + DetectHiddenWindows, %detect_state% ; Intentionally don't detect hidden windows here to see what Manager_hungTest does - If Manager_hungTest(w) + If Manager_isHung(w) isResponsive := " " Else isResponsive := "*" + - Log_bare(w . "`t" . isHidden . " " isWinFocus . " " . isBugnActive . " " . isFloating . " " . isDecorated . " " . isResponsive . " " . Manager_#%w%_monitor . "`t" . Manager_#%w%_tags . "`t" . wndX . "`t" . wndY . "`t" . wndW . "`t" . wndH . "`t" . wndStyle . "`t" . wndProc . " / " . wndClass . " / " . wndTitle) + Log_bare(w . "`t" . isHidden . " " isWinFocus . " " . isBugnActive . " " . isFloating . " " . isDecorated . " " . isResponsive . " " . isGhost . " " . Manager_#%w%_monitor . "`t" . Manager_#%w%_tags . "`t" . wndX . "`t" . wndY . "`t" . wndW . "`t" . wndH . "`t" . wndStyle . "`t" . wndProc . " / " . wndClass . " / " . wndTitle) } Manager_logHeader() { - Log_bare( "ID`t`tH W A F D R M`tTags`tX`tY`tW`tH`tStyle`t`tProc / Class / Title") + Log_bare( "ID`t`tH W A F D R G M`tTags`tX`tY`tW`tH`tStyle`t`tProc / Class / Title") } Manager_logViewWindowList() { @@ -321,6 +327,7 @@ Manager_logHelp() { Log_bare(" F - Floating") Log_bare(" D - Decorated") Log_bare(" R - Responsive") + Log_bare(" G - Ghost") Log_bare(" M - Monitor") Log_bare(" Tags - Bit-mask of the views in which the window is active") Log_bare(" X - Windows X position") @@ -360,21 +367,44 @@ Manager_loop(index, increment, lowerBound, upperBound) { ; pv - Preferred view ; wndId - Window to add to the manager. Manager_manage(pm, pv, wndId) { - Local a, c0, hideTitle, i, isDecorated, isFloating, isManaged, l, m, n, replace, search, tags + Local a, c0, hideTitle, i, isDecorated, isFloating, isManaged, l, m, n, replace, search, tags, body Local wndControlList0, wndId0, wndIds, wndX, wndY, wndWidth, wndHeight, wndProcessName If Not InStr(Manager_allWndIds, wndId ";") Manager_allWndIds .= wndId ";" - Manager_applyRules(wndId, isManaged, m, tags, isFloating, isDecorated, hideTitle) - If (m = 0) - m := pm - 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 << (pv - 1) + body := 0 + If Manager_isGhost( wndId ) { + Log_dbg_msg(2, "A window has given up the ghost (Ghost wndId: " . wndId . ")") + ; Ghosts need special attention. + ; Say a quick prayer and try to reattach it to its body. + body := Manager_findHung( wndId ) + If body { + isManaged := InStr(Manager_managedWndIds, body ";") + m := Manager_#%body%_monitor + tags := Manager_#%body%_tags + isDecorated := Manager_#%body%_isDecorated + isFloating := Manager_#%body%_isFloating + hideTitle := InStr(Bar_hideTitleWndIds, body ";") + } + Else { + Log_dbg_msg(1, "No body could be found for ghost wndId: " . wndId) + } + } + + ; 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) + + If (m = 0) + m := pm + 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 << (pv - 1) + } WinGet, wndProcessName, ProcessName, ahk_id %wndId% If (wndProcessName = "chrome.exe") { @@ -395,7 +425,13 @@ Manager_manage(pm, pv, wndId) { Loop, % Config_viewCount If (Manager_#%wndId%_tags & 1 << A_Index - 1) { - View_addWnd(m, A_Index, wndId) + If (body) { + ; Try to position near the body. + View_ghostWnd(m, A_Index, body, wndId) + } + Else { + View_addWnd(m, A_Index, wndId) + } } If Not Config_showBorder @@ -456,19 +492,48 @@ HSHELL_WINDOWDESTROYED := 2 HSHELL_WINDOWACTIVATED := 4 ; At least title change. HSHELL_REDRAW := 6 +; The following two are seen when a hung window recovers. +; lParam notes the ghost process +HSHELL_WINDOWREPLACED := 13 +; lParam notes the recovered process +;14 ; Full-screen app activated? Root-privileged window activated? HSHELL_RUDEAPPACTIVATED := 32772 ; When a window is signalling an application update. WINDOW_NOTICE := 32774 +; +; Reliable messages and their meanings (note that any message may be missed if bug.n is hung): +; 1 - Window shown (shown ID) +; 2 - Window destroyed or hidden, same message for both (destroyed or hidden ID) +; 4 - Window activated via mouse, alt+tab, or hotkey (sometimes 32772, but always one of them) +; 6 - Window title change (ID of redrawn window) +; 13 - Hung window recovers and replaces ghost window (ghost window ID is provided) +; 14 - Hung window recovered (ID of previously hung window) +; 32772 - Window activated via mouse, alt+tab, or hotkey (sometimes 4, but always one of them) +; 32774 - Window is flashing due to some event, one message for each flash +; +; Indications of: +; New windows - cmd/shell may be starting a new window on message 6 +; Win+e indicates a new window with message 6 as long as the button +; presses are below a certain frequency. +; Message 1 may indicate a new window started from Windows Explorer +; There doesn't seem to be a reliable way to get all application starts. +; Closed windows - 13 always indicates closed ghost window +; 2 always indicates closed standard window +; Focus change - 4 or 32772 always catch this +; Window event - 6 indicates when title changes which can be used +; in the case of some applications, 32774 works for others +; Manager_onShellMessage(wParam, lParam) { Local a, isChanged, aWndClass, aWndHeight, aWndId, aWndTitle, aWndWidth, aWndX, aWndY, m, t, wndClass, wndId, wndIds, wndPName, wndTitle, x, y - Log_dbg_msg(2, "Manager_onShellMessage(wParam: " . wParam . ", lParam: " . lParam) - SetFormat, Integer, hex lParam := lParam+0 SetFormat, Integer, d + + Log_dbg_msg(2, "Manager_onShellMessage( wParam: " . wParam . ", lParam: " . lParam . " )") + WinGetClass, wndClass, ahk_id %lParam% WinGetTitle, wndTitle, ahk_id %lParam% WinGet, wndPName, ProcessName, ahk_id %lParam% @@ -484,6 +549,15 @@ Manager_onShellMessage(wParam, lParam) { Bar_updateTitle() } + 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. + } + If (wParam = 1 Or wParam = 2 Or wParam = 4 Or wParam = 6 Or wParam = 32772) And lParam And Not Manager_hideShow And Not Manager_focus { If Not (wParam = 4 Or wParam = 32772) If Not wndClass And Not (wParam = 2) { @@ -513,8 +587,6 @@ Manager_onShellMessage(wParam, lParam) { If wndIds { If (Config_onActiveHiddenWnds = "view") { - ; Grab the first of such windows and make it visible. - ; All others get forgotten (until the next round?) wndId := SubStr(wndIds, 1, InStr(wndIds, ";") - 1) Loop, % Config_viewCount If (Manager_#%wndId%_tags & 1 << A_Index - 1) { @@ -646,8 +718,11 @@ Manager_sync(ByRef wndIds = "") { flag := Manager_manage(Manager_aMonitor, Monitor_#%Manager_aMonitor%_aView_#1, wndId%A_Index%) If flag a := flag - } Else + } Else If Not Manager_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% ";" } @@ -738,7 +813,7 @@ Manager_unmanage(wndId) { } Manager_winActivate(wndId) { - Local wndHeight, wndWidth, wndX, wndY + Local wndHeight, wndWidth, wndX, wndY, newWnd If Config_mouseFollowsFocus { If wndId { @@ -747,16 +822,23 @@ Manager_winActivate(wndId) { } 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)) } - If Manager_hungTest(wndId) - Log_msg("Manager_winActivate: Potentially hung window " . wndId) - Else + If Manager_isHung(wndId) { + Log_dbg_msg(2, "Manager_winActivate: Potentially hung window " . wndId) + Return 1 + } + Else { WinActivate, ahk_id %wndId% + WinGet, newWin, ID, A + If (wndId != newWin) + Return 1 + } Bar_updateTitle() + Return 0 } Manager_winMove(wndId, x, y, width, height) { - If Manager_hungTest(wndId) { - Log_msg("Manager_winMove: Potentially hung window " . wndId) + If Manager_isHung(wndId) { + Log_dbg_msg(2, "Manager_winMove: Potentially hung window " . wndId) Return 1 } Else @@ -765,7 +847,7 @@ Manager_winMove(wndId, x, y, width, height) { WM_EXITSIZEMOVE = 0x0232 SendMessage, WM_ENTERSIZEMOVE, , , , ahk_id %wndId% If ErrorLevel { - Log_msg("Manager_winMove: Potentially hung window " . wndId) + Log_dbg_msg(2, "Manager_winMove: Potentially hung window " . wndId) Return 1 } Else { @@ -776,8 +858,8 @@ Manager_winMove(wndId, x, y, width, height) { Manager_winHide(wndId) { - If Manager_hungTest(wndId) { - Log_msg("Manager_winHide: Potentially hung window " . wndId) + If Manager_isHung(wndId) { + Log_dbg_msg(2, "Manager_winHide: Potentially hung window " . wndId) Return 1 } Else { @@ -788,8 +870,8 @@ Manager_winHide(wndId) { Manager_winShow(wndId) { - If Manager_hungTest(wndId) { - Log_msg("Manager_winShow: Potentially hung window " . wndId) + If Manager_isHung(wndId) { + Log_dbg_msg(2, "Manager_winShow: Potentially hung window " . wndId) Return 1 } Else { @@ -800,8 +882,8 @@ Manager_winShow(wndId) { Manager_winClose(wndId) { - If Manager_hungTest(wndId) { - Log_msg("Manager_winClose: Potentially hung window " . wndId) + If Manager_isHung(wndId) { + Log_dbg_msg(2, "Manager_winClose: Potentially hung window " . wndId) Return 1 } Else { @@ -812,8 +894,8 @@ Manager_winClose(wndId) { Manager_winSet(type, value, wndId) { - If Manager_hungTest(wndId) { - Log_msg("Manager_winSet: Potentially hung window " . wndId) + If Manager_isHung(wndId) { + Log_dbg_msg(2, "Manager_winSet: Potentially hung window " . wndId) Return 1 } Else { @@ -824,7 +906,7 @@ Manager_winSet(type, value, wndId) { ; 0 - Not hung ; 1 - Hung -Manager_hungTest(wndId) { +Manager_isHung(wndId) { Local result, detect_setting, WM_NULL WM_NULL := 0 detect_setting := A_DetectHiddenWindows @@ -837,4 +919,38 @@ Manager_hungTest(wndId) { Return 1 Else Return 0 +} + +; Given a ghost window, try to find its body. +; This is only known to work on Windows 7 +Manager_findHung( ghostWnd ) { + Local expectedTitle, expectedX, expectedY, expectedW, expectedH, wndTitle, wndX, wndY, wndW, wndH, wndIds + ;Log_dbg_msg(3, "Manager_findHung(" . ghostWnd . ")") + WinGetTitle, expectedTitle, ahk_id %ghostWnd% + StringReplace, expectedTitle, expectedTitle, " (Not Responding)", "" + WinGetPos, expectedX, expectedY, expectedW, expectedH, ahk_id %ghostWnd% + + SetTitleMatchMode, 2 + WinGet, wndIds, List, %expectedTitle% + Loop, % wndIds { + If (A_Index = ghostWnd) + Continue + WinGetPos, wndX, wndY, wndW, wndH, % "ahk_id" wndIDs%A_Index% + + If (wndX = expectedX) And (wndY = expectedY) And (wndW = expectedW) And (wndH = expectedH) + Return wndIds%A_Index% + } + Return 0 +} + +Manager_isGhost(wndId) { + Local wndClass, wndProc + + WinGet, wndProc, ProcessName, ahk_id %wndId% + WinGetClass, wndClass, ahk_id %wndId% + + If (wndProc = "dwm.exe") And (wndClass = "Ghost") + Return 1 + Else + Return 0 } \ No newline at end of file diff --git a/src/View.ahk b/src/View.ahk index df8858a..ce54aea 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -36,7 +36,7 @@ View_init(m, v) { } View_activateWindow(d) { - Local aWndId, i, j, v, wndId, wndId0, wndIds, success, direction + Local aWndId, i, j, v, wndId, wndId0, wndIds, failure, direction Log_dbg_msg(1, "View_activateWindow(" . d . ")") @@ -51,6 +51,8 @@ View_activateWindow(d) { StringSplit, wndId, wndIds, `; Log_dbg_bare(2, "wndId count: " . wndId0) If (wndId0 > 1) { + If Manager_#%aWndId%_isFloating + Manager_winSet("Bottom", "", aWndId) Loop, % wndId0 If (wndId%A_Index% = aWndId) { i := A_Index @@ -66,14 +68,17 @@ View_activateWindow(d) { Log_dbg_bare(2, "Next wndId index: " . j) wndId := wndId%j% Manager_winSet("AlwaysOnTop", "On", wndId) - success := Manager_winSet("AlwaysOnTop", "Off", wndId) - If (success = 0) + Manager_winSet("AlwaysOnTop", "Off", wndId) + ; This is a lot of extra work in case 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 + } + j := Manager_loop(j, direction, 1, wndId0) } - If Manager_#%aWndId%_isFloating - Manager_winSet("Bottom", "", aWndId) - Manager_winActivate(wndId) + } } @@ -115,6 +120,14 @@ View_addWnd(m, v, wndId) { View_#%m%_#%v%_wndIds := wndId ";" View_#%m%_#%v%_wndIds } +View_ghostWnd(m, v, bodyWndId, ghostWndId) { + Local search, replace + + search := bodyWndId ";" + replace := search ghostWndId ";" + StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, %search%, %replace% +} + ; Remove a window from the view in question. View_delWnd(m, v, wndId) { StringReplace, View_#%m%_#%v%_wndIds, View_#%m%_#%v%_wndIds, %wndId%`;, @@ -140,7 +153,7 @@ View_getTiledWndIds(m, v, ByRef tiledWndIds) { StringTrimRight, wndIds, View_#%m%_#%v%_wndIds, 1 Loop, PARSE, wndIds, `; { - If Not Manager_#%A_LoopField%_isFloating And WinExist("ahk_id " A_LoopField) { + If Not Manager_#%A_LoopField%_isFloating And WinExist("ahk_id " A_LoopField) and Not Manager_isHung(A_LoopField) { n += 1 tiledWndIds .= A_LoopField ";" } From 85e6635d31c9ee0626ffcdb8803845585296eda0 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 12:23:19 -0400 Subject: [PATCH 51/60] Noted that bug 018641 is fixed. --- ChangeLog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9a19a56..b70b3f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,8 @@ Features in the absence of windows. Bugs + - BID 018641: Freezing problem. This problem has been largely mitigated, + but it is still possible. - Cycling through windows on a view no longer gets stuck. - Prevent windows from switching to different monitors under odd circumstances. From a6928208f68596127059580095ca32e5a0ce7c75 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 12:24:48 -0400 Subject: [PATCH 52/60] Prepare for submission to project repository. --- src/Config.ahk | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index ac1a8aa..dcd46ca 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -60,11 +60,11 @@ Config_init() { Config_layoutAxis_#1 := 1 ; The layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top. Config_layoutAxis_#2 := 2 ; The master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle). Config_layoutAxis_#3 := 2 ; The stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle). - Config_layoutGapWidth := -4 ; The default gap width in px (only even numbers) of the "tile" layout, i. e. the space between windows and around the layout. + Config_layoutGapWidth := 0 ; The default gap width in px (only even numbers) of the "tile" layout, i. e. the space between windows and around the layout. Config_layoutMFactor := 0.6 ; The factor for the size of the master area, which is multiplied by the monitor size. Config_mouseFollowsFocus := True ; If true, the mouse pointer is set over the focused window, if a window is activated by bug.n. Config_onActiveHiddenWnds := "view" ; The action, which will be taken, if a window e. g. should be activated, but is not visible; "view": show the view accordng to the first tag of the window in question, "tag": add the window in question to the current visible view, "hide": hide the window again ignoring the activation. - Config_newWndPosition := "bottom" ; The position of a new window in a view; "top": at the beginning of the window list and the master area (default), "masterBottom": at the end of the master area, "stackTop": on top of the stack area, "bottom": at the end of the window list and the stack area. + Config_newWndPosition := "top" ; The position of a new window in a view; "top": at the beginning of the window list and the master area (default), "masterBottom": at the end of the master area, "stackTop": on top of the stack area, "bottom": at the end of the window list and the stack area. Config_shellMsgDelay := 350 ; The time bug.n waits after a shell message (a window is opened, closed or the focus has been changed); if there are any problems recognizing, when windows are opened or closed, try to increase this number. Config_syncMonitorViews := 0 ; The number of monitors (2 or more), for which views should be activated, when using the accordant hotkey. If set to 1, the views are activated for all monitors. If set to 0, views are activated independently (only on the active monitor). Config_viewFollowsTagged := False ; If true and a window is tagged with a single tag, the view is correspondingly set to the tag. @@ -377,41 +377,41 @@ Config_saveSession() { * format: <modifier><key>::<function>(<argument>) * modifier: ! = Alt (Mod1Mask), ^ = Ctrl (ControlMask), + = Shift (ShiftMask), # = LWin (Mod4Mask) */ -#m::View_activateWindow(+1) ; Activate the next window in the active view. -#n::View_activateWindow(-1) ; Activate the previous window in the active view. -#+m::View_shuffleWindow(+1) ; Move the active window to the next position in the window list of the view. -#+n::View_shuffleWindow(-1) ; Move the active window to the previous position in the window list of the view. +#Down::View_activateWindow(+1) ; Activate the next window in the active view. +#Up::View_activateWindow(-1) ; Activate the previous window in the active view. +#+Down::View_shuffleWindow(+1) ; Move the active window to the next position in the window list of the view. +#+Up::View_shuffleWindow(-1) ; Move the active window to the previous position in the window list of the view. #+Enter::View_shuffleWindow(0) ; Move the active window to the first position in the window list of the view. #c::Manager_closeWindow() ; Close the active window. #+d::Manager_toggleDecor() ; Show / Hide the title bar of the active window. #+f::View_toggleFloating() ; Toggle the floating status of the active window (i. e. dis- / regard it when tiling). -#+q::Manager_moveWindow() ; Move the active window by key (only floating windows). +#+m::Manager_moveWindow() ; Move the active window by key (only floating windows). #+s::Manager_sizeWindow() ; Resize the active window by key (only floating windows). #+x::Manager_maximizeWindow() ; Move and resize the active window to the size of the work area (only floating windows). #i::Manager_getWindowInfo() ; Get information for the active window (id, title, class, process name, style, geometry, tags and floating state). #+i::Manager_getWindowList() ; Get a window list for the active view (id, title and class). -#^i::Manager_logViewWindowList() -#+^i::Manager_logManagedWindowList() -#^h::Manager_logHelp() -#^d::Log_decDebugLevel() -#^e::Log_incDebugLevel() +#^i::Manager_logViewWindowList() ; Dump window information for the active view. +#+^i::Manager_logManagedWindowList() ; Dump window information for every managed window. +#^h::Manager_logHelp() ; Dump to the log an explanation of some of the other more cryptic log messages. +#^[::Log_decDebugLevel() ; Decrement the log debug level. +#^]::Log_incDebugLevel() ; Increment the log debug level. #Tab::View_setLayout(-1) ; Set the previously set layout. You may also use View_setLayout(">") for setting the next layout in the layout array. -#\::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). -#]::View_setLayout(2) ; Set the 2nd defined layout (i. e. monocle layout in the default configuration). -#[::View_setLayout(1) ; Set the 1st defined layout (i. e. tile layout in the default configuration). +#f::View_setLayout(3) ; Set the 3rd defined layout (i. e. floating layout in the default configuration). +#m::View_setLayout(2) ; Set the 2nd defined layout (i. e. monocle layout in the default configuration). +#t::View_setLayout(1) ; Set the 1st defined layout (i. e. tile layout in the default configuration). #Left::View_setMFactor(-0.05) ; Reduce the size of the master area in the active view (only for the "tile" layout). #Right::View_setMFactor(+0.05) ; Enlarge the size of the master area in the active view (only for the "tile" layout). #^t::View_rotateLayoutAxis(1, +1) ; Rotate the layout axis (i. e. 2 -> 1 = vertical layout, 1 -> 2 = horizontal layout, only for the "tile" layout). #^Enter::View_rotateLayoutAxis(1, +2) ; Mirror the layout axis (i. e. -1 -> 1 / 1 -> -1 = master on the left / right side, -2 -> 2 / 2 -> -2 = master at top / bottom, only for the "tile" layout). #^Tab::View_rotateLayoutAxis(2, +1) ; Rotate the master axis (i. e. 3 -> 1 = x-axis = horizontal stack, 1 -> 2 = y-axis = vertical stack, 2 -> 3 = z-axis = monocle, only for the "tile" layout). #^+Tab::View_rotateLayoutAxis(3, +1) ; Rotate the stack axis (i. e. 3 -> 1 = x-axis = horizontal stack, 1 -> 2 = y-axis = vertical stack, 2 -> 3 = z-axis = monocle, only for the "tile" layout). -#^Up::View_setMY(+1) ; Move the master splitter, i. e. decrease the number of windows in the master area (only for the "tile" layout). -#^Down::View_setMY(-1) ; Move the master splitter, i. e. increase the number of windows in the master area (only for the "tile" layout). -#^Right::View_setMX(+1) -#^Left::View_setMX(-1) -#Up::View_setGapWidth(-2) ; Decrease the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). -#Down::View_setGapWidth(+2) ; Increase the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). +#^Up::View_setMY(+1) ; Increase the master Y dimension [1,9] (only for the "tile" layout). +#^Down::View_setMY(-1) ; Decrease the master Y dimension [1,9] (only for the "tile" layout). +#^Right::View_setMX(+1) ; Increase the master X dimension [1,9] (only for the "tile" layout). +#^Left::View_setMX(-1) ; Decrease the master X dimension [1,9] (only for the "tile" layout). +#<::View_setGapWidth(-2) ; Decrease the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). +#+<::View_setGapWidth(+2) ; Increase the gap width by 2 px (only for the "tile" layout and even numbers; see the variable "Config_layoutGapWidth"). #BackSpace::Monitor_activateView(-1) ; Activate the previously activated view. You may also use Monitor_activateView("<") or Monitor_activateView(">") for activating the previous or next adjacent view. #+0::Monitor_setWindowTag(0) ; Tag the active window with all tags (1 ... Config_viewCount). You may also use Monitor_setWindowTag("<") or Monitor_setWindowTag(">") for setting the tag of the previous or next adjacent to the current view. @@ -453,9 +453,9 @@ Config_saveSession() { #+Space::Monitor_toggleBar() ; Hide / Show the bar (bug.n status bar) on the active monitor. #Space::Monitor_toggleTaskBar() ; Hide / Show the task bar. #y::Bar_toggleCommandGui() ; Open the command GUI for executing programmes or bug.n functions. -;#^e::Run, edit %Config_filePath% ; Open the configuration file in the standard text editor. +#^e::Run, edit %Config_filePath% ; Open the configuration file in the standard text editor. #^s::Config_saveSession() ; Save the current state of monitors, views, layouts to the configuration file. #^r::Main_reload() ; Reload bug.n (i. e. the configuration and its dependent settings) without deleting the window lists of bug.n and restoring windows. ; It does not reset internal configuration variables, the tray icon or menu, hotkeys (unless set explicitly in Config.ini), individual window settings like Config_showBorder (since windows might be hidden) or hiding the title bar, the monitor count or views. ; It does not reload functions. Changed rules are only applied to new windows. -#^Del::ExitApp ; Quit bug.n, restore the default Windows UI and show all windows. +#^q::ExitApp ; Quit bug.n, restore the default Windows UI and show all windows. From 809d91868ab277732a1b8590c26ef1c9e150c568 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 12:37:13 -0400 Subject: [PATCH 53/60] Use user data directory for logs. --- src/Main.ahk | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Main.ahk b/src/Main.ahk index 3487259..96dffd4 100644 --- a/src/Main.ahk +++ b/src/Main.ahk @@ -32,7 +32,22 @@ SetWinDelay, 10 #WinActivateForce ; pseudo main function - Log_init("bugn_log.txt", False) + + + EnvGet, appDir, APPDATA + bugnDir := appDir . "\bug.n" + IfNotExist, %bugnDir% + FileCreateDir, %bugnDir% + FileGetAttrib, attrib, %bugnDir% + IfNotInString, attrib, D + { + MsgBox, The file path '%appDir%' already exists and is not a directory. Aborting. + Return + } + logFile := bugnDir . "\bugn_log.txt" + Log_init(logFile, False) + + Log_msg("====== Initializing ======") If 0 = 1 Config_filePath = %1% From 4ad41cb813f3bd70870904d76d0a33256b9d54d2 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 12:57:20 -0400 Subject: [PATCH 54/60] Update UI with new options. Left logging commented out because it might not be a feature that should be advertised. --- src/Bar.ahk | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Bar.ahk b/src/Bar.ahk index 2717287..b15867e 100644 --- a/src/Bar.ahk +++ b/src/Bar.ahk @@ -214,8 +214,10 @@ Bar_initCmdGui() { TV_Add("rotate master axis", itemId20) TV_Add("rotate stack axis", itemId20) TV_Add("mirror tile layout", itemId20) - TV_Add("increase master split", itemId20) - TV_Add("decrease master split", itemId20) + TV_Add("increase master X", itemId20) + TV_Add("decrease master X", itemId20) + TV_Add("increase master Y", itemId20) + TV_Add("decrease master Y", itemId20) TV_Add("increase master factor", itemId20) TV_Add("decrease master factor", itemId20) itemId30 := TV_Add("View") @@ -229,6 +231,12 @@ Bar_initCmdGui() { TV_Add("toggle task bar", itemId40) TV_Add("activate next", itemId40) TV_Add("activate prev", itemId40) + ;itemId50 := TV_add("Log") + ; TV_Add("increment debug level", itemId50) + ; TV_Add("decrement debug level", itemId50) + ; TV_Add("log help info", itemId50) + ; TV_Add("log view window info", itemId50) + ; TV_Add("log managed window info", itemId50) TV_Add("Reload") TV_Add("Quit") GuiControl, +Redraw, Bar_#0_#0 @@ -353,6 +361,17 @@ Bar_evaluateCommand() { Manager_activateMonitor(+1) Else If (Bar_command_#1 = "activate prev") Manager_activateMonitor(-1) + } Else If (Bar_command_#2 = "Log") { + If (Bar_command_#1 = "increment debug level") + Manager_incDebugLevel() + If (Bar_command_#1 = "decrement debug level") + Manager_decDebugLevel() + If (Bar_command_#1 = "log help info") + Manager_logHelp() + If (Bar_command_#1 = "log view window info") + Manager_logViewWindowList() + If (Bar_command_#1 = "log managed window info") + Manager_logManagedWindowList() } Else If (Bar_command_#1 = "Reload") Main_reload() Else If (Bar_command_#1 = "Quit") From 643bf5b5ad35dea60a964a60b9f783f2ae159798 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 13:37:37 -0400 Subject: [PATCH 55/60] Oops, committed without testing. Sure enough, there were bugs. --- src/Bar.ahk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bar.ahk b/src/Bar.ahk index b15867e..40bdc50 100644 --- a/src/Bar.ahk +++ b/src/Bar.ahk @@ -363,9 +363,9 @@ Bar_evaluateCommand() { Manager_activateMonitor(-1) } Else If (Bar_command_#2 = "Log") { If (Bar_command_#1 = "increment debug level") - Manager_incDebugLevel() + Log_incDebugLevel() If (Bar_command_#1 = "decrement debug level") - Manager_decDebugLevel() + Log_decDebugLevel() If (Bar_command_#1 = "log help info") Manager_logHelp() If (Bar_command_#1 = "log view window info") From fbaab8e3aa4719277d4bf97590ccaee77920f2e3 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 13:38:00 -0400 Subject: [PATCH 56/60] Elaborated on the help messages a bit. --- src/Manager.ahk | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/Manager.ahk b/src/Manager.ahk index de1d25f..8af7559 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -320,22 +320,22 @@ Manager_logManagedWindowList() { Manager_logHelp() { Log_msg("Help Display") Log_bare("Window list columns") - Log_bare(" ID - Windows ID") - Log_bare(" H - Hidden") - Log_bare(" W - Windows active") - Log_bare(" A - View active") - Log_bare(" F - Floating") - Log_bare(" D - Decorated") - Log_bare(" R - Responsive") - Log_bare(" G - Ghost") - Log_bare(" M - Monitor") - Log_bare(" Tags - Bit-mask of the views in which the window is active") - Log_bare(" X - Windows X position") - Log_bare(" Y - Windows Y position") - Log_bare(" W - Windows width") - Log_bare(" H - Windows height") - Log_bare(" Style - Windows style") - Log_bare(" Proc / Class / Title - Process/Class/Title of the window") + Log_bare(" ID - Windows ID. Unique, OS-assigned ID") + Log_bare(" H - Hidden. Whether bug.n thinks this window is hidden.") + Log_bare(" W - Windows active. This window is active according to Windows.") + Log_bare(" A - View active. This window is active according to bug.n.") + Log_bare(" F - Floating. This window should not be positioned and resized by the layout.") + Log_bare(" D - Decorated. Does the window have a title bar?") + Log_bare(" R - Responsive. Is responding to messages?") + Log_bare(" G - Ghost. Is this window a ghost of another hung window?") + Log_bare(" M - Monitor number.") + Log_bare(" Tags - Bit-mask of the views in which the window is active.") + Log_bare(" X - Windows X position.") + Log_bare(" Y - Windows Y position.") + Log_bare(" W - Windows width.") + Log_bare(" H - Windows height.") + Log_bare(" Style - Windows style.") + Log_bare(" Proc / Class / Title - Process/Class/Title of the window.") } Manager_lockWorkStation() { From 8d5d92952d3ed04225bd43c51cd4c2f8a78f7acc Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 14:27:56 -0400 Subject: [PATCH 57/60] Change _layoutMPri/_layoutMSec to _layoutMX/_layoutMY and update logic accordingly per perliminary review. --- src/Config.ahk | 8 ++-- src/View.ahk | 114 +++++++++++++++++++++++-------------------------- 2 files changed, 58 insertions(+), 64 deletions(-) diff --git a/src/Config.ahk b/src/Config.ahk index dcd46ca..dea5701 100644 --- a/src/Config.ahk +++ b/src/Config.ahk @@ -361,10 +361,10 @@ Config_saveSession() { 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%_layoutMPri = 1) - text .= "View_#" m "_#" A_Index "_layoutMPri=" View_#%m%_#%A_Index%_layoutMPri "`n" - If Not (View_#%m%_#%A_Index%_layoutMSec = 1) - text .= "View_#" m "_#" A_Index "_layoutMSec=" View_#%m%_#%A_Index%_layoutMSec "`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" } } diff --git a/src/View.ahk b/src/View.ahk index ce54aea..954cbc1 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -29,8 +29,8 @@ View_init(m, v) { View_#%m%_#%v%_layoutAxis_#3 := Config_layoutAxis_#3 View_#%m%_#%v%_layoutGapWidth := Config_layoutGapWidth View_#%m%_#%v%_layoutMFact := Config_layoutMFactor - View_#%m%_#%v%_layoutMPri := 1 - View_#%m%_#%v%_layoutMSec := 1 + View_#%m%_#%v%_layoutMX := 1 + View_#%m%_#%v%_layoutMY := 1 View_#%m%_#%v%_layoutSymbol := Config_layoutSymbol_#1 View_#%m%_#%v%_wndIds := "" } @@ -96,7 +96,7 @@ View_addWnd(m, v, wndId) { l := View_#%m%_#%v%_layout_#1 If (Config_layoutFunction_#%l% = "tile") And ((Config_newWndPosition = "masterBottom") Or (Config_newWndPosition = "stackTop")) { n := View_getTiledWndIds(m, v, wndIds) - msplit := View_#%m%_#%v%_layoutMPri * View_#%m%_#%v%_layoutMSec + 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 } @@ -191,7 +191,7 @@ View_arrange_monocle(m, v, wndIds) { } View_rotateLayoutAxis(i, d) { - Local f, l, v + Local f, l, v, n, tmp v := Monitor_#%Manager_aMonitor%_aView_#1 l := View_#%Manager_aMonitor%_#%v%_layout_#1 @@ -203,8 +203,16 @@ View_rotateLayoutAxis(i, d) { f := View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i% / Abs(View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i%) View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i% := f * Manager_loop(Abs(View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i%), d, 1, 2) } - } Else - View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i% := Manager_loop(View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i%, d, 1, 3) + } Else { + n := Manager_loop(View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i%, d, 1, 3) + ; When we rotate the axis, we may need to swap the X and Y dimensions. + If Not (n = View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i%) And (n = 1) Or (View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i% = 1) { + tmp := View_#%Manager_aMonitor%_#%v%_layoutMX + View_#%Manager_aMonitor%_#%v%_layoutMX := View_#%Manager_aMonitor%_#%v%_layoutMY + View_#%Manager_aMonitor%_#%v%_layoutMY := tmp + } + View_#%Manager_aMonitor%_#%v%_layoutAxis_#%i% := n + } View_arrange(Manager_aMonitor, v) } } @@ -258,52 +266,38 @@ View_setMFactor(d) { } } -View_setMPrimary(d) { - Local l, n, v, wndIds - - v := Monitor_#%Manager_aMonitor%_aView_#1 - l := View_#%Manager_aMonitor%_#%v%_layout_#1 - If (Config_layoutFunction_#%l% = "tile") { - n := View_#%Manager_aMonitor%_#%v%_layoutMPri + d - If ( n > 0 And n < 10 ) { - View_#%Manager_aMonitor%_#%v%_layoutMPri := n - View_arrange(Manager_aMonitor, v) - } - } -} - -View_setMSecondary(d) { - Local l, n, v, wndIds - - v := Monitor_#%Manager_aMonitor%_aView_#1 - l := View_#%Manager_aMonitor%_#%v%_layout_#1 - If (Config_layoutFunction_#%l% = "tile") { - n := View_#%Manager_aMonitor%_#%v%_layoutMSec + d - If ( n > 0 And n < 10 ) { - View_#%Manager_aMonitor%_#%v%_layoutMSec := n - View_arrange(Manager_aMonitor, v) - } - } -} - View_setMX(d) { - Local a, v - v := Monitor_#%Manager_aMonitor%_aView_#1 - a := View_#%Manager_aMonitor%_#%v%_layoutAxis_#2 - If ( a = 1 ) - View_setMPrimary(d) - Else - View_setMSecondary(d) + Local l, n, m, v + + m := Manager_aMonitor + v := Monitor_#%m%_aView_#1 + l := View_#%m%_#%v%_layout_#1 + Log_msg("View_setMX(): l: " . l) + If Not (Config_layoutFunction_#%l% = "tile") + Return + + n := View_#%m%_#%v%_layoutMX + d + If (n >= 1) And (n <= 9) { + View_#%m%_#%v%_layoutMX := n + View_arrange(m, v) + } } View_setMY(d) { - Local a, v - v := Monitor_#%Manager_aMonitor%_aView_#1 - a := View_#%Manager_aMonitor%_#%v%_layoutAxis_#2 - If ( a = 1 ) - View_setMSecondary(d) - Else - View_setMPrimary(d) + Local l, n, m, v + + m := Manager_aMonitor + v := Monitor_#%m%_aView_#1 + l := View_#%m%_#%v%_layout_#1 + Log_msg("View_setMY(): l: " . l) + If Not (Config_layoutFunction_#%l% = "tile") + Return + + n := View_#%m%_#%v%_layoutMY + d + If (n >= 1) And (n <= 9) { + View_#%m%_#%v%_layoutMY := n + View_arrange(m, v) + } } View_shuffleWindow(d) { @@ -366,8 +360,8 @@ View_updateLayout_tile(m, v) { ; 2 - horizontal divider ; 3 - monocle axis3 := View_#%m%_#%v%_layoutAxis_#3 - mp := View_#%m%_#%v%_layoutMPri - ms := View_#%m%_#%v%_layoutMSec + mx := View_#%m%_#%v%_layoutMX + my := View_#%m%_#%v%_layoutMY If ( Abs(axis1) = 1 ) master_div := "|" @@ -376,14 +370,14 @@ View_updateLayout_tile(m, v) { If ( axis2 = 1 ) { master_sym := "|" - master_dim := mp . "x" . ms + master_dim := mx . "x" . my } Else If ( axis2 = 2 ) { master_sym := "-" - master_dim := ms . "x" . mp + master_dim := mx . "x" . my } Else - master_sym := "[" . (mp * ms) . "]" + master_sym := "[" . (mx * my) . "]" If ( axis3 = 1 ) stack_sym := "|" @@ -530,9 +524,9 @@ View_arrange_tile(m, v, wndIds) { flipped := View_#%m%_#%v%_layoutAxis_#1 < 0 gapW_2 := View_#%m%_#%v%_layoutGapWidth/2 mfact := View_#%m%_#%v%_layoutMFact - mp := View_#%m%_#%v%_layoutMPri - ms := View_#%m%_#%v%_layoutMSec - msplit := mp * ms + dimAligned := (axis2 = 1) ? View_#%m%_#%v%_layoutMX : View_#%m%_#%v%_layoutMY + dimOrtho := (axis2 = 1) ? View_#%m%_#%v%_layoutMY : View_#%m%_#%v%_layoutMX + msplit := dimAligned * dimOrtho If (msplit > View_arrange_tile_wndId0) { msplit := View_arrange_tile_wndId0 @@ -560,14 +554,14 @@ View_arrange_tile(m, v, wndIds) { } Else { - secondary_areas := Ceil(msplit / mp) + secondary_areas := Ceil(msplit / dimAligned) areas_remaining := secondary_areas windows_remaining := msplit - ;Log_bare("msplit: " . msplit . "; layoutMPri: " . mp . "; secondary_areas: " . secondary_areas . "; areas_remaining: " . areas_remaining . "; windows_remaining: " . windows_remaining) + ;Log_bare("msplit: " . msplit . "; layoutMX/Y: " . dimAligned . "; secondary_areas: " . secondary_areas . "; areas_remaining: " . areas_remaining . "; windows_remaining: " . windows_remaining) Loop, % secondary_areas { View_split_region(Not (axis2 - 1), (1/areas_remaining), x1, y1, w1, h1, mx1, my1, mw1, mh1, x1, y1, w1, h1) - draw_windows := mp - If (windows_remaining < mp) { + draw_windows := dimAligned + If (windows_remaining < dimAligned) { draw_windows := windows_remaining } View_draw_row("View_arrange_tile_wndId", msplit - windows_remaining + 1, draw_windows, 0, axis2 - 1, mx1, my1, mw1, mh1, gapW_2) From e93f12c91ea5e8be54141d92360e341b3b5f5b23 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 15:39:32 -0400 Subject: [PATCH 58/60] Updated documentation with respect to new multi-dimensional master area. --- src/docs/help.t2t | 2 +- src/docs/hotkeys.t2t | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/docs/help.t2t b/src/docs/help.t2t index 0f85922..fd0e24e 100644 --- a/src/docs/help.t2t +++ b/src/docs/help.t2t @@ -71,7 +71,7 @@ There are three layouts. A master area for the main window(s) and a stacking area for the rest, all windows are shown at any time. This layout can be further changed in the following respects: - - the number of windows in the master area (1 ... all) + - the dimensions of the master area (1x1 ... 9x9) - the stacking direction of the master and stacking area (from left to right, from top to bottom or monocle) - the position of the master area (left, top, right or bottom) diff --git a/src/docs/hotkeys.t2t b/src/docs/hotkeys.t2t index 7d7db4b..f96fde6 100644 --- a/src/docs/hotkeys.t2t +++ b/src/docs/hotkeys.t2t @@ -134,13 +134,21 @@ pressing the left Windows key and the shift key and the q key 1 -> 2 = y-axis = vertical stack, 2 -> 3 = z-axis = monocle, only for the "tile" layout). -: #^Left::**View_setMSplit(+1)** - Move the master splitter, i. e. decrease the number of windows in the - master area (only for the "tile" layout). +: #^Left::**View_setMX(-1)** + Decrease the master X dimension by 1, i. e. decrease the number of + windows in the master area by Y. Minimum of 1. -: #^Right::**View_setMSplit(-1)** - Move the master splitter, i. e. increase the number of windows in the - master area (only for the "tile" layout). +: #^Right::**View_setMX(+1) + Increase the master X dimension by 1, i. e. increase the number of + windows in the master area by Y. Maximum of 9. + +: #^Down::**View_setMY(-1)** + Decrease the master Y dimension by 1, i.e. decrease the number of + windows in the master area by X. Minimum of 1. + +: #^Up::**View_setMY(+1)** + Increase the master Y dimension by 1, i.e. increase the number of + windows in the master area by X. Maximum of 9. === Tag / View related hotkeys === @@ -197,6 +205,25 @@ pressing the left Windows key and the shift key and the q key Hide / Show the task bar. +=== Logging/Debugging related hotkeys === + +: #^i::**Manager_logViewWindowList()** + Dump the contents of the current view to the bug.n log. + +: #+^i::**Manager_logManagedWindowList()** + Dump the contents of the managed window list to the bug.n log. + +: #^h::**Manager_logHelp()** + Print to the log a description of the formatting used in the + previous two log messages. + +: #^[::**Log_decDebugLevel()** + Decrement the debug log level. Show fewer debug messages. + +: #^]::**Log_incDebugLevel()** + Increment the debug log level. Show more debug messages. + + === Application related hotkeys === : #y::**Bar_toggleCommandGui()** From e0c16bbe881ddc595f95787745e109e8bfcad5a5 Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sat, 30 Jun 2012 23:55:12 -0400 Subject: [PATCH 59/60] Remove new changelog because there's already a place to log changes --- ChangeLog | 19 ------------------- src/docs/changes.t2t | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 19 deletions(-) delete mode 100644 ChangeLog diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index b70b3f6..0000000 --- a/ChangeLog +++ /dev/null @@ -1,19 +0,0 @@ -8.2.2 --------- - -Features - - NxM master area tiling. - - Split windows between multiple monitors on startup based on their - starting positions (has no effect on configured positions). - - Faster view drawing. - - Logging and debug logging capabilities. - - Layout and content are now distinct. View layouts may be manipulated - in the absence of windows. - -Bugs - - BID 018641: Freezing problem. This problem has been largely mitigated, - but it is still possible. - - Cycling through windows on a view no longer gets stuck. - - Prevent windows from switching to different monitors under odd - circumstances. - - Gap width usage is now consistent between tile and monocle layouts. diff --git a/src/docs/changes.t2t b/src/docs/changes.t2t index 407b153..457ab6e 100644 --- a/src/docs/changes.t2t +++ b/src/docs/changes.t2t @@ -10,6 +10,23 @@ (~) changed (+) added +=8.2.2(?)= + +(+) Multi-dimensional tiling of the master area. The user may now specify + X and Y dimensions independently up to 9 x 9. +(+) Initially assign windows to the monitor on which they appear if + nothing is specified in the configuration. +(~) Improved view arranging runtime. +(+) Created bug.n log to record major and debugging events. +(~) Fixed bug #18641: Freezing problem. In most cases, bug.n will no + longer hang when one of its managed windows hangs. +(~) Fixed bug: Sometimes cycling through the windows in a view would + get stuck on a particular window. +(~) Fixed bug: Activating a window on a non-active view on + a non-active monitor could cause both monitors to change views. +(~) Gap widths are now treated identically on both "tile" and "monocle" + layouts. + =8.2.1= From 29e31ee74da0292a62d1c76e023e234fccf463ba Mon Sep 17 00:00:00 2001 From: Joshua Fuhs <fuhsjr00@gmail.com> Date: Sun, 1 Jul 2012 12:27:47 -0400 Subject: [PATCH 60/60] Remove unnecessary log messages --- src/View.ahk | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/View.ahk b/src/View.ahk index 954cbc1..68b50f6 100644 --- a/src/View.ahk +++ b/src/View.ahk @@ -272,7 +272,6 @@ View_setMX(d) { m := Manager_aMonitor v := Monitor_#%m%_aView_#1 l := View_#%m%_#%v%_layout_#1 - Log_msg("View_setMX(): l: " . l) If Not (Config_layoutFunction_#%l% = "tile") Return @@ -289,7 +288,6 @@ View_setMY(d) { m := Manager_aMonitor v := Monitor_#%m%_aView_#1 l := View_#%m%_#%v%_layout_#1 - Log_msg("View_setMY(): l: " . l) If Not (Config_layoutFunction_#%l% = "tile") Return