{"action":"created","issue":{"url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/372","labels_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/372/labels{/name}","comments_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/372/comments","events_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/372/events","html_url":"https://github.com/Hammerspoon/hammerspoon/pull/372","id":93438973,"number":372,"title":"Add windowtracker extension","user":{"login":"tmandry","id":2280544,"avatar_url":"https://avatars.githubusercontent.com/u/2280544?v=3","gravatar_id":"","url":"https://api.github.com/users/tmandry","html_url":"https://github.com/tmandry","followers_url":"https://api.github.com/users/tmandry/followers","following_url":"https://api.github.com/users/tmandry/following{/other_user}","gists_url":"https://api.github.com/users/tmandry/gists{/gist_id}","starred_url":"https://api.github.com/users/tmandry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tmandry/subscriptions","organizations_url":"https://api.github.com/users/tmandry/orgs","repos_url":"https://api.github.com/users/tmandry/repos","events_url":"https://api.github.com/users/tmandry/events{/privacy}","received_events_url":"https://api.github.com/users/tmandry/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-07-07T04:59:43Z","updated_at":"2015-07-08T21:51:44Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/Hammerspoon/hammerspoon/pulls/372","html_url":"https://github.com/Hammerspoon/hammerspoon/pull/372","diff_url":"https://github.com/Hammerspoon/hammerspoon/pull/372.diff","patch_url":"https://github.com/Hammerspoon/hammerspoon/pull/372.patch"},"body":"Here's my response to #254. I personally think this is a simple and effective approach to dealing with window events. Happy to discuss and make revisions.\r\n\r\nI've toyed with the idea of giving it criteria for which windows to watch, but not sure on the interface or what the use case is. (For the interface, it could accept a list of app bundle IDs or something.) What do you think?\r\n\r\nDocs\r\n---\r\n\r\nTrack all windows on the screen. windowtracker abstracts away applications and treats all\r\nwindows the same, subscribing to all events on all windows.\r\n\r\nYou can watch for the following events:\r\n* hs.windowtracker.windowCreated: A window was created.\r\n* hs.windowtracker.windowDestroyed: A window was destroyed.\r\n* hs.windowtracker.mainWindowChanged: The main window was changed. This is usually the same as\r\n  the focused window (except for helper dialog boxes like file pickers, which are not reported\r\n  by this event). Note that switching applications triggers this event, unlike the OS X\r\n  accessibility API.\r\n* hs.windowtracker.windowMoved: A window was moved.\r\n* hs.windowtracker.windowResized: A window was resized.\r\n* hs.windowtracker.windowMinimized: A window was minimized.\r\n* hs.windowtracker.windowUnminimized: A window was unminimized.\r\n\r\nNote that Hammerspoon windows (the console) are ignored by windowtracker. This is because the\r\nconsole pops after an error, which can cause infinite exception loops, rendering the computer\r\nunusable.\r\n\r\nCaveats\r\n---\r\nCalling `start()` can hang for awhile because of asking every app for all of its windows (the same way that `hs.window.allWindows()` works)."},"comment":{"url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/comments/119741526","html_url":"https://github.com/Hammerspoon/hammerspoon/pull/372#issuecomment-119741526","issue_url":"https://api.github.com/repos/Hammerspoon/hammerspoon/issues/372","id":119741526,"user":{"login":"lowne","id":6718755,"avatar_url":"https://avatars.githubusercontent.com/u/6718755?v=3","gravatar_id":"","url":"https://api.github.com/users/lowne","html_url":"https://github.com/lowne","followers_url":"https://api.github.com/users/lowne/followers","following_url":"https://api.github.com/users/lowne/following{/other_user}","gists_url":"https://api.github.com/users/lowne/gists{/gist_id}","starred_url":"https://api.github.com/users/lowne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lowne/subscriptions","organizations_url":"https://api.github.com/users/lowne/orgs","repos_url":"https://api.github.com/users/lowne/repos","events_url":"https://api.github.com/users/lowne/events{/privacy}","received_events_url":"https://api.github.com/users/lowne/received_events","type":"User","site_admin":false},"created_at":"2015-07-08T21:51:44Z","updated_at":"2015-07-08T21:51:44Z","body":"I finally landed my PR at #374 (but the conversation started here, so here it shall continue).\r\n\r\nFirst, the story about my take: as I started writing modules for my own use, there were two things that I was doing over and over on each module:\r\n1. limit the scope of whatever the module was doing to specific windows\r\n2. dance the dance with watchers for getting events (that got old *real* quick)\r\nAnd so I made windowfilter and windowwatcher, respectively; the latter basically started exactly as this one, which I was unaware of; this \"independent invention\", along with #254 (which I also just recently learned of) tells me that I'm not alone in dreading OS-level event watchers :)\r\nI made windowwatcher depend on windowfilter because I *always* want at least basic filtering (which is what `hs.windowfilter.default` is about); during revisions I integrated them more and more, until I decided it made sense to just merge them - and the \"windowfilter\" name might not be the best choice for the resulting module, it just stuck (and is ofc amenable to improvement).\r\n\r\nAs its sheer size suggests, windowfilter does quite a bit more than windowtracker (which is not necessarily a good thing by itself). These imho are the more interesting additions:\r\n* the whole filtering business, which is half the module\r\n* in the \"watcher\" part alone, for a fairer comparison, windowfilter keeps its own internal data structure tracking all the apps and windows; incoming events act on it, and then windowfilter events are emitted; this allows it to do a lot of cleanup on the incoming event stream, making the resulting stream *much* saner (see comments at the top of the file for examples); the end user needn't worry about OS X quirks (which bit me many many times) \r\n* the :notify method is very convenient for otherwise quite convoluted use cases - see the \"timewaster\" example in my PR, which doesn't really make it justice but hopefully gets the idea across.\r\n\r\n"}}