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.
This commit is contained in:
en 2026-09-16 05:47:41 +02:00 committed by en
parent 1b8b2cdf24
commit 6028987a6e
2 changed files with 23 additions and 4 deletions

View File

@ -70,3 +70,14 @@
`layout-apply` against the desktop when only a terminal (or any `layout-apply` against the desktop when only a terminal (or any
unrelated window) is open. unrelated window) is open.
- **Profile:** `Character` derives `Default` (needed for the padding). - **Profile:** `Character` derives `Default` (needed for the padding).
- **Overlay:** `set_margin` arguments corrected to `(top, right, bottom,
left)`. The previous `(rect.y, rect.x, 0, 0)` passed `rect.x` as the
*right* margin, which is a no-op under TOP+LEFT anchoring — so the
overlay's x offset was silently dropped. Now `(y, 0, 0, x)` which
pushes the surface down by `y` and right by `x`.
- **Overlay:** Left-click on a slot no longer sets `state.exited = true`.
Doing so dropped the badge and 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 tears the
live thread down — click just sends the swap IPC and returns.

View File

@ -229,9 +229,12 @@ fn run(slot: u32, rect: OverlayRect, ipc_sock: PathBuf) -> anyhow::Result<()> {
layer.set_anchor(zwlr_layer_surface_v1::Anchor::Top | zwlr_layer_surface_v1::Anchor::Left); layer.set_anchor(zwlr_layer_surface_v1::Anchor::Top | zwlr_layer_surface_v1::Anchor::Left);
layer.set_size(rect.w.max(1) as u32, rect.h.max(1) as u32); layer.set_size(rect.w.max(1) as u32, rect.h.max(1) as u32);
layer.set_exclusive_zone(-1); layer.set_exclusive_zone(-1);
// Margins encode the offset: with TOP+LEFT anchor, a positive top // zwlr_layer_surface::set_margin is (top, right, bottom, left).
// margin pushes the surface down; positive left pushes it right. // With TOP+LEFT anchor: top margin pushes the surface down, left
layer.set_margin(rect.y.max(0), rect.x.max(0), 0, 0); // margin pushes it right. (Earlier versions of this code passed
// rect.x as the right margin, which is a no-op when only TOP+LEFT
// are anchored.)
layer.set_margin(rect.y.max(0), 0, 0, rect.x.max(0));
layer.set_keyboard_interactivity(zwlr_layer_surface_v1::KeyboardInteractivity::None); layer.set_keyboard_interactivity(zwlr_layer_surface_v1::KeyboardInteractivity::None);
state.surface = Some(surface.clone()); state.surface = Some(surface.clone());
state.layer_surface = Some(layer); state.layer_surface = Some(layer);
@ -463,7 +466,12 @@ impl Dispatch<wl_pointer::WlPointer, ()> for OverlayState {
&& matches!(btn_state, wayland_client::WEnum::Value(wl_pointer::ButtonState::Pressed)) && matches!(btn_state, wayland_client::WEnum::Value(wl_pointer::ButtonState::Pressed))
{ {
send_swap(state.slot, &state.ipc_sock); send_swap(state.slot, &state.ipc_sock);
state.exited = true; // NOTE: do not flip `state.exited = true` here. Doing so
// destroys the badge and `OverlayHub.by_slot` still holds
// the slot, so the hub refuses to respawn it (it thinks
// the slot is already served). The compositor's
// zwlr_layer_surface::Closed event is the only path that
// should tear down the live thread.
} }
} }
} }