Skip to content

Instantly share code, notes, and snippets.

@DerBunman
Last active July 16, 2019 02:00
Show Gist options
  • Save DerBunman/2fe23d26d4a79bb4fe4cab1e243062ee to your computer and use it in GitHub Desktop.
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
#!/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