fix(ui): #139 sheets size themselves; #141 waybar clicks stop reading the env
Some checks failed
Check / eval (push) Has been cancelled
Some checks failed
Check / eval (push) Has been cancelled
#139 — calcurse/doctor floated full-screen. Two faults stacked, which is why it looked like the float rules were dead: 1. Hyprland 0.55.4 silently ignores percentage `size` rules. Matrix on hardware (both orders, kitty memory off): `size 60% 65%` never applies, `size 1536 936` applies either way, configerrors empty both times. Rule order was a red herring. 2. Kitty defaults to remember_window_size=yes and replays the last OS window's size into every float — so after a tiled terminal, a sheet opens maximized. This is the Ghostty regression: Ghostty had no such memory, so fault 1 stayed invisible until #95. Fix: remember_window_size=no (floats must be deterministic) and the sheets ask for their own size — term-sheet.nix reads the focused monitor and hands kitty the px, because px in a rule cannot mean "a fraction of *this* screen" and one pair cannot serve 2560x1440 and the 1366x768 Acer (#131). Those windows keep float/center and deliberately carry no size rule. #141 — the updates click did nothing: whole-swaps hand-wrote `sh -c '$TERMINAL …'` and Waybar has no TERMINAL (home.sessionVariables → login shells only; the bar is spawned by Hyprland). Fixed at the root: `nomarchy-updates upgrade-window` opens its own window, so all five call sites name one env-free command and a theme file stops having an opinion about terminals. checks.waybar-swap-env guards the class. Bernardo asked mid-task for the update window to float — it is now the third caller of the sheet helper (com.nomarchy.updates, 45%x50%). V3 on the dev box: calendar 1536x936, doctor 1408x1008, updates 1152x720 — exactly the intended fractions, floating and centred; #141 driven under `env -i` with no TERMINAL, matching Waybar's real environment; the guard proven by reintroducing the bug. Acer V3 queued. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -211,66 +211,6 @@ scaled splash — the LUKS prompt especially, since a passphrase box half off
|
|||||||
the panel is the failure that matters. Pass = docked boot + shutdown centred
|
the panel is the failure that matters. Pass = docked boot + shutdown centred
|
||||||
on both heads; undocked unchanged.
|
on both heads; undocked unchanged.
|
||||||
|
|
||||||
### 139. Terminal floats open full-screen — % size rules are ignored, and Kitty remembers
|
|
||||||
|
|
||||||
Bernardo 2026-07-16: calcurse and nomarchy-doctor float but fill the screen —
|
|
||||||
the reduced size we had under Ghostty is gone. Reproduced and root-caused live
|
|
||||||
on the T14s (Hyprland 0.55.4, single 2560×1440 head), and it is **two** faults
|
|
||||||
stacked, which is why it looks like the float rules are dead when they are not:
|
|
||||||
|
|
||||||
1. **Percentage sizes silently no-op.** `com.nomarchy.calendar` came up
|
|
||||||
`floating=true` but `size=[2526,1360]` — the full work area, not the
|
|
||||||
`size 60% 65%` in `modules/home/hyprland.nix:1064`. A runtime rule with
|
|
||||||
**absolute** pixels (`size 1400 900`) applied perfectly and even centred
|
|
||||||
itself, so `size` works and the matcher works: it is the `%` form that this
|
|
||||||
Hyprland drops. No `hyprctl configerrors` — it fails silently, which is
|
|
||||||
how it survived the rule-syntax rewrite.
|
|
||||||
2. **Kitty remembers its last window size.** With the rule not applying,
|
|
||||||
nothing overrides Kitty's own request, and Kitty defaults to
|
|
||||||
`remember_window_size yes` — `~/.cache/kitty/main.json` literally holds
|
|
||||||
`{"window-size": [...]}` and is replayed into every new OS window. So the
|
|
||||||
float inherits whatever the last Kitty was, which after any tiled window is
|
|
||||||
~full-screen. **This is the Ghostty regression** (#95, Kitty-only): Ghostty
|
|
||||||
kept no such memory, so fault 1 was invisible — fault 2 exposed it.
|
|
||||||
|
|
||||||
Both need fixing, and fixing either alone is a trap: absolute pixels alone
|
|
||||||
stop being right on the 1366-wide Acer (#131's machine) or any scaled head,
|
|
||||||
and pinning Kitty alone leaves the `%` rules rotting for the next window we
|
|
||||||
float. Likely shape: `-o remember_window_size=no` (plus
|
|
||||||
`initial_window_width/height`) in the `nomarchy-calendar` / doctor launchers
|
|
||||||
so Kitty stops fighting us, and either the working syntax for `%` or a
|
|
||||||
documented note that this Hyprland wants absolute px. Affects every rule using
|
|
||||||
`%` — today calendar (`:1064`) and doctor (`:1070`). Pass = both sheets open
|
|
||||||
centred at their intended fraction on the dev box **and** on the Acer.
|
|
||||||
|
|
||||||
_(My probes wrote `{"window-size": [1400, 900]}` into your Kitty cache — it is
|
|
||||||
a self-updating cache, harmless, and any resize overwrites it.)_
|
|
||||||
|
|
||||||
### 141. Waybar's update module is dead in the whole-swap themes (`$TERMINAL` is unset)
|
|
||||||
|
|
||||||
Bernardo 2026-07-16: clicking the Waybar updates module does nothing.
|
|
||||||
Confirmed live and it is a **Waybar parity break** (CONVENTIONS § whole-swaps),
|
|
||||||
not an updates bug. The generated module bakes the terminal in —
|
|
||||||
`"${config.nomarchy.terminal} -e nomarchy-updates upgrade"`
|
|
||||||
(`modules/home/waybar.nix:356`) — but the four whole-swap themes hand-write
|
|
||||||
`"sh -c '$TERMINAL -e nomarchy-updates upgrade'"`, and **Waybar's environment
|
|
||||||
has no `TERMINAL`**: its 55 vars contain zero matches (pid 1688, `/proc/*/environ`).
|
|
||||||
`TERMINAL` is a `home.sessionVariables` entry (`modules/home/default.nix:104`),
|
|
||||||
so login shells get it and the Hyprland-spawned bar does not. The click expands
|
|
||||||
to `sh -c ' -e nomarchy-updates upgrade'` → nothing, no error, no toast. You
|
|
||||||
are on **boreal**, a whole-swap, which is why you see it.
|
|
||||||
|
|
||||||
Affected, one line each: `themes/{boreal,summer-day,summer-night,executive-slate}/waybar.jsonc`
|
|
||||||
(`custom/updates.on-click` — grep says this is the *only* `$TERMINAL` use left
|
|
||||||
in any whole-swap, so the blast radius is exactly these 4 lines). Fix = drop
|
|
||||||
the env dependency the way calendar/doctor already do — name `kitty` outright,
|
|
||||||
Kitty being sole supported since #95 — or, better and one place instead of
|
|
||||||
five, give `nomarchy-updates` a subcommand that opens its own terminal so
|
|
||||||
every caller stops needing `$TERMINAL`. Worth a check against the class of
|
|
||||||
bug, not the instance: nothing today asserts that a whole-swap's on-click
|
|
||||||
survives Waybar's actual environment, so the next hand-written jsonc can
|
|
||||||
reintroduce it silently.
|
|
||||||
|
|
||||||
### 142. A rebuild while docked undoes dock mode (the panel comes back, a workspace jumps to it)
|
### 142. A rebuild while docked undoes dock mode (the panel comes back, a workspace jumps to it)
|
||||||
|
|
||||||
Bernardo 2026-07-16: every rebuild while docked lands in the undocked state —
|
Bernardo 2026-07-16: every rebuild while docked lands in the undocked state —
|
||||||
|
|||||||
@@ -531,6 +531,14 @@ Everything else below stays open; order is convenience, not a gate.
|
|||||||
proves the menu row + flow renders; a real capsule write is
|
proves the menu row + flow renders; a real capsule write is
|
||||||
hardware-only.)
|
hardware-only.)
|
||||||
|
|
||||||
|
## Acer Aspire M5-481T only (1366×768 — the narrow-panel case)
|
||||||
|
- [ ] **#139 sheets on a small panel** — Waybar clock → calendar, System ▸
|
||||||
|
Doctor, and the Waybar updates click. Pass = each opens floating and
|
||||||
|
centred at roughly 60%×65% / 55%×70% / 45%×50% of *that* screen (they are
|
||||||
|
computed from the focused monitor now, so this is checking the fallback
|
||||||
|
path and the font, not the arithmetic), fully on-screen, none clipped by
|
||||||
|
the bar. Dev box (2560×1440) already measured exact.
|
||||||
|
|
||||||
## Latitude 5310 / 5410 only
|
## Latitude 5310 / 5410 only
|
||||||
- [ ] **v1 QA batch on-hardware pass** (583708d batch was QEMU-verified) —
|
- [ ] **v1 QA batch on-hardware pass** (583708d batch was QEMU-verified) —
|
||||||
general smoke before the next `main → v1` promotion (broader than
|
general smoke before the next `main → v1` promotion (broader than
|
||||||
|
|||||||
@@ -19,6 +19,34 @@ Template:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-07-16 — #139 + #141: the quick ones from the T14s round
|
||||||
|
- **Task:** #139 (terminal sheets open full-screen) and #141 (Waybar updates
|
||||||
|
click does nothing) — Bernardo: "let's do the quick ones first".
|
||||||
|
- **Did:** #139 was two faults: Hyprland 0.55.4 ignores **percentage** `size`
|
||||||
|
rules (clean matrix on hardware: both orders, Kitty memory off — px applies,
|
||||||
|
% never does, no configerror), and Kitty replays its remembered window size
|
||||||
|
into every float. Fix: `remember_window_size no` + a shared
|
||||||
|
`modules/home/term-sheet.nix` that reads the focused monitor and hands Kitty
|
||||||
|
the px, so the % intent survives without a rule; the size rules are gone.
|
||||||
|
#141: whole-swaps used `$TERMINAL`, which Waybar's env does not have →
|
||||||
|
`nomarchy-updates upgrade-window` opens its own window, all 5 call sites are
|
||||||
|
env-free, `checks.waybar-swap-env` guards the class. Bernardo asked mid-task
|
||||||
|
for the update window to float too → third caller of the sheet helper.
|
||||||
|
- **Verified:** V0 `nix flake check --no-build`. **V3 on the dev box:** built
|
||||||
|
the HM package with `--override-input`, drove the real launchers — calendar
|
||||||
|
1536×936 (=60%×65%), doctor 1408×1008 (=55%×70%), updates 1152×720
|
||||||
|
(=45%×50%), all floating + centred in the work area. #141 tested the way it
|
||||||
|
actually fails: `env -i` with no `TERMINAL` (matching Waybar's real env) →
|
||||||
|
window opens. Guard proven by reintroducing the bug: it fails with the
|
||||||
|
offending file/module/key named.
|
||||||
|
- **Pending:** Acer (1366×768) V3 queued — the sheets are monitor-relative now,
|
||||||
|
so it should hold by construction, which is exactly why it is worth one look.
|
||||||
|
#131 is **live on 2560** per Bernardo, so its "only at 1366" model is wrong —
|
||||||
|
next up.
|
||||||
|
- **Next suggestion:** #131 (recovery labels truncating on a wide panel —
|
||||||
|
observed, so the measurement in that item is what needs re-doing), then #137
|
||||||
|
(plymouth per-head) or #142 (rebuild-while-docked).
|
||||||
|
|
||||||
## 2026-07-16 — #138 dock audio: the graph restart was the bug (44aac0f + this)
|
## 2026-07-16 — #138 dock audio: the graph restart was the bug (44aac0f + this)
|
||||||
- **Task:** #138 — Meet "no mic or speakers" in Chromium; Zoom fine; no repro
|
- **Task:** #138 — Meet "no mic or speakers" in Chromium; Zoom fine; no repro
|
||||||
on a fresh boot. Bernardo's hypothesis (pipewire restarts → Chromium never
|
on a fresh boot. Bernardo's hypothesis (pipewire restarts → Chromium never
|
||||||
|
|||||||
@@ -427,6 +427,47 @@ Design/decision records and a running log of shipped work (items marked
|
|||||||
default `$TERMINAL` / SUPER+Return, doctor + calendar + what-changed use
|
default `$TERMINAL` / SUPER+Return, doctor + calendar + what-changed use
|
||||||
`kitty --class=com.nomarchy.*`. Ghostty module and install-time GL probe
|
`kitty --class=com.nomarchy.*`. Ghostty module and install-time GL probe
|
||||||
removed. V3: Acer SUPER+Return + doctor float.
|
removed. V3: Acer SUPER+Return + doctor float.
|
||||||
|
- ✓ **The floating sheets got their size back (#139, 2026-07-16):** Bernardo:
|
||||||
|
calcurse and the doctor sheet float, but full-screen — the reduced size
|
||||||
|
Ghostty used to give them was gone. Two independent faults, stacked, which
|
||||||
|
is why it read as "the float rules are dead" when they were not.
|
||||||
|
**(1)** Hyprland 0.55.4 silently ignores a *percentage* `size` rule. Matrix
|
||||||
|
on hardware, both rule orders, Kitty's memory disabled so nothing could mask
|
||||||
|
it: `size 60% 65%` never applies, `size 1536 936` applies in either order,
|
||||||
|
and `hyprctl configerrors` is empty both ways — which is how it slipped
|
||||||
|
through the post-0.53 rule rewrite. Order turned out to be a red herring.
|
||||||
|
**(2)** Kitty defaults to `remember_window_size yes` and replays the last OS
|
||||||
|
window's size (`~/.cache/kitty/main.json`) into the next one, so with (1)
|
||||||
|
applying nothing, every sheet inherited whatever the last terminal was —
|
||||||
|
after a tiled one, the whole screen. **This is the Ghostty regression**: it
|
||||||
|
kept no such memory, so (1) was invisible until #95 made Kitty the only
|
||||||
|
terminal. Fix: `remember_window_size no` (floats must be deterministic; the
|
||||||
|
compositor sizes tiled windows anyway) and the sheets now ask for their own
|
||||||
|
size — `modules/home/term-sheet.nix` reads the focused monitor and hands
|
||||||
|
Kitty the px, because px in a rule cannot mean "a fraction of *this* screen"
|
||||||
|
and one pair cannot serve a 2560×1440 desk monitor and the 1366×768 Acer
|
||||||
|
(#131). Those windows therefore carry float/center rules and deliberately no
|
||||||
|
`size` rule. Measured after: calendar 1536×936 = exactly 60%×65%, doctor
|
||||||
|
1408×1008 = 55%×70%, both centred in the Waybar work area.
|
||||||
|
- ✓ **Waybar whole-swap on-clicks lost their environment (#141, 2026-07-16):**
|
||||||
|
clicking the updates module did nothing. Not an updates bug — a **parity**
|
||||||
|
break: the generated module bakes the terminal in at eval time, but the four
|
||||||
|
whole-swaps hand-wrote `sh -c '$TERMINAL -e nomarchy-updates upgrade'`, and
|
||||||
|
Waybar has no `TERMINAL`. It is a `home.sessionVariables` entry, so login
|
||||||
|
shells get it and the Hyprland-spawned bar does not; the click expanded to
|
||||||
|
`sh -c ' -e nomarchy-updates upgrade'` and failed silently, with no error and
|
||||||
|
no toast. Fix at the root rather than in five places: `nomarchy-updates
|
||||||
|
upgrade-window` opens its own terminal, so every caller names one env-free
|
||||||
|
command and a *theme* file stops having an opinion about terminals.
|
||||||
|
`checks.waybar-swap-env` guards the class — no whole-swap `exec`/`on-click`
|
||||||
|
may read an env var (`$name`; `$1` positionals stay legal) — and was proven
|
||||||
|
by reintroducing the bug and watching it fail. The lesson generalises past
|
||||||
|
Waybar: **anything Hyprland spawns has no login shell**, so a hand-written
|
||||||
|
command that works in your terminal proves nothing about the bar. Bernardo
|
||||||
|
asked for the window to be a small float while this was in flight, so it is
|
||||||
|
a classed sheet (`com.nomarchy.updates`, 45%×50%) like the calendar and
|
||||||
|
doctor — the third caller of #139's helper, which is what made it a one-line
|
||||||
|
ask rather than a fourth copy of the sizing logic.
|
||||||
- ✓ **GTK dialog button labels (#98):** Stylix always set `gtk-theme-name=
|
- ✓ **GTK dialog button labels (#98):** Stylix always set `gtk-theme-name=
|
||||||
adw-gtk3` (light sheet) while recoloring tokens for dark palettes — light
|
adw-gtk3` (light sheet) while recoloring tokens for dark palettes — light
|
||||||
sheet hardcodes near-black button text → black-on-dark in GTK dialogs
|
sheet hardcodes near-black button text → black-on-dark in GTK dialogs
|
||||||
|
|||||||
42
flake.nix
42
flake.nix
@@ -1431,6 +1431,48 @@
|
|||||||
in
|
in
|
||||||
assert ok; pkgs.runCommand "nomarchy-waybar-language" { } "touch $out";
|
assert ok; pkgs.runCommand "nomarchy-waybar-language" { } "touch $out";
|
||||||
|
|
||||||
|
# A whole-swap's commands must not read the session environment.
|
||||||
|
# Waybar is spawned by Hyprland and never sources a login shell, so
|
||||||
|
# `home.sessionVariables` (TERMINAL, EDITOR …) simply are not there:
|
||||||
|
# the on-click expands to nothing, the click does nothing, and there
|
||||||
|
# is no error to notice (#141 — it went unseen because only the
|
||||||
|
# whole-swap themes hand-write these; the generated module bakes the
|
||||||
|
# value at eval time and cannot regress). Guards the class: the next
|
||||||
|
# hand-written jsonc reaching for an env var fails here instead.
|
||||||
|
waybar-swap-env =
|
||||||
|
let
|
||||||
|
inherit (nixpkgs) lib;
|
||||||
|
expect = cond: msg: lib.assertMsg cond "waybar-swap-env: ${msg}";
|
||||||
|
swaps = lib.filter
|
||||||
|
(n: builtins.pathExists (./themes + "/${n}/waybar.jsonc"))
|
||||||
|
(builtins.attrNames (builtins.readDir ./themes));
|
||||||
|
# `$1`/`$2` (awk, sh positionals) are fine — a *name* after the
|
||||||
|
# sigil is what marks an environment read.
|
||||||
|
readsEnv = s: builtins.match ".*\\$[A-Za-z_{].*" s != null;
|
||||||
|
isCmdKey = k:
|
||||||
|
lib.hasPrefix "on-click" k || lib.hasPrefix "on-scroll" k
|
||||||
|
|| k == "exec" || k == "exec-if";
|
||||||
|
offendersIn = name:
|
||||||
|
let bar = builtins.fromJSON (builtins.readFile (./themes + "/${name}/waybar.jsonc"));
|
||||||
|
in lib.concatMap (mod:
|
||||||
|
let m = bar.${mod}; in
|
||||||
|
if !builtins.isAttrs m then [ ] else
|
||||||
|
lib.concatMap (k:
|
||||||
|
let v = m.${k}; in
|
||||||
|
if isCmdKey k && builtins.isString v && readsEnv v
|
||||||
|
then [ "${name}: ${mod}.${k} = ${v}" ] else [ ])
|
||||||
|
(builtins.attrNames m))
|
||||||
|
(builtins.attrNames bar);
|
||||||
|
offenders = lib.concatMap offendersIn swaps;
|
||||||
|
ok =
|
||||||
|
expect (swaps != [ ])
|
||||||
|
"fixture drift: no theme ships a waybar.jsonc — the guard is checking nothing"
|
||||||
|
&& expect (offenders == [ ])
|
||||||
|
("a whole-swap command reads the environment, which Waybar does not have: "
|
||||||
|
+ lib.concatStringsSep "; " offenders);
|
||||||
|
in
|
||||||
|
assert ok; pkgs.runCommand "nomarchy-waybar-swap-env" { } "touch $out";
|
||||||
|
|
||||||
# Docking artifact guard: default/no-profile Home Manager output
|
# Docking artifact guard: default/no-profile Home Manager output
|
||||||
# must still launch both hotplug watchers, put Rofi on the focused
|
# must still launch both hotplug watchers, put Rofi on the focused
|
||||||
# monitor, expose the manual keyboard picker, and never ship the
|
# monitor, expose the manual keyboard picker, and never ship the
|
||||||
|
|||||||
@@ -1060,16 +1060,22 @@ in
|
|||||||
|
|
||||||
# Calendar popup (item 42): nomarchy-calendar → calcurse in a
|
# Calendar popup (item 42): nomarchy-calendar → calcurse in a
|
||||||
# kitty window tagged with a distinct --class, so it floats centered.
|
# kitty window tagged with a distinct --class, so it floats centered.
|
||||||
|
# No `size` rule on purpose: a percentage one is silently ignored here
|
||||||
|
# (#139, measured on hardware — see term-sheet.nix), and px cannot mean
|
||||||
|
# "a fraction of *this* monitor". The launcher sizes the window itself.
|
||||||
"float 1, match:class ^(com\\.nomarchy\\.calendar)$"
|
"float 1, match:class ^(com\\.nomarchy\\.calendar)$"
|
||||||
"size 60% 65%, match:class ^(com\\.nomarchy\\.calendar)$"
|
|
||||||
"center 1, match:class ^(com\\.nomarchy\\.calendar)$"
|
"center 1, match:class ^(com\\.nomarchy\\.calendar)$"
|
||||||
|
|
||||||
# Doctor sheet (System › Doctor / Waybar custom/doctor click):
|
# Doctor sheet (System › Doctor / Waybar custom/doctor click):
|
||||||
# nomarchy-menu doctor → kitty --class=com.nomarchy.doctor.
|
# nomarchy-menu doctor → nomarchy-term-sheet, sized the same way.
|
||||||
"float 1, match:class ^(com\\.nomarchy\\.doctor)$"
|
"float 1, match:class ^(com\\.nomarchy\\.doctor)$"
|
||||||
"size 55% 70%, match:class ^(com\\.nomarchy\\.doctor)$"
|
|
||||||
"center 1, match:class ^(com\\.nomarchy\\.doctor)$"
|
"center 1, match:class ^(com\\.nomarchy\\.doctor)$"
|
||||||
|
|
||||||
|
# Upgrade prompt (Waybar custom/updates click → nomarchy-updates
|
||||||
|
# upgrade-window): the same classed sheet, smaller — it is a y/N flow.
|
||||||
|
"float 1, match:class ^(com\\.nomarchy\\.updates)$"
|
||||||
|
"center 1, match:class ^(com\\.nomarchy\\.updates)$"
|
||||||
|
|
||||||
# Polkit auth (hyprpolkitagent — app id / binary name in the package)
|
# Polkit auth (hyprpolkitagent — app id / binary name in the package)
|
||||||
# and pinentry-qt (keys.nix default; org.gnupg.pinentry-qt desktop).
|
# and pinentry-qt (keys.nix default; org.gnupg.pinentry-qt desktop).
|
||||||
# workspace current: agent was started on ws1 at login; without this
|
# workspace current: agent was started on ws1 at login; without this
|
||||||
|
|||||||
@@ -47,6 +47,14 @@ in
|
|||||||
wayland_titlebar_color = lib.mkDefault "background";
|
wayland_titlebar_color = lib.mkDefault "background";
|
||||||
# Fresh windows for doctor/calendar --class launches (not one shared instance).
|
# Fresh windows for doctor/calendar --class launches (not one shared instance).
|
||||||
single_instance = lib.mkDefault false;
|
single_instance = lib.mkDefault false;
|
||||||
|
# Kitty's default is to remember the last OS window's size and replay it
|
||||||
|
# into the next one (~/.cache/kitty/main.json). Harmless while tiled —
|
||||||
|
# the compositor sizes those — but every *floating* kitty then inherits
|
||||||
|
# whatever the last window happened to be, so a sheet opened after a
|
||||||
|
# maximized terminal opens maximized (#139: the Ghostty regression, which
|
||||||
|
# kept no such memory). Floats should be deterministic: each launcher
|
||||||
|
# asks for the size it wants.
|
||||||
|
remember_window_size = lib.mkDefault false;
|
||||||
} // colorSettings);
|
} // colorSettings);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ let
|
|||||||
cfg = config.nomarchy;
|
cfg = config.nomarchy;
|
||||||
t = cfg.theme;
|
t = cfg.theme;
|
||||||
c = t.colors;
|
c = t.colors;
|
||||||
|
termSheet = import ./term-sheet.nix { inherit pkgs; };
|
||||||
inherit (config.lib.formats.rasi) mkLiteral;
|
inherit (config.lib.formats.rasi) mkLiteral;
|
||||||
|
|
||||||
px = n: mkLiteral "${toString n}px";
|
px = n: mkLiteral "${toString n}px";
|
||||||
@@ -1043,9 +1044,10 @@ ${themeRows}
|
|||||||
doctor)
|
doctor)
|
||||||
# Read-only health sheet in a floating, centered kitty window
|
# Read-only health sheet in a floating, centered kitty window
|
||||||
# (class matched by hyprland.nix windowrules). Same pattern as
|
# (class matched by hyprland.nix windowrules). Same pattern as
|
||||||
# nomarchy-calendar. Exit code doesn't matter; the sheet is the product.
|
# nomarchy-calendar, sizing itself for the same reason (#139).
|
||||||
exec kitty --class=com.nomarchy.doctor \
|
# Exit code doesn't matter; the sheet is the product.
|
||||||
-e sh -c "nomarchy-doctor
|
exec ${termSheet}/bin/nomarchy-term-sheet com.nomarchy.doctor 55 70 \
|
||||||
|
sh -c "nomarchy-doctor
|
||||||
printf '\nEnter to close.'; read -r _" ;;
|
printf '\nEnter to close.'; read -r _" ;;
|
||||||
|
|
||||||
firmware)
|
firmware)
|
||||||
|
|||||||
52
modules/home/term-sheet.nix
Normal file
52
modules/home/term-sheet.nix
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Shared launcher for the floating terminal sheets (#139). Used by waybar.nix
|
||||||
|
# (nomarchy-calendar) and rofi.nix (the doctor sheet) — the classed Kitty
|
||||||
|
# windows hyprland.nix floats and centers.
|
||||||
|
#
|
||||||
|
# Why the size lives here and not in a window rule: Hyprland 0.55.4 silently
|
||||||
|
# ignores a *percentage* `size` rule. Measured on hardware 2026-07-16, both
|
||||||
|
# rule orders, Kitty's own memory disabled so nothing could mask it:
|
||||||
|
# `size 60% 65%` → the window keeps its requested size (no rule applied);
|
||||||
|
# `size 1536 936` → lands exactly, in either order. No `hyprctl configerrors`
|
||||||
|
# either way, which is how it survived the post-0.53 rule rewrite unnoticed.
|
||||||
|
#
|
||||||
|
# Absolute px is not a fix: "a fraction of the screen" is the whole intent, and
|
||||||
|
# one px pair cannot serve a 2560x1440 desk monitor and the 1366x768 Acer that
|
||||||
|
# is live QA (#131). A rule cannot compute it — the monitor is unknown at
|
||||||
|
# eval time — so the sheet asks for its own size instead: read the focused
|
||||||
|
# monitor here, hand Kitty the px, and let it request them. Those windows
|
||||||
|
# therefore carry float/center rules and deliberately no `size` rule.
|
||||||
|
{ pkgs }:
|
||||||
|
|
||||||
|
pkgs.writeShellScriptBin "nomarchy-term-sheet" ''
|
||||||
|
set -u
|
||||||
|
# usage: nomarchy-term-sheet <class> <width%> <height%> <cmd> [args...]
|
||||||
|
[ "$#" -ge 4 ] || { echo "usage: nomarchy-term-sheet <class> <w%> <h%> <cmd> [args...]" >&2; exit 64; }
|
||||||
|
cls="$1"; wpct="$2"; hpct="$3"; shift 3
|
||||||
|
|
||||||
|
# Hyprland reports the monitor in physical px plus the scale it renders at;
|
||||||
|
# Kitty sizes in logical px, so divide before taking the fraction. A sheet
|
||||||
|
# that opens at a clumsy size still beats no sheet, so every failure here
|
||||||
|
# falls back rather than exits: no compositor (a TTY run), no jq answer, or
|
||||||
|
# a nonsense answer all land on a size that fits the smallest panel we ship
|
||||||
|
# on.
|
||||||
|
dims=$(hyprctl monitors -j 2>/dev/null \
|
||||||
|
| ${pkgs.jq}/bin/jq -r --argjson w "$wpct" --argjson h "$hpct" '
|
||||||
|
[ .[] | select(.focused) ][0]
|
||||||
|
| select(. != null)
|
||||||
|
| (.scale // 1) as $s
|
||||||
|
| select($s > 0)
|
||||||
|
| "\((.width / $s * $w / 100) | floor) \((.height / $s * $h / 100) | floor)"' 2>/dev/null) || dims=
|
||||||
|
width=''${dims%% *}
|
||||||
|
height=''${dims##* }
|
||||||
|
case "$width$height" in
|
||||||
|
*[!0-9]*|"") width=800; height=500 ;;
|
||||||
|
esac
|
||||||
|
[ "$width" -ge 320 ] 2>/dev/null || width=800
|
||||||
|
[ "$height" -ge 240 ] 2>/dev/null || height=500
|
||||||
|
|
||||||
|
exec ${pkgs.kitty}/bin/kitty \
|
||||||
|
-o remember_window_size=no \
|
||||||
|
-o initial_window_width="$width" \
|
||||||
|
-o initial_window_height="$height" \
|
||||||
|
--class="$cls" -e "$@"
|
||||||
|
''
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.nomarchy.updates;
|
cfg = config.nomarchy.updates;
|
||||||
|
termSheet = import ./term-sheet.nix { inherit pkgs; };
|
||||||
|
|
||||||
nomarchy-updates = pkgs.writeShellScriptBin "nomarchy-updates" ''
|
nomarchy-updates = pkgs.writeShellScriptBin "nomarchy-updates" ''
|
||||||
set -u
|
set -u
|
||||||
@@ -113,7 +114,23 @@ let
|
|||||||
fi
|
fi
|
||||||
"$0" check
|
"$0" check
|
||||||
echo "Done — press enter."; read -r _ || true ;;
|
echo "Done — press enter."; read -r _ || true ;;
|
||||||
*) echo "usage: nomarchy-updates [check|status|upgrade]" >&2; exit 64 ;;
|
upgrade-window)
|
||||||
|
# The Waybar click target. `upgrade` prompts, so it needs a terminal —
|
||||||
|
# and the bar has none: it is spawned by Hyprland, whose environment has
|
||||||
|
# no $TERMINAL (that is a home.sessionVariables entry, so only login
|
||||||
|
# shells see it). A whole-swap's hand-written on-click that reached for
|
||||||
|
# $TERMINAL expanded to nothing and the click silently did nothing
|
||||||
|
# (#141). Opening our own window is the fix that cannot rot: every
|
||||||
|
# caller — generated module and whole-swap alike — names one env-free
|
||||||
|
# command, and a theme file stops having an opinion about terminals.
|
||||||
|
#
|
||||||
|
# A classed sheet like the calendar and doctor: a short y/N flow has no
|
||||||
|
# business taking the whole screen, and the class is what hyprland.nix
|
||||||
|
# floats it by. Smaller than either (45%x50%) — this is a prompt, not a
|
||||||
|
# document.
|
||||||
|
exec ${termSheet}/bin/nomarchy-term-sheet com.nomarchy.updates 45 50 \
|
||||||
|
"$0" upgrade ;;
|
||||||
|
*) echo "usage: nomarchy-updates [check|status|upgrade|upgrade-window]" >&2; exit 64 ;;
|
||||||
esac
|
esac
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
let
|
let
|
||||||
t = config.nomarchy.theme;
|
t = config.nomarchy.theme;
|
||||||
|
termSheet = import ./term-sheet.nix { inherit pkgs; };
|
||||||
|
|
||||||
# Whether the keyboard-layout indicator is worth bar space, and the filter
|
# Whether the keyboard-layout indicator is worth bar space, and the filter
|
||||||
# that holds a whole-swap to the same answer. Contract + rationale (and
|
# that holds a whole-swap to the same answer. Contract + rationale (and
|
||||||
@@ -95,13 +96,14 @@ let
|
|||||||
|
|
||||||
# Opens calcurse (lightweight TUI calendar) in a floating, centered kitty
|
# Opens calcurse (lightweight TUI calendar) in a floating, centered kitty
|
||||||
# window — Waybar clock on-click. Distinct --class → hyprland.nix float
|
# window — Waybar clock on-click. Distinct --class → hyprland.nix float
|
||||||
# rules. Kitty is always installed (kitty.nix).
|
# rules. Kitty is always installed (kitty.nix). The sheet sizes itself
|
||||||
|
# (#139: a percentage `size` rule is silently ignored) — see term-sheet.nix.
|
||||||
calendarLauncher = pkgs.writeShellScriptBin "nomarchy-calendar" ''
|
calendarLauncher = pkgs.writeShellScriptBin "nomarchy-calendar" ''
|
||||||
if ! command -v calcurse >/dev/null 2>&1; then
|
if ! command -v calcurse >/dev/null 2>&1; then
|
||||||
notify-send "Calendar" "calcurse isn't installed (removed from home.packages?)." 2>/dev/null
|
notify-send "Calendar" "calcurse isn't installed (removed from home.packages?)." 2>/dev/null
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
exec kitty --class=com.nomarchy.calendar -e calcurse
|
exec ${termSheet}/bin/nomarchy-term-sheet com.nomarchy.calendar 60 65 calcurse
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# VPN indicator — shows a shield when a NetworkManager VPN/WireGuard
|
# VPN indicator — shows a shield when a NetworkManager VPN/WireGuard
|
||||||
@@ -353,7 +355,7 @@ let
|
|||||||
return-type = "json";
|
return-type = "json";
|
||||||
interval = 1800;
|
interval = 1800;
|
||||||
signal = 9;
|
signal = 9;
|
||||||
on-click = "${config.nomarchy.terminal} -e nomarchy-updates upgrade";
|
on-click = "nomarchy-updates upgrade-window";
|
||||||
};
|
};
|
||||||
|
|
||||||
# swaync notification bell + Do-Not-Disturb state. `-swb` streams JSON
|
# swaync notification bell + Do-Not-Disturb state. `-swb` streams JSON
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
"interval": 1800,
|
"interval": 1800,
|
||||||
"signal": 9,
|
"signal": 9,
|
||||||
"exec": "nomarchy-updates status",
|
"exec": "nomarchy-updates status",
|
||||||
"on-click": "sh -c '$TERMINAL -e nomarchy-updates upgrade'"
|
"on-click": "nomarchy-updates upgrade-window"
|
||||||
},
|
},
|
||||||
"custom/doctor": {
|
"custom/doctor": {
|
||||||
"return-type": "json",
|
"return-type": "json",
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
"interval": 1800,
|
"interval": 1800,
|
||||||
"signal": 9,
|
"signal": 9,
|
||||||
"exec": "nomarchy-updates status",
|
"exec": "nomarchy-updates status",
|
||||||
"on-click": "sh -c '$TERMINAL -e nomarchy-updates upgrade'"
|
"on-click": "nomarchy-updates upgrade-window"
|
||||||
},
|
},
|
||||||
"pulseaudio": {
|
"pulseaudio": {
|
||||||
"scroll-step": 5,
|
"scroll-step": 5,
|
||||||
|
|||||||
@@ -146,7 +146,7 @@
|
|||||||
"interval": 1800,
|
"interval": 1800,
|
||||||
"signal": 9,
|
"signal": 9,
|
||||||
"exec": "nomarchy-updates status",
|
"exec": "nomarchy-updates status",
|
||||||
"on-click": "sh -c '$TERMINAL -e nomarchy-updates upgrade'"
|
"on-click": "nomarchy-updates upgrade-window"
|
||||||
},
|
},
|
||||||
"custom/notification": {
|
"custom/notification": {
|
||||||
"format": "{icon}",
|
"format": "{icon}",
|
||||||
|
|||||||
@@ -145,7 +145,7 @@
|
|||||||
"interval": 1800,
|
"interval": 1800,
|
||||||
"signal": 9,
|
"signal": 9,
|
||||||
"exec": "nomarchy-updates status",
|
"exec": "nomarchy-updates status",
|
||||||
"on-click": "sh -c '$TERMINAL -e nomarchy-updates upgrade'"
|
"on-click": "nomarchy-updates upgrade-window"
|
||||||
},
|
},
|
||||||
"custom/notification": {
|
"custom/notification": {
|
||||||
"format": "{icon}",
|
"format": "{icon}",
|
||||||
|
|||||||
Reference in New Issue
Block a user