docs: the power button, the maintenance chord, and why long-Escape should change

Records what was measured this pass and, as importantly, what was not.

KGlobalAccel will accept a bare Escape and its component carries both a
pressed and a released signal, so hold-and-cancel is expressible. What
could not be measured here is whether a global shortcut takes the key
away from applications, because key injection cannot reach the nested
session. The mechanism says it does — KWin matches shortcuts in an input
filter ahead of the focused surface — which would cost the classroom
every ordinary use of Escape. That is inference, and it is written down
as inference, with the thirty-second bench test that settles it.

The recommendation is to change the gesture rather than grab the key an
appliance uses most: hold-to-confirm on an on-screen control, which is
ordinary Qt inside our own surface, or a modifier chord like the one the
maintenance terminal just proved. Either keeps the deliberate ceremony
without an input daemon.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
ekklesia
2026-09-10 15:24:28 -05:00
co-authored by Claude Opus 5
parent 30a924d945
commit 6050144e5d
6 changed files with 220 additions and 43 deletions
+204 -43
View File
@@ -746,45 +746,6 @@ record failures rather than successes.
machine whose network NetworkManager actually owns.
## Television control, and where CEC will fit
The devices arrive today. **Nothing here guesses at their protocol** and
no CEC code has been written.
What the architecture needs to leave room for: the volume control in the
bar today is the *computer's* volume, and once the television is under
CEC control that is the wrong thing for a teacher to be adjusting. The
teacher should be turning the television up, not the computer.
The shape that keeps Plasma out of the hardware:
```
panel button / notification presentation only
|
v
ekklesia-classroom-tv.service a small supervised user service
| the same shape as the audio policy
+-- backend: CEC over the adapter
+-- interface: on, off, volume up, volume down, mute, input
```
Three properties to hold to:
* **Plasma is presentation.** The panel may show state and send an
action; it must not contain the protocol. That is why the audio policy
is a service and not a plasmoid, and this should follow it.
* **The interface is verbs, not device commands.** "Volume up" is the
contract; whether that is a CEC user-control-pressed opcode or
something else is the backend's business.
* **Supervised and failure-tolerant.** A television that is off, an
adapter that is unplugged, or a set that ignores CEC must degrade to
nothing happening, never to a stuck classroom.
When the hardware has been exercised, the computer volume applet comes
out of the bar and a television control goes in. Until then it stays,
because a room with no sound control at all is worse.
## Live View, and whether this desktop can carry it
Not implemented. What the KDE architecture already provides for it:
@@ -804,6 +765,178 @@ Not implemented. What the KDE architecture already provides for it:
The likely media path (MediaMTX, WHEP) is a property of the player
application and does not touch the desktop architecture.
## The power button, and the way back in
### A press does nothing
Two layers, and both are needed. While a graphical session is running,
PowerDevil takes logind's `handle-power-key` inhibitor and acts on the
button itself, so a logind drop-in on its own would be overruled.
| layer | file | what it says |
| --- | --- | --- |
| logind | `/etc/systemd/logind.conf.d/ekklesia-classroom.conf` | `HandlePowerKey`, `HandleSuspendKey`, `HandleHibernateKey`, `HandleRebootKey` and every lid switch set to `ignore`, long-press included |
| PowerDevil | `/etc/ekklesia-classroom/xdg/powermanagementprofilesrc` | `powerButtonAction=0` and `lidAction=0` in all three profiles, groups marked `[$i]` so the session cannot put an action back |
logind covers the machine before the session starts, after it ends, and
if PowerDevil is not running at all. PowerDevil covers it while a teacher
is using it.
Measured in the lab: with the drop-in installed and logind reloaded,
logind reports `ignore` for the power, suspend, hibernate and lid keys —
it reported `poweroff` and `suspend` before — and the running graphical
session was not disturbed by the reload. The `postinst` therefore
reloads logind, so the button stops working at install time rather than
at the next boot.
**Holding the button still cuts the power.** That is firmware, below any
operating system, and it is left alone on purpose: it is the only
recovery a person standing at a wedged machine has.
**Needs the hardware.** Nothing in a container has a power button. What
is proven is that both layers are configured, packaged, and read back
the way they should. Pressing the button is a bench test.
### One chord opens a terminal
`Meta+Ctrl+Alt+Shift+K`.
Normal administration is still SSH. This is for the case where somebody
is standing at a machine and SSH is not available.
The chord is declared in the package — `X-KDE-Shortcuts` in
`ekklesia-admin-terminal.desktop` — rather than seeded into a teacher's
configuration, where an update could not reach it. KGlobalAccel read the
entry and registered a component for it; invoking that component's
`_launch` over D-Bus opened a working shell, which is how the whole path
was verified without a keyboard.
It needed a wrapper, for a reason worth recording. The classroom's Kiosk
policy sets `shell_access=false` and **Konsole honours it**: with the
classroom configuration in its cascade, Konsole starts and prints
*Program to run not set.* rather than opening a shell. That restriction
is worth keeping for everything else, so `classroom-admin-terminal`
lifts it for one process by leaving the classroom's configuration
directory out of that process's `XDG_CONFIG_DIRS`. Nothing is patched,
no binary is replaced, and the terminal therefore looks like stock KDE
rather than like the classroom — which is fair, because it is not part
of the classroom.
**It grants no privilege.** The classroom user has no sudo rule, and
anything needing root still needs the administrator's own account and
password. `shell_access` was always a barrier in the interface, never a
privilege boundary.
Konsole is a package dependency, so the route exists on every machine.
Its own entry is shadowed from `/usr/local/share/applications` with
`NoDisplay=true`, leaving Konsole's file exactly where its package put
it.
One thing found while testing, and kept as a second layer rather than
removed: **Konsole ships `X-KDE-Shortcuts=Ctrl+Alt+T`**, a chord a great
many people know. The shadow entry blanks it, but the registration comes
from Konsole's own file and survives that — so it is still registered.
It is also inert: Konsole's entry carries
`X-KDE-AuthorizeAction=shell_access`, and with the classroom's
`shell_access=false` the launch is refused. Measured: invoking that
component over D-Bus opened nothing.
Nothing is pinned to the panel. A task button appears only while a
terminal is open, and closing it returns the bar to three launchers.
**Needs the hardware.** The chord itself has never been pressed — key
injection cannot reach the nested session in this lab. What is verified
is that the shortcut is registered from the packaged entry and that its
action opens a shell.
## Long-Escape to turn the television off: it should change
The gesture asked for was: hold Escape, silence for three seconds, then a
five-second visible countdown, cancel on release. Deliberate, hard to
trigger by accident, and a clear intent.
### What was measured
* **KGlobalAccel accepts a bare `Escape`.** A probe entry declaring
`X-KDE-Shortcuts=Escape` was registered and given its own component. So
the binding is possible.
* **Press *and release* are both observable.** The component's D-Bus
interface carries `globalShortcutPressed` **and**
`globalShortcutReleased`. Hold duration and cancel-on-release are
therefore expressible without any input daemon of our own.
* **KWin's scripting API has no key events at all** — `registerShortcut`
and screen edges, and nothing that reports a key going up.
### What was not measured, and why it decides the answer
Whether a registered global shortcut **takes the key away from
applications**. Key injection cannot reach the nested session in this
lab, so this could not be pressed.
The mechanism says it does: on Wayland, KWin matches global shortcuts in
an input filter that runs before the event reaches the focused surface,
and a match stops propagation. That is how `Meta+Q` never arrives at an
application. A bare `Escape` bound globally should therefore stop
reaching anything — no leaving a fullscreen video, no dismissing a Chrome
dialog, no closing the Parent Call card.
**This is inference, not a measurement, and it is a thirty-second bench
test**: bind the probe entry above, press Escape in a fullscreen video,
and see whether it leaves fullscreen.
### The recommendation
**Change the gesture.** Even if Escape were forwarded as well as
observed, the whole ceremony would rest on a global grab of the key an
appliance uses most, and a countdown driven from the process holding
that grab is an input daemon in all but name. That is the fragile thing
the classroom keeps removing.
Two clean alternatives, both using mechanisms already proven here:
1. **Hold-to-confirm on screen.** A television control where the volume
applet is now: press and hold it, a countdown runs, releasing
cancels. Press, hold and release inside an application's own surface
are ordinary Qt and need no global input at all. This keeps every
property the gesture was for — deliberate, visible countdown,
cancel-on-release — and costs nothing in reliability.
2. **A modifier chord**, the same mechanism as the maintenance terminal
and proven to work in this session. Instant rather than ceremonial,
but impossible to press by accident. Worth adding as a second route
for somebody who cannot find the mouse.
If a keyboard hold is still wanted after the bench test, it should be on
a key the classroom does not otherwise use — never Escape.
## The television control service
Unchanged in shape from the previous checkpoint, and now with the
gesture question answered:
```
panel control / chord presentation only
|
v
ekklesia-classroom-tv.service small, supervised, ours
|
+-- backend: CEC over the adapter
+-- interface: on, off, volume up, volume down, mute, input
```
* The keyboard and the panel request **"TV off"**. They never speak CEC.
* The service decides how. CEC hardware can change without the desktop
noticing.
* The same service will own automatic TV-on at session start, volume,
mute and input, and it is why the computer's own volume applet is
expected to leave the bar.
* Supervised and self-recovering, the same way the audio policy is.
**No CEC code has been written and no protocol has been guessed.** The
adapters arrive today; the commands get measured before anything is
built on them.
## Unresolved risks
In the order I would worry about them.
@@ -848,6 +981,18 @@ In the order I would worry about them.
against this palette, and is to be supplied separately.
10. **The disc launcher tracks the drive, not the disc.** A room with a
drive shows the DVD button whether or not anything is in it.
11. **The power button has never been pressed.** Both layers are
configured, packaged, and read back correctly, but nothing in a
container has a power button.
12. **The maintenance chord has never been typed.** The shortcut is
registered from the packaged entry and its action opens a shell —
verified over D-Bus — but key injection cannot reach the nested
session, so `Meta+Ctrl+Alt+Shift+K` itself is unpressed.
13. **Ctrl+Alt+T is still registered.** Konsole's own entry declares it
and the registration survives being shadowed. It is inert, because
Konsole refuses to open a shell under the classroom's
`shell_access=false` — measured — but it rests on that one
restriction rather than on the chord not existing.
## Would I trust it on a classroom computer, unattended, for a Sunday?
@@ -872,9 +1017,14 @@ Before any room:
hardware*.
3. Press Parent Call and **type a name with a real keyboard**. Then do it
with the coordinator's mode off, and with the broker stopped.
4. Print to Elmer.
5. Play a DVD, if that room uses them: cover, picture, controls, eject.
6. Leave it running from Friday to Sunday.
4. **Press the power button.** Nothing should happen. Then hold it, and
confirm the machine still dies — that is the recovery path and it
must stay.
5. **Type Meta+Ctrl+Alt+Shift+K.** A terminal should open. Then try
Ctrl+Alt+T and confirm nothing does.
6. Print to Elmer.
7. Play a DVD, if that room uses them: cover, picture, controls, eject.
8. Leave it running from Friday to Sunday.
## Alternate operating systems
@@ -922,13 +1072,24 @@ The existing Debian classroom test VM should be kept.
can reach a room that has already run.
* **Recovery re-measured against the packaged build**, not a hand-edited
session.
* **The power button disabled at both layers**, packaged, and read back
from logind after a reload that did not disturb the session.
* **A maintenance terminal behind one obscure chord**, declared in the
package, hidden from every application list, granting no privilege.
* **Long-Escape investigated and recommended against**, with the two
clean alternatives written down.
**Next**, in order:
0. **The thirty-second Escape test**, before anything is built on the
gesture: bind a probe entry to `Escape`, press it in a fullscreen
video, and see whether the video leaves fullscreen. That settles the
one thing this pass could not measure.
1. **On the bench, tonight.** Type a name into Parent Call with a real
keyboard. Switch a television on after the computer and listen. Play a
disc. These three are the only things left that a container cannot
answer, and each of them is a Sunday-morning path.
answer, and each of them is a Sunday-morning path. Add the power
button and the maintenance chord to that list.
2. Publish `0.1.45~plasma1` to a channel of its own, the way the Hyprland
milestone did, so a stable or canary room can never be offered it.
3. Bench-test SDDM: autologin, and that ending the session brings the
+7
View File
@@ -59,6 +59,13 @@ container lab. See [../classroom-v2-experiment.md](../classroom-v2-experiment.md
| `v2-layershell` | a gtk-layer-shell overlay under KWin — what the DVD loading cover is made of |
| `v2-notification-crop` | a notification card, top right |
## Administration
| | |
| --- | --- |
| `admin-terminal` | the maintenance terminal, opened by its chord's action |
| `admin-terminal-bar` | the bar with the terminal open, and after closing it: a task button while it runs, no launcher ever |
## Reliability and lockdown
| | |
Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

After

Width:  |  Height:  |  Size: 254 KiB