diff --git a/nix/configuration/roles/shikane/files/config.toml b/nix/configuration/roles/shikane/files/config.toml index b5beefcb..d8b651b8 100644 --- a/nix/configuration/roles/shikane/files/config.toml +++ b/nix/configuration/roles/shikane/files/config.toml @@ -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 diff --git a/nix/configuration/roles/sway/default.nix b/nix/configuration/roles/sway/default.nix index a907b7e7..10e0cfc3 100644 --- a/nix/configuration/roles/sway/default.nix +++ b/nix/configuration/roles/sway/default.nix @@ -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 { diff --git a/nix/configuration/roles/sway/files/workspace_helper.bash b/nix/configuration/roles/sway/files/workspace_helper.bash new file mode 100644 index 00000000..544f7bc4 --- /dev/null +++ b/nix/configuration/roles/sway/files/workspace_helper.bash @@ -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 "${@}"