commit d51d7cd19fad8a5b3f6aa33f224dfafc3c30c2aa
parent b07b53c5fd2814c4fa43bdf4c053637526395914
Author: Luke Willis <lukejw@loquat.dev>
Date:   Sat, 28 Mar 2026 23:21:27 -0400

Basic working configuration with multiple windows

Diffstat:
Mscm/wig.scm | 24+++++++++++++++++++++++-
Msrc/main.c | 143++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
2 files changed, 113 insertions(+), 54 deletions(-)

diff --git a/scm/wig.scm b/scm/wig.scm @@ -1,4 +1,5 @@ (define-module (wig) + #:use-module (srfi srfi-1) #:use-module (srfi srfi-9) #:export (anchors anchors? @@ -11,7 +12,10 @@ window-label window-anchors window-width - window-height)) + window-height + configuration + configuration? + configuration-windows)) (define-record-type <anchors> (make-anchors top bottom left right) @@ -57,4 +61,22 @@ (integer? height) (integer? margin)) (error "Invalid window!")) + (when (and (anchors-top anchors) + (anchors-bottom anchors) + (anchors-left anchors) + (anchors-right anchors) + exclusive) + (error "A window cannot anchor to all sides and still be exclusive.")) (make-window label anchors exclusive width height margin)) + +(define-record-type <configuration> + (make-configuration windows) + configuration? + (windows configuration-windows)) + +(define* (configuration #:key + (windows '())) + (unless (and (list? windows) + (every window? windows)) + (error "Invalid configuration!")) + (make-configuration windows)) diff --git a/src/main.c b/src/main.c @@ -11,6 +11,14 @@ #include "wl.h" +struct wig_window { + char *label; + struct wl_surface *wl_surface; + struct zwlr_layer_surface_v1 *wlr_layer_surface; + + struct wl_shm *shm; +}; + struct wig_state { struct wl_display *display; struct wl_registry *registry; @@ -19,8 +27,7 @@ struct wig_state { struct wl_shm *shm; struct zwlr_layer_shell_v1 *layer_shell; - struct wl_surface *surface; - struct zwlr_layer_surface_v1 *layer_surface; + struct wig_window *windows; }; /* @@ -36,7 +43,7 @@ static const struct wl_buffer_listener wl_buffer_listener = { .release = wl_buffer_release, }; -static struct wl_buffer *draw_frame(struct wig_state *state, int width, +static struct wl_buffer *draw_frame(struct wig_window *state, int width, int height) { int stride = width * 4; @@ -86,12 +93,16 @@ static void zwlr_layer_surface_configure(void *data, struct zwlr_layer_surface_v uint32_t serial, uint32_t width, uint32_t height) { - struct wig_state *state = data; + struct wig_window *window = data; zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial); - struct wl_buffer *buffer = draw_frame(state, width, height); - wl_surface_attach(state->surface, buffer, 0, 0); - wl_surface_commit(state->surface); + struct wl_buffer *buffer = draw_frame(window, width, height); + wl_surface_attach(window->wl_surface, buffer, 0, 0); + wl_surface_commit(window->wl_surface); + + fprintf(stderr, "\"%s\" reconfigured\n", window->label); + fprintf(stderr, " %u x %u\n", width, height); + } static void zwlr_layer_surface_closed(void *data, struct zwlr_layer_surface_v1 @@ -137,62 +148,90 @@ registry_handle_global_remove(void *data, struct wl_registry *registry, } static const struct wl_registry_listener registry_listener = { - .global = registry_handle_global, - .global_remove = registry_handle_global_remove, -}; +.global = registry_handle_global,.global_remove = + registry_handle_global_remove,}; /* Main */ -static void -inner_main (void *data, int argc, char **argv) +static void inner_main(void *data, int argc, char **argv) { struct wig_state *state = data; /* Evaluate configuration */ - SCM wig_window_type = scm_c_private_ref("wig", "<window>"); + SCM wig_configuration_type = + scm_c_private_ref("wig", "<configuration>"); SCM config = scm_c_primitive_load("wig.scm"); - if (scm_is_false(scm_eq_p(scm_struct_vtable(config), wig_window_type))) { - fprintf(stderr, "Invalid configuration!\n"); - return; + /* TODO: Catch errors properly */ + if (scm_is_false + (scm_eq_p(scm_struct_vtable(config), wig_configuration_type))) { + fprintf(stderr, "Invalid configuration!\n"); + return; } - /* The configuration is validated on the Scheme side of things. */ - - char *label = scm_to_utf8_stringn(scm_struct_ref(config, scm_from_int(0)), - NULL); - SCM anchors = scm_struct_ref(config, scm_from_int(1)); - uint32_t anchor = 0; - for (uint32_t i = 0; i < 4; i++) - if (scm_is_true(scm_struct_ref(anchors, scm_from_uint32(i)))) - anchor |= (1 << i); - - int exclusive = scm_is_true(scm_struct_ref(config, scm_from_int(2))); - - uint32_t width = scm_to_uint32(scm_struct_ref(config, scm_from_int(3))); - uint32_t height = scm_to_uint32(scm_struct_ref(config, scm_from_int(4))); - uint32_t margin = scm_to_uint32(scm_struct_ref(config, scm_from_int(5))); - - /* Create surface */ - state->surface = wl_compositor_create_surface(state->compositor); - state->layer_surface = - zwlr_layer_shell_v1_get_layer_surface(state->layer_shell, - state->surface, - NULL, - ZWLR_LAYER_SHELL_V1_LAYER_TOP, - label); - zwlr_layer_surface_v1_add_listener(state->layer_surface, - &layer_surface_listener, state); - zwlr_layer_surface_v1_set_size(state->layer_surface, width, height); - zwlr_layer_surface_v1_set_anchor(state->layer_surface, anchor); - - /* TODO: Select correct dimensions */ - if (exclusive) - zwlr_layer_surface_v1_set_exclusive_zone(state->layer_surface, height); - - zwlr_layer_surface_v1_set_margin(state->layer_surface, margin, margin, margin, margin); - wl_surface_commit(state->surface); + SCM windows = scm_struct_ref(config, scm_from_int(0)); + size_t num_windows = scm_to_size_t(scm_length(windows)); + state->windows = malloc(num_windows * sizeof(struct wig_window)); + + for (size_t i = 0; i < num_windows; i++) { + SCM scm_window = scm_car(windows); + + char *label = + scm_to_utf8_stringn(scm_struct_ref + (scm_window, scm_from_int(0)), NULL); + + SCM anchors = scm_struct_ref(scm_window, scm_from_int(1)); + uint32_t anchor = 0; + for (uint32_t i = 0; i < 4; i++) + if (scm_is_true(scm_struct_ref(anchors, scm_from_uint32(i)))) + anchor |= (1 << i); + + int exclusive = scm_is_true(scm_struct_ref(scm_window, scm_from_int(2))); + + uint32_t width = + scm_to_uint32(scm_struct_ref(scm_window, scm_from_int(3))); + uint32_t height = + scm_to_uint32(scm_struct_ref(scm_window, scm_from_int(4))); + uint32_t margin = + scm_to_uint32(scm_struct_ref(scm_window, scm_from_int(5))); + + struct wig_window *window = &state->windows[i]; + window->label = label; + window->shm = state->shm; + + window->wl_surface = + wl_compositor_create_surface(state->compositor); + window->wlr_layer_surface = + zwlr_layer_shell_v1_get_layer_surface(state->layer_shell, + window->wl_surface, NULL, + ZWLR_LAYER_SHELL_V1_LAYER_TOP, + label); + + zwlr_layer_surface_v1_add_listener(window->wlr_layer_surface, + &layer_surface_listener, + window); + zwlr_layer_surface_v1_set_size(window->wlr_layer_surface, + width, height); + zwlr_layer_surface_v1_set_anchor(window->wlr_layer_surface, anchor); + zwlr_layer_surface_v1_set_margin(window->wlr_layer_surface, margin, margin, margin, margin); + + if (exclusive) { + if ((anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) && + (anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM)) { + zwlr_layer_surface_v1_set_exclusive_zone(window->wlr_layer_surface, + width); + } else if ((anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT) && + (anchor & ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT)) { + zwlr_layer_surface_v1_set_exclusive_zone(window->wlr_layer_surface, + height); + } + } + + wl_surface_commit(window->wl_surface); + + windows = scm_cdr(windows); + } /* Loop */ while (wl_display_dispatch(state->display) != -1) { @@ -201,8 +240,6 @@ inner_main (void *data, int argc, char **argv) /* Cleanup */ wl_display_disconnect(state->display); - - free(label); } int main(int argc, char *argv[])