A X11 holidays: Terminal Emulator, WM and Text Editor
Over the course of the year end holidays of 2024, I have fulfilled a long time dream of mine: writing my Terminal Emulator (sort of, and not finished yet) and own WM! Throwing in a 2 for 1 free offer is a toy Text Editor.
Here are the links:
- Terminal Emulator: https://github.com/ChanderG/vex (still WIP as of writing this)
- WM: https://github.com/ChanderG/cellwm (quite stable)
- Text Editor: https://github.com/ChanderG/te (just a toy)
I am using the first two of these, even as I type this, though the Terminal Emulator still has a long way to go.
1. The X11 Programming Wall
The barrier to this, for a long time, was understanding X11 Programming. I have been a long time user of DWM and st, and have patched these quite extensively and even blogged about this before here.
And yet, I didn't really understand the internals beyond being aware of the Tronche manual.
2. The Inciting Incidents
A few months back, in yet one of my endless side projects, I was looking for a minimal desktop UI framework. Lighter than GTK, and better than Tcl/Tk is what I was going for. I was initially only looking for Lisp bindings, but after a thorough search, the best option looked like Dear Imgui.
For a long time, I had an internalized preference for non-mainstream languages for such side projects. But the problem here is that using bindings in Common Lisp for example means you now have 2 problems: understand the original library enough to create/use bindings in another language where you have no documentation. So something clicked and I decided to bit the bullet: get back to C++ after a long time.
And surprisingly, I had a lot of fun! Dear Imgui is some good stuff. This gave me the idea that I should get into OpenGL programming in C++, with the aim of creating a Terminal Emulator. But again, I have 2 problems: learning OpenGL and going back to understanding how to implement a Terminal Emulator.
As it turned out, I side-stepped both the problems.
I knew of libvterm as an "easy" alternative to writing everything from scratch, but the barrier there was that I knew that there was zero documentation. Still, a lot better than the other option: get into reading 4000 lines of st. Since I just had the experience of going through the Dear Imgui header files, I had the momentum to do the same with libvterm.
Here, I started search for blogs on terminal emulators and got my other out: eduterm. Eduterm gave me on a platter the basic structure of the program: both the pts backend and a X11 frontend. That was my second escape hatch: with this base, I switched my target from OpenGL to X11.
3. Vex: The Terminal Emulator
Vex is not complete, there is still ways to go. But, here I list the main challenges and my approach. For a successful terminal emulator, we need three parts:
- The pts backed. This is the structure of how an emulator "talks" to the actual process, ususally the shell that you start. I go this for free from eduterm.
- The UI frontend. This is the UI that is responsible for reading and writing things from/to the screen. I go the main logic for this from eduterm again, but some more work was needed, as I will explain further.
- The actual Terminal emulator logic. This is the state management and processing of the various ANSI Escape codes ala VT100 and later. This is the heart of the Terminal Emulator. This, I outsourced to libvterm, with some effort from my side.
3.1. Challenge 1: libvterm
You know that libvterm is fantastic, if it can power emulators for Emacs(emacs-libvterm) and NeoVim, but how do you use it? There is basically 0 documentation about this libray online!
I did a bunch of source reading of emacs-libvterm and the libvterm header and pieced together of how the flow is supposed to work. Vex, when it will be more feature complete, will be the first demo of libvterm to exist. As of this blog, only the basic integration is done and I am working on finishing the rest. The Vex repo will have a diagram about using libvterm when I am done.
3.2. Challenge 2: The Looks
Basic eduterm's looks are not really usable. The problem is the font. The default X font mechanism restricts you to the built in, ugly looking, archaic to use font system. We want generic, pretty fonts!
Enter the Xft library. Understanding how to exactly use this library was the biggest challenge, one that I crossed through purely by reading, re-reading and reading again the relevant man pages. In a follow up blog post, I will detail the Xft API and how to use it, which became the basis of all three tools in this blog post.
4. Cellwm: The Window Manager
In the middle of the process of creating Vex, when I was stuck at some point, I came across this video https://www.youtube.com/watch?v=LelSKwXAdX0, where Steven creates a toy X11 window manager in a shockingly few number of lines.
Being a dwm user for around 10 years, I always thought that a WM would be 2-4k lines of C code project. This video unlocked my thinking: a WM in 100s of lines of code was a feasible. Since Vex was giving me a problem and I get distracted by side-projects quite easily, I took the chance to jump at this new project, applying my newly learnt X11 programming skills.
The result is CellWM: https://github.com/ChanderG/cellwm, my own Window Manager. I did all the testing on Xephyr and when I finally boot into it directly, I ran into a serious bug, where the WM crashed on opening/closing windows. Since I couldn't debug this error on Xephyr, I had a serious problem, where I pretty much gave up on the whole project.
After a week break, I faced the problem again, ripping out major chunks of the code and re-writing the WM from scratch pretty much, in a desparate attempt at figuring out the source of the bug. In the end, using valgrind
gave me an hint to finally isolate and fix this problem, allowing me to use CellWM as my main driver!
CellWM is far from complete, there are bugs which lead to the whole WM crashing randomly. Some of this I know the source of. I give it 3-6 months for the WM to stabilize, let's see.
5. Te: the Text Editor
In the time when I got stuck on the WM, in a bout of frustration, I started this project, to maximize my newly gained knowledge. It is a toy, complete, at this point with no further intention of development.
It is a demo which can found here: https://github.com/ChanderG/te.
6. Lessons
As 2025 begins, I have replaced two of my daily used key software pieces with my own implementation. I always intended for this at some point, but I didn't think it would come this soon. That does feel amazing.
Of course, the next few months of use and updates are crucical. Vex (the terminal) lacks a number of features I need to add incrementally. CellWM is feature complete, but is prone to bugs which can be problematic for a window manager. Let's see how it goes!