summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2024-01-16 17:43:08 +0000
committerSean Whitton <spwhitton@spwhitton.name>2024-01-16 18:10:25 +0000
commit2de521a884bc18a80d3aa7b58591019f2257fcd0 (patch)
tree920d1ba67ab3684acf2f68bb138327be7079c2b2 /scripts
parent5a7cf7e3595c3a25c8885d40a0793228b80be7c1 (diff)
downloaddotfiles-2de521a884bc18a80d3aa7b58591019f2257fcd0.tar.gz
i3status-wrapper: rewrite normalise_ws_cols, improve monocle mode
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/desktop/i3status-wrapper136
1 files changed, 94 insertions, 42 deletions
diff --git a/scripts/desktop/i3status-wrapper b/scripts/desktop/i3status-wrapper
index 81e1e7cc..11864e23 100755
--- a/scripts/desktop/i3status-wrapper
+++ b/scripts/desktop/i3status-wrapper
@@ -31,7 +31,7 @@ use Sys::Hostname;
use POSIX "floor", "mkfifo";
use File::Basename "basename", "dirname";
use File::Spec::Functions "catfile";
-use List::Util "first", "max";
+use List::Util qw(first min max);
$| = 1;
@@ -274,8 +274,13 @@ unless (fork // warn "couldn't fork command pipe reader") {
$mv->($i-1);
}
} elsif ($cmd eq "monocle toggle\n") {
- $ws->{monocle} = !$ws->{monocle};
- normalise_ws_cols();
+ if (my $m = $ws->{monocle}) {
+ undef $ws->{monocle};
+ normalise_ws_cols(abs ++$m);
+ } else {
+ $ws->{monocle} = -$i-1;
+ normalise_ws_cols();
+ }
kill USR1 => $i3status;
}
@@ -394,7 +399,7 @@ sub normalise_ws_cols {
my $ws = $info{paper_ws}{$info{focused_ws}};
my $floating_focus;
my $old_cols = $ws->{cols};
- my $old_i = first { $old_cols->[$_] == $ws->{focused_col} }
+ my $old_i = shift // first { $old_cols->[$_] == $ws->{focused_col} }
0..$#$old_cols;
my @trees = $wmipc->get_tree;
while (@trees) {
@@ -409,47 +414,94 @@ sub normalise_ws_cols {
}
}
my $cols = $ws->{cols};
- with_ignored_events {
- $wmipc->cmd("focus tiling");
- while (1) {
- my $i = first { $cols->[$_] eq $ws->{focused_col} } 0..$#$cols;
- my $mid_i = floor @$cols/2;
- # Pull column in if there are too few columns but some available.
- if (!$ws->{monocle} && $ws->{ncols} > @$cols
- && ($ws->{off_left}->@* || $ws->{off_right}->@*)) {
-
- if ($ws->{off_left}->@* # pull from left
- && ($i < $mid_i || !$ws->{off_right}->@*)) {
- my $pulled = pop $ws->{off_left}->@*;
- my $k = $old_i == $#$old_cols ? $i+1 : $i;
- $wmipc->cmd(("focus left")x$i,
- show_con($pulled), "move left",
- ("focus right")x$k);
- unshift @$cols, $pulled;
- $ws->{focused_col} = $cols->[$k];
-
- } elsif ($ws->{off_right}->@* # pull from right
- && ($i >= $mid_i || !$ws->{off_left}->@*)) {
- my $j = $#$cols - $i;
- my $pulled = pop $ws->{off_right}->@*;
- $wmipc->cmd(("focus right")x$j,
- show_con($pulled),
- ("focus left")x($old_i == 0 ? $j+1 : $j));
- push @$cols, $pulled;
- $ws->{focused_col} = $cols->[$old_i == 0 ? $i : $i+1];
- }
+ my $i = first { $cols->[$_] eq $ws->{focused_col} } 0..$#$cols;
+
+ my @cmds;
+ my $avail_l = scalar $ws->{off_left}->@*;
+ my $avail_r = scalar $ws->{off_right}->@*;
+ if (!$ws->{monocle} && $ws->{ncols} > @$cols && ($avail_l || $avail_r)) {
+ # Pull columns in if there are too few columns but some available.
+ # Want the focused column, after pulls, to be the $old_i'th.
+ my ($from_l, $from_r);
+ my $want = $ws->{ncols} - @$cols;
+ # When we lose columns, the focused column either moves left or
+ # stays the same. So always $old_i >= $i.
+ if ($old_i > $i) {
+ if ($old_i == $#$old_cols) {
+ # We were in the final column. Either we closed the
+ # rightmost column, or we lost arbitrary columns from the
+ # left (e.g. monocle from the last column).
+ # In either case it is fine to pull more from the left.
+ $from_l = min $avail_l, $want;
+ } else {
+ # We have $i < $old_i < $#$old_cols.
+ # We must have lost at least $old_i-$i from the left.
+ $from_l = min $avail_l, $old_i-$i;
}
- # Push a column off if there are too many columns.
- elsif (@$cols > $ws->{ncols} || $ws->{monocle} && @$cols > 1) {
- my $pushed = $i < $mid_i ? pop @$cols : shift @$cols;
- $wmipc->cmd(hide_con($pushed));
- push $ws->{$i < $mid_i ? "off_right" : "off_left"}->@*,
- $pushed;
+ } else { # $old_i == $i.
+ if ($old_i == 0) {
+ # We were in the first column. Either we closed the leftmost
+ # column, or we lost arbitrary columns from the left
+ # (e.g. monocle from the first column). We prefer to pull
+ # from the left in the former case. If we are indeed exiting
+ # monocle mode, we must pull from the right.
+ if (@$cols == 1) {
+ $from_r = min $avail_r, $want;
+ } else {
+ $from_l = !!$avail_l;
+ }
+ } else {
+ # It must be that we lost columns from the right.
+ $from_r = min $avail_r, $want;
}
- # Number of columns is correct.
- else { last }
}
- $wmipc->cmd("focus floating") if $floating_focus;
+
+ if ($from_l //= min $avail_l, $want-$from_r) {
+ my @pulled = splice $ws->{off_left}->@*, -$from_l, $from_l;
+ push @cmds, ("focus left")x$i,
+ map +(show_con($_), "move left"), reverse @pulled;
+ unshift @$cols, @pulled;
+ $i = 0;
+ }
+ if ($from_r //= min $avail_r, $want-$from_l) {
+ my @pulled
+ = reverse splice $ws->{off_right}->@*, -$from_r, $from_r;
+ push @cmds, ("focus right")x($#$cols-$i),
+ map show_con($_), @pulled;
+ push @$cols, @pulled;
+ $i = $#$cols;
+ }
+
+ if ($i > $old_i) {
+ push @cmds, ("focus left")x($i-$old_i);
+ } elsif ($old_i > $i) {
+ push @cmds, ("focus right")x($old_i-$i);
+ }
+
+ $ws->{focused_col} = $cols->[$old_i];
+ }
+ # Push columns off if there are too many columns.
+ # This should never change which container is focused.
+ elsif (my $n = $ws->{monocle} ? @$cols-1 : @$cols-$ws->{ncols} > 0) {
+ my $left = $i;
+ my $right = $#$cols-$i;
+ if ($left >= $right) {
+ $left = min $left, $n;
+ $right = $n-$left;
+ } else {
+ $right = min $right, $n;
+ $left = $n-$right;
+ }
+ my @to_left = splice @$cols, 0, $left;
+ my @to_right = reverse splice @$cols, -$right, $right;
+
+ push @cmds, map hide_con($_), @to_left, @to_right;
+ push $ws->{off_left}->@*, @to_left;
+ push $ws->{off_right}->@*, @to_right;
+ }
+ if (@cmds) {
+ push @cmds, "focus floating" if $floating_focus;
+ with_ignored_events { $wmipc->cmd("focus tiling", @cmds) }
}
}