Commit Graph
6 Commits
Author SHA1 Message Date
Gabriel Brown 9ffaf45a4d Make every settings row reachable, and every accessibility switch honest
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
2026-08-24 21:03:36 -04:00
Gabriel Brown 3d21e20041 Make every control tell the truth
The audit's first tier, in one change: every case found where the interface
asserted something the system did not do.

Twenty-one compositor-owned preferences -- the whole Mouse & Touchpad page,
plus window layout, snapping, dim-inactive and the magnifier -- had the live
half (hyprctl eval) and not the config-time half, so they quietly reverted on
every hyprctl reload. All 70 hypr-backed keys now have a prefs.get() in the
Lua, and hypr-prefs-contract pins both the presence and that the Lua fallback
equals the schema default, which is how the touchpad page misreported natural
scrolling on first boot.

The idle generator fell back from unwritten battery keys to the AC values
while the Power page displayed the schema defaults: a fresh laptop showed
"suspend at 20 minutes" and generated no suspend listener, then discharged to
zero in a bag. Unwritten keys now use the defaults the page shows
(idle-defaults-contract pins generator to schema; idle-config-contract
re-pinned to the new rule with the tradeoff recorded), and change-settings
enables managed idle on any machine with a battery -- without starting
hypridle in whatever session the installer runs under.

The per-app lock-screen notification switches wrote fields nothing read:
hyprlock cannot render notifications. Removed, with the rule model shrunk to
{enabled}, stale stored fields dropped at normalization, and the contract now
forbidding the page from growing lock-screen switches it cannot honor.

The battery warning thresholds were searchable, documented as "Found on
Power & Lock", and rendered nowhere -- and crossing the low threshold changed
only a glyph's color. Both sliders now exist where search was already sending
people, and low battery publishes a real notification at important priority.

Three handoffs opened GNOME panels that are inert in a Hyprland session. The
keyboard handoff is gone (that panel writes gsettings nothing here reads, and
the working controls sat on the same page); Connectivity gains a Wi-Fi row
that opens GNOME's actual Wi-Fi panel -- hidden SSIDs and 802.1X finally have
a road -- beside the network row that legitimately drives NetworkManager; the
universal-access handoff is gone, its few working toggles being controls this
app already owns. And the accessibility page now gives the true reason sticky
keys are missing: each Wayland compositor implements its own and Hyprland
does not yet -- not "an X11 feature with no Wayland equivalent," which sent
people to the wrong conclusion about the platform.

Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
2026-08-23 11:43:39 -04:00
Gabriel Brown 6997dd535f Add high contrast, and make remote desktop configurable
Two of the three panels still handed to GNOME, having actually checked
each rather than repeating that they were not worth owning.

Universal Access turned out to be mostly ours already: the magnifier,
pointer size, text scale, motion and dimming were all present. High
contrast was the real gap. It reaches GTK4 applications through the
desktop portal, which republishes GNOME's accessibility setting as
org.freedesktop.appearance contrast -- so no high-contrast theme is
involved, and none is installed here. Verified end to end: committing
the preference drove gsettings and the portal reported contrast 1.

Sticky, slow and bounce keys stay absent. There is no Wayland or
Hyprland implementation, and the compositor would store the XKB option
while nothing ever acted on it.

Remote desktop gained port, view-only, and clearing stored credentials.
SETTING credentials opens a terminal running grdctl, which prompts for
the password itself. That is not a hand-off for lack of effort: grdctl
takes the password on a terminal and core-dumps without one, and the
only alternative -- passing it as an argument -- would publish it
through /proc to every process on this machine. Typed into grdctl
directly it never passes through Panama, and a contract now fails if it
ever appears on a command line.

Color stays with GNOME, and not for lack of effort either. colord runs
here with seven profiles and zero devices registered, because the
daemons that register displays do not run under this session, and
Hyprland exposes no ICC, gamma, or color-management option at all. A
Color page could import a profile, attach it to nothing, and change
nothing -- the same failure refused for rollback and printer drivers.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-19 16:42:20 -04:00
Gabriel Brown 54b8a82803 Give Accessibility a real magnifier, and stop implying the rest is available
The page had two settings and a hand-off card claiming GNOME's stack
provided "screen reader, zoom, and on-screen keyboard". Zoom did not
need handing off at all, and the claim about the rest was optimistic.

Zoom is native now. Hyprland has a real magnifier -- cursor:zoom_factor
follows the pointer -- so it is a slider here rather than a button that
opens another application. Inactive windows can also be dimmed as well
as faded, which is the other thing that makes a focused window
unmistakable. 47 mapped compositor options, from 43.

