Skip to content

General improvements and refactoring - #52

Open
RAPSNX wants to merge 72 commits into
mainfrom
zionos
Open

General improvements and refactoring#52
RAPSNX wants to merge 72 commits into
mainfrom
zionos

Conversation

@RAPSNX

@RAPSNX RAPSNX commented Jun 24, 2026

Copy link
Copy Markdown
Owner

No description provided.

RAPSNX added 16 commits July 22, 2026 20:48
Adds gaps.inner/outer, window/floating border width, sway-input(5)
keyboard settings, and window-rules (assigns for firefox/chromium
workspaces, floating criteria for steam/nextcloud) -- all direct sway
equivalents of the corresponding Hyprland settings. Also wires waybar's
systemd target and disables sway's own default i3status bar and
catppuccin theming, matching how Hyprland is already configured.
Mirrors hypridle/hyprlock's lock-on-timeout + DPMS-off-on-timeout
behavior, gated on either sway or niri being enabled. Implemented as a
single shared module rather than one copy per compositor: both can be
enabled simultaneously as separate selectable sessions, and duplicating
services.swayidle.timeouts per compositor would double-register the
same timeout list. The DPMS command detects which compositor is
actually running at fire time (swaymsg vs niri msg), since both can be
installed at once even though only one runs.

One accepted gap, not a workaround: hyprlock's live blurred-screenshot
background has no swaylock equivalent (static image/color only), so
this falls back to a solid catppuccin-flavored color.
…land

Adds layout.gaps/border, niri's native window-open animations (default,
no config needed) and geometry-corner-radius (a real niri feature, unlike
sway which needs the SwayFX fork for either) for Hyprland's
decoration.rounding equivalent, input.keyboard/mouse settings, and
window-rules for steam/nextcloud floating.

