Watch
1
0
Fork
You've already forked souveraine
0
Commit graph souveraine/surfaces/quickshell/modules/common
Author SHA1 Message Date
Fimeg
44acb11ab5 shell: two faults the load found that no gate did
Both were live in the running shell and invisible to every check that ran
before it. Found by reading the shell's log after Casey applied.

ThinkingCard: missing `import qs.modules.common.functions`

  ReferenceError: ColorUtils is not defined, on every render of every
  reasoning segment. My own defect, shipped through a lint that said clean.

  The lint was blind because I staged an approximation of the composed tree by
  hand instead of linting the composed tree itself. Against the real composed
  tree qmllint reports it plainly: 1 ColorUtils diagnostic before, 0 after.
  Lint the composed tree. A hand-built stand-in tests the stand-in.

Config: sidebar.ai.fontSize restored

  MessageTextBlock (vendor) reads Config.options.sidebar.ai.fontSize and got
  undefined, assigning undefined to font.pixelSize on every text render.
  Pre-existing, not from 0008 — the vendor delegate used MessageTextBlock too.

  Cause is structural: modules/common/Config.qml SHADOWS ii-base's Config
  wholesale, so every key ii-base adds after the fork silently disappears. The
  key even carries an ii-base comment explaining it was added deliberately as
  a live theme binding. Nothing failed; a number was just quietly absent.

  Restored as a live binding, never a literal and never null
  (null-in-a-serialized-config, 2026-08-11).

Verified: shell alive 12s after the Config edit (the crash-loop window),
config.json 46 keys and zero nulls, both fault lines gone from the log.
2026-08-12 14:51:09 -04:00
Fimeg
f7e0e51116 config: never store a null option
Null-valued options serialised into config.json and segfaulted
JsonAdapter on the next launch, killing the shell after load.
Tristate strings (auto/on/off) with boolean fallback.
2026-08-12 09:23:19 -04:00
Fimeg
12da479c23 bar: finish the shared resource widget 2026-08-11 18:40:35 -04:00
Fimeg
391e239010 bar: one BarContent for every device, layout as data
ii-base and ii-phone each carried a 357-line BarContent to express eight
differences, all of them either "is this widget shown" or "which slot is
it in". No behaviour differed. Every bar edit had to be made twice or
diverge silently against the pin.

Widgets are now declared once as Components in a registry; each slot is a
Repeater over a list of widget names, so placement and order are data.
Config names a slot or a device profile picks it. "auto" derives the
profile from the same cramped-ness test behind useShortenedForm, so the
phone keeps its arrangement with no config file. Loaders are active only
when placed, so an unplaced widget is never constructed.

The agent island becomes a placeable widget rather than a mount smuggled
into UtilButtons: it reaches every device bar from one declaration.

ClockWidget is unified for the same reason. Its phone fork existed solely
to add customFormat, which BarContent now sets on every device.

bar.agentSessions was landing under background.widgets, not bar, so
Config.options.bar.agentSessions was always undefined and only the ?? true
fallback made the island appear wired. Moved, and merged into the existing
bar.indicators rather than declaring a second one.
2026-08-11 14:40:07 -04:00
Fimeg
658217e72e polkit: add temporary FPC confirmation 2026-08-10 20:46:28 -04:00
Fimeg
902a724855 lock: add FPC wiring preview 2026-08-10 20:10:50 -04:00
Fimeg
5c44ea06d5 dock: scale it up, and put the scale in settings
44px buttons with 35px icons read small on a 540px panel, and a stack's
members were 12px inside a 35px box — unreadable, which is the whole job of
the collapsed form. 56/44 now, and the member icons give back the border and
padding that were being subtracted from them as well as the grid spacing.

