2012-09-27 20:32:27 +00:00
/*
bug . n - - tiling window management
Copyright ( c ) 2010 - 2012 Joshua Fuhs , 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
( a t y o u r o p t i o n ) a n y l a t e r v e r s i o n .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : / / www . gnu . org / licenses / > .
@version 8.3 . 0
* /
2011-07-27 17:43:34 +00:00
2012-10-03 19:05:09 +00:00
Manager_init ( )
{
2012-09-29 18:30:48 +00:00
Global
2012-09-27 20:32:27 +00:00
2012-09-29 18:30:48 +00:00
Manager_setWindowBorder ( )
2012-09-27 20:32:27 +00:00
Bar_getHeight ( )
Manager_aMonitor := 1
Manager_taskBarMonitor := " "
Manager_showTaskBar := True
SysGet , Manager_monitorCount , MonitorCount
Loop , % Manager_monitorCount
2012-10-03 19:05:09 +00:00
{
2012-09-27 20:32:27 +00:00
Monitor_init ( A_Index )
2012-10-03 19:05:09 +00:00
}
2012-09-27 20:32:27 +00:00
Bar_initCmdGui ( )
If Not Config_showTaskBar
Monitor_toggleTaskBar ( )
Manager_focus := False
Manager_hideShow := False
Bar_hideTitleWndIds := " "
Manager_allWndIds := " "
Manager_managedWndIds := " "
Manager_initial_sync ( )
Bar_updateStatus ( )
Bar_updateTitle ( )
2012-10-03 19:05:09 +00:00
Loop , % Manager_monitorCount
{
2012-09-27 20:32:27 +00:00
View_arrange ( A_Index , Monitor_# %A_Index% _aView_#1 )
Bar_updateView ( A_Index , Monitor_# %A_Index% _aView_#1 )
}
Manager_registerShellHook ( )
SetTimer , Bar_loop , %Config_readinInterval%
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_activateMonitor ( d )
{
2012-09-27 20:32:27 +00:00
Local aView , aWndClass , aWndHeight , aWndId , aWndWidth , aWndX , aWndY , v , wndId
2012-10-03 19:05:09 +00:00
If ( Manager_monitorCount > 1 )
{
2012-09-27 20:32:27 +00:00
aView := Monitor_# %Manager_aMonitor% _aView_#1
WinGet , aWndId , ID , A
2012-10-03 19:05:09 +00:00
If WinExist ( " ahk_id " aWndId )
{
2012-09-27 20:32:27 +00:00
WinGetClass , aWndClass , ahk_id %aWndId%
2012-10-03 19:05:09 +00:00
If Not ( aWndClass = " Progman " ) And Not ( aWndClass = " AutoHotkeyGui " ) And Not ( aWndClass = " DesktopBackgroundClass " )
{
2012-09-27 20:32:27 +00:00
WinGetPos , aWndX , aWndY , aWndWidth , aWndHeight , ahk_id %aWndId%
If ( Monitor_get ( aWndX + aWndWidth / 2 , aWndY + aWndHeight / 2 ) = Manager_aMonitor )
View_# %Manager_aMonitor% _# %aView% _aWndId := aWndId
}
}
Manager_aMonitor := Manager_loop ( Manager_aMonitor , d , 1 , Manager_monitorCount )
v := Monitor_# %Manager_aMonitor% _aView_#1
wndId := View_# %Manager_aMonitor% _# %v% _aWndId
2012-10-03 19:05:09 +00:00
If Not ( wndId And WinExist ( " ahk_id " wndId ) )
{
2012-09-27 20:32:27 +00:00
If View_# %Manager_aMonitor% _# %v% _wndIds
wndId := SubStr ( View_# %Manager_aMonitor% _# %v% _wndIds , 1 , InStr ( View_# %Manager_aMonitor% _# %v% _wndIds , " ; " ) - 1 )
Else
wndId := 0
}
Manager_winActivate ( wndId )
}
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_applyRules ( wndId , ByRef isManaged , ByRef m , ByRef tags , ByRef isFloating , ByRef isDecorated , ByRef hideTitle )
{
2012-09-27 20:32:27 +00:00
Local mouseX , mouseY , wndClass , wndHeight , wndStyle , wndTitle , wndWidth , wndX , wndY
Local rule0 , rule1 , rule2 , rule3 , rule4 , rule5 , rule6 , rule7 , rule8 , rule9
isManaged := True
m := 0
tags := 0
isFloating := False
isDecorated := False
hideTitle := False
WinGetClass , wndClass , ahk_id %wndId%
WinGetTitle , wndTitle , ahk_id %wndId%
WinGetPos , wndX , wndY , wndWidth , wndHeight , ahk_id %wndId%
WinGet , wndStyle , Style , ahk_id %wndId%
2012-10-03 19:05:09 +00:00
If wndClass And wndTitle And Not ( wndX < - 4999 ) And Not ( wndY < - 4999 )
{
Loop , % Config_ruleCount
{
2012-09-27 20:32:27 +00:00
StringSplit , rule , Config_rule_# %A_index% , `;
2012-10-03 19:05:09 +00:00
If RegExMatch ( wndClass . " ; " . wndTitle , rule1 . " ; " . rule2 ) And ( rule3 = " " Or wndStyle & rule3 )
{ ;; The last matching rule is returned.
2012-09-27 20:32:27 +00:00
isManaged := rule4
m := rule5
tags := rule6
isFloating := rule7
isDecorated := rule8
hideTitle := rule9
}
}
2012-10-03 19:05:09 +00:00
}
Else
{
2012-09-27 20:32:27 +00:00
isManaged := False
If wndTitle
hideTitle := True
}
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_cleanup ( )
{
2012-09-27 20:32:27 +00:00
Local aWndId , m , ncmSize , ncm , wndIds
WinGet , aWndId , ID , A
2012-09-29 18:30:48 +00:00
Manager_resetWindowBorder ( )
2012-09-27 20:32:27 +00:00
2012-10-03 19:05:09 +00:00
;; Show borders and title bars.
2012-09-27 20:32:27 +00:00
StringTrimRight , wndIds , Manager_managedWndIds , 1
Manager_hideShow := True
Loop , PARSE , wndIds , `;
{
Manager_winShow ( A_LoopField )
If Not Config_showBorder
Manager_winSet ( " Style " , " +0x40000 " , A_LoopField )
Manager_winSet ( " Style " , " +0xC00000 " , A_LoopField )
}
2012-10-03 19:05:09 +00:00
;; Show the task bar.
2012-09-27 20:32:27 +00:00
WinShow , Start ahk_class Button
WinShow , ahk_class Shell_TrayWnd
Manager_hideShow := False
2012-10-03 19:05:09 +00:00
;; Reset windows position and size.
2012-09-27 20:32:27 +00:00
Manager_showTaskBar := True
2012-10-03 19:05:09 +00:00
Loop , % Manager_monitorCount
{
2012-09-27 20:32:27 +00:00
m := A_Index
Monitor_# %m% _showBar := False
Monitor_getWorkArea ( m )
2012-10-03 19:05:09 +00:00
Loop , % Config_viewCount
{
2012-09-27 20:32:27 +00:00
View_arrange ( m , A_Index )
2012-10-03 19:05:09 +00:00
}
2012-09-27 20:32:27 +00:00
}
Manager_winSet ( " AlwaysOnTop " , " On " , aWndId )
Manager_winSet ( " AlwaysOnTop " , " Off " , aWndId )
DllCall ( " Shell32.dll\SHAppBarMessage " , " UInt " , ( ABM_REMOVE := 0x1 ) , " UInt " , & Bar_appBarData )
2012-10-03 19:05:09 +00:00
;; SKAN: Crazy Scripting : Quick Launcher for Portable Apps (http://www.autohotkey.com/forum/topic22398.html)
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_closeWindow ( )
{
2012-09-27 20:32:27 +00:00
WinGet , aWndId , ID , A
WinGetClass , aWndClass , ahk_id %aWndId%
WinGetTitle , aWndTitle , ahk_id %aWndId%
If Not ( aWndClass = " AutoHotkeyGUI " And RegExMatch ( aWndTitle , " bug.n_BAR_[0-9]+ " ) )
Manager_winClose ( aWndId )
2011-07-27 17:43:34 +00:00
}
2012-10-03 20:21:57 +00:00
;; Given a ghost window, try to find its body.
;; This is only known to work on Windows 7
Manager_findHung ( ghostWnd )
{
Local expectedH , expectedTitle , expectedW , expectedX , expectedY , wndH , wndIds , wndTitle , wndW , wndX , wndY
WinGetTitle , expectedTitle , ahk_id %ghostWnd%
StringReplace , expectedTitle , expectedTitle , %Config_ghostWndSubString% ,
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
}
2012-10-03 19:05:09 +00:00
Manager_getWindowInfo ( )
{
2012-09-27 20:32:27 +00:00
Local text , v , aWndClass , aWndHeight , aWndId , aWndProcessName , aWndStyle , aWndTitle , aWndWidth , aWndX , aWndY
WinGet , aWndId , ID , A
WinGetClass , aWndClass , ahk_id %aWndId%
WinGetTitle , aWndTitle , ahk_id %aWndId%
WinGet , aWndProcessName , ProcessName , ahk_id %aWndId%
WinGet , aWndStyle , Style , ahk_id %aWndId%
WinGetPos , aWndX , aWndY , aWndWidth , aWndHeight , ahk_id %aWndId%
text := " ID: " aWndId " `n class:`t " aWndClass " `n title:`t " aWndTitle
If InStr ( Bar_hiddenWndIds , aWndId )
text .= " (hidden) "
text .= " `n process:`t " aWndProcessName " `n style:`t " aWndStyle " `n metrics:`tx: " aWndX " , y: " aWndY " , width: " aWndWidth " , height: " aWndHeight " `n tags:`t " Manager_# %aWndId% _tags
If Manager_# %aWndId% _isFloating
text .= " (floating) "
MsgBox , 260 , bug . n : Window Information , % text " `n `n Copy text to clipboard? "
IfMsgBox Yes
Clipboard := text
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_getWindowList ( )
{
2012-09-27 20:32:27 +00:00
Local text , v , aWndId , wndIds , aWndTitle
v := Monitor_# %Manager_aMonitor% _aView_#1
aWndId := View_# %Manager_aMonitor% _# %v% _aWndId
WinGetTitle , aWndTitle , ahk_id %aWndId%
text := " Active Window`n " aWndId " :`t " aWndTitle
StringTrimRight , wndIds , View_# %Manager_aMonitor% _# %v% _wndIds , 1
text .= " `n `n Window List "
Loop , PARSE , wndIds , `;
{
WinGetTitle , wndTitle , ahk_id %A_LoopField%
text .= " `n " A_LoopField " :`t " wndTitle
}
MsgBox , 260 , bug . n : Window List , % text " `n `n Copy text to clipboard? "
IfMsgBox Yes
Clipboard := text
2011-07-27 17:43:34 +00:00
}
2012-10-03 20:21:57 +00:00
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
}
;; 0 - Not hung
;; 1 - Hung
Manager_isHung ( wndId )
{
Local detect_setting , result , 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
}
2012-10-03 19:05:09 +00:00
Manager_lockWorkStation ( )
{
2012-09-27 20:32:27 +00:00
Global Config_shellMsgDelay
RegWrite , REG_DWORD , HKEY_CURRENT_USER , Software \Microsoft \Windows \CurrentVersion \Policies \System , DisableLockWorkstation , 0
Sleep , % Config_shellMsgDelay
DllCall ( " LockWorkStation " )
Sleep , % 4 * Config_shellMsgDelay
RegWrite , REG_DWORD , HKEY_CURRENT_USER , Software \Microsoft \Windows \CurrentVersion \Policies \System , DisableLockWorkstation , 1
2012-06-06 19:14:40 +00:00
}
2012-10-03 19:05:09 +00:00
;; Unambiguous: Re-use WIN+L as a hotkey in bug.n (http://www.autohotkey.com/community/viewtopic.php?p=500903&sid=eb3c7a119259b4015ff045ef80b94a81#p500903)
2012-06-06 19:14:40 +00:00
2012-10-03 19:05:09 +00:00
Manager_loop ( index , increment , lowerBound , upperBound )
{
2012-09-27 20:32:27 +00:00
index + = increment
If ( index > upperBound )
index := lowerBound
If ( index < lowerBound )
index := upperBound
If ( upperBound = 0 )
index := 0
Return , index
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
;; Accept a window to be added to the system for management.
;; Provide a monitor and view preference, but don't override the config.
Manager_manage ( preferredMonitor , preferredView , wndId )
{
2012-09-27 20:32:27 +00:00
Local a , c0 , hideTitle , i , isDecorated , isFloating , isManaged , l , m , n , replace , search , tags , body
2012-10-03 19:05:09 +00:00
Local wndControlList0 , wndId0 , wndIds , wndX , wndY , wndWidth , wndHeight , wndProcessName
2012-09-27 20:32:27 +00:00
If Not InStr ( Manager_allWndIds , wndId " ; " )
Manager_allWndIds .= wndId " ; "
body := 0
2012-10-03 19:05:09 +00:00
If Manager_isGhost ( wndId )
{
2012-09-28 15:46:17 +00:00
Debug_logMessage ( " DEBUG[2] A window has given up the ghost (Ghost wndId: " . wndId . " ) " , 2 )
2012-10-03 19:05:09 +00:00
body := Manager_findHung ( wndId )
If body
{
2012-09-27 20:32:27 +00:00
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 " ; " )
}
2012-10-03 19:05:09 +00:00
Else
{
2012-09-28 15:46:17 +00:00
Debug_logMessage ( " DEBUG[1] No body could be found for ghost wndId: " . wndId , 1 )
2012-09-27 20:32:27 +00:00
}
}
2012-10-03 19:05:09 +00:00
;; Apply rules, if the window is either a normal window or a ghost without a body.
If ( body = 0 )
{
2012-09-27 20:32:27 +00:00
Manager_applyRules ( wndId , isManaged , m , tags , isFloating , isDecorated , hideTitle )
If ( m = 0 )
2012-10-03 19:05:09 +00:00
m := preferredMonitor
2012-09-27 20:32:27 +00:00
If ( m < 0 )
m := 1
2012-10-03 19:05:09 +00:00
If ( m > Manager_monitorCount ) ;; If the specified monitor is out of scope, set it to the max. monitor.
2012-09-27 20:32:27 +00:00
m := Manager_monitorCount
If ( tags = 0 )
2012-10-03 19:05:09 +00:00
tags := 1 << ( preferredView - 1 )
2012-09-27 20:32:27 +00:00
}
WinGet , wndProcessName , ProcessName , ahk_id %wndId%
2012-10-03 19:05:09 +00:00
If ( wndProcessName = " chrome.exe " )
{
2012-09-27 20:32:27 +00:00
WinGet , wndControlList , ControlList , ahk_id %wndId%
StringSplit , c , wndControlList , `n
If ( c0 < = 1 )
isManaged := False
}
2012-10-03 19:05:09 +00:00
If isManaged
{
2012-09-27 20:32:27 +00:00
Monitor_moveWindow ( m , wndId )
Manager_managedWndIds .= wndId " ; "
Manager_# %wndId% _monitor := m
Manager_# %wndId% _tags := tags
Manager_# %wndId% _isDecorated := isDecorated
Manager_# %wndId% _isFloating := isFloating
2012-10-03 19:05:09 +00:00
Loop , % Config_viewCount
{
If ( Manager_# %wndId% _tags & 1 << A_Index - 1 )
{
If ( body )
{ ;; Try to position near the body.
2012-09-27 20:32:27 +00:00
View_ghostWnd ( m , A_Index , body , wndId )
}
2012-10-03 19:05:09 +00:00
Else
2012-09-27 20:32:27 +00:00
View_addWnd ( m , A_Index , wndId )
}
2012-10-03 19:05:09 +00:00
}
2012-09-27 20:32:27 +00:00
If Not Config_showBorder
Manager_winSet ( " Style " , " -0x40000 " , wndId )
If Not Manager_# %wndId% _isDecorated
Manager_winSet ( " Style " , " -0xC00000 " , wndId )
a := Manager_# %wndId% _tags & 1 << Monitor_# %m% _aView_#1 - 1
2012-10-03 19:05:09 +00:00
If a
{
2012-09-27 20:32:27 +00:00
Manager_aMonitor := m
Manager_winActivate ( wndId )
2012-10-03 19:05:09 +00:00
}
Else
{
2012-09-27 20:32:27 +00:00
Manager_hideShow := True
Manager_winHide ( wndId )
Manager_hideShow := False
}
}
If hideTitle And Not InStr ( Bar_hideTitleWndIds , wndId )
Bar_hideTitleWndIds .= wndId . " ; "
Else If Not hideTitle
StringReplace , Bar_hideTitleWndIds , Bar_hideTitleWndIds , %wndId% `; ,
Return , a
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_maximizeWindow ( )
{
2012-09-27 20:32:27 +00:00
Local aWndId , l , v
WinGet , aWndId , ID , A
v := Monitor_# %Manager_aMonitor% _aView_#1
l := View_# %Manager_aMonitor% _# %v% _layout_#1
If Not Manager_# %aWndId% _isFloating And Not ( Config_layoutFunction_# %l% = " " )
View_toggleFloating ( )
Manager_winSet ( " Top " , " " , aWndId )
Manager_winMove ( aWndId , Monitor_# %Manager_aMonitor% _x , Monitor_# %Manager_aMonitor% _y , Monitor_# %Manager_aMonitor% _width , Monitor_# %Manager_aMonitor% _height )
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_moveWindow ( )
{
2012-09-27 20:32:27 +00:00
Local aWndId , l , SC_MOVE , v , WM_SYSCOMMAND
WinGet , aWndId , ID , A
v := Monitor_# %Manager_aMonitor% _aView_#1
l := View_# %Manager_aMonitor% _# %v% _layout_#1
If Not Manager_# %aWndId% _isFloating And Not ( Config_layoutFunction_# %l% = " " )
View_toggleFloating ( )
Manager_winSet ( " Top " , " " , aWndId )
WM_SYSCOMMAND = 0x112
2012-10-03 19:05:09 +00:00
SC_MOVE = 0xF010
2012-09-27 20:32:27 +00:00
SendMessage , WM_SYSCOMMAND , SC_MOVE , , , ahk_id %aWndId%
2011-07-27 17:43:34 +00:00
}
2012-06-23 20:58:29 +00:00
HSHELL_WINDOWCREATED := 1
2012-10-03 19:05:09 +00:00
HSHELL_WINDOWDESTROYED := 2 ;; Seems to get sent sometimes when windows are deactivated.
HSHELL_WINDOWACTIVATED := 4 ;; At least title change.
2012-06-23 20:58:29 +00:00
HSHELL_REDRAW := 6
2012-10-03 19:05:09 +00:00
;; The following two are seen when a hung window recovers.
HSHELL_WINDOWREPLACED := 13 ;; lParam notes the ghost process
;14 ;; lParam notes the recovered process
HSHELL_RUDEAPPACTIVATED := 32772 ;; Full-screen app activated? Root-privileged window activated?
WINDOW_NOTICE := 32774 ;; When a window is signalling an application update.
/*
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 aWndClass , aWndHeight , aWndId , aWndTitle , aWndWidth , aWndX , aWndY , isChanged , m , t , wndClass , wndId , wndIds , wndPName , wndTitle , x , y
2012-09-27 20:32:27 +00:00
SetFormat , Integer , hex
lParam := lParam + 0
SetFormat , Integer , d
2012-09-28 15:46:17 +00:00
Debug_logMessage ( " DEBUG[2] Manager_onShellMessage( wParam: " . wParam . " , lParam: " . lParam . " ) " , 2 )
2012-09-27 20:32:27 +00:00
WinGetClass , wndClass , ahk_id %lParam%
WinGetTitle , wndTitle , ahk_id %lParam%
WinGet , wndPName , ProcessName , ahk_id %lParam%
WinGet , aWndId , ID , A
WinGetClass , aWndClass , ahk_id %aWndId%
WinGetTitle , aWndTitle , ahk_id %aWndId%
2012-10-03 19:05:09 +00:00
If ( ( wParam = 4 Or wParam = 32772 ) And lParam = 0 And aWndClass = " Progman " And aWndTitle = " Program Manager " )
{
2012-09-27 20:32:27 +00:00
MouseGetPos , x , y
m := Monitor_get ( x , y )
If m
Manager_aMonitor := m
Bar_updateTitle ( )
}
2012-10-03 19:05:09 +00:00
If ( wParam = 13 )
{ ;; This shouldn't need a redraw because the window was supposedly replaced.
2012-09-27 20:32:27 +00:00
Manager_unmanage ( lParam )
}
2012-10-03 19:05:09 +00:00
; If (wParam = 14)
; { ;; Window recovered from being hung. Maybe force a redraw.
; }
2012-09-27 20:32:27 +00:00
2012-10-03 19:05:09 +00:00
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
{
2012-09-27 20:32:27 +00:00
If Not ( wParam = 4 Or wParam = 32772 )
2012-10-03 19:05:09 +00:00
If Not wndClass And Not ( wParam = 2 )
{
2012-09-27 20:32:27 +00:00
WinGetClass , wndClass , ahk_id %lParam%
2012-10-03 19:05:09 +00:00
If wndClass
{
2012-09-27 20:32:27 +00:00
If ( wndClass = " Emacs " )
Sleep , % 12 * Config_shellMsgDelay
2012-10-03 19:05:09 +00:00
}
Else
2012-09-27 20:32:27 +00:00
Sleep , %Config_shellMsgDelay%
}
isChanged := Manager_sync ( wndIds )
If wndIds
isChanged := False
2012-10-03 19:05:09 +00:00
If isChanged
{
2012-09-27 20:32:27 +00:00
View_arrange ( Manager_aMonitor , Monitor_# %Manager_aMonitor% _aView_#1 )
Bar_updateView ( Manager_aMonitor , Monitor_# %Manager_aMonitor% _aView_#1 )
}
2012-10-03 19:05:09 +00:00
If ( Manager_monitorCount > 1 )
{
2012-09-27 20:32:27 +00:00
WinGetPos , aWndX , aWndY , aWndWidth , aWndHeight , ahk_id %aWndId%
m := Monitor_get ( aWndX + aWndWidth / 2 , aWndY + aWndHeight / 2 )
If m
Manager_aMonitor := m
}
2012-10-03 19:05:09 +00:00
If wndIds
{ ;; If there are new (unrecognized) windows, which are hidden ...
If ( Config_onActiveHiddenWnds = " view " )
{ ;; ... change the view, to shw the first hidden window
2012-09-27 20:32:27 +00:00
wndId := SubStr ( wndIds , 1 , InStr ( wndIds , " ; " ) - 1 )
Loop , % Config_viewCount
2012-10-03 19:05:09 +00:00
{
If ( Manager_# %wndId% _tags & 1 << A_Index - 1 )
{
2012-09-28 15:46:17 +00:00
Debug_logMessage ( " DEBUG[3] Switching views because " . wndId . " is considered hidden and active " , 3 )
2012-09-27 20:32:27 +00:00
Manager_aMonitor := Manager_# %wndId% _monitor
Monitor_activateView ( A_Index )
Break
}
2012-10-03 19:05:09 +00:00
}
}
Else
{ ;; ... re-hide them
2012-09-27 20:32:27 +00:00
StringTrimRight , wndIds , wndIds , 1
StringSplit , wndId , wndIds , `;
2012-10-03 19:05:09 +00:00
If ( Config_onActiveHiddenWnds = " hide " )
{
Loop , % wndId0
{
2012-09-27 20:32:27 +00:00
Manager_winHide ( wndId %A_Index% )
2012-10-03 19:05:09 +00:00
}
}
Else If ( Config_onActiveHiddenWnds = " tag " )
{
;; ... or tag all of them for the current view.
2012-09-27 20:32:27 +00:00
t := Monitor_# %Manager_aMonitor% _aView_#1
2012-10-03 19:05:09 +00:00
Loop , % wndId0
{
2012-09-27 20:32:27 +00:00
wndId := wndId %A_Index%
View_# %Manager_aMonitor% _# %t% _wndIds := wndId " ; " View_# %Manager_aMonitor% _# %t% _wndIds
View_# %Manager_aMonitor% _# %t% _aWndId := wndId
Manager_# %wndId% _tags + = 1 << t - 1
}
Bar_updateView ( Manager_aMonitor , t )
View_arrange ( Manager_aMonitor , t )
}
}
}
Bar_updateTitle ( )
}
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_registerShellHook ( )
{
2012-09-27 20:32:27 +00:00
Gui , + LastFound
hWnd := WinExist ( )
2012-10-03 19:05:09 +00:00
DllCall ( " RegisterShellHookWindow " , " UInt " , hWnd ) ;; Minimum operating systems: Windows 2000 (http://msdn.microsoft.com/en-us/library/ms644989(VS.85).aspx)
2012-09-27 20:32:27 +00:00
msgNum := DllCall ( " RegisterWindowMessage " , " Str " , " SHELLHOOK " )
OnMessage ( msgNum , " Manager_onShellMessage " )
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
;; SKAN: How to Hook on to Shell to receive its messages? (http://www.autohotkey.com/forum/viewtopic.php?p=123323#123323)
2011-07-27 17:43:34 +00:00
2012-09-29 18:30:48 +00:00
Manager_resetWindowBorder ( )
{
Local ncm , ncmSize
If Config_selBorderColor
DllCall ( " SetSysColors " , " Int " , 1 , " Int* " , 10 , " UInt* " , Manager_normBorderColor )
2012-10-03 19:05:09 +00:00
If ( Config_borderWidth > 0 ) Or ( Config_borderPadding > = 0 And A_OSVersion = WIN_VISTA )
{
2012-09-29 18:30:48 +00:00
ncmSize := VarSetCapacity ( ncm , 4 * ( A_OSVersion = WIN_VISTA ? 11 : 10 ) + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , 0 )
NumPut ( ncmSize , ncm , 0 , " UInt " )
DllCall ( " SystemParametersInfo " , " UInt " , 0x0029 , " UInt " , ncmSize , " UInt " , & ncm , " UInt " , 0 )
If ( Config_borderWidth > 0 )
NumPut ( Manager_borderWidth , ncm , 4 , " Int " )
If ( Config_borderPadding > = 0 And A_OSVersion = WIN_VISTA )
NumPut ( Manager_borderPadding , ncm , 40 + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , " Int " )
DllCall ( " SystemParametersInfo " , " UInt " , 0x002a , " UInt " , ncmSize , " UInt " , & ncm , " UInt " , 0 )
}
}
2012-10-03 19:05:09 +00:00
Manager_setViewMonitor ( d )
{
2012-09-27 20:32:27 +00:00
Local aView , m , v , wndIds
2012-10-03 19:05:09 +00:00
If ( Manager_monitorCount > 1 )
{
2012-09-27 20:32:27 +00:00
m := Manager_loop ( Manager_aMonitor , d , 1 , Manager_monitorCount )
v := Monitor_# %m% _aView_#1
aView := Monitor_# %Manager_aMonitor% _aView_#1
2012-10-03 19:05:09 +00:00
If View_# %Manager_aMonitor% _# %aView% _wndIds
{
2012-09-27 20:32:27 +00:00
View_# %m% _# %v% _wndIds := View_# %Manager_aMonitor% _# %aView% _wndIds View_# %m% _# %v% _wndIds
StringTrimRight , wndIds , View_# %Manager_aMonitor% _# %aView% _wndIds , 1
Loop , PARSE , wndIds , `;
{
2012-10-03 19:05:09 +00:00
Loop , % Config_viewCount
{
2012-09-27 20:32:27 +00:00
StringReplace , View_# %Manager_aMonitor% _# %A_Index% _wndIds , View_# %Manager_aMonitor% _# %A_Index% _wndIds , %A_LoopField% `; ,
View_# %Manager_aMonitor% _# %A_Index% _aWndId := 0
}
Monitor_moveWindow ( m , A_LoopField )
Manager_# %A_LoopField% _tags := 1 << v - 1
}
View_arrange ( Manager_aMonitor , aView )
2012-10-03 19:05:09 +00:00
Loop , % Config_viewCount
{
2012-09-27 20:32:27 +00:00
Bar_updateView ( Manager_aMonitor , A_Index )
2012-10-03 19:05:09 +00:00
}
2012-09-27 20:32:27 +00:00
Manager_aMonitor := m
View_arrange ( m , v )
Bar_updateTitle ( )
Bar_updateView ( m , v )
}
}
2011-07-27 17:43:34 +00:00
}
2012-09-29 18:30:48 +00:00
Manager_setWindowBorder ( )
{
Local ncm , ncmSize
2012-10-03 19:05:09 +00:00
If Config_selBorderColor
{
2012-09-29 18:30:48 +00:00
SetFormat , Integer , hex
Manager_normBorderColor := DllCall ( " GetSysColor " , " Int " , 10 )
SetFormat , Integer , d
DllCall ( " SetSysColors " , " Int " , 1 , " Int* " , 10 , " UInt* " , Config_selBorderColor )
}
2012-10-03 19:05:09 +00:00
If ( Config_borderWidth > 0 ) Or ( Config_borderPadding > = 0 And A_OSVersion = WIN_VISTA )
{
2012-09-29 18:30:48 +00:00
ncmSize := VarSetCapacity ( ncm , 4 * ( A_OSVersion = WIN_VISTA ? 11 : 10 ) + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , 0 )
NumPut ( ncmSize , ncm , 0 , " UInt " )
DllCall ( " SystemParametersInfo " , " UInt " , 0x0029 , " UInt " , ncmSize , " UInt " , & ncm , " UInt " , 0 )
Manager_borderWidth := NumGet ( ncm , 4 , " Int " )
Manager_borderPadding := NumGet ( ncm , 40 + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , " Int " )
If ( Config_borderWidth > 0 )
NumPut ( Config_borderWidth , ncm , 4 , " Int " )
If ( Config_borderPadding > = 0 And A_OSVersion = WIN_VISTA )
NumPut ( Config_borderPadding , ncm , 40 + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , " Int " )
DllCall ( " SystemParametersInfo " , " UInt " , 0x002a , " UInt " , ncmSize , " UInt " , & ncm , " UInt " , 0 )
}
}
2012-10-03 19:05:09 +00:00
Manager_setWindowMonitor ( d )
{
2012-09-27 20:32:27 +00:00
Local aWndId , v
WinGet , aWndId , ID , A
2012-10-03 19:05:09 +00:00
If ( Manager_monitorCount > 1 And InStr ( Manager_managedWndIds , aWndId " ; " ) )
{
Loop , % Config_viewCount
{
2012-09-27 20:32:27 +00:00
StringReplace , View_# %Manager_aMonitor% _# %A_Index% _wndIds , View_# %Manager_aMonitor% _# %A_Index% _wndIds , %aWndId% `; ,
If ( aWndId = View_# %Manager_aMonitor% _# %A_Index% _aWndId )
View_# %Manager_aMonitor% _# %A_Index% _aWndId := 0
Bar_updateView ( Manager_aMonitor , A_Index )
}
View_arrange ( Manager_aMonitor , Monitor_# %Manager_aMonitor% _aView_#1 )
Manager_aMonitor := Manager_loop ( Manager_aMonitor , d , 1 , Manager_monitorCount )
Monitor_moveWindow ( Manager_aMonitor , aWndId )
v := Monitor_# %Manager_aMonitor% _aView_#1
Manager_# %aWndId% _tags := 1 << v - 1
View_# %Manager_aMonitor% _# %v% _wndIds := aWndId " ; " View_# %Manager_aMonitor% _# %v% _wndIds
View_# %Manager_aMonitor% _# %v% _aWndId := aWndId
View_arrange ( Manager_aMonitor , v )
Bar_updateTitle ( )
Bar_updateView ( Manager_aMonitor , v )
}
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_sizeWindow ( )
{
2012-09-27 20:32:27 +00:00
Local aWndId , l , SC_SIZE , v , WM_SYSCOMMAND
WinGet , aWndId , ID , A
v := Monitor_# %Manager_aMonitor% _aView_#1
l := View_# %Manager_aMonitor% _# %v% _layout_#1
If Not Manager_# %aWndId% _isFloating And Not ( Config_layoutFunction_# %l% = " " )
View_toggleFloating ( )
Manager_winSet ( " Top " , " " , aWndId )
WM_SYSCOMMAND = 0x112
2012-10-03 19:05:09 +00:00
SC_SIZE = 0xF000
2012-09-27 20:32:27 +00:00
SendMessage , WM_SYSCOMMAND , SC_SIZE , , , ahk_id %aWndId%
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_sync ( ByRef wndIds = " " )
{
2012-09-27 20:32:27 +00:00
Local a , flag , shownWndIds , v , visibleWndIds , wndId
2012-10-03 19:05:09 +00:00
Loop , % Manager_monitorCount
{
2012-09-27 20:32:27 +00:00
v := Monitor_# %A_Index% _aView_#1
shownWndIds .= View_# %A_Index% _# %v% _wndIds
}
2012-10-03 19:05:09 +00:00
;; Check all visible windows against the known windows
2012-09-27 20:32:27 +00:00
WinGet , wndId , List , , ,
2012-10-03 19:05:09 +00:00
Loop , % wndId
{
If Not InStr ( shownWndIds , wndId %A_Index% " ; " )
{
If Not InStr ( Manager_managedWndIds , wndId %A_Index% " ; " )
{
2012-09-27 20:32:27 +00:00
flag := Manager_manage ( Manager_aMonitor , Monitor_# %Manager_aMonitor% _aView_#1 , wndId %A_Index% )
If flag
a := flag
2012-10-03 19:05:09 +00:00
}
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.
2012-09-27 20:32:27 +00:00
wndIds .= wndId %A_Index% " ; "
}
}
visibleWndIds := visibleWndIds wndId %A_Index% " ; "
}
2012-10-03 19:05:09 +00:00
;; Check, if a window, that is known to be visible, is actually not visible
2012-09-27 20:32:27 +00:00
StringTrimRight , shownWndIds , shownWndIds , 1
Loop , PARSE , shownWndIds , `;
{
2012-10-03 19:05:09 +00:00
If Not InStr ( visibleWndIds , A_LoopField )
{
2012-09-27 20:32:27 +00:00
flag := Manager_unmanage ( A_LoopField )
If flag
a := flag
}
}
Return , a
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
;; No windows are known to the system yet.
;; Try to do something smart with the initial layout.
Manager_initial_sync ( )
{
Local m , wnd , wndH , wndId , wndId0 , wndIds , wndW , wndX , wndY
2012-09-27 20:32:27 +00:00
2012-10-03 19:05:09 +00:00
;; Initialize lists
;; Note that these variables make this function non-reentrant.
Loop , % Manager_monitorCount
{
2012-09-28 12:23:34 +00:00
Manager_initial_sync_m# %A_Index% _wndList := " "
2012-10-03 19:05:09 +00:00
}
2012-09-27 20:32:27 +00:00
2012-10-03 19:05:09 +00:00
;; Check all visible windows against the known windows
2012-09-27 20:32:27 +00:00
WinGet , wndId , List , , ,
2012-10-03 19:05:09 +00:00
Loop , % wndId
{
;; Based on some analysis here, determine which monitors and layouts would best
;; serve existing windows. Do not override configuration settings.
2012-09-27 20:32:27 +00:00
2012-10-03 19:05:09 +00:00
;; Which monitor is it on?
2012-09-27 20:32:27 +00:00
wnd := wndId %A_Index%
WinGetPos , wndX , wndY , wndW , wndH , ahk_id %wnd%
2012-10-03 19:05:09 +00:00
m := Monitor_get ( wndX + wndW / 2 , wndY + wndH / 2 )
2012-09-27 20:32:27 +00:00
If m > 0
2012-09-28 12:23:34 +00:00
Manager_initial_sync_m# %m% _wndList .= wndId %A_Index% " ; "
2012-09-27 20:32:27 +00:00
2012-10-03 19:05:09 +00:00
;; @todo: What percentage of the monitor area is it occupying? (Suggest layout)
;; @todo: What part of the monitor is it on? (Ordering of windows)
2012-09-27 20:32:27 +00:00
}
2012-09-28 12:23:34 +00:00
Loop , % Manager_monitorCount
{
2012-09-27 20:32:27 +00:00
m := A_Index
2012-09-28 12:23:34 +00:00
StringTrimRight , wndIds , Manager_initial_sync_m# %m% _wndList , 1
StringSplit , wndId , wndIds , `;
2012-10-03 19:05:09 +00:00
Loop , % wndId0
{
2012-09-28 12:23:34 +00:00
Manager_manage ( m , 1 , wndId %A_Index% )
2012-10-03 19:05:09 +00:00
}
2012-09-27 20:32:27 +00:00
}
2012-06-24 22:04:41 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_toggleDecor ( )
{
2012-09-27 20:32:27 +00:00
Local aWndId
WinGet , aWndId , ID , A
Manager_# %aWndId% _isDecorated := Not Manager_# %aWndId% _isDecorated
If Manager_# %aWndId% _isDecorated
Manager_winSet ( " Style " , " +0xC00000 " , aWndId )
Else
Manager_winSet ( " Style " , " -0xC00000 " , aWndId )
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_unmanage ( wndId )
{
2012-09-27 20:32:27 +00:00
Local a
a := Manager_# %wndId% _tags & 1 << Monitor_# %Manager_aMonitor% _aView_#1 - 1
2012-10-03 19:05:09 +00:00
Loop , % Config_viewCount
{
If ( Manager_# %wndId% _tags & 1 << A_Index - 1 )
{
2012-10-04 18:05:17 +00:00
StringReplace , View_# %Manager_aMonitor% _# %A_Index% _wndIds , View_# %Manager_aMonitor% _# %A_Index% _wndIds , %wndId% `; ,
2012-09-27 20:32:27 +00:00
Bar_updateView ( Manager_aMonitor , A_Index )
}
2012-10-03 19:05:09 +00:00
}
2012-09-27 20:32:27 +00:00
Manager_# %wndId% _monitor :=
Manager_# %wndId% _tags :=
Manager_# %wndId% _isDecorated :=
Manager_# %wndId% _isFloating :=
StringReplace , Bar_hideTitleWndIds , Bar_hideTitleWndIds , %wndId% `; ,
StringReplace , Manager_allWndIds , Manager_allWndIds , %wndId% `; ,
StringReplace , Manager_managedWndIds , Manager_managedWndIds , %wndId% `; , , All
Return , a
2011-07-27 17:43:34 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_winActivate ( wndId )
{
Local newWnd , wndHeight , wndWidth , wndX , wndY
2012-09-27 20:32:27 +00:00
2012-10-03 19:05:09 +00:00
If Config_mouseFollowsFocus
{
If wndId
{
2012-09-27 20:32:27 +00:00
WinGetPos , wndX , wndY , wndWidth , wndHeight , ahk_id %wndId%
DllCall ( " SetCursorPos " , " Int " , Round ( wndX + wndWidth / 2 ) , " Int " , Round ( wndY + wndHeight / 2 ) )
2012-10-03 19:05:09 +00:00
}
Else
2012-09-27 20:32:27 +00:00
DllCall ( " SetCursorPos " , " Int " , Round ( Monitor_# %Manager_aMonitor% _x + Monitor_# %Manager_aMonitor% _width / 2 ) , " Int " , Round ( Monitor_# %Manager_aMonitor% _y + Monitor_# %Manager_aMonitor% _height / 2 ) )
}
2012-10-03 19:05:09 +00:00
If Manager_isHung ( wndId )
{
2012-09-28 15:46:17 +00:00
Debug_logMessage ( " DEBUG[2] Manager_winActivate: Potentially hung window " . wndId , 2 )
2012-09-27 20:32:27 +00:00
Return 1
}
2012-10-03 19:05:09 +00:00
Else
{
2012-09-27 20:32:27 +00:00
WinActivate , ahk_id %wndId%
WinGet , newWin , ID , A
If ( wndId != newWin )
Return 1
}
Bar_updateTitle ( )
Return 0
2011-07-27 17:43:34 +00:00
}
2012-10-03 20:21:57 +00:00
Manager_winClose ( wndId )
2012-10-03 19:05:09 +00:00
{
If Manager_isHung ( wndId )
{
2012-10-03 20:21:57 +00:00
Debug_logMessage ( " DEBUG[2] Manager_winClose: Potentially hung window " . wndId , 2 )
2012-09-27 20:32:27 +00:00
Return 1
}
2012-10-03 19:05:09 +00:00
Else
{
2012-10-03 20:21:57 +00:00
WinClose , ahk_id %wndId%
Return 0
2012-09-27 20:32:27 +00:00
}
2011-07-27 17:43:34 +00:00
}
2012-06-28 02:00:32 +00:00
2012-10-03 19:05:09 +00:00
Manager_winHide ( wndId )
{
If Manager_isHung ( wndId )
{
2012-09-28 15:46:17 +00:00
Debug_logMessage ( " DEBUG[2] Manager_winHide: Potentially hung window " . wndId , 2 )
2012-09-27 20:32:27 +00:00
Return 1
}
2012-10-03 19:05:09 +00:00
Else
{
2012-09-27 20:32:27 +00:00
WinHide , ahk_id %wndId%
Return 0
}
2012-06-28 02:00:32 +00:00
}
2012-10-03 20:21:57 +00:00
Manager_winMove ( wndId , x , y , width , height )
2012-10-03 19:05:09 +00:00
{
If Manager_isHung ( wndId )
{
2012-10-03 20:21:57 +00:00
Debug_logMessage ( " DEBUG[2] Manager_winMove: Potentially hung window " . wndId , 2 )
2012-09-27 20:32:27 +00:00
Return 1
}
2012-10-03 20:21:57 +00:00
Else
WinRestore , ahk_id %wndId%
WM_ENTERSIZEMOVE = 0x0231
WM_EXITSIZEMOVE = 0x0232
SendMessage , WM_ENTERSIZEMOVE , , , , ahk_id %wndId%
If ErrorLevel
2012-10-03 19:05:09 +00:00
{
2012-10-03 20:21:57 +00:00
Debug_logMessage ( " DEBUG[2] Manager_winMove: Potentially hung window " . wndId , 1 )
2012-09-27 20:32:27 +00:00
Return 1
}
2012-10-03 19:05:09 +00:00
Else
{
2012-10-03 20:21:57 +00:00
WinMove , ahk_id %wndId% , , %x% , %y% , %width% , %height%
SendMessage , WM_EXITSIZEMOVE , , , , ahk_id %wndId%
2012-09-27 20:32:27 +00:00
}
2012-06-28 02:00:32 +00:00
}
2012-10-03 19:05:09 +00:00
Manager_winSet ( type , value , wndId )
{
If Manager_isHung ( wndId )
{
2012-09-28 15:46:17 +00:00
Debug_logMessage ( " DEBUG[2] Manager_winSet: Potentially hung window " . wndId , 2 )
2012-09-27 20:32:27 +00:00
Return 1
}
2012-10-03 19:05:09 +00:00
Else
{
2012-09-27 20:32:27 +00:00
WinSet , %type% , %value% , ahk_id %wndId%
Return 0
}
2012-06-28 03:34:19 +00:00
}
2012-10-03 20:21:57 +00:00
Manager_winShow ( wndId )
2012-10-03 19:05:09 +00:00
{
2012-10-03 20:21:57 +00:00
If Manager_isHung ( wndId )
2012-10-03 19:05:09 +00:00
{
2012-10-03 20:21:57 +00:00
Debug_logMessage ( " DEBUG[2] Manager_winShow: Potentially hung window " . wndId , 2 )
2012-09-27 20:32:27 +00:00
Return 1
2012-10-03 20:21:57 +00:00
}
Else
{
WinShow , ahk_id %wndId%
2012-09-27 20:32:27 +00:00
Return 0
2012-10-03 20:21:57 +00:00
}
2012-09-27 20:32:27 +00:00
}