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:
| M | scm/wig.scm | | | 24 | +++++++++++++++++++++++- |
| M | src/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[])