Both numbers live in Config so this is a setting rather than a rebuild, with
spin boxes in Settings > Dock. Two numbers and not one ratio: the button is
the row's height and the icon is what you see, and fixing the ratio would
mean either cramped icons in a tall row or icons overflowing a short one.
2026-08-07 02:04:12 -04:00
Fimeg
bf8bc013ef three-finger tap opens a window sheet, not the overview 2026-08-05 14:12:22 -04:00
Fimeg
80cb4b289d shell: read the instance file synchronously, or it is empty when asked
FileView loads async, so text() was still empty when onReadyChanged read it
once to decide whether this is a new session. It fell through to the unset
env var and persisted "" — the same bug, reached by a different route.
Verified on device: the stored signature now matches viewtop.instance.
2026-08-04 19:25:59 -04:00
Fimeg
95dd21b998 shell: take the instance signature from viewtop, not from Hyprland's env
HYPRLAND_INSTANCE_SIGNATURE is unset under viewtop, so this compared "" to
"" and isNewHyprlandInstance was false on every start. It gates
lock.launchOnStartup, which has therefore never fired once under viewtop,
and both Idle.qml copies read it as well.

viewtop publishes viewtop.instance beside its control socket — pid plus
startup nanos, different every start. Read that first, fall back to the env
var so a Hyprland session (the laptop is still one) keeps working, and
treat "neither" as the session continuing, which re-locks rather than
assuming a fresh boot.
2026-08-04 19:19:31 -04:00
Fimeg
266af98a99 sessiond: double-tap-to-wake wakes, and the volume keys work again
Two things that worked under Hyprland and stopped when viewtop took the
session, both for the same reason: the binding lived in hyprland.lua and
the daemon was never in the path.

dt2w: note_input recorded the wake and returned Restore, which is
brightness. So a double tap reported to the machine and the screen stayed
dark. It now returns Unblank first — the brightness a panel comes back at
means nothing until the panel is back. Only for the deliberate wakes
(DoubleTapToWake, Squeeze) and only when the panel is actually dark. The
power button is excluded on purpose: apply_gesture already wakes on its
resolved tap, and emitting a second unblank here is precisely how the
wake loop happened in the compositor this afternoon.

Volume: Action::Volume through the executor table, per §12 — a small
daemon reading a signal and calling wpctl is the eighth blind actor. It
fires on the DOWN edge rather than from a recognised gesture, because
BUTTON_MULTI_TAP_WINDOW is 300ms and a volume key that lags a third of a
second behind the press feels broken. The recogniser still sees the
edges, so a future binding table gets volume hold-to-ramp without this
changing.

Shell: HyprlandData did a bare JSON.parse on hyprctl output, which throws
on every refresh when there is no hyprctl — six exceptions a pass, and
every consumer of monitorData.scale got undefined. That is why the region
selector rendered as a sliver: the geometry was not wrong, it was NaN.
Absence is now a latched state, and RegionSelection/OverviewWidget fall
back to screen.devicePixelRatio. Hyprland stays preferred where it exists.

105 tests.
2026-08-02 18:28:49 -04:00
Fimeg
94988138b4 lock hint: resolve the seat's session, and replay the report
LockedHint was never set on this device, so sessiond's `locked` (which
comes from logind per doctrine §4) was permanently false, request_blank()
timed out LOCK_ACK_BUDGET on every blank, and the panel went dark on a
session nobody could confirm was locked. LOCK-DPMS-LESSONS §1 held in the
code and not on the glass — every blank recorded blank-without-lock.

Three faults, measured 2026-08-02:

- Session.qml wrote the hint through /session/auto, which is the caller's
  own session. The shell is not in the session that owns the seat:
  viewtop in logind 66 (seat0/tty1), qs in 70. Written to one session,
  read from another.
- lockhint.rs resolved via User.Display, which an ssh login is enough to
  point at a seatless remote session — and which then went stale when
  that session ended. Both sides now ask seat0 for its active session.
- The report was dropped outright. hasLoginctl starts false and only
  flips when a Process probe returns; secure=true landed 30s earlier, so
  the one edge that mattered hit the guard and was never retried, because
  the shell locks once at boot and never changes again. Fourth
  edge-vs-level bug after locked_ack, ChargeRate and bootBloomActive.

