#define _POSIX_C_SOURCE 200112L #include #include #include "xdg-shell-client-protocol.h" #include #include #include #include #include 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); } static const struct xdg_wm_base_listener wm_base_listener = { .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); } static const struct xdg_surface_listener xdg_surface_listener = { .configure = xdg_surface_configure, }; static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t w, int32_t h, struct wl_array *states) { if (w > 0 && h > 0) { width = w; height = h; } } static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) { running = 0; } static const struct xdg_toplevel_listener xdg_toplevel_listener = { .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) { 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) { } static const struct wl_registry_listener registry_listener = { .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; } 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); 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"); wl_surface_commit(surface); wl_display_roundtrip(display); buffer = create_buffer(width, height, &pixel_data); if (!buffer) { fprintf(stderr, "failed to create buffer\n"); return 1; } draw_window(); wl_surface_attach(surface, buffer, 0, 0); wl_surface_damage(surface, 0, 0, width, height); wl_surface_commit(surface); printf("window open, running...\n"); while (running && wl_display_dispatch(display) != -1) { } wl_display_disconnect(display); return 0; }