Commit Graph

3 Commits

Author SHA1 Message Date
en
b9d5f144bd Overlay: thread can be stopped externally instead of detaching (Bug #5)
Bug from Grok round-1 #5. spawn_with_sock returned Ok(_) and dropped
the LiveOverlayHandle, so the JoinHandle was never joined or signalled.
The thread detached; OverlayHub could only clear its slot map, never
stop the actual Wayland thread. With env-gated rendering (Bug #8), the
operator's overlays would accumulate as ghost threads.

Changes:

- wayland_layer: LiveOverlayHandle gains a stop: Arc<AtomicBool>.
  spawn() allocates it, threads a copy into run(), stores a copy on the
  returned handle.
- wayland_layer: run() polls stop in addition to state.exited; flipping
  the bit causes the next roundtrip to exit instead of waiting on the
  compositor's Closed event.
- overlay: OverlayHandle gains stop: Option<Arc<AtomicBool>> and a
  kill() method that flips the bit.
- overlay: spawn_with_sock now puts the same stop Arc on the returned
  OverlayHandle (was previously throwing the live handle away).
- overlay: OverlayHub.sync() and kill_all() call kill() on every
  removed handle, so slot changes actually tear the threads down.

cargo test 96+/0; clippy clean.
2026-09-16 08:06:12 +02:00
en
6028987a6e Overlay: set_margin order + click handler no longer kills the badge
- set_margin (wayland_layer.rs:234): correct arg order to
  (top, right, bottom, left). The previous code passed rect.x as
  the right margin, a no-op under TOP+LEFT anchoring, so the
  overlay's x offset was silently dropped. Comment updated to
  document the protocol's true shape.

- click handler (wayland_layer.rs:466): drop 'state.exited = true'
  after send_swap. Flipping exited destroyed the badge but left
  OverlayHub.by_slot still holding the slot, so the hub refused to
  respawn it. The compositor's zwlr_layer_surface::Closed event
  is the only path that drives thread teardown — the click now
  just fires the swap IPC and returns.

- CHANGELOG entries.

cargo test 96+/0; clippy clean.
2026-09-16 05:58:27 +02:00
en
9d2f51685d Finish the project (T7..T15): layout wizard, broadcast, overlay, dmabuf, teams
Layout wizard (T7):
- App::layout_canvas with monitor backgrounds, click-to-select, draggable tiles
- borderless Hyprland window_rule on run
- App::refresh_monitors + Refresh monitors button; monitors cache for canvas sync

Routing extras (T8, T13, T14):
- clipboard IPC verb (wl-paste / xclip -> Ctrl+V to non-leader slots)
- mirror-mode mouse click broadcast via hypr::deliver_click
- round_robin / rr bind target rotates through ALL slots (leader included)

Slot overlay (T9 real):
- src/wayland_layer.rs: zwlr_layer_shell_v1 client, shm buffers, 3x5 bitmap
  digit glyphs, wl_pointer click -> swap <slot>
- gated ENBOXER_ENABLE_OVERLAY=1; cargo test does not connect

Covered-window VFX capture (T10 real):
- src/toplevel_export.rs: zwlr_export_dmabuf_unstable_v1 client
- ARGB8888 / XRGB8888 format negotiation, synthetic-PNG fallback for tests
- gated ENBOXER_ENABLE_TOPLEVEL=1; gbm_bo_map upgrade documented

Teams + Lutris launcher (T15):
- src/team.rs: Team, list_teams, teams_dir, current_team
- src/lutris.rs: LutrisGame parser, load_all with bad-YAML tolerance
- src/launcher.rs: SpawnPlan merges Lutris config + per-character wine-prefix
- GUI: Teams menu (New / Switch / Refresh / Show / Delete) + Launch menu
- Lutris picker visible only in New-team flow; direct Wine spawn, no lutris CLI

Tests: 89 passed; 0 failed (up from 24).
Clippy: clean with -D warnings.

Safety:
- No live hyprctl dispatch that moves / resizes / pins / closes the session.
- All Wayland paths feature-gated; cargo test does not connect.
- apply_layout still gated by allow_layout + confirm_apply.

Files: 14 modified + 6 new (src/{launcher,lutris,overlay,team,toplevel_export,wayland_layer}.rs)
Diff: +1570 / -29
2026-09-15 17:18:37 +02:00