summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
authorAnna (navi) Figueiredo Gomes <navi@vlhl.dev>2024-06-30 22:23:08 +0200
committerAnna (navi) Figueiredo Gomes <navi@vlhl.dev>2024-06-30 22:29:30 +0200
commit87c8428df0bf1b2f6932bb16390f69be57e21f6b (patch)
tree0cc0f7cab79a0373ef366898df8f5773391bae17 /src/window.c
libvlkn: inital commit, basic prototype api in placeHEADmain
Signed-off-by: Anna (navi) Figueiredo Gomes <navi@vlhl.dev>
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/window.c b/src/window.c
new file mode 100644
index 0000000..0d5bac8
--- /dev/null
+++ b/src/window.c
@@ -0,0 +1,177 @@
+#include <vlkn.h>
+#include "window.h"
+#include "utils.h"
+#include <vulkan/vulkan_wayland.h>
+#include <stdlib.h>
+#include <string.h>
+
+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, &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;
+}