What is NOT here is the more useful half of the change. Sticky keys,
slow keys, bounce keys and mouse keys are AccessX, an X11 SERVER
feature. XKB under Wayland has no accessx option group at all -- checked
against evdev.lst, which lists altwin, caps, compose, ctrl, grp and the
rest, and nothing resembling accessx -- and Hyprland implements none of
it. The compositor will accept "accessx:enable" as a keyboard option and
store it happily; I verified that, and verified nothing acts on it.

So the page says plainly that they are unavailable in this session
rather than offering switches, and does not point at GNOME's panel for
them either: the daemon that would apply those keys is not running here,
so that hand-off would be just as empty. Orca is offered instead, since
the accessibility bus genuinely does work.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-18 10:49:04 -04:00
Gabriel Brown 9b2fa80ab7 Drop the product branding: this is just Settings
It is the system settings app for this desktop, so it is named the way
one is. The window is "Settings", the titlebar is "Settings", the
wordmark above the search field is gone, the sidebar's last row is
"About", and the status line reads "Desktop is healthy".

Prose followed the same rule. Forty-odd strings explained what "Panama"
does -- "Panama never animates while idle", "Restore Panama defaults",
"Panama looks in ~/Pictures/Wallpapers" -- which is how a product
describes itself, not how a settings panel describes a setting. They now
say what happens. No user-visible "Panama" remains anywhere in the app.

Two consequences worth naming:

The SUPER+I shortcut's description is user-visible, because the
Shortcuts page is generated from it, so that is renamed too. Rebindings
are keyed by shipped chord rather than description, so no existing
override is orphaned by this.

Three contracts matched the window by title and one matched that
shortcut by description; all four are updated. There are no Hyprland
window rules keyed on the title, so nothing about the window's placement
changes.

The desktop entry is now Name=Settings, but the FILE keeps its
panama-settings name, as does the icon: the dock pins applications by
desktop id, and renaming the file would silently unpin it.
dock-pins-contract covers exactly that.

The dated design docs under docs/superpowers keep the old name. They are
a record of what was decided when, and editing them to agree with the
present would make them lie about the past.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-18 10:08:55 -04:00
Gabriel Brown 2bc12e6022 Add wallpaper, power, date, accessibility, and real search
Continues the settings expansion toward replacing GNOME Settings for
everything Panama actually owns.

Wallpaper. A thumbnail grid rather than a path field: the value of this
setting is the picture, so typing a path to something you cannot see is
the worst version of it. Two things about hyprpaper 0.8 shaped this. Its
IPC is much smaller than older documentation suggests -- preload,
listloaded, unload, and reload all answer "invalid hyprpaper request",
so setting is a single call with no preload. And the "<empty>,<path>"
form that used to mean every output is silently ignored, so a wallpaper
set that way appears to succeed and never changes; outputs are walked
explicitly instead. hyprpaper.conf lives in the repo through the
~/.config/hypr symlink and so cannot hold machine state, which is why
the choice lives in the shared settings store and is re-applied at
startup.

Power & Lock. hypridle has no IPC for reconfiguration and its config is
hyprlang rather than the shared JSON, so scripts/panama-idle generates a
config from the settings store and restarts the daemon. The generated
file lives under XDG_STATE_HOME for the same symlink reason, with a
systemd drop-in pointing hypridle at it. Management is a real state and
the page says which one you are in rather than showing sliders that
quietly do nothing. Zero means never for all three timers, which a naive
template would render as "immediately".

Date & Time. Deliberately not stored in Panama's settings: the timezone
and network time belong to the machine and are shared with sessions that
never see this file. Storing a copy would create a second answer to a
question the system already answers. Reads and writes timedatectl
directly; a cancelled polkit prompt surfaces as an error rather than as
a value that appears to have been accepted.

Accessibility. Pointer size and text scale have to agree across three
consumers with no shared configuration -- the compositor, GTK, and the
shell -- so the store is the source of truth and the values are pushed
outward to gsettings and hyprctl setcursor.

Search now indexes the schema instead of the twelve page labels. "gaps",
"wallpaper", and "screenshot" previously found nothing on an app that
has all three, which is the clearest way a settings app feels smaller
than it is. Shortcuts are indexed by what they do. A contract asserts
every non-internal schema label is reachable, so a new setting cannot be
added in an undiscoverable state.

The GNOME delegation allow-list was widened to the panel names
gnome-control-center actually reports; the previous list contained
"users", which is not one of them and so opened nothing.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-18 00:42:13 -04:00