Verified on hardware: LockedHint now goes yes ~2s after a power tap.
2026-08-02 15:26:37 -04:00
Fimeg
efe2d0d1e0 lock: adopt the session lock across a scene reload
sessiond admits shell_ready from the lease holder's own pid; the shell
carries its lock request through the reload so WlSessionLock adopts the
existing lock instead of taking the unlock branch on it.
2026-07-31 14:32:29 -04:00
Fimeg
0b57daac06 shell: VPN quick toggle in the right panel
Deliberate, never automatic. The autonomous gate it replaces recycled the
tunnel 652 times in 90 minutes and could not be switched off, because
'nmcli connection down' fired the dispatcher that brought it back up.

Reads NM for state rather than tracking a bool. No privilege needed: polkit
already lets the seat user activate a system connection. Registered in the
ii-phone chooser as well as ii-base, or the phone overlay wins and the
delegate never appears.
2026-07-30 19:13:19 -04:00
Fimeg
147999a918 Selection service: compositor-wide primary selection for TASK-18
Verified on blueline that Hyprland advertises primary-selection plus both
data-control managers, so wl-paste --primary --watch sees every selection with
no per-app hooks. Settles TASK-18's selection-detection question as
compositor-level; viewtop is not needed.

The protocol gives no selection rectangle, so anchor is the pointer position at
selection time. Opt-in by default: the watcher observes every highlight on the
device, including passwords, so it is killed while locked and selection text is
never persisted, logged, or trailed.
2026-07-29 17:25:34 -04:00
Fimeg
0a635ff984 lock: dismiss the boot bloom on a level, not only on an edge
bootBloomActive defaults true on every scene construction and bootDismissed
resets with it, but the only thing that cleared them was the secure EDGE. A
scene reload during an already-secure lock never moves `secure`, so nothing
cleared the bloom and the phone sat under a full-screen white overlay until the
shell was restarted. Casey hit it and reported it as "the hyprland error
screen"; `grim` returned a solid white 9KB frame, and hyprctl configerrors was
empty the whole time.

Third instance of this exact shape: locked_ack after a sessiond restart, the
ChargeRate stale-scene reload, and now this. Check the level at construction as
well as the edge.

