After T10 shipped (commit 0ba3c59) several docs still claimed the
gbm_bo_map / ENBOXER_ENABLE_TOPLEVEL path was a stub, follow-up, or
"/dev/dri/renderD128 + new dep" work that never happened. Rewrite:
- README.md: ENABLE_TOPLEVEL row no longer says "unset = stub".
- docs/VIDEO.md: live toplevel-export is real (gbm_bo_map via
runtime dlopen of libgbm.so.1, real RGBA8 PNG via the png crate).
- CHANGELOG.md: T10 follow-up entry rewritten as shipped.
- docs/MACROS.md: stale "Forever is not out yet / later helper
(not shipped)" paragraph rewritten to point users at the
per-character GUI rebind instead.
29 lines
2.1 KiB
Markdown
29 lines
2.1 KiB
Markdown
# Live crop (Video FX)
|
||
|
||
You pick **two rectangles**:
|
||
|
||
1. **Source** — which part of another client to copy, and how large that crop is.
|
||
2. **Viewer** — where that crop is drawn on the primary client, and how large it is shown.
|
||
|
||
Numbers `0`–`1` are fractions of that window. Numbers **greater than 1** are pixels inside the window. In the GUI, **Pick source / Pick viewer** uses `slurp` and stores pixels.
|
||
|
||
When the mouse is over the viewer, **clicks and keys go only to the source client**, not to the primary and not to the rest of the team.
|
||
|
||
Configure this in the **Video FX** page of the control panel (`enboxer` with no arguments).
|
||
|
||
It is not a second monitor and not a window swap. The other client can sit behind the main one; you still see the cropped piece.
|
||
|
||
## What Hyprland can actually do
|
||
|
||
| Method | Sees a window that is fully covered? | What we use |
|
||
| --- | --- | --- |
|
||
| `grim` of a screen rectangle | No — only pixels currently on the output | **Yes, default** |
|
||
| `hyprland-toplevel-export` | Yes — compositor copy of that window’s buffer | **Yes, gated behind `ENBOXER_ENABLE_TOPLEVEL=1`** |
|
||
| Desktop portal / PipeWire | Yes, heavier | No |
|
||
|
||
The dispatcher in `src/vfx.rs::capture_for_source` checks `is_window_visible(monitors, client)`. If the source window sits on a visible output, `grim` captures it. If the window is covered and the operator has opted in to compositor-side capture (`ENBOXER_ENABLE_TOPLEVEL=1`), the dispatcher routes to `capture_toplevel` (zwlr_export_dmabuf_unstable_v1). With the gate off, covered windows fall through to `grim` and the operator sees whatever is currently on top of those pixels — exactly the previous behaviour.
|
||
|
||
So: keep the source window **on a visible output** for the default `grim` path. Set `ENBOXER_ENABLE_TOPLEVEL=1` when you want a stacked layout where some sources are fully covered by another; the live toplevel-export client reads pixels through `gbm_bo_map` (dlopen'd at runtime from `libgbm.so.1`) and writes a real RGBA8 PNG via the `png` crate.
|
||
|
||
The overlay itself is an `mpv` window (`class: enboxer-vfx`) that reloads each `grim` frame.
|