From 286dd0fb0e7520ae2bd6d820dcc0956bd858f903 Mon Sep 17 00:00:00 2001 From: Jayden Grubb Date: Sat, 5 Apr 2025 07:07:54 +1000 Subject: [PATCH] Add basic Window creation to X11WindowDriver --- engine/CMakeLists.txt | 1 + engine/include/nova/platform/window_driver.h | 17 ++++ engine/include/nova/types.h | 7 +- engine/src/drivers/x11/window_driver.cpp | 87 ++++++++++++++++++++ engine/src/drivers/x11/window_driver.h | 23 ++++++ 5 files changed, 133 insertions(+), 2 deletions(-) diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 31fcb1f..d9e8bf8 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -51,6 +51,7 @@ set(ENGINE_INCLUDES_PUBLIC ) set(ENGINE_LIBS_PRIVATE $<$:Vulkan::Vulkan> + $<$:X11> ) set(ENGINE_LIBS_PUBLIC spdlog::spdlog diff --git a/engine/include/nova/platform/window_driver.h b/engine/include/nova/platform/window_driver.h index 64a503e..55542d4 100644 --- a/engine/include/nova/platform/window_driver.h +++ b/engine/include/nova/platform/window_driver.h @@ -7,12 +7,29 @@ #pragma once #include +#include +#include + +#include namespace Nova { + using WindowID = uptr; + class NOVA_API WindowDriver { public: virtual ~WindowDriver() = default; + virtual void poll_events() = 0; + + virtual WindowID create_window(std::string_view title = "Nova", u32 width = 800, u32 height = 600) = 0; + virtual void destroy_window(WindowID window) = 0; + + virtual void set_window_title(WindowID window, std::string_view title) = 0; + virtual void set_window_size(WindowID window, u32 width, u32 height) = 0; + virtual void set_window_position(WindowID window, i32 x, i32 y) = 0; + + [[nodiscard]] virtual u32 get_window_count() const = 0; + [[nodiscard]] virtual const char* get_surface_extension() const = 0; }; } // namespace Nova diff --git a/engine/include/nova/types.h b/engine/include/nova/types.h index a059c2f..4fd33f2 100644 --- a/engine/include/nova/types.h +++ b/engine/include/nova/types.h @@ -13,14 +13,17 @@ using u8 = uint8_t; using u16 = uint16_t; using u32 = uint32_t; using u64 = uint64_t; +using usize = size_t; +using uptr = uintptr_t; +using umax = uintmax_t; using i8 = int8_t; using i16 = int16_t; using i32 = int32_t; using i64 = int64_t; - -using usize = size_t; using isize = ptrdiff_t; +using iptr = intptr_t; +using imax = intmax_t; using f32 = float; using f64 = double; diff --git a/engine/src/drivers/x11/window_driver.cpp b/engine/src/drivers/x11/window_driver.cpp index 3974282..8cf6939 100644 --- a/engine/src/drivers/x11/window_driver.cpp +++ b/engine/src/drivers/x11/window_driver.cpp @@ -19,10 +19,97 @@ using namespace Nova; X11WindowDriver::X11WindowDriver() { NOVA_AUTO_TRACE(); + + m_display = XOpenDisplay(nullptr); + if (!m_display) { + throw std::runtime_error("Failed to connect to X server"); + } + + m_window_close_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", False); } X11WindowDriver::~X11WindowDriver() { NOVA_AUTO_TRACE(); + + for (const auto& [id, _] : m_windows) { + XDestroyWindow(m_display, id); + } + + if (m_display) { + XCloseDisplay(m_display); + m_display = nullptr; + } +} + +void X11WindowDriver::poll_events() { + NOVA_AUTO_TRACE(); + + XEvent event; + XNextEvent(m_display, &event); + + WindowID id = event.xany.window; + NOVA_ASSERT(m_windows.contains(id)); + + switch (event.type) { + case Expose: + break; + case ClientMessage: { + if (event.xclient.data.l[0] == static_cast(m_window_close_atom)) { + destroy_window(id); + } + break; + } + default: + NOVA_WARN("Unhandled X11 event: {}", event.type); + break; + } +} + +WindowID X11WindowDriver::create_window(std::string_view title, u32 width, u32 height) { + NOVA_AUTO_TRACE(); + + WindowID window = XCreateSimpleWindow(m_display, DefaultRootWindow(m_display), 0, 0, width, height, 0, 0, 0); + WindowData& data = m_windows[window]; + (void)data; // TODO: Initialize window data + + XSetWMProtocols(m_display, window, &m_window_close_atom, 1); + XSelectInput(m_display, window, ExposureMask); + XStoreName(m_display, window, title.data()); + XMapWindow(m_display, window); + XFlush(m_display); + + return window; +} + +void X11WindowDriver::destroy_window(WindowID id) { + NOVA_AUTO_TRACE(); + if (!m_windows.contains(id)) { + return; + } + XDestroyWindow(m_display, id); + m_windows.erase(id); +} + +void X11WindowDriver::set_window_title(WindowID id, std::string_view title) { + NOVA_AUTO_TRACE(); + NOVA_ASSERT(m_windows.contains(id)); + XStoreName(m_display, id, title.data()); +} + +void X11WindowDriver::set_window_size(WindowID id, u32 width, u32 height) { + NOVA_AUTO_TRACE(); + NOVA_ASSERT(m_windows.contains(id)); + XResizeWindow(m_display, id, width, height); +} + +void X11WindowDriver::set_window_position(WindowID id, i32 x, i32 y) { + NOVA_AUTO_TRACE(); + NOVA_ASSERT(m_windows.contains(id)); + XMoveWindow(m_display, id, x, y); +} + +u32 X11WindowDriver::get_window_count() const { + return m_windows.size(); } const char* X11WindowDriver::get_surface_extension() const { diff --git a/engine/src/drivers/x11/window_driver.h b/engine/src/drivers/x11/window_driver.h index f7b9255..1498939 100644 --- a/engine/src/drivers/x11/window_driver.h +++ b/engine/src/drivers/x11/window_driver.h @@ -11,13 +11,36 @@ #include #include +#include + namespace Nova { + struct WindowData { + // TODO: Add stuff here + }; + class X11WindowDriver final : public WindowDriver { public: X11WindowDriver(); ~X11WindowDriver() override; + void poll_events() override; + + WindowID create_window(std::string_view title, u32 width, u32 height) override; + void destroy_window(WindowID window) override; + + void set_window_title(WindowID window, std::string_view title) override; + void set_window_size(WindowID window, u32 width, u32 height) override; + void set_window_position(WindowID window, i32 x, i32 y) override; + + [[nodiscard]] u32 get_window_count() const override; + [[nodiscard]] const char* get_surface_extension() const override; + + private: + Display* m_display = nullptr; + std::unordered_map m_windows; + + Atom m_window_close_atom = 0; }; } // namespace Nova