#include #include "window.h" #include "utils.h" #include #include #include static void global(void *data, struct wl_registry *reg, uint32_t name, const char *interface, uint32_t version) { struct vlkn_window *win = data; if (strcmp(wl_compositor_interface.name, interface) == 0) { win->comp = wl_registry_bind(reg, name, &wl_compositor_interface, version); } else if (strcmp(xdg_wm_base_interface.name, interface) == 0) { win->xdg_base = wl_registry_bind(reg, name, &xdg_wm_base_interface, version); } else if (strcmp(zxdg_decoration_manager_v1_interface.name, interface) == 0) { win->deco_manager = wl_registry_bind(reg, name, &zxdg_decoration_manager_v1_interface, version); } } static void global_remove(void *data, struct wl_registry *reg, uint32_t name) { (void) data; (void) reg; (void) name; abort(); } static struct wl_registry_listener reg_list = { .global = global, .global_remove = global_remove }; static void ping(void *data, struct xdg_wm_base *base, uint32_t serial) { (void) data; xdg_wm_base_pong(base, serial); } static struct xdg_wm_base_listener xdg_list = { .ping = ping }; void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) { (void) data; xdg_surface_ack_configure(xdg_surface, serial); } static struct xdg_surface_listener xdg_surface_list = { .configure = xdg_surface_configure, }; void toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height, struct wl_array *states) { (void) xdg_toplevel; (void) states; struct vlkn_window *win = data; win->resize = true; win->width = width != 0 ? width : 1920; win->height = height != 0 ? height : 1080; if (win->on_resize) win->on_resize(win->data); dbglogf("%dx%d\n", win->width, win->height); } void toplevel_close(void *data, struct xdg_toplevel *toplevel) { (void) toplevel; struct vlkn_window *win = data; win->should_close = true; } void configure_bounds(void *data, struct xdg_toplevel *xdg_toplevel, int32_t width, int32_t height) { (void) data; (void) xdg_toplevel; (void) width; (void) height; } void wm_capabilities(void *data, struct xdg_toplevel *xdg_toplevel, struct wl_array *capabilities) { (void) data; (void) xdg_toplevel; (void) capabilities; } static struct xdg_toplevel_listener toplevel_listener = { .configure = toplevel_configure, .close = toplevel_close, .configure_bounds = configure_bounds, .wm_capabilities = wm_capabilities }; struct vlkn_window *vlkn_window_init(const char *title) { struct vlkn_window *win = calloc(1, sizeof(*win)); if (!win) return NULL; win->title = title; win->should_close = false; win->dpy = wl_display_connect(NULL); if (!win->dpy) goto err; win->reg = wl_display_get_registry(win->dpy); if (!win->reg) goto err; wl_registry_add_listener(win->reg, ®_list, win); wl_display_roundtrip(win->dpy); if (!win->comp || !win->dpy || !win->deco_manager || !win->xdg_base) goto err; xdg_wm_base_add_listener(win->xdg_base, &xdg_list, win); win->surface = wl_compositor_create_surface(win->comp); if (!win->surface) goto err; win->xdg_surface = xdg_wm_base_get_xdg_surface(win->xdg_base, win->surface); xdg_surface_add_listener(win->xdg_surface, &xdg_surface_list, win); win->xdg_toplevel = xdg_surface_get_toplevel(win->xdg_surface); xdg_toplevel_set_title(win->xdg_toplevel, title); xdg_toplevel_set_min_size(win->xdg_toplevel, 640, 480); xdg_toplevel_add_listener(win->xdg_toplevel, &toplevel_listener, win); win->deco = zxdg_decoration_manager_v1_get_toplevel_decoration(win->deco_manager, win->xdg_toplevel); zxdg_toplevel_decoration_v1_set_mode(win->deco, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); wl_surface_commit(win->surface); while (!win->resize) wl_display_roundtrip(win->dpy); win->resize = false; return win; err: vlkn_window_destroy(win); return NULL; } void window_on_resize(struct vlkn_window *win, void (*callback)(void *data), void *data) { win->on_resize = callback; win->data = data; } void vlkn_window_destroy(struct vlkn_window *win) { if (!win) return; if (win->deco) zxdg_toplevel_decoration_v1_destroy(win->deco); if (win->deco_manager) zxdg_decoration_manager_v1_destroy(win->deco_manager); if (win->xdg_toplevel) xdg_toplevel_destroy(win->xdg_toplevel); if (win->xdg_surface) xdg_surface_destroy(win->xdg_surface); if (win->xdg_base) xdg_wm_base_destroy(win->xdg_base); if (win->comp) wl_compositor_destroy(win->comp); if (win->reg) wl_registry_destroy(win->reg); if (win->dpy) wl_display_disconnect(win->dpy); free(win); } VkSurfaceKHR window_create_vk_surface(VkInstance instance, struct vlkn_window *win) { if (!win) return VK_NULL_HANDLE; VkWaylandSurfaceCreateInfoKHR create_info = { .sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, .display = win->dpy, .surface = win->surface }; VkSurfaceKHR surface; if (!vlkn_check(vkCreateWaylandSurfaceKHR(instance, &create_info, NULL, &surface))) return VK_NULL_HANDLE; return surface; }