Deliberately not a timeout — a bloom outliving its reason is a bug to locate.
2026-07-29 10:54:45 -04:00
Fimeg
43c1fdbc05 session: one IPC owner for target 'session', not a load-order coin flip
Session.qml and Lock.qml both registered target 'session'; quickshell keeps
whichever loads first and drops the other. Lock.qml's handler is a strict
superset, so the duplicate goes.
2026-07-26 19:04:14 -04:00
Fimeg
4d64b4540c polkit: stop the prompt covering the on-screen keyboard
The fullscreen overlay sat above squeekboard's layer and owned the whole
screen's input region, so taps in the keyboard area hit the dialog. It now
yields the bottom third while the OSK is up. Exclusive keyboard focus was
tried and reverted — it stopped the keyboard taking touch entirely.
2026-07-26 17:39:38 -04:00
Fimeg
4f113ad62d shell: the dim is a grace before the lock, not a second absolute timer 2026-07-26 15:09:17 -04:00
Fimeg
19fe6b1d0e shell: dock reorder, fullscreen detection fix, idle-power, sessiond, misc shell work
- Dock drag-to-reorder for pinned apps (insertion gap, quick-slide vs dwell)
- Fullscreen detection: scan all windows via HyprlandData.windowList
- IdleCoordinator, GlobalStates, Session.qml updates
- Deploy script, qmldir, settings, wallpaper, visualizer fixes
- sessiond server, memory module updates

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-22 22:18:20 -04:00
Fimeg
db6d732e32 shell: regenerate qmldir manifests from the composed tree
The repo qmldirs listed only repo-owned types; composed dirs also carry
ii-borrowed types (ReloadPopup, PanelLoader, Bar, ...) which a qmldir
present in the dir must list or they stop resolving — broke the phone
shell on deploy. Regenerated every deployed qmldir from the composed
config on-device (capitalized .qml -> type line, pragma Singleton ->
singleton line) and pulled back. Shell verified active, zero load
errors.
2026-07-21 13:36:39 -04:00
Fimeg
271e4f2cc2 shell: add missing qmldir manifests + rail OSK layer fix
19 dirs had .qml but no qmldir -> quickshell config load failed
(File not found @ shell.qml[-1:-1]). Corrected singleton decls in
3 existing qmldir. SystemGestureRail: pill->WlrLayer.Top, oskLift
200, drop oskOpen hide.
2026-07-21 13:01:58 -04:00
Fimeg
402e887dfc settings: Speech page — STT/TTS endpoints with live health probe
speech.stt/speech.tts land in Config so the settings page, the
souveraine-stt CLI, and the keyboard mic key all read one source of
truth. STT defaults to the VPN faster-whisper bridge; the page probes
/health so configured and answering are visibly different states. TTS
is a field waiting for a server.
2026-07-21 09:58:09 -04:00
Fimeg
90077bb1ea lock: notifications card + NotifyEvents fan-out seam, battery fraction fix 2026-07-21 08:17:54 -04:00
Fimeg
5083954c38 lock: own backdrop with wallpaper option, am/pm clock
The session-lock surface was transparent with nothing painting behind it.
TouchLockSurface now owns its backdrop: lock.wallpaperPath when pinned,
else the system wallpaper, else a dark field — plus a scrim for glance
legibility. Glance clock gains lock.twelveHourClock (default on, h:mm ap).
LockConfig grows the wallpaper picker (same FolderListModel grid as the
wallpaper page, no matugen side effects) and the 12-hour switch.
2026-07-20 22:47:11 -04:00
Fimeg
d027251024 session: use systemctl for power verbs, not loginctl
loginctl manages sessions/users/seats only — `loginctl poweroff` exits 1
"Unknown command verb". Preferring it silently broke poweroff/reboot/
suspend/hibernate from every shell surface. Use systemctl; fall back to
loginctl only on elogind systems where it does carry power verbs. The
logind D-Bus capability probe (CanPowerOff etc.) is unchanged — logind
owns policy, systemctl carries out the action.
2026-07-20 17:51:30 -04:00
Fimeg
e3cf50bf75 quickshell: boot bloom overlay + native pipewire audio
The C splash now plays only Acts I-III and hands off at ~6.8s; a new
BootBloom layershell overlay (modules/souveraine/boot) resumes Acts IV-V
(Souvie + bloom flower) over the live compositor, clock-aligned to the boot
epoch so the animation is continuous across the process swap. It maps as
Hyprland's first surface (top-level in ShellRoot, before Config.ready),
pokes splash-signal on its first frame to release the GPU, and LockScreen
clears bootBloomActive on secure to fade it out and reveal the lock. Bloom
shader is qsb-compiled from BootBloom.frag at deploy time.

