summaryrefslogtreecommitdiff
path: root/src/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/window.c')
-rw-r--r--src/window.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/window.c b/src/window.c
new file mode 100644
index 0000000..63aefec
--- /dev/null
+++ b/src/window.c
@@ -0,0 +1,148 @@
+#include "render/window.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 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) {}
+
+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) {
+ 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) {
+ 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) {
+ struct window *win = data;
+ win->resize = true;
+ win->width = width != 0 ? width : 1920;
+ win->height = height != 0 ? height : 1080;
+}
+
+void toplevel_close(void *data, struct xdg_toplevel *toplevel) {
+ struct window *win = data;
+ win->should_close = true;
+}
+
+static struct xdg_toplevel_listener toplevel_listener = {
+ .configure = toplevel_configure,
+ .close = toplevel_close,
+};
+
+struct window *window_init(const char *title) {
+ struct window *win = calloc(1, sizeof(*win));
+
+ 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:
+ window_destroy(win);
+ return NULL;
+}
+
+void window_destroy(struct 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 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;
+ VkResult res = vkCreateWaylandSurfaceKHR(instance, &create_info, NULL, &surface);
+ if (res != VK_SUCCESS)
+ return VK_NULL_HANDLE;
+
+ return surface;
+}