diff --git a/wayland/CMakeLists.txt b/wayland/CMakeLists.txt index 32c298e..4b363b5 100644 --- a/wayland/CMakeLists.txt +++ b/wayland/CMakeLists.txt @@ -7,4 +7,44 @@ enable_language(ASM_NASM) set(CMAKE_ASM_NASM_FLAGS "-f elf64") set(CMAKE_ASM_NASM_FLAGS_DEBUG "-gdwarf") -add_executable(wayland asm.asm c.c) \ No newline at end of file +find_package(PkgConfig REQUIRED) + +# Находим программу wayland-scanner +find_program(WAYLAND_SCANNER wayland-scanner REQUIRED) + +# Ищем директорию с протоколами Wayland +find_path(WAYLAND_PROTOCOLS_DIR + NAMES stable/xdg-shell/xdg-shell.xml + PATHS /usr/share/wayland-protocols /usr/local/share/wayland-protocols + REQUIRED +) + +# Путь к протоколу xdg-shell +set(PROTOCOL_XML ${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml) + +# Генерируем заголовочный файл протокола +add_custom_command( + OUTPUT xdg-shell-client-protocol.h + COMMAND ${WAYLAND_SCANNER} client-header ${PROTOCOL_XML} xdg-shell-client-protocol.h + DEPENDS ${PROTOCOL_XML} +) + +# Генерируем исходный файл протокола +add_custom_command( + OUTPUT xdg-shell-client-protocol.c + COMMAND ${WAYLAND_SCANNER} private-code ${PROTOCOL_XML} xdg-shell-client-protocol.c + DEPENDS ${PROTOCOL_XML} +) + +# Цель для генерации протокола +add_custom_target(generate-xdg-shell DEPENDS xdg-shell-client-protocol.h xdg-shell-client-protocol.c) + +# Создаем исполняемый файл из ассемблерного, C и сгенерированного кода +add_executable(wayland asm.asm c.c xdg-shell-client-protocol.c) + +# Зависимость от генерации протокола +add_dependencies(wayland generate-xdg-shell) + +pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client) +target_link_libraries(wayland ${WAYLAND_CLIENT_LIBRARIES}) +target_include_directories(wayland PRIVATE ${WAYLAND_CLIENT_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/wayland/CMakePresets.json b/wayland/CMakePresets.json index 0b9e457..53e7d83 100644 --- a/wayland/CMakePresets.json +++ b/wayland/CMakePresets.json @@ -3,9 +3,8 @@ "configurePresets": [ { "name": "debug-gcc", - "binaryDir": "${sourceDir}/out/build/${presetName}", + "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { - "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}", "CMAKE_C_COMPILER": "/usr/bin/gcc", "CMAKE_CXX_COMPILER": "/usr/bin/g++", "CMAKE_BUILD_TYPE": "Debug" @@ -13,9 +12,8 @@ }, { "name": "release-gcc", - "binaryDir": "${sourceDir}/out/build/${presetName}", + "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { - "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}", "CMAKE_C_COMPILER": "/usr/bin/gcc", "CMAKE_CXX_COMPILER": "/usr/bin/g++", "CMAKE_BUILD_TYPE": "Release" diff --git a/wayland/asm.asm b/wayland/asm.asm index 9eac30d..0e4d53a 100644 --- a/wayland/asm.asm +++ b/wayland/asm.asm @@ -1,23 +1,11 @@ global main -extern sum, print, scan -extern a +extern run_wayland section .text main: - push rbx - call scan ; прочитать первое число - mov rbx, rax ; сохранить первое число - call scan ; прочитать второе число - mov rdi, rbx ; a - mov rsi, rax ; b - call sum ; сумма - mov rdi, rax ; результат - push rax - call print ; напечатать - pop rax - pop rbx - - mov dword [rel a], eax ; записать значение 42 в переменную a + 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 f90fb1c..4780e43 100644 --- a/wayland/c.c +++ b/wayland/c.c @@ -1,24 +1,100 @@ +#include +#include +#include +#include +#include #include -#include +#include "xdg-shell-client-protocol.h" -int a; +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; -int sum(int a, int b) { - return a+b; -} - -void print(int num) { - printf("%d\n", num); - fflush(stdout); -} - -int scan() { - char buffer[100]; - int res; - if (fgets(buffer, sizeof(buffer), stdin) != NULL) { - if (sscanf(buffer, "%d", &res) == 1) { - return res; - } +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); } - return 0; // or handle error +} + +static void registry_global_remove(void *data, struct wl_registry *registry, uint32_t name) {} + +static const struct wl_registry_listener registry_listener = { + .global = registry_global, + .global_remove = registry_global_remove, +}; + +static void create_buffer(); + +static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { + xdg_surface_ack_configure(xdg_surface, serial); + create_buffer(); +} + +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; +} + +static void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) { + running = 0; +} + +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 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); + 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); + 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) {} + wl_display_disconnect(display); } \ No newline at end of file