Tiling window manager
A couple of months ago it occurred to me that I’ve been manually tiling my windows. That is, I use all the screen real estate, and don’t have windows overlapping each other.
In various window manages (and on Windows) I have used Super+Left and Super+Right to divide the screen 50/50.
So why am I not running a tiling window manager? That’s literally what they do, and they allow more flexibility in how to tile, without wasting space.
Switching to tiling
A quick googling says that i3 is what I want. Fast, small, efficient. No bells and whistles.
I used it for a little while, but then because I wanted to make it even harder on myself, err… I mean to join the 21st century, I thought I’d switch from X11 to Wayland, too. Luckily there’s a Wayland Compositor that’s equilavent to the i3 Window Manager called Sway.
It’s great! I knew X11 and Gnome had issues, but I didn’t realize just how much better I feel when I don’t have to deal with their deficiencies.
Like:
- screen tearing when scrolling in terminal windows
- changing focus can take up to a second, sometimes
- X11 resets keyboard settings when it bloody feels like it, in addition to every single time you plug/unplug a keyboard
Wayland’s not been entirely smooth sailing though:
- My custom keys don’t work in XWayland (I believe this is fixed in a newer version of Sway)
- And they don’t paste properly in Chrome on Wayland
- And some don’t work on Chrome on Wayland at all
- It’s not entirely obvious how to move windows around to have a perfect layout. It works logically with a container tree, but that container tree is not actually visible on screen. Identical layouts can have multiple layouts. They say this gets better with experience.
- Mouse horizontal scroll wheel was inverted under Wayland. Fixed in Chrome 89.
Terminals
Now that the biggest issues with performance were gone, it became more
noticeable that gnome-terminal
is pretty slow too. Reading my email
in my text client I noticed that merely scrolling through an
email could take 45% CPU on a modern machine. That’s ridiculous, even
if it’s a full height window on a 4k monitor, thus many pixels.
At first I thought it was due to my email client not being efficient at rendering. After all, it redraws the whole text buffer from scratch when you scroll. So I implemented scrolling using terminal escape codes.
Curiously that didn’t help at all. Oh well, at least it improves screen tearing on X11, and reduces network use when run through SSH.
I got a recommendation to use the terminal foot
. Terrible
name. But in the spirit of i3 and Sway (and being native Wayland), it
looked pretty neat. And yes, much faster.
I had to adjust the colors. The default ones were very muted.
One mayor drawback though is that it does not support tabs. But Sway does support tabs for windows, so why do I need tabs both in the WM (ehem, compositor) and in the terminal?
After trying it as-is, it turns out that I really want to be able to cycle through the tabs inside the same “visual space”, and moving to another window is something else to me entirely. Similar to how when I move away from the browser window, I move away from all the browser tabs, but moving between browser tabs is a completely different conceptual thing.
What I want shortcuts for:
- “if focus is inside a tabbed container, go out of that tabbed container and to the left” (or up, down, right, whatever)
- “go to the next tab. If it’s the last tab, cycle back to the first one”
- “jump directly to tab number N”
Neither foot
nor Sway support this. But Sway supports dumping a JSON
representation of the layout, and it supports sending navigation
commands.
So I made a shell script that takes the JSON layout, locates the currently focused window, and does what I want.
I felt kinda icky having Sway execute my script, which in turn does
three more exec()
calls (and all the other syscalls to fork()
and
shuffle data between them), just to “focus next window”. Running the
script took about 50ms, too. Not really a problem, but could be
noticeable on a loaded system with many more windows.
So I rewrote it in
C++,
using simdjson. Turns out the JSON parsing and querying of
jq
was the biggest time thief. But now it’s down to being so fast
time
often claims it’s 0.000s
of CPU time.
Possibly the jq
query
could be optimized, but I wanted to not even waste time loading four
binaries (swaymsg, bash, jq, and swaymsg again) to select the next
window. I don’t even particularly like the one exec()
call.
And now I can configure moving around the way I want it.
And if I have other fancy nav things I want to do I have the library to get started.
In conclusion
I highly recommend tiling window managers, and i3 and Sway in particular. I run Sway both on my laptop and on my dual monitor desktop. Sway also handles unplugging/replugging the extra monitor much better, where Gnome just left a horrible mess.
And I recommend simdjson for all your JSON parsing needs. It’s really fast, and a nice modern C++ API.