aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArslaan Pathan <[email protected]>2026-05-15 10:17:57 +1200
committerArslaan Pathan <[email protected]>2026-05-15 10:18:14 +1200
commite5ee38e9b97581fb204f60c92fdb4659bb2cf3c8 (patch)
tree6878f85f0465ef558308f669917fa8af30b5c5c7
parentbe3da49ea23bbadf04c8a9b9190598a257a33bf2 (diff)
downloadsimple-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.c167
1 files changed, 112 insertions, 55 deletions
diff --git a/main.c b/main.c
index 154afef..3b9db79 100644
--- a/main.c
+++ b/main.c
@@ -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, &registry_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, &registry_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;
}