From 08192cb0e667cb9eeb8e5760f57f97509490d871 Mon Sep 17 00:00:00 2001 From: Sean Whitton Date: Wed, 10 Apr 2024 18:33:20 +0800 Subject: i3status-wrapper: refactor: move processing user commands into a sub --- scripts/desktop/i3status-wrapper | 382 +++++++++++++++++++-------------------- 1 file changed, 190 insertions(+), 192 deletions(-) diff --git a/scripts/desktop/i3status-wrapper b/scripts/desktop/i3status-wrapper index 8cde0a94..054e804a 100755 --- a/scripts/desktop/i3status-wrapper +++ b/scripts/desktop/i3status-wrapper @@ -220,198 +220,7 @@ unless (fork // warn "couldn't fork command pipe reader") { while (my $cmd = <$cmdpipe_r>) { tied(%info)->lock; - - my $ws = $info{paper_ws}{$info{focused_ws}}; - my $cols = $ws->{cols}; - my $col_rows = $info{col_rows}{$ws->{focused_col}}; - my $i = first { $cols->[$_] == $ws->{focused_col} } 0..$#$cols; - - my $mv = sub { - my ($j, $move) = @_; - if (@$cols > $j >= 0) { - if ($move) { - # This does not trigger any events. - $wmipc->cmd( -"[con_id=@$cols[$i]] swap container with con_id @$cols[$j]" - ); - @$cols[$i, $j] = @$cols[$j, $i]; - } else { - $wmipc->cmd($j > $i ? "focus right" : "focus left"); - } - } elsif ($move && $ws->{monocle}) { - if ($j > $i && $ws->{off_right}->@*) { - push $ws->{off_left}->@*, pop $ws->{off_right}->@*; - } elsif ($j < $i && $ws->{off_left}->@*) { - push $ws->{off_right}->@*, pop $ws->{off_left}->@*; - } - } elsif ($j == @$cols && $ws->{off_right}->@*) { - my $pushed = shift @$cols; - my $pulled = pop $ws->{off_right}->@*; - my @cmds = show_con($pulled); - push $ws->{off_left}->@*, $pushed; - - if ($move) { - if ($col_rows || @$cols) { - push @cmds, $col_rows - ? "move left" - : "swap container with con_id @$cols[-1]"; - push @cmds, "focus right"; - } - if (@$cols) { - my $tem = pop @$cols; - push @$cols, $pulled, $tem; - } else { - push @$cols, $pulled; - } - } else { - $ws->{focused_col} = $pulled; - push @cmds, "move right" if $col_rows; - push @$cols, $pulled; - push @cmds, "focus child" if $info{col_rows}{$pulled}; - } - - with_ignored_events { $wmipc->cmd(@cmds, hide_con($pushed)) }; - kill USR1 => $i3status; - } elsif ($j == -1 && $ws->{off_left}->@*) { - my $pushed = pop @$cols; - my $pulled = pop $ws->{off_left}->@*; - my @cmds = show_con($pulled); - - push $ws->{off_right}->@*, $pushed; - - if ($move) { - if (@$cols) { - push @cmds, "move right" if $col_rows; - push @cmds, "focus left"; - my $tem = shift @$cols; - unshift @$cols, $tem, $pulled; - } else { - unshift @$cols, $pulled; - } - } else { - if ($col_rows) { - push @cmds, "move left"; - } elsif (@$cols) { - push @cmds, "swap container with con_id @$cols[0]"; - } - $ws->{focused_col} = $pulled; - unshift @$cols, $pulled; - push @cmds, "focus child" if $info{col_rows}{$pulled}; - } - - with_ignored_events { $wmipc->cmd(@cmds, hide_con($pushed)) }; - kill USR1 => $i3status; - } - $ws->{last_dir} = $j > $i ? 1 : -1; - }; - - # Command dispatch - - if ($cmd =~ /^(focus|move) (left|right)$/) { - $mv->($2 eq "right" ? $i+1 : $i-1, $1 eq "move"); - } elsif ($cmd =~ /^cols (incr|decr)$/) { - $ws->{ncols} += $1 eq "incr" ? 1 : -1; - normalise_ws_cols(); - kill USR1 => $i3status; - } - - elsif ($cmd =~ /^other column$/) { - # This is meant to be similar to my custom Emacs C-x o. - if ($i == 0 || $ws->{last_dir} == -1 && $i < $#$cols) { - $mv->($i+1); - } elsif ($i == $#$cols || $ws->{last_dir} == 1) { - $mv->($i-1); - } - } elsif ($cmd eq "monocle toggle\n") { - unless (ensure_disable_monocle($ws)) { - $ws->{monocle} = -$i-1; - normalise_ws_cols(); - } - kill USR1 => $i3status; - } - - elsif ($cmd =~ /^fresh-workspace ?(take|send)?$/) { - fresh_workspace(do { - if ($1 && $1 eq "take") { - go => 1, send => 1; - } elsif ($1 && $1 eq "send") { - send => 1; - } else { - go => 1; - } - }); - } - - elsif ($cmd =~ /^absorb_expel ?(left|right)?$/) { - my $dir = $1 eq "right" ? 1 : -1; - if ($col_rows > 1) { # expel - # If the column to the right or left also has rows, we'll just - # move the container into that column instead of expelling it. - # Possibly we could float the container, select the - # appropriate full column and unfloat it into place? - $wmipc->cmd(sprintf "move %s", $dir > 0 ? "right" : "left"); - $ws->{last_dir} = $dir; - } else { # absorb - my @cmds; - if ($i == 0 && $dir < 0 && $ws->{off_left}->@*) { - my $pulled = pop $ws->{off_left}->@*; - push @cmds, show_con($pulled), "move left"; - push @cmds, "splitv" unless $info{col_rows}{$pulled}; - push @cmds, "focus right", "move left"; - - with_ignored_events { $wmipc->cmd(@cmds) }; - normalise_ws_cols(); - } elsif ($i == $#$cols && $dir > 0 && $ws->{off_right}->@*) { - my $pulled = pop $ws->{off_right}->@*; - push @cmds, show_con($pulled); - push @cmds, "move right" if $col_rows; - push @cmds, "splitv" unless $info{col_rows}{$pulled}; - push @cmds, "focus left", "move right"; - - with_ignored_events { $wmipc->cmd(@cmds) }; - normalise_ws_cols(); - } elsif ($i == $#$cols && $dir < 0 - || $#$cols > $i > 0 - || $i == 0 && $dir > 0) { - push @cmds, $dir > 0 - ? ("focus right", "splitv", "focus left") - : ("focus left", "splitv", "focus right") - unless $info{col_rows}{ @$cols[$i+$dir] }; - push @cmds, $dir > 0 ? "move right" : "move left"; - - with_ignored_events { $wmipc->cmd(@cmds) }; - normalise_ws_cols($ws->{off_left}->@* && $dir > 0 - || $ws->{off_right}->@* && $dir < 0 - ? min($#$cols, max 0, $i+$dir) : $i); - } - if (@cmds) { - $ws->{last_dir} = $dir; - kill USR1 => $i3status; - } - } - } - - # Basic purpose of this wrapper command is to prevent accidentally - # moving to one of the holding workspaces using Sway's own commands. - elsif ($cmd =~ /^(move_)?workspace (prev|next)$/) { - my ($move, $dir) = (!!$1, $2); - $move && ensure_disable_monocle($ws); - my @keys = sorted_paper_ws(); - my $k = first { $keys[$_] == $info{focused_ws} } 0..$#keys; - if ($dir eq "next" && $k < $#keys || $dir eq "prev" && $k > 0) { - my @cmds = "workspace $dir"; - $info{focused_ws} = $keys[$dir eq "next" ? $k+1 : $k-1]; - if ($move) { - push @cmds, show_con($ws->{focused_col}); - push @cmds, "move right" - if $info{col_rows} - { $info{paper_ws}{$info{focused_ws}}{focused_col} }; - push @cmds, "focus child" if $col_rows; - } - $wmipc->cmd(@cmds); - } - } - + process_msg($cmd); tied(%info)->unlock; } } @@ -670,6 +479,195 @@ sub normalise_ws_cols { } } +sub process_msg { + my $cmd = shift; + + my $ws = $info{paper_ws}{$info{focused_ws}}; + my $cols = $ws->{cols}; + my $col_rows = $info{col_rows}{$ws->{focused_col}}; + my $i = first { $cols->[$_] == $ws->{focused_col} } 0..$#$cols; + + my $mv = sub { + my ($j, $move) = @_; + if (@$cols > $j >= 0) { + if ($move) { + # This does not trigger any events. + $wmipc->cmd( +"[con_id=@$cols[$i]] swap container with con_id @$cols[$j]" + ); + @$cols[$i, $j] = @$cols[$j, $i]; + } else { + $wmipc->cmd($j > $i ? "focus right" : "focus left"); + } + } elsif ($move && $ws->{monocle}) { + if ($j > $i && $ws->{off_right}->@*) { + push $ws->{off_left}->@*, pop $ws->{off_right}->@*; + } elsif ($j < $i && $ws->{off_left}->@*) { + push $ws->{off_right}->@*, pop $ws->{off_left}->@*; + } + } elsif ($j == @$cols && $ws->{off_right}->@*) { + my $pushed = shift @$cols; + my $pulled = pop $ws->{off_right}->@*; + my @cmds = show_con($pulled); + push $ws->{off_left}->@*, $pushed; + + if ($move) { + if ($col_rows || @$cols) { + push @cmds, $col_rows + ? "move left" + : "swap container with con_id @$cols[-1]"; + push @cmds, "focus right"; + } + if (@$cols) { + my $tem = pop @$cols; + push @$cols, $pulled, $tem; + } else { + push @$cols, $pulled; + } + } else { + $ws->{focused_col} = $pulled; + push @cmds, "move right" if $col_rows; + push @$cols, $pulled; + push @cmds, "focus child" if $info{col_rows}{$pulled}; + } + + with_ignored_events { $wmipc->cmd(@cmds, hide_con($pushed)) }; + kill USR1 => $i3status; + } elsif ($j == -1 && $ws->{off_left}->@*) { + my $pushed = pop @$cols; + my $pulled = pop $ws->{off_left}->@*; + my @cmds = show_con($pulled); + + push $ws->{off_right}->@*, $pushed; + + if ($move) { + if (@$cols) { + push @cmds, "move right" if $col_rows; + push @cmds, "focus left"; + my $tem = shift @$cols; + unshift @$cols, $tem, $pulled; + } else { + unshift @$cols, $pulled; + } + } else { + if ($col_rows) { + push @cmds, "move left"; + } elsif (@$cols) { + push @cmds, "swap container with con_id @$cols[0]"; + } + $ws->{focused_col} = $pulled; + unshift @$cols, $pulled; + push @cmds, "focus child" if $info{col_rows}{$pulled}; + } + + with_ignored_events { $wmipc->cmd(@cmds, hide_con($pushed)) }; + kill USR1 => $i3status; + } + $ws->{last_dir} = $j > $i ? 1 : -1; + }; + + # Command dispatch + + if ($cmd =~ /^(focus|move) (left|right)$/) { + $mv->($2 eq "right" ? $i+1 : $i-1, $1 eq "move"); + } elsif ($cmd =~ /^cols (incr|decr)$/) { + $ws->{ncols} += $1 eq "incr" ? 1 : -1; + normalise_ws_cols(); + kill USR1 => $i3status; + } elsif ($cmd =~ /^other column$/) { + # This is meant to be similar to my custom Emacs C-x o. + if ($i == 0 || $ws->{last_dir} == -1 && $i < $#$cols) { + $mv->($i+1); + } elsif ($i == $#$cols || $ws->{last_dir} == 1) { + $mv->($i-1); + } + } elsif ($cmd eq "monocle toggle\n") { + unless (ensure_disable_monocle($ws)) { + $ws->{monocle} = -$i-1; + normalise_ws_cols(); + } + kill USR1 => $i3status; + } elsif ($cmd =~ /^fresh-workspace ?(take|send)?$/) { + fresh_workspace(do { + if ($1 && $1 eq "take") { + go => 1, send => 1; + } elsif ($1 && $1 eq "send") { + send => 1; + } else { + go => 1; + } + }); + } elsif ($cmd =~ /^absorb_expel ?(left|right)?$/) { + my $dir = $1 eq "right" ? 1 : -1; + if ($col_rows > 1) { # expel + # If the column to the right or left also has rows, we'll just + # move the container into that column instead of expelling it. + # Possibly we could float the container, select the + # appropriate full column and unfloat it into place? + $wmipc->cmd(sprintf "move %s", $dir > 0 ? "right" : "left"); + $ws->{last_dir} = $dir; + } else { # absorb + my @cmds; + if ($i == 0 && $dir < 0 && $ws->{off_left}->@*) { + my $pulled = pop $ws->{off_left}->@*; + push @cmds, show_con($pulled), "move left"; + push @cmds, "splitv" unless $info{col_rows}{$pulled}; + push @cmds, "focus right", "move left"; + + with_ignored_events { $wmipc->cmd(@cmds) }; + normalise_ws_cols(); + } elsif ($i == $#$cols && $dir > 0 && $ws->{off_right}->@*) { + my $pulled = pop $ws->{off_right}->@*; + push @cmds, show_con($pulled); + push @cmds, "move right" if $col_rows; + push @cmds, "splitv" unless $info{col_rows}{$pulled}; + push @cmds, "focus left", "move right"; + + with_ignored_events { $wmipc->cmd(@cmds) }; + normalise_ws_cols(); + } elsif ($i == $#$cols && $dir < 0 + || $#$cols > $i > 0 + || $i == 0 && $dir > 0) { + push @cmds, $dir > 0 + ? ("focus right", "splitv", "focus left") + : ("focus left", "splitv", "focus right") + unless $info{col_rows}{ @$cols[$i+$dir] }; + push @cmds, $dir > 0 ? "move right" : "move left"; + + with_ignored_events { $wmipc->cmd(@cmds) }; + normalise_ws_cols($ws->{off_left}->@* && $dir > 0 + || $ws->{off_right}->@* && $dir < 0 + ? min($#$cols, max 0, $i+$dir) : $i); + } + if (@cmds) { + $ws->{last_dir} = $dir; + kill USR1 => $i3status; + } + } + } + + # Basic purpose of this wrapper command is to prevent accidentally + # moving to one of the holding workspaces using Sway's own commands. + elsif ($cmd =~ /^(move_)?workspace (prev|next)$/) { + my ($move, $dir) = (!!$1, $2); + $move && ensure_disable_monocle($ws); + my @keys = sorted_paper_ws(); + my $k = first { $keys[$_] == $info{focused_ws} } 0..$#keys; + if ($dir eq "next" && $k < $#keys || $dir eq "prev" && $k > 0) { + my @cmds = "workspace $dir"; + $info{focused_ws} = $keys[$dir eq "next" ? $k+1 : $k-1]; + if ($move) { + push @cmds, show_con($ws->{focused_col}); + push @cmds, "move right" + if $info{col_rows} + { $info{paper_ws}{$info{focused_ws}}{focused_col} }; + push @cmds, "focus child" if $col_rows; + } + $wmipc->cmd(@cmds); + } + } +} + =head fresh_workspace(%opts) Switch to the next free workspace, if any. Return the name of that workspace, -- cgit v1.2.3