From d8e0fa71c26c8fe2d9282f6b9eb3afc85131db13 Mon Sep 17 00:00:00 2001 From: Aleksey Samoilov Date: Fri, 28 Feb 2025 00:16:34 +0400 Subject: [PATCH] Implement the individual windows sharing feature Original MR: https://gitlab.com/tile-os/tileos-settings-sway/-/merge_requests/21 --- etc/skel/.config/dunst/dunstrc | 2 +- etc/sway/modes/default.conf | 1 - etc/sway/modes/screenmirror.conf | 18 ++++++++++++ etc/sway/outputs/headless-output.conf | 9 ++++++ etc/sway/variables | 2 +- etc/xdg/xdg-desktop-portal-wlr/config | 3 ++ usr/share/sway/scripts/recorder.sh | 2 ++ usr/share/sway/scripts/screenmirror.sh | 38 +++++++++++++++++++++++++ usr/share/sway/scripts/select-output.sh | 33 +++++++++++++++++++++ 9 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 etc/sway/modes/screenmirror.conf create mode 100644 etc/sway/outputs/headless-output.conf create mode 100644 etc/xdg/xdg-desktop-portal-wlr/config create mode 100755 usr/share/sway/scripts/screenmirror.sh create mode 100755 usr/share/sway/scripts/select-output.sh diff --git a/etc/skel/.config/dunst/dunstrc b/etc/skel/.config/dunst/dunstrc index 01e2854..729b877 100644 --- a/etc/skel/.config/dunst/dunstrc +++ b/etc/skel/.config/dunst/dunstrc @@ -17,7 +17,7 @@ # # If this option is set to mouse or keyboard, the monitor option # will be ignored. - follow = none + follow = mouse ### Geometry ### diff --git a/etc/sway/modes/default.conf b/etc/sway/modes/default.conf index 73f6436..5582313 100644 --- a/etc/sway/modes/default.conf +++ b/etc/sway/modes/default.conf @@ -97,7 +97,6 @@ $bindsym $mod+6 workspace $ws6 $bindsym $mod+7 workspace $ws7 $bindsym $mod+8 workspace $ws8 $bindsym $mod+9 workspace $ws9 -$bindsym $mod+0 workspace $ws10 set $focus_ws [ "$focus_after_move" == 'true' ] && swaymsg workspace diff --git a/etc/sway/modes/screenmirror.conf b/etc/sway/modes/screenmirror.conf new file mode 100644 index 0000000..3d3f19b --- /dev/null +++ b/etc/sway/modes/screenmirror.conf @@ -0,0 +1,18 @@ +# +# Screenmirror: +# +# The mode allows the user to mirror the headless output. +# This is primarily used when screencasting to cast only the windows that +# belong to the headless output instead of casting the entire screen. +# +# See the following link for more details: +# https://github.com/emersion/xdg-desktop-portal-wlr/issues/107#issuecomment-1596107337 + +set $screenmirror /usr/share/sway/scripts/screenmirror.sh +set $start_mirror systemd-cat $screenmirror $headless +set $stop_mirror systemd-cat $screenmirror -k + +## Launch // Switch to the workspace for mirroring ## +$bindsym $mod+0 exec $start_mirror, workspace $ws10 +## Launch // Switch back from the workspace for mirroring ## +$bindsym $mod+Mod1+0 exec $stop_mirror, workspace back_and_forth diff --git a/etc/sway/outputs/headless-output.conf b/etc/sway/outputs/headless-output.conf new file mode 100644 index 0000000..b17efc1 --- /dev/null +++ b/etc/sway/outputs/headless-output.conf @@ -0,0 +1,9 @@ +# This output configuration is required for the screenmirror mode to work. + +set $headless HEADLESS-1 + +output $headless { + position 16000 16000 +} +workspace $ws10 output $headless +exec swaymsg create_output diff --git a/etc/sway/variables b/etc/sway/variables index ae01908..4e09d1f 100644 --- a/etc/sway/variables +++ b/etc/sway/variables @@ -72,7 +72,7 @@ set $ws6 number 6 set $ws7 number 7 set $ws8 number 8 set $ws9 number 9 -set $ws10 number 10 +set $ws10 "🖵" # Screenshot set $grimshot /usr/bin/grimshot diff --git a/etc/xdg/xdg-desktop-portal-wlr/config b/etc/xdg/xdg-desktop-portal-wlr/config new file mode 100644 index 0000000..8a29294 --- /dev/null +++ b/etc/xdg/xdg-desktop-portal-wlr/config @@ -0,0 +1,3 @@ +[screencast] +chooser_type=dmenu +chooser_cmd=/usr/share/sway/scripts/select-output.sh diff --git a/usr/share/sway/scripts/recorder.sh b/usr/share/sway/scripts/recorder.sh index 0f0dedd..15c82a2 100755 --- a/usr/share/sway/scripts/recorder.sh +++ b/usr/share/sway/scripts/recorder.sh @@ -52,12 +52,14 @@ main() { wf-recorder --audio -g "$area" --file="$file" else file="$target_path/$timestamp.webm" + output="$(swaymsg -t get_outputs | jq -r '.[] | select(.focused) | .name')" wf-recorder \ -g "$area" -c libvpx \ --codec-param="qmin=0" \ --codec-param="qmax=25" \ --codec-param="crf=4" \ --codec-param="b:v=1M" \ + -o "$output" \ --file="$file" fi diff --git a/usr/share/sway/scripts/screenmirror.sh b/usr/share/sway/scripts/screenmirror.sh new file mode 100755 index 0000000..f9b62e0 --- /dev/null +++ b/usr/share/sway/scripts/screenmirror.sh @@ -0,0 +1,38 @@ +#!/bin/bash +# +# This script implements the function of mirroring outputs. +# It uses wl-mirror and Sway's ability to create headless outputs. +# +# The script is written as a singleton. It allows the user to run only one +# instance of itself and kills all others. This is necessary so that wl-mirror +# instances do not interfere with each other. + +SELF_NAME="$(basename "$0")" +SELF_PID="$$" + +get_pgid() { + ps -h -o "%r" -p "$1" | awk '{print $1}' +} +SELF_PGID="$(get_pgid "$SELF_PID")" + +kill_by_pgid() { + pkill -"$2" -g "$1" +} + +kill_copies() { + mapfile -t pids < <(pgrep -u "$USER" -x "$SELF_NAME") + for pid in "${pids[@]}" ; do + pgid="$(get_pgid "$pid")" + [[ $pgid -ne $SELF_PGID ]] && kill_by_pgid "$pgid" "INT" + done +} + +main() { + # Don't single quote the trap's command! + # It must be expanded when the trap is defined. + # shellcheck disable=SC2064 + trap "kill_by_pgid $SELF_PGID TERM" INT + kill_copies + [[ "$1" != "-k" ]] && wl-mirror -F "${1:-HEADLESS-1}" +} +main "$@" diff --git a/usr/share/sway/scripts/select-output.sh b/usr/share/sway/scripts/select-output.sh new file mode 100755 index 0000000..bb20fcd --- /dev/null +++ b/usr/share/sway/scripts/select-output.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +export LC_ALL=C + +TITLE="Select the output for the screencast" +OUT_NAME="HEADLESS-1" +FONT_SIZE="12" +ROSEWATER="#f4dbd6" + +FONT="Noto Sans ${FONT_SIZE}" +FONT_COLOR="${ROSEWATER}" + +I_SIZE="$(awk "BEGIN {print (${FONT_SIZE}*1.08)}")" +OUT_SIZE="$(awk "BEGIN {print (${FONT_SIZE}*0.94)}")" +TIP_SHIFT="$(awk "BEGIN {print (1+(${I_SIZE}-${FONT_SIZE})/2)}")" +TIP="\ +\ + \ +use \ +${OUT_NAME} \ +to cast only chosen windows\ +\ +\ +" + +swaymsg -t get_outputs \ + | jq -r '.[] | .name' \ + | rofi \ + -dmenu -i -l 4 \ + -p "${TITLE}" \ + -window-title "${TITLE}" \ + -mesg "${TIP}" \ + -font "${FONT}"