diff options
author | Sean Whitton <spwhitton@spwhitton.name> | 2023-02-01 11:31:07 -0700 |
---|---|---|
committer | Sean Whitton <spwhitton@spwhitton.name> | 2023-02-01 12:05:27 -0700 |
commit | 14873d2c0083cd4ed340dc1f63c31030d3e020e0 (patch) | |
tree | 5d74f8abde6ac789c965fb8396ece3c122063e0d | |
parent | a23690c7ec4a361d956254d27fbbe6a7009f3a13 (diff) | |
download | papersway-14873d2c0083cd4ed340dc1f63c31030d3e020e0.tar.gz |
i3status-wrapper: swap parent and child processes
This should ensure the filtering loop stays alive in more circumstances.
-rwxr-xr-x | scripts/desktop/i3status-wrapper | 168 |
1 files changed, 84 insertions, 84 deletions
diff --git a/scripts/desktop/i3status-wrapper b/scripts/desktop/i3status-wrapper index 91f8303..0f8f96e 100755 --- a/scripts/desktop/i3status-wrapper +++ b/scripts/desktop/i3status-wrapper @@ -42,108 +42,108 @@ unless ($i3status) { tie my %info, "IPC::Shareable", undef, { destroy => 1 }; -unless (fork // die "couldn't fork()!") { - $pipe->reader; - open STDIN, "<&=", $pipe->fileno - or die "couldn't reopen child's STDIN!"; +unless (fork // warn "couldn't fork monitoring loop") { + my $caffeinated_id; - # Following based on Michael Stapelberg's sample i3status-wrapper script. + open my $events, "-|", + $wmipc, "-t", "subscribe", "-m", '[ "window", "workspace" ]'; - my $hostname = hostname; - my $username = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<); - - # Skip the first line which contains the version header. - print scalar <>; - - # The second line contains the start of the infinite array. - print scalar <>; + sub register_caffeinated { + $caffeinated_id = $_[0]->{id}; + $info{caffeinated_name} = $_[0]->{name}; + kill USR1 => $i3status; + } - # Read lines forever, ignore a comma at the beginning if it exists. - while (my ($statusline) = (<> =~ /^,?(.*)/)) { - # If there is a decoding error, just skip this line, to minimise - # status bar freezes. This should be fine here because this filtering - # loop is in itself stateless. It's only if the decoding error - # involves newlines in the wrong places, or similar, that this skip - # could cause us to produce invalid output. - my $blocks = eval { decode_json $statusline } // next; + sub clear_caffeinated { + undef $caffeinated_id; + undef $info{caffeinated_name}; + kill USR1 => $i3status; + } - unshift @$blocks, - { - name => "caffeinated", - full_text => "Caffeinated: " . $info{caffeinated_name} } - if $info{caffeinated_name}; + # Determine the initial state -- the WM might just have been reloaded. - unshift @$blocks, - { name => "hostinfo", full_text => $username . "@" . $hostname }; + my $workspaces = @{ decode_json `$wmipc -t get_workspaces` }; + wsbuttons($workspaces > 1 ? "yes" : "no"); - print encode_json($blocks) . ",\n"; + my @trees = decode_json `$wmipc -t get_tree`; + while (@trees) { + for ((shift @trees)->{nodes}->@*) { + if (grep $_ eq "caffeinated", $_->{marks}->@*) { + register_caffeinated($_); + last; + } else { + unshift @trees, $_; + } + } } + + # Now loop forever reading events, assuming no exceptions. + + eval { + while (my $event = decode_json <$events>) { + if ($event->{change} eq "mark") { + if (grep $_ eq "caffeinated", $event->{container}{marks}->@*) + { + register_caffeinated($event->{container}); + } elsif ($caffeinated_id + and $caffeinated_id == $event->{container}{id}) { + clear_caffeinated(); + } + } elsif ($event->{change} eq "init") { + ++$workspaces == 2 and wsbuttons("yes"); + } elsif ($event->{change} eq "empty") { + --$workspaces == 1 and wsbuttons("no"); + # For simplicity, only fresh-workspace script calls + # compact_workspaces atm. For greater consistency we could + # call it here, too, without supplying a leave_gap argument. + } + } + }; + + # Give up if there's a decoding error. We can't ignore the problem + # because we don't want our ideas regarding how many workspaces there are, + # and whether anything is caffeinated, to get out of sync. + # + # The user can use the WM's "reload" command to restart this loop. + $@ and wsbuttons("yes"), clear_caffeinated(); } -my $caffeinated_id; +$pipe->reader; +open STDIN, "<&=", $pipe->fileno or die "couldn't reopen STDIN!"; -open my $events, "-|", - $wmipc, "-t", "subscribe", "-m", '[ "window", "workspace" ]'; +# Following based on Michael Stapelberg's sample i3status-wrapper script. -# Determine the initial state -- the WM might just have been reloaded. +my $hostname = hostname; +my $username = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<); -my $workspaces = @{ decode_json `$wmipc -t get_workspaces` }; -wsbuttons($workspaces > 1 ? "yes" : "no"); +# Skip the first line which contains the version header. +print scalar <>; -my @trees = decode_json `$wmipc -t get_tree`; -while (@trees) { - for ((shift @trees)->{nodes}->@*) { - if (grep $_ eq "caffeinated", $_->{marks}->@*) { - register_caffeinated($_); - last; - } else { - unshift @trees, $_; - } - } -} +# The second line contains the start of the infinite array. +print scalar <>; -# Now loop forever reading events, assuming no exceptions. +# Read lines forever, ignore a comma at the beginning if it exists. +while (my ($statusline) = (<> =~ /^,?(.*)/)) { + # If there is a decoding error, just skip this line, to minimise status + # bar freezes. This should be fine here because this filtering loop is in + # itself stateless. It's only if the decoding error involves newlines in + # the wrong places, or similar, that this skip could cause us to produce + # invalid output. + my $blocks = eval { decode_json $statusline } // next; -eval { - while (my $event = decode_json <$events>) { - if ($event->{change} eq "mark") { - if (grep $_ eq "caffeinated", $event->{container}{marks}->@*) { - register_caffeinated($event->{container}); - } elsif ($caffeinated_id - and $caffeinated_id == $event->{container}{id}) { - clear_caffeinated(); - } - } elsif ($event->{change} eq "init") { - ++$workspaces == 2 and wsbuttons("yes"); - } elsif ($event->{change} eq "empty") { - --$workspaces == 1 and wsbuttons("no"); - # For simplicity, only fresh-workspace script calls - # compact_workspaces atm. For greater consistency we could call - # it here, too, without supplying a leave_gap argument. - } - } -}; + unshift @$blocks, + { + name => "caffeinated", + full_text => "Caffeinated: " . $info{caffeinated_name} } + if $info{caffeinated_name}; -# Here we give up if there's a decoding error. We can't ignore the problem -# because we don't want our ideas regarding how many workspaces there are, and -# whether anything is caffeinated, to get out of sync. -# -# The user can use the WM's "reload" command to restart the loop. -$@ and wsbuttons("yes"), clear_caffeinated(); + unshift @$blocks, + { name => "hostinfo", full_text => $username . "@" . $hostname }; + + print encode_json($blocks) . ",\n"; +} sub wsbuttons { return unless $ENV{XDG_CURRENT_DESKTOP} eq "sway"; wmipc "bar bar-0 workspace_buttons $_[0]"; } - -sub register_caffeinated { - $caffeinated_id = $_[0]->{id}; - $info{caffeinated_name} = $_[0]->{name}; - kill USR1 => $i3status; -} - -sub clear_caffeinated { - undef $caffeinated_id; - undef $info{caffeinated_name}; - kill USR1 => $i3status; -} |