My i3 window manager setup
over 5 years ago
I have been a long time i3 window manager user. But not really.
My old Windows 10 based setup involved doing all my console work in an Ubuntu VM running i3. However, the lion’s share of the non console work was still done in Windows, including browsing and more.
For multiple years now I only partially experienced i3, it showed. My i3 setup was almost vanilla.
My move to Arch Linux changed everything.
This move completely shifted the way I think about my relationship with my desktop environment. Previously, my relationship with Windows was very simplistic. Windows works the way it works, I simply adapted to that. Sometimes I learned a new shortcut, but the majority of my Windows day-to-day involved dragging windows around, reaching Firefox window and tab saturation, closing windows with the mouse and so on.
I am not a great example of a Windows ninja some users go down a far more custom path. I do feel I am pretty typical though of a developer using Windows or Mac. I was given a menu, I learned a tiny bit of it, then I simply threw away the menu and reached for the mouse.
In this blog post I would like to talk about what my 3.5 week adventure has looked like and where I am today!
Opening moves
When I moved to Linux I did not know much of the current state of Linux on the desktop but I did know 2 things:
- I would be using Arch Linux
- I would be using the i3 tiling window manager
I opted for Arch cause I love not having to worry about upgrading my system every 6-12 months to another major release, I think pacman and the package library on Arch is amazing, if I ever am missing tiny bits from the official library it is trivial for me to just grab a package from the very comprehensive AUR. I also think the documentation in the Arch wiki is fantastic and it helped me enormously.
I opted for i3 cause I wanted to fully experience the window manager, not treat it as a glorified tmux like I was for years.
A day or so into my move I was uncomfortable with the way my stock install looked and acted, I quickly learned about the r/unixporn reddit and this movement called “Ricing”.
During the first few days I watched a fair bit of youtube to see what others are doing.
I can recommend:
- The 3 part series by code cast on i3. Especially the last one.
- Ethan Schoonover excellent xmonad demo - If you have not seen this yet I recommend you stop reading and go watch it.
- Aline Abler course on tiling window managers
My basic ricing
I totally get that lots of people love dmenu people get it to do all sorts of amazing things like mount drives, select monitors and pick files. It is a very powerful and in true suckless fashion minimal tool.
I opted to swap out my dmenu with rofi which I seem to like a bit more. It looks like this:
I prefer the positioning and really like the combi menu that allows me to also navigate through my open windows. rofi works in a dmenu mode as well so I can just use it interchangeably.
I also used LXApperance for some very rudimentary themeing in particular I do like the Apple San Fransico font that I use for my window titles:
I also set up a basic gruvbox theme for my urxvt terminal and was careful to grab the fork with 24 bit color support so everything looks just right. Initially I tried out terminator but find urxvt a bit “lighter” that said, I may try out st next.
Finally I swapped out i3status with i3status-rust. It shows me weather, volume, network and cpu speed and pending update count. I really enjoy it.
My ricing is very basic, I don’t like wallpapers, I don’t like transparency and am unsure if I would even like to try gaps or not.
A tiny note on mod keys
A large amount of i3 configuration relies on using a mod
key. The mod
key is mapped by end users to an appropriate key that does not get in the way with other keyboard bindings other programs use.
In my case I map mod
to both the Windows
key and the right Menu
key. I do the menu key mapping by running exec_always --no-startup-id xmodmap -e "keysym Menu = Super_R"
in my config file.
The tool I used for displaying keys on this blog post (the amazing screenkey) calls the Windows key Super
which is the Linuxey name. I can rename it to mod, but I am already multiple screenshots in.
For the purpose of this blog post. Mod
== Super
== Windows Keyboard key
. I will be calling this key Super
from here downwards.
Easy editing of Discourse
When I moved to i3 proper I set myself the goal to eliminate trivialities. I observed things that I kept on doing inefficiently and optimized my setup.
I found that in the past every time I wanted to hack on Discourse I would
- Open a terminal
cd Source/discourse
- open nvim
- split the window
- open nerdtree
This flow involved lots of steps which can easily be automated:
I now hit Super
+ Shift
+ D
and tada Discourse opens.
This is done by adding this to my i3 config:
bindsym $mod+Shift+d exec "i3-sensible-terminal -e '/home/sam/.i3/edit_discourse'"
And this tiny shell script
sam@arch .i3 % cat edit_discourse
#!/bin/zsh
cd /home/sam/Source/discourse
exec nvim -c ':NERDTree|:wincmd w|:vsplit'
Smart window centering
Even though i3 is a “tiled” window manager. Some windows… I prefer in floating mode. In particular I like having Firefox in floating mode.
I like having Firefox in the middle of my center monitor at very particular dimensions. I do sometimes drag it around but it is nice to “reset” the position.
Sometimes I like it a bit wider, so I hit Super
+ c
again.
And sometimes I like it a tiny bit wider, so I hit Super+c
again.
If I hit Super
+ c
yet again it is back to square one and window is small centered.
I achieve this by having this in my i3 file.
bindsym $mod+c exec "/home/sam/.i3/i3-plus smart_center 1830x2100,2030x2100,2230x2100"
The little i3-plus
utility is a work-in-progress Ruby utility I have that interacts with the i3 IPC so it can make smart decisions about what to do. You can find the source for it in my dotfiles.
The basic logic being:
This config also allows me to quickly zoom a tiled panel to the middle of the screen, size it right and once I am done with focused work I can ship it back to the tile with Super
+Shift
+Enter
Easy terminal arrangement
One issue I had with i3 for quite a while was needing to remember to flip the way I split windows in tiling mode. I would hit Super
+Enter
to open a terminal, then hit it again and open a terminal to the right.
And then I hit a problem.
My brain simply did not consistently remember if I had to hit Super
+v
for a vertical split or Super
+ h
for a horizontal split. Is splitting vertically splitting the vertical window in half or is splitting horizontally splitting tall window at the horizon.
Clearly, I could work around my brain glitch by using a different shortcut that was easier for me to associate. Or just tough it up and train myself properly. But what I observed here is that I was just repeating a pointless task.
I like my tiled windows arranged “just so” and in a specific order. i3 by design is not a “just so” tiler, all tiling is manual not automatic like xmonad and dwm. This is an explicit design goal of the project.
Michael Stapelberg explains:
Actually, now that I think of it, what you describe is how automatic tiling WMs work (like DWM, awesome, etc.). If you really need that, you might be better off using one of these. i3 is (and will stay) a manual tiling WM.
That said… this is my Window Manager, and I can make it do what I want. Unlike my life in Windows and Mac, when I dislike a behavior I can amend it. I am encouraged to amend it. i3 will not merge in dynamic tiling which is a way they manage bloat and complexity, but I can have a bodged up dynamic tiling system that works for my workflows with i3.
So, I have this standard behavior:
Followed by this … non standard behavior. (notice how I never had to hit Super+v
What more it gets better cause then next Super+enter
switches panels, no matter what terminal I am on.
My system is somewhat glitchy, I have only been doing this for a few weeks, but it scratches my itch big time.
As an added bonus I made it so when I am on my right most monitor I start tiling vertically in the left column instead of right.
My work in progress code to make this happen is at my i3-plus file in my dotfiles.
At the moment layout is hardcoded and I simply run:
bindsym $mod+Return exec /home/sam/.i3/i3-plus layout_exec i3-sensible-terminal
Tweaks to multi monitor focus
I tend to keep a floating window around on my left monitor for chat. I found that I tended to get trapped on my left monitor after hitting Super + Left
. i3 has a behavior where it cycles between floating windows on a monitor. This got in the way of my workflows.
After raising raising this at GitHub airblader fairly concluded that this is a minor annoyance with a clear workaround but was worried about adding any more complexity to focus behavior. This is fair.
But… this is my Window Manager and I get to call the shots on my computer.
So now my focus never gets trapped on a monitor. My Super + Right
key works the way I want it to.
Tweaks to move
Out-of-the-box i3s example file binds Super + Shift + Right/Left
to the i3 command move
.
What this does is:
- In tiled mode moves the tile to left or right
- In floating mode moves the window a few pixels to the left or right.
The behavior in tiled mode worked for me, but I found that I am not really into positioning floating windows using arrows and instead find it far more useful to “throw” a floated window to the right or left monitor.
From what I can tell (and I may be wrong) I could not find a way to tell i3 to run a certain command in floating mode and another in tiled mode. However using the ipc interface this was trivial:
def move(dir)
if is_floating?
@i3.command("mark _last")
@i3.command("move to output #{dir}")
@i3.command('[con_mark="_last"] focus')
else
@i3.command("move #{dir}")
end
end
A keyboard friendly exit
The i3 sample config spins up a nagbar prior to attempting to exit the windows manager. I found the position of this nagbar not ideal and did not like that I needed to reach for the mouse. I am not alone here but this is really only a common problem when you are heavily tweaking stuff.
That said I came across this wonderful idea somewhere, which I would love to share:
mode "exit: [l]ogout, [r]eboot, [s]hutdown" {
bindsym l exec i3-msg exit
bindsym r exec systemctl reboot
bindsym s exec systemctl shutdown
bindsym Escape mode "default"
bindsym Return mode "default"
}
bindsym $mod+x mode "exit: [l]ogout, [r]eboot, [s]hutdown"
I now use Super + x
to enter my “exit i3 mode”, which gives me all the goodies I need with a nice UX.
I love screenshots
During my day I tend to take a lot of screenshots. I always struggled with this for a degree. I never had the “right” tool for the job in my Windows days. Now I do.
I set up my screenshot hotkeys as:
-
PrtScn
: take a screenshot of a selection -
Super + PrtScn
: take a 3 second delayed screenshot of a selection -
Super + Shift + PrtScn
: take a screenshot of the current desktop + pass it through pngquant and add to clipboard.
(1) in the list here was really easy. I used the flameshot tool and simply bound prtscn to it:
exec --no-startup-id flameshot
bindsym Print exec "flameshot gui"
It works a treat. Highly recommend.
Delayed screenshots (2) is where stuff got tricky.
Flameshot has a delay option, even if it did not it is trivial to exec sleep 2 && flameshot gui
. However, I like having a visible reminder on the screen that this thing will happen:
To implement this I adapted the countdown script from Jacob Vlijm
In i3 I have:
bindsym $mod+Print exec "/bin/bash -c '/home/sam/.i3/countdown 3 && sleep 0.2 && flameshot gui'"
Full screen screenshots (3), like the ones further up this blog post was a bit tricky.
Xwindows screenshot tools like treating all my 3 4k screens as one big panel, not too many tools out there can figure out current focused monitor let alone split up the enormous image.
To achieve this I rolled my own script that uses the i3 IPC to figure out what display has focus and then tells ImageMagick to capture and crop correctly and finally passes throw pngquant and back on to the clipboard in a web past friendly format using CopyQ.
This simple binding then takes care of it for me.
bindsym $mod+Shift+Print exec "/home/sam/.i3/i3-plus screenshot"
Scratchpad
i3 has a special desktop that is not visible called “the scratchpad”. If you want to get rid of a window temporarily you can always just ship it there and recall it from there. I like to use it for a couple of things.
-
I bind
Super + b
to toggle my browser in and out of the scratchpad. No matter which monitor I am on I can summon my browser with this hotkey (and make it go away) -
I bind
Super + p
to toggle a dedicated terminal. I like to use this dedicated terminal to run stuff likepacman -Syu
that can take a bit, look at a calendar, run a quick calculation and so on. -
Similar to both above I like
Super + y
to bring up my yubico authenticator. (I highly recommend a Yubikey for devs it is a big time saver)
# terminal that pops up on demand
exec urxvt -name scratch-term
for_window [instance="scratch-term"] floating enable, move to scratchpad
bindsym $mod+p [instance="scratch-term"] scratchpad show
exec firefox
for_window [class="Firefox"] floating enable, move to scratchpad, scratchpad show
bindsym $mod+b [class="Firefox"] scratchpad show
exec yubioath-desktop
for_window [class="Yubico Authenticator"] floating enable, move to scratchpad
bindsym $mod+y [class="Yubico Authenticator"] scratchpad show
Other bits and pieces
My current .xinitrc looks like this:
eval $(dbus-launch -sh-syntax --exit-with-session)
dbus-update-activation-environment --systemd DISPLAY
xrdb -merge ~/.Xresources
xrandr --output DVI-D-0 --off --output HDMI-1 --off --output HDMI-0 --mode 3840x2160 --pos 0x0 --rotate normal --output DP-3 --off --output DP-2 --primary --mode 3840x2160 --pos 3840x0 --rotate normal --output DP-1 --off --output DP-0 --mode 3840x2160 --pos 7680x0 --rotate normal
eval $(/usr/bin/gnome-keyring-daemon --start --components=gpg,pkcs11,secrets,ssh)
export GNOME_KEYRING_CONTROL GNOME_KEYRING_PID GPG_AGENT_INFO SSH_AUTH_SOCK
exec i3
I am not a fan of using Gnome Display Manager as I feel it introduces more complexity into my setup. Instead, I just run startx
after logging in.
The two trips here is that I needed a dbus session so gnome type apps work (like skype for example) and needed to spin up my keyring (which skype needed as well)
Do I actually get any work done?
The i3 sample config file has a wonderful comment at the top.
# This file has been auto-generated by i3-config-wizard(1).
# It will not be overwritten, so edit it as you like.
My i3 setup is my setup. It is tailored for my use cases.
I love that i3 has a single config file, it is very easy to reason about my current desktop environment. If I don’t ever use a shortcut I can remove it. If I need a new shortcut I can add it. If I forget what is “on the menu” I can read the reasonably small file to figure out!
All of this tweaking does sound like it could be a full time job for multiple weeks but it really was not at all. I hit barriers in my workflow, unblocked them and then moved on. Each barrier I removed made me more efficient.
The end result has been that I can now jump on a problem and solve it with significantly more focus. My window manager is working for me, I am no longer its slave.
In my previous blog post I talked about leaving Windows. The catalyst was performance. What I did not know was what a wonderful experience I would have in my new Linux home.
Sure, I have the usual niggles of needing to run a compositor fight with Nvidia drivers and deal with finding Linux alternatives for Windows tools I was used to using. However, on a fundamental level I am just so much happier now. I feel like I relinquished control over my computer for too long.
What you can do?
If you wish to do a Linux experiment you can choose the hard mode or the easy mode, there are plenty of alternatives out there. If you want to try out tiling, you can even just pick up Manjaro which has an i3 distribution or Regolith Linux.
As a programmer in any terminal dominated technology stack (like Ruby/Rust/Golang and so on) I strongly recommend trying out a tiling window manager.
From all my research i3 is the perfect first choice for trying out a tiling window manager, it comes with very sane and complete defaults, the config file is very easy to reason about and it works great!
If you have any questions or would like any tips feel free to post here and I will reply, but be warned, I am no expert I am just learning.
Big thank you to Michael Stapelberg for creating i3, and the very active community (Airblader, Orestis and others) for maintaining i3. Big thank you to all you people putting excellent content out there and making my ride into the Linux world easy.
For anyone stuck on Macos for work reasons, skhd + chunkwm can replicate a lot of i3 functionality with some effort.
i3 is truly the best possible wm for serious developers though.