diff options
Diffstat (limited to 'i3')
-rwxr-xr-x | i3/.bin/i3-switch-workspace | 137 | ||||
-rwxr-xr-x | i3/.bin/kill-focused | 49 | ||||
-rw-r--r-- | i3/.config/i3/config | 77 | ||||
-rw-r--r-- | i3/.config/i3/terminal-workspace.json | 125 |
4 files changed, 388 insertions, 0 deletions
diff --git a/i3/.bin/i3-switch-workspace b/i3/.bin/i3-switch-workspace new file mode 100755 index 0000000..b54afa1 --- /dev/null +++ b/i3/.bin/i3-switch-workspace @@ -0,0 +1,137 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use 5.014; + +use IO::Socket::UNIX; +use JSON::PP; + +my $json = JSON::PP->new; + +my $virtual_workspace = 'virtual'; + +my %message_types = ( + command => 0, + get_workspaces => 1, + subscribe => 2, + get_outputs => 3, + get_tree => 4, + get_marks => 5, + get_bar_config => 6, + get_version => 7, +); + +my %message_codes = (reverse %message_types); + +my $dir = $ARGV[0]; + +chomp(my $path = qx(i3 --get-socketpath)); +my $sock = IO::Socket::UNIX->new(Peer => $path); + +my $workspace_data = $json->decode(i3_msg('get_workspaces')); +my $tree_data = $json->decode(i3_msg('get_tree')); + +my $first = 99999; +my $last = -99999; +my $cur; +my $cur_name; +my $virtual_output; + +for my $i (0..$#$workspace_data) { + my $num = $workspace_data->[$i]{num}; + if ($workspace_data->[$i]{focused}) { + $cur = $num; + $cur_name = $workspace_data->[$i]{name}; + if ($cur_name eq $virtual_workspace) { + $virtual_output = $workspace_data->[$i]{output}; + } + } + + my $workspace_tree = find_workspace($tree_data, $num); + next unless + @{ $workspace_tree->{nodes} } || + @{ $workspace_tree->{floating_nodes} }; + + $first = $num if $num < $first; + $last = $num if $num > $last; +} + +if ($dir eq 'prev') { + if ($cur >= $first) { + i3_msg('command', "workspace ${\($cur - 1)}"); + } +} +elsif ($dir eq 'next') { + if ($cur <= $last) { + i3_msg('command', "workspace ${\($cur + 1)}"); + } +} +elsif ($dir eq $virtual_workspace) { + if (!defined $virtual_output || $virtual_output eq 'VIRTUAL1') { + i3_msg( + 'command', + "workspace $virtual_workspace; move workspace to output eDP1", + ); + } + else { + i3_msg( + 'command', + "workspace $virtual_workspace; move workspace to output VIRTUAL1", + ); + } +} +else { + die "unknown subcommand $dir"; +} + +sub find_workspace { + my ($tree, $num) = @_; + if (exists $tree->{num} && $tree->{num} == $num) { + return $tree; + } + for my $node (@{ $tree->{nodes} }) { + my $found = find_workspace($node, $num); + return $found if $found; + } + return; +} + +sub build_i3_msg { + my ($type, $payload) = @_; + + $payload = '' + unless $type eq 'command' || $type eq 'subscribe'; + + utf8::encode($payload); + + return 'i3-ipc' + . pack('LL', length($payload), $message_types{$type}) + . $payload; +} + +sub get_i3_msg { + my $bytes = $sock->read(my $header, 14); + die "invalid read" if $bytes != 14; + die "invalid format: $header" if substr($header, 0, 6) ne 'i3-ipc'; + my ($length, $type) = unpack('LL', substr($header, 6, 8)); + + if ($length) { + my $bytes = $sock->read(my $payload, $length); + die "invalid read" if $bytes != $length; + utf8::decode($payload); + return ($message_codes{$type}, $payload); + } + else { + return ($message_codes{$type}); + } +} + +sub i3_msg { + my ($type, $payload) = @_; + my $msg = build_i3_msg($type, $payload); + $sock->write($msg); + my ($got_type, $got_payload) = get_i3_msg(); + die "got $got_type message, expected $type message" + unless $type eq $got_type; + return $got_payload; +} diff --git a/i3/.bin/kill-focused b/i3/.bin/kill-focused new file mode 100755 index 0000000..37271ac --- /dev/null +++ b/i3/.bin/kill-focused @@ -0,0 +1,49 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use 5.014; + +use JSON::PP; + +my ($sig) = @ARGV; +my $pid = get_pid(); +my $pgrp = get_pgrp($pid); +kill $sig, -$pgrp; + +sub get_pid { + my $window_id = get_window_id(); + die "couldn't find window" unless defined $window_id; + my $prop = `xprop -id $window_id _NET_WM_PID`; + die "couldn't get pid from focused window" + if $prop =~ /not found/; + chomp($prop); + $prop =~ s/^_NET_WM_PID\(CARDINAL\) = //; + return $prop; +} + +sub get_pgrp { + my ($pid) = @_; + open my $stat_fh, '<', "/proc/$pid/stat" + or die "couldn't open /proc/$pid/stat"; + my $stat = do { local $/; <$stat_fh> }; + my @f = ($stat =~ /\([^)]*\)|[^ ]+/g); + return $f[4]; +} + +sub get_window_id { + return find(decode_json(`i3-msg -t get_tree`))->{window}; +} + +sub find { + my ($t) = @_; + if ($t->{focused}) { + return $t; + } + + for my $subtree (@{ $t->{nodes} }, @{ $t->{floating_nodes} }) { + my $found = find($subtree); + return $found if $found; + } + + return; +} diff --git a/i3/.config/i3/config b/i3/.config/i3/config new file mode 100644 index 0000000..afa6af1 --- /dev/null +++ b/i3/.config/i3/config @@ -0,0 +1,77 @@ +set $mod Mod4 + +default_border pixel 1 +hide_edge_borders smart +client.focused #aaaaaa #aaaaaa #ffffff #ffffff +client.focused_inactive #000000 #000000 #ffffff #888888 +client.unfocused #000000 #000000 #ffffff #888888 +client.urgent #ff0000 #ff0000 #ffffff #ff0000 + +floating_modifier $mod +floating_minimum_size 1 x 1 +floating_maximum_size -1 x -1 + +focus_wrapping no + +for_window [instance="Alacritty-tdrop"] floating enable +for_window [instance="Alacritty-tdrop"] sticky enable + +for_window [class="Steam"] floating enable +for_window [class="ArenaTracker"] floating enable + +for_window [title="zoom"] floating enable + +bindsym $mod+q kill + +bindsym $mod+h focus left +bindsym $mod+j focus down +bindsym $mod+k focus up +bindsym $mod+l focus right + +bindsym $mod+Shift+h move left +bindsym $mod+Shift+j move down +bindsym $mod+Shift+k move up +bindsym $mod+Shift+l move right + +bindsym $mod+f fullscreen + +bindsym $mod+Shift+space floating toggle +bindsym $mod+space focus mode_toggle + +bindsym $mod+bracketleft exec i3-switch-workspace prev +bindsym $mod+bracketright exec i3-switch-workspace next +bindsym $mod+v exec vscreen goto + +bindsym $mod+Shift+o exec "i3-msg 'append_layout .config/i3/terminal-workspace.json; exec env WINIT_X11_SCALE_FACTOR=1 alacritty; exec env WINIT_X11_SCALE_FACTOR=1 alacritty; exec env WINIT_X11_SCALE_FACTOR=1 alacritty; exec env WINIT_X11_SCALE_FACTOR=1 alacritty; exec env WINIT_X11_SCALE_FACTOR=1 alacritty'" + +bindsym $mod+1 workspace 1 +bindsym $mod+2 workspace 2 +bindsym $mod+3 workspace 3 +bindsym $mod+4 workspace 4 +bindsym $mod+5 workspace 5 +bindsym $mod+6 workspace 6 +bindsym $mod+7 workspace 7 +bindsym $mod+8 workspace 8 +bindsym $mod+9 workspace 9 + +bindsym $mod+Shift+1 move container to workspace 1 +bindsym $mod+Shift+2 move container to workspace 2 +bindsym $mod+Shift+3 move container to workspace 3 +bindsym $mod+Shift+4 move container to workspace 4 +bindsym $mod+Shift+5 move container to workspace 5 +bindsym $mod+Shift+6 move container to workspace 6 +bindsym $mod+Shift+7 move container to workspace 7 +bindsym $mod+Shift+8 move container to workspace 8 +bindsym $mod+Shift+9 move container to workspace 9 + +bindsym $mod+c reload +bindsym $mod+Shift+c restart +bindsym $mod+Shift+q exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" + +bar { + tray_output primary + status_command status + font xft:DejaVuSansMono 12 +} + +exec "i3-msg 'workspace 5'" diff --git a/i3/.config/i3/terminal-workspace.json b/i3/.config/i3/terminal-workspace.json new file mode 100644 index 0000000..d957bc1 --- /dev/null +++ b/i3/.config/i3/terminal-workspace.json @@ -0,0 +1,125 @@ +// vim:ts=4:sw=4:et +{ + // splitv split container with 3 children + "border": "pixel", + "floating": "auto_off", + "layout": "splitv", + "marks": [], + "percent": 0.337251851851852, + "type": "con", + "nodes": [ + { + "border": "pixel", + "current_border_width": 1, + "floating": "auto_off", + "geometry": { + "height": 340, + "width": 564, + "x": 0, + "y": 0 + }, + "marks": [], + "name": "main:0:zsh - \"doy@hornet:~/conf\"", + "percent": 0.333333333333333, + "swallows": [ + { + "instance": "^Alacritty$" + } + ], + "type": "con" + }, + { + "border": "pixel", + "current_border_width": 1, + "floating": "auto_off", + "geometry": { + "height": 340, + "width": 564, + "x": 0, + "y": 0 + }, + "marks": [], + "name": "work:0:zsh - \"doy@hornet:~\"", + "percent": 0.333333333333333, + "swallows": [ + { + "instance": "^Alacritty$" + } + ], + "type": "con" + }, + { + "border": "pixel", + "current_border_width": 1, + "floating": "auto_off", + "geometry": { + "height": 340, + "width": 564, + "x": 0, + "y": 0 + }, + "marks": [], + "name": "misc:0:mtr - \"doy@hornet:~\"", + "percent": 0.333333333333333, + "swallows": [ + { + "instance": "^Alacritty$" + } + ], + "type": "con" + } + ] +} + +{ + // splitv split container with 2 children + "border": "pixel", + "floating": "auto_off", + "layout": "splitv", + "marks": [], + "percent": 0.662748148148148, + "type": "con", + "nodes": [ + { + "border": "pixel", + "current_border_width": 1, + "floating": "auto_off", + "geometry": { + "height": 340, + "width": 564, + "x": 0, + "y": 0 + }, + "marks": [], + "name": "chat:0:vim - \"doy@hornet:~\"", + "percent": 0.5, + "swallows": [ + { + "instance": "^Alacritty$" + } + ], + "type": "con" + }, + { + "border": "pixel", + "current_border_width": 1, + "floating": "auto_off", + "geometry": { + "height": 340, + "width": 564, + "x": 0, + "y": 0 + }, + "marks": [], + "name": "docs:0:zsh - \"doy@hornet:~\"", + "percent": 0.5, + "swallows": [ + { + "instance": "^Alacritty$" + } + ], + "type": "con" + } + ] +} + |