window.c (3879B)


      1 /*
      2  * Wig --- Widgets in Guile
      3  * Copyright © 2026 Luke Willis <lukejw@monastech.xyz>
      4  *
      5  * This file is part of Wig.
      6  *
      7  * Wig is free software: you can redistribute it and/or modify it under
      8  * the terms of the GNU General Public License as published by the Free
      9  * Software Foundation, either version 3 of the License, or (at your option)
     10  * any later version.
     11  *
     12  * Wig is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
     15  * more details.
     16  *
     17  * You should have received a copy of the GNU General Public License along
     18  * with Wig. If not, see <https://www.gnu.org/licenses/>.
     19  */
     20 
     21 #include <stdint.h>
     22 #include <stdio.h>
     23 
     24 #include "wlr-layer-shell-unstable-v1-client-protocol.h"
     25 #include <pixman.h>
     26 #include <wayland-client.h>
     27 
     28 #include "globals.h"
     29 #include "surface.h"
     30 #include "window.h"
     31 
     32 static inline uint32_t
     33 min_u32(uint32_t a, uint32_t b)
     34 {
     35 	return (a < b) ? a : b;
     36 }
     37 
     38 static inline uint32_t
     39 max_u32(uint32_t a, uint32_t b)
     40 {
     41 	return (a > b) ? a : b;
     42 }
     43 
     44 static void
     45 zwlr_layer_surface_v1_configure(
     46 	void *data, struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1,
     47 	uint32_t serial, uint32_t width, uint32_t height)
     48 {
     49 	zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial);
     50 
     51 	struct wig_window *window = data;
     52 
     53 	/* Skip pointless reconfiguration */
     54 	if (window->surface.configured && width == window->surface.width &&
     55 	    height == window->surface.height) {
     56 		return;
     57 	}
     58 
     59 	int result = wig_surface_reconfigure(&window->surface, width, height);
     60 
     61 	if (result) {
     62 		fprintf(stderr, "Failed to reconfigure %s's surface\n",
     63 		        window->label);
     64 		return;
     65 	}
     66 
     67 	size_t num_widgets =
     68 		scm_to_size_t(scm_wig_count_widgets(window->widgets));
     69 	size_t size = num_widgets * sizeof(struct wig_widget);
     70 	struct wig_widget *widgets = malloc(size);
     71 	SCM bv = scm_c_pointer_to_bytevector(widgets, size);
     72 
     73 	scm_wig_compile_widgets(window->widgets, window->surface.width,
     74 	                        window->surface.height, bv);
     75 
     76 	for (size_t i = 0; i < num_widgets; i++) {
     77 		struct wig_widget widget = widgets[i];
     78 
     79 		fprintf(stderr, "Widget %zu\n", i);
     80 		fprintf(stderr, "  X: %u\n", widget.x);
     81 		fprintf(stderr, "  Y: %u\n", widget.y);
     82 		fprintf(stderr, "  W: %u\n", widget.width);
     83 		fprintf(stderr, "  H: %u\n", widget.height);
     84 		fprintf(stderr, "  Color: %08X\n", widget.color);
     85 		fprintf(stderr, "  Flags: %08X\n", widget.flags);
     86 
     87 		if (widget.flags & WIDGET_GHOST) {
     88 			fprintf(stderr, "    Ghost!\n");
     89 			continue;
     90 		}
     91 
     92 		if (widget.x >= width || widget.y >= height) {
     93 			fprintf(stderr, "  Out of bounds! Skipping...\n");
     94 			continue;
     95 		}
     96 
     97 		pixman_fill(window->surface.buffer, width, 32, widget.x,
     98 		            widget.y, min_u32(widget.width, width - widget.x),
     99 		            min_u32(widget.height, height - widget.y),
    100 		            widget.color | 0xFF000000);
    101 	}
    102 
    103 	wig_surface_commit(&window->surface);
    104 }
    105 
    106 static void
    107 zwlr_layer_surface_v1_closed(
    108 	void *data, struct zwlr_layer_surface_v1 *zwlr_layer_surface_v1)
    109 {
    110 	/* TODO */
    111 }
    112 
    113 static const struct zwlr_layer_surface_v1_listener
    114 	zwlr_layer_surface_v1_listener = {
    115 		.configure = zwlr_layer_surface_v1_configure,
    116 		.closed = zwlr_layer_surface_v1_closed,
    117 	};
    118 
    119 int
    120 wig_window_init(struct wig_window *window, char *label,
    121                 struct wig_surface surface,
    122                 struct zwlr_layer_shell_v1 *zwlr_layer_shell_v1)
    123 {
    124 	window->label = label;
    125 	window->surface = surface;
    126 
    127 	window->zwlr_layer_surface_v1 = zwlr_layer_shell_v1_get_layer_surface(
    128 		zwlr_layer_shell_v1, window->surface.wl_surface, NULL,
    129 		ZWLR_LAYER_SHELL_V1_LAYER_TOP, label);
    130 	zwlr_layer_surface_v1_add_listener(window->zwlr_layer_surface_v1,
    131 	                                   &zwlr_layer_surface_v1_listener,
    132 	                                   window);
    133 
    134 	return 0;
    135 }