diff --git a/Sources/AppBundle/model/ServerEvent.swift b/Sources/AppBundle/model/ServerEvent.swift index 7eb3983d1..3587e8f68 100644 --- a/Sources/AppBundle/model/ServerEvent.swift +++ b/Sources/AppBundle/model/ServerEvent.swift @@ -45,4 +45,8 @@ public struct ServerEvent: Codable, Sendable { public static func bindingTriggered(mode: String, binding: String) -> ServerEvent { ServerEvent(_event: .bindingTriggered, mode: mode, binding: binding) } + + public static func windowClosed(windowId: UInt32, workspace: String?) -> ServerEvent { + ServerEvent(_event: .windowClosed, windowId: windowId, workspace: workspace) + } } diff --git a/Sources/AppBundle/subscriptions.swift b/Sources/AppBundle/subscriptions.swift index a8b325bdc..5748ac107 100644 --- a/Sources/AppBundle/subscriptions.swift +++ b/Sources/AppBundle/subscriptions.swift @@ -30,7 +30,7 @@ func handleSubscribeAndWaitTillError(_ connection: NWConnection, _ args: Subscri workspace: f.workspace.name, monitorId_oneBased: f.workspace.workspaceMonitor.monitorId_oneBased ?? 0, ) - case .windowDetected, .bindingTriggered: continue + case .windowDetected, .bindingTriggered, .windowClosed: continue } if await connection.writeAtomic(event, jsonEncoder).error != nil { return diff --git a/Sources/AppBundle/tree/MacWindow.swift b/Sources/AppBundle/tree/MacWindow.swift index 5fd6cbd08..f18e426d3 100644 --- a/Sources/AppBundle/tree/MacWindow.swift +++ b/Sources/AppBundle/tree/MacWindow.swift @@ -83,6 +83,7 @@ final class MacWindow: Window { if !skipClosedWindowsCache { cacheClosedWindowIfNeeded() } let parent = unbindFromParent().parent let deadWindowWorkspace = parent.nodeWorkspace + broadcastEvent(.windowClosed(windowId: windowId, workspace: deadWindowWorkspace?.name)) let focus = focus if let deadWindowWorkspace, deadWindowWorkspace == focus.workspace || deadWindowWorkspace == prevFocusedWorkspace && prevFocusedWorkspaceDate.distance(to: .now) < 1 diff --git a/Sources/AppBundleTests/command/SubscribeCmdArgsTest.swift b/Sources/AppBundleTests/command/SubscribeCmdArgsTest.swift index 9876ee137..34ddd7dd8 100644 --- a/Sources/AppBundleTests/command/SubscribeCmdArgsTest.swift +++ b/Sources/AppBundleTests/command/SubscribeCmdArgsTest.swift @@ -31,7 +31,7 @@ final class SubscribeCmdArgsTest: XCTestCase { case .failure(let err): let expectedMsg = """ ERROR: Can't parse 'unknown-event'. - Possible values: (focus-changed|focused-monitor-changed|focused-workspace-changed|mode-changed|window-detected|binding-triggered) + Possible values: (focus-changed|focused-monitor-changed|focused-workspace-changed|mode-changed|window-detected|binding-triggered|window-closed) """ assertEquals(err, .init(expectedMsg, 2)) } diff --git a/Sources/Common/cmdArgs/impl/SubscribeCmdArgs.swift b/Sources/Common/cmdArgs/impl/SubscribeCmdArgs.swift index f1bfcf40f..46563a0d1 100644 --- a/Sources/Common/cmdArgs/impl/SubscribeCmdArgs.swift +++ b/Sources/Common/cmdArgs/impl/SubscribeCmdArgs.swift @@ -60,4 +60,5 @@ public enum ServerEventType: String, Codable, CaseIterable, Sendable { case modeChanged = "mode-changed" case windowDetected = "window-detected" case bindingTriggered = "binding-triggered" + case windowClosed = "window-closed" } diff --git a/docs/aerospace-subscribe.adoc b/docs/aerospace-subscribe.adoc index db13198c5..7bd32b959 100644 --- a/docs/aerospace-subscribe.adoc +++ b/docs/aerospace-subscribe.adoc @@ -50,6 +50,8 @@ window-detected:: Fired when a new window is detected. Includes `windowId`, `wor binding-triggered:: Fired when a keyboard binding is triggered. Includes `binding`, `mode`. +window-closed:: Fired when a window is closed. Includes `windowId`, `workspace`. + // =========================================================== Output Format include::util/conditional-output-format-header.adoc[] diff --git a/grammar/commands-bnf-grammar.txt b/grammar/commands-bnf-grammar.txt index be48fd72e..203ef51c6 100644 --- a/grammar/commands-bnf-grammar.txt +++ b/grammar/commands-bnf-grammar.txt @@ -152,4 +152,4 @@ aerospace -h; ::= {{{ aerospace list-apps --format '%{app-pid}%{tab}%{app-name}' }}}; ::= all | mouse | focused | {{{ aerospace list-monitors --format '%{monitor-id}%{tab}%{monitor-name}' }}}; - ::= focus-changed | focused-monitor-changed | focused-workspace-changed | mode-changed | window-detected | binding-triggered; + ::= focus-changed | focused-monitor-changed | focused-workspace-changed | mode-changed | window-detected | binding-triggered | window-closed;