Created
December 21, 2014 08:30
-
-
Save tmandry/a5b1ab6d6ea012c1e8c5 to your computer and use it in GitHub Desktop.
Track all window open, close, move, and resize events using Hammerspoon
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local events = hs.uielement.watcher | |
watchers = {} | |
function init() | |
appsWatcher = hs.application.watcher.new(handleGlobalAppEvent) | |
appsWatcher:start() | |
-- Watch any apps that already exist | |
local apps = hs.application.runningApplications() | |
for i = 1, #apps do | |
if apps[i]:title() ~= "Hammerspoon" then | |
watchApp(apps[i], true) | |
end | |
end | |
end | |
function handleGlobalAppEvent(name, event, app) | |
if event == hs.application.watcher.launched then | |
watchApp(app) | |
elseif event == hs.application.watcher.terminated then | |
-- Clean up | |
local appWatcher = watchers[app:pid()] | |
if appWatcher then | |
appWatcher.watcher:stop() | |
for id, watcher in pairs(appWatcher.windows) do | |
watcher:stop() | |
end | |
watchers[app:pid()] = nil | |
end | |
end | |
end | |
function watchApp(app, initializing) | |
if watchers[app:pid()] then return end | |
local watcher = app:newWatcher(handleAppEvent) | |
watchers[app:pid()] = {watcher = watcher, windows = {}} | |
watcher:start({events.windowCreated, events.focusedWindowChanged}) | |
-- Watch any windows that already exist | |
for i, window in pairs(app:allWindows()) do | |
watchWindow(window, initializing) | |
end | |
end | |
function handleAppEvent(element, event) | |
if event == events.windowCreated then | |
watchWindow(element) | |
elseif event == events.focusedWindowChanged then | |
-- Handle window change | |
end | |
end | |
function watchWindow(win, initializing) | |
local appWindows = watchers[win:application():pid()].windows | |
if win:isStandard() and not appWindows[win:id()] then | |
local watcher = win:newWatcher(handleWindowEvent, {pid=win:pid(), id=win:id()}) | |
appWindows[win:id()] = watcher | |
watcher:start({events.elementDestroyed, events.windowResized, events.windowMoved}) | |
if not initializing then | |
hs.alert.show('window created: '..win:id()..' with title: '..win:title()) | |
end | |
end | |
end | |
function handleWindowEvent(win, event, watcher, info) | |
if event == events.elementDestroyed then | |
watcher:stop() | |
watchers[info.pid].windows[info.id] = nil | |
else | |
-- Handle other events... | |
end | |
hs.alert.show('window event '..event..' on '..info.id) | |
end | |
init() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Depends on Hammerspoon/hammerspoon#162 and Hammerspoon/hammerspoon#161
The bookkeeping is almost all for the purpose of not leaking resources when apps or windows are closed.