diff --git a/sway/displays.pl b/sway/displays.pl index bc6c149..8d9d3c4 100755 --- a/sway/displays.pl +++ b/sway/displays.pl @@ -1,5 +1,16 @@ #!/usr/bin/perl +######################################################################## +# Usage +######################################################################## +# +# $ displays.pl [layout] [-w] +# +# layout Name of desired layout, as configured starting at line 100 +# If missing, last known layout is used (logged to file $last) +# -w (Re)load waybar only. Skip display configuration. Only kill +# existing waybars and start new ones for desired layout + ######################################################################## # Dependencies ######################################################################## @@ -17,11 +28,14 @@ # "output": __OUTPUT__ # "position": __POSITION__ # "width": __WIDTH__ (optional) -my $waybar_template = '/home/jpm/.config/waybar/config.template'; +my $waybar_template = "$ENV{'HOME'}/.config/waybar/config.template"; # Temporary directory to save generated waybar config(s) my $waybar_temporary = '/tmp'; +# File to log and recover last used layout name +my $last = "$ENV{'HOME'}/.config/last_display"; + ######################################################################## # Display Serials and Names ######################################################################## @@ -138,8 +152,6 @@ my %configs = ( use strict; use warnings; -# Bail if zero or >1 args -my $last = "/home/jpm/.config/last_display"; my $waybar_only = 0; my $config; @@ -157,12 +169,12 @@ if (scalar(@ARGV)) { } } +# Get previous config if one is not provided unless (defined $config) { - open(my $fh, '<', $last); + open(my $fh, '<', $last) || die "Config name not provided and failed to open $last\n"; $config = <$fh>; close($fh); chomp $config; - print "$config\n"; } # Bail if requested config doesn't exist @@ -170,11 +182,14 @@ unless (defined $configs{$config}) { die "$config is not a defined configuration: " . join(', ', keys %configs) . "\n"; } -# Import and setup JSON object -use JSON::XS; -my $json = JSON::XS->new(); +# Write config that is to be used so that it can be recovered as default +open(my $fh, '>', $last) || print STDERR "Config name cannot be written to $last\n"; +print $fh $config; +close($fh); # Fetch connected displays +use JSON::XS; +my $json = JSON::XS->new(); my $displays_raw = `swaymsg -t get_outputs --raw`; my $displays = $json->decode($displays_raw); @@ -182,7 +197,6 @@ my $displays = $json->decode($displays_raw); # displays and a list of displays to disable my $on; my @off; - for (my $i = 0; $i < scalar(@$displays); $i++) { # If a display is found without any settings, print error and turn it off @@ -203,8 +217,9 @@ for (my $i = 0; $i < scalar(@$displays); $i++) { } +# Skip enabling/disabling displays if only running waybar (re)start unless ($waybar_only) { - # Number of simultaneous outputs is limited by possible, so disabled displays first + # Number of simultaneous outputs is limited by gpu, so disabled displays first foreach (@off) { # Sway returns status as JSON @@ -226,14 +241,35 @@ foreach my $p ( @{ $t->table } ) { my $cmndline = $p->{'cmndline'}; $cmndline =~ s/\s*$//g; if ($cmndline =~ /^waybar.*/) { + # Never kill this process if ($p->{'pid'} == $$) { next; + # SIGKILL match + # TODO BUG: when multiple processes are running, some respawn with new PIDs. IDK why? } else { $p->kill(9); } } } +# Load in config template +my $template; +if (open (my $fh, '<', $waybar_template)) { + while (<$fh>) { + $template .= $_; + } + close $fh; + chomp $template; +} else { + print STDERR "Failed to load template $waybar_template\n"; +} + +# If template is already set up as an array, remove the square brackets so that we can concatenate multiple displays +$template =~ s/^[^\[\{]*\[(.*)\]$/$1/s; + +# Setup waybar config file +my $waybar = ''; + # Configure each enabled display foreach my $out (keys %$on) { @@ -262,46 +298,45 @@ foreach my $out (keys %$on) { } } - # If waybar position is set, fork, generate config and execute it - if (defined $on->{$out}->{waybar}) { - my $pid = fork; - unless ($pid) { - open STDIN, '/dev/null'; - open STDOUT, '>>/dev/null'; - open STDERR, '>>/dev/null'; + # Skip waybar setup if template failed to be loaded + if ( (defined $template) && (defined $on->{$out}->{waybar}) && ($on->{$out}->{waybar} =~ m/(top|bottom|left|right)/) ) { - # Load in config template - my $waybar; - open (my $fh, '<', $waybar_template); - while (<$fh>) { - $waybar .= $_; - } - close $fh; - chomp $waybar; - - # Replace basic preferences - $waybar =~ s/__OUTPUT__/"$on->{$out}->{output}"/; - $waybar =~ s/__POSITION__/"$on->{$out}->{waybar}"/; - if (defined $on->{$out}->{width}) { - $waybar =~ s/__WIDTH__/$on->{$out}->{width}/; - # If width is not set, comment that line out to use default - } else { - $waybar =~ s/([^\s]*\s*)__WIDTH__/\/\/ $1__WIDTH__/gg; - } - - # Write config to a temporary file - my $tmp = $waybar_temporary . "/" . $on->{$out}->{output} . ".tmp"; - open ($fh, '>', $tmp); - print $fh $waybar; - close $fh; - `nohup waybar --config=$tmp`; - - # Remove config - unlink $tmp; + # If there's already a display set up, add a comma + unless ($waybar eq '') { + $waybar .= ','; } + + $waybar .= $template; + + # Replace basic preferences + $waybar =~ s/__OUTPUT__/"$on->{$out}->{output}"/; + $waybar =~ s/__POSITION__/"$on->{$out}->{waybar}"/; + if (defined $on->{$out}->{width}) { + $waybar =~ s/__WIDTH__/$on->{$out}->{width}/; + # If width is not set, comment that line out to use default + } else { + $waybar =~ s/([^\s]*\s*)__WIDTH__/\/\/ $1__WIDTH__/gg; + } + } } -open(my $fh, '>', $last); -print $fh $config; -close($fh); +# Restore array formatting +$waybar = '[' . $waybar . ']'; + +# Start Waybar as fork +my $pid = fork; +unless ($pid) { + open STDIN, '/dev/null'; + open STDOUT, '>>/dev/null'; + open STDERR, '>>/dev/null'; + # Write config to a temporary file + my $tmp = $waybar_temporary . "/waybar-" . time() .".config"; + open ($fh, '>', $tmp); + print $fh $waybar; + close $fh; + `nohup waybar --config=$tmp`; + + # Remove config + unlink $tmp; +}