Filter windows by application, title, location on screen and more, and easily subscribe to events on these windows
Warning: this module is still somewhat experimental. Should you encounter any issues, please feel free to report them on https://github.com/Hammerspoon/hammerspoon/issues or #hammerspoon on irc.libera.chat.
Windowfilters monitor all windows as they're created, closed, moved etc., and select some (or none) among these windows
according to specific filtering rules. These filtering rules are app-specific, i.e. they start off by selecting all windows
belonging to a certain application (but you can also define default and override filters - see :setAppFilter(),
:setDefaultFilter(), :setOverrideFilter()) and they can allow or reject windows based on:
The filtering happens automatically in the background; windowfilters then:
:getWindows()):subscribe() and the module constants with all the events)A default windowfilter (not to be confused with the default filter within a windowfilter) is provided as convenience;
it excludes some known apps and windows that are transient in nature, therefore unlikely to be "interesting" for e.g. window management.
hs.window.filter.new() (with no arguments) returns a copy of the default windowfilter that you can further tailor
to your needs - see hs.window.filter.default and hs.window.filter.new() for more information.
Usage examples:
local wf=hs.window.filter
-- alter the default windowfilter
wf.default:setAppFilter('My IDE',{allowTitles=1}) -- ignore no-title windows (e.g. transient autocomplete suggestions) in My IDE
-- set the exact scope of what you're interested in - see hs.window.filter:setAppFilter()
wf_terminal = wf.new{'Terminal','iTerm2'} -- all visible terminal windows
wf_timewaster = wf.new(false):setAppFilter('Safari',{allowTitles='reddit'}) -- any Safari windows with "reddit" anywhere in the title
wf_leftscreen = wf.new{override={visible=true,fullscreen=false,allowScreens='-1,0',currentSpace=true}}
-- all visible and non-fullscreen windows that are on the screen to the left of the primary screen in the current Space
wf_editors_righthalf = wf.new{'TextEdit','Sublime Text','BBEdit'}:setRegions(hs.screen.primaryScreen():fromUnitRect'0.5,0/1,1')
-- text editor windows that are on the right half of the primary screen
wf_bigwindows = wf.new(function(w)return w:frame().area>3000000 end) -- only very large windows
wf_notif = wf.new{['Notification Center']={allowRoles='AXNotificationCenterAlert'}} -- notification center alerts
-- subscribe to events
wf_terminal:subscribe(wf.windowFocused,some_fn) -- run a function whenever a terminal window is focused
wf_timewaster:subscribe(wf.hasWindow,startAnnoyingMe):subscribe(wf.hasNoWindows,stopAnnoyingMe) -- fight procrastination :)
| Signature | hs.window.filter.default |
|---|---|
| Type | Constant |
| Description | The default windowfilter; it filters apps whose windows are transient in nature so that you're unlikely (and often |
| Notes |
|
| Source | extensions/window/window_filter.lua line 743 |
| Signature | hs.window.filter.defaultCurrentSpace |
|---|---|
| Type | Constant |
| Description | A copy of the default windowfilter (see |
| Notes |
|
| Source | extensions/window/window_filter.lua line 764 |
| Signature | hs.window.filter.hasNoWindows |
|---|---|
| Type | Constant |
| Description | Pseudo-event for |
| Notes |
|
| Source | extensions/window/window_filter.lua line 916 |
| Signature | hs.window.filter.hasWindow |
|---|---|
| Type | Constant |
| Description | Pseudo-event for |
| Notes |
|
| Source | extensions/window/window_filter.lua line 907 |
| Signature | hs.window.filter.sortByCreated |
|---|---|
| Type | Constant |
| Description | Sort order for |
| Source | extensions/window/window_filter.lua line 1771 |
| Signature | hs.window.filter.sortByCreatedLast |
|---|---|
| Type | Constant |
| Description | Sort order for |
| Source | extensions/window/window_filter.lua line 1767 |
| Signature | hs.window.filter.sortByFocused |
|---|---|
| Type | Constant |
| Description | Sort order for |
| Source | extensions/window/window_filter.lua line 1763 |
| Signature | hs.window.filter.sortByFocusedLast |
|---|---|
| Type | Constant |
| Description | Sort order for |
| Notes |
|
| Source | extensions/window/window_filter.lua line 1756 |
| Signature | hs.window.filter.windowAllowed |
|---|---|
| Type | Constant |
| Description | Pseudo-event for |
| Notes |
|
| Source | extensions/window/window_filter.lua line 893 |
| Signature | hs.window.filter.windowCreated |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 815 |
| Signature | hs.window.filter.windowDestroyed |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 819 |
| Signature | hs.window.filter.windowFocused |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 881 |
| Signature | hs.window.filter.windowFullscreened |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 827 |
| Signature | hs.window.filter.windowHidden |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 847 |
| Signature | hs.window.filter.windowInCurrentSpace |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 861 |
| Signature | hs.window.filter.windowMinimized |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 835 |
| Signature | hs.window.filter.windowMoved |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 823 |
| Signature | hs.window.filter.windowNotInCurrentSpace |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 866 |
| Signature | hs.window.filter.windowNotOnScreen |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 876 |
| Signature | hs.window.filter.windowNotVisible |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 856 |
| Signature | hs.window.filter.windowOnScreen |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 871 |
| Signature | hs.window.filter.windowRejected |
|---|---|
| Type | Constant |
| Description | Pseudo-event for |
| Notes |
|
| Source | extensions/window/window_filter.lua line 900 |
| Signature | hs.window.filter.windowsChanged |
|---|---|
| Type | Constant |
| Description | Pseudo-event for |
| Notes |
|
| Source | extensions/window/window_filter.lua line 925 |
| Signature | hs.window.filter.windowTitleChanged |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 889 |
| Signature | hs.window.filter.windowUnfocused |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 885 |
| Signature | hs.window.filter.windowUnfullscreened |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 831 |
| Signature | hs.window.filter.windowUnminimized |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 839 |
| Signature | hs.window.filter.windowVisible |
|---|---|
| Type | Constant |
| Description | Event for |
| Source | extensions/window/window_filter.lua line 851 |
| Signature | hs.window.filter.allowedWindowRoles |
|---|---|
| Type | Variable |
| Description | A table for window roles (as per |
| Notes |
|
| Source | extensions/window/window_filter.lua line 180 |
| Signature | hs.window.filter.forceRefreshOnSpaceChange |
|---|---|
| Type | Variable |
| Description | Tells all windowfilters whether to refresh all windows when the user switches to a different Mission Control Space. |
| Notes |
|
| Source | extensions/window/window_filter.lua line 1522 |
| Signature | hs.window.filter.ignoreAlways |
|---|---|
| Type | Variable |
| Description | A table of application names (as per |
| Notes |
|
| Source | extensions/window/window_filter.lua line 103 |
| Signature | hs.window.filter.focusEast() |
|---|---|
| Type | Function |
| Description | Convenience function to focus the nearest window to the east |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2253 |
| Signature | hs.window.filter.focusNorth() |
|---|---|
| Type | Function |
| Description | Convenience function to focus the nearest window to the north |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2292 |
| Signature | hs.window.filter.focusSouth() |
|---|---|
| Type | Function |
| Description | Convenience function to focus the nearest window to the south |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2279 |
| Signature | hs.window.filter.focusWest() |
|---|---|
| Type | Function |
| Description | Convenience function to focus the nearest window to the west |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2266 |
| Signature | hs.window.filter.isGuiApp(appname) -> boolean |
|---|---|
| Type | Function |
| Description | Checks whether an app is a known non-GUI app, as per |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 772 |
| Signature | hs.window.filter.switchedToSpace(space) |
|---|---|
| Type | Function |
| Description | Callback to inform all windowfilters that the user initiated a switch to a (numbered) Mission Control Space. |
| Parameters |
|
| Returns | |
| Notes |
|
| Source | extensions/window/window_filter.lua line 1483 |
| Signature | hs.window.filter.copy(windowfilter[,logname[,loglevel]]) -> hs.window.filter object |
|---|---|
| Type | Constructor |
| Description | Returns a copy of an hs.window.filter object that you can further restrict or expand |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 725 |
| Signature | hs.window.filter.new(fn[,logname[,loglevel]]) -> hs.window.filter object |
|---|---|
| Type | Constructor |
| Description | Creates a new hs.window.filter instance |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 673 |
| Signature | hs.window.filter:allowApp(appname) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Sets the windowfilter to allow all visible windows belonging to a specific app |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 343 |
| Signature | hs.window.filter:focusWindowEast(window, frontmost, strict) |
|---|---|
| Type | Method |
| Description | Focuses the nearest window to the east of a given window |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2185 |
| Signature | hs.window.filter:focusWindowNorth(window, frontmost, strict) |
|---|---|
| Type | Method |
| Description | Focuses the nearest window to the south of a given window |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2235 |
| Signature | hs.window.filter:focusWindowSouth(window, frontmost, strict) |
|---|---|
| Type | Method |
| Description | Focuses the nearest window to the north of a given window |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2218 |
| Signature | hs.window.filter:focusWindowWest(window, frontmost, strict) |
|---|---|
| Type | Method |
| Description | Focuses the nearest window to the west of a given window |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2202 |
| Signature | hs.window.filter:getFilters() -> table |
|---|---|
| Type | Method |
| Description | Return a table with all the filtering rules defined for this windowfilter |
| Parameters |
|
| Returns |
after performing valid manipulations) to |
| Source | extensions/window/window_filter.lua line 642 |
| Signature | hs.window.filter:getWindows([sortOrder]) -> list of hs.window objects |
|---|---|
| Type | Method |
| Description | Gets the current windows allowed by this windowfilter |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 1825 |
| Signature | hs.window.filter:isAppAllowed(appname) -> boolean |
|---|---|
| Type | Method |
| Description | Checks if an app is allowed by the windowfilter |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 313 |
| Signature | hs.window.filter:isWindowAllowed(window) -> boolean |
|---|---|
| Type | Method |
| Description | Checks if a window is allowed by the windowfilter |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 193 |
| Signature | hs.window.filter:pause() -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Stops the windowfilter event subscriptions; no more event callbacks will be triggered, but the subscriptions remain intact for a subsequent call to |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 2054 |
| Signature | hs.window.filter:rejectApp(appname) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Sets the windowfilter to outright reject any windows belonging to a specific app |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 327 |
| Signature | hs.window.filter:resume() -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Resumes the windowfilter event subscriptions |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 2039 |
| Signature | hs.window.filter:setAppFilter(appname, filter) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Sets the detailed filtering rules for the windows of a specific app |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 441 |
| Signature | hs.window.filter:setCurrentSpace(val) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Sets whether the windowfilter should only allow (or reject) windows in the current Mission Control Space |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 382 |
| Signature | hs.window.filter:setDefaultFilter(filter) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Set the default filtering rules to be used for apps without app-specific rules |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 358 |
| Signature | hs.window.filter:setFilters(filters) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Sets multiple filtering rules |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 602 |
| Signature | hs.window.filter:setOverrideFilter(filter) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Set overriding filtering rules that will be applied for all apps before any app-specific rules |
| Parameters |
|
| Returns |
|
| Source | extensions/window/window_filter.lua line 370 |
| Signature | hs.window.filter:setRegions(regions) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Sets the allowed screen regions for this windowfilter |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 404 |
| Signature | hs.window.filter:setScreens(screens) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Sets the allowed screens for this windowfilter |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 422 |
| Signature | hs.window.filter:setSortOrder(sortOrder) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Sets the sort order for this windowfilter's |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 1785 |
| Signature | hs.window.filter:subscribe(event, fn[, immediate]) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Subscribe to one or more events on the allowed windows |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 1879 |
| Signature | hs.window.filter:unsubscribe([event][, fn]) -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Removes one or more event subscriptions |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 1956 |
| Signature | hs.window.filter:unsubscribeAll() -> hs.window.filter object |
|---|---|
| Type | Method |
| Description | Removes all event subscriptions |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2020 |
| Signature | hs.window.filter:windowsToEast(window, frontmost, strict) -> list of |
|---|---|
| Type | Method |
| Description | Gets all visible windows allowed by this windowfilter that lie to the east a given window |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2114 |
| Signature | hs.window.filter:windowsToNorth(window, frontmost, strict) -> list of |
|---|---|
| Type | Method |
| Description | Gets all visible windows allowed by this windowfilter that lie to the north a given window |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2148 |
| Signature | hs.window.filter:windowsToSouth(window, frontmost, strict) -> list of |
|---|---|
| Type | Method |
| Description | Gets all visible windows allowed by this windowfilter that lie to the south a given window |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2166 |
| Signature | hs.window.filter:windowsToWest(window, frontmost, strict) -> list of |
|---|---|
| Type | Method |
| Description | Gets all visible windows allowed by this windowfilter that lie to the west a given window |
| Parameters |
|
| Returns |
|
| Notes |
|
| Source | extensions/window/window_filter.lua line 2132 |