2012-12-04 02:52:43 +00:00
/*
bug . n - - tiling window management
Copyright ( c ) 2010 - 2012 Joshua Fuhs , joten
2012-11-27 03:13:38 +00:00
2012-12-04 02:52:43 +00:00
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 / > .
2012-11-27 03:13:38 +00:00
2012-12-04 02:52:43 +00:00
@version 8.3 . 0
* /
Manager_init ( )
{
Global
Manager_setWindowBorder ( )
2012-11-27 03:13:38 +00:00
Bar_getHeight ( )
; axes, dimensions, percentage, flipped, gapWidth
Manager_layoutDirty := 0
; New/closed windows, active changed,
Manager_windowsDirty := 0
Manager_aMonitor := 1
Manager_taskBarMonitor := " "
Manager_showTaskBar := True
SysGet , Manager_monitorCount , MonitorCount
Loop , % Manager_monitorCount
2012-12-04 02:52:43 +00:00
{
2012-11-27 03:13:38 +00:00
Monitor_init ( A_Index )
2012-12-04 02:52:43 +00:00
}
2012-11-27 03:13:38 +00:00
Bar_initCmdGui ( )
If Not Config_showTaskBar
Monitor_toggleTaskBar ( )
2012-12-04 02:52:43 +00:00
Manager_focus := False
Manager_hideShow := False
Bar_hideTitleWndIds := " "
Manager_allWndIds := " "
Manager_managedWndIds := " "
2012-11-27 03:13:38 +00:00
Manager_initial_sync ( )
Bar_updateStatus ( )
Bar_updateTitle ( )
2012-12-04 02:52:43 +00:00
Loop , % Manager_monitorCount
{
2012-11-27 03:13:38 +00:00
View_arrange ( A_Index , Monitor_# %A_Index% _aView_#1 )
Bar_updateView ( A_Index , Monitor_# %A_Index% _aView_#1 )
}
Manager_registerShellHook ( )
SetTimer , Manager_maintenance_label , %Config_maintenanceInterval%
SetTimer , Bar_loop , %Config_readinInterval%
2011-07-27 17:43:34 +00:00
}
2012-11-25 13:56:35 +00:00
; Asynchronous management of various WM properties.
; We want to make sure that we can recover the layout and windows in the event of
; unexpected problems.
; Periodically check for changes to these things and save them somewhere (not over
; user-defined files).
Manager_maintenance_label:
2012-11-27 03:13:38 +00:00
Manager_maintenance ( )
2012-11-25 13:56:35 +00:00
Return
Manager_maintenance ( ) {
2012-11-27 03:13:38 +00:00
Local tmp
;Debug_logMessage("Manager_maintenance", 2)
; @todo: Check for changes to the layout.
;If Manager_layoutDirty {
;Debug_logMessage("Saving layout state: " . Main_autoLayout, 0)
Config_saveSession ( Config_filaPath , Main_autoLayout )
Manager_layoutDirty := 0
;}
2012-11-25 13:56:35 +00:00
2012-12-04 02:52:43 +00:00
; @todo: Manager_sync?
2012-11-25 13:56:35 +00:00
2012-11-27 03:13:38 +00:00
; @todo: Check for changes to windows.
;If Manager_windowsDirty {
;Debug_logMessage("Saving window state: " . Main_autoWindowState, 0)
Manager_saveWindowState ( Main_autoWindowState , Manager_monitorCount , Config_viewCount )
Manager_windowsDirty := 0
;}
2012-11-25 13:56:35 +00:00
}
2012-11-27 03:13:38 +00:00
Manager_activateMonitor ( d )
2012-12-04 02:52:43 +00:00
{
Local aView , aWndHeight , aWndId , aWndWidth , aWndX , aWndY , v , wndId
2012-11-27 03:13:38 +00:00
If ( Manager_monitorCount > 1 )
{
aView := Monitor_# %Manager_aMonitor% _aView_#1
2012-12-04 02:52:43 +00:00
aWndId := View_getActiveWindow ( Manager_aMonitor , aView )
If aWndId
2012-11-27 03:13:38 +00:00
{
2012-12-04 02:52:43 +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
2012-11-27 03:13:38 +00:00
}
Manager_aMonitor := Manager_loop ( Manager_aMonitor , d , 1 , Manager_monitorCount )
v := Monitor_# %Manager_aMonitor% _aView_#1
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 )
Else
wndId := 0
}
2012-12-04 02:52:43 +00:00
Debug_logMessage ( " DEBUG[1] Manager_activateMonitor: Manager_aMonitor: " Manager_aMonitor " , d: " d " , wndId: " wndId , 1 )
2012-11-27 03:13:38 +00:00
Manager_winActivate ( wndId )
}
2012-06-26 16:52:44 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_applyRules ( wndId , ByRef isManaged , ByRef m , ByRef tags , ByRef isFloating , ByRef isDecorated , ByRef hideTitle , ByRef action )
2012-11-27 03:13:38 +00:00
{
Local mouseX , mouseY , wndClass , wndHeight , wndStyle , wndTitle , wndWidth , wndX , wndY
2012-12-04 02:52:43 +00:00
Local rule0 , rule1 , rule2 , rule3 , rule4 , rule5 , rule6 , rule7 , rule8 , rule9 , rule10
2012-11-27 03:13:38 +00:00
isManaged := True
m := 0
tags := 0
isFloating := False
isDecorated := False
hideTitle := False
2012-12-04 02:52:43 +00:00
action := " "
2012-11-27 03:13:38 +00:00
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-12-04 02:52:43 +00:00
If wndClass And wndTitle And Not ( wndX < - 4999 ) And Not ( wndY < - 4999 )
{
Loop , % Config_ruleCount
{
2012-11-27 03:13:38 +00:00
StringSplit , rule , Config_rule_# %A_index% , `;
2012-12-04 02:52:43 +00:00
If RegExMatch ( wndClass . " ; " . wndTitle , rule1 . " ; " . rule2 ) And ( rule3 = " " Or wndStyle & rule3 )
{ ;; The last matching rule is returned.
2012-11-27 03:13:38 +00:00
isManaged := rule4
m := rule5
tags := rule6
isFloating := rule7
isDecorated := rule8
hideTitle := rule9
2012-12-04 02:52:43 +00:00
action := rule10
2012-11-27 03:13:38 +00:00
}
}
}
Else
{
isManaged := False
If wndTitle
hideTitle := True
}
2012-06-28 03:34:19 +00:00
}
2012-11-27 03:13:38 +00:00
Manager_cleanup ( )
{
Local aWndId , m , ncmSize , ncm , wndIds
WinGet , aWndId , ID , A
2012-12-04 02:52:43 +00:00
Manager_resetWindowBorder ( )
2012-11-27 03:13:38 +00:00
2012-12-04 02:52:43 +00:00
;; Show borders and title bars.
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
;; Show the task bar.
2012-11-27 03:13:38 +00:00
WinShow , Start ahk_class Button
WinShow , ahk_class Shell_TrayWnd
Manager_hideShow := False
2012-12-04 02:52:43 +00:00
;; Reset windows position and size.
2012-11-27 03:13:38 +00:00
Manager_showTaskBar := True
Loop , % Manager_monitorCount
{
m := A_Index
Monitor_# %m% _showBar := False
Monitor_getWorkArea ( m )
2012-12-04 02:52:43 +00:00
Loop , % Config_viewCount
{
2012-11-27 03:13:38 +00:00
View_arrange ( m , A_Index )
2012-12-04 02:52:43 +00:00
}
2012-11-27 03:13:38 +00:00
}
Manager_winSet ( " AlwaysOnTop " , " On " , aWndId )
Manager_winSet ( " AlwaysOnTop " , " Off " , aWndId )
DllCall ( " Shell32.dll\SHAppBarMessage " , " UInt " , ( ABM_REMOVE := 0x1 ) , " UInt " , & Bar_appBarData )
2012-12-04 02:52:43 +00:00
;; SKAN: Crazy Scripting : Quick Launcher for Portable Apps (http://www.autohotkey.com/forum/topic22398.html)
2012-06-22 23:56:13 +00:00
}
2012-11-27 03:13:38 +00:00
Manager_closeWindow ( )
{
2012-12-05 00:36:38 +00:00
Local aWndId , aview , c0
2012-11-27 03:13:38 +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]+ " ) )
2012-12-05 00:36:38 +00:00
{
;; Prior to closing, find the next window that should have focus.
;; If there is no such window, choose the bar on the same monitor.
aview := Monitor_# %Manager_aMonitor% _aView_#1
wnds := View_# %Manager_aMonitor% _# %aview% _wndIds
StringSplit , c , wnds , `;
If ( c0 < 3 )
{
Manager_winActivate ( 0 )
}
Else
{
View_activateWindow ( 1 )
}
2012-11-27 03:13:38 +00:00
Manager_winClose ( aWndId )
2012-12-05 00:36:38 +00:00
}
2012-06-22 23:56:13 +00:00
}
2012-12-04 02:52:43 +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-11-27 03:13:38 +00:00
Manager_getWindowInfo ( )
{
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
2012-06-28 03:34:19 +00:00
}
2012-11-27 03:13:38 +00:00
Manager_getWindowList ( )
{
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
2012-06-26 16:52:44 +00:00
}
2012-12-04 02:52:43 +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-11-27 03:13:38 +00:00
Manager_lockWorkStation ( )
{
Global Config_shellMsgDelay
RegWrite , REG_DWORD , HKEY_CURRENT_USER , Software \Microsoft \Windows \CurrentVersion \Policies \System , DisableLockWorkstation , 0
Sleep , % Config_shellMsgDelay
DllCall ( " LockWorkStation " )
Sleep , % 4 * Config_shellMsgDelay
RegWrite , REG_DWORD , HKEY_CURRENT_USER , Software \Microsoft \Windows \CurrentVersion \Policies \System , DisableLockWorkstation , 1
2012-06-06 19:14:40 +00:00
}
2012-12-04 02:52:43 +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-11-27 03:13:38 +00:00
Manager_loop ( index , increment , lowerBound , upperBound )
{
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-11-27 03:13:38 +00:00
Manager__setWinProperties ( wndId , isManaged , m , tags , isDecorated , isFloating , hideTitle )
{
Local a
2012-11-25 13:56:35 +00:00
2012-11-27 03:13:38 +00:00
If Not Instr ( Manager_allWndIds , wndId " ; " )
Manager_allWndIds .= wndId " ; "
2012-11-25 13:56:35 +00:00
2012-12-04 03:40:52 +00:00
If ( isManaged )
{
2012-11-27 03:13:38 +00:00
Manager_managedWndIds .= wndId " ; "
Monitor_moveWindow ( m , wndId )
Manager_# %wndId% _tags := tags
Manager_# %wndId% _isDecorated := isDecorated
Manager_# %wndId% _isFloating := isFloating
If Not Config_showBorder
Manager_winSet ( " Style " , " -0x40000 " , wndId )
If Not Manager_# %wndId% _isDecorated
Manager_winSet ( " Style " , " -0xC00000 " , wndId )
2012-11-25 13:56:35 +00:00
2012-11-27 03:13:38 +00:00
a := Manager_# %wndId% _tags & ( 1 << ( Monitor_# %m% _aView_#1 - 1 ) )
2012-12-04 03:40:52 +00:00
If a
{
2012-11-27 03:13:38 +00:00
Manager_aMonitor := m
Manager_winActivate ( wndId )
2012-12-04 03:40:52 +00:00
}
Else
{
2012-11-27 03:13:38 +00:00
Manager_hideShow := True
Manager_winHide ( wndId )
Manager_hideShow := False
}
}
If hideTitle
Bar_hideTitleWndIds .= wndId . " ; "
Return , a
2012-11-25 13:56:35 +00:00
}
2012-12-04 02:52:43 +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 )
{
Local a , action , c0 , hideTitle , i , isDecorated , isFloating , isManaged , l , m , n , replace , search , tags , body
Local wndControlList0 , wndId0 , wndIds , wndX , wndY , wndWidth , wndHeight , wndProcessName
2012-11-27 03:13:38 +00:00
; Manage any window only once.
If InStr ( Manager_managedWndIds , wndId " ; " )
Return
body := 0
2012-12-04 02:52:43 +00:00
If Manager_isGhost ( wndId )
{
Debug_logMessage ( " DEBUG[2] A window has given up the ghost (Ghost wndId: " . wndId . " ) " , 2 )
body := Manager_findHung ( wndId )
If body
{
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
action := " "
2012-11-27 03:13:38 +00:00
}
2012-12-04 02:52:43 +00:00
Else
{
Debug_logMessage ( " DEBUG[1] No body could be found for ghost wndId: " . wndId , 1 )
2012-11-27 03:13:38 +00:00
}
}
2012-12-04 02:52:43 +00:00
;; Apply rules if the window is either a normal window or a ghost without a body.
If ( body = 0 )
{
Manager_applyRules ( wndId , isManaged , m , tags , isFloating , isDecorated , hideTitle , action )
2012-11-27 03:13:38 +00:00
If ( m = 0 )
2012-12-04 02:52:43 +00:00
m := preferredMonitor
2012-11-27 03:13:38 +00:00
If ( m < 0 )
m := 1
2012-12-04 02:52:43 +00:00
If ( m > Manager_monitorCount ) ;; If the specified monitor is out of scope, set it to the max. monitor.
2012-11-27 03:13:38 +00:00
m := Manager_monitorCount
If ( tags = 0 )
2012-12-04 02:52:43 +00:00
tags := 1 << ( preferredView - 1 )
2012-11-27 03:13:38 +00:00
}
; @todo: Remove this application-specific code.
WinGet , wndProcessName , ProcessName , ahk_id %wndId%
2012-12-04 02:52:43 +00:00
If ( wndProcessName = " chrome.exe " )
{
2012-11-27 03:13:38 +00:00
WinGet , wndControlList , ControlList , ahk_id %wndId%
StringSplit , c , wndControlList , `n
If ( c0 < = 1 )
isManaged := False
}
a := Manager__setWinProperties ( wndId , isManaged , m , tags , isDecorated , isFloating , hideTitle )
; Do view placement.
If isManaged {
Loop , % Config_viewCount
If ( Manager_# %wndId% _tags & ( 1 << ( A_Index - 1 ) ) ) {
If ( body ) {
; Try to position near the body.
2012-12-04 02:52:43 +00:00
View_ghostWindow ( m , A_Index , body , wndId )
2012-11-27 03:13:38 +00:00
}
2012-12-04 02:52:43 +00:00
Else
View_addWindow ( m , A_Index , wndId )
2012-11-27 03:13:38 +00:00
}
}
Return , a
2011-07-27 17:43:34 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_maximizeWindow ( )
{
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
Manager_moveWindow ( )
{
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
SC_MOVE = 0xF010
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
;; Seems to get sent sometimes when windows are deactivated.
2012-06-23 20:58:29 +00:00
HSHELL_WINDOWDESTROYED := 2
HSHELL_WINDOWACTIVATED := 4
2012-12-04 02:52:43 +00:00
;; At least title change.
2012-06-23 20:58:29 +00:00
HSHELL_REDRAW := 6
2012-12-04 02:52:43 +00:00
;; The following two are seen when a hung window recovers.
;; lParam notes the ghost process
2012-06-30 02:20:15 +00:00
HSHELL_WINDOWREPLACED := 13
2012-12-04 02:52:43 +00:00
;; lParam notes the recovered process
;;14
;; Full-screen app activated? Root-privileged window activated?
2012-06-23 20:58:29 +00:00
HSHELL_RUDEAPPACTIVATED := 32772
2012-12-04 02:52:43 +00:00
;; When a window is signalling an application update.
2012-06-26 16:52:44 +00:00
WINDOW_NOTICE := 32774
2012-06-23 20:58:29 +00:00
2012-12-04 02:52:43 +00:00
/*
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
Windows events can 't always be caught .
* /
2011-07-27 17:43:34 +00:00
Manager_onShellMessage ( wParam , lParam ) {
2012-11-27 03:13:38 +00:00
Local a , isChanged , aWndClass , aWndHeight , aWndId , aWndTitle , aWndWidth , aWndX , aWndY , m , t , wndClass , wndId , wndIds , wndPName , wndTitle , x , y
SetFormat , Integer , hex
lParam := lParam + 0
SetFormat , Integer , d
2012-12-04 02:52:43 +00:00
Debug_logMessage ( " DEBUG[2] Manager_onShellMessage( wParam: " . wParam . " , lParam: " . lParam . " ) " , 2 )
2012-11-27 03:13:38 +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-12-04 12:22:59 +00:00
If ( ( wParam = 4 Or wParam = 32772 ) And lParam = 0 And aWndClass = " Progman " And aWndTitle = " Program Manager " )
{
2012-11-27 03:13:38 +00:00
MouseGetPos , x , y
m := Monitor_get ( x , y )
If m
Manager_aMonitor := m
Bar_updateTitle ( )
}
2012-12-04 02:52:43 +00:00
If ( wParam = HSHELL_WINDOWREPLACED )
{ ;; This shouldn't need a redraw because the window was supposedly replaced.
2012-11-27 03:13:38 +00:00
Manager_unmanage ( lParam )
}
2012-12-04 02:52:43 +00:00
; If (wParam = 14)
; { ;; Window recovered from being hung. Maybe force a redraw.
; }
;; @todo: There are two problems with the use of Manager_hideShow:
;; 1) If Manager_hideShow is set when we hit this block, we won't take some actions that should eventually be taken.
;; This _may_ explain why some windows never get picked up when spamming Win+e
;; 2) There is a race condition between the time that Manager_hideShow is checked and any other action which we are
;; trying to protect against. If another process (hotkey) enters a hideShow block after Manager_hideShow has
;; been checked here, bad things could happen. I've personally observed that windows may be permanently hidden.
;; Look into the use of AHK synchronization primitives.
If ( wParam = 1 Or wParam = 2 Or wParam = 4 Or wParam = 6 Or wParam = 32772 ) And lParam And Not Manager_hideShow And Not Manager_focus
{
If Not wndClass And Not ( wParam = 2 Or wParam = 4 Or wParam = 32772 )
{
Sleep , %Config_shellMsgDelay%
WinGetClass , wndClass , ahk_id %lParam%
}
2012-11-27 03:13:38 +00:00
isChanged := Manager_sync ( wndIds )
If wndIds
isChanged := False
2012-12-04 02:52:43 +00:00
If isChanged
{
2012-11-27 03:13:38 +00:00
View_arrange ( Manager_aMonitor , Monitor_# %Manager_aMonitor% _aView_#1 )
Bar_updateView ( Manager_aMonitor , Monitor_# %Manager_aMonitor% _aView_#1 )
}
2012-12-04 02:52:43 +00:00
If ( Manager_monitorCount > 1 )
{
WinGet , aWndId , ID , A
2012-11-27 03:13:38 +00:00
WinGetPos , aWndX , aWndY , aWndWidth , aWndHeight , ahk_id %aWndId%
m := Monitor_get ( aWndX + aWndWidth / 2 , aWndY + aWndHeight / 2 )
2012-12-04 02:52:43 +00:00
Debug_logMessage ( " DEBUG[1] Manager_onShellMessage: Manager_monitorCount: " Manager_monitorCount " , Manager_aMonitor: " Manager_aMonitor " , m: " m " , aWndId: " aWndId , 1 )
2012-12-05 00:36:38 +00:00
If m
Manager_aMonitor := m
2012-11-27 03:13:38 +00:00
}
2012-12-04 02:52:43 +00:00
If wndIds
{ ;; If there are new (unrecognized) windows, which are hidden ...
If ( Config_onActiveHiddenWnds = " view " )
{ ;; ... change the view to show the first hidden window
2012-11-27 03:13:38 +00:00
wndId := SubStr ( wndIds , 1 , InStr ( wndIds , " ; " ) - 1 )
Loop , % Config_viewCount
2012-12-04 02:52:43 +00:00
{
If ( Manager_# %wndId% _tags & 1 << A_Index - 1 )
{
Debug_logMessage ( " DEBUG[3] Switching views because " . wndId . " is considered hidden and active " , 3 )
2012-11-27 03:13:38 +00:00
Manager_aMonitor := Manager_# %wndId% _monitor
Monitor_activateView ( A_Index )
Break
}
2012-12-04 02:52:43 +00:00
}
}
Else
{ ;; ... re-hide them
2012-11-27 03:13:38 +00:00
StringTrimRight , wndIds , wndIds , 1
StringSplit , wndId , wndIds , `;
2012-12-04 02:52:43 +00:00
If ( Config_onActiveHiddenWnds = " hide " )
{
Loop , % wndId0
{
2012-11-27 03:13:38 +00:00
Manager_winHide ( wndId %A_Index% )
2012-12-04 02:52:43 +00:00
}
}
Else If ( Config_onActiveHiddenWnds = " tag " )
{
;; ... or tag all of them for the current view.
2012-11-27 03:13:38 +00:00
t := Monitor_# %Manager_aMonitor% _aView_#1
2012-12-04 02:52:43 +00:00
Loop , % wndId0
{
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
Manager_registerShellHook ( )
{
2012-11-27 03:13:38 +00:00
Gui , + LastFound
hWnd := WinExist ( )
2012-12-04 02:52:43 +00:00
DllCall ( " RegisterShellHookWindow " , " UInt " , hWnd ) ;; Minimum operating systems: Windows 2000 (http://msdn.microsoft.com/en-us/library/ms644989(VS.85).aspx)
2012-11-27 03:13:38 +00:00
msgNum := DllCall ( " RegisterWindowMessage " , " Str " , " SHELLHOOK " )
OnMessage ( msgNum , " Manager_onShellMessage " )
2011-07-27 17:43:34 +00:00
}
2012-12-04 02:52:43 +00:00
;; SKAN: How to Hook on to Shell to receive its messages? (http://www.autohotkey.com/forum/viewtopic.php?p=123323#123323)
Manager_resetWindowBorder ( )
{
Local ncm , ncmSize
If Config_selBorderColor
DllCall ( " SetSysColors " , " Int " , 1 , " Int* " , 10 , " UInt* " , Manager_normBorderColor )
If ( Config_borderWidth > 0 ) Or ( Config_borderPadding > = 0 And A_OSVersion = WIN_VISTA )
{
ncmSize := VarSetCapacity ( ncm , 4 * ( A_OSVersion = WIN_VISTA ? 11 : 10 ) + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , 0 )
NumPut ( ncmSize , ncm , 0 , " UInt " )
DllCall ( " SystemParametersInfo " , " UInt " , 0x0029 , " UInt " , ncmSize , " UInt " , & ncm , " UInt " , 0 )
If ( Config_borderWidth > 0 )
NumPut ( Manager_borderWidth , ncm , 4 , " Int " )
If ( Config_borderPadding > = 0 And A_OSVersion = WIN_VISTA )
NumPut ( Manager_borderPadding , ncm , 40 + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , " Int " )
DllCall ( " SystemParametersInfo " , " UInt " , 0x002a , " UInt " , ncmSize , " UInt " , & ncm , " UInt " , 0 )
}
}
2011-07-27 17:43:34 +00:00
2012-12-04 02:52:43 +00:00
Manager_setViewMonitor ( d )
{
Local aView , aWndId , m , v , wndIds
2012-11-27 03:13:38 +00:00
2012-12-04 02:52:43 +00:00
If ( Manager_monitorCount > 1 )
{
2012-11-27 03:13:38 +00:00
m := Manager_loop ( Manager_aMonitor , d , 1 , Manager_monitorCount )
v := Monitor_# %m% _aView_#1
aView := Monitor_# %Manager_aMonitor% _aView_#1
2012-12-04 02:52:43 +00:00
If View_# %Manager_aMonitor% _# %aView% _wndIds
{
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
Loop , % Config_viewCount
{
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
Loop , % Config_viewCount
{
2012-11-27 03:13:38 +00:00
Bar_updateView ( Manager_aMonitor , A_Index )
2012-12-04 02:52:43 +00:00
}
2012-11-27 03:13:38 +00:00
Manager_aMonitor := m
View_arrange ( m , v )
2012-12-04 02:52:43 +00:00
WinGet , aWndId , ID , A
Manager_winActivate ( aWndId )
2012-11-27 03:13:38 +00:00
Bar_updateView ( m , v )
}
}
2011-07-27 17:43:34 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_setWindowBorder ( )
{
Local ncm , ncmSize
If Config_selBorderColor
{
SetFormat , Integer , hex
Manager_normBorderColor := DllCall ( " GetSysColor " , " Int " , 10 )
SetFormat , Integer , d
DllCall ( " SetSysColors " , " Int " , 1 , " Int* " , 10 , " UInt* " , Config_selBorderColor )
}
If ( Config_borderWidth > 0 ) Or ( Config_borderPadding > = 0 And A_OSVersion = WIN_VISTA )
{
ncmSize := VarSetCapacity ( ncm , 4 * ( A_OSVersion = WIN_VISTA ? 11 : 10 ) + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , 0 )
NumPut ( ncmSize , ncm , 0 , " UInt " )
DllCall ( " SystemParametersInfo " , " UInt " , 0x0029 , " UInt " , ncmSize , " UInt " , & ncm , " UInt " , 0 )
Manager_borderWidth := NumGet ( ncm , 4 , " Int " )
Manager_borderPadding := NumGet ( ncm , 40 + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , " Int " )
If ( Config_borderWidth > 0 )
NumPut ( Config_borderWidth , ncm , 4 , " Int " )
If ( Config_borderPadding > = 0 And A_OSVersion = WIN_VISTA )
NumPut ( Config_borderPadding , ncm , 40 + 5 * ( 28 + 32 * ( A_IsUnicode ? 2 : 1 ) ) , " Int " )
DllCall ( " SystemParametersInfo " , " UInt " , 0x002a , " UInt " , ncmSize , " UInt " , & ncm , " UInt " , 0 )
}
}
Manager_setWindowMonitor ( d )
{
2012-11-27 03:13:38 +00:00
Local aWndId , v
WinGet , aWndId , ID , A
2012-12-04 02:52:43 +00:00
If ( Manager_monitorCount > 1 And InStr ( Manager_managedWndIds , aWndId " ; " ) )
{
Loop , % Config_viewCount
{
2012-11-27 03:13:38 +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 )
2012-12-04 02:52:43 +00:00
Manager_winActivate ( aWndId )
2012-11-27 03:13:38 +00:00
Bar_updateView ( Manager_aMonitor , v )
}
2011-07-27 17:43:34 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_sizeWindow ( )
{
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
SC_SIZE = 0xF000
2012-11-27 03:13:38 +00:00
SendMessage , WM_SYSCOMMAND , SC_SIZE , , , ahk_id %aWndId%
2011-07-27 17:43:34 +00:00
}
2012-12-04 02:52:43 +00:00
;; @todo: This constantly tries to re-add windows that are never going to be manageable.
;; Manager_manage should probably ignore all windows that are already in Manager_allWndIds.
Manager_sync ( ByRef wndIds = " " )
{
2012-11-27 03:13:38 +00:00
Local a , flag , shownWndIds , v , visibleWndIds , wndId
2012-12-04 02:52:43 +00:00
Loop , % Manager_monitorCount
{
2012-11-27 03:13:38 +00:00
v := Monitor_# %A_Index% _aView_#1
shownWndIds .= View_# %A_Index% _# %v% _wndIds
}
2012-12-04 02:52:43 +00:00
;; Check all visible windows against the known windows
2012-11-27 03:13:38 +00:00
WinGet , wndId , List , , ,
2012-12-04 02:52:43 +00:00
Loop , % wndId
{
If Not InStr ( shownWndIds , wndId %A_Index% " ; " )
{
If Not InStr ( Manager_managedWndIds , wndId %A_Index% " ; " )
{
2012-11-27 03:13:38 +00:00
flag := Manager_manage ( Manager_aMonitor , Monitor_# %Manager_aMonitor% _aView_#1 , wndId %A_Index% )
If flag
a := flag
2012-12-04 02:52:43 +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-11-27 03:13:38 +00:00
wndIds .= wndId %A_Index% " ; "
}
}
visibleWndIds := visibleWndIds wndId %A_Index% " ; "
}
2012-12-04 02:52:43 +00:00
;; @todo-future: Find out why this unmanage code exists and if it's still needed.
;; check, if a window, that is known to be visible, is actually not visible
2012-11-27 03:13:38 +00:00
StringTrimRight , shownWndIds , shownWndIds , 1
Loop , PARSE , shownWndIds , `;
{
2012-12-04 02:52:43 +00:00
If Not InStr ( visibleWndIds , A_LoopField )
{
2012-11-27 03:13:38 +00:00
flag := Manager_unmanage ( A_LoopField )
If flag
a := flag
}
}
Return , a
2011-07-27 17:43:34 +00:00
}
2012-11-25 13:56:35 +00:00
2012-12-04 02:52:43 +00:00
Manager_saveWindowState ( filename , nm , nv )
{
2012-11-27 03:13:38 +00:00
Local allWndId , allWndIds , process , title , text , monitor , wndId , view , isManaged , isTitleHidden
text := " ; bug.n - tiling window management`n; @version " VERSION " `n `n "
tmpfname := filename . " .tmp "
FileDelete , %tmpfname%
; Dump window ID and process name. If these two don't match an existing process, we won't try
; to recover that window.
StringTrimRight , allWndIds , Manager_allWndIds , 1
StringSplit , allWndId , allWndIds , `;
DetectHiddenWindows , On
2012-12-04 02:52:43 +00:00
Loop , % allWndId0
{
2012-11-27 03:13:38 +00:00
wndId := allWndId %A_Index%
WinGet , process , ProcessName , ahk_id %wndId%
; Include title for informative reasons.
WinGetTitle , title , ahk_id %wndId%
; wndId;process;Tags;Floating;Decorated;HideTitle;Managed;Title
2012-12-04 02:52:43 +00:00
If ( InStr ( Manager_managedWndIds , wndId . " ; " ) > 0 )
{
2012-11-27 03:13:38 +00:00
isManaged := 1
}
2012-12-04 02:52:43 +00:00
else
{
2012-11-27 03:13:38 +00:00
isManaged := 0
}
If ( InStr ( Bar_hideTitleWndIds , wndId . " ; " ) > 0 )
isTitleHidden := 1
Else
isTitleHidden := 0
text .= " Window " . wndId . " ; " . process . " ; " . Manager_# %wndId% _monitor . " ; " . Manager_# %wndId% _tags . " ; " . Manager_# %wndId% _isFloating . " ; " . Manager_# %wndId% _isDecorated . " ; " . isTitleHidden . " ; " . isManaged . " ; " . title . " `n "
}
DetectHiddenWindows , Off
2012-11-25 13:56:35 +00:00
2012-11-27 03:13:38 +00:00
text .= " `n "
; @todo: Dump window arrangements on every view. If some views or monitors have disappeared, leave their
; corresponding windows alone.
2012-12-04 02:52:43 +00:00
Loop , % nm
{
2012-11-27 03:13:38 +00:00
monitor := A_Index
2012-12-04 02:52:43 +00:00
Loop , % nv
{
2012-11-27 03:13:38 +00:00
view := A_Index
; @todo: Dump all view window lists
text .= " View_# " . monitor . " _# " . view . " _wndIds= " . View_# %monitor% _# %view% _wndIds . " `n "
}
}
2012-11-25 13:56:35 +00:00
2012-11-27 03:13:38 +00:00
FileAppend , %text% , %tmpfname%
2012-12-04 02:52:43 +00:00
If ErrorLevel
{
2012-11-27 03:13:38 +00:00
If FileExist ( tmpfname )
FileDelete , %tmpfname%
}
Else
FileMove , %tmpfname% , %filename% , 1
2012-11-25 13:56:35 +00:00
}
2012-12-04 02:52:43 +00:00
;; Restore previously saved window state.
;; If the state is completely different, this function won't do much. However, if restoring from a crash
;; or simply restarting bug.n, it should completely recover the window state.
Manager__restoreWindowState ( filename )
{
2012-11-27 03:13:38 +00:00
Local vidx , widx , i , j , m , v , candidate_set , view_set , excluded_view_set , view_m0 , view_v0 , view_list0 , wnds0 , items0 , wndProc , view_var , isManaged , isFloating , isDecorated , hideTitle
If Not FileExist ( filename )
Return
widx := 1
vidx := 1
view_set := " "
excluded_view_set := " "
2012-12-04 02:52:43 +00:00
;; Read all interesting things from the file.
2012-11-27 03:13:38 +00:00
Loop , READ , %filename%
2012-12-04 02:52:43 +00:00
{
If ( SubStr ( A_LoopReadLine , 1 , 5 ) = " View_ " )
{
2012-11-27 03:13:38 +00:00
i := InStr ( A_LoopReadLine , " # " )
j := InStr ( A_LoopReadLine , " _ " , false , i )
m := SubStr ( A_LoopReadLine , i + 1 , j - i - 1 )
i := InStr ( A_LoopReadLine , " # " , false , j )
j := InStr ( A_LoopReadLine , " _ " , false , i )
v := SubStr ( A_LoopReadLine , i + 1 , j - i - 1 )
i := InStr ( A_LoopReadLine , " = " , j + 1 )
2012-12-04 02:52:43 +00:00
If ( m < = Manager_monitorCount ) And ( v < = Config_viewCount )
{
2012-11-27 03:13:38 +00:00
view_list %vidx% := SubStr ( A_LoopReadLine , i + 1 )
view_m %vidx% := m
view_v %vidx% := v
view_set := view_set . view_list %vidx%
vidx := vidx + 1
}
2012-12-04 02:52:43 +00:00
Else
{
2012-11-27 03:13:38 +00:00
excluded_view_set := excluded_view_set . view_list %vidx%
Debug_logMessage ( " View ( " . m . " , " . v . " ) is no longer available ( " . vidx . " ) " , 0 )
}
}
Else If ( SubStr ( A_LoopReadLine , 1 , 7 ) = " Window " ) {
wnds %widx% := SubStr ( A_LoopReadLine , 8 )
widx := widx + 1
}
2012-12-04 02:52:43 +00:00
}
2012-11-27 03:13:38 +00:00
;Debug_logMessage("view_set: " . view_set, 1)
;Debug_logMessage("excluded_view_set: " . excluded_view_set, 1)
2012-12-04 03:18:19 +00:00
candidate_set := " "
2012-11-27 03:13:38 +00:00
; Scan through all defined windows. Create a candidate set of windows based on whether the properties of existing windows match.
2012-12-04 02:52:43 +00:00
Loop , % ( widx - 1 )
{
2012-11-27 03:13:38 +00:00
StringSplit , items , wnds %A_Index% , `;
2012-12-04 02:52:43 +00:00
If ( items0 < 9 )
{
2012-11-27 03:13:38 +00:00
Debug_logMessage ( " Window ' " . wnds %A_Index% . " ' could not be processed due to parse error " , 0 )
Continue
}
i := 1
i := items %i%
j := 2
DetectHiddenWindows , On
WinGet , wndProc , ProcessName , ahk_id %i%
DetectHiddenWindows , Off
2012-12-04 02:52:43 +00:00
If Not ( items %j% = wndProc )
{
2012-11-27 03:13:38 +00:00
Debug_logMessage ( " Window ahk_id " . i . " process ' " . wndProc . " ' doesn't match expected ' " . items %j% . " ', forgetting this window " , 0 )
Continue
}
j := 8
isManaged := items %j%
; If Managed
If ( items %j% )
2012-12-04 02:52:43 +00:00
{
If ( InStr ( view_set , i ) = 0 )
{
If ( InStr ( excluded_view_set , i ) )
{
2012-11-27 03:13:38 +00:00
Debug_logMessage ( " Window ahk_id " . i . " is being ignored because it no longer belongs to an active view " , 0 )
}
2012-12-04 02:52:43 +00:00
Else
{
2012-11-27 03:13:38 +00:00
Debug_logMessage ( " Window ahk_id " . i . " is being ignored because it doesn't exist in any views " , 0 )
}
Continue
}
2012-12-04 02:52:43 +00:00
}
2012-11-25 13:56:35 +00:00
2012-11-27 03:13:38 +00:00
; Set up the window.
j := 3
m := items %j%
j := 4
v := items %j%
j := 5
isFloating := items %j%
j := 6
isDecorated := items %j%
j := 7
hideTitle := items %j%
Manager__setWinProperties ( i , isManaged , m , v , isDecorated , isFloating , hideTitle )
;Manager_winHide(i)
2012-12-04 03:18:19 +00:00
candidate_set := candidate_set . i . " ; "
2012-11-27 03:13:38 +00:00
}
;Debug_logMessage("candidate_set: " . candidate_set, 1)
; Set up all views. Must filter the window list by those from the candidate set.
2012-12-04 02:52:43 +00:00
Loop , % ( vidx - 1 )
{
2012-11-27 03:13:38 +00:00
StringSplit , items , view_list %A_Index% , `;
view_set := " "
2012-12-04 02:52:43 +00:00
Loop , % items0 - 1
{
2012-11-27 03:13:38 +00:00
If ( InStr ( candidate_set , items %A_Index% ) > 0 )
view_set := view_set . items %A_Index% . " ; "
}
view_var := " View_# " . view_m %A_Index% . " _# " . view_v %A_Index% . " _wndIds "
%view_var% := view_set
}
2012-11-25 13:56:35 +00:00
}
2012-06-24 22:04:41 +00:00
; No windows are known to the system yet.
; Try to do something smart with the initial layout.
2012-12-04 02:52:43 +00:00
Manager_initial_sync ( )
{
2012-11-27 03:13:38 +00:00
Local wndId0 , wnd , wndX , wndY , wndW , wndH , x , y , m , len
2012-12-04 02:52:43 +00:00
;; Initialize lists
;; Note that these variables make this function non-reentrant.
Loop , % Manager_monitorCount
{
Manager_initial_sync_m# %A_Index% _wndList := " "
}
2012-11-27 03:13:38 +00:00
2012-12-04 02:52:43 +00:00
;; Use saved window placement settings to first determine
;; which monitor/view a window should be attached to.
2012-11-27 03:13:38 +00:00
Manager__restoreWindowState ( Main_autoWindowState )
2012-12-04 02:52:43 +00:00
;; Check all remaining visible windows against the known windows
2012-11-27 03:13:38 +00:00
WinGet , wndId , List , , ,
2012-12-04 02:52:43 +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-11-27 03:13:38 +00:00
2012-12-04 02:52:43 +00:00
;; Which monitor is it on?
2012-11-27 03:13:38 +00:00
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
2012-12-04 02:52:43 +00:00
Manager_initial_sync_m# %m% _wndList .= wndId %A_Index% " ; "
2012-11-27 03:13:38 +00:00
}
2012-06-24 22:04:41 +00:00
2012-12-04 02:52:43 +00:00
Loop , % Manager_monitorCount
{
2012-11-27 03:13:38 +00:00
m := A_Index
2012-12-04 02:52:43 +00:00
StringTrimRight , wndIds , Manager_initial_sync_m# %m% _wndList , 1
StringSplit , wndId , wndIds , `;
Loop , % wndId0
{
Manager_manage ( m , 1 , wndId %A_Index% )
}
2012-11-27 03:13:38 +00:00
}
2012-06-24 22:04:41 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_toggleDecor ( )
{
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
Manager_unmanage ( wndId )
{
2012-11-27 03:13:38 +00:00
Local a
2012-12-04 02:52:43 +00:00
;; Do our best to make sure that any unmanaged windows are left visible.
2012-11-27 03:13:38 +00:00
Manager_winShow ( wndId )
a := Manager_# %wndId% _tags & 1 << Monitor_# %Manager_aMonitor% _aView_#1 - 1
2012-12-04 02:52:43 +00:00
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% `; ,
2012-11-27 03:13:38 +00:00
Bar_updateView ( Manager_aMonitor , A_Index )
}
2012-12-04 02:52:43 +00:00
}
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
Manager_winActivate ( wndId )
{
Local aWndId , wndHeight , wndWidth , wndX , wndY
2012-11-27 03:13:38 +00:00
2012-12-04 02:52:43 +00:00
If Config_mouseFollowsFocus
{
If wndId
{
2012-11-27 03:13:38 +00:00
WinGetPos , wndX , wndY , wndWidth , wndHeight , ahk_id %wndId%
DllCall ( " SetCursorPos " , " Int " , Round ( wndX + wndWidth / 2 ) , " Int " , Round ( wndY + wndHeight / 2 ) )
2012-12-04 02:52:43 +00:00
}
Else
2012-11-27 03:13:38 +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-12-04 02:52:43 +00:00
If wndId And Manager_isHung ( wndId )
{
Debug_logMessage ( " DEBUG[2] Manager_winActivate: Potentially hung window " . wndId , 2 )
2012-11-27 03:13:38 +00:00
Return 1
}
2012-12-04 02:52:43 +00:00
Else
{
Debug_logMessage ( " DEBUG[1] Activating window: " wndId , 1 )
If Not wndId
{
WinGet , wndId , ID , Program Manager ahk_class Progman
Debug_logMessage ( " DEBUG[1] Activating Program Manager: " wndId , 1 )
}
2012-11-27 03:13:38 +00:00
WinActivate , ahk_id %wndId%
2012-12-04 02:52:43 +00:00
WinGet , aWndId , ID , A
If ( wndId != aWndId )
2012-11-27 03:13:38 +00:00
Return 1
}
Bar_updateTitle ( )
Return 0
2011-07-27 17:43:34 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_winClose ( wndId )
{
If Manager_isHung ( wndId )
{
Debug_logMessage ( " DEBUG[2] Manager_winClose: Potentially hung window " . wndId , 2 )
2012-11-27 03:13:38 +00:00
Return 1
}
2012-12-04 02:52:43 +00:00
Else
{
WinClose , ahk_id %wndId%
Return 0
2012-11-27 03:13:38 +00:00
}
2011-07-27 17:43:34 +00:00
}
2012-06-28 02:00:32 +00:00
2012-12-04 02:52:43 +00:00
Manager_winHide ( wndId )
{
If Manager_isHung ( wndId )
{
Debug_logMessage ( " DEBUG[2] Manager_winHide: Potentially hung window " . wndId , 2 )
2012-11-27 03:13:38 +00:00
Return 1
}
2012-12-04 02:52:43 +00:00
Else
{
2012-11-27 03:13:38 +00:00
WinHide , ahk_id %wndId%
Return 0
}
2012-06-28 02:00:32 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_winMaximize ( wndId )
{
If Manager_isHung ( wndId )
{
Debug_logMessage ( " DEBUG[2] Manager_winMaximize: Potentially hung window " . wndId , 2 )
2012-11-27 03:13:38 +00:00
Return 1
}
2012-12-04 02:52:43 +00:00
Else
{
WinMaximize , ahk_id %wndId%
2012-11-27 03:13:38 +00:00
Return 0
}
2012-06-28 02:00:32 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_winMove ( wndId , x , y , width , height )
{
If Manager_isHung ( wndId )
{
Debug_logMessage ( " DEBUG[2] Manager_winMove: Potentially hung window " . wndId , 2 )
2012-11-27 03:13:38 +00:00
Return 1
}
2012-12-04 02:52:43 +00:00
Else
{
WinGet , wndMin , MinMax , ahk_id %wndId%
If ( wndMin = - 1 )
WinRestore , ahk_id %wndId%
}
WM_ENTERSIZEMOVE = 0x0231
WM_EXITSIZEMOVE = 0x0232
SendMessage , WM_ENTERSIZEMOVE , , , , ahk_id %wndId%
If ErrorLevel
{
Debug_logMessage ( " DEBUG[2] Manager_winMove: Potentially hung window " . wndId , 1 )
Return 1
}
Else
{
WinMove , ahk_id %wndId% , , %x% , %y% , %width% , %height%
SendMessage , WM_EXITSIZEMOVE , , , , ahk_id %wndId%
2012-11-27 03:13:38 +00:00
}
2012-06-28 02:00:32 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_winSet ( type , value , wndId )
{
If Manager_isHung ( wndId )
{
Debug_logMessage ( " DEBUG[2] Manager_winSet: Potentially hung window " . wndId , 2 )
2012-11-27 03:13:38 +00:00
Return 1
}
2012-12-04 02:52:43 +00:00
Else
{
2012-11-27 03:13:38 +00:00
WinSet , %type% , %value% , ahk_id %wndId%
Return 0
}
2012-06-28 03:34:19 +00:00
}
2012-12-04 02:52:43 +00:00
Manager_winShow ( wndId )
{
If Manager_isHung ( wndId )
{
Debug_logMessage ( " DEBUG[2] Manager_winShow: Potentially hung window " . wndId , 2 )
2012-11-27 03:13:38 +00:00
Return 1
2012-12-04 02:52:43 +00:00
}
Else
{
WinShow , ahk_id %wndId%
2012-11-27 03:13:38 +00:00
Return 0
}
2012-06-30 02:20:15 +00:00
}