top | item 44634208

Mwm – The smallest usable X11 window manager

203 points| daureg | 7 months ago |github.com

93 comments

order

90s_dev|7 months ago

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|7 months ago

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 &");
          }
      }
  }

ajross|7 months ago

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.

trollied|7 months ago

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.

chasil|7 months ago

Your X network traffic would be clear text over the network if you did it this way.

Instead, you should "ssh -x" or "ssh -y" to pull the traffic over the ssh encrypted channel.

The -y option should be used with caution; read the docs.

pjmlp|7 months ago

Yeah, the days of remote displaying unwanted adult content on other computers on university lab for anyone clueless about xhost command, as teenagers do.

supportengineer|7 months ago

We had a bright future in the past.

SbEpUBz2|7 months ago

There's waypipe.

dingnuts|7 months ago

This still works if X11 is installed on the remote. I have a remote that runs Wayland locally, and I run Wayland in the client machine as well, but I have X11 installed on the remote and X11 forwarding still works, it just opens the remote application in an XWayland window inside the local Wayland session. No biggie

ahlCVA|7 months ago

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|7 months ago

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.

zenolijo|7 months ago

> 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.

Like what?

A few years ago I copied the wlroots example, simplified it to less than 1000 LoC and then did some of my own modifications and additions like workspaces. And this side-project was done in less than a week on my spare time.

bitwize|7 months ago

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

chasil|7 months ago

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.

zshrc|7 months ago

MWM is included in modern Motif binary packages.

ajross|7 months ago

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

yjftsjthsd-h|7 months ago

> 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|7 months ago

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.

mosquitobiten|7 months ago

What's the point of the cage?

90s_dev|7 months ago

> 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|7 months ago

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.

jjrh|7 months ago

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.

throwaway328|7 months ago

Is there a repo or page somewhere listing the mini-est stuff? Very cool here!

adxl|7 months ago

You can read and understand the code in a minute. Very creative.

scoreandmore|7 months ago

How dare this person take `mwm`!!!

I have been using mwm (MOTIF) since 1991. Exact same configuration. It’s the perfect wm in my opinion. I’ve tried every major wm since, and I just can’t quit it. I do everything on the commandline, so I don’t need anything more than mwm. Who’s with me? Anyone? Anyone?

spauldo|7 months ago

I ran it a bit back in the day. Wound up on FVWM since it supports MWM's features in addition to tons of other functionality.

These days I use KDE 'cause I'm lazy and it has decent customization options. It won't quite do what FVWM would, but it's in the right ballpark for me.

hulitu|7 months ago

> Mwm – The smallest usable X11 window manager

Usable ? And using a traditional name ? Why not name it GNOME or KDE ? Or better: Windows.

teddyh|7 months ago

Not ICCCM compliant.

yjftsjthsd-h|7 months ago

It does say,

> Not standards-compliant.

in the very opening list of (non)features.

blueflow|7 months ago

How can you tell / what did you see that was missing for ICCCM compliance?

newlisp|7 months ago

This WM is too extreme but in linux desktop, the less GUI you use, the better.

pjmlp|7 months ago

It is smallest than twn or uwm though?

rs_rs_rs_rs_rs|7 months ago

"usable" is very generous

silon42|7 months ago

If it had proper Alt+Tab... and maybe a full screen mode, it would be usable...

userbinator|7 months ago

The very essential things a window manager should let me do are:

Launch applications (which might create new windows). Switch between windows. Close windows.

That sounds like the people who grew up using nothing but a smartphone all their lives. I find that there's an entire new generation of developers (and likely users) who don't understand basic window management at all --- all they have on their huge monitors all the time is one maximised application. Meanwhile I have several dozen windows open, all of various sizes, and when they see it, they are surprised at how I can work in such an environment.

No, I would not consider something that can't do what even Windows 1.0 could (tiled, nonoverlapping windows) a "window manager".

anthk|7 months ago

My cwm setup with a keyboard it's like that, but with a far better approach.

~/.cwmrc:

https://termbin.com/3jrl

It has a border (2px/4px dep. on the mood), you can execute programs with autocomplete (win+a), search between open windows (win+s), resize/move them, close (win+q), move them to virtual tags (desktops) shift+win+1-4, and go to each of these tags (win+1-4).

Minimal but actually usable. And fast as hell. I don't even need a mouse, and my RSI plumetted once I came from Emacs for a experiment (yes, I always had Ctrl and CapsLock switched over), even with CWM.

0points|7 months ago

I find your stance uneducated.

I use tiling vm fully (sway) and mostly work in single app full screen, one desktop per app, which is the least disruptive way possible to use a PC for work. You should try it.

blueflow|7 months ago

When you have scanning eyes, any window on-screen that you are currently not scanning is a waste of pixels. These pixels could display data from your focused window instead.