diff --git a/nasm.code-workspace b/nasm.code-workspace index 6e8cf42..e4325b9 100644 --- a/nasm.code-workspace +++ b/nasm.code-workspace @@ -14,5 +14,9 @@ "debug.allowBreakpointsEverywhere": true, "debug.inlineValues": "on", "editor.codeLens": false, + "files.associations": { + "flake.lock": "json", + "ios": "c" + }, } } diff --git a/wayland/asm.asm b/wayland/asm.asm index 0e4d53a..65e38cd 100644 --- a/wayland/asm.asm +++ b/wayland/asm.asm @@ -6,6 +6,4 @@ main: enter 0, 0 call run_wayland leave - - mov rax, 0 ret \ No newline at end of file diff --git a/wayland/c.c b/wayland/c.c index 4780e43..3c2ffef 100644 --- a/wayland/c.c +++ b/wayland/c.c @@ -6,95 +6,189 @@ #include #include "xdg-shell-client-protocol.h" -static struct wl_display *display; -static struct wl_registry *registry; static struct wl_compositor *compositor; -static struct wl_shm *shm; static struct xdg_wm_base *xdg_wm_base; -static struct wl_surface *surface; + +// Всё ниже - для одного окна static struct xdg_surface *xdg_surface; static struct xdg_toplevel *xdg_toplevel; -static volatile int running = 1; -static int width = 800, height = 600; +static struct wl_surface *wl_surface; +static struct wl_buffer *buffer; +static struct wl_shm *shm; +static int16_t width = 200; +static int16_t height = 100; +static int8_t *data; +static int8_t need_close = 0; -static void registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { - if (strcmp(interface, "wl_compositor") == 0) { - compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1); - } else if (strcmp(interface, "wl_shm") == 0) { - shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); - } else if (strcmp(interface, "xdg_wm_base") == 0) { - xdg_wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1); +int32_t alloc_shm(size_t size) +{ + char name[32]; + sprintf(name, "/wayland-shm-%d", getpid()); + + int32_t fd = shm_open(name, O_RDWR | O_CREAT, 0600); + if (fd == -1) + return fd; + shm_unlink(name); + ftruncate(fd, size); + return fd; +} + +void resize_canvas() +{ + size_t stride = width * 4; + size_t size = stride * height; + int32_t fd = alloc_shm(size); + + data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); + buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + close(fd); +} + +void resize_new(int16_t w, int16_t h) +{ + if (!w || !h) + return; + if (width != w || height != h) + { + if(data) + munmap(data, width*height*4); + width = w; + height = h; + resize_canvas(); } } -static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) {} +int8_t c; +void draw() +{ + size_t stride = width * 4; + size_t size = stride * height; -static const struct wl_registry_listener registry_listener = { - .global = registry_global, - .global_remove = registry_global_remove, -}; + memset(data, c++, size); -static void create_buffer(); + wl_surface_attach(wl_surface, buffer, 0, 0); + wl_surface_damage_buffer(wl_surface, 0, 0, width, height); + wl_surface_commit(wl_surface); +} -static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { +void xdg_surface_conf(void *data, struct xdg_surface *xdg_surface, uint32_t serial) +{ xdg_surface_ack_configure(xdg_surface, serial); - create_buffer(); + if (!data) + resize_canvas(); + + draw(); } -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) width = w; - if (h > 0) height = h; +void xdg_toplevel_conf(void *data, struct xdg_toplevel *xdg_top, int32_t w, int32_t h, struct wl_array *states) +{ + resize_new(w, h); } -static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) { - running = 0; +void xdg_toplevel_cls(void *data, struct xdg_toplevel *xdg_top) +{ + need_close = 1; } -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - .configure = xdg_toplevel_configure, - .close = xdg_toplevel_close, -}; - -static void create_buffer() { - char name[32]; - sprintf(name, "/wayland-shm-%d", getpid()); - int stride = width * 4; - int size = stride * height; - int fd = shm_open(name, O_RDWR | O_CREAT, 0600); - if (fd == -1) return; - ftruncate(fd, size); - void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - memset(data, 0xFF, size); // white - struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); - struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); - wl_surface_attach(surface, buffer, 0, 0); - wl_surface_damage(surface, 0, 0, width, height); - wl_surface_commit(surface); - wl_buffer_destroy(buffer); - wl_shm_pool_destroy(pool); - close(fd); - shm_unlink(name); - munmap(data, size); +void xdg_toplevel_bounds(void *data, struct xdg_toplevel *xdg_top, int32_t w, int32_t h) +{ } -void run_wayland() { - display = wl_display_connect(NULL); - if (!display) return; - registry = wl_display_get_registry(display); - wl_registry_add_listener(registry, ®istry_listener, NULL); - wl_display_dispatch(display); +void xdg_toplevel_wm_caps(void *data, struct xdg_toplevel *xdg_top, struct wl_array *caps) +{ +} + +struct wl_callback_listener callback_listener; +void frame_new(void *date, struct wl_callback *cb, uint32_t _) +{ + wl_callback_destroy(cb); + cb = wl_surface_frame(wl_surface); + wl_callback_add_listener(cb, &callback_listener, 0); + draw(); +} + +void wm_base_ping(void *data, struct xdg_wm_base *wm_base, uint32_t serial) +{ + xdg_wm_base_pong(wm_base, serial); +} + +struct xdg_wm_base_listener wm_base_listener; +// Функция для прослушивания глобальных объектов +void registry_global(void *data, struct wl_registry *reg, uint32_t name, const char *intf, uint32_t version) +{ + printf("%u\t%s\tv:%u\n", name, intf, version); + if (!strcmp(intf, wl_compositor_interface.name)) + { + compositor = wl_registry_bind(reg, name, &wl_compositor_interface, version); + } + else if (!strcmp(intf, wl_shm_interface.name)) + { + shm = wl_registry_bind(reg, name, &wl_shm_interface, version); + } + else if (!strcmp(intf, xdg_wm_base_interface.name)) + { + xdg_wm_base = wl_registry_bind(reg, name, &xdg_wm_base_interface, version); + xdg_wm_base_add_listener(xdg_wm_base, &wm_base_listener, 0); + } +} + +void registry_global_remove(void *data, struct wl_registry *reg, uint32_t name) {} + +struct wl_callback_listener callback_listener = { + .done = frame_new}; + +struct xdg_wm_base_listener wm_base_listener = { + .ping = wm_base_ping}; + +struct xdg_toplevel_listener top_listener = { + .configure = xdg_toplevel_conf, + .close = xdg_toplevel_cls, + .configure_bounds = xdg_toplevel_bounds, + .wm_capabilities = xdg_toplevel_wm_caps}; + +struct xdg_surface_listener surface_listener = { + .configure = xdg_surface_conf}; + +struct wl_registry_listener registry_listener = { + .global = registry_global, + .global_remove = registry_global_remove}; + +int32_t run_wayland() +{ + struct wl_display *display = wl_display_connect(0); + if (!display) + return -1; + struct wl_registry *registry = wl_display_get_registry(display); + wl_registry_add_listener(registry, ®istry_listener, 0); wl_display_roundtrip(display); - if (!compositor || !shm || !xdg_wm_base) return; - surface = wl_compositor_create_surface(compositor); - xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, surface); - xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, NULL); + + wl_surface = wl_compositor_create_surface(compositor); + struct wl_callback *wl_callback = wl_surface_frame(wl_surface); + wl_callback_add_listener(wl_callback, &callback_listener, 0); + + xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, wl_surface); + xdg_surface_add_listener(xdg_surface, &surface_listener, 0); xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); - xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, NULL); - wl_surface_commit(surface); - while (running && wl_display_dispatch(display) != -1) {} + xdg_toplevel_add_listener(xdg_toplevel, &top_listener, 0); + xdg_toplevel_set_title(xdg_toplevel, "Custom client"); + wl_surface_commit(wl_surface); + + while (wl_display_dispatch(display)) + { + if (need_close) + { + printf("Window closing\n"); + break; + } + } + + if (buffer) + wl_buffer_destroy(buffer); + xdg_toplevel_destroy(xdg_toplevel); + xdg_surface_destroy(xdg_surface); + wl_surface_destroy(wl_surface); wl_display_disconnect(display); + return 0; } \ No newline at end of file