make Theme monitor dependent

This commit is contained in:
2026-07-12 15:59:04 +02:00
parent 19a8f09e5a
commit 0ff1664974
7 changed files with 72 additions and 64 deletions
+3 -2
View File
@@ -7,18 +7,19 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
private var observers: [IPCObserver] = [] private var observers: [IPCObserver] = []
/// Create one bar controller per screen. Each screen resolves its own /// Create one bar controller per screen. Each screen resolves its own
/// window and block set from the config, so refresh state and layout stay /// theme, window and block set from the config, so refresh state and layout stay
/// independent across monitors. /// independent across monitors.
init( init(
config: PHConfig, config: PHConfig,
screens: [NSScreen], screens: [NSScreen],
theme: PHTheme,
debug: Bool debug: Bool
) throws { ) throws {
super.init() super.init()
for screen in screens { for screen in screens {
let theme = try PHTheme.load(config.theme(for: screen))
let blocks = try PHBlock.load(config.blocks(for: screen)) let blocks = try PHBlock.load(config.blocks(for: screen))
controllers.append( controllers.append(
BarController( BarController(
config: config, config: config,
-2
View File
@@ -14,7 +14,6 @@ extension phbar {
mutating func run() throws { mutating func run() throws {
let config = try PHConfig.load() let config = try PHConfig.load()
let theme = try PHTheme.load("voltage")
// NOTE: Make sure NSApp.run() runs in the main thread // NOTE: Make sure NSApp.run() runs in the main thread
dispatchPrecondition(condition: .onQueue(.main)) dispatchPrecondition(condition: .onQueue(.main))
@@ -28,7 +27,6 @@ extension phbar {
let delegate = try AppDelegate( let delegate = try AppDelegate(
config: config, config: config,
screens: screens, screens: screens,
theme: theme,
debug: debug debug: debug
) )
let app = NSApplication.shared let app = NSApplication.shared
+3 -34
View File
@@ -1,43 +1,12 @@
struct PHConfig: Decodable { struct PHConfig: Decodable {
let theme: String
let window: String let window: String
let blocks: String? let blocks: String?
let env: [String: String]? let env: [String: String]?
let monitors: [String: PHMonitorOverride]? let monitors: [String: PHConfigMonitorOverride]?
private enum CodingKeys: String, CodingKey { private enum CodingKeys: String, CodingKey {
case window, blocks, env case theme, window, blocks, env
case monitors = "monitor" case monitors = "monitor"
} }
} }
/// A per-monitor entry from the config's `[monitor]` table.
///
/// Either field is optional; an unset field inherits the matching global
/// (`window` or `blocks`) so a monitor can override just one of the two.
struct PHMonitorOverride: Decodable {
let window: String?
let blocks: String?
}
extension PHConfig {
/// The override matching a screen identifier, if any.
/// Pure (no AppKit). Precedence: monitor name monitor index.
func monitorOverride(screenName: String, screenIndex: Int?) -> PHMonitorOverride? {
guard let monitors else { return nil }
if let byName = monitors[screenName] { return byName }
if let index = screenIndex, let byIndex = monitors[String(index)] { return byIndex }
return nil
}
/// Window definition name for a screen (pure resolver).
/// Override's `window` if set, else the global `window`.
func windowName(screenName: String, screenIndex: Int?) -> String {
monitorOverride(screenName: screenName, screenIndex: screenIndex)?.window ?? window
}
/// Block-set name for a screen (pure resolver).
/// Override's `blocks` if set, else the global `blocks` (default `"default"`).
func blocksName(screenName: String, screenIndex: Int?) -> String {
monitorOverride(screenName: screenName, screenIndex: screenIndex)?.blocks ?? (blocks ?? "default")
}
}
@@ -1,22 +0,0 @@
import AppKit
extension PHConfig {
/// The per-monitor override that applies to `screen`, if any.
/// Precedence: monitor name monitor index.
func monitorOverride(for screen: NSScreen) -> PHMonitorOverride? {
let index = NSScreen.screens.firstIndex(of: screen)
return monitorOverride(screenName: screen.localizedName, screenIndex: index)
}
/// Window definition name for `screen`: the override's `window` if set,
/// otherwise the global `window`.
func windowName(for screen: NSScreen) -> String {
monitorOverride(for: screen)?.window ?? window
}
/// Block-set name for `screen`: the override's `blocks` if set, otherwise
/// the global `blocks` (defaulting to `"default"`).
func blocks(for screen: NSScreen) -> String {
monitorOverride(for: screen)?.blocks ?? (blocks ?? "default")
}
}
@@ -0,0 +1,59 @@
import AppKit
/// A per-monitor entry from the config's `[monitor]` table.
///
/// Either field is optional; an unset field inherits the matching global
/// (`window` or `blocks`) so a monitor can override just one of the two.
struct PHConfigMonitorOverride: Decodable {
let theme: String?
let window: String?
let blocks: String?
}
extension PHConfig {
/// The override matching a screen identifier, if any.
/// Pure (no AppKit). Precedence: monitor name monitor index.
func monitorOverride(screenName: String, screenIndex: Int?) -> PHConfigMonitorOverride? {
guard let monitors else { return nil }
if let byName = monitors[screenName] { return byName }
if let index = screenIndex, let byIndex = monitors[String(index)] { return byIndex }
return nil
}
/// Window definition name for a screen (pure resolver).
/// Override's `window` if set, else the global `window`.
func windowName(screenName: String, screenIndex: Int?) -> String {
monitorOverride(screenName: screenName, screenIndex: screenIndex)?.window ?? window
}
/// Block-set name for a screen (pure resolver).
/// Override's `blocks` if set, else the global `blocks` (default `"default"`).
func blocksName(screenName: String, screenIndex: Int?) -> String {
monitorOverride(screenName: screenName, screenIndex: screenIndex)?.blocks ?? (blocks ?? "default")
}
/// The per-monitor override that applies to `screen`, if any.
/// Precedence: monitor name monitor index.
func monitorOverride(for screen: NSScreen) -> PHConfigMonitorOverride? {
let index = NSScreen.screens.firstIndex(of: screen)
return monitorOverride(screenName: screen.localizedName, screenIndex: index)
}
/// Window definition name for `screen`: the override's `window` if set,
/// otherwise the global `window`.
func windowName(for screen: NSScreen) -> String {
monitorOverride(for: screen)?.window ?? window
}
/// Block-set name for `screen`: the override's `blocks` if set, otherwise
/// the global `blocks` (defaulting to `"default"`).
func blocks(for screen: NSScreen) -> String {
monitorOverride(for: screen)?.blocks ?? (blocks ?? "default")
}
/// Theme name for `screen`: the override's `theme` if set, otherwise
/// the global `theme` (defaulting to `"default"`).
func theme(for screen: NSScreen) -> String {
monitorOverride(for: screen)?.theme ?? theme
}
}
+5 -1
View File
@@ -1,19 +1,23 @@
# Default window and block set for every monitor. # Default window and block set for every monitor.
# - theme: a named theme at ~/.config/phbar/themes/<name>.toml
# - window: a [[window]] definition from the theme file # - window: a [[window]] definition from the theme file
# - blocks: a named set at ~/.config/phbar/blocks/<name>.toml # - blocks: a named set at ~/.config/phbar/blocks/<name>.toml
theme = "default"
window = "default" window = "default"
blocks = "default" blocks = "default"
# Optional: override the window and/or block set per monitor. # Optional: override the theme, window, and/or block set per monitor.
# - quoted numeric key → NSScreen index # - quoted numeric key → NSScreen index
# - string key → NSScreen.localizedName (stable across replugs) # - string key → NSScreen.localizedName (stable across replugs)
# Precedence: monitor name → monitor index → the globals above. # Precedence: monitor name → monitor index → the globals above.
# Either field may be omitted to inherit its global value. # Either field may be omitted to inherit its global value.
# #
# [monitor."1"] # [monitor."1"]
# theme = "default"
# window = "bottom" # window = "bottom"
# blocks = "laptop" # blocks = "laptop"
# #
# [monitor."DELL U2723QE"] # [monitor."DELL U2723QE"]
# theme = "external"
# window = "clock" # window = "clock"
# blocks = "external" # blocks = "external"
+2 -3
View File
@@ -1,13 +1,12 @@
# phbar theme file ~ Voltage # phbar theme file
# #
# Place at ~/.config/phbar/themes/voltage.toml # Place at ~/.config/phbar/themes/default.toml
[[window]] [[window]]
name = "default" name = "default"
anchor = "top" anchor = "top"
height = 30 height = 30
width = "100%" width = "100%"
margin = { leading = 30, top = 30, trailing = 30, bottom = 30 }
[[window]] [[window]]
name = "bottom" name = "bottom"