aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Sources/bar/Models/AppDelegate.swift37
-rw-r--r--Sources/bar/Models/Notifier.swift26
-rw-r--r--Sources/bar/bar.docc/manual-updates.md4
3 files changed, 42 insertions, 25 deletions
diff --git a/Sources/bar/Models/AppDelegate.swift b/Sources/bar/Models/AppDelegate.swift
index a7ecb5a..cefdfc0 100644
--- a/Sources/bar/Models/AppDelegate.swift
+++ b/Sources/bar/Models/AppDelegate.swift
@@ -16,15 +16,30 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
windows.append(window)
}
+ // Register a listener to hide the bar
+ tokens.append(
+ Notifier.register("bar.hide") { [weak self] in
+ self?.hide()
+ }
+ )
+
+ // Register a listener to show the bar
+ tokens.append(
+ Notifier.register("bar.show") { [weak self] in
+ self?.show()
+ }
+ )
+
// Register one listener per unique name; a single post fans out to every
// block with that name (see Notifier).
for name in Set(blocks.map(\.name)) {
- let token = Notifier.register(name) { [weak self] in
+ let token = Notifier.register("bar.touch.\(name)") { [weak self] in
self?.handleRefresh(name)
}
tokens.append(token)
}
+ // Start the block's auto refresh
for block in blocks { block.start() }
}
@@ -33,6 +48,26 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
for token in tokens { Notifier.cancel(token) }
}
+ /// Order out all bar windows
+ nonisolated private func hide() {
+ Task { @MainActor [weak self] in
+ guard let self else { return }
+ for window in self.windows {
+ window.orderOut(nil)
+ }
+ }
+ }
+
+ /// Order front all bar windows
+ nonisolated private func show() {
+ Task { @MainActor [weak self] in
+ guard let self else { return }
+ for window in self.windows {
+ window.orderFrontRegardless()
+ }
+ }
+ }
+
/// Called from a Darwin notification handler. Marked `nonisolated` because
/// libnotify's delivery contract isn't statically visible to Swift, so we
/// hop back to the main actor explicitly.
diff --git a/Sources/bar/Models/Notifier.swift b/Sources/bar/Models/Notifier.swift
index cdfe19e..24c4950 100644
--- a/Sources/bar/Models/Notifier.swift
+++ b/Sources/bar/Models/Notifier.swift
@@ -17,15 +17,7 @@ private final class NotifyBox {
/// no client binary, using `notifyutil`:
///
/// ```
-/// notifyutil -p <prefix><name>
-/// ```
-///
-/// Each category of events uses a different `prefix`
-/// to avoid collisions. For example, block refresh
-/// notifications use ``touchPrefix``:
-///
-/// ```
-/// notifyutil -p bar.touch.<name>
+/// notifyutil -p bar.touch.<block-name>
/// ```
///
/// > Note: `notify.h` isn't part of Swift's Darwin module,
@@ -35,18 +27,10 @@ private final class NotifyBox {
/// > The callback fires on an arbitrary thread; handlers
/// > must hop to the main actor themselves (see ``AppDelegate``).
enum Notifier {
- /// Prefix for block refresh notifications.
- ///
- /// Use `notifyutil -p bar.touch.<name>` to trigger
- /// a block update from the shell.
- static let touchPrefix = "bar.touch."
-
/// Register `handler` to fire whenever the notification is posted.
///
/// - Parameters:
- /// - name: The notification name suffix.
- /// - prefix: The full notification name will be `prefix + name`.
- /// Defaults to ``touchPrefix``.
+ /// - name: The notification name.
/// - handler: Closure to invoke when the notification fires.
///
/// The returned token is a retained pointer used to keep the handler
@@ -56,10 +40,8 @@ enum Notifier {
@discardableResult
static func register(
_ name: String,
- prefix: String = Notifier.touchPrefix,
handler: @escaping @Sendable () -> Void
) -> UnsafeMutableRawPointer {
- let fullName = prefix + name
let ctx = Unmanaged.passRetained(NotifyBox(handler)).toOpaque()
CFNotificationCenterAddObserver(
@@ -70,7 +52,7 @@ enum Notifier {
let box = Unmanaged<NotifyBox>.fromOpaque(observer).takeUnretainedValue()
box.handler()
},
- fullName as CFString,
+ name as CFString,
nil,
.deliverImmediately
)
@@ -80,7 +62,7 @@ enum Notifier {
/// Remove and release a registration.
///
- /// Pass the token returned by ``Notifier/register(_:prefix:handler:)``.
+ /// Pass the token returned by ``Notifier/register(_:handler:)``.
/// Optional: process exit clears all pending registrations anyway.
static func cancel(_ token: UnsafeMutableRawPointer) {
let center = CFNotificationCenterGetDarwinNotifyCenter()
diff --git a/Sources/bar/bar.docc/manual-updates.md b/Sources/bar/bar.docc/manual-updates.md
index 60520ca..c5157e5 100644
--- a/Sources/bar/bar.docc/manual-updates.md
+++ b/Sources/bar/bar.docc/manual-updates.md
@@ -10,10 +10,10 @@ This is done by posting a [Darwin notification](https://developer.apple.com/docu
Use `notifyutil` (bundled with macOS) to post a notification:
```shell
-notifyutil -p bar.touch.<name>
+notifyutil -p bar.touch.<block-name>
```
-Replace `<name>` with the block's name (e.g. `clock`, `battery`).
+Replace `<block-name>` with the block's name (e.g. `clock`, `battery`).
If multiple blocks share the same name, a single notification refreshes them all.
## Use cases