Watch
1
0
Fork
You've already forked souveraine-viewtop
0
Commit graph

138 commits

Author SHA1 Message Date
Fimeg
52700e924e public: carry the ViewTop x86 session edge
Expose the package-owned session entry without carrying the private build and archive workflow. The public recipe continues to name Forge as its source.
2026-08-25 21:51:41 -04:00
Fimeg
fb74c9c6a3 readme: describe the kms path that exists 2026-08-24 14:04:28 -04:00
Fimeg
0c95bb6758 survive a transient lookup while assembling the sysroot
The gate failed on name resolution for the package archive after apt had
already succeeded in the same job -- intermittent, not configuration.
2026-08-23 21:30:20 -04:00
Fimeg
d277802180 project the tested ref onto the public forge 2026-08-23 21:10:28 -04:00
Fimeg
8ec3aa5fb6 add the cross libc the aarch64 link needs
gcc-aarch64-linux-gnu ships the compiler, not the target startup files;
without libc6-dev-arm64-cross ld cannot find Scrt1.o.
2026-08-23 21:07:14 -04:00
Fimeg
493322dc64 retrigger: the smithay dependency is now public 2026-08-23 20:59:02 -04:00
Fimeg
df3b56f933 prove the phone binary carries nothing from the build host
Eight checks after the link: AArch64 ELF, expected loader, no embedded RPATH,
and every DT_NEEDED resolving to an aarch64 object inside the constructed
sysroot. CI builds that sysroot in runner temp from empty, so nothing survives
between runs to become part of the contract again.
2026-08-23 18:53:36 -04:00
Fimeg
6ddcffe334 assemble the phone sysroot from declared inputs
It was a directory on one machine with no record of its contents, which made
the only build that can take the panel reproducible by one person. 155 arm64
packages now resolve from 12 requirements derived from the kms feature, each
verified against the archive index.
2026-08-23 18:43:53 -04:00
Fimeg
9e9e433938 stop tracking the mechanism's bytecode
Compiled copies of the scanner carry its rule literals into the tree as bytes
no reviewer reads, and they change on every run. Ignored.
2026-08-23 18:00:32 -04:00
Fimeg
684e4569c2 run the public gate on the ordinary runner class
Toolchain, aarch64 target, cross linker and smithay's dependency list are
declared here instead of assumed from the build host. The phone KMS build is
named as absent and why -- it needs a target sysroot no workflow can declare.
2026-08-23 18:00:19 -04:00
Fimeg
505a3220a9 mechanism v1, matrix-capable gate evaluator
Selection for matrix gates is an explicit enumeration; the prefix count is a
tripwire only. The pinned digest moves with it, so an un-updated copy stops
the job rather than changing what "checked" means.
2026-08-23 17:47:52 -04:00
Fimeg
18d3781c2a deps: pin the fork tip that explains itself
Same code; the revision now lands on the commit carrying the fork rationale,
so a reader following the dependency arrives at the explanation.
2026-08-23 11:44:19 -04:00
Fimeg
dd9f5ea862 publication: bless the gate's own install commit 2026-08-23 11:39:31 -04:00
Fimeg
e1bf4d995c publication: install the gate and bless the history
Twenty commits carry internal topology in their diffs and two in their
subjects. No secrets, and the tree at HEAD is clean, so the accepted history
cannot excuse anything live.
2026-08-23 11:39:05 -04:00
Fimeg
4adf8c0bbb public: cut the internal half out of the projection
Build and test stay; packaging, signing and archive publication do not, and
neither does the operator harness. Four references to the build host become
generic, package URLs point at the public forge, checkout is SHA-pinned.
2026-08-23 11:38:28 -04:00
Fimeg
a6859d8f7c deps: point smithay at the published fork
The dependency was pinned to a host no one outside the house can reach, so a
public clone could not resolve it. Same five patches, same tree; the revision
moved because two commit identities were corrected before first publication.
2026-08-23 11:38:28 -04:00
Fimeg
b8a56049c8 merge the packaged session start path 2026-08-17 10:52:14 -04:00
Fimeg
e8e3f9b1b4 package: carry the whole session start path 2026-08-17 10:51:56 -04:00
Fimeg
3431223b1f xdg: tell a tiled window it is tiled, and retile when one floats
Size alone is a hint to a floating toplevel. Firefox kept its CSD shadow
and drew 504 of the 540 it was told; kitty obeyed, which made it look
like Firefox's fault. Four tiled edges, unset again on place.