Drop services/Audio.qml from the manifest: it was a pactl mirror written
for native PulseAudio and only tracked the default sink/source. The phone
runs PipeWire now, so ii's native Pipewire Audio service (full graph,
WirePlumber-owned volume) takes over.
2026-07-20 17:51:23 -04:00
Fimeg
a2320641a3 restore LockContext.qml (recovered from live phone deploy)
Deleted from repo in a prior session while reverting an experiment;
never should have removed a file that wasn't reverted alongside it.
Pulled back from the phone's live ~/.config/quickshell deploy, which
was still running the correct version the whole time.
2026-07-20 07:58:35 -04:00
Fimeg
5cb1be06cd lock primitives: power-from-lock, login1 polkit rule, gesture rail progress
seat0-active polkit rule so power off/reboot/suspend stop returning
challenge into a session with no polkit agent on the lock surface.
Lock-surface buttons stay gated behind allowPowerFromLock (opt-in) and
requirePasswordToPower. SystemGestureRail progressive gesture + mission
control nav flag.
2026-07-19 22:13:08 -04:00
Fimeg
4fe27d9ef5 lock: resync screenLocked when compositor ends our lock
ext-session-lock finished (another client held the lock) drops
WlSessionLock.locked C++-side; the request bool never heard about it.
Stale true lied to redaction/capability gates and blocked re-locking
(the binding only fires on a false->true edge).
2026-07-17 06:17:53 -04:00
Fimeg
50530b1159 fix lock feedback loop + impatient sessiond boot lock
Session.lock() notified logind unconditionally; hypridle's lock_cmd fires
on logind's Lock signal, so every lock echoed back through logind ->
hypridle -> lock() forever. Observed: ~450 lock requests/min for 7 minutes,
re-locking the screen seconds after each unlock. Notify only on the
unlocked->locked edge.

sessiond gave up waiting for the compositor lock ack after one dispatch —
at boot Hyprland defers the ack while the splash holds DRM, so the initial
lock silently failed (journal: 'never acknowledged', 0.7s in) and boot ran
on the legacy lock path. Wait up to 60s for locked/finished.
2026-07-17 06:01:36 -04:00
Fimeg
856c6e5576 sessiond: session authority daemon — lock-before-shell, lock-past-shell-death
ext-session-lock client that locks at session start, hands the lock to the
shell over a runtime socket without an unlocked instant (abandon + restore),
and retakes it the moment the shell heartbeat drops. Spartan PIN fallback
surface, PAM via hand-rolled libpam FFI, machined-style sync server.
Shell side: SessiondBridge singleton + LockScreen initIfReady routes the
startup lock decision through the handshake.
2026-07-16 20:32:46 -04:00
Fimeg
b18fa331e0 idle: wire the dim stage and native-coordinator hardening
Dimmed now actually lowers the backlight (brightnessctl save/restore)
and Active restores it - previously dimRequested had no consumer, so
auto-dim never existed on this stack. Keep System Awake is checked
inside the monitor handlers rather than bound to enabled: recreating
the ext-idle-notify object during lock teardown is a fatal Wayland
protocol error on the Pixel compositor. Defaults now mirror the
hypridle timers (dim 120s, lock 300s).
2026-07-16 17:44:01 -04:00
Fimeg
c96f95b9da quickshell: fix drag-to-combine, rail rides the keyboard, overview gap-tap dismiss
The drag ghost was anchored (centerIn) — Qt won't move an anchored
drag.target, so no DropArea ever fired and stack creation died silently;
position it on press instead. Drag lifecycle now sets dockDragInProgress
(the DockManifest guard finally has a writer). Restored pulseDockReveal,
lost in a refactor while its osk.pulseDock caller survived.

Rail lifts atop squeekboard by measured layer height (hyprctl -j layers,
namespace osk); swipe down dismisses the keyboard first, then a visible
dock in any state (new dockSuppressed, cleared by swipe up). Overview:
taps in the grid's dead space dismiss it instead of being eaten.
DockConfig grew the real pins/stacks editor (unpin, rename, unstack,
dissolve).
2026-07-16 12:04:08 -04:00
Fimeg
72b01457d2 quickshell: restore ii-stock config keys the fork dropped
Config.qml regained sidebar.width/widthExtended (their absence collapsed
the right sidebar PanelWindow to 1px — 'unclickable' on the laptop), plus
lock.dpmsTimeout, lock.unlockHook, and autoIdleInhibit with its Idle.qml
property. Audio.qml's absent capture source is now a zero-volume stub so
stock consumers stop dereferencing null, and the pactl status parse runs
under LC_ALL=C. volumeMixer dialog content comes along for the sidebar.
Findings logged in SouveraineOS/docs/DUMP-power-idle-lock-2026-07-15.md.
2026-07-16 08:06:11 -04:00
Fimeg
13cded0087 fix: Timer not available in functions module, use Process instead 2026-07-14 22:15:10 -04:00
Fimeg
e17f02b030 fix: add missing QtQuick import to Session.qml (Timer needs it) 2026-07-14 22:05:46 -04:00
Fimeg
10c206c09c fix: Component.onCompleted doesn't work on QML Singletons
Replaced with Timer { interval: 0; running: true } in:
- Session.qml (boot IPC audit)
- SessionAudit.qml (init log)
- SessionEvents.qml (init log)
2026-07-14 21:58:02 -04:00
Fimeg
a8fd510dc7 session trust phase 1: logind ingress, sleep inhibitor, step-up auth
Phase 1 of the SouveraineOS homogenization — the three highest-priority
gaps from the session trust architecture:

