// 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 // --- Callbacks --- static void framebuffer_size_callback(GLFWwindow* window, int width, int height) { PlatformState* state = (PlatformState*)glfwGetWindowUserPointer(window); if (state) { state->width = width; state->height = height; } } static void glfw_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { PlatformState* state = (PlatformState*)glfwGetWindowUserPointer(window); if (action == GLFW_PRESS) { if (key == GLFW_KEY_ESCAPE || key == GLFW_KEY_Q) { glfwSetWindowShouldClose(window, GLFW_TRUE); } else if (key == GLFW_KEY_F) { if (state) platform_toggle_fullscreen(state); } } } // --- Public API Implementation --- void platform_init(PlatformState* state, bool fullscreen, int* width_ptr, int* height_ptr) { if (width_ptr && height_ptr) { state->width = *width_ptr; state->height = *height_ptr; } glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); state->window = glfwCreateWindow(state->width, state->height, "demo64k", nullptr, nullptr); // Store our state pointer in the window for callbacks glfwSetWindowUserPointer(state->window, state); // Immediately query the actual framebuffer size for high-DPI displays glfwGetFramebufferSize(state->window, &state->width, &state->height); glfwSetKeyCallback(state->window, glfw_key_callback); glfwSetFramebufferSizeCallback(state->window, framebuffer_size_callback); state->is_fullscreen = fullscreen; if (fullscreen) { glfwGetWindowPos(state->window, &state->windowed_x, &state->windowed_y); glfwGetWindowSize(state->window, &state->windowed_w, &state->windowed_h); GLFWmonitor* monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(monitor); glfwSetWindowMonitor(state->window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); } } void platform_shutdown(PlatformState* state) { if (state->window) { glfwDestroyWindow(state->window); } glfwTerminate(); } void platform_poll(PlatformState* state) { glfwPollEvents(); } bool platform_should_close(PlatformState* state) { return glfwWindowShouldClose(state->window); } void platform_toggle_fullscreen(PlatformState* state) { state->is_fullscreen = !state->is_fullscreen; if (state->is_fullscreen) { glfwGetWindowPos(state->window, &state->windowed_x, &state->windowed_y); glfwGetWindowSize(state->window, &state->windowed_w, &state->windowed_h); GLFWmonitor* monitor = glfwGetPrimaryMonitor(); const GLFWvidmode* mode = glfwGetVideoMode(monitor); glfwSetWindowMonitor(state->window, monitor, 0, 0, mode->width, mode->height, mode->refreshRate); } else { glfwSetWindowMonitor(state->window, nullptr, state->windowed_x, state->windowed_y, state->windowed_w, state->windowed_h, 0); } } WGPUSurface platform_create_wgpu_surface(WGPUInstance instance, PlatformState* state) { return glfwCreateWindowWGPUSurface(instance, state->window); } // Note: platform_get_* functions are now inline in the header. // platform_get_time() remains global.