aboutsummaryrefslogtreecommitdiff
path: root/docs/design/2026-07-02-desktop-settings-panel-spec.org
blob: 8becf71da5dc499eb8738dcb0f793e0e078c0b7d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#+TITLE: Desktop-Settings Dropdown Panel
#+AUTHOR: Craig Jennings
#+DATE: 2026-07-02
#+TODO: TODO | DONE
#+TODO: DRAFT READY DOING | IMPLEMENTED SUPERSEDED CANCELLED

* DRAFT Status
:PROPERTIES:
:ID:       fb7eec22-a214-4568-82c4-903612f4832f
:END:
- [2026-07-02 Thu] DRAFT — initial spec from the todo.org task "Desktop-settings
  dropdown panel" (2026-06-24 review), updated for the Blueprint/GTK4 pipeline
  the net panel stood up 2026-07-01.

* Metadata

| Field  | Value                                        |
|--------+----------------------------------------------|
| Status | draft                                        |
|--------+----------------------------------------------|
| Owner  | Craig Jennings                               |
|--------+----------------------------------------------|
| Repo   | dotfiles                                     |
|--------+----------------------------------------------|
| Kin    | net panel (architecture donor), theme studio |
|--------+----------------------------------------------|

* Problem

Desktop toggles are scattered: dim, caffeine/idle, touchpad/mouse, airplane
mode each own a bar module and a keybind; brightness and keyboard-backlight
have keybinds but no visible control or level readout. The bar is running out
of glanceable width (hence the collapse arrows), and sliders can't live in
waybar at all. One settings dropdown — a gear glyph opening a small panel —
gathers them.

* Goals

1. One panel with every desktop toggle + slider: auto-dim, idle/caffeine,
   touchpad, mouse, airplane (laptop-only), screen brightness, keyboard
   backlight.
2. Conditional rows appear only when the hardware/context applies (mouse
   present, trackpad present, battery present) — reuse the detection the
   airplane/touchpad indicators already do.
3. Every control reflects live state and verifies its action took (the net
   panel's verify-everything contract).
4. Bar stays the quick layer: which standalone indicators survive is a
   decision below.

* Design sketch

** Architecture — clone the net panel's proven stack

- GTK4 + gtk4-layer-shell, Blueprint .blp sources compiled to committed .ui
  (=make ui=; dev-only build dependency, fresh clones run without the
  compiler).
- Humble-object split: a GTK-free PanelModel presenter (unit-tested to 100%
  like the net PanelModel) + thin composite-widget pages. Backing actions in
  a GTK-free settings.py that shells out to brightnessctl / hyprctl / the
  existing toggle scripts, TDD'd with fake binaries like every dotfiles
  suite.
- One gated AT-SPI smoke (the run-panel-smoke.sh pattern), no bespoke
  headless widget suite.
- Dupre WIP palette CSS, shared with the net panel — factor the palette
  block into a common css asset both panels load rather than duplicating
  (feeds the theme-studio task later).

** Controls and their backings

| Control            | Backing                                      |
|--------------------+----------------------------------------------|
| Auto-dim toggle    | hyprctl decoration:dim_inactive (dim-toggle) |
|--------------------+----------------------------------------------|
| Idle / caffeine    | hypridle start/stop (caffeine-toggle)        |
|--------------------+----------------------------------------------|
| Touchpad toggle    | toggle-touchpad + touchpad-state file        |
|--------------------+----------------------------------------------|
| Mouse toggle       | same mechanism, mouse-state file             |
|--------------------+----------------------------------------------|
| Airplane mode      | airplane-mode script (laptop-only row)       |
|--------------------+----------------------------------------------|
| Screen brightness  | brightnessctl (backlight class), slider + %  |
|--------------------+----------------------------------------------|
| Keyboard backlight | brightnessctl (kbd_backlight class), slider  |
|--------------------+----------------------------------------------|

Slider changes apply live (throttled) and read back the actual level after
apply — verify-everything. Toggles re-read their source of truth after
firing, same as the bar indicators do, and the bar modules get their refresh
signals so both surfaces agree.

** Open/close behavior

Gear glyph module on the bar right cluster; click toggles the panel
(layer-shell anchored under the bar, right-aligned). Focus-out auto-hide +
Close button, matching the net panel. Keybind decision below.

* Decisions (Craig)

** TODO Which standalone bar indicators collapse into the panel?
Options per module (dim, touchpad, caffeine): keep on bar + mirrored in
panel; or panel-only (frees bar width). Recommendation: keep touchpad and
caffeine visible on the bar (state you glance at), move dim into the panel
(you set it rarely), keep airplane where it is.

** TODO Keybind for the panel?
Super+Shift+G (gear) is free. Or no keybind — mouse-only surface.

** TODO Where does the code live?
Recommendation: dotfiles =settings/= sibling to =net/= (same src-layout,
tests in tests/settings/), sharing the palette css. In-tree pocketbook-style
was the old note; the net panel is the better donor now.

** TODO Slider granularity and floor
brightnessctl exposes 0-100%; a 5% floor stops "screen went black in a dark
room" lockouts. Confirm the floor (or allow 0 with a long-press escape
hatch).

* Implementation phases

1. settings.py backings (brightness get/set, kbd backlight, toggle
   state readers) — pure engine, TDD with fake brightnessctl/hyprctl.
2. PanelModel presenter (rows, conditional visibility, verify-after-apply
   semantics) — unit-tested, no GTK.
3. Blueprint UI + gear bar module + open/close wiring; palette css factored
   to a shared asset; AT-SPI smoke.
4. Bar-module consolidation per the decision above (drop/keep indicators,
   refresh-signal wiring, keybind).