Show MPRIS now-playing and upower battery under the clock, polled on a
background thread (zbus). Flags gate both drawing and D-Bus; desktops
without a battery stay blank; titles are truncated.
Also the locker audit pass that landed in the same files:
- PAM authenticates getuid()/getpwuid_r, not $USER, and missing
username still takes the lock
- one lock surface per output, generation-gated fail timers, PAM
timeout, Tab-reveal off by default and cleared on keyboard leave
- GPU chrome is a dirty-rect quad with EGL cleanup; shm reuses a
SlotPool; appear/shake/flash/veil/clock-crossfade bugs
- hold-to-reveal, checking ellipsis, and password display length
Live-checked on hermes (GPU path, PAM unlock, Tab-hold).
The greeter previously ignored the configured background image and
rendered a static palette screen. Now the wallpaper is painted behind
the login card via a GtkDrawingArea draw callback (GTK4's GL pipeline),
with a Ken Burns pan driven by a tick callback and a veil gradient
matching breadlock's software renderer. The clock + card cluster fades
in and rises on entry.
Key bug avoided: the first attempt panned by resizing a GtkPicture,
which fed back into the window's minimum size and grew the window
unboundedly (17k x 11k). The draw-callback approach has no layout
feedback.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Four lock-screen niceties:
- Caps Lock / layout chip: a small pill above the password pill shows
when Caps Lock is on or a non-default layout is selected, so all-caps
input never mystifies.
- Hold-to-reveal: holding Tab renders the plain password instead of
dots (Tab produces no utf8, so it can never be part of the password).
- Idle auto-dim: after `animation.idle_dim_after_secs` of no keystrokes
the dim veil deepens past the base gradient (background-only alpha can
legally exceed 1.0), ramping over a few seconds for OLED/burn-in
comfort. Shared `veil_alpha` keeps software and GPU paths identical.
- Attempt counter: repeat failures show "Wrong password — N failed
attempts" so a stuck locker reads differently from ordinary typos.
All four render paths covered by tests (veil math, reveal truncation,
chip/reveal compose) and live-verified in nested Hyprland on the GPU
path; idle dim confirmed to deepen the veil (84.5->75.8 top).
glTexSubImage2D has no row-stride concept on GLES2, so uploading the
chrome sub-rect directly from the full-surface pixmap shifted every row
after the first by (w - rw) pixels — the clock/pill rendered as garbage.
Pack the dirty rows into a tightly-strided buffer before upload instead
(GL_UNPACK_ROW_LENGTH is ES 3.0-only).
Add a regression test for the pack, plus one pinning the background
shader's veil gradient to the software dim_rows (gl_FragCoord.y is 0 at
the bottom of the framebuffer, which is easy to get backwards).
The Ken Burns wallpaper pan and dim veil move to the GPU: the lock
surface is wrapped in a wl_egl_window, the wallpaper is a textured quad
whose shader applies the pan transform and veil (GPU bilinear makes
sub-pixel panning free — the ~19ms/frame software bilinear is gone,
idle CPU drops from 40% to ~0%), and the clock/pill/status chrome is
still composed with tiny-skia and composited over. EGL init failure
falls back to the fully-software path unchanged.
Notable fixes along the way:
- Text blending is now destination-aware: the old blend forced output
alpha to 255, which is correct over the opaque background but made
every glyph opaque in the chrome-only pixmap the GPU path composites.
- wayland-client switches to its C backend for raw surface pointers,
and khronos-egl/glow replace a hand-rolled EGL loader.
Tests grew from 72 to 88: GPU pan_region parity with the software path
(and edge/bounds/corner invariants), shader-uniform/EGL-attrib sanity,
chrome bounding-rect tracking, and a pixel-level parity test proving
the GPU split stays within double-rounding ULP range of the single-pass
compose.
Adds a full motion system to the lock screen (staggered entrance, dot pop
+ caret, wrong-password shake, success flash, clock crossfade), depth
polish (gradient veil, pill shadow + hairline border, "Enter password"
hint, responsive typography), and a second wave of animations (idle
breathing, success dot cascade, status slide-in, parallax unlock drift,
animated checking ellipsis, opt-in Ken Burns wallpaper pan). Includes a
dev-only breadlock-preview harness that renders every state to PNGs with
no Wayland involved, and a design/sketch.html prototype.
Fixes text alpha being dropped by cosmic-text's glyph-mask path (all text
fades now work) and double-drifting that made the date/status overlap the
clock/pill during unlock.
Subscribe the same locker and breadlock listen handlers. Already
unlocked is bread.lock.unlock.done; otherwise run loginctl
unlock-session and emit done / failed. Do not call compositor
unlock() — PAM stays the compositor path (fail-secure). Document
in EVENTS.md and README; drop the "Not implemented: unlock"
paragraph. pin/blur stay unimplemented.
List .desktop sessions from the existing scan, pre-select bos when
present (else the first entry), and pass the chosen Exec= argv to
greetd StartSession.
Pin bread-theme/bread-utils to bread-ecosystem tag v0.7.2.
Subscribe from the locker and from `breadlock listen` so the command
works while unlocked; start breadlock the same way hypridle does.
Emit bread.lock.lock.done / .failed. Document loginctl lock-session
as the Super+L equivalent.
Optional GPG detach-sign of the .pkg.tar.zst when GPG_PRIVATE_KEY is
set; ISO [breadway] stays SigLevel = Never until a signed db exists.
Emit bread.lock.locked when ext-session-lock-v1 is accepted and
bread.lock.unlocked after PAM success. Fail-silent if breadd is down.
No command verbs (no pin/blur stubs). breadgreet is not on the bus.
Note that Forgejo Arch registry packages are unsigned (SigLevel=Never
on BOS) without changing the package.yml registry.
Point workspace bread-theme at git.breadway.dev tag v0.7.1 (gtk feature stays
on breadgreet). README no longer claims BOS ships tuigreet or that Super+L
is unimplemented. CONTRIBUTING records the single-trunk, pacman-only model;
there is still no bakery.toml.
breadlock isn't in bread-ecosystem/registry/bread-ecosystem.toml and
package.yml (the only release workflow this repo has) never reads
bakery.toml — it only touches packaging/arch/PKGBUILD. So the file was
dead metadata, and the README's claim that "bakery.toml is the
bread-ecosystem package index entry" was stale/incorrect: it never
actually was one. breadlock ships pacman-only, which makes sense for a
PAM/greeter component — README now says so explicitly.
- main.rs: dispatch-loop errors no longer silently exit; bounded retry with
loud logging, and explicitly never call unlock() on an error path (would
turn a fail-secure crash into a fail-open one)
- Cargo.toml/state.rs/keyboard.rs/auth/*: password buffer is now
Zeroizing<String>, with explicit zero-then-truncate on backspace and
zeroize on clear/submit; also zeroes pam-client2's internal Conversation
copy after use
- state.rs/main.rs: new AuthState::ConfigError, distinct on-screen message
and error!-level log for PAM context-init failures vs ordinary wrong
password
- lock/surface.rs/state.rs: LockSurface now tracks its wl_output so
output_destroyed can remove it, fixing the surfaces Vec leak on
monitor unplug
- input/keyboard.rs: bind the keyboard via get_keyboard_with_repeat so
held keys (e.g. backspace) actually repeat, regardless of whether the
compositor implements server-side wl_keyboard repeat
Pulls the fix for panels turning brown/off-hue when pywal extracts a light
or muddy background from the wallpaper — background/surface now stay BOS's
fixed dark constants regardless of what the wallpaper looks like.