Last active
July 16, 2019 02:00
-
-
Save DerBunman/2fe23d26d4a79bb4fe4cab1e243062ee to your computer and use it in GitHub Desktop.
start './i3winsplit.zsh xbindkeys" then cut windows like a man with right mouse and ctrl and a cutting motion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env zsh | |
# terminal to launch when splitting | |
# undefined window class. | |
# first choice urxvt fallback xterm. | |
terminal="${commands[urxvt]:-xterm}" | |
typeset -a allowed_actions=( | |
xbindkeys | |
start | |
end | |
) | |
if [ ${allowed_actions[(I)$1]} -le 0 ]; then | |
cat <<-EOF | |
i3winsplit.zsh | |
============== | |
Your scientists were so preoccupied with whether or not they could, | |
they didn’t stop to think if they should. - Jurassic Park | |
Updates: | |
======== | |
https://gist.github.com/DerBunman/2fe23d26d4a79bb4fe4cab1e243062ee/ | |
About: | |
====== | |
A tool which enables you to cut thru your i3 windows to split them. | |
Whatever the reason you feel like you need to do it. I feel you. | |
When I first had this idea it was a gamechanger for migrating back | |
from keyboard centric user input to a more mouse oriented approach. | |
While I soon realized that none of this made sense, I somehow wanted | |
to see and feel how this would work. | |
So well. Behold its glory: https://streamable.com/016h2 | |
Known problems: | |
=============== | |
* Sometimes i3 will reply with this message and split the window in the middle: | |
"ERROR: Failed to find appropriate tiling containers for resize operation" | |
* Some applications don't want to be resized. vim-gtk3 for example just resizes | |
never like it should, but sometimes it resizes some more windows while itd at it. | |
* However, I don't plan to use this script, so I didn't investigate any of these | |
issues. | |
Dependencies: | |
============= | |
The following binaries have to be in your path: | |
- xbindkeys | |
- xdotool | |
- i3-msg | |
- zsh (tested with 5.5.1, but should work with >=5.4.2) | |
- tee | |
- urxvt or xterm | |
- notify-send (optional. else output will only appear on stdout) | |
And, i3 has to be running with a few windows to tear down. | |
Allowed actions: | |
================ | |
- xbindkeys: | |
Starts the xbindkeys service which binds control + mouse button 3 (rmc) | |
to the start and end trigger. This is the only action you should call. | |
The other actions are said start and end trigger which will be called on | |
control+mouse button 3 (rmc) trgger (start) and release (end). | |
So, this is the command you should run: | |
======================================= | |
${0} xbindkeys | |
EOF | |
exit 1 | |
elif [ "$1" = "xbindkeys" ]; then | |
xbindkeys --verbose --nodaemon --file <(<<-EOF | |
"$0 start" | |
control + b:3 | |
"$0 end" | |
release+control + b:3 | |
EOF | |
) | |
exit | |
elif [ "$1" = "start" ]; then | |
xdotool getmouselocation >~/.i3winsplit.tmp | |
exit | |
fi | |
# use notify-send when in path` | |
NOTIFY_SEND="${commands[notify-send]:-cat}" | |
# $1 = end | |
setopt SH_WORD_SPLIT | |
typeset -A after=( ${$(xdotool getmouselocation)//:/ } ) | |
typeset -A before=( ${$(<~/.i3winsplit.tmp)//:/ } ) | |
# which command to send i3 | |
# depending on cut direction. | |
typeset -A splitcmd=( | |
x "split v" | |
y "split h" | |
) | |
# everything not defined here will spawn | |
# a new $TERM instance instead | |
typeset -A class_cmds=( | |
# gvim doesn't like to be split | |
# gvim "gvim" | |
urxvt "urxvtcd" | |
firefox "xdotool key --window ${before[window]} control+n" | |
) | |
{ # The following block will be sent to stdout and when in path notify-send | |
# abort when the mouse motion crossed more than one window | |
[ $after[window] -ne $before[window] ] && { | |
echo "[ $after[window] -ne $before[window] ]" | |
echo "ERROR: window ids are different." | |
exit | |
} | |
zmodload zsh/mathfunc | |
typeset -A diff | |
diff[x]=$(( $before[x] - $after[x] )) | |
diff[x_abs]=$(( sqrt($diff[x] * $diff[x]) )) | |
diff[y]=$(( $before[y] - $after[y] )) | |
diff[y_abs]=$(( sqrt($diff[y] * $diff[y]) )) | |
(( $diff[x_abs] > $diff[y_abs] )) \ | |
&& direction="x" \ | |
|| direction="y" | |
class=${(@)${$(xprop -id ${before[window]} WM_CLASS)}[4]//'"'/} | |
echo direction $splitcmd[$direction] | |
[ $direction = x ] \ | |
&& { axis=y; size=XWSHEIGHT } \ | |
|| { axis=x; size=XWSWIDTH } | |
offset_screen=$(( ( $before[$axis] + $after[$axis] ) /2 )) | |
eval $(xdotool getwindowgeometry --prefix XWS --shell $before[window]) | |
offset=$(( $offset_screen - ${(P)$(echo "XWS${axis:u}")} )) | |
# remaining percent of the window | |
# echo "PERC $(( $offset.0 / ${(P)size} *100 ))" | |
xdotool windowactivate $before[window] | |
i3-msg "${splitcmd[$direction]}"; sleep .5 | |
eval "${class_cmds[$class:l]:-$terminal}" &| | |
xdotool search --onlyvisible --pid $! | |
[ "${class:l}" = "firefox" ] && sleep .5 | |
xdotool windowactivate $before[window] | |
[ $direction = x ] \ | |
&& i3-msg "resize set height $offset px" \ | |
|| i3-msg "resize set width $offset px" | |
} 2>&1 | tee >("$NOTIFY_SEND" "$(cat -)") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment