#include "ark_wayland_server.h" #include #include #include #include #include static struct wl_display *display = NULL; static struct wl_event_loop *event_loop = NULL; static uint8_t* g_render_buffer = NULL; static int g_width = 1920; static int g_height = 1080; static int g_bpp = 4; struct ark_surface { struct wl_resource *resource; struct wl_resource *pending_buffer; }; // Surface interface implementations static void surface_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); } static void surface_attach(struct wl_client *client, struct wl_resource *resource, struct wl_resource *buffer, int32_t x, int32_t y) { struct ark_surface *surface = wl_resource_get_user_data(resource); surface->pending_buffer = buffer; } static void surface_damage(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) { // Basic implementation ignores partial damage and redraws all } static void surface_frame(struct wl_client *client, struct wl_resource *resource, uint32_t callback) { // Send frame event immediately for now (60fps limit handled by client or main loop) struct wl_resource *cb_resource = wl_resource_create(client, &wl_callback_interface, 1, callback); wl_callback_send_done(cb_resource, 0); wl_resource_destroy(cb_resource); } static void surface_set_opaque_region(struct wl_client *client, struct wl_resource *resource, struct wl_resource *region) {} static void surface_set_input_region(struct wl_client *client, struct wl_resource *resource, struct wl_resource *region) {} static void surface_commit(struct wl_client *client, struct wl_resource *resource) { struct ark_surface *surface = wl_resource_get_user_data(resource); if (surface->pending_buffer && g_render_buffer) { struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get(surface->pending_buffer); if (shm_buffer) { wl_shm_buffer_begin_access(shm_buffer); void *data = wl_shm_buffer_get_data(shm_buffer); int stride = wl_shm_buffer_get_stride(shm_buffer); int height = wl_shm_buffer_get_height(shm_buffer); int width = wl_shm_buffer_get_width(shm_buffer); // Copy buffer to global render buffer int max_y = (height < g_height) ? height : g_height; int max_bytes = (stride < g_width * g_bpp) ? stride : g_width * g_bpp; for (int y = 0; y < max_y; y++) { memcpy(g_render_buffer + (y * g_width * g_bpp), ((uint8_t*)data) + (y * stride), max_bytes); } wl_shm_buffer_end_access(shm_buffer); // Send release event to client wl_buffer_send_release(surface->pending_buffer); surface->pending_buffer = NULL; } } } static void surface_set_buffer_transform(struct wl_client *client, struct wl_resource *resource, int32_t transform) {} static void surface_set_buffer_scale(struct wl_client *client, struct wl_resource *resource, int32_t scale) {} static void surface_damage_buffer(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) {} static const struct wl_surface_interface surface_implementation = { surface_destroy, surface_attach, surface_damage, surface_frame, surface_set_opaque_region, surface_set_input_region, surface_commit, surface_set_buffer_transform, surface_set_buffer_scale, surface_damage_buffer }; static void destroy_surface(struct wl_resource *resource) { struct ark_surface *surface = wl_resource_get_user_data(resource); free(surface); } // Compositor interface implementations static void compositor_create_surface(struct wl_client *client, struct wl_resource *resource, uint32_t id) { struct ark_surface *surface = calloc(1, sizeof(struct ark_surface)); surface->resource = wl_resource_create(client, &wl_surface_interface, 4, id); wl_resource_set_implementation(surface->resource, &surface_implementation, surface, destroy_surface); } static void compositor_create_region(struct wl_client *client, struct wl_resource *resource, uint32_t id) { // Regions are not fully supported yet in minimal server } static const struct wl_compositor_interface compositor_implementation = { compositor_create_surface, compositor_create_region }; static void bind_compositor(struct wl_client *client, void *data, uint32_t version, uint32_t id) { struct wl_resource *resource = wl_resource_create(client, &wl_compositor_interface, version, id); wl_resource_set_implementation(resource, &compositor_implementation, NULL, NULL); } void ark_compositor_set_render_buffer(uint8_t* buffer, int width, int height, int bpp) { g_render_buffer = buffer; g_width = width; g_height = height; g_bpp = bpp; } bool ark_compositor_init(void) { display = wl_display_create(); if (!display) { fprintf(stderr, "ArkCompositor: Failed to create Wayland display\n"); return false; } event_loop = wl_display_get_event_loop(display); // Initialize SHM (shared memory) wl_display_init_shm(display); // Initialize Compositor wl_global_create(display, &wl_compositor_interface, 4, display, bind_compositor); // Add socket (this will usually bind to wayland-0) const char *socket = wl_display_add_socket_auto(display); if (!socket) { fprintf(stderr, "ArkCompositor: Failed to add socket\n"); wl_display_destroy(display); display = NULL; return false; } printf("ArkCompositor: Wayland server listening on socket '%s'\n", socket); return true; } void ark_compositor_dispatch(void) { if (display && event_loop) { wl_display_flush_clients(display); wl_event_loop_dispatch(event_loop, 0); // Non-blocking dispatch } } void ark_compositor_shutdown(void) { if (display) { wl_display_destroy(display); display = NULL; event_loop = NULL; } }