Major refactor.
This commit is contained in:
parent
bf0d3de94b
commit
bb8a508ef4
4 changed files with 67 additions and 46 deletions
43
README.md
43
README.md
|
|
@ -1,37 +1,42 @@
|
||||||
# mwm
|
# mwm
|
||||||
|
|
||||||
For the true minimalist:
|
The window manager for the true minimalist:
|
||||||
|
|
||||||
- ~40 LOC.
|
- 20 LOC.
|
||||||
- No default keybindings (just edit the source).
|
- No modes.
|
||||||
- No title bars, no status bars, no buttons, no borders, no menus, etc.
|
- No "eye-candy".
|
||||||
- No eye-candy.
|
|
||||||
- No mouse control.
|
- No mouse control.
|
||||||
- No virtual desktops.
|
- No virtual desktops.
|
||||||
- No configuration files.
|
- No configuration files.
|
||||||
|
- Not standards-compliant.
|
||||||
|
- 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.
|
||||||
- Absolutely adaptable to your needs.
|
- Absolutely adaptable to your needs.
|
||||||
- Includes just what is strictly needed.
|
- Includes just what is strictly needed.
|
||||||
- Not standards-compliant.
|
|
||||||
- All windows are full-screen, just one is visible at any given time.
|
This is the smallest, actually usable window manager I know about. Even
|
||||||
- No modes.
|
TinyWM is twice as large. However, it doesn't let you launch programs, or
|
||||||
|
switch between windows. `mwm` does.
|
||||||
|
|
||||||
## Why?
|
## Why?
|
||||||
|
|
||||||
Most software today is crappy. Do you really need all that? I found out
|
Most software today is crappy. Do you really need all the bells and whistles?
|
||||||
through experience that, generally, you don't. Do you really need to have
|
Generally, you don't. You need to get the job done.
|
||||||
a dozen windows opened simultaneously? When you do, you will need a way to
|
|
||||||
organize that mess. Virtual desktops, window tags, etc. are ways to cope
|
|
||||||
with the symptoms of a underlying issue.
|
|
||||||
|
|
||||||
We are in dire need of software that is hackable, fun, small, malleable,
|
We are in dire need of software that is hackable, fun, small, malleable, and
|
||||||
and that you can wrap your head around, because: is it truly free software
|
that you can wrap your head around, because: is it truly free software if, due
|
||||||
if, due to its complexity, you cannot modify it? ;)
|
to its complexity, you cannot modify it? ;)
|
||||||
|
|
||||||
## How?
|
## How?
|
||||||
|
|
||||||
Two macros are available for assigning keybindings: `grab` and `K`.
|
Two macros are available for assigning keybindings: `grab` and `map`. Read
|
||||||
Read the source for an example on how to use them (my own setup).
|
`mwm-custom.c` for an example on how to use them (my own setup).
|
||||||
|
|
||||||
Run `./build.sh`. Pass `CC=` to use a different C compiler (I use tcc).
|
You first need to `grab` the keys you want to be able to bind. Then you `map`
|
||||||
|
them to actions.
|
||||||
|
|
||||||
|
## Building.
|
||||||
|
|
||||||
|
Run `./build.sh`. Pass `CC=...` to use a different C compiler (I use `tcc`).
|
||||||
|
|
||||||
Dead simple.
|
Dead simple.
|
||||||
|
|
|
||||||
1
build.sh
1
build.sh
|
|
@ -1,4 +1,3 @@
|
||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
|
|
||||||
|
|
||||||
rm -f mwm; ${CC:-tcc} -lX11 mwm.c -o mwm
|
rm -f mwm; ${CC:-tcc} -lX11 mwm.c -o mwm
|
||||||
|
|
|
||||||
30
mwm-custom.c
Normal file
30
mwm-custom.c
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
#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", "w", "t", "l", "u", "i", "o", "p");
|
||||||
|
|
||||||
|
while (!XNextEvent (d, &e)) {
|
||||||
|
on(ConfigureRequest, XMoveResizeWindow(d, e.xconfigure.window, 0, 0, e.xconfigure.width, e.xconfigure.height);
|
||||||
|
XMoveResizeWindow(d, e.xconfigure.window, 0, 0, 1920, 1080)) // Needed due to a bug in XTerm.
|
||||||
|
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("w", system("chromium &"))
|
||||||
|
map("t", system("xterm &"))
|
||||||
|
map("l", system("rotK"))
|
||||||
|
map("u", system("vol 5%-"))
|
||||||
|
map("i", system("vol 5%+"))
|
||||||
|
map("o", system("bri -100"))
|
||||||
|
map("p", system("bri +100")))
|
||||||
|
}
|
||||||
|
}
|
||||||
39
mwm.c
39
mwm.c
|
|
@ -2,35 +2,22 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define stk(s) XKeysymToKeycode(d, XStringToKeysym(s))
|
#define stk(s) XKeysymToKeycode(d, XStringToKeysym(s))
|
||||||
#define K(k, x) if (e.xkey.keycode == stk(k)) { x; }
|
#define on(_, x) if (e.type == _) { x; }
|
||||||
#define E(_, x) if (e.type == _) { x; }
|
#define map(k, x) if (e.xkey.keycode == stk(k)) { x; }
|
||||||
#define grab(...) const char *l[] = { __VA_ARGS__ }; \
|
#define grab(...) const char *l[] = { __VA_ARGS__, 0 }; \
|
||||||
for (size_t i = 0; i < sizeof(l) / sizeof(*l); ++i) \
|
for (int i = 0; l[i]; i++) XGrabKey(d, stk(l[i]), Mod4Mask, r, 1, 1, 1);
|
||||||
XGrabKey (d, stk(l[i]), Mod4Mask, r, 1, 1, 1);
|
|
||||||
|
|
||||||
int main () {
|
int main() {
|
||||||
Display *d = XOpenDisplay(0); Window r = DefaultRootWindow(d); XEvent e;
|
Display *d = XOpenDisplay(0); Window r = DefaultRootWindow(d); XEvent e;
|
||||||
XSelectInput (d, r, SubstructureRedirectMask);
|
XSelectInput(d, r, SubstructureRedirectMask);
|
||||||
|
grab("n", "q", "e");
|
||||||
grab ("n", "q", "w", "t", "l", "u", "i", "o", "p");
|
|
||||||
|
|
||||||
while (!XNextEvent (d, &e)) {
|
while (!XNextEvent (d, &e)) {
|
||||||
E (KeyPress,
|
on(ConfigureRequest, XMoveResizeWindow(d, e.xconfigure.window, 0, 0, e.xconfigure.width, e.xconfigure.height));
|
||||||
K("n", XCirculateSubwindowsUp(d, r); XSetInputFocus(d, e.xkey.window, 2, 0))
|
on(MapRequest, XMapWindow(d, e.xmaprequest.window);
|
||||||
K("q", XKillClient(d, e.xkey.subwindow))
|
XSetInputFocus(d, e.xmaprequest.window, 2, 0));
|
||||||
K("w", system("chromium --enable-features=WebContentsForceDark &"))
|
on(KeyPress, map("n", XCirculateSubwindowsUp(d, r); XSetInputFocus(d, e.xkey.window, 2, 0))
|
||||||
K("t", system("xterm &"))
|
map("q", XKillClient(d, e.xkey.subwindow))
|
||||||
K("l", system("rotK"))
|
map("e", system("dmenu_run &")));
|
||||||
K("u", system("vol 5%-"))
|
|
||||||
K("i", system("vol 5%+"))
|
|
||||||
K("o", system("bri -100"))
|
|
||||||
K("p", system("bri +100")))
|
|
||||||
|
|
||||||
E (MapRequest, XMapWindow(d, e.xmaprequest.window);
|
|
||||||
XSetInputFocus(d, e.xmaprequest.window, 2, 0))
|
|
||||||
|
|
||||||
E (ConfigureRequest,
|
|
||||||
XMoveResizeWindow (d, e.xconfigure.window, 0, 0, e.xconfigure.width, e.xconfigure.height);
|
|
||||||
XMoveResizeWindow (d, e.xconfigure.window, 0, 0, 1920, 1080))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue