bread-capture: switch capture isolation to headless Sway
Nested Hyprland worked but had real limits: the outer compositor decided the nested window's pixel size (needing an outer-session float+resize dispatch per capture), occluded surfaces got no frame callbacks (so grim hung unless the nested window was also focused/raised), and there was no way to fully suppress a brief real, visible flash of that window on the operator's desktop. wlroots' WLR_BACKENDS=headless (Sway, not Hyprland, is built on wlroots directly) has a genuine headless backend: no seat/DRM-master claim, no window anywhere, ever. Confirmed empirically: zero visible footprint, both zwlr_layer_shell_v1 and zwlr_screencopy_manager_v1 present, grim completes instantly with no focus dance needed. This drops the Hyprland-specific plumbing that no longer applies: - bread-screenshots now exposes one compositor-agnostic capture_region primitive instead of capture_layer/capture_output, since the isolated canvas size is always known up front rather than queried via hyprctl. - bread-utils::hypr loses the Monitor scale/transform/logical_size and Layer/find_layer additions that only existed to support that querying. - bread-capture's isolation module spawns headless Sway instead of a nested Hyprland instance, and passes --width/--height through to the target app so it knows the canvas size without asking anyone. Also fixes a socket leak in isolation teardown: killing the compositor (Hyprland or Sway) doesn't unlink the wayland-N/.lock files it created, so every capture run was orphaning a socket pair in the runtime dir. Drop now removes them explicitly.
This commit is contained in:
parent
686af0d3dc
commit
d059d99437
4 changed files with 124 additions and 341 deletions
|
|
@ -7,7 +7,7 @@
|
|||
//! `screenshots/vX.Y.Z/latest` structure or manifest file yet, since those
|
||||
//! only earn their complexity once more apps are wired up.
|
||||
//!
|
||||
//! By default every capture runs inside a throwaway nested Hyprland instance
|
||||
//! By default every capture runs inside a throwaway headless Sway instance
|
||||
//! (see [`isolation`]) rather than the operator's live desktop, so another
|
||||
//! window (or their own differently-themed real bar) can't leak into a
|
||||
//! capture. `--no-isolate` skips that and captures directly against whatever
|
||||
|
|
@ -39,8 +39,8 @@ struct Cli {
|
|||
#[arg(long, default_value = "./screenshots")]
|
||||
out_dir: PathBuf,
|
||||
|
||||
/// Capture directly against the current session instead of a nested,
|
||||
/// throwaway Hyprland instance. Off by default so captures can't pick up
|
||||
/// Capture directly against the current session instead of a headless,
|
||||
/// throwaway Sway instance. Off by default so captures can't pick up
|
||||
/// whatever else is on the operator's desktop.
|
||||
#[arg(long)]
|
||||
no_isolate: bool,
|
||||
|
|
@ -63,13 +63,21 @@ fn main() -> Result<()> {
|
|||
Some(isolation::Isolation::start(cli.isolate_width, cli.isolate_height)?)
|
||||
};
|
||||
|
||||
let width_str = cli.isolate_width.to_string();
|
||||
let height_str = cli.isolate_height.to_string();
|
||||
|
||||
let mut failed = false;
|
||||
for (view, filename) in BREADBAR_TARGETS {
|
||||
let out_path = cli.out_dir.join(filename);
|
||||
let out_str = out_path.to_string_lossy();
|
||||
let result = bread_utils::proc::run(
|
||||
&cli.app_path,
|
||||
&["--screenshot", view, "--output", &out_str],
|
||||
&[
|
||||
"--screenshot", view,
|
||||
"--output", &out_str,
|
||||
"--width", &width_str,
|
||||
"--height", &height_str,
|
||||
],
|
||||
CAPTURE_TIMEOUT,
|
||||
);
|
||||
if result.success {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue