From 35755ecea793864138f24eb08b1917f95cfdcd1a Mon Sep 17 00:00:00 2001 From: John Mertz Date: Thu, 18 Jul 2024 22:46:46 -0600 Subject: [PATCH] Fix grave script! TODO: Should probably convert to use AnyEvent::Sway --- sway/popup-term.pl | 137 +++++++++++++++++++++++++++++-------------- sway/toggle_grave.sh | 9 +++ 2 files changed, 102 insertions(+), 44 deletions(-) create mode 100755 sway/toggle_grave.sh diff --git a/sway/popup-term.pl b/sway/popup-term.pl index d29a3fb..f3c6895 100755 --- a/sway/popup-term.pl +++ b/sway/popup-term.pl @@ -2,79 +2,128 @@ use strict; use warnings; +use feature ( 'signatures' ); +use JSON::MaybeXS; +my $json = JSON::MaybeXS->new(); + +our ($workspace, $term_id, $term_ws, $ww, $wh, $tw, $th, $tc); +# Desired terminal dimensions (px or %) and corner (top-right, top-left, bottom-right, bottom-left) +$tw = '100%'; +$th = '30%'; +$tc = 'bottom-right'; # Workspace to push the terminal to when dismissed my $hidden = 'grave'; -# Terminal application used for pop-up (swaymsg 'name') +# Terminal executable used for pop-up my $term = 'alacritty'; # App ID -my $class = 'Alacritty-grave'; +my $app_id = 'Alacritty-grave'; -use JSON::XS; -my $json = JSON::XS->new(); +sub search($nodes, $o=undef, $w=undef, $depth=0) { + my $debug = 0; + my $term_id; + $depth++; + my $prefix = " "x($depth*4); + foreach my $n (@{$nodes}) { + print("${prefix}Checking node $n->{id}".(defined($n->{name}) ? " ($n->{name})" : "")."\n") if ($debug); + print("${prefix}Considering $n->{app_id}...\n") if ($debug && defined($n->{app_id})); + if ($n->{type} eq "output") { + $o = $n->{name}; + print("${prefix}Searching output $o\n") if ($debug); + } elsif ($n->{type} eq "workspace") { + $w = $n->{name}; + print("${prefix}Searching workspace $w\n") if ($debug); + } else { + print("${prefix}Currently on display $o, workspace $w\n") if ($debug); + if (defined($n->{app_id}) && $n->{app_id} eq $app_id) { + $term_id = $n->{id}; + $term_ws = $w; + print("${prefix}Found $app_id with id $term_id on workspace $w\n") if ($debug); + return $term_id; + } + } + $term_id = search($n->{floating_nodes}, $o, $w, $depth); + $term_id = search($n->{nodes}, $o, $w, $depth) if ($term_id == 0); + print("${prefix}Found $term_id on $w\n") if ($debug && $term_id); + return $term_id if ($term_id); + } + print("${prefix}Not found, moving up a node\n") if ($debug); + return 0; +} + +sub resize() { + my ($d, $r, $h, $w) = (0, 0); + if (my ($hit) = $tw =~ m/^(100|\d\d?)\%$/) { + $w = int(($ww * $hit) / 100); + $r = $ww - $w if ($tc =~ m/right$/); + } elsif (($tw =~ m/^\d+$/) && (1 < $tw <= $ww)) { + $d = $wh - $th if ($tc =~ m/^bottom/); + } + if (my ($hit) = $th =~ m/^(100|\d\d?)\%$/) { + $h = int(($wh * $hit) / 100); + $d = $wh - $h if ($tc =~ m/^bottom/); + } elsif (($tw =~ m/^\d+$/) && (1 < $tw <= $ww)) { + $r = $ww - $tw if ($tc =~ m/right$/); + } + `swaymsg "[con_id=$term_id]" resize set width ${w}px height ${h}px, move position ${r}px ${d}px`; +} my $raw = join("\n",`swaymsg -t get_tree`); my $root = $json->decode($raw); +$term_id = search($root->{nodes}) || undef; -# Get focused -my $display = $root->{focus}->[0]; -my ($workspace, $term_id, $term_ws); +my $focused = $root->{focus}->[0]; foreach my $d (@{$root->{nodes}}) { - # If both the current workspace and terminal have been found - # nothing else to look for - if (defined($workspace) && defined($term_id)) { - last; - # If the display from this iteration of the loop is in focus - # look for the active workspace - } elsif ($d->{id} eq $display) { + last if (defined($workspace)); + if ($d->{id} eq $focused) { foreach my $w (@{$d->{nodes}}) { - # Again, if both found, skip - if (defined($workspace) && defined($term_id)) { - last; - # Otherwise if the current workspace is active, mark it - } elsif ($w->{id} eq $d->{focus}->[0]) { + if ($w->{id} eq $d->{focus}->[0]) { $workspace = $w->{name}; - } - # In any case, look for the terminal app - foreach my $n (@{$w->{floating_nodes}}) { - if ($n->{name} eq $term) { - $term_id = $n->{id}; - $term_ws = $w->{name}; - last; - } - } - } - # All other displays only need to be quickly searched for the term_id - } else { - foreach my $w (@{$d->{nodes}}) { - if (defined($term_id)) { + $ww = $w->{rect}->{width}; + $wh = $w->{rect}->{height}; last; } - foreach my $n (@{$w->{floating_nodes}}) { - if ($n->{name} eq $term) { - $term_id = $n->{id}; - $term_ws = $w->{name}; - last; - } - } } } } +#print("Current workspace is $workspace ($ww x $wh)\n"); +#print("Found terminal at node $term_id\n") if (defined($term_id)); +#print("Found terminal on workspace $term_ws\n") if (defined($term_ws)); + # If there is no terminal found, spawn one +my $resize = 0; if (!defined($term_id)) { - print "No term running, starting one\n"; - `$term --config-file $ENV{HOME}/.dotfiles/alacritty/grave.yml --class $class`; + my $pid = fork(); + if ($pid) { + print "No term running, starting one with PID $pid\n"; + sleep 1; + $raw = join("\n",`swaymsg -t get_tree`); + $root = $json->decode($raw); + $term_id = search($root->{nodes}) || undef; + die("Term not found after starting") unless (defined($term_id)); + } else { + print("Starting in fork...\n"); + `$term --config-file $ENV{HOME}/.dotfiles/alacritty/grave.toml --class $app_id & disown`; + print("Exitting\n"); + exit(1); + } + resize(); +} + # If the current workspace is known and terminal isn't on it, bring and focus -} elsif ($workspace != $term_ws) { +if (defined($term_ws) && $workspace ne $term_ws) { print "Term not on current workspace, bringing it\n"; + `swaymsg "[con_id=$term_id]" floating enable`; + resize(); + `swaymsg "[con_id=$term_id]" sticky enable`; `swaymsg "[con_id=$term_id]" move workspace $workspace`; `swaymsg "[con_id=$term_id]" focus`; - `swaymsg "[con_id=$term_id]" sticky enable`; # Otherwise hide it from whereever it is } else { print "Term is on current workspace or lost, moving to $hidden\n"; `swaymsg "[con_id=$term_id]" sticky disable`; `swaymsg "[con_id=$term_id]" move workspace $hidden`; + `swaymsg "[con_id=$term_id]" floating disable`; } diff --git a/sway/toggle_grave.sh b/sway/toggle_grave.sh new file mode 100755 index 0000000..cb1ba2e --- /dev/null +++ b/sway/toggle_grave.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +OLDPWD=$OLDPWD +PWD=$PWD +cd $HOME/scripts/sway/ +source ~/.dotfiles/bash/plenv-path.sh +perl -Ilocal/lib/perl5/5.38.2 popup-term.pl +cd $OLDPWD +cd $PWD