Slack screenshare chooser on sway
Recently, screensharing in Slack huddles got annoying. The usual Slack share dialog still appeared, but additionally something popped up in the sway bar, stole the keyboard focus and I had to press Escape (twice) before I could continue. Sharing the full screen still worked, but the popup was blocking everything until dismissed.
Two different choosers are involved here. The share dialog with the "Entire screen" / "Window" tabs is Slack's own (Electron) picker and was always there. On Wayland, Electron cannot capture the screen itself: it requests a PipeWire stream via xdg-desktop-portal, and the portal backend decides which output backs that stream -- even the live preview inside Slack's dialog comes from such a stream.
The new thing in the bar turned out to be bemenu, started by xdg-desktop-portal-wlr as a source chooser.
When an application requests a screencast, the portal walks through a list of chooser commands (wmenu, wofi, rofi, bemenu, ...) and runs the first one that exists.
On my system only bemenu is installed, so that one won. The journal shows the chain:
/bin/sh: line 1: rofi: command not found /bin/sh: line 1: wmenu: command not found [ERROR] - wlroots: no output found
The no output found error is the result of pressing Escape: an empty chooser selection makes that capture request fail. Slack coped with it -- sharing the full screen still worked afterwards -- but having to dismiss a focus-stealing prompt twice per share is not a good workflow.
The trigger was probably the sway 1.11 to 1.12 upgrade -- before that, no chooser ever appeared.
Slack itself (started with --enable-features=WebRTCPipeWireCapturer --ozone-platform=wayland) was unchanged.
Step 1: pin the chooser
xdg-desktop-portal-wlr reads ~/.config/xdg-desktop-portal-wlr/config.
Pinning the chooser to slurp replaces the bar takeover with a crosshair where I click on the monitor I want to share:
Then restart the portal: systemctl --user restart xdg-desktop-portal-wlr.
This worked, but now I had to click multiple times per share: Slack/Electron makes multiple portal requests (two for the live preview in the share dialog, one more when actually clicking "Share"), and the portal runs the chooser for every request.
xdg-desktop-portal-wlr does not support the portal restore-token mechanism, so it cannot remember the previous answer.
Step 2: cache the answer
So I wrapped slurp in a small script that asks once and reuses the answer for repeated requests within 60 seconds -- ~/bin/xdpw-output-chooser:
#!/bin/sh # Output chooser for xdg-desktop-portal-wlr: ask once via slurp, # reuse the choice for repeated requests within 60 seconds # (Slack/Electron fires several capture requests per share). cache="${XDG_RUNTIME_DIR:-/tmp}/xdpw-output-choice" if [ -f "$cache" ]; then age=$(( $(date +%s) - $(stat -c %Y "$cache") )) if [ "$age" -lt 60 ]; then cat "$cache" exit 0 fi fi choice=$(slurp -f %o -or) || exit 1 printf '%s\n' "$choice" | tee "$cache"
And point the portal config to it:
Now starting a screenshare is: open the share dialog, click the monitor once in slurp, the preview appears, click "Share" -- done. One click instead of three, and nothing steals the keyboard focus anymore.