176 lines
9.5 KiB
Markdown
176 lines
9.5 KiB
Markdown
# Lock, idle, and wallpaper reference extraction
|
||
|
||
This is a design extraction, not a dependency list. Souveraine should retain
|
||
one session authority across desktop, laptop, and phone; form factor changes
|
||
the chosen layout and cards, never the meaning of lock, idle, or auth.
|
||
|
||
Migration rule: ii is a temporary compatibility substrate, not a source of
|
||
new architecture. New behavior belongs in `surfaces/quickshell` under a
|
||
Souveraine-owned module or service. Borrowed code is replaced deliberately,
|
||
with the replacement's contract documented before the borrowed file leaves.
|
||
|
||
## What the active shell has today
|
||
|
||
The phone lock has a credential keypad, fingerprint attempt, battery state,
|
||
and guarded power actions. It does **not** yet have lockscreen media,
|
||
notifications, timers, weather, calls, agent output policy, a staged idle
|
||
coordinator, or a real sleep-inhibitor backend. `Idle.qml` currently controls
|
||
hypridle because the tested invisible Wayland idle inhibitor is not honoured
|
||
on the Pixel 3 compositor build.
|
||
|
||
That is a sound small base. It is not yet a phone-grade lock surface.
|
||
|
||
## Ideas to extract
|
||
|
||
| Source | Keep | Do not inherit |
|
||
| --- | --- | --- |
|
||
| Sailfish/Lipstick lockscreen | A lock screen as layered/pannable content: glance surface, credential surface, and event surface. Wake/display-off are separate from lock. | Its device-specific Lipstick and DeviceLock plumbing; source provenance must be audited before copying. |
|
||
| Glacier Home | A compact MPRIS card with capability-gated previous/play/next controls; media is loaded only if a player exists. Clock, media, keypad, and notifications are separate components. | Its older Nemo/Amber APIs and visual code verbatim unless copyright notices travel with it. |
|
||
| DankMaterialShell | Independent idle monitors for dim/DPMS/lock/suspend, explicit re-arming, AC-vs-battery thresholds, and a wake monitor after screen-off. | Treating its shell state as authority or blindly importing its settings model. |
|
||
| ii/iNiR | MPRIS card mechanics, downloaded artwork, palette adaptation, and image "least busy region" placement. ii already calculates content placement against wallpaper pixels. | The current one-file wallpaper assumption and arbitrary widget dimensions. |
|
||
| Ambxst | Screen capture at lock, short-lived credential handling, failure lockout feedback, and listening to logind Lock/PrepareForSleep events. | Its AGPL code, polling `axctl` layer, and its separate lockscreen authority. Concepts only. |
|
||
|
||
DankMaterialShell and iNiR are MIT; Glacier carries MIT/BSD notices. Ambxst is
|
||
AGPL and Vast is GPL. Do not copy from the latter two into this repository
|
||
without intentionally accepting their licence obligations. Sailfish files in
|
||
the local research extraction need per-file provenance review before reuse.
|
||
|
||
## One lock surface, composable cards
|
||
|
||
The lock surface should be a host with slots rather than a new shell for each
|
||
device:
|
||
|
||
```
|
||
WlSessionLockSurface
|
||
└─ LockSurfaceHost
|
||
├─ glance slot clock · date · battery · weather
|
||
├─ continuity slot timer · ongoing call · navigation · media transport
|
||
├─ event slot notification summaries / previews
|
||
├─ credential slot PIN/password/fingerprint PAM conversation
|
||
└─ ambient-agent slot explicitly safe question/answer cards
|
||
```
|
||
|
||
The host chooses a layout profile:
|
||
|
||
| Profile | Layout |
|
||
| --- | --- |
|
||
| phone portrait | One vertical glance surface; a swipe/press brings up credentials; continuity cards occupy the lower third. |
|
||
| laptop | Center credentials with a side or lower card rail; multi-monitor cards remain local to their screen. |
|
||
| desktop | Center credentials and a sparse, large-screen card rail; no phone gesture assumptions. |
|
||
|
||
Each card declares a tier and a lock-surface visibility policy. This prevents
|
||
an attractive card from silently becoming a data leak.
|
||
|
||
| Tier | Suitable cards | Rule |
|
||
| --- | --- | --- |
|
||
| ambient | clock, battery, weather, timer, transport buttons, an ongoing-call *indicator* | no user data beyond the explicitly permitted setting |
|
||
| personal | track title/art, notification body, calendar title, agent conversation, call identity | hidden until unlock unless the user opts that field into ambient |
|
||
| step-up | send/reply/delete/purchase/unlock a physical thing | never performed by a card tap alone; needs a recent step-up grant |
|
||
|
||
An ambient agent is not a diluted personal agent. It has a separate tool and
|
||
memory allowlist, cannot read conversation history or sensors, and its output
|
||
is labelled ambient. If the lock starts while a personal response streams, the
|
||
host immediately withdraws it.
|
||
|
||
## Idle is a transition graph, not a timer
|
||
|
||
The useful DMS extraction is the vocabulary and re-arm discipline. The actual
|
||
authority remains Wayland idle protocols plus logind:
|
||
|
||
```
|
||
active ─idle timeout→ dimmed ─timeout→ lock-requested
|
||
│
|
||
WlSessionLock.secure
|
||
↓
|
||
lock-secure ─timeout→ display-off
|
||
│ │
|
||
PrepareForSleep(true) ─────────────────────────────────────┘
|
||
↓
|
||
suspending → asleep → waking → active
|
||
```
|
||
|
||
Input can cancel dimming and display-off before lock. It cannot cancel an
|
||
already secure lock; credentials do that. Every transition has an event source
|
||
and an observable result. `screenLocked` is the request; `screenLockSecure` is
|
||
the compositor acknowledgement.
|
||
|
||
The implementation sequence is:
|
||
|
||
1. Add one `IdleCoordinator` that owns the staged state and form-factor
|
||
thresholds. It consumes native `IdleMonitor` events when verified on the
|
||
target; the Pixel can retain the hypridle adapter behind that interface.
|
||
2. Add a logind event watcher for this session's `Lock` and the manager's
|
||
`PrepareForSleep` signal.
|
||
3. Hold a delay-mode sleep inhibitor while the shell is running. Release it
|
||
only after the Wayland lock is secure; re-acquire it on wake. Measure the
|
||
actual logind delay budget on the Pixel 3.
|
||
4. Make `idle`, `sleep`, `logout`, and `user-switch` explicit inhibitor kinds.
|
||
Only expose a kind after it owns a real backend. `idle` is the sole
|
||
implemented kind today.
|
||
|
||
## Wallpaper should be an asset, not a path
|
||
|
||
The current background path gives every output the same image and asks crop to
|
||
solve incompatible aspect ratios. A downloaded landscape image consequently
|
||
loses its subject on the phone. Preserve originals, but track a portable asset
|
||
record:
|
||
|
||
```
|
||
id, originalPath, origin, licence, palette,
|
||
focalPoint(x,y), safeRegions[],
|
||
variants: { landscape, portrait, square },
|
||
previewPath, generatedAt
|
||
```
|
||
|
||
Selection order for a screen is:
|
||
|
||
1. Use an explicit per-device assignment when the user set one.
|
||
2. Select a sufficiently close aspect-ratio variant.
|
||
3. Crop a derived local variant around `focalPoint` while preserving a
|
||
`safeRegion`; never overwrite the original.
|
||
4. Fall back to a blurred/palette background with the image contained, rather
|
||
than crop the only meaningful part away.
|
||
|
||
ii's existing least-busy-region analysis is useful twice: place a clock/card
|
||
where it does not cover the subject, and propose an initial safe region.
|
||
However, it must run against the **actual output crop** and card dimensions,
|
||
not a fixed 300×300 desktop widget. A manual focal-point editor is the escape
|
||
hatch; an analyser may propose, never silently decide.
|
||
|
||
For the lock surface, prefer a frozen screencopy or an already-derived local
|
||
variant over downloading or decoding a remote wallpaper at lock time. Locking
|
||
must remain instant and work offline.
|
||
|
||
## Proposed Souveraine map
|
||
|
||
```
|
||
modules/common/functions/Session.qml lifecycle verbs + IPC projection
|
||
services/SessionEvents.qml logind Lock / PrepareForSleep ingress
|
||
services/IdleCoordinator.qml transition graph + target adapters
|
||
services/LockContentPolicy.qml card tier / field visibility decisions
|
||
modules/ii/lock/LockSurfaceHost.qml shared card host
|
||
modules/ii/lock/cards/ Clock · Media · Notifications · Continuity · AmbientAgent
|
||
services/StepUpAuth.qml independent PamContext + expiring grants
|
||
services/WallpaperAssets.qml asset records, variants, safe regions
|
||
```
|
||
|
||
None of these are separate session managers. They are consumers of the single
|
||
`session` lifecycle and its state projection.
|
||
|
||
## Build order
|
||
|
||
1. **Truth before visuals:** logind event ingress, delay inhibitor, and
|
||
`IdleCoordinator` with a visible transition log. [done — SessionEvents.qml, delay inhibitor in SessionEvents, IdleCoordinator extended with sleep states]
|
||
2. **First lock cards:** clock/date, battery, transport-only MPRIS. Add the
|
||
metadata privacy switch before title/artist/artwork.
|
||
3. **Continuity:** timers, ongoing call, navigation, and notification summary
|
||
cards with per-field redaction.
|
||
4. **Trust:** ambient-agent allowlist, lock-time response redaction, then
|
||
`StepUpAuth` and action-family grants. [partially done — StepUpAuth.qml built, minTier wiring and ambient-agent allowlist remain]
|
||
5. **Wallpaper assets:** per-device assignments, focal-point editor, derived
|
||
portrait/landscape variants, and crop-aware card placement.
|
||
|
||
The first useful vertical slice is therefore not a huge lockscreen redesign:
|
||
one shared `LockSurfaceHost`, a transport-only media card, a real staged idle
|
||
state projection, and a wallpaper asset descriptor. It proves the architecture
|
||
on both shapes without committing personal data to the lock surface.
|