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/filter.lua |
Signature | hs.window.filter.defaultCurrentSpace |
---|---|
Type | Constant |
Description | A copy of the default windowfilter (see `hs.window.filter.default`) that only allows windows in the current |
Notes | |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.hasNoWindows |
---|---|
Type | Constant |
Description | Pseudo-event for `hs.window.filter:subscribe()`: the windowfilter now rejects all windows |
Notes | |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.hasWindow |
---|---|
Type | Constant |
Description | Pseudo-event for `hs.window.filter:subscribe()`: the windowfilter now allows one window |
Notes | |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.sortByCreated |
---|---|
Type | Constant |
Description | Sort order for `hs.window.filter:getWindows()`: windows are sorted in order of creation, oldest first (see also `hs.window.filter:setSortOrder()`) |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.sortByCreatedLast |
---|---|
Type | Constant |
Description | Sort order for `hs.window.filter:getWindows()`: windows are sorted in order of creation, newest first (see also `hs.window.filter:setSortOrder()`) |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.sortByFocused |
---|---|
Type | Constant |
Description | Sort order for `hs.window.filter:getWindows()`: windows are sorted in order of focus received, least recently first (see also `hs.window.filter:setSortOrder()`) |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.sortByFocusedLast |
---|---|
Type | Constant |
Description | Sort order for `hs.window.filter:getWindows()`: windows are sorted in order of focus received, most recently first (see also `hs.window.filter:setSortOrder()`) |
Notes | |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowAllowed |
---|---|
Type | Constant |
Description | Pseudo-event for `hs.window.filter:subscribe()`: a previously rejected window (or a newly created one) is now allowed |
Notes | |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowCreated |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a new window was created |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowDestroyed |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window was destroyed |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowFocused |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window received focus |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowFullscreened |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window was expanded to fullscreen |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowHidden |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window was hidden (its app was hidden, e.g. via `cmd-h`) |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowInCurrentSpace |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window is now in the current Mission Control Space, due to |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowMinimized |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window was minimized |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowMoved |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window was moved or resized, including toggling fullscreen/maximize |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowNotInCurrentSpace |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window that used to be in the current Mission Control Space isn't anymore, |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowNotOnScreen |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window is no longer *actually* visible on any screen because it was minimized, closed, |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowNotVisible |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window is no longer "visible" (in *any* Mission Control Space, as per `hs.window:isVisible()`) |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowOnScreen |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window became *actually* visible on screen (i.e. it's "visible" as per `hs.window:isVisible()` |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowRejected |
---|---|
Type | Constant |
Description | Pseudo-event for `hs.window.filter:subscribe()`: a previously allowed window (or a window that's been destroyed) is now rejected |
Notes | |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowsChanged |
---|---|
Type | Constant |
Description | Pseudo-event for `hs.window.filter:subscribe()`: the list of allowed windows (as per `windowfilter:getWindows()`) has changed |
Notes | |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowTitleChanged |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window's title changed |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowUnfocused |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window lost focus |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowUnfullscreened |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window was reverted back from fullscreen |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowUnminimized |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window was unminimized |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.windowVisible |
---|---|
Type | Constant |
Description | Event for `hs.window.filter:subscribe()`: a window became "visible" (in *any* Mission Control Space, as per `hs.window:isVisible()`) |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.allowedWindowRoles |
---|---|
Type | Variable |
Description | A table for window roles (as per `hs.window:subrole()`) that are allowed by default. |
Notes | |
Source | extensions/window/filter.lua |
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/filter.lua |
Signature | hs.window.filter.ignoreAlways |
---|---|
Type | Variable |
Description | A table of application names (as per `hs.application:name()`) that are always ignored by this module. |
Notes | |
Source | extensions/window/filter.lua |
Signature | hs.window.filter.focusEast() |
---|---|
Type | Function |
Description | Convenience function to focus the nearest window to the east |
Parameters |
|
Returns |
|
Notes |
|
Source | extensions/window/filter.lua |
Signature | hs.window.filter.focusNorth() |
---|---|
Type | Function |
Description | Convenience function to focus the nearest window to the north |
Parameters |
|
Returns |
|
Notes |
|
Source | extensions/window/filter.lua |
Signature | hs.window.filter.focusSouth() |
---|---|
Type | Function |
Description | Convenience function to focus the nearest window to the south |
Parameters |
|
Returns |
|
Notes |
|
Source | extensions/window/filter.lua |
Signature | hs.window.filter.focusWest() |
---|---|
Type | Function |
Description | Convenience function to focus the nearest window to the west |
Parameters |
|
Returns |
|
Notes |
|
Source | extensions/window/filter.lua |
Signature | hs.window.filter.isGuiApp(appname) -> boolean |
---|---|
Type | Function |
Description | Checks whether an app is a known non-GUI app, as per `hs.window.filter.ignoreAlways` |
Parameters |
|
Returns |
|
Source | extensions/window/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
Signature | hs.window.filter:getFilters() -> table |
---|---|
Type | Method |
Description | Return a table with all the filtering rules defined for this windowfilter |
Parameters |
|
Returns |
|
Source | extensions/window/filter.lua |
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/filter.lua |
Signature | hs.window.filter:isAppAllowed(appname) -> boolean |
---|---|
Type | Method |
Description | Checks if an app is allowed by the windowfilter |
Parameters |
|
Returns |
|
Source | extensions/window/filter.lua |
Signature | hs.window.filter:isWindowAllowed(window) -> boolean |
---|---|
Type | Method |
Description | Checks if a window is allowed by the windowfilter |
Parameters |
|
Returns |
|
Source | extensions/window/filter.lua |
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 `hs.window.filter:resume()` |
Parameters |
|
Returns |
|
Source | extensions/window/filter.lua |
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/filter.lua |
Signature | hs.window.filter:resume() -> hs.window.filter object |
---|---|
Type | Method |
Description | Resumes the windowfilter event subscriptions |
Parameters |
|
Returns |
|
Source | extensions/window/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
Signature | hs.window.filter:setFilters(filters) -> hs.window.filter object |
---|---|
Type | Method |
Description | Sets multiple filtering rules |
Parameters |
|
Returns |
|
Notes |
|
Source | extensions/window/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
Signature | hs.window.filter:setSortOrder(sortOrder) -> hs.window.filter object |
---|---|
Type | Method |
Description | Sets the sort order for this windowfilter's `:getWindows()` method |
Parameters |
|
Returns |
|
Notes |
|
Source | extensions/window/filter.lua |
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/filter.lua |
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/filter.lua |
Signature | hs.window.filter:unsubscribeAll() -> hs.window.filter object |
---|---|
Type | Method |
Description | Removes all event subscriptions |
Parameters |
|
Returns |
|
Notes |
|
Source | extensions/window/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |
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/filter.lua |