#include "ark_wayland_client.h" #include #include #include #include #include #include #include static struct wl_display *display = NULL; static struct wl_registry *registry = NULL; static struct wl_compositor *compositor = NULL; static struct wl_shm *shm = NULL; static struct wl_surface *surface = NULL; static struct wl_buffer *buffer = NULL; static uint8_t *shm_data = NULL; static int shm_size = 0; static void registry_handler(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { if (strcmp(interface, "wl_compositor") == 0) { compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); } else if (strcmp(interface, "wl_shm") == 0) { shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); } } static void registry_remover(void *data, struct wl_registry *registry, uint32_t id) { // Handling removals not strictly needed for this simple client } static const struct wl_registry_listener registry_listener = { registry_handler, registry_remover }; bool ark_wayland_client_init(void) { display = wl_display_connect(NULL); if (!display) { fprintf(stderr, "ArkGraphics (Client): Failed to connect to Wayland display\n"); return false; } registry = wl_display_get_registry(display); wl_registry_add_listener(registry, ®istry_listener, NULL); // Wait for globals wl_display_roundtrip(display); if (!compositor || !shm) { fprintf(stderr, "ArkGraphics (Client): Compositor or SHM interface not found on Wayland server\n"); return false; } printf("ArkGraphics (Client): Connected to Wayland Server\n"); return true; } void ark_wayland_client_shutdown(void) { if (buffer) wl_buffer_destroy(buffer); if (surface) wl_surface_destroy(surface); if (shm_data) munmap(shm_data, shm_size); if (shm) wl_shm_destroy(shm); if (compositor) wl_compositor_destroy(compositor); if (registry) wl_registry_destroy(registry); if (display) wl_display_disconnect(display); } // OS helper for memfd create (if syscall not wrapped by libc, we can just use memfd_create) #include #include static int os_create_anonymous_file(off_t size) { int fd = syscall(SYS_memfd_create, "ark_wayland_shm", MFD_CLOEXEC); if (fd < 0) return -1; if (ftruncate(fd, size) < 0) { close(fd); return -1; } return fd; } uint8_t* ark_wayland_client_create_surface(int width, int height) { if (!compositor || !shm) return NULL; surface = wl_compositor_create_surface(compositor); if (!surface) return NULL; int stride = width * 4; // 4 bytes per pixel (ARGB8888) shm_size = stride * height; int fd = os_create_anonymous_file(shm_size); if (fd < 0) { fprintf(stderr, "ArkGraphics (Client): Failed to create SHM file\n"); return NULL; } shm_data = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (shm_data == MAP_FAILED) { close(fd); return NULL; } struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, shm_size); buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); wl_shm_pool_destroy(pool); // Pool object can be destroyed once buffer is created close(fd); // Wayland server keeps the fd open internally return shm_data; } void ark_wayland_client_commit(void) { if (!surface || !buffer) return; // Attach the buffer to the surface wl_surface_attach(surface, buffer, 0, 0); // Mark the entire surface as damaged so the compositor redraws it wl_surface_damage(surface, 0, 0, INT32_MAX, INT32_MAX); // Commit the surface state wl_surface_commit(surface); // Flush the display to ensure messages are sent wl_display_flush(display); }