[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)