~ruther/guix-config

1cfcfb3fbd16315949479ff6e6dd506f47e0dfe6 — Rutherther 9 days ago b9fd345
fix: patch xdg-desktop-portal-wlr so wlr-screencopy streams don't freeze
2 files changed, 76 insertions(+), 1 deletions(-)

M home/home-configuration.scm
A patches/xdpw-wlr-screencopy-trigger-process.patch
M home/home-configuration.scm => home/home-configuration.scm +18 -1
@@ 119,6 119,23 @@
                         (find-files source "\\.(otf|otc)$"))
               #t))))))))

;; xdpw 0.8.x connects the PipeWire stream with PW_STREAM_FLAG_DRIVER, so
;; .process only runs in reply to pw_stream_trigger_process().  Only the
;; ext-image-copy backend calls it; wlr-screencopy never does, so capture
;; delivers the frame primed at PW_STREAM_STATE_STREAMING and then stalls
;; forever.  dwl exposes zwlr_screencopy_manager_v1 only, so screen sharing
;; freezes on the first frame.  Backport of upstream ccd8e62 + c0255d7b,
;; which are not in any release yet (0.8.4 predates them).
;; https://github.com/emersion/xdg-desktop-portal-wlr/issues/369
(define xdg-desktop-portal-wlr-patched
  (package/inherit xdg-desktop-portal-wlr
    (source
     (origin
       (inherit (package-source xdg-desktop-portal-wlr))
       (patches
        (cons* (local-file "../patches/xdpw-wlr-screencopy-trigger-process.patch")
               (origin-patches (package-source xdg-desktop-portal-wlr))))))))

(home-environment
 (packages
  (append


@@ 424,7 441,7 @@ exec ~a ~a"
                   (implementations
                    (list
                     xdg-desktop-portal-gtk
                     xdg-desktop-portal-wlr))
                     xdg-desktop-portal-wlr-patched))
                   (configs
                    (list
                     (xdg-desktop-portals-conf

A patches/xdpw-wlr-screencopy-trigger-process.patch => patches/xdpw-wlr-screencopy-trigger-process.patch +58 -0
@@ 0,0 1,58 @@
diff --git a/src/screencast/wlr_screencopy.c b/src/screencast/wlr_screencopy.c
index 81beb9e..693ca4c 100644
--- a/src/screencast/wlr_screencopy.c
+++ b/src/screencast/wlr_screencopy.c
@@ -32,6 +32,14 @@ static void wlr_frame_finish(struct xdpw_screencast_instance *cast) {
 	logprint(TRACE, "wlroots: frame destroyed");
 }
 
+// Ends the current capture cycle: hand the buffer back to PipeWire and drop
+// the wlr frame. We drive the graph, so ask for the next cycle ourselves.
+static void wlr_frame_done(struct xdpw_screencast_instance *cast) {
+	xdpw_pwr_enqueue_buffer(cast);
+	wlr_frame_finish(cast);
+	pw_stream_trigger_process(cast->stream);
+}
+
 static void wlr_frame_buffer_done(void *data,
 		struct zwlr_screencopy_frame_v1 *frame);
 
@@ -137,16 +145,14 @@ static void wlr_frame_buffer_done(void *data,
 
 	if (!cast->current_frame.xdpw_buffer) {
 		logprint(WARN, "wlroots: no current buffer");
-		xdpw_pwr_enqueue_buffer(cast);
-		wlr_frame_finish(cast);
+		wlr_frame_done(cast);
 		return;
 	}
 
 	if (!check_constraints(&cast->current_constraints, cast->current_frame.xdpw_buffer)) {
 		logprint(DEBUG, "wlroots: buffer constraints changed");
 		pwr_update_stream_param(cast);
-		xdpw_pwr_enqueue_buffer(cast);
-		wlr_frame_finish(cast);
+		wlr_frame_done(cast);
 		return;
 	}
 
@@ -199,8 +205,7 @@ static void wlr_frame_ready(void *data, struct zwlr_screencopy_frame_v1 *frame,
 	cast->current_frame.completed = true;
 	logprint(TRACE, "wlroots: timestamp %"PRIu64":%"PRIu32, cast->current_frame.tv_sec, cast->current_frame.tv_nsec);
 
-	xdpw_pwr_enqueue_buffer(cast);
-	wlr_frame_finish(cast);
+	wlr_frame_done(cast);
 }
 
 static void wlr_frame_failed(void *data,
@@ -212,8 +217,7 @@ static void wlr_frame_failed(void *data,
 
 	logprint(TRACE, "wlroots: failed event handler");
 
-	xdpw_pwr_enqueue_buffer(cast);
-	wlr_frame_finish(cast);
+	wlr_frame_done(cast);
 }
 
 static const struct zwlr_screencopy_frame_v1_listener wlr_frame_listener = {