From ecf1cfc29c77ab5ad7be8aab5ecb41e12a241e66 Mon Sep 17 00:00:00 2001 From: Medusa Slockbower Date: Sat, 27 Dec 2025 07:19:53 -0500 Subject: [PATCH] - fleshing out event system and window manager - added tests back in for window management --- include/fennec/containers/object_pool.h | 9 ++- include/fennec/core/event.h | 2 +- include/fennec/memory/pointers.h | 3 + include/fennec/platform/interface/platform.h | 6 +- include/fennec/platform/interface/window.h | 2 +- include/fennec/platform/window_manager.h | 40 ++++++++------ source/core/event.cpp | 6 +- source/platform/interface/window.cpp | 9 ++- source/platform/linux/wayland/window.cpp | 8 --- source/platform/window_manager.cpp | 58 ++++++++++++++++++-- test/printing.h | 2 +- test/tests/test_platform.h | 23 ++++---- 12 files changed, 116 insertions(+), 52 deletions(-) diff --git a/include/fennec/containers/object_pool.h b/include/fennec/containers/object_pool.h index 2ed3fb6..fc455cf 100644 --- a/include/fennec/containers/object_pool.h +++ b/include/fennec/containers/object_pool.h @@ -137,6 +137,11 @@ public: return *_table[i]; } + constexpr bool operator()(size_t i) const { + assert(i < capacity(), "Index out of Bounds!"); + return _table[i]; + } + /// @} @@ -205,7 +210,7 @@ public: /// \brief C++ Iterator Specification `begin()` /// \returns an iterator at the start of the object pool const_iterator begin() const { - return iterator(this, 0); + return const_iterator(this, 0); } /// @@ -218,7 +223,7 @@ public: /// \brief C++ Iterator Specification `end()` /// \returns an iterator at the start of the end of the object pool const_iterator end() const { - return iterator(this, _size); + return const_iterator(this, _size); } /// diff --git a/include/fennec/core/event.h b/include/fennec/core/event.h index 2d50a56..8934a78 100644 --- a/include/fennec/core/event.h +++ b/include/fennec/core/event.h @@ -33,7 +33,7 @@ struct event; /// \brief Class outlining the interface for an object that listens for events class event_listener { public: - virtual ~event_listener() = default; + virtual ~event_listener(); /// /// \brief event handler callback diff --git a/include/fennec/memory/pointers.h b/include/fennec/memory/pointers.h index 3286c8d..bd207b4 100644 --- a/include/fennec/memory/pointers.h +++ b/include/fennec/memory/pointers.h @@ -212,6 +212,9 @@ public: return _handle != nullptr; } + /// + /// \brief dereference operator + /// \returns a reference to the held value element_t& operator*() const { return *_handle; } diff --git a/include/fennec/platform/interface/platform.h b/include/fennec/platform/interface/platform.h index 2314cfb..6ca99a8 100644 --- a/include/fennec/platform/interface/platform.h +++ b/include/fennec/platform/interface/platform.h @@ -87,18 +87,20 @@ public: /// /// \brief shared object release /// \param obj the shared object to release - virtual void unload_object(shared_object* obj) = 0; + virtual void unload_object(shared_object* obj) = 0; /// /// \brief shared object symbol locator /// \param obj the shared object to search /// \param name the name of the symbol to search for /// \returns a reference to the symbol - virtual symbol find_symbol(shared_object* obj, const cstring& name) = 0; + virtual symbol find_symbol(shared_object* obj, const cstring& name) = 0; virtual void initialize(); //!< Initialize Drivers and Contexts virtual void shutdown(); //!< Close Drivers and Contexts + virtual window_manager& get_window_manager() const { return *wmanager; } + protected: unique_ptr wmanager; //!< the window manager diff --git a/include/fennec/platform/interface/window.h b/include/fennec/platform/interface/window.h index 3879ead..39da3c9 100644 --- a/include/fennec/platform/interface/window.h +++ b/include/fennec/platform/interface/window.h @@ -336,9 +336,9 @@ public: protected: display_server* const server; //!< the display server the window belongs to window* const parent; //!< the parent window + window* root; //!< the nearest top-level window in the hierarchy config cfg; //!< the current configuration state state; //!< the current state - window* root; //!< the nearest top-level window in the hierarchy unique_ptr gfx_surface; //!< the corresponding graphics surface }; diff --git a/include/fennec/platform/window_manager.h b/include/fennec/platform/window_manager.h index 8d574e7..4bf05c4 100644 --- a/include/fennec/platform/window_manager.h +++ b/include/fennec/platform/window_manager.h @@ -38,28 +38,23 @@ #include #include #include +#include #include #include namespace fennec { +using window_id = size_t; //!< type representing an id for a window + /// /// \brief class for handling display servers and windows class window_manager { // Definitions ========================================================================================================= public: - using window_id = size_t; //!< type representing an id for a window - static constexpr window_id nullid = -1; //!< constant representing a null window private: - using server_t = unique_ptr; - using window_t = unique_ptr; - using window_pool_t = object_pool; - - using config = window::config; - enum command_ : uint8_t { command_set_flag = 0, command_resize @@ -71,6 +66,14 @@ private: void* data; }; + static constexpr size_t max_commands = 512; + + using server_t = unique_ptr; + using window_t = unique_ptr; + using window_pool_t = object_pool; + using command_queue_t = mpscq; + using config = window::config; + // Constructors & Destructor =========================================================================================== public: @@ -96,6 +99,7 @@ public: window_id create_window(const config& config, window_id parent = nullid); void begin(window_id window); void end(window_id window); + void close(window_id window); // Thread-Safe Functions =============================================================================================== @@ -111,11 +115,11 @@ public: ivec2 get_size(window_id window) const { lock_guard guard(_lock); - return _size(window); + return _get_size(window); } ivec2 get_position(window_id window) const { lock_guard guard(_lock); - return _position(window); + return _get_position(window); } bool is_visible(window_id window) const { lock_guard guard(_lock); return _check_state(window, window::state_visible); } @@ -151,18 +155,20 @@ public: private: - mutable mutex _lock; - thread::id _thread; - platform* _platform; - server_t _display; - window_pool_t _windows; + mutable mutex _lock; + thread::id _thread; + platform* _platform; + server_t _display; + window_pool_t _windows; + command_queue_t _commands; + window_id _parent(window_id id) const; window_id _root(window_id id) const; - ivec2 _size(window_id id) const; - ivec2 _position(window_id id) const; + ivec2 _get_size(window_id id) const; + ivec2 _get_position(window_id id) const; bool _check_state(window_id id, uint8_t state) const; diff --git a/source/core/event.cpp b/source/core/event.cpp index 1a68a31..bcaf8a0 100644 --- a/source/core/event.cpp +++ b/source/core/event.cpp @@ -30,7 +30,11 @@ namespace fennec static mutex lock; static dynarray> listeners; -static mpscq queue(FENNEC_EVENT_QUEUE_SIZE); +static mpscq queue(FENNEC_EVENT_QUEUE_SIZE); + +event_listener::~event_listener() { + event::remove_listener(this); +} void event::handle_events() { lock_guard guard(lock); diff --git a/source/platform/interface/window.cpp b/source/platform/interface/window.cpp index 9558d8c..e4dc130 100644 --- a/source/platform/interface/window.cpp +++ b/source/platform/interface/window.cpp @@ -24,9 +24,14 @@ namespace fennec { window::window(display_server* server, const config& conf, window* parent) - : server(server), parent(parent) - , cfg(conf), state(), root(nullptr) { + : server(server), parent(parent), root(parent ? parent : this) + , cfg(conf), state() { state.mode = conf.mode; + while (root != nullptr and root->is_popup()) { + root = root->get_parent(); + } + + assertf(root != nullptr, "Failed to find appropriate top-level window."); } window::~window() { diff --git a/source/platform/linux/wayland/window.cpp b/source/platform/linux/wayland/window.cpp index baee6b2..405a4d7 100644 --- a/source/platform/linux/wayland/window.cpp +++ b/source/platform/linux/wayland/window.cpp @@ -77,14 +77,6 @@ void wayland_window::initialize() { return; } - - root = parent; - while (root != nullptr and root->is_popup()) { - root = static_cast(root->get_parent()); - } - - assertf(root != nullptr, "Failed to find appropriate top-level window."); - wayland_server* wl_server = static_cast(server); surface = wl_compositor_create_surface(wl_server->compositor); diff --git a/source/platform/window_manager.cpp b/source/platform/window_manager.cpp index a3ab0aa..258d866 100644 --- a/source/platform/window_manager.cpp +++ b/source/platform/window_manager.cpp @@ -28,8 +28,8 @@ namespace fennec { window_manager::window_manager(platform* platform) - : _platform(platform) { -} + : _platform(platform) + , _commands(max_commands) {} window_manager::~window_manager() { shutdown(); @@ -95,7 +95,7 @@ void window_manager::dispatch() { _display->dispatch(); } -window_manager::window_id window_manager::create_window(const window::config& config, window_id parent) { +window_id window_manager::create_window(const window::config& config, window_id parent) { if (not _display) { return nullid; } @@ -104,7 +104,9 @@ window_manager::window_id window_manager::create_window(const window::config& co lock_guard guard(_lock); window* p = parent == nullid ? nullptr : _windows[parent].get(); - return _windows.emplace(_display->create_window(config, p)); + window_id id = _windows.emplace(_display->create_window(config, p)); + _windows[id]->initialize(); + return id; } void window_manager::begin(window_id window) { @@ -128,4 +130,52 @@ void window_manager::end(window_id window) { _windows[window]->end_frame(); } + +void window_manager::close(window_id window) { + if (not _display) { + return; + } + + assertf(_thread == thread::current(), "Attempted to set window context on a different thread!"); + lock_guard guard(_lock); + + _windows[window]->shutdown(); + _windows[window] = nullptr; + _windows.erase(window); +} + +window_id window_manager::_parent(window_id) const { + return nullid; +} + +window_id window_manager::_root(window_id) const { + return nullid; +} + +ivec2 window_manager::_get_size(window_id id) const { + return _windows[id]->get_size(); +} + +ivec2 window_manager::_get_position(window_id id) const { + return _windows[id]->get_position(); +} + +bool window_manager::_check_state(window_id id, uint8_t state) const { + switch (state) { + case window::state_running: return _windows[id]->is_running(); + case window::state_child: return _windows[id]->is_child(); + case window::state_suspended: return _windows[id]->is_suspended(); + case window::state_visible: return _windows[id]->is_visible(); + default: return false; + } +} + +bool window_manager::_get_flag(window_id id, uint8_t flag) const { + return _windows[id]->get_flag(flag); +} + +bool window_manager::_set_flag(window_id, uint8_t, bool) { + return false; +} + } // fennec \ No newline at end of file diff --git a/test/printing.h b/test/printing.h index b6c9690..ecb3837 100644 --- a/test/printing.h +++ b/test/printing.h @@ -79,7 +79,7 @@ inline std::ostream& operator<<(std::ostream& os, const path& str) { // Helper for printing types inline std::ostream& operator<<(std::ostream& os, const type& t) { - return os << t.name(); + return os << t.name().cstr(); } } diff --git a/test/tests/test_platform.h b/test/tests/test_platform.h index e2c2b46..fb6dda1 100644 --- a/test/tests/test_platform.h +++ b/test/tests/test_platform.h @@ -22,7 +22,7 @@ #include "../test.h" #include - +#include namespace fennec::test { @@ -32,14 +32,12 @@ inline void fennec_test_platform() { platform* platform = platform::instance(); platform->initialize(); - /* - display_server* display = platform->get_display_server(); + window_manager& wm = platform->get_window_manager(); - window* window = display->create_window(window::config { + window_id window = wm.create_window(window::config { .title = string("fennec-test"), .flags = { }, .mode = window::mode_windowed, - .parent = window::nullid, .rect = { .position = { 0, 0 }, .size = { 720, 480 }, @@ -48,19 +46,18 @@ inline void fennec_test_platform() { .accessibility = { string("test window"), string("test window description") } }); - assertf(window != nullptr, "Failed to create test window."); + assertf(window != window_manager::nullid, "Failed to create test window."); - window->initialize(); - while (window->is_running()) { - window->begin_frame(); - window->end_frame(); - display->dispatch(); + while (wm.is_running(window)) { + wm.begin(window); + wm.end(window); + + wm.dispatch(); } - window->shutdown(); - */ + wm.close(window); platform::instance()->shutdown();