diff options
| author | Arslaan Pathan <[email protected]> | 2026-05-15 10:17:57 +1200 |
|---|---|---|
| committer | Arslaan Pathan <[email protected]> | 2026-05-15 10:18:14 +1200 |
| commit | e5ee38e9b97581fb204f60c92fdb4659bb2cf3c8 (patch) | |
| tree | 6878f85f0465ef558308f669917fa8af30b5c5c7 | |
| parent | be3da49ea23bbadf04c8a9b9190598a257a33bf2 (diff) | |
| download | simple-wayland-client-e5ee38e9b97581fb204f60c92fdb4659bb2cf3c8.tar.xz simple-wayland-client-e5ee38e9b97581fb204f60c92fdb4659bb2cf3c8.zip | |
actually work (and this doesnt even handle resizes properly yet T_T)
| -rw-r--r-- | main.c | 167 |
1 files changed, 112 insertions, 55 deletions
@@ -1,109 +1,166 @@ #define _POSIX_C_SOURCE 200112L #include <wayland-client.h> +#include <wayland-client-protocol.h> #include "xdg-shell-client-protocol.h" #include <stdio.h> -#include <stdlib.h> #include <unistd.h> #include <string.h> - -struct wl_display *display = NULL; -struct wl_registry *registry = NULL; -struct wl_compositor *compositor = NULL; -struct xdg_wm_base *wm_base = NULL; -struct wl_surface *surface = NULL; -struct xdg_surface *xdg_surface = NULL; -struct xdg_toplevel *xdg_toplevel = NULL; +#include <sys/mman.h> +#include <fcntl.h> + +struct wl_display* display = NULL; +struct wl_registry* registry = NULL; +struct wl_compositor* compositor = NULL; +struct xdg_wm_base* wm_base = NULL; +struct wl_surface* surface = NULL; +struct xdg_surface* xdg_surface = NULL; +struct xdg_toplevel* xdg_toplevel = NULL; +struct wl_shm* shm = NULL; +struct wl_buffer* buffer = NULL; +void* pixel_data = NULL; +int width = 1024, height = 768; +int running = 1; static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) { - xdg_wm_base_pong(xdg_wm_base, serial); + xdg_wm_base_pong(xdg_wm_base, serial); } static const struct xdg_wm_base_listener wm_base_listener = { - .ping = xdg_wm_base_ping, + .ping = xdg_wm_base_ping, }; static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { - xdg_surface_ack_configure(xdg_surface, serial); + xdg_surface_ack_configure(xdg_surface, serial); } static const struct xdg_surface_listener xdg_surface_listener = { - .configure = xdg_surface_configure, + .configure = xdg_surface_configure, }; static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, - int32_t width, int32_t height, struct wl_array *states) + int32_t w, int32_t h, struct wl_array *states) { - /* just exist */ + if (w > 0 && h > 0) { + width = w; + height = h; + } } static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) { - printf("close requested\n"); - exit(0); + running = 0; } static const struct xdg_toplevel_listener xdg_toplevel_listener = { - .configure = xdg_toplevel_configure, - .close = xdg_toplevel_close, + .configure = xdg_toplevel_configure, + .close = xdg_toplevel_close, }; static void registry_handle_global(void *data, struct wl_registry *reg, uint32_t id, - const char *interface, uint32_t version) + const char *interface, uint32_t version) { - if (strcmp(interface, wl_compositor_interface.name) == 0) { - compositor = wl_registry_bind(reg, id, &wl_compositor_interface, 4); - } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { - wm_base = wl_registry_bind(reg, id, &xdg_wm_base_interface, 1); - xdg_wm_base_add_listener(wm_base, &wm_base_listener, NULL); - } + if (strcmp(interface, wl_compositor_interface.name) == 0) { + compositor = wl_registry_bind(reg, id, &wl_compositor_interface, 4); + } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { + wm_base = wl_registry_bind(reg, id, &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(wm_base, &wm_base_listener, NULL); + } else if (strcmp(interface, wl_shm_interface.name) == 0) { + shm = wl_registry_bind(reg, id, &wl_shm_interface, 1); + } } static void registry_handle_global_remove(void *data, struct wl_registry *reg, uint32_t id) { - /* ignore */ } 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, }; +struct wl_buffer* create_buffer(int w, int h, void** data_out) { + int stride = w * 4; + int size = stride * h; + int fd = shm_open("/wl_shm", O_CREAT | O_RDWR, 0600); + if (fd < 0) return NULL; + if (ftruncate(fd, size) < 0) { + close(fd); + return NULL; + } + void* data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + close(fd); + return NULL; + } + struct wl_shm_pool* pool = wl_shm_create_pool(shm, fd, size); + struct wl_buffer* buf = wl_shm_pool_create_buffer(pool, 0, w, h, stride, WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + close(fd); + shm_unlink("/wl_shm"); + *data_out = data; + return buf; +} + +void draw_window() { + uint32_t* pixels = (uint32_t*)pixel_data; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (x > 100 && x < 300 && y > 100 && y < 200) + pixels[y * width + x] = 0xFFFF0000; + else + pixels[y * width + x] = 0xFF202020; + } + } +} + int main(void) { - display = wl_display_connect(NULL); - if (!display) { - fprintf(stderr, "can't connect\n"); - return 1; - } + display = wl_display_connect(NULL); + if (!display) { + fprintf(stderr, "can't connect\n"); + return 1; + } + + registry = wl_display_get_registry(display); + wl_registry_add_listener(registry, ®istry_listener, NULL); + wl_display_roundtrip(display); + wl_display_roundtrip(display); + + if (!compositor || !wm_base || !shm) { + fprintf(stderr, "missing required interfaces\n"); + return 1; + } + + surface = wl_compositor_create_surface(compositor); + xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, surface); + xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, NULL); - registry = wl_display_get_registry(display); - wl_registry_add_listener(registry, ®istry_listener, NULL); - wl_display_roundtrip(display); + xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); + xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title(xdg_toplevel, "wayland window"); - if (!compositor || !wm_base) { - fprintf(stderr, "missing compositor or xdg_wm_base\n"); - return 1; - } + wl_surface_commit(surface); + wl_display_roundtrip(display); - surface = wl_compositor_create_surface(compositor); - xdg_surface = xdg_wm_base_get_xdg_surface(wm_base, surface); - xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, NULL); + buffer = create_buffer(width, height, &pixel_data); + if (!buffer) { + fprintf(stderr, "failed to create buffer\n"); + return 1; + } - xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); - xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL); - xdg_toplevel_set_title(xdg_toplevel, "wayland window"); + draw_window(); - wl_surface_commit(surface); - wl_display_roundtrip(display); + wl_surface_attach(surface, buffer, 0, 0); + wl_surface_damage(surface, 0, 0, width, height); + wl_surface_commit(surface); - printf("window open, running...\n"); + printf("window open, running...\n"); - while (wl_display_dispatch(display) != -1) { - /* events handled by callbacks */ - } + while (running && wl_display_dispatch(display) != -1) { + } - wl_display_disconnect(display); - return 0; + wl_display_disconnect(display); + return 0; } |