New files:
- services/SessionEvents.qml — logind event ingress (PrepareForSleep,
  session Lock signal) via gdbus monitor; delay-mode sleep inhibitor
  held from startup, released only after WlSessionLock.secure
- services/StepUpAuth.qml — step-up PAM authentication with short-lived
  in-memory grants per action family; revokes on lock/timeout/failure
- TRUST-BOUNDARY-MATRIX.md — every session operation classified by
  caller type, auth gate, and enforcement status

Modified:
- IdleCoordinator: extended with Suspending/Asleep/Waking states for
  the sleep lifecycle; wires to SessionEvents when present
- Session.qml: added sleep inhibitor kind, stepUp/sleepInhibitor
  state in IPC projection, boot-time IPC audit log
- Config.qml: added lock.stepUp config section (enabled, grantTtlMs)
- LockConfig.qml: added step-up authentication settings section
- deploy.sh: added SessionEvents and StepUpAuth to manifest
- SESSION-TRUST-ARCHITECTURE.md: marked phase 1 items as done
- REFERENCE-EXTRACTION.md: marked build order items as done
2026-07-14 20:48:46 -04:00
Fimeg
e31c3aaf62 quickshell: first-party lock/nav/session layer, retire the pill
Grows Souveraine's own surfaces on top of the borrowed ii shell and drops
the separate pill shell in favor of one integrated navigation rail.

Session arbiter (functions/Session.qml): probe logind's Can* methods over
busctl instead of guessing from installed binaries -- the answer carries the
polkit tier (yes/challenge/na), so a swapless phone reports hibernate as na
and refuses honestly rather than firing a verb that no-ops. Verbs run through
a Process that logs exit codes and tracks lastAction; refusals log too. The
busctl output is parsed with awk, not a sed regex buried under four escaping
layers -- the sed version returned nothing on the phone and left every
capability stuck at "unknown" (invisible on the laptop, where timing masked
it). Every structured result is JSON-over-string; quickshell maps a var
return to void.

Lock trust: screenLocked (the shell's lock request) is now distinct from
screenLockSecure (WlSessionLock.secure, the compositor's acknowledgement,
mirrored from LockScreen). Cards that disclose personal data gate on secure,
not on a button press. LockContentPolicy centralizes the ambient/personal/
step-up tiers so no card grows its own private rule.

New first-party namespace modules/souveraine/: LockMediaCard, LockSurfaceHost,
SystemGestureRail -- owned surfaces, not ii patches. IdleCoordinator gives one
staged idle vocabulary (dim/lock) gated behind nativeCoordinatorEnabled, off
until the native Wayland idle-notify is verified on the Pixel compositor;
hypridle stays the adapter. WallpaperAssets selects aspect-aware variants for
phone-vs-laptop display shapes.

Pill retired: pill/shell.qml and PillConfig gone, replaced by NavigationConfig
and the gesture rail. Hyprland starts qs -c souveraine directly; no secondary
shell, no qsConfig flip.

Verified on the phone: session.* reports challenge/na correctly, hibernate
and unlock refuse, inhibit round-trips with its reason.
2026-07-14 20:00:57 -04:00
Fimeg
cecde3bac2 quickshell: session arbiter + fix IPC returns silently dropping payloads
Fork ii's Session singleton and add a sessionctl.* surface.

The IPC bug is the important half. Quickshell marshals exactly five types
(string/int/bool/double/color) and maps a `var` return to VOID, discarding
the payload with no error -- src/io/ipc.cpp, "void and var get mixed by qml
engine". dock.*, shell.* and apps.* were all declared `: var`, so they
registered as `(): void` and returned nothing at all. The {ok, reason}
contract has never once reached a caller. All of them now return JSON as a
string, which is what actually crosses the socket.

Session: upstream fires `systemctl X || loginctl X` detached and throws the
exit code away. Fine on a desktop with someone at the keyboard, not fine on
a phone where the shell is the session manager and a verb that silently does
nothing leaves you believing the machine is suspending when it isn't. So:
probe loginctl/systemctl/hibernate once instead of assuming, run verbs
through a Process that logs the exit code, and refuse honestly when the
machine can't do the thing (the phone has no swap -- hibernate now says so
instead of no-opping). Every upstream verb keeps its name and call sites.

