├── LICENSE ├── README.md ├── build.sh ├── mwm-custom.c └── mwm.c /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2024 Luis Lavaire 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mwm 2 | 3 | The window manager for the true minimalist: 4 | 5 | - 20 LOC. 6 | - No modes. 7 | - No "eye-candy". 8 | - No mouse control. 9 | - No virtual desktops. 10 | - No configuration files. 11 | - Not standards-compliant. 12 | - No title bars, no status bars, no buttons, no borders, no menus, etc. 13 | - All windows are full-screen, just one is visible at any given time. 14 | - Absolutely adaptable to your needs. 15 | - Includes just what is strictly needed. 16 | 17 | This is the smallest, actually usable window manager I know about. Even 18 | TinyWM is twice as large. However, it doesn't let you launch programs, or 19 | assign key bindings. `mwm` does. 20 | 21 | --- 22 | 23 | _`xterm`, with the `micro` editor, editing `mwm`'s source._ 24 | 25 | ![2024-12-27-172602_1920x1080_scrot](https://github.com/user-attachments/assets/a369645f-bb80-40fc-9658-0225583d8741) 26 | 27 | ## Why? 28 | 29 | Most software today is crappy. Do you really need all the bells and whistles? 30 | Probably not. 31 | 32 | We are in dire need of software that is hackable, fun, small, malleable, and 33 | that you can wrap your head around, because: is it truly free software if, due 34 | to its complexity, you cannot modify it? ;) 35 | 36 | ## How? 37 | 38 | The very essential things a window manager should let me do are: 39 | 40 | - Launch applications (which might create new windows). 41 | - Switch between windows. 42 | - Close windows. 43 | 44 | Well, so that's all what `mwm` lets you do. 45 | 46 | Two macros are available for assigning keybindings: `grab` and `map`. Read 47 | `mwm-custom.c` for an example on how to use them (my own setup). 48 | 49 | You first need to `grab` the keys you want to be able to bind. Then you `map` 50 | them to actions. 51 | 52 | ## Building. 53 | 54 | Run `./build.sh`. Pass `CC=...` to use a different C compiler (I use `tcc`). 55 | Dead simple. 56 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | rm -f mwm; ${CC:-tcc} -lX11 mwm.c -o mwm 4 | -------------------------------------------------------------------------------- /mwm-custom.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define stk(s) XKeysymToKeycode(d, XStringToKeysym(s)) 5 | #define on(_, x) if (e.type == _) { x; } 6 | #define map(k, x) if (e.xkey.keycode == stk(k)) { x; } 7 | #define grab(...) const char *l[] = { __VA_ARGS__, 0 }; \ 8 | for (int i = 0; l[i]; i++) XGrabKey(d, stk(l[i]), Mod4Mask, r, 1, 1, 1); 9 | 10 | int main() { 11 | Display *d = XOpenDisplay(0); Window r = DefaultRootWindow(d); XEvent e; 12 | XSelectInput(d, r, SubstructureRedirectMask); 13 | grab("n", "q", "w", "t", "l", "u", "i", "o", "p"); 14 | 15 | while (!XNextEvent (d, &e)) { 16 | on(ConfigureRequest, XMoveResizeWindow(d, e.xconfigure.window, 0, 0, e.xconfigure.width, e.xconfigure.height); 17 | XMoveResizeWindow(d, e.xconfigure.window, 0, 0, 1920, 1080)) // Needed due to a bug in XTerm. 18 | on(MapRequest, XMapWindow(d, e.xmaprequest.window); 19 | XSetInputFocus(d, e.xmaprequest.window, 2, 0)) 20 | on(KeyPress, map("n", XCirculateSubwindowsUp(d, r); XSetInputFocus(d, e.xkey.window, 2, 0)) 21 | map("q", XKillClient(d, e.xkey.subwindow)) 22 | map("w", system("chromium &")) 23 | map("t", system("xterm &")) 24 | map("l", system("rotK")) 25 | map("u", system("vol 5%-")) 26 | map("i", system("vol 5%+")) 27 | map("o", system("bri -100")) 28 | map("p", system("bri +100"))) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /mwm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define stk(s) XKeysymToKeycode(d, XStringToKeysym(s)) 5 | #define on(_, x) if (e.type == _) { x; } 6 | #define map(k, x) if (e.xkey.keycode == stk(k)) { x; } 7 | #define grab(...) const char *l[] = { __VA_ARGS__, 0 }; \ 8 | for (int i = 0; l[i]; i++) XGrabKey(d, stk(l[i]), Mod4Mask, r, 1, 1, 1); 9 | 10 | int main() { 11 | Display *d = XOpenDisplay(0); Window r = DefaultRootWindow(d); XEvent e; 12 | XSelectInput(d, r, SubstructureRedirectMask); 13 | grab("n", "q", "e"); 14 | 15 | while (!XNextEvent (d, &e)) { 16 | on(ConfigureRequest, XMoveResizeWindow(d, e.xconfigure.window, 0, 0, e.xconfigure.width, e.xconfigure.height)); 17 | on(MapRequest, XMapWindow(d, e.xmaprequest.window); 18 | XSetInputFocus(d, e.xmaprequest.window, 2, 0)); 19 | on(KeyPress, map("n", XCirculateSubwindowsUp(d, r); XSetInputFocus(d, e.xkey.window, 2, 0)) 20 | map("q", XKillClient(d, e.xkey.subwindow)) 21 | map("e", system("dmenu_run &"))); 22 | } 23 | } 24 | --------------------------------------------------------------------------------