Firefox/Chromium placement on the secondary monitor is a static
open-on-output rule hardcoded to firefly's real secondary from the
home-firefly kanshi profile. This was originally meant to be a kanshi-
managed dynamic include file, but niri-flake's homeModules.config
hardcodes its generated config's file target internally, so there's no
supported way to combine programs.niri.settings with an extra include
line. A static rule was chosen over a niri-msg-event-stream watcher
daemon as the simpler option -- it just won't retarget itself at other
locations/kanshi profiles, gracefully falling back to normal placement
there instead (per niri's own open-on-output fallback behavior).

Also wires waybar's systemd target, since niri.service itself BindsTo
graphical-session.target rather than a dedicated *-session.target.
Adds swayWorkspaceSetup, a swaymsg-based equivalent of the existing
hyprctl-based workspaceSetup (pins workspaces 1-2/3-4 to the profile's
primary/secondary output and sets a random wallpaper via swaymsg output
bg, since sway has no hyprpaper equivalent).

kanshi's systemdTarget only accepts one target string, so it can't bind
to both hyprland-session.target and sway-session.target at once. Changed
to the shared graphical-session.target (which both compositors' session
units already BindsTo) and added runtime compositor detection
(runWorkspaceSetup, pgrep-based) so the profile exec script dispatches
to whichever compositor is actually running.
Matches Hyprland's existing autostart (mumble, firefox, chromium) now
that both compositor modules have an autostart option to migrate it
into.
hyprland/workspaces and hyprland/submap only connect to Hyprland's own
IPC socket, so under sway or niri the workspace indicator rendered
nothing. Adds sway/workspaces, niri/workspaces, and sway/mode (niri has
no modal binds, so no submap-equivalent needed there) to the same
shared waybar.json rather than maintaining a separate config per
compositor -- each compositor-specific module checks for its own
socket/env var at startup and silently no-ops if it's not the one
running, which is the standard way to run one waybar config across
multiple compositors.
services.swayidle.timeouts[].command gets embedded verbatim into
swayidle.service's ExecStart= line. The DPMS command was a multi-line
Nix string (an if/elif/fi block), so its raw embedded newlines broke
systemd's unit-file parser: "expected '=' but got 'o'" on switch,
since each newline started a new, invalid key=value line.

Moved the compositor-detection logic into a real script
(pkgs.writeShellScript) referenced by store path instead, which is
inherently a single-line value in the unit file. Verified this time
with systemd-analyze verify against the generated unit, not just a
nix build -- a nix build alone doesn't catch that the generated text
is invalid systemd syntax, only that the Nix evaluated successfully.
scratchy was dropped along with the rest of Hyprland's special
workspaces during the parity migration, but sway's real scratchpad
(a single unnamed pool) is actually an exact match for a single scratch
terminal -- "scratchpad show" is a genuine hide/show toggle. Only
"aux" stays dropped, since it needs two independently named pools,
which sway's scratchpad can't do. Mod4+o toggles it, Mod4+Shift+o
sends the focused window there, and the scratchy-titled alacritty
autostarts hidden straight into the scratchpad via a window command.

Also sets config.colors to Catppuccin Macchiato with a mauve focused
border, matching the accent used elsewhere in this repo, without
re-enabling full catppuccin.sway theming (which would also bring back
sway's own bar, already disabled in favor of waybar).
Niri has no scratchpad, so this reconstructs Hyprland's scratchy
toggle using niri's window-id IPC instead (niri msg action
focus-window / move-window-to-workspace, confirmed against the
niri-ipc source's Window/Workspace structs). Mod+O runs a script that
queries the scratchy window's is_focused state: if focused, moves it
to a dedicated "scratch-hidden" named workspace (kept out of the
Mod+1..5 binds so it's never visible in normal use); otherwise moves
it to the currently focused workspace and focuses it. Single
keypress-invoked script, not a persistent daemon.

The scratchy-titled Alacritty autostarts floating (a real niri
window-rule, unlike sway which needed no extra rule since its
scratchpad handles floating implicitly).
…tom exec scripts for plain settings

Alacritty's hint regexes embedded literal non-ASCII characters and relied
on Unicode-mode word boundaries, which its lazy-DFA hint compiler can't
build; force ASCII mode with (?-u) and drop the stray Unicode brackets.

kanshi's workspace-pinning scripts (workspaceSetup/swayWorkspaceSetup/
runWorkspaceSetup, mkExec, mkProfile) were dead/half-disabled leftovers
from an abandoned auto-pin-workspaces feature. Replaced with a plain
services.kanshi.settings list: no exec, external monitors matched by
vendor/model/serial identifier, eDP-1 kept as a connector name since the
internal panel reports no identifier. Removed the now-orphaned
hypr/workspaces.conf source line and updated docs/monitors.md to match.
…disable eDP-1 when docked

Replaces the exec-script-based workspace pinning with Hyprland's native
workspace = N, monitor:desc:<identifier> rules. These are no-ops when the
named monitor isn't connected (verified against hyprwm/Hyprland@4afc273,
the pinned hyprland-git rev), so a single static list correctly pins
workspaces on home/home-firefly and is inert on office/undocked.

For that fallback to actually land everything on the single active
monitor at the office (and when docked at home), eDP-1 now gets
`status = "disable"` in those kanshi profiles instead of staying enabled
alongside the external monitor.
boot.loader.timeout = 0 (a plain, priority-100 definition) collided with
nixpkgs' own nixos/modules/installer/cd-dvd/iso-image.nix, which sets the
same option to 10 at the same priority for live-ISO hosts like vinox
(imported via installation-cd-graphical-gnome.nix). NixOS's module
system throws "conflicting definition values" for two same-priority
definitions that disagree, which is exactly what failed in the "Host
vinox" CI job.

Restoring mkDefault drops our value back to low priority so real hosts
(zion, kubex, nixberry) still get timeout=0 as the sole definition,
while vinox's installer-provided timeout=10 (a sensible interactive
value for a live-boot menu) wins instead of erroring.

Verified locally: `nix build .#nixosConfigurations.vinox.config.system.build.toplevel` now succeeds.
@RAPSNX RAPSNX changed the title ZionOS General improvements and refactoring Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant