Skip to content

Hyprland layer-management system + single-source-of-truth dedup pass#11

Open
phibkro wants to merge 4 commits into
mainfrom
hyprland-layer-management
Open

Hyprland layer-management system + single-source-of-truth dedup pass#11
phibkro wants to merge 4 commits into
mainfrom
hyprland-layer-management

Conversation

@phibkro

@phibkro phibkro commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

A full session reworking how "layers" (special workspaces used as quick-summon overlays) are switched, announced, and organized on workstation, plus a code-smell/dedup pass applied afterward.

Keybind scheme (settled after two revisions):

  • SUPER+N (1-6) — toggle a layer's visibility, the higher-frequency bare-SUPER surface. New windows auto-route into the shown layer (removed the old per-app window_rule that was fighting this already-default Hyprland behavior).
  • SUPER+SHIFT+N — move the focused window into a layer.
  • SUPER+CTRL+N / SUPER+CTRL+SHIFT+N — regular workspace switch/move. CTRL rather than ALT, since ALT already means "window switching" elsewhere (ALT+TAB / SUPER+TAB).
  • SUPER+ALT+TAB / +SHIFT+TAB — cycle layers next/prev.

New capabilities:

  • layer-toggle / layer-cycle / layer-autohide — toggling/cycling a layer now announces it via a center-anchored, fading mako popup (fade comes from Hyprland's existing fadeLayersIn/Out animation, not mako itself — confirmed mako has no fade support). layer-autohide is a daemon watching Hyprland's IPC event stream that hides a shown layer when focus moves to a regular workspace (Hyprland doesn't do this on its own).
  • SUPER+G — a translucent+blurred "glass" spacer window: a real, inert ghostty instance that tiles like any window, reserving a layout slot without needing real content. No native Hyprland primitive does this.
  • SUPER+Rtile-ratio, a fuzzel-picked split-ratio tool. Presets are absolute (fraction of monitor width); typing a custom value is a relative multiplier on the current size. Empirically calibrates the real px-per-delta-unit per invocation since splitratio has no absolute-set mode and its relative effect scales with the local split context, not the whole monitor.

Dedup / single-source-of-truth pass (applied after reviewing lang-bang's practiced correct-by-construction / SSOT principles):

  • layerTags (home.nix) is now the sole source of the six tag names — hyprland.lua's tag table is generated from it via pkgs.replaceVars instead of hand-typed a second time.
  • spacerClass is the sole source of the glass-spacer's GTK application id (plain + regex-escaped forms generated from one value).
  • Extracted current-layer (query) and layer-announce (command) — the same hyprctl query was copy-pasted 3×, the same notify-send call 2×.
  • Named modifier-combo constants replace repeated raw modifier-string concatenation.
  • Fixed two stale comments left over from the ALT→CTRL modifier swap.

test-hypr was also strengthened along the way: Tier 2 now reads back actual state after each toggle instead of trusting hyprctl dispatch's "ok" response, which had silently masked a real regression (the table-arg form of toggle_special toggling the wrong workspace) for an unknown period.

Test plan

  • just test-hypr — 41/41 checks pass (dispatcher correctness, layer-cycle wraparound, full bind registry)
  • nix flake check — all checks pass, including the full VM e2e suite
  • Live round-trip verification: layer toggle/cycle/auto-hide, glass spacer spawn+resize+close, tile-ratio absolute/relative modes against real window splits, mako announcement delivery — all tested on an isolated empty workspace to avoid disrupting the real desktop
  • Manual click-through on the actual daily-driver session (recommended before relying on this day-to-day — most of this was tested via scripted hyprctl calls simulating keypresses, not literal key presses)

🤖 Generated with Claude Code

phibkro and others added 4 commits June 30, 2026 22:08
…orkstation

nixpkgs-master lags upstream by ~1 day — 2.1.197 shipped before nixpkgs
picked it up. Override version + src with the upstream manifest hashes
directly (all four platforms: x86_64/aarch64 × linux/darwin). The binary
is a single fetchurl from downloads.claude.ai; versionCheckHook confirmed
2.1.197 in nix-build trial run before committing.

Drop the override block and revert claude-code-master to
pkgsMaster.claude-code once nixpkgs-master carries ≥ 2.1.197.

Also: add pkgs.pulseaudio to workstation home packages for pactl — useful
for PipeWire/PulseAudio sink inspection (jack desync after replug, etc.).
…dedup pass

A cohesive Hyprland session reworking how "layers" (special
workspaces used as quick-summon overlays) are switched, announced,
and organized, plus a code-smell cleanup applied to all of it.

Keybind scheme (swapped twice this session, settled on):
- SUPER+N (1-6): toggle a layer's visibility — the higher-frequency,
  bare-SUPER surface. Auto-routes new windows into the shown layer
  (removed the old per-app window_rule that was fighting this
  already-default Hyprland behavior).
- SUPER+SHIFT+N: move the focused window into a layer.
- SUPER+CTRL+N / SUPER+CTRL+SHIFT+N: regular workspace switch/move.
  CTRL rather than ALT specifically, since ALT already means "window
  switching" elsewhere in this config (ALT+TAB / SUPER+TAB).
- SUPER+ALT+TAB / +SHIFT+TAB: cycle layers next/prev (layer-cycle).

New capabilities:
- layer-toggle / layer-cycle / layer-autohide: toggling/cycling a
  layer now announces it via a mako popup (center-anchored, fades via
  Hyprland's existing fadeLayersIn/Out animation — mako itself has no
  fade support, confirmed via its own docs). layer-autohide is a
  daemon watching Hyprland's IPC event stream that hides a shown
  layer when focus moves to a regular workspace, which Hyprland
  doesn't do on its own.
- SUPER+G: a translucent+blurred "glass" spacer window (a real,
  inert ghostty instance) that tiles like any window — reserves a
  slot in the dwindle layout without needing real content in it. No
  native Hyprland primitive does this (layoutmsg preselect only
  biases the *next* window's split direction, doesn't hold a slot
  open). Needed two ghostty CLI overrides to behave: blink disabled
  and confirm-close-surface=false (otherwise SUPER+Q silently hangs
  waiting on a close-confirmation dialog, since `sleep infinity`
  never exits on its own).
- SUPER+R: tile-ratio, a fuzzel-picked split-ratio tool. Presets
  (1/2, 1/3, 2/3, 1/4, 3/4, 1/5, 2/5) are absolute targets (fraction
  of monitor width); typing anything else is a relative multiplier on
  the current size ("2" -> double, "1/2" -> half). `splitratio`
  (dwindle) is relative-delta-only with no absolute-set mode
  (confirmed live: `splitratio exact 0.33` errors directly from
  Hyprland), so this empirically calibrates the real px-per-delta-
  unit for whatever split context the focused window is actually in
  (a fixed monitor-width-based formula undershoots for windows nested
  2+ levels deep, since splitratio's real effect scales with the
  local sibling-pair's extent, not the whole monitor — caught via a
  live repro that got stuck below its target on repeated application).

Code-smell / single-source-of-truth pass (applied after reviewing
lang-bang's practiced correct-by-construction / SSOT principles):
- layerTags (home.nix) is the sole source of the six tag names.
  hyprland.lua's `local tags = {...}` table is generated from it via
  pkgs.replaceVars instead of being hand-typed a second time; the
  bash scripts interpolate the same Nix list directly.
- spacerClass (home.nix) is the sole source of the glass-spacer's GTK
  application id, generated (plain + regex-escaped) into hyprland.lua
  instead of typed twice with two different, easy-to-desync escapings.
- Extracted current-layer (query) and layer-announce (command) — the
  same `hyprctl monitors -j | jq ...` pipeline was copy-pasted three
  times, and the same notify-send call twice.
- Named modifier-combo constants (layerMod/workspaceMod/layerCycleMod)
  replace repeated raw "SUPER + CTRL"/"SUPER + ALT" string
  concatenation.
- Fixed two stale comments left over from the ALT->CTRL workspace
  modifier swap that still said "SUPER+ALT+1..6" / "SUPER+ALT+2".
- tests/tests.just's own hand-typed tag list is a deliberately named
  exception (see inline comment), not a silent gap: wiring it to the
  real source needs layerTags promoted to an exposed option,
  disproportionate to a gap that already fails loud in CI.

test-hypr strengthened alongside: Tier 2 now reads back
`.specialWorkspace.name` after each toggle instead of trusting
`hyprctl dispatch`'s "ok" response, which had silently masked a real
regression (the table-arg form of toggle_special toggling the wrong,
bare unnamed special workspace) for an unknown period. Tier 2b/3 added
for layer-cycle wraparound and the full bind registry.

Verified throughout: just preview + test-hypr (41/41 checks) + nix
flake check (full VM e2e suite) + live round-trips for the spacer,
ratio tool, and mako announcements on an isolated empty workspace.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ation scan

A fast, single-pass (no subagents) technique skill for the refactor
step of red -> green -> refactor: scans a small recent diff for
Single-Source-of-Truth violations (duplicated literals, cross-file/
cross-language duplicated facts, copy-pasted logic, stale comments)
and Correct-by-Construction opportunities, recommending a fix via the
generate > test > convention ladder. Deliberately narrower and faster
than /simplify — scoped to what was just touched, not a repo sweep.

Authored via the write-a-skill workflow: drafted, then validated
against two fresh agents on a planted 5-file scenario (repeated
literals + pipeline, cross-file duplicated data, a stale comment, a
cross-repo case that should land on "convention" not "generate", and
a non-duplicated distractor). First pass correctly handled 4/5
categories but missed the stale-comment check entirely — folded that
gap back into the skill (made staleness its own dedicated pass rather
than competing with the more visually obvious duplication hits) and
re-verified on a focused re-test: the same planted stale comment was
then caught, correctly traced against the code, and fixed to state
reality rather than fabricating behavior to match the old claim.

This branch is otherwise about the Hyprland layer-management work
(PR #11) — this commit is unrelated and kept separate so it can be
cherry-picked or landed independently of that PR's review.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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