From 1a4c655b9d09a9ee42f6e0fa7470d1f07319892e Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sat, 11 Jul 2020 11:31:30 +0300 Subject: [PATCH] meta: Rewrite sowm and swap to XCB. This was my first real C project and it shows. Learning C is quite fun and I still have a long way to go. This next rewrite should be less of a hot-mess than the original Xlib version. Notable mistakes: - while (1 && ...) - for win (spastic pre-processor stuff) - no proper tracking of client sizes/positions. - lazy window focus model. - almost code-golfed code-base. - circular-doubly-linked-list for clients. The following changes mark the initial commit for the rewrite. The window manager works but does not yet do enough for it to be usable. Clients, keybindings, a configuration file, etc, etc do not yet exist. Baby steps. --- .gitignore | 1 + LICENSE.md | 33 ----- Makefile | 26 ++-- README.md | 98 -------------- config.def.h | 49 ------- sowm.c | 356 ++++++++++++++++++--------------------------------- sowm.h | 94 ++++++-------- 7 files changed, 180 insertions(+), 477 deletions(-) delete mode 100644 LICENSE.md delete mode 100644 README.md delete mode 100644 config.def.h diff --git a/.gitignore b/.gitignore index db4f001..9267cd5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ sowm sowm.o config.h +.ccls-cache diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 38cf607..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,33 +0,0 @@ -MIT/X Consortium License - -- © 2019- Dylan Araps -- © 2006-2011 Anselm R Garbe -- © 2007-2011 Peter Hartlich -- © 2010-2011 Connor Lane Smith -- © 2006-2009 Jukka Salmi -- © 2007-2009 Premysl Hruby -- © 2007-2009 Szabolcs Nagy -- © 2007-2009 Christof Musik -- © 2009 Mate Nagy -- © 2007-2008 Enno Gottox Boland -- © 2008 Martin Hurton -- © 2008 Neale Pickett -- © 2006-2007 Sander van Dijk - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/Makefile b/Makefile index 20f3734..0fe2f58 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,24 @@ -CFLAGS += -std=c99 -Wall -Wextra -pedantic -Wold-style-declaration -CFLAGS += -Wmissing-prototypes -Wno-unused-parameter -PREFIX ?= /usr -BINDIR ?= $(PREFIX)/bin -CC ?= gcc +.POSIX: + +PREFIX = /usr/local + +ALL_WARN = -Wall -Wextra -pedantic -Wmissing-prototypes -Wstrict-prototypes +ALL_CFLAGS = $(CFLAGS) $(CPPFLAGS) -std=c99 $(ALL_WARN) +ALL_LDFLAGS = $(LDFLAGS) -lxcb + +CC = cc all: sowm -config.h: - cp config.def.h config.h - -sowm: sowm.c sowm.h config.h Makefile - $(CC) -O3 $(CFLAGS) -o $@ $< -lX11 $(LDFLAGS) +sowm: sowm.c Makefile + $(CC) -O3 $(ALL_CFLAGS) -o $@ $< $(ALL_LDFLAGS) install: all - install -Dm755 sowm $(DESTDIR)$(BINDIR)/sowm + mkdir -p $(DESTDIR)/bin + cp sowm $(DESTDIR)/bin/sowm uninstall: - rm -f $(DESTDIR)$(BINDIR)/sowm + rm -f $(DESTDIR)/bin/sowm clean: rm -f sowm *.o diff --git a/README.md b/README.md deleted file mode 100644 index b063fc8..0000000 --- a/README.md +++ /dev/null @@ -1,98 +0,0 @@ -# sowm (*~~Simple~~ Shitty Opinionated Window Manager*) - - - -An itsy bitsy floating window manager (*220~ sloc!*). - -- Floating only. -- Fullscreen toggle. -- Window centering. -- Mix of mouse and keyboard workflow. -- Focus with cursor. -- Rounded corners (*[through patch](https://github.com/dylanaraps/sowm/pull/58)*) -- Titlebars (*[through patch](https://github.com/dylanaraps/sowm/pull/57)*) - - - -- Alt-Tab window focusing. -- All windows die on exit. -- No window borders. -- [No ICCCM](https://web.archive.org/web/20190617214524/https://raw.githubusercontent.com/kfish/xsel/1a1c5edf0dc129055f7764c666da2dd468df6016/rant.txt). -- No EWMH. -- etc etc etc - - -
- -Patches available here: https://github.com/dylanaraps/sowm/pulls - -## Default Keybindings - -**Window Management** - -| combo | action | -| -------------------------- | -----------------------| -| `Mouse` | focus under cursor | -| `MOD4` + `Left Mouse` | move window | -| `MOD4` + `Right Mouse` | resize window | -| `MOD4` + `f` | maximize toggle | -| `MOD4` + `c` | center window | -| `MOD4` + `q` | kill window | -| `MOD4` + `1-9` | desktop swap | -| `MOD4` + `Shift` +`1-9` | send window to desktop | -| `MOD1` + `TAB` (*alt-tab*) | focus cycle | - -**Programs** - -| combo | action | program | -| ------------------------ | ---------------- | -------------- | -| `MOD4` + `Return` | terminal | `st` | -| `MOD4` + `d` | dmenu | `dmenu_run` | -| `MOD4` + `p` | scrot | `scr` | -| `MOD4` + `w` | wallpaper cycler | `bud` | -| `XF86_AudioLowerVolume` | volume down | `amixer` | -| `XF86_AudioRaiseVolume` | volume up | `amixer` | -| `XF86_AudioMute` | volume toggle | `amixer` | -| `XF86_MonBrightnessUp` | brightness up | `bri` | -| `XF86_MonBrightnessDown` | brightness down | `bri` | - - -## Dependencies - -- `xlib` (*usually `libX11`*). - - -## Installation - -1) Copy `config.def.h` to `config.h` and modify it to suit your needs. -2) Run `make` to build `sowm`. -3) Copy it to your path or run `make install`. - - `DESTDIR` and `PREFIX` are supported. -4) (Optional) Apply patch with `git apply patches/patch-name` - - In case of applying multiple patches, it has to be done **manually**. - -If you are using GDM, save the following to `/usr/share/xsessions/sowm.desktop`. It is still recommended to start `sowm` from `.xinitrc` or through -[your own xinit implementation](https://github.com/dylanaraps/bin/blob/dfd9a9ff4555efb1cc966f8473339f37d13698ba/x). - -``` -[Desktop Entry] -Name=sowm -Comment=This session runs sowm as desktop manager -Exec=sowm -Type=Application -``` - - -## Thanks - -- 2bwm -- SmallWM -- berry -- catwm -- dminiwm -- dwm -- monsterwm -- openbox -- possumwm -- swm -- tinywm diff --git a/config.def.h b/config.def.h deleted file mode 100644 index cae2009..0000000 --- a/config.def.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef CONFIG_H -#define CONFIG_H - -#define MOD Mod4Mask - -const char* menu[] = {"dmenu_run", 0}; -const char* term[] = {"st", 0}; -const char* scrot[] = {"scr", 0}; -const char* briup[] = {"bri", "10", "+", 0}; -const char* bridown[] = {"bri", "10", "-", 0}; -const char* voldown[] = {"amixer", "sset", "Master", "5%-", 0}; -const char* volup[] = {"amixer", "sset", "Master", "5%+", 0}; -const char* volmute[] = {"amixer", "sset", "Master", "toggle", 0}; -const char* colors[] = {"bud", "/home/goldie/Pictures/Wallpapers", 0}; - -static struct key keys[] = { - {MOD, XK_q, win_kill, {0}}, - {MOD, XK_c, win_center, {0}}, - {MOD, XK_f, win_fs, {0}}, - - {Mod1Mask, XK_Tab, win_next, {0}}, - {Mod1Mask|ShiftMask, XK_Tab, win_prev, {0}}, - - {MOD, XK_d, run, {.com = menu}}, - {MOD, XK_w, run, {.com = colors}}, - {MOD, XK_p, run, {.com = scrot}}, - {MOD, XK_Return, run, {.com = term}}, - - {0, XF86XK_AudioLowerVolume, run, {.com = voldown}}, - {0, XF86XK_AudioRaiseVolume, run, {.com = volup}}, - {0, XF86XK_AudioMute, run, {.com = volmute}}, - {0, XF86XK_MonBrightnessUp, run, {.com = briup}}, - {0, XF86XK_MonBrightnessDown, run, {.com = bridown}}, - - {MOD, XK_1, ws_go, {.i = 1}}, - {MOD|ShiftMask, XK_1, win_to_ws, {.i = 1}}, - {MOD, XK_2, ws_go, {.i = 2}}, - {MOD|ShiftMask, XK_2, win_to_ws, {.i = 2}}, - {MOD, XK_3, ws_go, {.i = 3}}, - {MOD|ShiftMask, XK_3, win_to_ws, {.i = 3}}, - {MOD, XK_4, ws_go, {.i = 4}}, - {MOD|ShiftMask, XK_4, win_to_ws, {.i = 4}}, - {MOD, XK_5, ws_go, {.i = 5}}, - {MOD|ShiftMask, XK_5, win_to_ws, {.i = 5}}, - {MOD, XK_6, ws_go, {.i = 6}}, - {MOD|ShiftMask, XK_6, win_to_ws, {.i = 6}}, -}; - -#endif diff --git a/sowm.c b/sowm.c index b4a39dd..9983f00 100644 --- a/sowm.c +++ b/sowm.c @@ -1,277 +1,167 @@ -// sowm - An itsy bitsy floating window manager. - -#include -#include -#include -#include +#define _POSIX_C_SOURCE 200809L +#include #include #include -#include + +#include #include "sowm.h" -static client *list = {0}, *ws_list[10] = {0}, *cur; -static int ws = 1, sw, sh, wx, wy, numlock = 0; -static unsigned int ww, wh; +void event_button_press(xcb_generic_event_t *ev) { + xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; -static Display *d; -static XButtonEvent mouse; -static Window root; + ev_vals[0] = XCB_STACK_MODE_ABOVE; + xcb_configure_window(dpy, e->child, XCB_CONFIG_WINDOW_STACK_MODE, ev_vals); -static void (*events[LASTEvent])(XEvent *e) = { - [ButtonPress] = button_press, - [ButtonRelease] = button_release, - [ConfigureRequest] = configure_request, - [KeyPress] = key_press, - [MapRequest] = map_request, - [DestroyNotify] = notify_destroy, - [EnterNotify] = notify_enter, - [MotionNotify] = notify_motion -}; - -#include "config.h" - -void win_focus(client *c) { - cur = c; - XSetInputFocus(d, cur->w, RevertToParent, CurrentTime); + xcb_grab_pointer(dpy, 0, root, XCB_EVENT_MASK_BUTTON_RELEASE | + XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION_HINT, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE, + XCB_CURRENT_TIME); } -void notify_destroy(XEvent *e) { - win_del(e->xdestroywindow.window); - - if (list) win_focus(list->prev); +void event_button_release(xcb_generic_event_t *ev) { + xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); } -void notify_enter(XEvent *e) { - while(XCheckTypedEvent(d, EnterNotify, e)); +void event_configure_request(xcb_generic_event_t *ev) { + xcb_configure_request_event_t *e = (xcb_configure_request_event_t *)ev; + uint32_t values[7]; + int8_t i = -1; - for win if (c->w == e->xcrossing.window) win_focus(c); + if (e->value_mask & XCB_CONFIG_WINDOW_X) { + e->value_mask |= XCB_CONFIG_WINDOW_X; + values[++i] = e->x; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_Y) { + e->value_mask |= XCB_CONFIG_WINDOW_Y; + values[++i] = e->y; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { + e->value_mask |= XCB_CONFIG_WINDOW_WIDTH; + values[++i] = e->width; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { + e->value_mask |= XCB_CONFIG_WINDOW_HEIGHT; + values[++i] = e->height; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { + e->value_mask |= XCB_CONFIG_WINDOW_SIBLING; + values[++i] = e->sibling; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { + e->value_mask |= XCB_CONFIG_WINDOW_STACK_MODE; + values[++i] = e->stack_mode; + } + + if (i != -1) { + xcb_configure_window(dpy, e->window, e->value_mask, values); + xcb_flush(dpy); + } } -void notify_motion(XEvent *e) { - if (!mouse.subwindow || cur->f) return; - - while(XCheckTypedEvent(d, MotionNotify, e)); - - int xd = e->xbutton.x_root - mouse.x_root; - int yd = e->xbutton.y_root - mouse.y_root; - - XMoveResizeWindow(d, mouse.subwindow, - wx + (mouse.button == 1 ? xd : 0), - wy + (mouse.button == 1 ? yd : 0), - MAX(1, ww + (mouse.button == 3 ? xd : 0)), - MAX(1, wh + (mouse.button == 3 ? yd : 0))); +void event_key_press(xcb_generic_event_t *ev) { + xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev; } -void key_press(XEvent *e) { - KeySym keysym = XkbKeycodeToKeysym(d, e->xkey.keycode, 0, 0); +void event_notify_create(xcb_generic_event_t *ev) { + xcb_create_notify_event_t *e = (xcb_create_notify_event_t *)ev; - for (unsigned int i=0; i < sizeof(keys)/sizeof(*keys); ++i) - if (keys[i].keysym == keysym && - mod_clean(keys[i].mod) == mod_clean(e->xkey.state)) - keys[i].function(keys[i].arg); + ev_vals[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; + ev_vals[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + + xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, ev_vals); + xcb_map_window(dpy, e->window); + xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_PARENT, + e->window, XCB_CURRENT_TIME); } -void button_press(XEvent *e) { - if (!e->xbutton.subwindow) return; - - win_size(e->xbutton.subwindow, &wx, &wy, &ww, &wh); - XRaiseWindow(d, e->xbutton.subwindow); - mouse = e->xbutton; +void event_notify_destroy(xcb_generic_event_t *ev) { + xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *)ev; } -void button_release(XEvent *e) { - mouse.subwindow = 0; +void event_notify_enter(xcb_generic_event_t *ev) { + xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; + + xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_PARENT, + e->event, XCB_CURRENT_TIME); } -void win_add(Window w) { - client *c; +void event_notify_motion(xcb_generic_event_t *ev) { + xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *)ev; +} - if (!(c = (client *) calloc(1, sizeof(client)))) +void win_add(xcb_window_t win) { + +} + +void init_wm(void) { + dpy = xcb_connect(NULL, NULL); + + if (xcb_connection_has_error(dpy)) { + printf("error: Failed to start sowm\n"); exit(1); - - c->w = w; - - if (list) { - list->prev->next = c; - c->prev = list->prev; - list->prev = c; - c->next = list; - - } else { - list = c; - list->prev = list->next = list; } - ws_save(ws); + scr = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data; + + if (!scr) { + printf("error: Failed to assign screen number\n"); + xcb_disconnect(dpy); + exit(1); + } + + root = scr->root; + + ev_vals[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + xcb_change_window_attributes_checked(dpy, root, XCB_CW_EVENT_MASK, ev_vals); + xcb_flush(dpy); } -void win_del(Window w) { - client *x = 0; +void init_input(void) { + xcb_grab_key(dpy, 1, root, XCB_MOD_MASK_4, XCB_NO_SYMBOL, + XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); - for win if (c->w == w) x = c; + xcb_grab_button(dpy, 0, root, XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, + XCB_GRAB_MODE_ASYNC, root, XCB_NONE, 1, XCB_MOD_MASK_4); - if (!list || !x) return; - if (x->prev == x) list = 0; - if (list == x) list = x->next; - if (x->next) x->next->prev = x->prev; - if (x->prev) x->prev->next = x->next; + xcb_grab_button(dpy, 0, root, XCB_EVENT_MASK_BUTTON_PRESS | + XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, + XCB_GRAB_MODE_ASYNC, root, XCB_NONE, 3, XCB_MOD_MASK_4); - free(x); - ws_save(ws); + xcb_flush(dpy); } -void win_kill(const Arg arg) { - if (cur) XKillClient(d, cur->w); -} +void run_loop(void) { + xcb_generic_event_t *ev; -void win_center(const Arg arg) { - if (!cur) return; + for (;;) { + ev = xcb_wait_for_event(dpy); - win_size(cur->w, &(int){0}, &(int){0}, &ww, &wh); - XMoveWindow(d, cur->w, (sw - ww) / 2, (sh - wh) / 2); -} - -void win_fs(const Arg arg) { - if (!cur) return; - - if ((cur->f = cur->f ? 0 : 1)) { - win_size(cur->w, &cur->wx, &cur->wy, &cur->ww, &cur->wh); - XMoveResizeWindow(d, cur->w, 0, 0, sw, sh); - - } else { - XMoveResizeWindow(d, cur->w, cur->wx, cur->wy, cur->ww, cur->wh); + if (events[EVENT_MASK(ev->response_type)]) { + events[EVENT_MASK(ev->response_type)](ev); + xcb_flush(dpy); + } + free(ev); } } -void win_to_ws(const Arg arg) { - int tmp = ws; - - if (arg.i == tmp) return; - - ws_sel(arg.i); - win_add(cur->w); - ws_save(arg.i); - - ws_sel(tmp); - win_del(cur->w); - XUnmapWindow(d, cur->w); - ws_save(tmp); - - if (list) win_focus(list); -} - -void win_prev(const Arg arg) { - if (!cur) return; - - XRaiseWindow(d, cur->prev->w); - win_focus(cur->prev); -} - -void win_next(const Arg arg) { - if (!cur) return; - - XRaiseWindow(d, cur->next->w); - win_focus(cur->next); -} - -void ws_go(const Arg arg) { - int tmp = ws; - - if (arg.i == ws) return; - - ws_save(ws); - ws_sel(arg.i); - - for win XMapWindow(d, c->w); - - ws_sel(tmp); - - for win XUnmapWindow(d, c->w); - - ws_sel(arg.i); - - if (list) win_focus(list); else cur = 0; -} - -void configure_request(XEvent *e) { - XConfigureRequestEvent *ev = &e->xconfigurerequest; - - XConfigureWindow(d, ev->window, ev->value_mask, &(XWindowChanges) { - .x = ev->x, - .y = ev->y, - .width = ev->width, - .height = ev->height, - .sibling = ev->above, - .stack_mode = ev->detail - }); -} - -void map_request(XEvent *e) { - Window w = e->xmaprequest.window; - - XSelectInput(d, w, StructureNotifyMask|EnterWindowMask); - win_size(w, &wx, &wy, &ww, &wh); - win_add(w); - cur = list->prev; - - if (wx + wy == 0) win_center((Arg){0}); - - XMapWindow(d, w); - win_focus(list->prev); -} - -void run(const Arg arg) { - if (fork()) return; - if (d) close(ConnectionNumber(d)); - - setsid(); - execvp((char*)arg.com[0], (char**)arg.com); -} - -void input_grab(Window root) { - unsigned int i, j, modifiers[] = {0, LockMask, numlock, numlock|LockMask}; - XModifierKeymap *modmap = XGetModifierMapping(d); - KeyCode code; - - for (i = 0; i < 8; i++) - for (int k = 0; k < modmap->max_keypermod; k++) - if (modmap->modifiermap[i * modmap->max_keypermod + k] - == XKeysymToKeycode(d, 0xff7f)) - numlock = (1 << i); - - for (i = 0; i < sizeof(keys)/sizeof(*keys); i++) - if ((code = XKeysymToKeycode(d, keys[i].keysym))) - for (j = 0; j < sizeof(modifiers)/sizeof(*modifiers); j++) - XGrabKey(d, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); - - for (i = 1; i < 4; i += 2) - for (j = 0; j < sizeof(modifiers)/sizeof(*modifiers); j++) - XGrabButton(d, i, MOD | modifiers[j], root, True, - ButtonPressMask|ButtonReleaseMask|PointerMotionMask, - GrabModeAsync, GrabModeAsync, 0, 0); - - XFreeModifiermap(modmap); -} - -int main(void) { - XEvent ev; - - if (!(d = XOpenDisplay(0))) exit(1); +int main(int argc, char *argv[]) { + /* unused */ + (void) argc; + (void) argv; + /* we don't want sigchld */ signal(SIGCHLD, SIG_IGN); - XSetErrorHandler(xerror); - int s = DefaultScreen(d); - root = RootWindow(d, s); - sw = XDisplayWidth(d, s); - sh = XDisplayHeight(d, s); + init_wm(); + init_input(); + run_loop(); - XSelectInput(d, root, SubstructureRedirectMask); - XDefineCursor(d, root, XCreateFontCursor(d, 68)); - input_grab(root); - - while (1 && !XNextEvent(d, &ev)) // 1 && will forever be here. - if (events[ev.type]) events[ev.type](&ev); + return 0; } diff --git a/sowm.h b/sowm.h index 455ed93..026552a 100644 --- a/sowm.h +++ b/sowm.h @@ -1,57 +1,47 @@ -#include +#define _POSIX_C_SOURCE 200809L +#include -#define win (client *t=0, *c=list; c && t!=list->prev; t=c, c=c->next) -#define ws_save(W) ws_list[W] = list -#define ws_sel(W) list = ws_list[ws = W] -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - -#define win_size(W, gx, gy, gw, gh) \ - XGetGeometry(d, W, &(Window){0}, gx, gy, gw, gh, \ - &(unsigned int){0}, &(unsigned int){0}) - -// Taken from DWM. Many thanks. https://git.suckless.org/dwm -#define mod_clean(mask) (mask & ~(numlock|LockMask) & \ - (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) - -typedef struct { - const char** com; - const int i; - const Window w; -} Arg; - -struct key { - unsigned int mod; - KeySym keysym; - void (*function)(const Arg arg); - const Arg arg; +struct wconf { + int16_t x; + int16_t y; + uint16_t width; + uint16_t height; + uint8_t stack_mode; + xcb_window_t sibling; }; -typedef struct client { - struct client *next, *prev; - int f, wx, wy; - unsigned int ww, wh; - Window w; -} client; +xcb_connection_t *dpy; +xcb_screen_t *scr; +xcb_drawable_t root; -void button_press(XEvent *e); -void button_release(XEvent *e); -void configure_request(XEvent *e); -void input_grab(Window root); -void key_press(XEvent *e); -void map_request(XEvent *e); -void notify_destroy(XEvent *e); -void notify_enter(XEvent *e); -void notify_motion(XEvent *e); -void run(const Arg arg); -void win_add(Window w); -void win_center(const Arg arg); -void win_del(Window w); -void win_fs(const Arg arg); -void win_focus(client *c); -void win_kill(const Arg arg); -void win_prev(const Arg arg); -void win_next(const Arg arg); -void win_to_ws(const Arg arg); -void ws_go(const Arg arg); +uint32_t ev_vals[3]; -static int xerror() { return 0; } +/* xcb event with the largest value */ +#define XCB_LAST_EVENT XCB_GET_MODIFIER_MAPPING +#define EVENT_MASK(e) (((e) & ~0x80)) + +void init_wm(void); +void init_input(void); +void run_loop(void); + +void event_button_press(xcb_generic_event_t *ev); +void event_button_release(xcb_generic_event_t *ev); +void event_configure_request(xcb_generic_event_t *ev); +void event_key_press(xcb_generic_event_t *ev); +void event_notify_create(xcb_generic_event_t *ev); +void event_notify_destroy(xcb_generic_event_t *ev); +void event_notify_enter(xcb_generic_event_t *ev); +void event_notify_motion(xcb_generic_event_t *ev); + +void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { + [XCB_BUTTON_PRESS] = event_button_press, + [XCB_BUTTON_RELEASE] = event_button_release, + [XCB_CONFIGURE_REQUEST] = event_configure_request, + [XCB_KEY_PRESS] = event_key_press, + [XCB_CREATE_NOTIFY] = event_notify_create, + [XCB_DESTROY_NOTIFY] = event_notify_destroy, + [XCB_ENTER_NOTIFY] = event_notify_enter, + [XCB_MOTION_NOTIFY] = event_notify_motion +}; + +void win_add(xcb_window_t win);