ark_wayland_client.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #include "ark_wayland_client.h"
  2. #include <wayland-client.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <fcntl.h>
  8. #include <sys/mman.h>
  9. static struct wl_display *display = NULL;
  10. static struct wl_registry *registry = NULL;
  11. static struct wl_compositor *compositor = NULL;
  12. static struct wl_shm *shm = NULL;
  13. static struct wl_surface *surface = NULL;
  14. static struct wl_buffer *buffer = NULL;
  15. static uint8_t *shm_data = NULL;
  16. static int shm_size = 0;
  17. static void registry_handler(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) {
  18. if (strcmp(interface, "wl_compositor") == 0) {
  19. compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1);
  20. } else if (strcmp(interface, "wl_shm") == 0) {
  21. shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
  22. }
  23. }
  24. static void registry_remover(void *data, struct wl_registry *registry, uint32_t id) {
  25. // Handling removals not strictly needed for this simple client
  26. }
  27. static const struct wl_registry_listener registry_listener = {
  28. registry_handler,
  29. registry_remover
  30. };
  31. bool ark_wayland_client_init(void) {
  32. display = wl_display_connect(NULL);
  33. if (!display) {
  34. fprintf(stderr, "ArkGraphics (Client): Failed to connect to Wayland display\n");
  35. return false;
  36. }
  37. registry = wl_display_get_registry(display);
  38. wl_registry_add_listener(registry, &registry_listener, NULL);
  39. // Wait for globals
  40. wl_display_roundtrip(display);
  41. if (!compositor || !shm) {
  42. fprintf(stderr, "ArkGraphics (Client): Compositor or SHM interface not found on Wayland server\n");
  43. return false;
  44. }
  45. printf("ArkGraphics (Client): Connected to Wayland Server\n");
  46. return true;
  47. }
  48. void ark_wayland_client_shutdown(void) {
  49. if (buffer) wl_buffer_destroy(buffer);
  50. if (surface) wl_surface_destroy(surface);
  51. if (shm_data) munmap(shm_data, shm_size);
  52. if (shm) wl_shm_destroy(shm);
  53. if (compositor) wl_compositor_destroy(compositor);
  54. if (registry) wl_registry_destroy(registry);
  55. if (display) wl_display_disconnect(display);
  56. }
  57. // OS helper for memfd create (if syscall not wrapped by libc, we can just use memfd_create)
  58. #include <sys/syscall.h>
  59. #include <linux/memfd.h>
  60. static int os_create_anonymous_file(off_t size) {
  61. int fd = syscall(SYS_memfd_create, "ark_wayland_shm", MFD_CLOEXEC);
  62. if (fd < 0) return -1;
  63. if (ftruncate(fd, size) < 0) {
  64. close(fd);
  65. return -1;
  66. }
  67. return fd;
  68. }
  69. uint8_t* ark_wayland_client_create_surface(int width, int height) {
  70. if (!compositor || !shm) return NULL;
  71. surface = wl_compositor_create_surface(compositor);
  72. if (!surface) return NULL;
  73. int stride = width * 4; // 4 bytes per pixel (ARGB8888)
  74. shm_size = stride * height;
  75. int fd = os_create_anonymous_file(shm_size);
  76. if (fd < 0) {
  77. fprintf(stderr, "ArkGraphics (Client): Failed to create SHM file\n");
  78. return NULL;
  79. }
  80. shm_data = mmap(NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  81. if (shm_data == MAP_FAILED) {
  82. close(fd);
  83. return NULL;
  84. }
  85. struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, shm_size);
  86. buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
  87. wl_shm_pool_destroy(pool); // Pool object can be destroyed once buffer is created
  88. close(fd); // Wayland server keeps the fd open internally
  89. return shm_data;
  90. }
  91. void ark_wayland_client_commit(void) {
  92. if (!surface || !buffer) return;
  93. // Attach the buffer to the surface
  94. wl_surface_attach(surface, buffer, 0, 0);
  95. // Mark the entire surface as damaged so the compositor redraws it
  96. wl_surface_damage(surface, 0, 0, INT32_MAX, INT32_MAX);
  97. // Commit the surface state
  98. wl_surface_commit(surface);
  99. // Flush the display to ensure messages are sent
  100. wl_display_flush(display);
  101. }