[HN Gopher] Mwm - The smallest usable X11 window manager
       ___________________________________________________________________
        
       Mwm - The smallest usable X11 window manager
        
       Author : daureg
       Score  : 111 points
       Date   : 2025-07-21 12:04 UTC (3 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | ajross wrote:
       | Heh, it's a preprocessor DSL:                   #define on(_, x)
       | if (e.type == _) { x; }         #define map(k, x) if
       | (e.xkey.keycode == stk(k)) { x; }         #define grab(...) const
       | char *l[] = { __VA_ARGS__, 0 }; \                             for
       | (int i = 0; l[i]; i++) XGrabKey(d, stk(l[i]), Mod4Mask, r, 1, 1,
       | 1);
       | 
       | Stephen Bourne lives on! (Actually he's not dead, I just
       | checked.)
        
       | 90s_dev wrote:
       | > Most software today is crappy. Do you really need all the bells
       | and whistles? Probably not.
       | 
       | I agree that most software today is _bloated_ , but I wouldn't
       | say crappy. There are legitimate reasons to choose bloat, for
       | example using SDL or Electron to speed up development and have
       | easier portability. But for some reason I do strongly enjoy
       | writing and using minimalist software. That's why I removed C++,
       | SDL and other libs from my app (hram.dev) and just used C, native
       | Win32 APIs, and D3D, getting it down to 1.4mb and speeding up
       | compilation a _lot_. So projects like this always appeal to me,
       | and I love seeing different ways we can be minimalist without
       | sacrificing too much functionality or convenience.
        
         | gen2brain wrote:
         | The best apps I've used have implementations for every OS and
         | UI separately. Usually, everyone uses the easier route, but it
         | will only be good enough, not the best. But again, now your app
         | works only on Windows.
        
           | 90s_dev wrote:
           | Yeah those apps were my inspiration: use the native UI and
           | share logic as a lib.
           | 
           | I don't even have a Mac yet, so no point in shipping for that
           | if I can't debug it.
           | 
           | If sales are good, I'd be glad to buy a cheap macbook off
           | ebay and port it.
        
         | jjrh wrote:
         | It's a shame no one has figured out how we can get the
         | flexibility of html/css/js in a way that is fast.
        
           | ravetcofx wrote:
           | Python?
        
           | homarp wrote:
           | if you can elaborate a bit on a) flexibility b) fast
           | 
           | like the fellow commenter said, python might qualify as
           | flexible, fast to code, and 'fast enough'
        
           | toast0 wrote:
           | Tk?
        
       | 90s_dev wrote:
       | This is the entire source:                   #include
       | <X11/Xlib.h>         #include <stdlib.h>              #define
       | stk(s)    XKeysymToKeycode(d, XStringToKeysym(s))         #define
       | on(_, x)  if (e.type == _) { x; }         #define map(k, x) if
       | (e.xkey.keycode == stk(k)) { x; }         #define grab(...) const
       | char *l[] = { __VA_ARGS__, 0 }; \                             for
       | (int i = 0; l[i]; i++) XGrabKey(d, stk(l[i]), Mod4Mask, r, 1, 1,
       | 1);              int main() {           Display *d =
       | XOpenDisplay(0); Window r = DefaultRootWindow(d); XEvent e;
       | XSelectInput(d, r, SubstructureRedirectMask);           grab("n",
       | "q", "e");                while (!XNextEvent (d, &e)) {
       | on(ConfigureRequest, XMoveResizeWindow(d, e.xconfigure.window, 0,
       | 0, e.xconfigure.width, e.xconfigure.height));
       | on(MapRequest, XMapWindow(d, e.xmaprequest.window);
       | XSetInputFocus(d, e.xmaprequest.window, 2, 0));
       | on(KeyPress, map("n", XCirculateSubwindowsUp(d, r);
       | XSetInputFocus(d, e.xkey.window, 2, 0))
       | map("q", XKillClient(d, e.xkey.subwindow))
       | map("e", system("dmenu_run &")));           }         }
       | 
       | I have to say, I'm not usually a huge fan of C macros, but it
       | works here so well, it feels so elegant and clean somehow.
        
         | qsort wrote:
         | Is it really that much better than this:
         | #include <X11/Xlib.h>       #include <stdlib.h>
         | int GetKeyCode(Display* d, char* s)       {           return
         | XKeysymToKeycode(d, XStringToKeysym(s));       }
         | int main()       {           Display* d = XOpenDisplay(0);
         | Window r = DefaultRootWindow(d);           XSelectInput(d, r,
         | SubstructureRedirectMask);                  XGrabKey(d,
         | GetKeyCode(d, "n"), Mod4Mask, r, 1, 1, 1);
         | XGrabKey(d, GetKeyCode(d, "q"), Mod4Mask, r, 1, 1, 1);
         | XGrabKey(d, GetKeyCode(d, "e"), Mod4Mask, r, 1, 1, 1);
         | XEvent e;           while (!XNextEvent(d, &e)) {
         | switch (e.type) {               case ConfigureRequest:
         | XMoveResizeWindow(d, e.xconfigure.window, 0, 0,
         | e.xconfigure.width, e.xconfigure.height);
         | break;               case MapRequest:
         | XMapWindow(d, e.xmaprequest.window);                   break;
         | case KeyPress:                   if (e.xkey.keycode ==
         | GetKeyCode(d, "n")) {
         | XCirculateSubwindowsUp(d, r);
         | XSetInputFocus(d, e.xkey.window, 2, 0);                   }
         | if (e.xkey.keycode == GetKeyCode(d, "q"))
         | XKillClient(d, e.xkey.subwindow);                   if
         | (e.xkey.keycode == GetKeyCode(d, "e"))
         | system("dmenu_run &");               }           }       }
        
           | netrap wrote:
           | I think this is more readable than with macros, but it might
           | be a preference.
        
             | qsort wrote:
             | It's also 50 bytes longer than the original. More LOC only
             | because my Vim formats on save.
             | 
             | Whenever somebody comes up with some big brain idea with
             | macros, ORMs, DSLs, 180 IQ templates, language extensions
             | that even Haskell nerds would say are too much, there's a
             | good chance that the grugbrained version is just as
             | readable, just as concise without going against the
             | language.
             | 
             | I'm _this close_ to go completely nuts with this industry
             | and commit to full butlerian jihad against anybody who goes
             | higher in abstraction than ANSI C.
        
           | l-albertovich wrote:
           | Just for fun I reformatted it minimally in the conservative
           | way I write code that is intended to be easy to read and
           | understand to improve the odds of future contributors (or
           | future me) introducing a bug in it due to misunderstanding
           | it.
           | 
           | It's painfully verbose but I think it's worth it considering
           | that we're in 2025 and we're not limited to one character
           | variable names.
           | 
           | https://gist.github.com/leonardo-
           | albertovich/984fff0825ff8fe...
        
         | illegalmemory wrote:
         | This is slightly bigger version I wrote around 13 years ago. :)
         | 
         | https://github.com/savitasinghvit/piwm/blob/master/piwm.c
        
         | ajross wrote:
         | Beware! That's the DSL trap.
         | 
         | It works here so well _because_ it 's limited to 20 lines and
         | each macro does exactly what it needs to for the problem at
         | hand.
         | 
         | Take that DSL and use it over a year to write a bunch of code
         | to do normal things as your app grows into its problem domain
         | and spills over into a few more, and it melts. New developers
         | will show up to onboard to your and be like "WTF is this 'on()'
         | thing I'm looking at all over the place, and why isn't it used
         | over here?!". Some enterprising developer will introduce
         | "map2()" to indirect based on keysym and not keycode, etc...
         | 
         | Domain Specific Languages are a mistake, almost every time
         | they're used. And the only exceptions are the ones that grow
         | into first class languages for well-defined problem areas (I'm
         | thinking about things like VHDL or Mathematica here), and even
         | there they tend not to be _that_ much better than well-crafted
         | domain-specific APIs in true programming languages (think
         | numpy, pytorch, et. al.)
         | 
         | DSLs: Just say no.
        
           | 90s_dev wrote:
           | Yeah exactly, this is why I stopped liking DSLs about 15
           | years ago, shortly after using Ruby extensively (probably not
           | a coincidence) and converting to Clojure, where there was a
           | large movement away from macros despite it being lisp.
           | They're good in _very_ isolated situations, and only when
           | designed _very_ carefully. This wm is quite possibly one of
           | them; if you need more complexity than the macros here allow,
           | and adding /changing macros only makes it worse, just use
           | another wm.
        
           | convolvatron wrote:
           | there really isn't a fundamental difference between DSLs and
           | libraries for the points that you brought up. where it really
           | starts to get sketchy is when you do really funny things with
           | the base syntax (looking at you lisp and rust). if not well
           | thought out they can be fragile, confusing, and a real burden
           | for new contributors.
           | 
           | I guess here's a question - do you consider regex libraries
           | to be DSLs?
        
         | klaussilveira wrote:
         | That macro usage is sublime. Bravo!
        
       | teddyh wrote:
       | Not ICCCM compliant.
        
         | yjftsjthsd-h wrote:
         | It does say,
         | 
         | > Not standards-compliant.
         | 
         | in the very opening list of (non)features.
        
         | blueflow wrote:
         | How can you tell / what did you see that was missing for ICCCM
         | compliance?
        
       | rithikrolex wrote:
       | Hack rosien
        
         | poly2it wrote:
         | Pardon? Welcome to HN :^)
        
       | newlisp wrote:
       | This WM is too extreme but in linux desktop, the less GUI you
       | use, the better.
        
       | neoden wrote:
       | Is anything similar possible with Wayland?
        
       | ahlCVA wrote:
       | While this leaves a lot to be desired as a window manager, it
       | illustrates one of my main gripes about the Wayland ecosystem: By
       | effectively bundling the window manager and X server, it makes it
       | much harder for more niche/experimental window managers to come
       | about and stay alive. Even with things like wlroots, you have to
       | invest a lot more work to get even the basics working that X11
       | will give you for free.
        
         | tadfisher wrote:
         | True; but a counterargument is that the _display protocol_ is
         | not the right abstraction layer for decoupling window
         | management from the display server. There is nothing stopping
         | someone from writing a batteries-included wlroots-like library
         | where the only piece you need to write is the window management
         | and input handling, or even an entire Wayland compositor that
         | farms these pieces out to an embedded scripting runtime.
         | 
         | But even then, I think we have rose-tinted glasses on when it
         | comes to writing an X11 WM that actually works, because X11
         | does not actually give much for free. ICCCM is the glue that
         | makes window management work, and it is a complete inversion of
         | "mechanism, not policy" that defines the X11 protocol. It also
         | comes in at 60-odd pages in PDF form:
         | https://www.x.org/docs/ICCCM/icccm.pdf
         | 
         | For an example, X11 does not specify how copy-and-paste should
         | work between applications; that's all ICCCM.
        
           | fmbb wrote:
           | Copy&paste between apps should work just fine using this
           | window manager.
           | 
           | I have not tried mwm but use my own 100 line C window manager
           | and I can copy and paste without issue.
           | 
           | Wayland will take 20 more years before it can dethrone X11.
           | And even then we will mostly run X11 apps on XWayland.
        
             | tadfisher wrote:
             | I'm sorry for not making it more clear, but that was just
             | an example of something left unspecified by the X11 core
             | protocol but instead defined in a standard convention.
             | 
             | An example that matters for window managers would be
             | complex window reparenting policies or input grabs, but
             | that's a little less descriptive of the core concept I was
             | trying to get across.
        
               | DonHopkins wrote:
               | We may not always have Paris, but we will always have
               | XRotateBuffers.
               | 
               | https://tronche.com/gui/x/xlib/utilities/XRotateBuffers.h
               | tml
        
           | DonHopkins wrote:
           | https://www.donhopkins.com/home/catalog/unix-
           | haters/x-window...
           | 
           | Window Manager Flames, by Don Hopkins
           | 
           | The ICCCM Sucks
           | 
           | The ICCCM, abbreviated I39L, sucks. I39L is a hash for the
           | acronymic expansion of ICCCM for "Inter-Client Communication
           | Conventions Manual". Please read it if you don't believe me
           | that it sucks! It really does. However, we must live with it.
           | But how???
           | 
           | [...]
        
         | bitwize wrote:
         | YAGN more experimental/niche window managers. Windows and macOS
         | get by fine on one apiece, in fact their desktop story is
         | better because their WM and toolkit is standardized.
         | 
         | The developers of Wayland (who are identical to the developers
         | of Xorg) aspire to more of a Windows/Mac-like ecosystem for
         | Linux, in which standardization, performance, and support for
         | modern graphics hardware without hacks or workarounds are
         | prioritized over proliferation of niche window managers and
         | toolkits
        
           | l72 wrote:
           | Terrible window management is a huge reason I will not use
           | Mac OS or Windows. I immediately lose so much productivity. I
           | am coming up on my 30th year of using Linux, and I can't
           | imagine moving to an OS with such limited window
           | capabilities. No sloppy mouse focus? No always on top? No
           | sticky windows? No marking windows as utility windows to skip
           | alt-tab?
           | 
           | I watch my colleagues on Mac OS and Windows during peer
           | programming, and am flabbergasted as they fumble around
           | trying to find the right window.
           | 
           | I am interacting with my computers interface for 10+ hours
           | every single day. I do not stare at a single application, but
           | am constantly jumping between windows and tasks. The one size
           | fits all approach is the same as the lowest common
           | denominator approach, and it hinders people who need to do
           | real work.
        
             | dmytrish wrote:
             | Linux already has GNOME and KDE as solid mainstream
             | platforms (which is already twice as good as
             | MacOS/Windows), and it also already has Sway, Hyprland,
             | Niri. If an idea is worth implementing, it gets implemented
             | even with Wayland.
        
       | yjftsjthsd-h wrote:
       | > No title bars, no status bars, no buttons, no borders, no
       | menus, etc.
       | 
       | > All windows are full-screen, just one is visible at any given
       | time.
       | 
       | Oh, it's like cage ( https://github.com/cage-kiosk/cage ) for
       | X11. I was wondering ex. how you'd even move windows around in
       | that little code; the answer is "you don't":)
        
         | chmod775 wrote:
         | No it's not. It lets you cycle through active windows with a
         | hotkey, lets you close the current window, and launches dmenu
         | to let you open more applications.
        
         | vidarh wrote:
         | This one lets you move windows around:
         | 
         | https://github.com/mackstann/tinywm/blob/master/tinywm.c
        
       | trollied wrote:
       | I wish things were as easy as they were with X11. Being able to
       | ssh into a box and "export DISPLAY=192.168.0.7:0.0" then start an
       | app and have it show up locally is just magical.
        
         | SbEpUBz2 wrote:
         | There's waypipe.
        
         | supportengineer wrote:
         | We had a bright future in the past.
        
           | throwaway328 wrote:
           | You mean a kind of "Spectres of Marx", Jacques Derrida, 1993,
           | hauntology type thing?
        
       | rs_rs_rs_rs_rs wrote:
       | "usable" is very generous
        
       | throwaway328 wrote:
       | Is there a repo or page somewhere listing the mini-est stuff?
       | Very cool here!
        
       | int_19h wrote:
       | If you want something similar but more functional, check out
       | https://www.nongnu.org/ratpoison/
        
       | chasil wrote:
       | This name conflicts with the original Motif Window Manager, part
       | of OSF Motif. I don't know if mwm is found in modern Motif binary
       | packages.
       | 
       | https://en.m.wikipedia.org/wiki/Motif_Window_Manager
       | 
       | The dtvwm eclipsed this in CDE.
        
       ___________________________________________________________________
       (page generated 2025-07-24 23:00 UTC)