Window manager changed to i3: scratchpad tricks
Sticking to what seems to be my two-year window manager changing schedule, I switched again and ended up with i3. Xmonad was ok, performance- and feature-wise, but I didn't find the time to learn Haskell to be really able to configure it properly.
i3 has some properties I particularly like:
- The way it handles multi-monitor setups: Every workspace gets assigned to an output; switching to a workspace on another output opens the workspace there and warps the focus to that output.
- Layouting is so much more flexible, though I still somewhat miss my Super+Return "swap the current window with the big one" of Xmonad.
- The scratchpad: a place to send a window where it can easily be recalled as a popup to the desktop. To be fair, it should be possible to implement the same thing with Xmonad or awesome, but here, it's usable without learning a whole language.
I use the scratchpad as a more powerful replacement for dmenu_run, which under high IO load can take long time to fire up: I keep a terminal with tmux ready at the scratchpad, which is configured to hide itself again as soon as a command is executed, and to spawn another tmux window to be ready for the next input.
Usability-wise, it's like running dmenu or gmrun (which I used some time ago): You press Super-p, a window shows up, you enter your command, press Return, the window vanishes and the command gets executed. In addition, it offers
- a real shell, with all its tab completion powers, aliases etc., and
- a way to recover started processes' stdout/err data, even if they crash (the windows are kept around for some minutes).
The code for that is pretty short, and most of it is to cover corner cases. This file is ~/.config/i3/scratchpad/perpetual_terminal.sh and is best executed from i3 under a flock guard:
(download)
#!/bin/sh
run_inside="'ZDOTDIR=${HOME}/.config/i3/scratchpad zsh'"
while true; do
# not using urxvtc here, as we're relying on the process to run
# until either
#
# * it gets detached (eg by ^Ad)
# * it terminates (because someone killed all windows)
#
# in any case, we try to reattach to the session, or, if that fails,
# create a new one.
urxvt -name scratchpad -e sh -c "tmux attach -t scratchpad || tmux new-session -s scratchpad $run_inside ';' set-option -t scratchpad default-command $run_inside"
done
And this file, ~/.config/i3/scratchpad/.zshrc, configures the shell that gets executed:
(download)
source ~/.zshrc
# reset again what was set outside
export ZDOTDIR=${HOME}
PS1="(scratchpad)$PS1"
preexec() {
i3-msg '[instance="^scratchpad$"]' move scratchpad
tmux new-window
precmd() {
echo "=============================="
echo "exited with $?"
exec sleep 10m
}
}
zshexit() {
# user pressed ^D or window got killed, will not be executed when the
# shell gets "killed" by the final exec in the regular workflow
i3-msg '[instance="^scratchpad$"]' move scratchpad
tmux new-window
}
TRAPHUP() {
# when the window gets killed, just die
zshexit() {}
}
To activate this from i3, the following lines are placed in the i3 config:
bindsym $mod+p [instance="^scratchpad$"] scratchpad show exec_always flock -w1 ~/.config/i3/scratchpad/lockfile ~/.config/i3/scratchpad/perpetual_terminal.sh for_window [instance="^scratchpad$"] move scratchpad
All of the above requires zsh, tmux and urxvt to be installed, zsh to be configure as login shell and possibly other things I might have forgotten (please let me know if you have trouble reproducing this setup).
Other i3 features that look good and I plan to discover:
- Easy to use modes -- maybe I'll revive my key combos of old (Super+Space, g, P for "games / pioneers server", Super+Space, Print, u for "take a screenshot, upload it to my server and put the URL into my clipboard" etc.
- VIM-like marks
An issue I yet have to find a solution for is the status bar: I want nice graphs of CPU usage etc, so the tiling window manager typical solutions like dzen2 or i3's i3status/i3bar won't do the trick. I'm using conky for the moment, but I still need i3bar because it has a realtime display of the active workspace and of urgency notifications. Ideally, I'd want i3bar to provide an X window to conky where it can draw, but for the moment, I'm keeping a single statusline worth of visual information in two distinct panels.