// This file is part of the 64k demo project. // It implements platform-specific windowing and input using GLFW. // Handles fullscreen toggling and native surface creation for WebGPU. #include "platform.h" #include "glfw3webgpu.h" #include static GLFWwindow* window = nullptr; static int windowed_x, windowed_y, windowed_w, windowed_h; static bool g_is_fullscreen = false; // --- New state for framebuffer size --- static int g_width = 1280; static int g_height = 720; // Forward declaration for callback void platform_toggle_fullscreen(); // --- Callbacks --- static void framebuffer_size_callback(GLFWwindow* cb_window, int width, int height) { (void)cb_window; // Unused g_width = width; g_height = height; // Note: We would trigger a swap chain resize here, but our demo handles it implicitly. } static void glfw_key_callback(GLFWwindow* cb_window, int key, int scancode, int action, int mods) { if (action == GLFW_PRESS) { if (key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) { glfwSetWindowShouldClose(cb_window, GLFW_TRUE); } else if (key == GLFW_KEY_F) { platform_toggle_fullscreen(); } } } void platform_init_window(bool fullscreen, int* width_ptr, int* height_ptr) { if (width_ptr && height_ptr) { g_width = *width_ptr; g_height = *height_ptr; } glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); window = glfwCreateWindow(g_width, g_height, "demo64k", nullptr, nullptr); // Immediately query the actual framebuffer size for high-DPI displays glfwGetFramebufferSize(window, &g_width, &g_height); glfwSetKeyCallback(window, glfw_key_callback); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); g_is_fullscreen = fullscreen; if (fullscreen) { // Save current windowed mode dimensions before going fullscreen glfwGetWindowPos(window, &windowed_x, &windowed_y); glfwGetWindowSize(window, &windowed_w, &windowed_h); GLFWmonitor* monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(monitor); glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); } } void platform_shutdown() { glfwDestroyWindow(window); glfwTerminate(); } void platform_poll() { glfwPollEvents(); } bool platform_should_close() { return glfwWindowShouldClose(window); } void platform_toggle_fullscreen() { g_is_fullscreen = !g_is_fullscreen; if (g_is_fullscreen) { glfwGetWindowPos(window, &windowed_x, &windowed_y); glfwGetWindowSize(window, &windowed_w, &windowed_h); GLFWmonitor* monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(monitor); glfwSetWindowMonitor(window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); } else { glfwSetWindowMonitor(window, nullptr, windowed_x, windowed_y, windowed_w, windowed_h, 0); } } GLFWwindow* platform_get_window() { return window; } double platform_get_time() { return glfwGetTime(); } // --- New dimension getters --- int platform_get_width() { return g_width; } int platform_get_height() { return g_height; } float platform_get_aspect_ratio() { if (g_height == 0) return 1.0f; return (float)g_width / (float)g_height; } WGPUSurface platform_create_wgpu_surface(WGPUInstance instance) { return glfwCreateWindowWGPUSurface(instance, window); }