MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
GlfwWindow.cpp
Go to the documentation of this file.
1#include "GlfwWindow.hpp"
2
3#include "GlfwSingleton.hpp"
5
6#ifdef MAYAFLUX_PLATFORM_WINDOWS
7#define GLFW_EXPOSE_NATIVE_WIN32
8#include <GLFW/glfw3native.h>
9#elif MAYAFLUX_PLATFORM_LINUX
10#include <GLFW/glfw3native.h>
11#elif MAYAFLUX_PLATFORM_MACOS
12#define GLFW_EXPOSE_NATIVE_COCOA
13#include <GLFW/glfw3native.h>
14#endif
15
16namespace MayaFlux::Core {
17
19 const GraphicsSurfaceInfo& surface_info, GlobalGraphicsConfig::GraphicsApi api, GlfwPreInitConfig pre_init_config)
20 : m_create_info(create_info)
21{
22 GLFWSingleton::configure(pre_init_config);
23
25 error<std::runtime_error>(Journal::Component::Core, Journal::Context::WindowingSubsystem, std::source_location::current(),
26 "Failed to initialize GLFW for window creation");
27 }
28
29 configure_window_hints(surface_info, api);
30
31 GLFWmonitor* monitor = nullptr;
32 if (create_info.fullscreen) {
33 if (create_info.monitor_id >= 0) {
34 int count {};
35 std::span<GLFWmonitor*> monitors(glfwGetMonitors(&count), count);
36 if (create_info.monitor_id < count) {
37 monitor = monitors[create_info.monitor_id];
38 }
39 } else {
40 monitor = glfwGetPrimaryMonitor();
41 }
42 }
43
44 m_window = glfwCreateWindow(
45 create_info.width,
46 create_info.height,
47 create_info.title.c_str(),
48 monitor,
49 nullptr);
50
51 if (!m_window) {
52 error<std::runtime_error>(Journal::Component::Core, Journal::Context::WindowingSubsystem, std::source_location::current(),
53 "Failed to create GLFW window: {}", create_info.title);
54 }
55
56 glfwSetWindowUserPointer(m_window, this);
58
59 int w {}, h {};
60 glfwGetWindowSize(m_window, &w, &h);
63 m_state.is_visible = false;
64
66
68 "Created window '{}' ({}x{})", create_info.title, w, h);
69}
70
79
81 : m_window(other.m_window)
82 , m_create_info(std::move(other.m_create_info))
83 , m_state(other.m_state)
84 , m_input_config(other.m_input_config)
85 , m_event_callback(std::move(other.m_event_callback))
86{
87 other.m_window = nullptr;
88 if (m_window) {
89 glfwSetWindowUserPointer(m_window, this);
90 }
91}
92
94{
95 if (this != &other) {
96 if (m_window) {
97 glfwDestroyWindow(m_window);
99 }
100
101 m_window = other.m_window;
102 m_create_info = std::move(other.m_create_info);
103 m_state = other.m_state;
104 m_input_config = other.m_input_config;
105 m_event_callback = std::move(other.m_event_callback);
106
107 other.m_window = nullptr;
108 if (m_window) {
109 glfwSetWindowUserPointer(m_window, this);
110 }
111 }
112 return *this;
113}
114
115void GlfwWindow::set_title(const std::string& title)
116{
117 if (m_window) {
118 glfwSetWindowTitle(m_window, title.c_str());
119 m_create_info.title = title;
120 }
121}
122
124{
125 glfwDefaultWindowHints();
126
127 glfwWindowHint(GLFW_RESIZABLE, m_create_info.resizable ? GLFW_TRUE : GLFW_FALSE);
128 glfwWindowHint(GLFW_DECORATED, m_create_info.decorated ? GLFW_TRUE : GLFW_FALSE);
129 glfwWindowHint(GLFW_FLOATING, m_create_info.floating ? GLFW_TRUE : GLFW_FALSE);
130 glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, m_create_info.transparent ? GLFW_TRUE : GLFW_FALSE);
131 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
132
134 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
136 glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
137 }
138}
139
141{
142 glfwSetWindowSizeCallback(m_window, glfw_window_size_callback);
143 glfwSetWindowCloseCallback(m_window, glfw_window_close_callback);
144 glfwSetWindowFocusCallback(m_window, glfw_window_focus_callback);
145 glfwSetFramebufferSizeCallback(m_window, glfw_framebuffer_size_callback);
146 glfwSetKeyCallback(m_window, glfw_key_callback);
147 glfwSetCursorPosCallback(m_window, glfw_cursor_pos_callback);
148 glfwSetMouseButtonCallback(m_window, glfw_mouse_button_callback);
149 glfwSetScrollCallback(m_window, glfw_scroll_callback);
150}
151
153{
154 if (m_window) {
155 glfwShowWindow(m_window);
156 m_state.is_visible = true;
157 }
158}
159
161{
162 if (m_window) {
163 glfwHideWindow(m_window);
164 m_state.is_visible = false;
165 }
166}
167
169{
170 return m_window ? glfwWindowShouldClose(m_window) : true;
171}
172
174{
175 m_event_callback = std::move(callback);
176}
177
179{
180 if (!m_window)
181 return nullptr;
182
183#ifdef MAYAFLUX_PLATFORM_WINDOWS
184 return glfwGetWin32Window(m_window);
185#elif MAYAFLUX_PLATFORM_LINUX
186#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
187 if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) {
188 return glfwGetWaylandWindow(m_window);
189 }
190#endif
191#if defined(GLFW_EXPOSE_NATIVE_X11)
192 if (glfwGetPlatform() == GLFW_PLATFORM_X11) {
193 return reinterpret_cast<void*>(glfwGetX11Window(m_window));
194 }
195#endif
196 return nullptr;
197#elif MAYAFLUX_PLATFORM_MACOS
198 return glfwGetCocoaWindow(m_window);
199#else
200 return m_window;
201#endif
202}
203
205{
206#ifdef MAYAFLUX_PLATFORM_LINUX
207#if defined(GLFW_EXPOSE_NATIVE_WAYLAND)
208 if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) {
209 return glfwGetWaylandDisplay();
210 }
211#endif
212#if defined(GLFW_EXPOSE_NATIVE_X11)
213 if (glfwGetPlatform() == GLFW_PLATFORM_X11) {
214 return glfwGetX11Display();
215 }
216#endif
217#endif
218 return nullptr;
219}
220
221void GlfwWindow::glfw_window_size_callback(GLFWwindow* window, int width, int height)
222{
223 auto* win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
224 if (win && win->m_event_callback) {
225 win->m_state.current_width = width;
226 win->m_state.current_height = height;
227
228 if (win->m_event_callback) {
229 WindowEvent event;
231 event.timestamp = glfwGetTime();
232 event.data = WindowEvent::ResizeData {
233 .width = static_cast<uint32_t>(width),
234 .height = static_cast<uint32_t>(height)
235 };
236 win->m_event_callback(event);
237 }
238 }
239}
240
241void GlfwWindow::set_size(uint32_t width, uint32_t height)
242{
243 if (m_window) {
244 glfwSetWindowSize(m_window, static_cast<int>(width), static_cast<int>(height));
245 }
246
247 m_create_info.width = width;
248 m_create_info.height = height;
249}
250
251void GlfwWindow::set_position(uint32_t x, uint32_t y)
252{
253 if (m_window) {
254 glfwSetWindowPos(m_window, static_cast<int>(x), static_cast<int>(y));
255 }
256}
257
259{
260 auto* win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
261 if (!win)
262 return;
263
264 WindowEvent event;
266 event.timestamp = glfwGetTime();
267
268 win->m_event_source.signal(event);
269
270 if (win->m_event_callback) {
271 win->m_event_callback(event);
272 }
273}
274
275void GlfwWindow::glfw_window_focus_callback(GLFWwindow* window, int focused)
276{
277 auto* win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
278 if (!win)
279 return;
280
281 win->m_state.is_focused = (focused == GLFW_TRUE);
282
283 WindowEvent event;
286 event.timestamp = glfwGetTime();
287
288 win->m_event_source.signal(event);
289
290 if (win->m_event_callback) {
291 win->m_event_callback(event);
292 }
293}
294
295void GlfwWindow::glfw_framebuffer_size_callback(GLFWwindow* window, int width, int height)
296{
297 auto* win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
298 if (!win)
299 return;
300
301 WindowEvent event;
303 event.timestamp = glfwGetTime();
304 event.data = WindowEvent::ResizeData {
305 .width = static_cast<uint32_t>(width),
306 .height = static_cast<uint32_t>(height)
307 };
308
309 win->m_event_source.signal(event);
310
311 if (win->m_event_callback) {
312 win->m_event_callback(event);
313 }
314}
315
316void GlfwWindow::glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
317{
318 auto* win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
319 if (!win)
320 return;
321
322 WindowEventType type;
323 switch (action) {
324 case GLFW_PRESS:
326 break;
327 case GLFW_RELEASE:
329 break;
330 case GLFW_REPEAT:
332 break;
333 default:
334 return;
335 }
336
337 WindowEvent event;
338 event.type = type;
339 event.timestamp = glfwGetTime();
340 event.data = WindowEvent::KeyData {
341 .key = key,
342 .scancode = scancode,
343 .mods = mods
344 };
345
346 win->m_event_source.signal(event);
347
348 if (win->m_event_callback) {
349 win->m_event_callback(event);
350 }
351}
352
353void GlfwWindow::glfw_cursor_pos_callback(GLFWwindow* window, double xpos, double ypos)
354{
355 auto* win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
356 if (!win)
357 return;
358
359 WindowEvent event;
361 event.timestamp = glfwGetTime();
362
363 event.data = WindowEvent::MousePosData {
364 .x = xpos,
365 .y = ypos
366 };
367
368 win->m_event_source.signal(event);
369
370 if (win->m_event_callback) {
371 win->m_event_callback(event);
372 }
373}
374
375void GlfwWindow::glfw_mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
376{
377 auto* win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
378 if (!win)
379 return;
380
381 WindowEvent event;
382 event.type = (action == GLFW_PRESS) ? WindowEventType::MOUSE_BUTTON_PRESSED
384 event.timestamp = glfwGetTime();
385
386 event.data = WindowEvent::MouseButtonData {
387 .button = button,
388 .mods = mods
389 };
390
391 win->m_event_source.signal(event);
392
393 if (win->m_event_callback) {
394 win->m_event_callback(event);
395 }
396}
397
398void GlfwWindow::glfw_scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
399{
400 auto* win = static_cast<GlfwWindow*>(glfwGetWindowUserPointer(window));
401 if (!win)
402 return;
403
404 WindowEvent event;
406 event.timestamp = glfwGetTime();
407 event.data = WindowEvent::ScrollData {
408 .x_offset = xoffset,
409 .y_offset = yoffset
410 };
411
412 win->m_event_source.signal(event);
413
414 if (win->m_event_callback) {
415 win->m_event_callback(event);
416 }
417}
418
420{
421 m_graphics_registered.store(registered, std::memory_order_release);
422}
423
424}
#define MF_INFO(comp, ctx,...)
static void mark_window_created()
Increments the count of active GLFW windows.
static void mark_window_destroyed()
Decrements the count of active GLFW windows.
static bool initialize()
Initializes the GLFW library if not already initialized.
static void terminate()
Terminates the GLFW library if initialized and no windows remain.
static void configure(const GlfwPreInitConfig &config)
Configures GLFW with pre-initialization hints.
bool should_close() const override
Poll for window events (non-blocking)
void * get_native_display() const override
Get native display handle (platform-specific)
static void glfw_scroll_callback(GLFWwindow *window, double xoffset, double yoffset)
void set_graphics_registered(bool registered) override
Mark window as registered/unregistered with graphics Called by GraphicsSubsystem during register/unre...
static void glfw_key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
WindowCreateInfo m_create_info
static void glfw_cursor_pos_callback(GLFWwindow *window, double xpos, double ypos)
void * get_native_handle() const override
Get native window handle (platform-specific)
void show() override
Show the window.
void set_title(const std::string &title) override
Set window title, size, or position.
static void glfw_window_size_callback(GLFWwindow *window, int width, int height)
void set_position(uint32_t x, uint32_t y) override
Move the window to a new position.
void set_event_callback(WindowEventCallback callback) override
Set the callback function for window events.
std::atomic< bool > m_graphics_registered
static void glfw_window_focus_callback(GLFWwindow *window, int focused)
GlfwWindow & operator=(const GlfwWindow &)=delete
static void glfw_mouse_button_callback(GLFWwindow *window, int button, int action, int mods)
void hide() override
Hide the window.
void configure_window_hints(const GraphicsSurfaceInfo &surface_info, GlobalGraphicsConfig::GraphicsApi api) const
static void glfw_window_close_callback(GLFWwindow *window)
void set_size(uint32_t width, uint32_t height) override
Resize the window.
static void glfw_framebuffer_size_callback(GLFWwindow *window, int width, int height)
WindowEventCallback m_event_callback
GlfwWindow(const WindowCreateInfo &create_info, const GraphicsSurfaceInfo &surface_info, GlobalGraphicsConfig::GraphicsApi api, GlfwPreInitConfig pre_init_config={})
Creates a window with the given configuration.
Platform-agnostic window wrapper.
WindowEventType
Types of window and input events.
std::function< void(const WindowEvent &)> WindowEventCallback
@ WindowingSubsystem
Windowing system operations (GLFW, SDL)
@ Core
Core engine, backend, subsystems.
Configuration hints for GLFW initialization.
System-wide configuration for visual stream processing.
bool transparent
Transparent framebuffer (compositing)
std::string title
Window title/identifier.
bool fullscreen
Start in fullscreen mode.
bool resizable
Window can be resized by user.
uint32_t width
Initial window dimensions.
int32_t monitor_id
Target monitor ID (-1 = primary monitor)
bool decorated
Show OS window decorations (title bar, borders)
Configuration for creating a single window instance.
Event data for window and input events.