plwm: An X11 window manager written in Prolog
39 points by classichasclass
39 points by classichasclass
Thank you for sharing this!
I have been meaning to publish some lists I have been compiling of “short” (usu. ≤1000) examples of programmes that most programmers could not write off the top of their head. Most of these are programmes which are both fundamental but seem very daunting to write. I think I could write a simple line-orientated grep
off the top of my head, but I don’t know where to start (or how much effort and research is needed) to write a window manager or a terminal multiplexer.
However, if I have a few examples of very simple implementations of such programmes, if such programmes are complete (even if lacking in features) such that I can build them and make small tweaks, if they are written in a language I can squint by way through, and if the code is short enough for me to read in the course of a lazy afternoon, the barrier is eliminated.
For an X11 window manager, we might expect interaction with Xcb or similar underlying APIs might add a lot of boilerplate to the code; thus, we may relax our burden from ≤1000 to ≤10000 lines of code. plwm
is toward the upper end of this.
Project & Code: Total Lines of Code† with Breakdown (indicating dominant language)
ansic
: 47 (97.92%)ansic
: 82 (75.23%)python
: 275 (100%)ansic
: 359 (100.00%)ansic
: 543 (100.00%)ansic
: 2535 (100.00%)ansic
: 2531 (93.74%)ansic
: 2780 (100.00%)ansic
: 2918 (100.00%)ansic
: 3096 (100.00%)perl
: 3268 (100%)cpp
: 3466 (100.00%)ansic
: 3657 (100.00%)ansic
: 3895 (86.25%)cpp
: 5280 (100.00%)prolog
‡: 4087 (74.40%); ansic
: 1278 (23.27%)ansic
: 5710 (90.03%)ansic
: 6371 (94.95%)ansic
: 8167 (99.98%)python
: 8281 (88.51%)† “Total Physical Lines of Code” and “Grouped by Language” as reported by David A. Wheeler’s sloccount
‡ Incorrectly reported as perl
, likely based on .pl
extension; there may be other mistakes than this.
⹋ Added based on other comments: ~mhd
…but I don’t know where to start (or how much effort and research is needed) to write a window manager or a terminal multiplexer.
Because you don’t know the API’s involved, that’s all. For good reason; they’re not very nice API’s.
Because you don’t know the API’s involved, that’s all.
I don’t think that’s all. I also don’t know the APIs for Parsimonious a PEG-grammar toolkit for Python, and it has been some time since I’ve studied context-free grammars, but I was able to cobble together an extremely rough starting point for parsing Djot the other week.
For that problem, my greater confidence came from knowing what I knew and also knowing what I didn’t know, as well as being able to situate the various pieces of my fractured knowledge into a larger conceptual model. This last part was key, because it meant that I could rely on things that I did know (e.g., basic regular expressions and simple, line-by-line, imperative string manipulation) to make strategic simplifications (i.e., to “cut corners”) without weakening the whole of my approach.
In fact, if you had put me in front of an audience during this exercise, I suspect I could have live-coded a working example (of very rough quality) in one continuous motion.
However, in the case of a Window Manager, I’m not sure I could do this without a substantial amount of prior research, reviewing examples like those I have collected. Yes, in the end, it’s just a bunch of C code making a bunch of function calls, but it’s not the kind of problem for which I already have (even a piecemeal) holistic understanding. Thus, by reviewing and retracing the steps of very simple examples, I can develop such an understanding such that, at some later point, I may be able to live-code a window manager in real-time.
For good reason; they’re not very nice API’s.
This is an interesting comment, and I have seen similar complaints, but my understanding is that much of the difficulty of frameworks such as Xlib was that they tried to paper over the fundamentally asynchronous nature of the X11 protocol. As I understand it, Xcb is actually quite straightforward to use.
That some of the examples of small Window Managers are well under 1000 lines of code suggests that while the APIs may have fundamental design flaws, getting them to do something useful is quite achievable. Similarly, a very full-featured Window Manager like qtile has only about 6,000 lines of code in their backend/X11 which uses an FFI wrapper around XCB. How bad can it really be?
This is an interesting comment, and I have seen similar complaints, but my understanding is that much of the difficulty of frameworks such as Xlib was that they tried to paper over the fundamentally asynchronous nature of the X11 protocol
These complaints are really overblown - the biggest part where the api makes things hard are a few (not that many!) functions where it waits for the reply before returning, so you have to be careful with those for speed but you get easy error messages, and then the others where error messages reference a “Sequence number” but that’s somewhat opaque to you… like you can keep track if you want but the error messages also include the failed command so that often is enough to tie it back anyway.
The bigger question is WHY it failed and that can be obscure sometimes since there’s required setup steps and such but… well that’s programming sometimes. Once you get to know it, the steps all make sense.
With most gui programs, the bulk of the code is in handling all the various possible little user interactions.
…my greater confidence came from knowing what I knew and also knowing what I didn’t know, as well as being able to situate the various pieces of my fractured knowledge into a larger conceptual model.
I mean… some of this is experience and context (which is kinda what I was referring to earlier), and some of it is a symptom of those API’s being bad. A windowing system at its core is an event loop, some drawing/GPU stuff, and an API for programs to talk to the windowing system and each other. Now that you know that does it sound more attainable?
my understanding is that much of the difficulty of frameworks such as Xlib was that they tried to paper over the fundamentally asynchronous nature of the X11 protocol.
That’s an interesting comment too; I hadn’t heard that. I don’t know as much about X11 as Wayland, and I don’t know much about Wayland, but my impression is that X11 makes simple things pretty simple, and makes less-simple things nigh impossible. The 6000-line WM’s do the simple things just fine, and good luck with something like hotplugging a monitor or making the three different clipboards play nice together.
How bad can it really be? Again I haven’t written much X11 code for real but it reminds me of OpenGL, another infamously bad API. Drawing a mesh on the screen is 150 lines of code in OpenGL and 1500 lines of code in Vulkan. Making a performant and modern rendering engine is like 15,000 lines of code in OpenGL and 5000 lines of code in Vulkan, and the OpenGL one will be full of nasty little edge-cases where things break.
good luck with something like hotplugging a monitor or making the three different clipboards play nice together.
These aren’t really the responsibility of the window manager, but they’re also not hard to do at all - you get an event saying the monitors have changed or another program is claiming the clipboard, and you respond to them. Not really any different than anything else.
I am still compiling this and my other lists, so I welcome additions or leads.
I plan to create Arch AUR packages and OCI containers for each of these, so that they can be easily installed. The goal would be for someone curious about writing their own window manager to exhaustively read through a few of the very short examples, then pick out a few of the medium-length examples to tweak as they develop their understanding, then refer to a few of the longer-length (i.e., likely more complete) examples when trying to figure out how to handle tricky corner cases.
Personally, I have great interest in writing my own Window Manager, in part because I have convinced myself that II need to adopt an infinite-scrolling, code-based-configuration tiling WM to replace the use of my current non-scrolling, (Lua) code-based configuration, tiling WM (AwesomeWM.)
I was quite interested in Qtile, since it has both X11 and Wayland backends and is written in Python which I know quite well, but I ran across enough odd choices in their use of Python that I figure I might as well try writing my own tool. Qtile is quite rich in features—I have a colleague who switched to it some time back—and it’s only about 50k or so lines of (kind of bizarre) Python code (excl. tests,) so I figure this may more achievable than one might otherwise assume.
I am still compiling this and my other lists, so I welcome additions or leads.
i don’t see fvwm there … why oh why ? it has been my daily driver for quite a while (≥ 2.5 decades) now, and i haven’t found anything even close, and yes, i have looked.
github: https://github.com/fvwmorg/fvwm3
interwebs: https://www.fvwm.org/
I was quite interested in Qtile, since it has both X11 and Wayland backends and is written in Python which I know quite well, but I ran across enough odd choices in their use of Python that I figure I might as well try writing my own tool. Qtile is quite rich in features—I have a colleague who switched to it some time back—and it’s only about 50k or so lines of (kind of bizarre) Python code (excl. tests,) so I figure this may more achievable than one might otherwise assume.
qtile was my daily driver most of the time from mid 2018 - late 2022. (I did briefly try to switch to kde, but couldn’t get the tiling to work the way I wanted within the timebox I’d allowed for messing with my desktop and switched back.)
If I go back to using Linux as my primary desktop, I’ll probably use it again. I still like it when I fire up the thinkpad.
I understand what you mean by calling it kind of bizarre, but I never found it unreadably so. I really liked that it was configured using python. I tried AwesomeWM briefly before I settled on qtile, but for me python code based configuration was so much faster to navigate/understand than lua code based configuration that there was no contest. If I wanted to write my own window manager, I’d probably start off looking mostly at qtile.
Qtile is … (kind of bizarre) Python code
I understand what you mean by calling it kind of bizarre, but I never found it unreadably so.
Honestly, I should be a bit more careful in how I make these comments. Not like anyone really cares or anyone really listens to me (though I have keynoted events like PyCon US…) but really because I don’t want to disparage the work of others in a way that seems rude or mean.
At the same time, I want to be honest when I see something that I think was done poorly, and even be honest if I think something was done poorly despite being well within the capabilities of the authors (and well within reasonable expectations we might have of the authors’ capabilities.)
My posting on this website is already extremely tedious—just check out my comment history!—and I also want to avoid being even more tedious with endless qualifications, impenetrable euphemisms, or blasé equivocations.
So, Qtile as a software product works. It works well for my friend (who is a very well-known and very capable Python programmer!) I don’t exactly remember the details, but I looked into how one might extend the provided layouts, since I wanted to see how much effort it would be to mimic my AwesomeWM setup exactly. I skimmed through the core engine code itself, to try to determine whether some things that AwesomeWM can do (e.g., toggling window tags on and off) are possible in Qtile. I recall that the code was not horrible, but there were many instances where it seemed like significantly better choices could have been made, and, as a result, I dismissed the possibility of extending or even adopted Qtile. As I saw it, I won’t be forced onto Wayland for another few years and what I need that AwesomeWM cannot provide me is not pressing enough that I can’t afford spending many more months just circling this problem and slowly doing background research in anticipation of trying to build something from scratch.
xmonad’s core – which is already a window manager on its own, just rather minimal – consists of around 2000 lines of standard Haskell2010-ish code. It binds directly to Xlib instead of Xcb, but most of the C bindings are not directly included in the project; if you count that as well, perhaps add like 500 lines on top of that.
I would also say, don’t forget about this resource: https://www.gilesorr.com/wm/table.html
Can one rely on Prolog’s computational model to do constraint resolving that looks like minimization rather than outright solving? It’s clearly a different kind of problem to solve but I would imagine that with a window manager there are times where you can’t resolve 100% of the constraints, right?
You can because it’s Turing complete but you don’t need to do strange tricks: you can use dynamic programming with tabling or use clpz (clpfd in SWI) to get a minimization.
Yeah, I guess that in that case though you’re not really relying on Prolog’s evaluation model right? You’re just doing bog-standard deterministic programming?
Or I guess the dispatch can still happen through the logic layer… I have a very approximate understanding of this stuff. But thanks for the poitners!