Mirrored from GitHub

Jump to: Makefile README.md config.h sowm.c sowm.h


Makefile

1	CFLAGS += -std=c99 -Wall -Wextra -pedantic -Wold-style-declaration
2	CFLAGS += -Wmissing-prototypes -Wno-unused-parameter
3	PREFIX ?= /usr
4	BINDIR ?= $(PREFIX)/bin
5	CC     ?= gcc
6	
7	all: sowm
8	
9	config.h:
10		cp config.def.h config.h
11	
12	sowm: sowm.c sowm.h config.h Makefile
13		$(CC) -O3 $(CFLAGS) -o $@ $< -lX11 $(LDFLAGS)
14	
15	install: all
16		install -Dm755 sowm $(DESTDIR)$(BINDIR)/sowm
17	
18	uninstall:
19		rm -f $(DESTDIR)$(BINDIR)/sowm
20	
21	clean:
22		rm -f sowm *.o
23	
24	.PHONY: all install uninstall clean

README.md

1	# even shittier opinionated window manager
2	
3	## about
4	
5	esowm strips [sowm](//github.com/dylanaraps/sowm>sowm) of vanity
6	
7	## <s>Features</s>
8	
9	- No workspaces
10	- No Alt-Tab
11	- No fullscreen
12	
13	Read [Why Tiling Window Managers suck, X.Lee](http://xahlee.info/linux/why_tiling_window_manager_sucks.html)
14	
15	## Commands
16	
17	- Super + q, kill window
18	- Super + d, dmenu
19	- Super + Enter, Spawn terminal
20	- Super + Mouse Button 1, manual window raise
21	
22	## Recommended 
23	
24	- winwatch (plan9port)
25	- totop 

config.h

1	#ifndef CONFIG_H
2	#define CONFIG_H
3	#define MOD Mod4Mask
4	const char* menu[]    = {"dmenu_run",      0};
5	const char* term[]    = {"st",             0};
6	const char* stup[]   = {"stup",            0};
7	const char* brup[]   = {"brup",          0};
8	const char* acmeup[]   = {"acmeup",          0};
9	const char* zoom[]   = {"boomer",          0};
10	const char* bookmark[]   = {"bookmark",          0};
11	const char* ploomb[]   = {"ploomb",            0};
12	const char* scr[]   = {"scr",          0};
13	static struct key keys[] = {
14	    {MOD,      XK_q,   win_kill,   {0}},
15	    {MOD, XK_b,      run, {.com = bookmark}},
16	    {MOD, XK_d,      run, {.com = menu}},
17	    {MOD, XK_f,      run, {.com = ploomb}},
18	    {MOD, XK_z,      run, {.com = zoom}},
19	    {MOD, XK_Return, run, {.com = term}},
20	    {0,   XK_Print,  run, {.com = scr}},
21	    {0,   XF86XK_AudioLowerVolume,  run, {.com = brup}},
22	    {0,   XF86XK_AudioRaiseVolume,  run, {.com = stup}},
23	    {0,   XF86XK_AudioMute,         run, {.com = acmeup}},
24	};
25	#endif
26	

sowm.c

1	#include <X11/Xlib.h>
2	#include <X11/XF86keysym.h>
3	#include <X11/keysym.h>
4	#include <X11/XKBlib.h>
5	#include <stdlib.h>
6	#include <signal.h>
7	#include <unistd.h>
8	#include "sowm.h"
9	static client       *list = {0}, *ws_list[10] = {0}, *cur;
10	static int          ws = 1, sw, sh, wx, wy, numlock = 0;
11	static unsigned int ww, wh;
12	static Display      *d;
13	static XButtonEvent mouse;
14	static Window       root;
15	static void (*events[LASTEvent])(XEvent *e) = {
16	[ButtonPress]      = button_press,
17	[ButtonRelease]    = button_release,
18	[ConfigureRequest] = configure_request,
19	[KeyPress]         = key_press,
20	[MapRequest]       = map_request,
21	[MappingNotify]    = mapping_notify,
22	[EnterNotify]      = notify_enter,
23	[MotionNotify]     = notify_motion
24	};
25	#include "config.h"
26	void win_focus(client *c) {
27	cur = c;
28	XSetInputFocus(d, cur->w, RevertToParent, CurrentTime);
29	}
30	void notify_enter(XEvent *e) {
31	while(XCheckTypedEvent(d, EnterNotify, e));
32	for win if (c->w == e->xcrossing.window) win_focus(c);
33	}
34	void notify_motion(XEvent *e) {
35	if (!mouse.subwindow || cur->f) return;
36	while(XCheckTypedEvent(d, MotionNotify, e));
37	int xd = e->xbutton.x_root - mouse.x_root;
38	int yd = e->xbutton.y_root - mouse.y_root;
39	XMoveResizeWindow(d, mouse.subwindow,
40	wx + (mouse.button == 1 ? xd : 0),
41	wy + (mouse.button == 1 ? yd : 0),
42	MAX(1, ww + (mouse.button == 3 ? xd : 0)),
43	MAX(1, wh + (mouse.button == 3 ? yd : 0)));
44	}
45	
46	void key_press(XEvent *e) {
47	KeySym keysym = XkbKeycodeToKeysym(d, e->xkey.keycode, 0, 0);
48	
49	for (unsigned int i=0; i < sizeof(keys)/sizeof(*keys); ++i)
50	if (keys[i].keysym == keysym &&
51	    mod_clean(keys[i].mod) == mod_clean(e->xkey.state))
52	    keys[i].function(keys[i].arg);
53	}
54	
55	void button_press(XEvent *e) {
56	if (!e->xbutton.subwindow) return;
57	
58	win_size(e->xbutton.subwindow, &wx, &wy, &ww, &wh);
59	XRaiseWindow(d, e->xbutton.subwindow);
60	mouse = e->xbutton;
61	}
62	
63	void button_release(XEvent *e) {
64	mouse.subwindow = 0;
65	}
66	
67	void win_add(Window w) {
68	client *c;
69	
70	if (!(c = (client *) calloc(1, sizeof(client))))
71	exit(1);
72	
73	c->w = w;
74	
75	if (list) {
76	list->prev->next = c;
77	c->prev          = list->prev;
78	list->prev       = c;
79	c->next          = list;
80	
81	} else {
82	list = c;
83	list->prev = list->next = list;
84	}
85	
86	ws_save(ws);
87	}
88	
89	
90	void win_kill(const Arg arg) {
91	if (cur) XKillClient(d, cur->w);
92	}
93	
94	void configure_request(XEvent *e) {
95	    XConfigureRequestEvent *ev = &e->xconfigurerequest;
96	
97	    XConfigureWindow(d, ev->window, ev->value_mask, &(XWindowChanges) {
98	        .x          = ev->x,
99	        .y          = ev->y,
100	        .width      = ev->width,
101	        .height     = ev->height,
102	        .sibling    = ev->above,
103	        .stack_mode = ev->detail
104	    });
105	}
106	
107	void map_request(XEvent *e) {
108	    Window w = e->xmaprequest.window;
109	
110	    XSelectInput(d, w, StructureNotifyMask|EnterWindowMask);
111	    win_size(w, &wx, &wy, &ww, &wh);
112	    win_add(w);
113	    cur = list->prev;
114	
115	
116	    XMapWindow(d, w);
117	    win_focus(list->prev);
118	}
119	
120	void mapping_notify(XEvent *e) {
121	    XMappingEvent *ev = &e->xmapping;
122	
123	    if (ev->request == MappingKeyboard || ev->request == MappingModifier) {
124	        XRefreshKeyboardMapping(ev);
125	        input_grab(root);
126	    }
127	}
128	
129	void run(const Arg arg) {
130	    if (fork()) return;
131	    if (d) close(ConnectionNumber(d));
132	
133	    setsid();
134	    execvp((char*)arg.com[0], (char**)arg.com);
135	}
136	
137	void input_grab(Window root) {
138	    unsigned int i, j, modifiers[] = {0, LockMask, numlock, numlock|LockMask};
139	    XModifierKeymap *modmap = XGetModifierMapping(d);
140	    KeyCode code;
141	
142	    for (i = 0; i < 8; i++)
143	        for (int k = 0; k < modmap->max_keypermod; k++)
144	            if (modmap->modifiermap[i * modmap->max_keypermod + k]
145	                == XKeysymToKeycode(d, 0xff7f))
146	                numlock = (1 << i);
147	
148	    XUngrabKey(d, AnyKey, AnyModifier, root);
149	    for (i = 0; i < sizeof(keys)/sizeof(*keys); i++)
150	        if ((code = XKeysymToKeycode(d, keys[i].keysym)))
151	            for (j = 0; j < sizeof(modifiers)/sizeof(*modifiers); j++)
152	                XGrabKey(d, code, keys[i].mod | modifiers[j], root,
153	                        True, GrabModeAsync, GrabModeAsync);
154	    for (i = 1; i < 4; i += 2)
155	        for (j = 0; j < sizeof(modifiers)/sizeof(*modifiers); j++)
156	            XGrabButton(d, i, MOD | modifiers[j], root, True,
157	                ButtonPressMask|ButtonReleaseMask|PointerMotionMask,
158	                GrabModeAsync, GrabModeAsync, 0, 0);
159	    XFreeModifiermap(modmap);
160	}
161	int main(void) {
162	    XEvent ev;
163	    if (!(d = XOpenDisplay(0))) exit(1);
164	    signal(SIGCHLD, SIG_IGN);
165	    XSetErrorHandler(xerror);
166	    int s = DefaultScreen(d);
167	    root  = RootWindow(d, s);
168	    sw    = XDisplayWidth(d, s);
169	    sh    = XDisplayHeight(d, s);
170	    XSelectInput(d,  root, SubstructureRedirectMask);
171	    XDefineCursor(d, root, XCreateFontCursor(d, 68));
172	    input_grab(root);
173	    while (1 && !XNextEvent(d, &ev)) // 1 && will forever be here.
174	        if (events[ev.type]) events[ev.type](&ev);
175	}
176	

sowm.h

1	#include <X11/Xlib.h>
2	
3	#define win        (client *t=0, *c=list; c && t!=list->prev; t=c, c=c->next)
4	#define ws_save(W) ws_list[W] = list
5	#define ws_sel(W)  list = ws_list[ws = W]
6	#define MAX(a, b)  ((a) > (b) ? (a) : (b))
7	
8	#define win_size(W, gx, gy, gw, gh) \
9	    XGetGeometry(d, W, &(Window){0}, gx, gy, gw, gh, \
10	                 &(unsigned int){0}, &(unsigned int){0})
11	
12	// Taken from DWM. Many thanks. https://git.suckless.org/dwm
13	#define mod_clean(mask) (mask & ~(numlock|LockMask) & \
14	        (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
15	
16	typedef struct {
17	    const char** com;
18	    const int i;
19	    const Window w;
20	} Arg;
21	
22	struct key {
23	    unsigned int mod;
24	    KeySym keysym;
25	    void (*function)(const Arg arg);
26	    const Arg arg;
27	};
28	
29	typedef struct client {
30	    struct client *next, *prev;
31	    int f, wx, wy;
32	    unsigned int ww, wh;
33	    Window w;
34	} client;
35	
36	void button_press(XEvent *e);
37	void button_release(XEvent *e);
38	void configure_request(XEvent *e);
39	void input_grab(Window root);
40	void key_press(XEvent *e);
41	void map_request(XEvent *e);
42	void mapping_notify(XEvent *e);
43	void notify_destroy(XEvent *e);
44	void notify_enter(XEvent *e);
45	void notify_motion(XEvent *e);
46	void run(const Arg arg);
47	void win_add(Window w);
48	void win_focus(client *c);
49	void win_kill(const Arg arg);
50	static int xerror() { return 0; }
51