diff --git a/omarchy/README.md b/omarchy/README.md index 267c0f9..859c56c 100644 --- a/omarchy/README.md +++ b/omarchy/README.md @@ -108,13 +108,23 @@ leaves the lock unbranded rather than broken. The password field is restyled to match the AGS widgets: a 2px border and square corners in place of the shell's 3px rounded outline, an -`alpha(background, 0.6)` fill matching `.qs-tile`, and the `.theme-chip` -accent treatment - a translucent accent border while the field is empty that -goes solid once there is something in it, with `urgent` on a failed attempt. -Those come from `Color.accent`, `Color.background`, and `Color.urgent`, so the -field still follows a theme change; only the geometry and the alphas are fixed, -exactly as they are in `ags/style.css`. The `[lock]` tokens in a theme's -`shell.toml` no longer reach the border or the fill. +`alpha(background, 0.6)` fill matching `.qs-tile`, and the AGS border pair - +`alpha(color4, 0.5)` while the field is empty, going to a solid `accent` once +there is something in it, with `urgent` on a failed attempt. Only the geometry +and the alphas are fixed; the colors come from the active theme, so the field +follows a theme change the way the AGS widgets do. The `[lock]` tokens in a +theme's `shell.toml` no longer reach the border or the fill. + +`color4` needs reading from disk. The `Color` singleton resolves the palette +down to `foreground`, `background`, `accent`, `urgent`, and `muted`, and uses +`color4` only as the fallback when a theme declares no separate `accent` - so +the raw slot the AGS stylesheet borders with is not exposed anywhere. The +service parses it out of the active theme's `colors.toml` with the same regex +`Color.loadColors` uses. Stock `Color` reads that file once at startup and +takes runtime theme switches over IPC instead, but +`~/.local/state/omarchy/current/theme` is a real directory rewritten in place +rather than a swapped symlink, so watching the file is enough here. A palette +with no `color4` falls back to the accent. Unlike the other clones this one is load-bearing for security. The lock is a `service` plugin, so it is enabled by its id appearing in `plugins[]` and the diff --git a/omarchy/plugins/blob.lock/LockView.qml b/omarchy/plugins/blob.lock/LockView.qml index 63f604e..7620edf 100644 --- a/omarchy/plugins/blob.lock/LockView.qml +++ b/omarchy/plugins/blob.lock/LockView.qml @@ -9,6 +9,7 @@ Item { property string backgroundPath: "" property int backgroundVersion: 0 property string brandingText: "" + property string paletteColor4: "" property bool fingerprintConfigured: false property bool authenticatingPassword: false property string failureMessage: "" @@ -45,16 +46,18 @@ Item { readonly property bool showPasswordCursor: inputEnabled && !authenticatingPassword && failureMessage.length === 0 readonly property bool errorState: failureMessage.length > 0 - // An empty field reads as resting and a filled one as active, which is the - // .theme-chip treatment in ags/style.css: a translucent accent border that - // goes solid once the tile is in use. The spec is built here rather than - // read from the [lock] theme tokens, since those carry the shell's own - // heavier look. Color.accent and Color.background still follow the theme, - // so this tracks a theme change exactly like the AGS widgets do. + // The AGS border pair: containers rest on alpha(@color4, 0.5) and go to a + // solid @accent once in use. An empty field reads as resting and a filled + // one as active. The spec is built here rather than read from the [lock] + // theme tokens, since those carry the shell's own heavier look; the colors + // themselves still come from the active theme, so this follows a theme + // change exactly like the AGS widgets do. color4 falls back to the accent + // for a palette that does not define one. readonly property bool inputActive: passwordText.length > 0 || authenticatingPassword + readonly property color inputRestingBorder: paletteColor4.length > 0 ? paletteColor4 : Color.accent readonly property color inputBorderColor: errorState ? Color.urgent - : (inputActive ? Color.accent : Util.alpha(Color.accent, 0.6)) + : (inputActive ? Color.accent : Util.alpha(root.inputRestingBorder, 0.5)) readonly property color inputBackground: Util.alpha(Color.background, 0.6) readonly property var inputBorderSpec: Border.flat(root.inputBorderColor, root.outlineThickness) diff --git a/omarchy/plugins/blob.lock/Service.qml b/omarchy/plugins/blob.lock/Service.qml index 08649ac..6f228f7 100644 --- a/omarchy/plugins/blob.lock/Service.qml +++ b/omarchy/plugins/blob.lock/Service.qml @@ -16,6 +16,7 @@ Item { readonly property string userName: Quickshell.env("USER") || Quickshell.env("LOGNAME") readonly property string currentBackgroundLink: stateHome + "/omarchy/current/background" readonly property string brandingPath: home + "/.config/omarchy/branding/screensaver.txt" + readonly property string currentThemePath: stateHome + "/omarchy/current/theme" property bool lockRequested: false property bool pendingSessionLock: false @@ -31,6 +32,7 @@ Item { property string backgroundPath: "" property int backgroundVersion: 0 property string brandingText: "" + property string paletteColor4: "" property string lastEvent: "init" property string lastEventAt: "" property bool strandedLock: false @@ -273,6 +275,7 @@ Item { backgroundPath: root.backgroundPath backgroundVersion: root.backgroundVersion brandingText: root.brandingText + paletteColor4: root.paletteColor4 fingerprintConfigured: root.fingerprintConfigured authenticatingPassword: root.authenticatingPassword failureMessage: root.failureMessage @@ -304,6 +307,7 @@ Item { backgroundPath: root.backgroundPath backgroundVersion: root.backgroundVersion brandingText: root.brandingText + paletteColor4: root.paletteColor4 fingerprintConfigured: root.fingerprintConfigured authenticatingPassword: false failureMessage: "" @@ -485,6 +489,29 @@ Item { else armBlankTimer() } + // The Color singleton exposes only foreground, background, accent, urgent, + // and muted, so the raw color4 slot the AGS stylesheet borders with has to + // be read here. Same file and same shape Color itself parses; the current + // theme directory is a real directory rewritten in place on every theme + // change, so watching the file is enough to follow a theme switch. + function readPaletteColor4(raw) { + var lines = String(raw || "").split("\n") + for (var i = 0; i < lines.length; i++) { + var match = lines[i].match(/^\s*color4\s*=\s*["']?(#[0-9A-Fa-f]{6})/) + if (match) return match[1] + } + return "" + } + + FileView { + path: root.currentThemePath + "/colors.toml" + watchChanges: true + printErrors: false + onLoaded: root.paletteColor4 = root.readPaletteColor4(text()) + onLoadFailed: root.paletteColor4 = "" + onFileChanged: reload() + } + // The same file the screensaver paints. Watched so an edit through // `omarchy branding screensaver text` shows up on the next lock without a // shell restart. A missing file simply leaves the lock screen unbranded.