Inhibits carry a mandatory reason and get a cookie; state() lists who is
holding the machine awake and why. "Why didn't it sleep" is now answerable.
unlock() is refused by design -- the lock is the credential gate, so no IPC
caller routes around the PIN pad.

Named sessionctl, not session: ii's SessionScreen already owns "session",
and quickshell drops duplicate targets silently rather than erroring.

Idle: drop the 2>/dev/null and run hypridle through a Process, so a unit
that fails to come back is a log line instead of a flat battery.

Verified on the laptop: inhibit stops hypridle, uninhibit brings it back.
2026-07-14 18:31:59 -04:00
Fimeg
c78c5510af quickshell: run as qs -c souveraine + dock/shell/apps method surfaces
Own config name composed by deploy.sh from our files + pristine-ii dir
borrows; ii tree stays untouched. One SouveraineFamily, two modes gated
on souveraine.phone.

Three guarded IPC surfaces for the agent (via Souveraine's harness, not
a new integration): dock.manifest/pin/unpin/restack, shell.surfaces/state
(layer registry, live-derived), apps.list/get/find/categories (.desktop
scan). Refusals are result shapes, not errors.

Settings app split into per-domain pages (Device/Lock/Dock/Pill/Keyboard).
Config backports (background.widgets, claudeUsage, fileSearch) kill the
laptop TypeErrors.
2026-07-14 15:03:07 -04:00
Fimeg
72f5169458 quickshell: touch PIN lock screen for the phone
The OSK is layershell and can't rise above a session lock, so the lock
surface carries its own keypad. Lock state persists to states.json so a
qs crash while locked comes back locked; with lock.launchOnStartup the
lock screen is the greeter (greetd autologins straight into Hyprland).
Keypad gated behind lock.touchKeypad so desktop deploys keep the stock
surface.
2026-07-13 15:19:59 -04:00
Fimeg
ec7c4e8e8c quickshell: dock geometry/icon-centering, GlobalStates, ConflictKiller service
Dock + pill z-order and icon centering pass; GlobalStates.qml and a
ConflictKiller service for the ii sidebar.
2026-07-12 14:56:56 -04:00
Fimeg
8915ac2a1a dock/pill: movement cancels hold-menu, folder-style stack icon, tap focuses running member; lua-fork hyprctl dispatch syntax; kill AiChat/notification TypeErrors 2026-07-12 09:51:09 -04:00
Fimeg
037dc06922 surfaces/quickshell: bring the phone shell under the surface tree
Dock fan-out stacks, drag-to-combine, pill gesture rewrite, and the ii
patch set (TaskbarApps stacks API, Config dock.stacks schema) — pulled
from the live phone and made canonical here. deploy.sh grew a manifest
and a --phone mode: rsync the surface over, symlink ii into it, so live
edits land in a git tree instead of drifting.
2026-07-12 08:57:10 -04:00