unplace() has always retiled and place() never did, so floating half a
split left the other half at its old rect over live dead space.
2026-08-16 14:01:39 -04:00
Fimeg
41f07b1411 touch: only frame a group that reached a client
wl_touch.frame closes a group of delivered events, and most contacts on
this device never reach one — the rail, dock and pill are shell surfaces.
One warning per touch, 3034 in a session, burying the starved evidence
queue underneath them.
2026-08-16 13:58:33 -04:00
Fimeg
7883f7d118 session: ask for the targets in a way systemd will answer
graphical-session{,-pre}.target are RefuseManualStart=yes, so the launcher's
start on them failed every boot from 2026-08-15: sessiond never came up, viewtop
started locked, and the panel was black. A dependency may pull a refused target
in where a direct request cannot; these two do that and nothing else.
2026-08-16 10:31:37 -04:00
Fimeg
55f93a0688 input: hit-test a window in its own coordinate space
window_local_under answers relative to the window rectangle; Window::surface_under
walks from offset (0,0) and reads its argument as relative to the buffer. Those
differ by geometry().loc — the inset a client-side-decorated app declares its
window at inside a buffer that also holds its shadow. The render already
subtracts it, so every lookup landed a shadow-width up-and-left of the finger
and Firefox had to be aimed down-and-right of anything you wanted to hit.
2026-08-15 23:15:49 -04:00
Fimeg
1d6d7c127f workspaces: report what a client drew, not only what it was told
size is the rect the configure asked for. A client laying out against
something else keeps rendering its own, and since contacts are mapped through
the rect, the error grows with distance from the window's origin — which is
what "everywhere I tap is off, and it depends where I tap" looks like from the
outside. Nothing reported the drawn rectangle, so nothing could see it.
2026-08-15 23:10:16 -04:00
Fimeg
78f885e5d8 state: report who holds the keyboard
An on-screen keyboard has nothing to enable against when nothing is focused, so
"tapping the field does nothing" and "no surface has focus" looked identical
from outside the compositor — and no verb could tell them apart. TASK-59's rule:
what is invisible on the glass is reported.
2026-08-15 22:53:34 -04:00
Fimeg
1f478429c1 atmosphere: dissonance can strike instead of hold
Casey on the glass: held at weight it is a distortion to look past, "sexy IF
it's very brief". A strike is 370ms end to end on one shared envelope — rise 90,
hold 60, fall 220 — and clears any standing weight, because a pulse that left
the screen fractured behind it is not a pulse. Blink reads the same envelope.
2026-08-15 22:31:59 -04:00
Fimeg
b7ef258271 atmosphere: the blink's curve, on the one clock
TASK-52 #15. The dim inverted — expose and dissonance ease toward a level and
stay, this rises, holds and returns to nothing without being told to. That is
the whole technique: a presence you have to dismiss is furniture, one that
leaves on its own is weather.

Peak 0.12 so everything underneath stays readable through her; the fall is more
than twice the rise, because symmetric timings read as an element flashing. Both
chosen by eye and both said so. Absent between blinks — None rather than a zero
alpha, so the render path can skip a full-panel quad instead of compositing a
transparent one sixty times a second. Re-firing restarts; two at once would be
one blink at twice the alpha.

Not wired. The surface it drives does not exist yet: wayland.rs:186 says a
second piece of furniture arrives as a declared role on the wire and not another
app_id constant, so the veil wants a role that is full-panel, input-transparent,
and above everything but the lock. The curve is landed first because it is the
half that has to feel right, and it is the half a test can hold.
2026-08-15 21:36:18 -04:00
Fimeg
5d6f0f0a90 atmosphere: dissonance is a verb
TASK-52 #6, the chromatic split. `{"intent":"dissonance","amount":0.35}` sets a
0..=1 weight — the agent composes attention and the compositor owns the mapping
to texels, so nobody outside has to track the panel's geometry. Optional angle
for the fracture's axis; it lands instantly while the amount eases, because an
axis is a direction the effect has and not a place it travels through.

atmosphere.rs owns the dial and the one settle rate, which the exposure ease now
reads too — TASK-52's whole warning is fifteen animators growing fifteen timers
and beating against each other.

The split is renderer state, not an element, so damage tracking cannot see it
move; the render path clears the buffer ages while it eases or the loop goes
idle one frame in and the fracture stops half-open. Captures are exempt: a
screenshot is a record and a record that came out fractured is unreadable.

