MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
WindowManager.cpp
Go to the documentation of this file.
1#include "WindowManager.hpp"
2
7
9
11
12namespace MayaFlux::Core {
13
15 : m_config(config)
16{
18 "WindowManager initialized");
19}
20
22{
23 m_windows.clear();
24 m_window_lookup.clear();
25
26#ifdef GLFW_BACKEND
27 GLFWSingleton::terminate();
28#endif // GLFW_BACKEND
29
31 "WindowManager destroyed");
32}
33
34std::shared_ptr<Window> WindowManager::create_window(const WindowCreateInfo& create_info)
35{
36 if (m_window_lookup.count(create_info.title) > 0) {
38 "Window with title '{}' already exists", create_info.title);
39 return nullptr;
40 }
41
43 "Creating window '{}' ({}x{}), for platform {}", create_info.title, create_info.width, create_info.height, get_platform_name());
44
45 auto window = create_window_internal(create_info);
46 if (!window) {
47 return nullptr;
48 }
49
50 m_windows.push_back(window);
51 m_window_lookup[create_info.title] = window;
52
53 if (window->get_create_info().register_for_processing) {
54 m_processing_windows.push_back(window);
55 }
56
58 "Created window '{}' - total: {}", create_info.title, m_windows.size());
59
60 return window;
61}
62
63void WindowManager::destroy_window(const std::shared_ptr<Window>& window, bool cleanup_backend)
64{
65 if (!window)
66 return;
67
68 auto pr_it = std::ranges::find(m_processing_windows, window);
69 if (pr_it != m_processing_windows.end()) {
70 m_processing_windows.erase(pr_it);
71 }
72
73 const std::string title = window->get_create_info().title;
74 remove_from_lookup(window);
75
76 auto it = std::ranges::find(m_windows, window);
77 if (it != m_windows.end()) {
78 m_windows.erase(it);
80 "Destroyed window '{}' - remaining: {}", title, m_windows.size());
81 }
82
83 if (!cleanup_backend) {
84 return;
85 }
86
87 if (m_terminate.load()) {
88 window->destroy();
89 } else {
91 window->destroy();
92 });
93 }
95 "Backend resources for window '{}' cleaned up", title);
96}
97
98bool WindowManager::destroy_window_by_title(const std::string& title)
99{
100 auto window = find_window(title);
101 if (window) {
102 destroy_window(window);
103 return true;
104 }
105 return false;
106}
107
108std::vector<std::shared_ptr<Window>> WindowManager::get_windows() const
109{
110 std::vector<std::shared_ptr<Window>> ptrs;
111 ptrs.reserve(m_windows.size());
112 for (const auto& w : m_windows) {
113 ptrs.push_back(w);
114 }
115 return ptrs;
116}
117
118std::shared_ptr<Window> WindowManager::find_window(const std::string& title) const
119{
120 auto it = m_window_lookup.find(title);
121 return (it != m_window_lookup.end()) ? it->second.lock() : nullptr;
122}
123
124std::shared_ptr<Window> WindowManager::get_window(size_t index) const
125{
126 if (index >= m_windows.size()) {
127 return nullptr;
128 }
129 return m_windows[index];
130}
131
133{
134 return std::ranges::any_of(m_windows,
135 [](const auto& w) { return w->should_close(); });
136}
137
139{
140 size_t destroyed_count = 0;
141
142 std::vector<std::shared_ptr<Window>> to_destroy;
143 for (const auto& window : m_windows) {
144 if (window->should_close()) {
145 to_destroy.push_back(window);
146 }
147 }
148
149 for (auto& window : to_destroy) {
150 destroy_window(window);
151 destroyed_count++;
152 }
153
154 if (destroyed_count > 0) {
156 "Destroyed {} closed window(s)", destroyed_count);
157 }
158
159 return destroyed_count;
160}
161
163 const WindowCreateInfo& create_info)
164{
165 switch (m_config.windowing_backend) {
167#if defined(GLFW_BACKEND)
168 return std::make_unique<GlfwWindow>(create_info, m_config.surface_info,
169 m_config.requested_api, m_config.glfw_preinit_config);
170#else
172 "GLFW backend not compiled in");
173 return nullptr;
174#endif
175
177#if defined(MAYAFLUX_PLATFORM_WINDOWS)
178 return std::make_shared<Win32Window>(create_info, m_config);
179#else
181 "Native Win32 backend not implemented on this platform");
182 return nullptr;
183#endif
184
186#if defined(MAYAFLUX_PLATFORM_LINUX)
187 return std::make_shared<WaylandWindow>(create_info, m_config);
188#else
190 "Wayland native backend not compiled in");
191 return nullptr;
192#endif
193
194 default:
196 "Unknown windowing backend: {}",
197 static_cast<int>(m_config.windowing_backend));
198 return nullptr;
199 }
200}
201
202void WindowManager::remove_from_lookup(const std::shared_ptr<Window>& window)
203{
204 const auto& title = window->get_create_info().title;
205 m_window_lookup.erase(title);
206}
207
209{
210
211#if defined(GLFW_BACKEND)
213 glfwPollEvents();
214 });
215#else
216 for (auto& w : m_processing_windows)
217 w->poll();
218#endif
219
220 {
221 std::lock_guard<std::mutex> lock(m_hooks_mutex);
222 for (const auto& [name, hook] : m_frame_hooks) {
223 hook();
224 }
225 }
226
228
229 return window_count() > 0;
230}
231
232void WindowManager::register_frame_hook(const std::string& name,
233 std::function<void()> hook)
234{
235 std::lock_guard<std::mutex> lock(m_hooks_mutex);
236 m_frame_hooks[name] = std::move(hook);
237}
238
239void WindowManager::unregister_frame_hook(const std::string& name)
240{
241 std::lock_guard<std::mutex> lock(m_hooks_mutex);
242 m_frame_hooks.erase(name);
243}
244
245} // namespace MayaFlux::Core
#define MF_INFO(comp, ctx,...)
#define MF_LOG(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
std::shared_ptr< Window > get_window(size_t index) const
Gets window by index.
std::atomic< bool > m_terminate
bool process()
Process windows for one frame.
std::mutex m_hooks_mutex
Mutex for protecting m_windows and m_window_lookup.
std::vector< std::shared_ptr< Window > > get_windows() const
Gets all active windows.
std::vector< std::shared_ptr< Window > > m_windows
std::shared_ptr< Window > find_window(const std::string &title) const
Finds window by title.
WindowManager(const GlobalGraphicsConfig &config)
Constructs WindowManager with global graphics config.
std::shared_ptr< Window > create_window_internal(const WindowCreateInfo &create_info)
Factory for creating backend-specific windows.
bool any_window_should_close() const
Checks if any window should close.
void register_frame_hook(const std::string &name, std::function< void()> hook)
Register a hook that runs every frame.
size_t destroy_closed_windows()
Destroys all windows that should close.
void remove_from_lookup(const std::shared_ptr< Window > &window)
Removes window from lookup table.
std::shared_ptr< Window > create_window(const WindowCreateInfo &create_info)
Creates a new window.
GlobalGraphicsConfig m_config
std::unordered_map< std::string, std::function< void()> > m_frame_hooks
Calls all registered frame hooks.
std::unordered_map< std::string, std::weak_ptr< Window > > m_window_lookup
bool destroy_window_by_title(const std::string &title)
Destroys a window by title.
std::vector< std::shared_ptr< Window > > m_processing_windows
size_t window_count() const
Gets number of active windows.
void unregister_frame_hook(const std::string &name)
Unregister a previously registered frame hook.
void destroy_window(const std::shared_ptr< Window > &window, bool cleanup_backend=false)
Destroys a window by pointer.
@ WindowingSubsystem
Windowing system operations (GLFW, SDL)
@ Core
Core engine, backend, subsystems.
auto dispatch_main_sync(Func &&func, Args &&... args) -> decltype(auto)
Definition Dispatch.hpp:107
GraphicsSurfaceInfo surface_info
System-wide configuration for visual stream processing.
WindowingBackend windowing_backend
Selected windowing backend.
GraphicsApi requested_api
Selected graphics API for rendering.
std::string title
Window title/identifier.
uint32_t width
Initial window dimensions.
Configuration for creating a single window instance.