Commit Graph
11 Commits
Author SHA1 Message Date
Gabriel Brown e6b4d3c1a1 Stop lists and sliders from losing input under the user
WifiList and the notification toasts built their model from a plain
computed array, so any background property tick (a scan result, an
unrelated notification arriving) reassigned the whole array and the
Repeater destroyed and recreated every delegate -- including one with
an open, focused password field or an in-progress reply. Switched
both to a ScriptModel, which diffs by identity instead of resetting.

ValueSlider had its pointer-to-value mapping offset by 16px (the
hit-area margin was applied with the wrong sign), so 0% was
unreachable and every click landed to the right of where it was
placed -- affects every slider in the shell. SliderRow used -1 as a
sentinel for "nothing pending," which collides with legitimate
negative preference values like pointer sensitivity.

Dock intellihide read the globally focused workspace instead of each
monitor's own, so an empty workspace on one screen could hide the
dock on another; ActivityPanel rebuilt every row once a second during
a recording because the elapsed-time read lived in the model
construction instead of each row's own binding.

Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
2026-08-18 21:22:58 -04:00
Gabriel Brown bd5d030d91 Put power profiles and the colour scheme in the Control Center
The panel is for "change it now" decisions, and two of the most obvious
were reachable only through Settings. Night Light was already here;
these were the genuine gaps.

The colour scheme is a grid toggle beside it. It writes the preference
and stops -- ColorScheme propagates the change to GTK, the portal, the
terminals, the launcher, btop, tmux and the lock screen, and nothing in
the panel needs to know that list. Light is the lit state because dark
is what Panama ships, and "active" reads as the non-default everywhere
else in this grid.

Power profiles are a summary row that expands into a list, matching how
the audio device lists behave. A row per profile rather than a cycling
button: there are three, and cycling passes through one you did not want
on a machine where the change is immediate and audible. The row hides
entirely where no power-profiles daemon is running, and the panel
re-reads the active profile on open, because the daemon owns it and
anything on the system can change it.

Worth recording, because it invalidates something I believed earlier in
this session: the live shell runs `quickshell --daemonize` and does NOT
hot-reload. Editing a file under config/dot/quickshell changes nothing
until the shell is restarted. The PID changes I had taken for hot
reloads were tests killing and restarting it. Both of these controls
were written, verified in a harness, and completely absent from the
running panel until the shell was restarted.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-18 16:25:59 -04:00
Gabriel Brown 7541a45e77 Add external monitor brightness over DDC/CI
brightnessctl drives the kernel backlight class, which laptop panels
have and this desktop does not -- it reports only keyboard and NIC LEDs.
So BrightnessControl removed itself and there was no way to dim the
screen from Panama at all. DDC/CI is the channel the buttons on a
monitor's bezel drive, and it is the only brightness an external display
has. Both sources now render a row each, so a machine gets whichever it
actually has, or none.

Displays are enumerated from sysfs rather than `ddcutil detect`. The
kernel publishes the connector-to-bus mapping as
/sys/class/drm/<card>-<connector>/ddc along with whether anything is
plugged in, which beats parsing detect's undocumented brief output,
yields the connector name spelled exactly as Hyprland spells it, and
probes only connectors with a monitor attached -- one bus on this
machine rather than fourteen, where each empty bus costs a timeout.
No model name is read: Hyprland already knows what every output is
called, so the UI joins on the connector instead of keeping a second
source of truth that could disagree with the Displays page.

Writes are debounced, serial, and read back. Serial because DDC/CI has
no arbitration and two ddcutil processes on one bus interleave their
exchanges and both return garbage. Read back because a write is not a
promise: panels clamp to their own range, ignore values while waking
from standby, and drop writes that arrive too fast. Without the read the
slider would show what Panama asked for rather than what the monitor
did, which is the same class of lie as trusting `hyprctl keyword`.

Brightness is deliberately not a stored preference. The monitor
remembers it and the bezel buttons change it behind Panama's back, so
persisting it would mean restoring a value the panel had moved past.

The contract runs against fixtures with ddcutil stubbed and both sysfs
roots redirected, so it never touches a real monitor. Its fixture
reports a maximum of 200 rather than 100 on purpose -- at 100 the
scaling arithmetic is the identity and a helper that ignored the
reported maximum would pass everything. Verified it catches that, plus a
dropped connection-status filter and an unstripped connector prefix.

Not yet confirmed against hardware: this machine cannot open any I2C bus
yet. ddcutil's udev rule grants that through uaccess but only to devices
created after it was installed, so it needs one udevadm trigger. The
helper detects exactly that case and returns the command as its error
rather than reporting "no displays".

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-18 08:01:49 -04:00
Gabriel Brown 3cfa592db9 Build complete PipeWire sound settings 2026-08-18 05:54:14 -04:00
Gabriel Brown 7f540a58e5 Avoid visual Phone harness teardown 2026-08-17 19:42:15 -04:00
Gabriel Brown 3213a0989a Fix Phone controls runtime accessibility 2026-08-17 19:01:42 -04:00
Gabriel Brown fbf729b25c Add BlueBubbles to Phone controls 2026-08-17 18:48:28 -04:00
Gabriel Brown e37df9d838 Fix Home shelf slider interactions 2026-08-17 18:34:48 -04:00
Gabriel Brown 673aac6aba Build the Home accessory shelf 2026-08-17 18:22:27 -04:00
Gabriel Brown 5940d6b4bd Build the Panama Control Center 2026-08-17 13:44:18 -04:00
Gabriel Brown 5248883e4b Build the Panama Hyprland desktop 2026-08-17 10:32:55 -04:00