summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Fadel <samuel@nihil.ws>2022-12-02 16:14:26 +0100
committerSamuel Fadel <samuel@nihil.ws>2022-12-02 16:14:26 +0100
commit21ebd4dda267d09c60d8b646782aed28138c5690 (patch)
treea07d2103c745e382160a344263790235e3ec0c68
parent7aa66702b2b9396add0cc20849ec89a48495c7ff (diff)
Proof-of-concept event handling. See NOTE.
-rw-r--r--main.scm6
-rw-r--r--schewm.c241
-rw-r--r--wm.scm30
3 files changed, 265 insertions, 12 deletions
diff --git a/main.scm b/main.scm
index 07c2f04..8a34528 100644
--- a/main.scm
+++ b/main.scm
@@ -1,4 +1,8 @@
(use-modules (wm))
(when (wm-init)
- (wm-quit "hello"))
+ (wm-set-configure-notify-handler!
+ (lambda (x y w h)
+ (display (+ x y w h))
+ (display "\n")))
+ (wm-quit))
diff --git a/schewm.c b/schewm.c
index 72f89bf..53919bd 100644
--- a/schewm.c
+++ b/schewm.c
@@ -1,11 +1,248 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
+#include <string.h>
+
+#include <xcb/randr.h>
+#include <xcb/xcb_ewmh.h>
+#include <xcb/xcb_keysyms.h>
+#include <X11/keysym.h>
+
+/*
+ * Array of (internal) event handlers. They cast the event pointer to
+ * the proper type and call the custom handlers defined in Scheme.
+ */
+typedef void (*generic_event_handler_t)(xcb_generic_event_t *);
+static generic_event_handler_t events[XCB_NO_OPERATION];
+
+/*
+ * NOTE:
+ * Don't do the thing below. Create hooks for relevant stuff the user
+ * might care about, call them at the appropriate places. Design should be:
+ * - Event handlers: the WMs job
+ * - Hooks: user customization
+ *
+ * Current sketch is too complex and we don't need to customize
+ * behavior that much anyway.
+ */
+
+// XCB_CONFIGURE_REQUEST
+static void ev_configure_request(xcb_generic_event_t *);
+typedef void (*configure_request_handler_t)();
+static configure_request_handler_t configure_request_handler = NULL;
+
+void wm_set_configure_request_handler(configure_request_handler_t handler) {
+ configure_request_handler = handler;
+}
+
+static void ev_configure_request(xcb_generic_event_t *generic_ev) {
+ if (configure_request_handler) {
+ xcb_configure_request_event_t *ev = (xcb_configure_request_event_t *) generic_ev;
+ configure_request_handler();
+ }
+}
+
+// XCB_DESTROY_NOTIFY
+static void ev_destroy_notify(xcb_generic_event_t *);
+typedef void (*destroy_notify_handler_t)();
+static destroy_notify_handler_t destroy_notify_handler = NULL;
+
+void wm_set_destroy_notify_handler(destroy_notify_handler_t handler) {
+ destroy_notify_handler = handler;
+}
+
+static void ev_destroy_notify(xcb_generic_event_t *generic_ev) {
+ if (destroy_notify_handler) {
+ xcb_destroy_notify_event_t *ev = (xcb_destroy_notify_event_t *) generic_ev;
+ destroy_notify_handler();
+ }
+}
+
+// XCB_ENTER_NOTIFY
+static void ev_enter_notify(xcb_generic_event_t *);
+typedef void (*enter_notify_handler_t)();
+static enter_notify_handler_t enter_notify_handler = NULL;
+
+void wm_set_enter_notify_handler(enter_notify_handler_t handler) {
+ enter_notify_handler = handler;
+}
+
+static void ev_enter_notify(xcb_generic_event_t *generic_ev) {
+ if (enter_notify_handler) {
+ xcb_enter_notify_event_t *ev = (xcb_enter_notify_event_t *) generic_ev;
+ enter_notify_handler();
+ }
+}
+
+// XCB_KEY_PRESS
+static void ev_key_press(xcb_generic_event_t *);
+typedef void (*key_press_handler_t)();
+static key_press_handler_t key_press_handler = NULL;
+
+void wm_set_key_press_handler(key_press_handler_t handler) {
+ key_press_handler = handler;
+}
+
+static void ev_key_press(xcb_generic_event_t *generic_ev) {
+ if (key_press_handler) {
+ xcb_key_press_event_t *ev = (xcb_key_press_event_t *) generic_ev;
+ key_press_handler();
+ }
+}
+
+// XCB_MAP_REQUEST
+static void ev_map_request(xcb_generic_event_t *);
+typedef void (*map_request_handler_t)();
+static map_request_handler_t map_request_handler = NULL;
+
+void wm_set_map_request_handler(map_request_handler_t handler) {
+ map_request_handler = handler;
+}
+
+static void ev_map_request(xcb_generic_event_t *generic_ev) {
+ if (map_request_handler) {
+ xcb_map_request_event_t *ev = (xcb_map_request_event_t *) generic_ev;
+ map_request_handler();
+ }
+}
+
+// XCB_UNMAP_NOTIFY
+static void ev_unmap_notify(xcb_generic_event_t *);
+typedef void (*unmap_notify_handler_t)();
+static unmap_notify_handler_t unmap_notify_handler = NULL;
+
+void wm_set_unmap_notify_handler(unmap_notify_handler_t handler) {
+ unmap_notify_handler = handler;
+}
+
+static void ev_unmap_notify(xcb_generic_event_t *generic_ev) {
+ if (unmap_notify_handler) {
+ xcb_unmap_notify_event_t *ev = (xcb_unmap_notify_event_t *) generic_ev;
+ unmap_notify_handler();
+ }
+}
+
+// XCB_MAPPING_NOTIFY
+static void ev_mapping_notify(xcb_generic_event_t *);
+typedef void (*mapping_notify_handler_t)();
+static mapping_notify_handler_t mapping_notify_handler = NULL;
+
+void wm_set_mapping_notify_handler(mapping_notify_handler_t handler) {
+ mapping_notify_handler = handler;
+}
+
+static void ev_mapping_notify(xcb_generic_event_t *generic_ev) {
+ if (mapping_notify_handler) {
+ xcb_mapping_notify_event_t *ev = (xcb_mapping_notify_event_t *) generic_ev;
+ mapping_notify_handler();
+ }
+}
+
+// XCB_CONFIGURE_NOTIFY
+static void ev_configure_notify(xcb_generic_event_t *);
+typedef void (*configure_notify_handler_t)(int16_t, int16_t, uint16_t, uint16_t);
+static configure_notify_handler_t configure_notify_handler = NULL;
+
+void wm_set_configure_notify_handler(configure_notify_handler_t handler) {
+ configure_notify_handler = handler;
+}
+
+static void ev_configure_notify(xcb_generic_event_t *generic_ev) {
+ if (configure_notify_handler) {
+ xcb_configure_notify_event_t *ev = (xcb_configure_notify_event_t *) generic_ev;
+ configure_notify_handler(ev->x, ev->y, ev->width, ev->height);
+ }
+}
+
+// XCB_CIRCULATE_REQUEST
+static void ev_circulate_request(xcb_generic_event_t *);
+typedef void (*circulate_request_handler_t)();
+static circulate_request_handler_t circulate_request_handler = NULL;
+
+void wm_set_circulate_request_handler(circulate_request_handler_t handler) {
+ circulate_request_handler = handler;
+}
+
+static void ev_circulate_request(xcb_generic_event_t *generic_ev) {
+ if (circulate_request_handler) {
+ xcb_circulate_request_event_t *ev = (xcb_circulate_request_event_t *) generic_ev;
+ circulate_request_handler();
+ }
+}
+
+// XCB_BUTTON_PRESS
+static void ev_button_press(xcb_generic_event_t *);
+typedef void (*button_press_handler_t)();
+static button_press_handler_t button_press_handler = NULL;
+
+void wm_set_button_press_handler(button_press_handler_t handler) {
+ button_press_handler = handler;
+}
+
+static void ev_button_press(xcb_generic_event_t *generic_ev) {
+ if (button_press_handler) {
+ xcb_button_press_event_t *ev = (xcb_button_press_event_t *) generic_ev;
+ button_press_handler();
+ }
+}
+
+// XCB_CLIENT_MESSAGE
+static void ev_client_message(xcb_generic_event_t *);
+typedef void (*client_message_handler_t)();
+static client_message_handler_t client_message_handler = NULL;
+
+void wm_set_client_message_handler(client_message_handler_t handler) {
+ client_message_handler = handler;
+}
+
+static void ev_client_message(xcb_generic_event_t *generic_ev) {
+ if (client_message_handler) {
+ xcb_client_message_event_t *ev = (xcb_client_message_event_t *) generic_ev;
+ client_message_handler();
+ }
+}
bool wm_init() {
+ memset(events, 0, sizeof(events));
+ events[XCB_CONFIGURE_REQUEST] = ev_configure_request;
+ events[XCB_DESTROY_NOTIFY] = ev_destroy_notify;
+ events[XCB_ENTER_NOTIFY] = ev_enter_notify;
+ events[XCB_KEY_PRESS] = ev_key_press;
+ events[XCB_MAP_REQUEST] = ev_map_request;
+ events[XCB_UNMAP_NOTIFY] = ev_unmap_notify;
+ events[XCB_MAPPING_NOTIFY] = ev_mapping_notify;
+ events[XCB_CONFIGURE_NOTIFY] = ev_configure_notify;
+ events[XCB_CIRCULATE_REQUEST] = ev_circulate_request;
+ events[XCB_BUTTON_PRESS] = ev_button_press;
+ events[XCB_CLIENT_MESSAGE] = ev_client_message;
return true;
}
-void wm_quit(const char *m) {
- printf("hello, %s\n", m);
+void wm_destroy();
+
+void wm_run() {
+ /*
+ while (wm.is_running) {
+ xcb_generic_event_t *ev = xcb_wait_for_event(display_server.conn);
+ int ev_type = ev->response_type & 0x80;
+ generic_event_handler_t handler = wm.events[ev_type];
+ if (handler) {
+ handler(ev);
+ }
+ free(ev);
+ }
+
+ wm_destroy();
+ */
+}
+
+void wm_quit() {
+ if (configure_notify_handler) {
+ // xcb_configure_notify_event_t ev;
+ // ev.x = 0;
+ // ev.y = 1;
+ // ev.width = 2;
+ // ev.height = 3;
+ configure_notify_handler(0, 1, 2, 3);
+ }
}
diff --git a/wm.scm b/wm.scm
index 8304dca..3d46652 100644
--- a/wm.scm
+++ b/wm.scm
@@ -1,6 +1,8 @@
(define-module (wm)
#:use-module (system foreign)
- #:export (wm-init wm-quit))
+ #:export (wm-init
+ wm-set-configure-notify-handler!
+ wm-quit))
(define libschewm (dynamic-link "libschewm"))
@@ -13,12 +15,22 @@
(dynamic-func name libschewm)
args))
+(define c/wm-init
+ (schewm-func int "wm_init" '()))
+
(define (wm-init)
- (let ((c/wm-init
- (schewm-func int "wm_init" '())))
- (int-as-bool (c/wm-init))))
-
-(define (wm-quit s)
- (let ((c/wm-quit
- (schewm-func void "wm_quit" (list '*))))
- (c/wm-quit (string->pointer s))))
+ (int-as-bool (c/wm-init)))
+
+(define wm-quit
+ (schewm-func void "wm_quit" '()))
+
+(define c/wm-set-configure-notify-handler
+ (schewm-func void
+ "wm_set_configure_notify_handler"
+ (list '*)))
+
+(define (wm-set-configure-notify-handler! handler)
+ (c/wm-set-configure-notify-handler
+ (procedure->pointer void
+ handler
+ (list int16 int16 uint32 uint32))))