Skip to content

Commit

Permalink
Add single-output-sway helper script
Browse files Browse the repository at this point in the history
For sway 1.7, this disables all but one output on connect, then restores
everything on disconnect.

For sway 1.8 and later, creates a virtual HEADLESS output, disables all
others, then restores everything on disconnect.

Signed-off-by: Jim Ramsay <[email protected]>
  • Loading branch information
lack committed Dec 23, 2022
1 parent 5cf9ad6 commit 63eff03
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
26 changes: 26 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Example Scripts

The scripts here are examples of how you can automate interesting things with the wayvncctl IPC events.

## event-watcher

This is a pretty simple example that just demonstrates how to tie the
`wayvncctl event-receive` event loop into a bash script. It logs when clients
connect and disconnect.

## single-output-sway

This is more purposeful, and implements an idea for multi-output wayland
servers, collapsing all outputs down to one when the first client connects, and
restoring the configuration when the last client exits.

The mechanism used to collapse the outputs depends on the version of sway installed:

- For sway-1.7 and earlier, the script just temporarily disables all outputs
except the one being captured. This moves all workspaces to the single
remaining output.

- For sway-1.8 and later, the script creates a temporary virtual output called
`HEADLESS-1' and then disables all physical outputs, which moves all
workspaces to the virtual output. On disconnect, all original physical
outputs are re-enabled, and the virtual output is destroyed.
99 changes: 99 additions & 0 deletions examples/single-output-sway
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#!/bin/bash

WAYVNCCTL=${WAYVNCCTL:-wayvncctl}
SWAYMSG=${SWAYMSG:-swaymsg}

SWAY_HAS_UNPLUG=false
IFS=" .-" read -r _ _ SWAYMAJOR SWAYMINOR _ < <($SWAYMSG -v)
if [[ $SWAYMAJOR -ge 1 && $SWAYMINOR -ge 8 ]]; then
echo "Detected sway version 1.8 or later: Enabling virtual output device mode"
SWAY_HAS_UNPLUG=true
else
echo "Detected sway version 1.7 or earlier: Not enabling virtual output device mode"
fi

find_output_matching() {
local pattern=$1
$WAYVNCCTL -j get-outputs | jq -r ".[].name | match(\"$pattern\").string"
}

wait_for_output_matching() {
local pattern=$1
local output
output=$(find_output_matching "$pattern")
while [[ -z $output ]]; do
sleep 0.5
output=$(find_output_matching "$pattern")
done
echo "$output"
}

OUTPUTS_TO_RECONNECT=()
HEADLESS=
restore_outputs() {
[[ ${#OUTPUTS_TO_RECONNECT[@]} -ge 1 ]] || return
echo "Restoring original output state"
for output in "${OUTPUTS_TO_RECONNECT[@]}"; do
echo "Re-enabling output $output"
$SWAYMSG output "$output" enable
done
if [[ $SWAY_HAS_UNPLUG == true && $HEADLESS ]]; then
local firstOutput=${OUTPUTS_TO_RECONNECT[0]}
echo "Switching wayvnc back to physical output $firstOutput"
wait_for_output_matching "$firstOutput" >/dev/null
$WAYVNCCTL set-output --switch-to="$firstOutput"
echo "Removing virtual output $HEADLESS"
$SWAYMSG output "$HEADLESS" unplug
fi
OUTPUTS_TO_RECONNECT=()
HEADLESS=
}
trap restore_outputs EXIT

collapse_outputs() {
if [[ $SWAY_HAS_UNPLUG == true ]]; then
local preexisting="$(find_output_matching 'HEADLESS-\\d+')"
if [[ $preexisting ]]; then
echo "Switching to preexisting virtual output $preexisting"
$WAYVNCCTL set-output --switch-to="$preexisting"
else
echo "Creating and switching to a virtual display"
$SWAYMSG create_output
echo "Waiting for HEADLESS output to be created..."
HEADLESS=$(wait_for_output_matching 'HEADLESS-\\d+')
echo "Switching to virtual output $HEADLESS"
$WAYVNCCTL set-output --switch-to="$HEADLESS"
fi
fi
for output in $($WAYVNCCTL -j get-outputs | jq -r '.[] | select(.captured==false).name'); do
echo "Disabling extra output $output"
$SWAYMSG output "$output" disable
OUTPUTS_TO_RECONNECT+=("$output")
done
}

connection_count_now() {
local count=$1
if [[ $count == 1 ]]; then
collapse_outputs
elif [[ $count == 0 ]]; then
restore_outputs
fi
}

while IFS= read -r EVT; do
case "$(jq -r '.method' <<<"$EVT")" in
client-*onnected)
count=$(jq -r '.params.connection_count' <<<"$EVT")
connection_count_now "$count"
;;
wayvnc-shutdown)
echo "wayvncctl is no longer running"
connection_count_now 0
;;
wayvnc-startup)
echo "Ready to receive wayvnc events"
;;
esac
done < <("$WAYVNCCTL" --wait --reconnect --json event-receive)

0 comments on commit 63eff03

Please sign in to comment.