summaryrefslogtreecommitdiff
path: root/src/sxwm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sxwm.c')
-rw-r--r--src/sxwm.c102
1 files changed, 97 insertions, 5 deletions
diff --git a/src/sxwm.c b/src/sxwm.c
index 5000f2e..c8d50ba 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -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)
{