// ===================================================================================================================== // fennec, a free and open source game engine // Copyright © 2025 - 2026 Medusa Slockbower // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // ===================================================================================================================== #include #include #include #include #include #include namespace fennec { window_manager::window_manager(platform* platform) : _platform(platform) , _commands(max_commands) {} window_manager::~window_manager() { shutdown(); } void window_manager::initialize() { if (_display) { return; } // Get the list of registered display servers display_server::entrylist_t display_servers = display_server::get_type_list(); // Find first valid server while (not display_servers.is_empty()) { display_server::entry it = display_servers.front(); display_servers.pop(); unique_ptr server = unique_ptr(it.ctor(_platform)); server->connect(); if (server->connected()) { logger::log(format("Selected {} for the display server.", server->get_type().name())); _display = move(server); break; } } assertf(_display, "Failed to select a display server!"); _thread = thread::current(); logger::log(format("Initializing Window Manager on thread: {:#016x}.", _thread)); } void window_manager::shutdown() { if (not _display) { return; } assertf(_thread == thread::current(), "Attempted to shutdown Window Manager on a different thread!"); lock_guard guard(_lock); // Cleanup Windows for (auto& window : _windows) { window->shutdown(); window.reset(); } _windows.clear(); // Cleanup Display Server _display->disconnect(); _display.reset(); } void window_manager::dispatch() { if (not _display) { return; } assertf(_thread == thread::current(), "Attempted to dispatch Window Manager on a different thread!"); lock_guard guard(_lock); _display->dispatch(); } window_id window_manager::create_window(const window::config& config, window_id parent) { if (not _display) { return nullid; } assertf(_thread == thread::current(), "Attempted to create a window on a different thread!"); lock_guard guard(_lock); window* p = parent == nullid ? nullptr : _windows[parent].get(); window_id id = _windows.emplace(_display->create_window(config, p)); _windows[id]->initialize(); return id; } void window_manager::begin_frame(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]->begin_frame(); } void window_manager::end_frame(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]->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(); } irect window_manager::_get_bounds(window_id id) const { return _windows[id]->get_bounds(); } 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