Refuses `unavailable` when the driver would not compile the shader, rather than
accepting a look and showing nothing.
2026-08-15 20:59:48 -04:00
Fimeg
3d6af624fe atmosphere: blur and pop on load
A fresh window veils in and pops to full over the same clock — the 'blur and pop' on load. Alpha eases 0→1, scale eases 0.94→1.0, ease-out over ~220ms, frame-rate independent. Obscured stays instant; a readable ghost mid-fade is a disclosure.
2026-08-15 19:37:05 -04:00
Fimeg
325ec74c46 atmosphere: ease the dim, don't snap it
First brick of the one attention clock (TASK-52). expose still sets the discrete target; the compositor now eases each surface's painted alpha toward it on the vblank clock, so a dim is a curve instead of a snap. Obscured stays instant — a readable ghost mid-fade is a disclosure. Frame-rate independent, like the strip settle.
2026-08-15 19:24:47 -04:00
Fimeg
ff754c73ab input: a three-finger tap claims the stream
The tap was delivered twice — once to the app underneath, once (late) to the recogniser, which only commits on the last lift. The window sheet opened while the app had already eaten all three fingers. Now three fingers that arrive together cancel the client's touch and withhold the rest of the sequence, while the recogniser keeps running to resolve the tap. Two fingers still reach apps; a grab still owns its own touches.
2026-08-15 19:02:02 -04:00
Fimeg
1692b3598a start the session targets instead of naming units
The launcher already imported the environment, then hand-kicked three units
with reset-failed, restart and a sleep 3 — a hand-rolled PartOf and a
hand-rolled After. It starts graphical-session-pre then graphical-session now,
waits on sessiond's socket rather than a guessed 3 s, and stops both on exit.
souveraine-shell.service comes with it; it lived unowned in /etc since 07-17.
2026-08-15 10:54:40 -04:00
Fimeg
7c9d06e28d ci: gate viewtop by its declared artifacts
validate-distribution.py --complete (SouveraineOS a3ff225) fails the run
when emitted artifacts differ from the manifest. viewtop opts in first.
2026-08-14 20:30:10 -04:00
Fimeg
78e936e502 docs: name the glass boundary 2026-08-13 17:46:49 -04:00
Fimeg
0f82700dd7 ci: verify viewtop release contract 2026-08-13 13:57:02 -04:00
Fimeg
f5b13ca0bf ci: ship viewtop from one release build 2026-08-13 13:45:14 -04:00
Fimeg
991f7664cc ci: version packages from full history 2026-08-11 14:38:00 -04:00
Fimeg
1bcbfa5176 packaging: publish ViewTop for the laptop 2026-08-11 13:53:45 -04:00
Fimeg
a073ea506d input: let application popups take their touches
Firefox extension and Bitwarden popups were rendered above their parent but absent from client hit testing, so every contact fell through to the toplevel beneath. Walk application popups at the same origin and in the same parent-by-parent order used by rendering, including popup area outside the parent bounds.
2026-08-11 13:06:37 -04:00
Fimeg
f45f459f35 ci: permit rerunning the phone build 2026-08-10 19:32:11 -04:00
Fimeg
f49af4af66 smithay: lock the fence-wait revision 2026-08-10 16:39:28 -04:00
Fimeg
72608e9188 smithay: pick up the missing fence wait
build_planes documented a wait it never performed, so with no exportable
fence the atomic commit raced the renderer into the scan-out buffer. That is
the tearing on the d10: simpledrm has no syncobj, supports_fencing is false,
and nothing held the flip while llvmpipe was still writing.
2026-08-10 11:39:08 -04:00
Fimeg
3c853972ae the overview carry: one owner for the transition geometry
The shell scaled real windows through pose while ZoneOverview scaled its
cards, both off one progress and running opposite curves, so the window
was at 0.6 of the glass when the card arrived near full bleed. Worse,
the pose was applied by the rail and had to be undone by whoever ended
the gesture — tapping a card never touches the rail, so a window came
back shrunk with no way to restore it.

transition.rs owns the carry: the rects are named once at begin, and
commit/cancel release. Releasing is arriving, so nothing can outlive the
gesture. Geometry reaches the glass through `carried`, read by both
window_origin and window_extent, so the render and the hit test cannot
grow terms the other lacks. focus_border yields while a window is
carried — the card draws the frame, and two frames on one rectangle was
the blue slab under the rounded card.

overview_begin/progress/commit/cancel mirror the back verbs. EndTarget
names all four destinations; LastZone is a destination rather than an
abandon branch.
2026-08-07 09:46:48 -04:00
Fimeg
62ec16bc56 feeds: a slow subscriber is behind, not gone
A full channel dropped the subscriber, which made a fast stream
self-terminating: gaze pushes at ~25/s filled the queue faster than a QML
socket drained it, so the shell was unsubscribed inside the first burst of a
drag and never told. It looked exactly like a compositor that had stopped
pushing — and an external client that read faster kept working, which is what
made it look like the shell's bug.

