Add support for a portable monitor.

This commit is contained in:
Tom Alexander 2026-03-07 12:58:20 -05:00
parent ea133ded21
commit 7f9f010217
Signed by: talexander
GPG Key ID: 36C99E8B3C39D85F
3 changed files with 238 additions and 20 deletions

View File

@ -44,3 +44,24 @@ position = "0,0"
scale = 1.0
transform = "normal"
adaptive_sync = false
[[profile]]
name = "portablemonitor"
[[profile.output]]
enable = true
search = ["m=0x0BCA", "s=", "v=BOE"]
mode = "2256x1504@59.999Hz"
position = "0,0"
scale = 1.5
transform = "normal"
adaptive_sync = false
[[profile.output]]
enable = true
search = ["m=HG560T34", "s=0x10101010", "v=Invalid Vendor Codename - RTK"]
mode = "3840x2400@59.994Hz"
position = "1504,0"
scale = 2
transform = "normal"
adaptive_sync = false

View File

@ -6,6 +6,25 @@
}:
let
patchScriptBin =
{
filename,
contents,
path ? [ ],
}:
((pkgs.writeScriptBin filename contents).overrideAttrs (old: {
buildCommand = "${old.buildCommand}\n patchShebangs $out";
postBuild = ''
wrapProgram $out/bin/${filename} --prefix PATH : ${lib.makeBinPath path}
'';
}));
workspace_helper = (
patchScriptBin {
filename = "workspace_helper";
contents = (builtins.readFile ./files/workspace_helper.bash);
path = with pkgs; [ jq ];
}
);
sway-config = pkgs.writeTextFile {
name = "config";
text = ''
@ -174,29 +193,34 @@ let
# Workspaces:
#
# switch to workspace
bindsym $mod+1 workspace 1
bindsym $mod+2 workspace 2
bindsym $mod+3 workspace 3
bindsym $mod+4 workspace 4
bindsym $mod+5 workspace 5
bindsym $mod+6 workspace 6
bindsym $mod+7 workspace 7
bindsym $mod+8 workspace 8
bindsym $mod+9 workspace 9
bindsym $mod+0 workspace 10
bindsym $mod+1 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 1
bindsym $mod+2 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 2
bindsym $mod+3 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 3
bindsym $mod+4 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 4
bindsym $mod+5 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 5
bindsym $mod+6 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 6
bindsym $mod+7 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 7
bindsym $mod+8 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 8
bindsym $mod+9 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 9
bindsym $mod+0 exec ${workspace_helper}/bin/workspace_helper go_to_workspace 10
# move focused container to workspace
bindsym $mod+Shift+1 move container to workspace 1
bindsym $mod+Shift+2 move container to workspace 2
bindsym $mod+Shift+3 move container to workspace 3
bindsym $mod+Shift+4 move container to workspace 4
bindsym $mod+Shift+5 move container to workspace 5
bindsym $mod+Shift+6 move container to workspace 6
bindsym $mod+Shift+7 move container to workspace 7
bindsym $mod+Shift+8 move container to workspace 8
bindsym $mod+Shift+9 move container to workspace 9
bindsym $mod+Shift+0 move container to workspace 10
bindsym $mod+Shift+1 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 1
bindsym $mod+Shift+2 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 2
bindsym $mod+Shift+3 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 3
bindsym $mod+Shift+4 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 4
bindsym $mod+Shift+5 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 5
bindsym $mod+Shift+6 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 6
bindsym $mod+Shift+7 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 7
bindsym $mod+Shift+8 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 8
bindsym $mod+Shift+9 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 9
bindsym $mod+Shift+0 exec ${workspace_helper}/bin/workspace_helper send_to_workspace 10
# Note: workspaces can have any name you want, not just numbers.
# We just use 1-10 as the default.
bindsym $mod+Ctrl+Left exec ${workspace_helper}/bin/workspace_helper go_to_previous_monitor
bindsym $mod+Ctrl+Shift+Left exec ${workspace_helper}/bin/workspace_helper send_to_previous_monitor
bindsym $mod+Ctrl+Right exec ${workspace_helper}/bin/workspace_helper go_to_next_monitor
bindsym $mod+Ctrl+Shift+Right exec ${workspace_helper}/bin/workspace_helper send_to_next_monitor
'';
};
disable-focus-follows-mouse = pkgs.writeTextFile {

View File

@ -0,0 +1,173 @@
#!/usr/bin/env bash
#
# A helper to manage workspaces across multiple monitors.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# TODO: Only move output if it is on the wrong monitor
############## Setup #########################
# function cleanup {
# log "Killing child process $wlsunset_pid"
# kill "$wlsunset_pid"
# true
# }
# for sig in EXIT; do
# trap "set +e; cleanup" "$sig"
# done
function die {
local status_code="$1"
shift
(>&2 echo "${@}")
exit "$status_code"
}
function log {
(>&2 echo "${@}")
}
############## Program #########################
function main {
local cmd="$1"
shift
if [ "$cmd" = "go_to_next_monitor" ]; then
go_to_next_monitor "${@}"
elif [ "$cmd" = "send_to_next_monitor" ]; then
send_to_next_monitor "${@}"
elif [ "$cmd" = "go_to_previous_monitor" ]; then
go_to_previous_monitor "${@}"
elif [ "$cmd" = "send_to_previous_monitor" ]; then
send_to_previous_monitor "${@}"
elif [ "$cmd" = "go_to_workspace" ]; then
go_to_workspace "${@}"
elif [ "$cmd" = "send_to_workspace" ]; then
send_to_workspace "${@}"
else
die 1 "Unrecognized command $cmd"
fi
}
function go_to_next_monitor {
local monitor_index workspace_index workspace
workspace=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused == true) | .name')
workspace_index=$(parse_workspace_index "${workspace}")
# monitor_index=$(parse_monitor_index "${workspace}")
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
local target output target_monitor
target_monitor=$(normalize_monitor_index "$((monitor_index+1))")
target=$(encode_workspace "${target_monitor}" "${workspace_index}")
output=$(get_output "${target_monitor}")
swaymsg workspace "${target}" \; move workspace to output "$output"
}
function send_to_next_monitor {
local monitor_index workspace_index workspace
workspace=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused == true) | .name')
workspace_index=$(parse_workspace_index "${workspace}")
# monitor_index=$(parse_monitor_index "${workspace}")
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
local target output target_monitor
target_monitor=$(normalize_monitor_index "$((monitor_index+1))")
target=$(encode_workspace "${target_monitor}" "${workspace_index}")
output=$(get_output "${target_monitor}")
swaymsg move container to workspace "${target}" \; workspace "$target" move to output "$output"
}
function go_to_previous_monitor {
local monitor_index workspace_index workspace
workspace=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused == true) | .name')
workspace_index=$(parse_workspace_index "${workspace}")
# monitor_index=$(parse_monitor_index "${workspace}")
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
local target output target_monitor
target_monitor=$(normalize_monitor_index "$((monitor_index-1))")
target=$(encode_workspace "${target_monitor}" "${workspace_index}")
output=$(get_output "${target_monitor}")
swaymsg workspace "${target}" \; move workspace to output "$output"
}
function send_to_previous_monitor {
local monitor_index workspace_index workspace
workspace=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused == true) | .name')
workspace_index=$(parse_workspace_index "${workspace}")
# monitor_index=$(parse_monitor_index "${workspace}")
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
local target output target_monitor
target_monitor=$(normalize_monitor_index "$((monitor_index-1))")
target=$(encode_workspace "${target_monitor}" "${workspace_index}")
output=$(get_output "${target_monitor}")
swaymsg move container to workspace "${target}" \; workspace "$target" move to output "$output"
}
function go_to_workspace {
local monitor_index workspace_index workspace output
workspace_index="$1"
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
workspace=$(encode_workspace "$monitor_index" "$workspace_index")
output=$(get_output "${monitor_index}")
swaymsg workspace "${workspace}" \; move workspace to output "$output"
}
function send_to_workspace {
local monitor_index workspace_index workspace output
workspace_index="$1"
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
workspace=$(encode_workspace "$monitor_index" "$workspace_index")
output=$(get_output "${monitor_index}")
swaymsg move container to workspace "${workspace}" \; workspace "${workspace}" move to output "$output"
}
function get_output {
local monitor_index output
monitor_index="$1"
output=$(swaymsg -t get_outputs | jq -r ".[${monitor_index}].name")
echo "$output"
}
function encode_workspace {
local monitor_index workspace_index
monitor_index="$1"
workspace_index="$2"
if [ "$monitor_index" = "0" ]; then
echo "$workspace_index"
else
echo "${monitor_index}-${workspace_index}"
fi
}
function parse_monitor_index {
local workspace="$1"
if [[ $workspace = *-* ]]; then
cut -d '-' -f 1 <<<"$workspace"
else
echo "0"
fi
}
function parse_workspace_index {
local workspace="$1"
if [[ $workspace = *-* ]]; then
cut -d '-' -f 2 <<<"$workspace"
else
echo "$workspace"
fi
}
function normalize_monitor_index {
local monitor_index num_monitors
monitor_index="$1"
num_monitors=$(swaymsg -t get_outputs | jq length)
while [ "$monitor_index" -lt 0 ]; do
monitor_index=$((monitor_index + num_monitors))
done
while [ "$monitor_index" -ge "$num_monitors" ]; do
monitor_index=$((monitor_index - num_monitors))
done
echo "$monitor_index"
}
main "${@}"