@@ 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
@@ 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 = {