Skipping the message is right for both feeds: the strip republishes on the
next change, and a contact point nobody read is stale by the time it would
have arrived.
2026-08-07 02:21:06 -04:00
Fimeg
b14d9926bb layer surfaces get their popups drawn, and touched
An xdg_popup is its own surface, not a subsurface, so a layer surface's
surface tree does not contain it — and only toplevels had a popup pass. Every
menu the shell opened from the bar, the dock or the pill was created,
configured, and never composited. The dock's app-stack fan named it: tapping
a stack set `expanded`, built the arc, and put nothing on the glass.

The hit test had the same hole, one step further on: popups are not in the
layer map, so a tap on an open menu fell through to whatever was behind it.
Drawn and inert is the worse half — the surface underneath acts on a tap the
user aimed somewhere else.
2026-08-07 01:52:24 -04:00
Fimeg
f6778efe47 move mode: the sheet that ends it keeps its touches
Withholding every client contact during a grab took the shell's own chrome
with it, because a quickshell layer surface is a Wayland client like any
other. So "Done moving" went deaf and the move could be entered and never
left. Top and overlay layers are exempt now; the app underneath still gets
nothing, which is the point of the grab.

A release is never withheld either — the surface given the contact has to be
told it ended, or it holds a finger that is no longer on the glass.

And a three-finger tap during a move is dropped rather than stacking a second
sheet over a grab that is still live.

`scene` intent `drop` already clears a stuck grab, which is how the phone got
out of this one.
2026-08-07 01:45:05 -04:00
Fimeg
d7a6760b29 gaze: push where contacts are, so a face can look at them
Her input region is her silhouette now, so the compositor stops handing her
contacts that land on the wallpaper — which also stopped her tracking unless
you touched her first. Where a finger is and who receives it are different
questions; this answers the first without changing the second.

Its own feed, not a field on subscribe: the strip changes when the world
does, a contact changes tens of times a second, and subscribe's dedup would
fight it. Throttled to 40ms, physical contacts only, and the release is never
dropped or she keeps staring at where the finger last was.
2026-08-07 00:59:35 -04:00
Fimeg
bb9530780f furniture: a role for the face, and honour input regions
A toplevel is classified at its first commit rather than at map, because
xdg_toplevel is created before the client sends set_app_id — so the old code
minted a zone, moved the strip, took the keyboard and told the dock about a
window it had not yet identified. Furniture (org.souveraine.face) takes no
zone, is announced to nobody, wears no frame, keeps its own size, and hangs
from the top of the zone with the room below it left free.

windows_under never consulted wl_surface.set_input_region, so a transparent
surface took every contact inside its bounds. The face is the width of the
panel, so that was the whole screen. This also stops GTK client-side
decoration shadows from eating taps meant for what is behind them.

state reports furniture and its input rectangle count: neither is visible on
the glass, and a face that swallows the screen looks identical to one that
does not.
2026-08-07 00:20:11 -04:00
Fimeg
21882c90c2 colour management: map sRGB into the panel's primaries
blueline's SW43408 has no EDID and viewtop has been scanning out raw sRGB
onto a ~P3 panel since the move off Hyprland, so everything reads
oversaturated. The linear-light transform lives in the GLES fork; this side
owns which matrix, because only the compositor knows which device it is.

Default off, and off is a separate shader path rather than an identity
matrix, so it is bit-identical to before. TASK-61.

Fork pin moves to 645961c, which is the colour-transform branch folded into
souveraine; the branch is deleted. The local [patch] used to verify it was
never for commit and is gone.
2026-08-07 00:20:01 -04:00
Fimeg
90d6b846e5 scan-out formats: offer 10-bit behind VIEWTOP_10BIT, default off (TASK-61) 2026-08-06 18:56:07 -04:00
Fimeg
60ff76415c zone minting: an occupied zone-1 is never reused from home (TASK-86)
Opening a second app from home claimed zone 1 unconditionally once it
existed, so both apps shared one workspace and placement.rs split that
zone top/bottom. The home path now checks occupancy the same way the
non-home path does; an occupied neighbour mints a fresh zone instead of
dividing the first one.

Extracted the decision into a pure, testable pick_zone_for_new_window
with a regression test.
2026-08-06 14:39:33 -04:00