From 3aef06001ba5b68fdfd0b6f23d7ccc0cbd1cacdb Mon Sep 17 00:00:00 2001 From: Brad Stein Date: Mon, 1 Dec 2025 00:07:09 -0300 Subject: [PATCH] client: screen relay switched to ximagesink --- client/src/main.rs | 10 +++++ client/src/output/video.rs | 78 ++++++++++---------------------------- 2 files changed, 31 insertions(+), 57 deletions(-) diff --git a/client/src/main.rs b/client/src/main.rs index 9273772..7b885a0 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -23,6 +23,16 @@ fn ensure_runtime_dir() { #[tokio::main(flavor = "current_thread")] async fn main() -> Result<()> { + // Prefer X11/Xwayland on KDE Wayland so wmctrl-based placement works + if env::var_os("WAYLAND_DISPLAY").is_some() { + if let Some(desktop) = env::var_os("XDG_CURRENT_DESKTOP") { + if desktop.to_string_lossy().to_ascii_lowercase().contains("kde") { + env::set_var("GDK_BACKEND", "x11"); + env::set_var("WINIT_UNIX_BACKEND", "x11"); + } + } + } + ensure_runtime_dir(); /*------------- common filter & stderr layer ------------------------*/ diff --git a/client/src/output/video.rs b/client/src/output/video.rs index 51f331a..e3d1714 100644 --- a/client/src/output/video.rs +++ b/client/src/output/video.rs @@ -12,19 +12,6 @@ use tracing::{error, info, warn, debug}; use crate::output::{display, layout}; -/* ---------- pipeline ---------------------------------------------------- -* ┌────────────┐ H.264/AU ┌─────────┐ Decoded ┌─────────────┐ -* │ AppSrc │────────────► decodebin ├──────────► glimagesink │ -* └────────────┘ (autoplug) (overlay) | -* ----------------------------------------------------------------------*/ -const PIPELINE_DESC: &str = concat!( - "appsrc name=src is-live=true format=time do-timestamp=true block=false ! ", - "queue leaky=downstream ! ", - "capsfilter caps=video/x-h264,stream-format=byte-stream,alignment=au ! ", - "h264parse disable-passthrough=true ! decodebin ! videoconvert ! ", - "glimagesink name=sink sync=false" -); - pub struct MonitorWindow { _pipeline: gst::Pipeline, src: gst_app::AppSrc, @@ -35,7 +22,23 @@ impl MonitorWindow { gst::init().context("initialising GStreamer")?; // --- Build pipeline --------------------------------------------------- - let pipeline: gst::Pipeline = gst::parse::launch(PIPELINE_DESC)? + let sink = if std::env::var("GDK_BACKEND") + .map(|v| v.contains("x11")) + .unwrap_or_else(|_| std::env::var_os("DISPLAY").is_some()) + { + "ximagesink name=sink sync=false" + } else { + "glimagesink name=sink sync=false" + }; + + let desc = format!( + "appsrc name=src is-live=true format=time do-timestamp=true block=false ! \ + queue leaky=downstream ! \ + capsfilter caps=video/x-h264,stream-format=byte-stream,alignment=au ! \ + h264parse disable-passthrough=true ! decodebin ! videoconvert ! {sink}" + ); + + let pipeline: gst::Pipeline = gst::parse::launch(&desc)? .downcast::() .expect("not a pipeline"); @@ -59,6 +62,9 @@ impl MonitorWindow { /* -------- move/resize overlay ---------------------------------- */ if let Some(sink_elem) = pipeline.by_name("sink") { + if sink_elem.find_property("window-title").is_some() { + let _ = sink_elem.set_property("window-title", &format!("Lesavka-eye-{id}")); + } if let Ok(overlay) = sink_elem.dynamic_cast::() { if let Some(r) = rects.get(id as usize) { // 1. Tell glimagesink how to crop the texture in its own window @@ -81,11 +87,6 @@ impl MonitorWindow { run: Arc std::io::Result + Send + Sync>, } - let is_kde = std::env::var("XDG_CURRENT_DESKTOP") - .unwrap_or_default() - .to_ascii_lowercase() - .contains("kde"); - let placer = if Command::new("swaymsg").arg("-t").arg("get_tree") .output().is_ok() { @@ -102,30 +103,6 @@ impl MonitorWindow { .status() }), } - } else if is_kde { - // KWin DBus script: move/resize by title - Placer { - name: "kwin", - run: Arc::new(|script| { - let dbus = if Command::new("qdbus6") - .arg("--version") - .status() - .is_ok() - { - "qdbus6" - } else { - "qdbus" - }; - Command::new(dbus) - .args([ - "org.kde.KWin", - "/KWin", - "org.kde.KWin.evaluateScript", - script, - ]) - .status() - }), - } } else { Placer { name: "noop", @@ -150,19 +127,6 @@ impl MonitorWindow { x = r.x, y = r.y, ), - // KWin JS via DBus - "kwin" => format!( - "var clients = workspace.clientList(); \ - clients.forEach(function(c) {{ \ - if (c.caption === \"Lesavka-eye-{id}\") {{ \ - c.geometry = {{x:{x}, y:{y}, width:{w}, height:{h}}}; \ - }} \ - }});", - x = r.x, - y = r.y, - w = r.w, - h = r.h, - ), _ => String::new(), }; @@ -187,7 +151,7 @@ impl MonitorWindow { }); } } - // 3. X11 placement (kwin/i3/etc.) via wmctrl + // 3. X11 / Xwayland placement via wmctrl else if std::env::var_os("DISPLAY").is_some() { let title = format!("Lesavka-eye-{id}"); let w = r.w;