diff options
Diffstat (limited to 'src/sxwm.c')
-rw-r--r-- | src/sxwm.c | 102 |
1 files changed, 97 insertions, 5 deletions
@@ -11,12 +11,65 @@ */// (C) Abhinav Prasai 2025 -#include "sxwm.h" +#include <err.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <X11/Xlib.h> +#include <X11/XKBlib.h> + +#include "defs.h" + +typedef void (*EventHandler)(XEvent *); + +static void hdl_dummy(XEvent *xev); +static void hdl_keypress(XEvent *xev); +static void other_wm(void); +static int other_wm_err(Display *dpy, XErrorEvent *ee); +static void quit(void); +static void run(void); +static void setup(void); +static void spawn(const char **cmd); +static int xerr(Display *dpy, XErrorEvent *ee); +static void xev_case(XEvent *xev); + +static Client clients[MAXCLIENTS] = {0}; +static EventHandler evtable[LASTEvent]; +static Display *dpy; +static Window root; + +#include "usercfg.h" + +static void +hdl_dummy(XEvent *xev){} static void -otherwm(void) +hdl_keypress(XEvent *xev) { - XSetErrorHandler(otherwmerr); + KeySym keysym; + XKeyEvent *ev = &xev->xkey; + unsigned int modifiers; + + modifiers = ev->state; + keysym = XkbKeycodeToKeysym(dpy, ev->keycode, 0, 0); + + int lenbindings = sizeof(binds) / sizeof(binds[0]); + for (int i = 0; i < lenbindings; ++i) { + if (keysym == binds[i].keysym && modifiers == binds[i].mods) { + if (binds[i].is_func) + binds[i].action.fn(); + else + spawn(binds[i].action.cmd); + return; + } + } +} + +static void +other_wm(void) +{ + XSetErrorHandler(other_wm_err); XChangeWindowAttributes(dpy, root, CWEventMask, &(XSetWindowAttributes){.event_mask = SubstructureRedirectMask}); XSync(dpy, False); @@ -25,7 +78,7 @@ otherwm(void) } static int -otherwmerr(Display *dpy, XErrorEvent *ee) +other_wm_err(Display *dpy, XErrorEvent *ee) { errx(0, "sxwm: can't start because another window manager is already running"); return 0; @@ -33,11 +86,18 @@ otherwmerr(Display *dpy, XErrorEvent *ee) } static void +quit(void) +{ + errx(0, "sxwm: quitting..."); +} + +static void run(void) { XEvent xev; for (;;) { XNextEvent(dpy, &xev); + xev_case(&xev); } } @@ -49,10 +109,33 @@ setup(void) errx(0, "sxwm: can't open display."); root = XDefaultRootWindow(dpy); - otherwm(); + other_wm(); XSelectInput(dpy, root, SubstructureRedirectMask | KeyPressMask | KeyReleaseMask ); + + for (int i = 0; i < LASTEvent; ++i) + evtable[i] = hdl_dummy; + + evtable[KeyPress] = hdl_keypress; +} + +static void +spawn(const char **cmd) +{ + if (!cmd) return; + printf("sxwm: attempting to spawn: %s\n", cmd[0]); + + pid_t pid = fork(); + if (pid == 0) { + if (dpy) + close(ConnectionNumber(dpy)); + setsid(); + execvp(cmd[0], (char *const*)cmd); + errx(1, "sxwm: execvp '%s' failed\n", cmd[0]); + } else if (pid < 0) { + fprintf(stderr, "sxwm: failed to fork process\n"); + } } static int @@ -64,6 +147,15 @@ xerr(Display *dpy, XErrorEvent *ee) if (dpy && ee) return 0; } +static void +xev_case(XEvent *xev) +{ + if (xev->type >= 0 && xev->type < LASTEvent) + evtable[xev->type](xev); + else + printf("sxwm: invalid event type: %d\n", xev->type); +} + int main(int ac, char **av) { |