From 1a4c655b9d09a9ee42f6e0fa7470d1f07319892e Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sat, 11 Jul 2020 11:31:30 +0300 Subject: [PATCH 01/22] 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 | 328 +++++++++++++++++---------------------------------- sowm.h | 100 +++++++--------- 7 files changed, 169 insertions(+), 466 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: -all: sowm +PREFIX = /usr/local + +ALL_WARN = -Wall -Wextra -pedantic -Wmissing-prototypes -Wstrict-prototypes +ALL_CFLAGS = $(CFLAGS) $(CPPFLAGS) -std=c99 $(ALL_WARN) +ALL_LDFLAGS = $(LDFLAGS) -lxcb -config.h: - cp config.def.h config.h +CC = cc + +all: sowm -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 "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; - -static Display *d; -static XButtonEvent mouse; -static Window root; - -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); -} -void notify_destroy(XEvent *e) { - win_del(e->xdestroywindow.window); - - if (list) win_focus(list->prev); -} - -void notify_enter(XEvent *e) { - while(XCheckTypedEvent(d, EnterNotify, e)); - - for win if (c->w == e->xcrossing.window) win_focus(c); -} +#include -void notify_motion(XEvent *e) { - if (!mouse.subwindow || cur->f) return; +#include "sowm.h" - while(XCheckTypedEvent(d, MotionNotify, e)); +void event_button_press(xcb_generic_event_t *ev) { + xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; - int xd = e->xbutton.x_root - mouse.x_root; - int yd = e->xbutton.y_root - mouse.y_root; + ev_vals[0] = XCB_STACK_MODE_ABOVE; + xcb_configure_window(dpy, e->child, XCB_CONFIG_WINDOW_STACK_MODE, ev_vals); - 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))); + 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 key_press(XEvent *e) { - KeySym keysym = XkbKeycodeToKeysym(d, e->xkey.keycode, 0, 0); - - 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); +void event_button_release(xcb_generic_event_t *ev) { + xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); } -void button_press(XEvent *e) { - if (!e->xbutton.subwindow) return; +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; - win_size(e->xbutton.subwindow, &wx, &wy, &ww, &wh); - XRaiseWindow(d, e->xbutton.subwindow); - mouse = e->xbutton; -} + if (e->value_mask & XCB_CONFIG_WINDOW_X) { + e->value_mask |= XCB_CONFIG_WINDOW_X; + values[++i] = e->x; + } -void button_release(XEvent *e) { - mouse.subwindow = 0; -} + if (e->value_mask & XCB_CONFIG_WINDOW_Y) { + e->value_mask |= XCB_CONFIG_WINDOW_Y; + values[++i] = e->y; + } -void win_add(Window w) { - client *c; + if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { + e->value_mask |= XCB_CONFIG_WINDOW_WIDTH; + values[++i] = e->width; + } - if (!(c = (client *) calloc(1, sizeof(client)))) - exit(1); + if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { + e->value_mask |= XCB_CONFIG_WINDOW_HEIGHT; + values[++i] = e->height; + } - c->w = w; + if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { + e->value_mask |= XCB_CONFIG_WINDOW_SIBLING; + values[++i] = e->sibling; + } - if (list) { - list->prev->next = c; - c->prev = list->prev; - list->prev = c; - c->next = list; + if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { + e->value_mask |= XCB_CONFIG_WINDOW_STACK_MODE; + values[++i] = e->stack_mode; + } - } else { - list = c; - list->prev = list->next = list; + if (i != -1) { + xcb_configure_window(dpy, e->window, e->value_mask, values); + xcb_flush(dpy); } - - ws_save(ws); } -void win_del(Window w) { - client *x = 0; - - for win if (c->w == w) x = c; - - 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; - - free(x); - ws_save(ws); +void event_key_press(xcb_generic_event_t *ev) { + xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev; } -void win_kill(const Arg arg) { - if (cur) XKillClient(d, cur->w); -} +void event_notify_create(xcb_generic_event_t *ev) { + xcb_create_notify_event_t *e = (xcb_create_notify_event_t *)ev; -void win_center(const Arg arg) { - if (!cur) return; + ev_vals[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; + ev_vals[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - win_size(cur->w, &(int){0}, &(int){0}, &ww, &wh); - XMoveWindow(d, cur->w, (sw - ww) / 2, (sh - wh) / 2); + 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 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); - } +void event_notify_destroy(xcb_generic_event_t *ev) { + xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *)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); +void event_notify_enter(xcb_generic_event_t *ev) { + xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; - ws_sel(tmp); - win_del(cur->w); - XUnmapWindow(d, cur->w); - ws_save(tmp); - - if (list) win_focus(list); + xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_PARENT, + e->event, XCB_CURRENT_TIME); } -void win_prev(const Arg arg) { - if (!cur) return; - - XRaiseWindow(d, cur->prev->w); - win_focus(cur->prev); +void event_notify_motion(xcb_generic_event_t *ev) { + xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *)ev; } -void win_next(const Arg arg) { - if (!cur) return; +void win_add(xcb_window_t win) { - 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); +void init_wm(void) { + dpy = xcb_connect(NULL, NULL); - ws_sel(tmp); + if (xcb_connection_has_error(dpy)) { + printf("error: Failed to start sowm\n"); + exit(1); + } - for win XUnmapWindow(d, c->w); + scr = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data; - ws_sel(arg.i); + if (!scr) { + printf("error: Failed to assign screen number\n"); + xcb_disconnect(dpy); + exit(1); + } - if (list) win_focus(list); else cur = 0; -} + root = scr->root; -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 - }); + 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 map_request(XEvent *e) { - Window w = e->xmaprequest.window; +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); - XSelectInput(d, w, StructureNotifyMask|EnterWindowMask); - win_size(w, &wx, &wy, &ww, &wh); - win_add(w); - cur = list->prev; + 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 (wx + wy == 0) win_center((Arg){0}); + 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); - XMapWindow(d, w); - win_focus(list->prev); + xcb_flush(dpy); } -void run(const Arg arg) { - if (fork()) return; - if (d) close(ConnectionNumber(d)); +void run_loop(void) { + xcb_generic_event_t *ev; - setsid(); - execvp((char*)arg.com[0], (char**)arg.com); -} + for (;;) { + ev = xcb_wait_for_event(dpy); -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); + if (events[EVENT_MASK(ev->response_type)]) { + events[EVENT_MASK(ev->response_type)](ev); + xcb_flush(dpy); + } + free(ev); + } } -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); - XSelectInput(d, root, SubstructureRedirectMask); - XDefineCursor(d, root, XCreateFontCursor(d, 68)); - input_grab(root); + init_wm(); + init_input(); + run_loop(); - 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 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; +#define _POSIX_C_SOURCE 200809L +#include + +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; - -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); - -static int xerror() { return 0; } +xcb_connection_t *dpy; +xcb_screen_t *scr; +xcb_drawable_t root; + +uint32_t ev_vals[3]; + +/* 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); From 04b35c3f5e8b13d50ad4db361efebda9a939831e Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sat, 11 Jul 2020 11:45:17 +0300 Subject: [PATCH 02/22] sowm.h: Fix mixed indentation --- sowm.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sowm.h b/sowm.h index 026552a..183e33c 100644 --- a/sowm.h +++ b/sowm.h @@ -2,12 +2,12 @@ #include struct wconf { - int16_t x; + int16_t x; int16_t y; - uint16_t width; + uint16_t width; uint16_t height; - uint8_t stack_mode; - xcb_window_t sibling; + uint8_t stack_mode; + xcb_window_t sibling; }; xcb_connection_t *dpy; From 5c998e05f416ac6802535787b378446991d7fade Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sat, 11 Jul 2020 11:46:20 +0300 Subject: [PATCH 03/22] sowm.h: Drop XCB_LAST_EVENT --- sowm.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/sowm.h b/sowm.h index 183e33c..d70c9eb 100644 --- a/sowm.h +++ b/sowm.h @@ -16,8 +16,6 @@ xcb_drawable_t root; uint32_t ev_vals[3]; -/* xcb event with the largest value */ -#define XCB_LAST_EVENT XCB_GET_MODIFIER_MAPPING #define EVENT_MASK(e) (((e) & ~0x80)) void init_wm(void); From a743d166fee91d324f444149ff5cda5f98072513 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sat, 11 Jul 2020 11:50:54 +0300 Subject: [PATCH 04/22] sowm: Shuffle declarations around --- sowm.h => event.h | 22 ---------------------- sowm.c | 15 ++++++++++++++- types.h | 10 ++++++++++ 3 files changed, 24 insertions(+), 23 deletions(-) rename sowm.h => event.h (72%) create mode 100644 types.h diff --git a/sowm.h b/event.h similarity index 72% rename from sowm.h rename to event.h index d70c9eb..83e36c1 100644 --- a/sowm.h +++ b/event.h @@ -1,27 +1,7 @@ -#define _POSIX_C_SOURCE 200809L #include -struct wconf { - int16_t x; - int16_t y; - uint16_t width; - uint16_t height; - uint8_t stack_mode; - xcb_window_t sibling; -}; - -xcb_connection_t *dpy; -xcb_screen_t *scr; -xcb_drawable_t root; - -uint32_t ev_vals[3]; - #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); @@ -41,5 +21,3 @@ void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { [XCB_ENTER_NOTIFY] = event_notify_enter, [XCB_MOTION_NOTIFY] = event_notify_motion }; - -void win_add(xcb_window_t win); diff --git a/sowm.c b/sowm.c index 9983f00..63b4eb1 100644 --- a/sowm.c +++ b/sowm.c @@ -5,7 +5,20 @@ #include -#include "sowm.h" +#include "event.h" +#include "types.h" + +static xcb_connection_t *dpy; +static xcb_screen_t *scr; +static xcb_drawable_t root; + +/* required for button press, motion and release */ +static uint32_t ev_vals[3]; + +static void init_wm(void); +static void init_input(void); +static void run_loop(void); +static void win_add(xcb_window_t win); void event_button_press(xcb_generic_event_t *ev) { xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; diff --git a/types.h b/types.h new file mode 100644 index 0000000..38a9d4e --- /dev/null +++ b/types.h @@ -0,0 +1,10 @@ +#include + +struct wconf { + int16_t x; + int16_t y; + uint16_t width; + uint16_t height; + xcb_window_t sibling; + uint8_t stack_mode; +}; From 2e4015f9884f3893d1890aa5a8fb22c48963df83 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sat, 11 Jul 2020 12:16:47 +0300 Subject: [PATCH 05/22] sowm: Add back LICENSE/README files --- LICENSE | 21 +++++++++++++++++++++ README | 3 +++ 2 files changed, 24 insertions(+) create mode 100644 LICENSE create mode 100644 README diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..acdb5b5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019-2020 Dylan Araps + +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/README b/README new file mode 100644 index 0000000..58517a7 --- /dev/null +++ b/README @@ -0,0 +1,3 @@ +SOWM (Simple Opinionated Window Manager) +________________________________________________________________________________ + From 3e711082e76dc52b47c89f5f82a7c670e5a1efb9 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sat, 11 Jul 2020 14:47:07 +0300 Subject: [PATCH 06/22] sowm2: Resizing and moving --- sowm.c | 162 +++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 118 insertions(+), 44 deletions(-) diff --git a/sowm.c b/sowm.c index 63b4eb1..c85ef03 100644 --- a/sowm.c +++ b/sowm.c @@ -13,7 +13,10 @@ static xcb_screen_t *scr; static xcb_drawable_t root; /* required for button press, motion and release */ -static uint32_t ev_vals[3]; +static uint32_t motion_vals[3]; +static xcb_window_t motion_win; +static xcb_get_geometry_reply_t *motion_geom; +static int is_motion = 0; static void init_wm(void); static void init_input(void); @@ -23,17 +26,43 @@ static void win_add(xcb_window_t win); void event_button_press(xcb_generic_event_t *ev) { xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; - ev_vals[0] = XCB_STACK_MODE_ABOVE; - xcb_configure_window(dpy, e->child, XCB_CONFIG_WINDOW_STACK_MODE, ev_vals); + if (e->child == root) { + return; + } + + motion_vals[0] = XCB_STACK_MODE_ABOVE; + motion_win = e->child; + is_motion = 1; + + xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_STACK_MODE, + motion_vals); + + motion_geom = xcb_get_geometry_reply(dpy, + xcb_get_geometry(dpy, motion_win), NULL); + + /* resize */ + if (e->detail == 1) { + xcb_warp_pointer(dpy, XCB_NONE, motion_win, 0, 0, 0, 0, 1, 1); + motion_vals[2] = 1; + + /* move */ + } else { + xcb_warp_pointer(dpy, XCB_NONE, motion_win, 0, 0, 0, 0, 1, 1); + motion_vals[2] = 3; + } 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); + + xcb_flush(dpy); } void event_button_release(xcb_generic_event_t *ev) { xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); + xcb_flush(dpy); + is_motion = 0; } void event_configure_request(xcb_generic_event_t *ev) { @@ -41,37 +70,43 @@ void event_configure_request(xcb_generic_event_t *ev) { uint32_t values[7]; int8_t i = -1; - 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) { + if (e->value_mask & XCB_CONFIG_WINDOW_X) { + e->value_mask |= XCB_CONFIG_WINDOW_X; + i++; + values[i] = e->x; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_Y) { + e->value_mask |= XCB_CONFIG_WINDOW_Y; + i++; + values[i] = e->y; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { + e->value_mask |= XCB_CONFIG_WINDOW_WIDTH; + i++; + values[i] = e->width; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { + e->value_mask |= XCB_CONFIG_WINDOW_HEIGHT; + i++; + values[i] = e->height; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { + e->value_mask |= XCB_CONFIG_WINDOW_SIBLING; + i++; + values[i] = e->sibling; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { + e->value_mask |= XCB_CONFIG_WINDOW_STACK_MODE; + i++; + values[i] = e->stack_mode; + } + + if (i != -1) { xcb_configure_window(dpy, e->window, e->value_mask, values); xcb_flush(dpy); } @@ -83,14 +118,13 @@ void event_key_press(xcb_generic_event_t *ev) { void event_notify_create(xcb_generic_event_t *ev) { xcb_create_notify_event_t *e = (xcb_create_notify_event_t *)ev; + uint32_t values[2]; - ev_vals[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; - ev_vals[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; + values[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, ev_vals); + xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, values); xcb_map_window(dpy, e->window); - xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_PARENT, - e->window, XCB_CURRENT_TIME); } void event_notify_destroy(xcb_generic_event_t *ev) { @@ -100,12 +134,52 @@ void event_notify_destroy(xcb_generic_event_t *ev) { 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, + if (e->event == root || is_motion) { + return; + } + + xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, e->event, XCB_CURRENT_TIME); + + xcb_flush(dpy); } void event_notify_motion(xcb_generic_event_t *ev) { - xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *)ev; + xcb_query_pointer_reply_t *ptr; + + ptr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), 0); + + /* move */ + if (motion_vals[2] == 1) { + motion_geom = xcb_get_geometry_reply(dpy, + xcb_get_geometry(dpy, motion_win), NULL); + + motion_vals[0] = + (ptr->root_x + motion_geom->width > scr->width_in_pixels)? + (scr->width_in_pixels - motion_geom->width):ptr->root_x; + + motion_vals[1] = + (ptr->root_y + motion_geom->height > scr->height_in_pixels)? + (scr->height_in_pixels - motion_geom->height):ptr->root_y; + + xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_X | + XCB_CONFIG_WINDOW_Y, motion_vals); + + xcb_flush(dpy); + + /* resize */ + } else if (motion_vals[2] == 3) { + motion_geom = xcb_get_geometry_reply(dpy, + xcb_get_geometry(dpy, motion_win), NULL); + + motion_vals[0] = ptr->root_x - motion_geom->x; + motion_vals[1] = ptr->root_y - motion_geom->y; + + xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_WIDTH | + XCB_CONFIG_WINDOW_HEIGHT, motion_vals); + + xcb_flush(dpy); + } } void win_add(xcb_window_t win) { @@ -113,6 +187,7 @@ void win_add(xcb_window_t win) { } void init_wm(void) { + uint32_t values[2]; dpy = xcb_connect(NULL, NULL); if (xcb_connection_has_error(dpy)) { @@ -130,8 +205,8 @@ void init_wm(void) { root = scr->root; - ev_vals[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - xcb_change_window_attributes_checked(dpy, root, XCB_CW_EVENT_MASK, ev_vals); + values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + xcb_change_window_attributes_checked(dpy, root, XCB_CW_EVENT_MASK, values); xcb_flush(dpy); } @@ -158,7 +233,6 @@ void run_loop(void) { if (events[EVENT_MASK(ev->response_type)]) { events[EVENT_MASK(ev->response_type)](ev); - xcb_flush(dpy); } free(ev); } From b5eca40b64ae2dda71d78ed74f222f24e96a8471 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 21 Jul 2020 09:18:05 +0300 Subject: [PATCH 07/22] rewrite --- event.h | 23 ----- sowm.c | 231 +++++++-------------------------------------- sowm2.c | 285 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ types.h | 10 -- 4 files changed, 319 insertions(+), 230 deletions(-) delete mode 100644 event.h create mode 100644 sowm2.c delete mode 100644 types.h diff --git a/event.h b/event.h deleted file mode 100644 index 83e36c1..0000000 --- a/event.h +++ /dev/null @@ -1,23 +0,0 @@ -#include - -#define EVENT_MASK(e) (((e) & ~0x80)) - -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 -}; diff --git a/sowm.c b/sowm.c index c85ef03..18ecbac 100644 --- a/sowm.c +++ b/sowm.c @@ -5,189 +5,26 @@ #include -#include "event.h" -#include "types.h" - static xcb_connection_t *dpy; static xcb_screen_t *scr; -static xcb_drawable_t root; - -/* required for button press, motion and release */ -static uint32_t motion_vals[3]; -static xcb_window_t motion_win; -static xcb_get_geometry_reply_t *motion_geom; -static int is_motion = 0; static void init_wm(void); static void init_input(void); -static void run_loop(void); -static void win_add(xcb_window_t win); - -void event_button_press(xcb_generic_event_t *ev) { - xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; - - if (e->child == root) { - return; - } - - motion_vals[0] = XCB_STACK_MODE_ABOVE; - motion_win = e->child; - is_motion = 1; - - xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_STACK_MODE, - motion_vals); - - motion_geom = xcb_get_geometry_reply(dpy, - xcb_get_geometry(dpy, motion_win), NULL); - - /* resize */ - if (e->detail == 1) { - xcb_warp_pointer(dpy, XCB_NONE, motion_win, 0, 0, 0, 0, 1, 1); - motion_vals[2] = 1; - - /* move */ - } else { - xcb_warp_pointer(dpy, XCB_NONE, motion_win, 0, 0, 0, 0, 1, 1); - motion_vals[2] = 3; - } - - 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); - - xcb_flush(dpy); -} - -void event_button_release(xcb_generic_event_t *ev) { - xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); - xcb_flush(dpy); - is_motion = 0; -} - -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; - - if (e->value_mask & XCB_CONFIG_WINDOW_X) { - e->value_mask |= XCB_CONFIG_WINDOW_X; - i++; - values[i] = e->x; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_Y) { - e->value_mask |= XCB_CONFIG_WINDOW_Y; - i++; - values[i] = e->y; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { - e->value_mask |= XCB_CONFIG_WINDOW_WIDTH; - i++; - values[i] = e->width; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { - e->value_mask |= XCB_CONFIG_WINDOW_HEIGHT; - i++; - values[i] = e->height; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { - e->value_mask |= XCB_CONFIG_WINDOW_SIBLING; - i++; - values[i] = e->sibling; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { - e->value_mask |= XCB_CONFIG_WINDOW_STACK_MODE; - i++; - values[i] = e->stack_mode; - } - - if (i != -1) { - xcb_configure_window(dpy, e->window, e->value_mask, values); - xcb_flush(dpy); - } -} - -void event_key_press(xcb_generic_event_t *ev) { - xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev; -} -void event_notify_create(xcb_generic_event_t *ev) { - xcb_create_notify_event_t *e = (xcb_create_notify_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 */ +}; + +static void init_wm(void) { uint32_t values[2]; - values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; - values[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - - xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, values); - xcb_map_window(dpy, e->window); -} - -void event_notify_destroy(xcb_generic_event_t *ev) { - xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *)ev; -} - -void event_notify_enter(xcb_generic_event_t *ev) { - xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; - - if (e->event == root || is_motion) { - return; - } - - xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, - e->event, XCB_CURRENT_TIME); - - xcb_flush(dpy); -} - -void event_notify_motion(xcb_generic_event_t *ev) { - xcb_query_pointer_reply_t *ptr; - - ptr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), 0); - - /* move */ - if (motion_vals[2] == 1) { - motion_geom = xcb_get_geometry_reply(dpy, - xcb_get_geometry(dpy, motion_win), NULL); - - motion_vals[0] = - (ptr->root_x + motion_geom->width > scr->width_in_pixels)? - (scr->width_in_pixels - motion_geom->width):ptr->root_x; - - motion_vals[1] = - (ptr->root_y + motion_geom->height > scr->height_in_pixels)? - (scr->height_in_pixels - motion_geom->height):ptr->root_y; - - xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_X | - XCB_CONFIG_WINDOW_Y, motion_vals); - - xcb_flush(dpy); - - /* resize */ - } else if (motion_vals[2] == 3) { - motion_geom = xcb_get_geometry_reply(dpy, - xcb_get_geometry(dpy, motion_win), NULL); - - motion_vals[0] = ptr->root_x - motion_geom->x; - motion_vals[1] = ptr->root_y - motion_geom->y; - - xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_WIDTH | - XCB_CONFIG_WINDOW_HEIGHT, motion_vals); - - xcb_flush(dpy); - } -} - -void win_add(xcb_window_t win) { - -} - -void init_wm(void) { - uint32_t values[2]; dpy = xcb_connect(NULL, NULL); if (xcb_connection_has_error(dpy)) { @@ -203,42 +40,33 @@ void init_wm(void) { exit(1); } - root = scr->root; - values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - xcb_change_window_attributes_checked(dpy, root, XCB_CW_EVENT_MASK, values); + + xcb_change_window_attributes_checked(dpy, scr->root, + XCB_CW_EVENT_MASK, values); + xcb_flush(dpy); } -void init_input(void) { - xcb_grab_key(dpy, 1, root, XCB_MOD_MASK_4, XCB_NO_SYMBOL, +static void init_input(void) { + xcb_grab_key(dpy, 1, scr->root, XCB_MOD_MASK_4, XCB_NO_SYMBOL, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); - xcb_grab_button(dpy, 0, root, XCB_EVENT_MASK_BUTTON_PRESS | + xcb_grab_button(dpy, 0, scr->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); + XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 1, XCB_MOD_MASK_4); - xcb_grab_button(dpy, 0, root, XCB_EVENT_MASK_BUTTON_PRESS | + xcb_grab_button(dpy, 0, scr->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); + XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 3, XCB_MOD_MASK_4); xcb_flush(dpy); } -void run_loop(void) { +int main(int argc, char **argv) { xcb_generic_event_t *ev; + unsigned int ev_type; - for (;;) { - ev = xcb_wait_for_event(dpy); - - if (events[EVENT_MASK(ev->response_type)]) { - events[EVENT_MASK(ev->response_type)](ev); - } - free(ev); - } -} - -int main(int argc, char *argv[]) { /* unused */ (void) argc; (void) argv; @@ -248,7 +76,16 @@ int main(int argc, char *argv[]) { init_wm(); init_input(); - run_loop(); + + while ((ev = xcb_wait_for_event(dpy))) { + ev_type = ev->response_type & ~0x80; + + if (events[ev_type]) { + events[ev_type](ev); + } + + free(ev); + } return 0; } diff --git a/sowm2.c b/sowm2.c new file mode 100644 index 0000000..21953b6 --- /dev/null +++ b/sowm2.c @@ -0,0 +1,285 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include + +#include + +#include "event.h" +#include "types.h" + +static xcb_connection_t *dpy; +static xcb_screen_t *scr; +static xcb_drawable_t root; + +/* required for button press, motion and release */ +static uint32_t motion_vals[3]; +static xcb_window_t motion_win; +static xcb_get_geometry_reply_t *motion_geom; +static int is_motion = 0; + +static void init_wm(void); +static void init_input(void); +static void run_loop(void); +static void win_add(xcb_window_t win); + +void event_button_press(xcb_generic_event_t *ev) { + xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; + + if (e->child == root) { + return; + } + + motion_vals[0] = XCB_STACK_MODE_ABOVE; + motion_win = e->child; + is_motion = 1; + + xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_STACK_MODE, + motion_vals); + + motion_geom = xcb_get_geometry_reply(dpy, + xcb_get_geometry(dpy, motion_win), NULL); + + /* resize */ + if (e->detail == 1) { + xcb_warp_pointer(dpy, XCB_NONE, motion_win, 0, 0, 0, 0, 1, 1); + motion_vals[2] = 1; + + /* move */ + } else { + xcb_warp_pointer(dpy, XCB_NONE, motion_win, 0, 0, 0, 0, 1, 1); + motion_vals[2] = 3; + } + + 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); + + xcb_flush(dpy); +} + +void event_button_release(xcb_generic_event_t *ev) { + xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); + xcb_flush(dpy); + is_motion = 0; +} + +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; + + if (e->value_mask & XCB_CONFIG_WINDOW_X) { + e->value_mask |= XCB_CONFIG_WINDOW_X; + i++; + values[i] = e->x; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_Y) { + e->value_mask |= XCB_CONFIG_WINDOW_Y; + i++; + values[i] = e->y; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { + e->value_mask |= XCB_CONFIG_WINDOW_WIDTH; + i++; + values[i] = e->width; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { + e->value_mask |= XCB_CONFIG_WINDOW_HEIGHT; + i++; + values[i] = e->height; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { + e->value_mask |= XCB_CONFIG_WINDOW_SIBLING; + i++; + values[i] = e->sibling; + } + + if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { + e->value_mask |= XCB_CONFIG_WINDOW_STACK_MODE; + i++; + values[i] = e->stack_mode; + } + + if (i != -1) { + xcb_configure_window(dpy, e->window, e->value_mask, values); + xcb_flush(dpy); + } +} + +void event_key_press(xcb_generic_event_t *ev) { + xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev; +} + +void event_notify_create(xcb_generic_event_t *ev) { + xcb_create_notify_event_t *e = (xcb_create_notify_event_t *)ev; + uint32_t values[2]; + + values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; + values[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + + xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, values); + xcb_map_window(dpy, e->window); +} + +void event_notify_destroy(xcb_generic_event_t *ev) { + xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *)ev; +} + +void event_notify_enter(xcb_generic_event_t *ev) { + xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; + + if (e->event == root || is_motion) { + return; + } + + xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, + e->event, XCB_CURRENT_TIME); + + xcb_flush(dpy); +} + +void event_notify_motion(xcb_generic_event_t *ev) { + xcb_query_pointer_reply_t *ptr; + + ptr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), 0); + + /* move */ + if (motion_vals[2] == 1) { + motion_geom = xcb_get_geometry_reply(dpy, + xcb_get_geometry(dpy, motion_win), NULL); + + motion_vals[0] = + (ptr->root_x + motion_geom->width > scr->width_in_pixels)? + (scr->width_in_pixels - motion_geom->width):ptr->root_x; + + motion_vals[1] = + (ptr->root_y + motion_geom->height > scr->height_in_pixels)? + (scr->height_in_pixels - motion_geom->height):ptr->root_y; + + xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_X | + XCB_CONFIG_WINDOW_Y, motion_vals); + + xcb_flush(dpy); + + /* resize */ + } else if (motion_vals[2] == 3) { + motion_geom = xcb_get_geometry_reply(dpy, + xcb_get_geometry(dpy, motion_win), NULL); + + motion_vals[0] = ptr->root_x - motion_geom->x; + motion_vals[1] = ptr->root_y - motion_geom->y; + + xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_WIDTH | + XCB_CONFIG_WINDOW_HEIGHT, motion_vals); + + xcb_flush(dpy); + } +} + +void win_add(xcb_window_t win) { + +} + +void init_wm(void) { + uint32_t values[2]; + dpy = xcb_connect(NULL, NULL); + + if (xcb_connection_has_error(dpy)) { + printf("error: Failed to start sowm\n"); + exit(1); + } + + 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; + + values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + xcb_change_window_attributes_checked(dpy, root, XCB_CW_EVENT_MASK, values); + xcb_flush(dpy); +} + +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); + + 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); + + 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); + + xcb_flush(dpy); +} + +void run_loop(void) { + xcb_generic_event_t *ev; + + for (;;) { + ev = xcb_wait_for_event(dpy); + + switch (EVENT_MASK(ev->response_type)) { + case XCB_BUTTON_PRESS: { + break; + } + + case XCB_BUTTON_RELEASE: { + break; + } + + case XCB_CONFIGURE_REQUEST: { + break; + } + + case XCB_KEY_PRESS: { + break; + } + + case XCB_CREATE_NOTIFY: { + break; + } + + case XCB_DESTROY_NOTIFY: { + break; + } + + case XCB_ENTER_NOTIFY: { + break; + } + + case XCB_MOTION_NOTIFY: { + break; + } + } + + free(ev); + } +} + +int main(int argc, char *argv[]) { + /* unused */ + (void) argc; + (void) argv; + + /* we don't want sigchld */ + signal(SIGCHLD, SIG_IGN); + + init_wm(); + init_input(); + run_loop(); + + return 0; +} diff --git a/types.h b/types.h deleted file mode 100644 index 38a9d4e..0000000 --- a/types.h +++ /dev/null @@ -1,10 +0,0 @@ -#include - -struct wconf { - int16_t x; - int16_t y; - uint16_t width; - uint16_t height; - xcb_window_t sibling; - uint8_t stack_mode; -}; From 196e8db5f6a2c05e2695d175e9ae7e3c43f0579b Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 21 Jul 2020 09:18:56 +0300 Subject: [PATCH 08/22] drop prior rewrite --- sowm2.c | 285 -------------------------------------------------------- 1 file changed, 285 deletions(-) delete mode 100644 sowm2.c diff --git a/sowm2.c b/sowm2.c deleted file mode 100644 index 21953b6..0000000 --- a/sowm2.c +++ /dev/null @@ -1,285 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include - -#include - -#include "event.h" -#include "types.h" - -static xcb_connection_t *dpy; -static xcb_screen_t *scr; -static xcb_drawable_t root; - -/* required for button press, motion and release */ -static uint32_t motion_vals[3]; -static xcb_window_t motion_win; -static xcb_get_geometry_reply_t *motion_geom; -static int is_motion = 0; - -static void init_wm(void); -static void init_input(void); -static void run_loop(void); -static void win_add(xcb_window_t win); - -void event_button_press(xcb_generic_event_t *ev) { - xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; - - if (e->child == root) { - return; - } - - motion_vals[0] = XCB_STACK_MODE_ABOVE; - motion_win = e->child; - is_motion = 1; - - xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_STACK_MODE, - motion_vals); - - motion_geom = xcb_get_geometry_reply(dpy, - xcb_get_geometry(dpy, motion_win), NULL); - - /* resize */ - if (e->detail == 1) { - xcb_warp_pointer(dpy, XCB_NONE, motion_win, 0, 0, 0, 0, 1, 1); - motion_vals[2] = 1; - - /* move */ - } else { - xcb_warp_pointer(dpy, XCB_NONE, motion_win, 0, 0, 0, 0, 1, 1); - motion_vals[2] = 3; - } - - 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); - - xcb_flush(dpy); -} - -void event_button_release(xcb_generic_event_t *ev) { - xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); - xcb_flush(dpy); - is_motion = 0; -} - -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; - - if (e->value_mask & XCB_CONFIG_WINDOW_X) { - e->value_mask |= XCB_CONFIG_WINDOW_X; - i++; - values[i] = e->x; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_Y) { - e->value_mask |= XCB_CONFIG_WINDOW_Y; - i++; - values[i] = e->y; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_WIDTH) { - e->value_mask |= XCB_CONFIG_WINDOW_WIDTH; - i++; - values[i] = e->width; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT) { - e->value_mask |= XCB_CONFIG_WINDOW_HEIGHT; - i++; - values[i] = e->height; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_SIBLING) { - e->value_mask |= XCB_CONFIG_WINDOW_SIBLING; - i++; - values[i] = e->sibling; - } - - if (e->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { - e->value_mask |= XCB_CONFIG_WINDOW_STACK_MODE; - i++; - values[i] = e->stack_mode; - } - - if (i != -1) { - xcb_configure_window(dpy, e->window, e->value_mask, values); - xcb_flush(dpy); - } -} - -void event_key_press(xcb_generic_event_t *ev) { - xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev; -} - -void event_notify_create(xcb_generic_event_t *ev) { - xcb_create_notify_event_t *e = (xcb_create_notify_event_t *)ev; - uint32_t values[2]; - - values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; - values[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - - xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, values); - xcb_map_window(dpy, e->window); -} - -void event_notify_destroy(xcb_generic_event_t *ev) { - xcb_destroy_notify_event_t *e = (xcb_destroy_notify_event_t *)ev; -} - -void event_notify_enter(xcb_generic_event_t *ev) { - xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; - - if (e->event == root || is_motion) { - return; - } - - xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, - e->event, XCB_CURRENT_TIME); - - xcb_flush(dpy); -} - -void event_notify_motion(xcb_generic_event_t *ev) { - xcb_query_pointer_reply_t *ptr; - - ptr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), 0); - - /* move */ - if (motion_vals[2] == 1) { - motion_geom = xcb_get_geometry_reply(dpy, - xcb_get_geometry(dpy, motion_win), NULL); - - motion_vals[0] = - (ptr->root_x + motion_geom->width > scr->width_in_pixels)? - (scr->width_in_pixels - motion_geom->width):ptr->root_x; - - motion_vals[1] = - (ptr->root_y + motion_geom->height > scr->height_in_pixels)? - (scr->height_in_pixels - motion_geom->height):ptr->root_y; - - xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_X | - XCB_CONFIG_WINDOW_Y, motion_vals); - - xcb_flush(dpy); - - /* resize */ - } else if (motion_vals[2] == 3) { - motion_geom = xcb_get_geometry_reply(dpy, - xcb_get_geometry(dpy, motion_win), NULL); - - motion_vals[0] = ptr->root_x - motion_geom->x; - motion_vals[1] = ptr->root_y - motion_geom->y; - - xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_WIDTH | - XCB_CONFIG_WINDOW_HEIGHT, motion_vals); - - xcb_flush(dpy); - } -} - -void win_add(xcb_window_t win) { - -} - -void init_wm(void) { - uint32_t values[2]; - dpy = xcb_connect(NULL, NULL); - - if (xcb_connection_has_error(dpy)) { - printf("error: Failed to start sowm\n"); - exit(1); - } - - 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; - - values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - xcb_change_window_attributes_checked(dpy, root, XCB_CW_EVENT_MASK, values); - xcb_flush(dpy); -} - -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); - - 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); - - 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); - - xcb_flush(dpy); -} - -void run_loop(void) { - xcb_generic_event_t *ev; - - for (;;) { - ev = xcb_wait_for_event(dpy); - - switch (EVENT_MASK(ev->response_type)) { - case XCB_BUTTON_PRESS: { - break; - } - - case XCB_BUTTON_RELEASE: { - break; - } - - case XCB_CONFIGURE_REQUEST: { - break; - } - - case XCB_KEY_PRESS: { - break; - } - - case XCB_CREATE_NOTIFY: { - break; - } - - case XCB_DESTROY_NOTIFY: { - break; - } - - case XCB_ENTER_NOTIFY: { - break; - } - - case XCB_MOTION_NOTIFY: { - break; - } - } - - free(ev); - } -} - -int main(int argc, char *argv[]) { - /* unused */ - (void) argc; - (void) argv; - - /* we don't want sigchld */ - signal(SIGCHLD, SIG_IGN); - - init_wm(); - init_input(); - run_loop(); - - return 0; -} From a047141f91979c0922105ae61150ea65b280da37 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 21 Jul 2020 09:20:46 +0300 Subject: [PATCH 09/22] stuff --- sowm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sowm.c b/sowm.c index 18ecbac..905f0e3 100644 --- a/sowm.c +++ b/sowm.c @@ -1,4 +1,3 @@ -#define _POSIX_C_SOURCE 200809L #include #include #include @@ -12,6 +11,7 @@ static void init_wm(void); static void init_input(void); void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { + [0] = 0, /* dummy for now */ /* [XCB_BUTTON_PRESS] = event_button_press, */ /* [XCB_BUTTON_RELEASE] = event_button_release, */ /* [XCB_CONFIGURE_REQUEST] = event_configure_request, */ From 0e6e6f469f2444eeacd838266c2b0c0027f3f16c Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 21 Jul 2020 09:26:36 +0300 Subject: [PATCH 10/22] add initial event functions --- sowm.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/sowm.c b/sowm.c index 905f0e3..368f329 100644 --- a/sowm.c +++ b/sowm.c @@ -10,18 +10,36 @@ static xcb_screen_t *scr; static void init_wm(void); static void init_input(void); +static void event_button_press(xcb_generic_event_t *ev); +static void event_button_release(xcb_generic_event_t *ev); +static void event_configure_request(xcb_generic_event_t *ev); +static void event_key_press(xcb_generic_event_t *ev); +static void event_notify_create(xcb_generic_event_t *ev); +static void event_notify_destroy(xcb_generic_event_t *ev); +static void event_notify_enter(xcb_generic_event_t *ev); +static void event_notify_motion(xcb_generic_event_t *ev); + void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { - [0] = 0, /* dummy for now */ - /* [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 */ + [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 }; +/* todo */ +static void event_button_press(xcb_generic_event_t *ev) { } +static void event_button_release(xcb_generic_event_t *ev) { } +static void event_configure_request(xcb_generic_event_t *ev) { } +static void event_key_press(xcb_generic_event_t *ev) { } +static void event_notify_create(xcb_generic_event_t *ev) { } +static void event_notify_destroy(xcb_generic_event_t *ev) { } +static void event_notify_enter(xcb_generic_event_t *ev) { } +static void event_notify_motion(xcb_generic_event_t *ev) { } + static void init_wm(void) { uint32_t values[2]; From d1535393aaf2ee2f7de64c58be2765ca66b9eacf Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 21 Jul 2020 09:45:29 +0300 Subject: [PATCH 11/22] move stuff to src --- .gitignore | 2 +- Makefile | 18 ++++++++++++------ src/event.c | 23 +++++++++++++++++++++++ src/event.h | 17 +++++++++++++++++ sowm.c => src/sowm.c | 32 ++------------------------------ 5 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 src/event.c create mode 100644 src/event.h rename sowm.c => src/sowm.c (55%) diff --git a/.gitignore b/.gitignore index 9267cd5..cca8e6e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ sowm -sowm.o config.h .ccls-cache +src/*.o diff --git a/Makefile b/Makefile index 0fe2f58..9a15a34 100644 --- a/Makefile +++ b/Makefile @@ -4,16 +4,22 @@ PREFIX = /usr/local ALL_WARN = -Wall -Wextra -pedantic -Wmissing-prototypes -Wstrict-prototypes ALL_CFLAGS = $(CFLAGS) $(CPPFLAGS) -std=c99 $(ALL_WARN) -ALL_LDFLAGS = $(LDFLAGS) -lxcb +ALL_LDFLAGS = $(LDFLAGS) $(LIBS) -lxcb CC = cc -all: sowm +OBJ = src/event.o src/sowm.o +HDR = src/event.h -sowm: sowm.c Makefile - $(CC) -O3 $(ALL_CFLAGS) -o $@ $< $(ALL_LDFLAGS) +.c.o: + $(CC) $(ALL_CFLAGS) -c -o $@ $< -install: all +sowm: $(OBJ) + $(CC) $(ALL_CFLAGS) -o $@ $(OBJ) $(ALL_LDFLAGS) + +$(OBJ): $(HDR) + +install: sowm mkdir -p $(DESTDIR)/bin cp sowm $(DESTDIR)/bin/sowm @@ -23,4 +29,4 @@ uninstall: clean: rm -f sowm *.o -.PHONY: all install uninstall clean +.PHONY: install uninstall clean diff --git a/src/event.c b/src/event.c new file mode 100644 index 0000000..7d39574 --- /dev/null +++ b/src/event.c @@ -0,0 +1,23 @@ +#include "event.h" + +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 +}; + +/* todo */ +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) { } + diff --git a/src/event.h b/src/event.h new file mode 100644 index 0000000..1dd44b3 --- /dev/null +++ b/src/event.h @@ -0,0 +1,17 @@ +#ifndef SOWM_EVENT_H_INCLUDED +#define SOWM_EVENT_H_INCLUDED + +#include + +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); + +extern void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *); + +#endif diff --git a/sowm.c b/src/sowm.c similarity index 55% rename from sowm.c rename to src/sowm.c index 368f329..2774e69 100644 --- a/sowm.c +++ b/src/sowm.c @@ -4,42 +4,14 @@ #include +#include "event.h" + static xcb_connection_t *dpy; static xcb_screen_t *scr; static void init_wm(void); static void init_input(void); -static void event_button_press(xcb_generic_event_t *ev); -static void event_button_release(xcb_generic_event_t *ev); -static void event_configure_request(xcb_generic_event_t *ev); -static void event_key_press(xcb_generic_event_t *ev); -static void event_notify_create(xcb_generic_event_t *ev); -static void event_notify_destroy(xcb_generic_event_t *ev); -static void event_notify_enter(xcb_generic_event_t *ev); -static 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 -}; - -/* todo */ -static void event_button_press(xcb_generic_event_t *ev) { } -static void event_button_release(xcb_generic_event_t *ev) { } -static void event_configure_request(xcb_generic_event_t *ev) { } -static void event_key_press(xcb_generic_event_t *ev) { } -static void event_notify_create(xcb_generic_event_t *ev) { } -static void event_notify_destroy(xcb_generic_event_t *ev) { } -static void event_notify_enter(xcb_generic_event_t *ev) { } -static void event_notify_motion(xcb_generic_event_t *ev) { } - static void init_wm(void) { uint32_t values[2]; From 136c30403b8b4181b7656b4a87fc5152fda99119 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 21 Jul 2020 10:02:14 +0300 Subject: [PATCH 12/22] add globals for connection/screen --- Makefile | 2 +- src/event.c | 9 +++++++-- src/event.h | 5 ----- src/globals.h | 4 ++++ src/sowm.c | 7 ++++--- 5 files changed, 16 insertions(+), 11 deletions(-) create mode 100644 src/globals.h diff --git a/Makefile b/Makefile index 9a15a34..63a4ff4 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ ALL_LDFLAGS = $(LDFLAGS) $(LIBS) -lxcb CC = cc OBJ = src/event.o src/sowm.o -HDR = src/event.h +HDR = src/event.h src/globals.h .c.o: $(CC) $(ALL_CFLAGS) -c -o $@ $< diff --git a/src/event.c b/src/event.c index 7d39574..937b174 100644 --- a/src/event.c +++ b/src/event.c @@ -1,3 +1,4 @@ +#include "globals.h" #include "event.h" void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { @@ -11,9 +12,13 @@ void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { [XCB_MOTION_NOTIFY] = event_notify_motion }; -/* todo */ void event_button_press(xcb_generic_event_t *ev) { } -void event_button_release(xcb_generic_event_t *ev) { } + +void event_button_release(xcb_generic_event_t *ev) { + xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); + xcb_flush(dpy); +} + 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) { } diff --git a/src/event.h b/src/event.h index 1dd44b3..d52f60b 100644 --- a/src/event.h +++ b/src/event.h @@ -1,6 +1,3 @@ -#ifndef SOWM_EVENT_H_INCLUDED -#define SOWM_EVENT_H_INCLUDED - #include void event_button_press(xcb_generic_event_t *ev); @@ -13,5 +10,3 @@ void event_notify_enter(xcb_generic_event_t *ev); void event_notify_motion(xcb_generic_event_t *ev); extern void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *); - -#endif diff --git a/src/globals.h b/src/globals.h new file mode 100644 index 0000000..6ea36c2 --- /dev/null +++ b/src/globals.h @@ -0,0 +1,4 @@ +#include + +extern xcb_connection_t *dpy; +extern xcb_screen_t *scr; diff --git a/src/sowm.c b/src/sowm.c index 2774e69..6b7dbdf 100644 --- a/src/sowm.c +++ b/src/sowm.c @@ -5,13 +5,14 @@ #include #include "event.h" - -static xcb_connection_t *dpy; -static xcb_screen_t *scr; +#include "globals.h" static void init_wm(void); static void init_input(void); +xcb_connection_t *dpy; +xcb_screen_t *scr; + static void init_wm(void) { uint32_t values[2]; From c75d34b7b1dd23a850f9c104ad22aabfb6fa5758 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 21 Jul 2020 10:05:19 +0300 Subject: [PATCH 13/22] more stuff --- src/event.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/src/event.c b/src/event.c index 937b174..86ea456 100644 --- a/src/event.c +++ b/src/event.c @@ -12,17 +12,51 @@ void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { [XCB_MOTION_NOTIFY] = event_notify_motion }; -void event_button_press(xcb_generic_event_t *ev) { } +void event_button_press(xcb_generic_event_t *ev) { + +} void event_button_release(xcb_generic_event_t *ev) { xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); xcb_flush(dpy); } -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 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) { + xcb_create_notify_event_t *e = (xcb_create_notify_event_t *)ev; + uint32_t values[2]; + + values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; + values[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + + xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, values); + xcb_map_window(dpy, e->window); +} + +void event_notify_destroy(xcb_generic_event_t *ev) { + +} + +void event_notify_enter(xcb_generic_event_t *ev) { + xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; + + if (e->event == scr->root) { + return; + } + + xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, + e->event, XCB_CURRENT_TIME); + + xcb_flush(dpy); +} + +void event_notify_motion(xcb_generic_event_t *ev) { +} From 02f08fba01f5863ec0002918c99b614092bf8792 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Tue, 21 Jul 2020 10:10:39 +0300 Subject: [PATCH 14/22] add initial action --- Makefile | 4 ++-- src/action.c | 37 +++++++++++++++++++++++++++++++++++++ src/action.h | 11 +++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/action.c create mode 100644 src/action.h diff --git a/Makefile b/Makefile index 63a4ff4..bc831fa 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ ALL_LDFLAGS = $(LDFLAGS) $(LIBS) -lxcb CC = cc -OBJ = src/event.o src/sowm.o -HDR = src/event.h src/globals.h +OBJ = src/event.o src/action.o src/sowm.o +HDR = src/event.h src/action.h src/globals.h .c.o: $(CC) $(ALL_CFLAGS) -c -o $@ $< diff --git a/src/action.c b/src/action.c new file mode 100644 index 0000000..8c5c997 --- /dev/null +++ b/src/action.c @@ -0,0 +1,37 @@ +#include "action.h" + +void action_win_add(void) { + +} + +void action_win_del(void) { + +} + +void action_win_center(void) { + +} + +void action_win_fullscreen(void) { + +} + +void action_win_focus(void) { + +} + +void action_win_kill(void) { + +} + +void action_win_next(void) { + +} + +void action_win_to_desktop(void) { + +} + +void action_to_desktop(void) { + +} diff --git a/src/action.h b/src/action.h new file mode 100644 index 0000000..3f18513 --- /dev/null +++ b/src/action.h @@ -0,0 +1,11 @@ +/* todo */ +void action_win_add(void); +void action_win_center(void); +void action_win_del(void); +void action_win_fullscreen(void); +void action_win_focus(void); +void action_win_kill(void); +void action_win_prev(void); +void action_win_next(void); +void action_win_to_desktop(void); +void action_to_desktop(void); From a9e3490de70e5a517981294bf3d6783bad3e2315 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sun, 26 Jul 2020 13:20:08 +0300 Subject: [PATCH 15/22] pointer stuff --- src/event.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++--- src/sowm.c | 7 +++--- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/src/event.c b/src/event.c index 86ea456..d73bd52 100644 --- a/src/event.c +++ b/src/event.c @@ -1,6 +1,10 @@ +#include + #include "globals.h" #include "event.h" +static xcb_window_t motion_win; + void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { [XCB_BUTTON_PRESS] = event_button_press, [XCB_BUTTON_RELEASE] = event_button_release, @@ -13,12 +17,40 @@ void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { }; void event_button_press(xcb_generic_event_t *ev) { + xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; + xcb_get_geometry_reply_t *geom; + uint32_t values[3]; + + if (e->child == XCB_NONE) { + return; + } + + motion_win = e->child; + values[0] = XCB_STACK_MODE_ABOVE; + xcb_configure_window(dpy, e->child, XCB_CONFIG_WINDOW_STACK_MODE, values); + + geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, e->child), NULL); + + /* resize */ + if (e->detail == 1) { + xcb_warp_pointer(dpy, XCB_NONE, e->child, 0, 0, 0, 0, 1, 1); + + /* move */ + } else { + xcb_warp_pointer(dpy, XCB_NONE, e->child, 0, 0, 0, 0, + geom->width, geom->height); + } + + xcb_grab_pointer(dpy, 0, scr->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, scr->root, XCB_NONE, + XCB_CURRENT_TIME); } void event_button_release(xcb_generic_event_t *ev) { xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); - xcb_flush(dpy); + motion_win = XCB_NONE; } void event_configure_request(xcb_generic_event_t *ev) { @@ -38,6 +70,9 @@ void event_notify_create(xcb_generic_event_t *ev) { xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, values); xcb_map_window(dpy, e->window); + + xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, + e->window, XCB_CURRENT_TIME); } void event_notify_destroy(xcb_generic_event_t *ev) { @@ -47,16 +82,44 @@ void event_notify_destroy(xcb_generic_event_t *ev) { void event_notify_enter(xcb_generic_event_t *ev) { xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; - if (e->event == scr->root) { + if (e->event == scr->root || e->event == XCB_NONE) { return; } xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, e->event, XCB_CURRENT_TIME); - - xcb_flush(dpy); } void event_notify_motion(xcb_generic_event_t *ev) { + xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *)ev; + xcb_query_pointer_reply_t *ptr; + xcb_get_geometry_reply_t *geom; + uint32_t values[3]; + + if (motion_win == scr->root || motion_win == XCB_NONE) { + return; + } + + ptr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, scr->root), 0); + geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, motion_win), NULL); + /* move */ + if (e->state & XCB_BUTTON_MASK_1) { + values[0] = (ptr->root_x + geom->width > scr->width_in_pixels)? + (scr->width_in_pixels - geom->width):ptr->root_x; + + values[1] = (ptr->root_y + geom->height > scr->height_in_pixels)? + (scr->height_in_pixels - geom->height):ptr->root_y; + + xcb_configure_window(dpy, motion_win, + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); + + /* resize */ + } else if (e->state & XCB_BUTTON_MASK_3) { + values[0] = ptr->root_x - geom->x; + values[1] = ptr->root_y - geom->y; + + xcb_configure_window(dpy, motion_win, + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); + } } diff --git a/src/sowm.c b/src/sowm.c index 6b7dbdf..19fe226 100644 --- a/src/sowm.c +++ b/src/sowm.c @@ -40,16 +40,16 @@ static void init_wm(void) { } static void init_input(void) { - xcb_grab_key(dpy, 1, scr->root, XCB_MOD_MASK_4, XCB_NO_SYMBOL, + xcb_grab_key(dpy, 1, scr->root, XCB_MOD_MASK_1, XCB_NO_SYMBOL, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); xcb_grab_button(dpy, 0, scr->root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, - XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 1, XCB_MOD_MASK_4); + XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 1, XCB_MOD_MASK_1); xcb_grab_button(dpy, 0, scr->root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, - XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 3, XCB_MOD_MASK_4); + XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 3, XCB_MOD_MASK_1); xcb_flush(dpy); } @@ -73,6 +73,7 @@ int main(int argc, char **argv) { if (events[ev_type]) { events[ev_type](ev); + xcb_flush(dpy); } free(ev); From 16a80214b8ce4423014be0caec703e2291968891 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sun, 26 Jul 2020 13:31:51 +0300 Subject: [PATCH 16/22] cleanup and minimum window size --- src/event.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/event.c b/src/event.c index d73bd52..febd20a 100644 --- a/src/event.c +++ b/src/event.c @@ -3,6 +3,8 @@ #include "globals.h" #include "event.h" +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + static xcb_window_t motion_win; void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { @@ -28,19 +30,15 @@ void event_button_press(xcb_generic_event_t *ev) { motion_win = e->child; values[0] = XCB_STACK_MODE_ABOVE; - xcb_configure_window(dpy, e->child, XCB_CONFIG_WINDOW_STACK_MODE, values); - - geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, e->child), NULL); + xcb_configure_window(dpy, e->child, + XCB_CONFIG_WINDOW_STACK_MODE, values); - /* resize */ - if (e->detail == 1) { - xcb_warp_pointer(dpy, XCB_NONE, e->child, 0, 0, 0, 0, 1, 1); + geom = xcb_get_geometry_reply(dpy, + xcb_get_geometry(dpy, e->child), NULL); - /* move */ - } else { - xcb_warp_pointer(dpy, XCB_NONE, e->child, 0, 0, 0, 0, - geom->width, geom->height); - } + xcb_warp_pointer(dpy, XCB_NONE, e->child, 0, 0, 0, 0, + e->detail != 1 ? geom->width : 1, + e->detail != 1 ? geom->height : 1); xcb_grab_pointer(dpy, 0, scr->root, XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_POINTER_MOTION_HINT, @@ -116,8 +114,8 @@ void event_notify_motion(xcb_generic_event_t *ev) { /* resize */ } else if (e->state & XCB_BUTTON_MASK_3) { - values[0] = ptr->root_x - geom->x; - values[1] = ptr->root_y - geom->y; + values[0] = MAX(10, ptr->root_x - geom->x); + values[1] = MAX(10, ptr->root_y - geom->y); xcb_configure_window(dpy, motion_win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); From aae3efc546865295c560a61f08f84a579dce3a47 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sun, 26 Jul 2020 15:17:58 +0300 Subject: [PATCH 17/22] shorter null checks --- src/event.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/event.c b/src/event.c index febd20a..0b303e8 100644 --- a/src/event.c +++ b/src/event.c @@ -23,7 +23,7 @@ void event_button_press(xcb_generic_event_t *ev) { xcb_get_geometry_reply_t *geom; uint32_t values[3]; - if (e->child == XCB_NONE) { + if (!e->child) { return; } @@ -48,7 +48,7 @@ void event_button_press(xcb_generic_event_t *ev) { void event_button_release(xcb_generic_event_t *ev) { xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); - motion_win = XCB_NONE; + motion_win = 0; } void event_configure_request(xcb_generic_event_t *ev) { @@ -80,7 +80,7 @@ void event_notify_destroy(xcb_generic_event_t *ev) { void event_notify_enter(xcb_generic_event_t *ev) { xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; - if (e->event == scr->root || e->event == XCB_NONE) { + if (e->event == scr->root || !e->event) { return; } @@ -94,7 +94,7 @@ void event_notify_motion(xcb_generic_event_t *ev) { xcb_get_geometry_reply_t *geom; uint32_t values[3]; - if (motion_win == scr->root || motion_win == XCB_NONE) { + if (motion_win == scr->root || !motion_win) { return; } From 710659f788efeb41a60dcd7523b1d9eb62350e5b Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sun, 26 Jul 2020 15:19:04 +0300 Subject: [PATCH 18/22] swap em round --- src/event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/event.c b/src/event.c index 0b303e8..abd5f77 100644 --- a/src/event.c +++ b/src/event.c @@ -80,7 +80,7 @@ void event_notify_destroy(xcb_generic_event_t *ev) { void event_notify_enter(xcb_generic_event_t *ev) { xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; - if (e->event == scr->root || !e->event) { + if (!e->event || e->event == scr->root) { return; } @@ -94,7 +94,7 @@ void event_notify_motion(xcb_generic_event_t *ev) { xcb_get_geometry_reply_t *geom; uint32_t values[3]; - if (motion_win == scr->root || !motion_win) { + if (!motion_win || motion_win == scr->root) { return; } From 37648b9576ad9336f1932c1132f3caae19354ea5 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sun, 26 Jul 2020 15:25:21 +0300 Subject: [PATCH 19/22] minor fixes --- src/action.c | 18 +++++++++--------- src/event.c | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/action.c b/src/action.c index 8c5c997..e9e4012 100644 --- a/src/action.c +++ b/src/action.c @@ -1,37 +1,37 @@ #include "action.h" -void action_win_add(void) { +void action_win_add() { } -void action_win_del(void) { +void action_win_del() { } -void action_win_center(void) { +void action_win_center() { } -void action_win_fullscreen(void) { +void action_win_fullscreen() { } -void action_win_focus(void) { +void action_win_focus() { } -void action_win_kill(void) { +void action_win_kill() { } -void action_win_next(void) { +void action_win_next() { } -void action_win_to_desktop(void) { +void action_win_to_desktop() { } -void action_to_desktop(void) { +void action_to_desktop() { } diff --git a/src/event.c b/src/event.c index abd5f77..fe2b90f 100644 --- a/src/event.c +++ b/src/event.c @@ -21,17 +21,17 @@ void (*events[XCB_NO_OPERATION])(xcb_generic_event_t *) = { void event_button_press(xcb_generic_event_t *ev) { xcb_button_press_event_t *e = (xcb_button_press_event_t *)ev; xcb_get_geometry_reply_t *geom; - uint32_t values[3]; + uint32_t value; if (!e->child) { return; } motion_win = e->child; - values[0] = XCB_STACK_MODE_ABOVE; + value = XCB_STACK_MODE_ABOVE; xcb_configure_window(dpy, e->child, - XCB_CONFIG_WINDOW_STACK_MODE, values); + XCB_CONFIG_WINDOW_STACK_MODE, &value); geom = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, e->child), NULL); From 4a369b4ab2528835eb5632e95312581eb993b175 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sun, 26 Jul 2020 15:28:44 +0300 Subject: [PATCH 20/22] Reduce length of values --- src/event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event.c b/src/event.c index fe2b90f..e08b7f3 100644 --- a/src/event.c +++ b/src/event.c @@ -92,7 +92,7 @@ void event_notify_motion(xcb_generic_event_t *ev) { xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *)ev; xcb_query_pointer_reply_t *ptr; xcb_get_geometry_reply_t *geom; - uint32_t values[3]; + uint32_t values[2]; if (!motion_win || motion_win == scr->root) { return; From fbf145e5af58d290e557bcc1aff1fea2203f4b3c Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Sun, 26 Jul 2020 15:30:17 +0300 Subject: [PATCH 21/22] reduce length of values --- src/event.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/event.c b/src/event.c index e08b7f3..78d99eb 100644 --- a/src/event.c +++ b/src/event.c @@ -61,12 +61,13 @@ void event_key_press(xcb_generic_event_t *ev) { void event_notify_create(xcb_generic_event_t *ev) { xcb_create_notify_event_t *e = (xcb_create_notify_event_t *)ev; - uint32_t values[2]; + uint32_t value; - values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE; - values[1] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + value = XCB_EVENT_MASK_ENTER_WINDOW | + XCB_EVENT_MASK_FOCUS_CHANGE | + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; - xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, values); + xcb_change_window_attributes(dpy, e->window, XCB_CW_EVENT_MASK, &value); xcb_map_window(dpy, e->window); xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, From d9f72fdffcb36d90fc5a8581ae619c56b3d74616 Mon Sep 17 00:00:00 2001 From: Dylan Araps Date: Wed, 29 Jul 2020 11:56:23 +0300 Subject: [PATCH 22/22] big poosh --- Makefile | 4 +- design.txt | 4 ++ src/action.c | 37 ----------- src/action.h | 11 ---- src/event.c | 19 +++--- src/event.h | 6 +- src/globals.h | 7 ++ src/sowm.c | 35 +++++++--- src/vec.h | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 228 insertions(+), 70 deletions(-) create mode 100644 design.txt delete mode 100644 src/action.c delete mode 100644 src/action.h create mode 100644 src/vec.h diff --git a/Makefile b/Makefile index bc831fa..63a4ff4 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ ALL_LDFLAGS = $(LDFLAGS) $(LIBS) -lxcb CC = cc -OBJ = src/event.o src/action.o src/sowm.o -HDR = src/event.h src/action.h src/globals.h +OBJ = src/event.o src/sowm.o +HDR = src/event.h src/globals.h .c.o: $(CC) $(ALL_CFLAGS) -c -o $@ $< diff --git a/design.txt b/design.txt new file mode 100644 index 0000000..3f03b3f --- /dev/null +++ b/design.txt @@ -0,0 +1,4 @@ +keybindings +events +actions +manager diff --git a/src/action.c b/src/action.c deleted file mode 100644 index e9e4012..0000000 --- a/src/action.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "action.h" - -void action_win_add() { - -} - -void action_win_del() { - -} - -void action_win_center() { - -} - -void action_win_fullscreen() { - -} - -void action_win_focus() { - -} - -void action_win_kill() { - -} - -void action_win_next() { - -} - -void action_win_to_desktop() { - -} - -void action_to_desktop() { - -} diff --git a/src/action.h b/src/action.h deleted file mode 100644 index 3f18513..0000000 --- a/src/action.h +++ /dev/null @@ -1,11 +0,0 @@ -/* todo */ -void action_win_add(void); -void action_win_center(void); -void action_win_del(void); -void action_win_fullscreen(void); -void action_win_focus(void); -void action_win_kill(void); -void action_win_prev(void); -void action_win_next(void); -void action_win_to_desktop(void); -void action_to_desktop(void); diff --git a/src/event.c b/src/event.c index 78d99eb..b9a8f5f 100644 --- a/src/event.c +++ b/src/event.c @@ -10,10 +10,10 @@ static xcb_window_t motion_win; 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_CONFIGURE_REQUEST] = event_configure_request, */ + /* [XCB_KEY_PRESS] = event_key_press, */ [XCB_CREATE_NOTIFY] = event_notify_create, - [XCB_DESTROY_NOTIFY] = event_notify_destroy, + /* [XCB_DESTROY_NOTIFY] = event_notify_destroy, */ [XCB_ENTER_NOTIFY] = event_notify_enter, [XCB_MOTION_NOTIFY] = event_notify_motion }; @@ -47,17 +47,18 @@ void event_button_press(xcb_generic_event_t *ev) { } void event_button_release(xcb_generic_event_t *ev) { + (void)(ev); xcb_ungrab_pointer(dpy, XCB_CURRENT_TIME); motion_win = 0; } -void event_configure_request(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_key_press(xcb_generic_event_t *ev) { */ -} +/* } */ void event_notify_create(xcb_generic_event_t *ev) { xcb_create_notify_event_t *e = (xcb_create_notify_event_t *)ev; @@ -74,9 +75,9 @@ void event_notify_create(xcb_generic_event_t *ev) { e->window, XCB_CURRENT_TIME); } -void event_notify_destroy(xcb_generic_event_t *ev) { +/* void event_notify_destroy(xcb_generic_event_t *ev) { */ -} +/* } */ void event_notify_enter(xcb_generic_event_t *ev) { xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *)ev; diff --git a/src/event.h b/src/event.h index d52f60b..ce6b04e 100644 --- a/src/event.h +++ b/src/event.h @@ -2,10 +2,10 @@ 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_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_destroy(xcb_generic_event_t *ev); */ void event_notify_enter(xcb_generic_event_t *ev); void event_notify_motion(xcb_generic_event_t *ev); diff --git a/src/globals.h b/src/globals.h index 6ea36c2..97505aa 100644 --- a/src/globals.h +++ b/src/globals.h @@ -2,3 +2,10 @@ extern xcb_connection_t *dpy; extern xcb_screen_t *scr; + +struct desktop { + xcb_window_t *windows; + int num; +}; + +extern int current_desktop; diff --git a/src/sowm.c b/src/sowm.c index 19fe226..32e6d99 100644 --- a/src/sowm.c +++ b/src/sowm.c @@ -5,16 +5,22 @@ #include #include "event.h" +#include "vec.h" #include "globals.h" +#include "config.h" static void init_wm(void); static void init_input(void); +static void init_desktops(void); xcb_connection_t *dpy; xcb_screen_t *scr; -static void init_wm(void) { - uint32_t values[2]; +struct desktop *desktops; +int current_desktop = 0; + +static void init_wm() { + uint32_t values; dpy = xcb_connect(NULL, NULL); @@ -31,29 +37,41 @@ static void init_wm(void) { exit(1); } - values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; + values = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY; xcb_change_window_attributes_checked(dpy, scr->root, - XCB_CW_EVENT_MASK, values); + XCB_CW_EVENT_MASK, &values); xcb_flush(dpy); } -static void init_input(void) { - xcb_grab_key(dpy, 1, scr->root, XCB_MOD_MASK_1, XCB_NO_SYMBOL, +static void init_input() { + xcb_grab_key(dpy, 1, scr->root, SOWM_MOD, XCB_NO_SYMBOL, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC); xcb_grab_button(dpy, 0, scr->root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, - XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 1, XCB_MOD_MASK_1); + XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 1, SOWM_MOD); xcb_grab_button(dpy, 0, scr->root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, - XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 3, XCB_MOD_MASK_1); + XCB_GRAB_MODE_ASYNC, scr->root, XCB_NONE, 3, SOWM_MOD); xcb_flush(dpy); } +static void init_desktops() { + struct desktop new = {0}; + + for (int i = 0; i < SOWM_NUM_DESKTOPS; i++) { + new.num = i; + vec_push_back(desktops, new); + } + + /* todo finish usage of desktops */ + vec_free(desktops); +} + int main(int argc, char **argv) { xcb_generic_event_t *ev; unsigned int ev_type; @@ -67,6 +85,7 @@ int main(int argc, char **argv) { init_wm(); init_input(); + init_desktops(); while ((ev = xcb_wait_for_event(dpy))) { ev_type = ev->response_type & ~0x80; diff --git a/src/vec.h b/src/vec.h new file mode 100644 index 0000000..f6f6e5e --- /dev/null +++ b/src/vec.h @@ -0,0 +1,175 @@ + +/* +This is an implementation of a std::vector like growable array, but in plain +C89 code. The result is a type safe, easy to use, dynamic array that has a +familiar set of operations. Source: https://github.com/eteran/c-vector + +The MIT License (MIT) + +Copyright (c) 2020 Dylan Araps +Copyright (c) 2015 Evan Teran + +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. +*/ + +#ifndef VEC_H_ +#define VEC_H_ + +#include /* for assert */ +#include /* for size_t */ +#include /* for malloc/realloc/free */ + +/** + * @brief vec_set_capacity - For internal use, set capacity variable. + * @param vec - the vector + * @param size - the new capacity to set + * @return void + */ +#define vec_set_capacity(vec, size) \ + do { \ + if (vec) { \ + ((size_t *)(vec))[-1] = (size); \ + } \ + } while (0) + +/** + * @brief vec_set_size - For internal use, sets the size variable of the vector + * @param vec - the vector + * @param size - the new capacity to set + * @return void + */ +#define vec_set_size(vec, size) \ + do { \ + if (vec) { \ + ((size_t *)(vec))[-2] = (size); \ + } \ + } while (0) + +/** + * @brief vec_capacity - gets the current capacity of the vector + * @param vec - the vector + * @return the capacity as a size_t + */ +#define vec_capacity(vec) ((vec) ? ((size_t *)(vec))[-1] : (size_t)0) + +/** + * @brief vec_size - gets the current size of the vector + * @param vec - the vector + * @return the size as a size_t + */ +#define vec_size(vec) ((vec) ? ((size_t *)(vec))[-2] : (size_t)0) + +/** + * @brief vec_empty - returns non-zero if the vector is empty + * @param vec - the vector + * @return non-zero if empty, zero if non-empty + */ +#define vec_empty(vec) (vec_size(vec) == 0) + +/** + * @brief vec_grow - For internal use, ensure that the vector is >= . + * @param vec - the vector + * @param size - the new capacity to set + * @return void + */ +#define vec_grow(vec, count) \ + do { \ + const size_t vec__sz = (count) * sizeof(*(vec)) + (sizeof(size_t) * 2); \ + if (!(vec)) { \ + size_t *vec__p = malloc(vec__sz); \ + assert(vec__p); \ + (vec) = (void *)(&vec__p[2]); \ + vec_set_capacity((vec), (count)); \ + vec_set_size((vec), 0); \ + } else { \ + size_t *vec__p1 = &((size_t *)(vec))[-2]; \ + size_t *vec__p2 = realloc(vec__p1, (vec__sz)); \ + assert(vec__p2); \ + (vec) = (void *)(&vec__p2[2]); \ + vec_set_capacity((vec), (count)); \ + } \ + } while (0) + +/** + * @brief vec_pop_back - removes the last element from the vector + * @param vec - the vector + * @return void + */ +#define vec_pop_back(vec) \ + do { \ + vec_set_size((vec), vec_size(vec) - 1); \ + } while (0) + +/** + * @brief vec_erase - removes the element at index i from the vector + * @param vec - the vector + * @param i - index of element to remove + * @return void + */ +#define vec_erase(vec, i) \ + do { \ + if (vec) { \ + const size_t vec__sz = vec_size(vec); \ + if ((i) < vec__sz) { \ + vec_set_size((vec), vec__sz - 1); \ + size_t vec__x; \ + for (vec__x = (i); vec__x < (vec__sz - 1); ++vec__x) { \ + (vec)[vec__x] = (vec)[vec__x + 1]; \ + } \ + } \ + } \ + } while (0) + +/** + * @brief vec_free - frees all memory associated with the vector + * @param vec - the vector + * @return void + */ +#define vec_free(vec) \ + do { \ + if (vec) { \ + size_t *p1 = &((size_t *)(vec))[-2]; \ + free(p1); \ + } \ + } while (0) + +/** + * @brief vec_end - returns an iterator to one past the last element + * @param vec - the vector + * @return a pointer to one past the last element (or NULL) + */ +#define vec_end(vec) ((vec) ? &((vec)[vec_size(vec)]) : NULL) + +/** + * @brief vec_push_back - adds an element to the end of the vector + * @param vec - the vector + * @param value - the value to add + * @return void + */ +#define vec_push_back(vec, value) \ + do { \ + size_t vec__cap = vec_capacity(vec); \ + if (vec__cap <= vec_size(vec)) { \ + vec_grow((vec), !vec__cap ? vec__cap + 1 : vec__cap * 2); \ + } \ + vec[vec_size(vec)] = (value); \ + vec_set_size((vec), vec_size(vec) + 1); \ + } while (0) + +#endif /* VEC_H_ */