From 9047bd7d1ffe9bd7215162ef338b59e8eeb213ed Mon Sep 17 00:00:00 2001 From: Sergio Valor Date: Mon, 13 Apr 2026 20:09:18 +0200 Subject: [PATCH] tone a commitar pa provar el canvi de pantalla en emscripten --- source/core/rendering/screen.cpp | 55 +++++++++++++++++++++++++--- source/core/rendering/screen.hpp | 2 +- source/core/system/global_events.cpp | 18 +++------ 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 5189fbb..269032d 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -1,6 +1,10 @@ #include "core/rendering/screen.hpp" #include +#ifdef __EMSCRIPTEN__ +#include +#include +#endif #include // Para max, min, transform #include // Para toupper @@ -28,6 +32,28 @@ // [SINGLETON] Screen* Screen::screen = nullptr; +#ifdef __EMSCRIPTEN__ +// Callbacks d'Emscripten per detectar canvis de mida que SDL3 no reporta +// de manera fiable al wasm: sortida de fullscreen (Esc/F11), rotació del +// dispositiu i resize de la finestra del navegador. Tots reenvien al mètode +// Screen::handleCanvasResized() que re-sincronitza la finestra SDL amb la +// mida real del canvas. Veure issues libsdl-org/SDL #13300 i #11389. +namespace { + auto onEmFullscreenChange(int /*event_type*/, const EmscriptenFullscreenChangeEvent* /*event*/, void* /*user_data*/) -> EM_BOOL { + if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); } + return EM_FALSE; + } + auto onEmResize(int /*event_type*/, const EmscriptenUiEvent* /*event*/, void* /*user_data*/) -> EM_BOOL { + if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); } + return EM_FALSE; + } + auto onEmOrientationChange(int /*event_type*/, const EmscriptenOrientationChangeEvent* /*event*/, void* /*user_data*/) -> EM_BOOL { + if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); } + return EM_FALSE; + } +} // namespace +#endif + // [SINGLETON] Crearemos el objeto con esta función estática void Screen::init() { Screen::screen = new Screen(); @@ -168,11 +194,21 @@ void Screen::toggleVideoMode() { setVideoMode(Options::video.fullscreen); } -// Re-sincronitza el logical size i el factor de zoom quan la mida de la finestra canvia -// per una causa externa al joc: navegador sortint de fullscreen (Esc), rotació del dispositiu, -// redimensionat de la finestra, etc. No toca SDL_SetWindowFullscreen ni SDL_SetWindowSize -// per no interferir amb el que estigui fent el sistema/navegador. -void Screen::handleWindowResized() { +// Re-sincronitza la finestra SDL amb la mida real del canvas HTML. Només cal en +// emscripten: quan l'usuari surt de fullscreen amb Esc, rota el dispositiu o +// canvia la mida del canvas, SDL3 no emet SDL_EVENT_WINDOW_LEAVE_FULLSCREEN ni +// SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED de manera fiable (issues libsdl-org/SDL +// #13300 i #11389), així que els callbacks d'Emscripten criden aquest mètode +// directament. Llegim la mida real del canvas per CSS i l'apliquem a la finestra +// SDL perquè el logical presentation s'escali al nou viewport. +void Screen::handleCanvasResized() { +#ifdef __EMSCRIPTEN__ + double css_w = 0.0; + double css_h = 0.0; + if (emscripten_get_element_css_size("#canvas", &css_w, &css_h) == EMSCRIPTEN_RESULT_SUCCESS && css_w > 0.0 && css_h > 0.0) { + SDL_SetWindowSize(window_, static_cast(css_w), static_cast(css_h)); + } +#endif adjustRenderLogicalSize(); updateZoomFactor(); } @@ -752,6 +788,15 @@ auto Screen::initSDLVideo() -> bool { SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND); SDL_SetRenderVSync(renderer_, Options::video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED); +#ifdef __EMSCRIPTEN__ + // Registrem callbacks d'Emscripten per reaccionar a canvis de mida del + // canvas que SDL3 no notifica: sortida de fullscreen amb Esc, rotació + // del dispositiu i resize de la finestra del navegador. + emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_TRUE, onEmFullscreenChange); + emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_TRUE, onEmResize); + emscripten_set_orientationchange_callback(nullptr, EM_TRUE, onEmOrientationChange); +#endif + std::cout << "Video system initialized successfully\n"; return true; } diff --git a/source/core/rendering/screen.hpp b/source/core/rendering/screen.hpp index a04b9fd..61a474f 100644 --- a/source/core/rendering/screen.hpp +++ b/source/core/rendering/screen.hpp @@ -38,7 +38,7 @@ class Screen { // Video y ventana void setVideoMode(bool mode); // Establece el modo de video void toggleVideoMode(); // Cambia entre pantalla completa y ventana - void handleWindowResized(); // Re-sincronitza logical size i zoom en canvis de mida externs (fullscreen, rotació, resize) + void handleCanvasResized(); // Re-sincronitza SDL amb la mida real del canvas (emscripten: sortida de fullscreen, rotació, resize) void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero void toggleVSync(); // Alterna entre activar y desactivar el V-Sync auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana diff --git a/source/core/system/global_events.cpp b/source/core/system/global_events.cpp index 4602a16..6247969 100644 --- a/source/core/system/global_events.cpp +++ b/source/core/system/global_events.cpp @@ -2,12 +2,11 @@ #include "core/input/input.hpp" // Para Input (gamepad add/remove) #include "core/input/mouse.hpp" -#include "core/locale/locale.hpp" // Para Locale -#include "core/rendering/screen.hpp" // Para Screen::handleWindowResized -#include "game/options.hpp" // Para Options, options, OptionsGame, OptionsAudio -#include "game/scene_manager.hpp" // Para SceneManager::current (filtrar BACK a GAME) -#include "game/ui/console.hpp" // Para Console -#include "game/ui/notifier.hpp" // Para Notifier +#include "core/locale/locale.hpp" // Para Locale +#include "game/options.hpp" // Para Options, options, OptionsGame, OptionsAudio +#include "game/scene_manager.hpp" // Para SceneManager::current (filtrar BACK a GAME) +#include "game/ui/console.hpp" // Para Console +#include "game/ui/notifier.hpp" // Para Notifier namespace GlobalEvents { @@ -24,13 +23,6 @@ namespace GlobalEvents { // reLoadTextures(); } - // Canvi de mida de la finestra (fullscreen toggle extern, rotació del dispositiu, - // resize manual...). Re-sincronitzem el logical size del renderer i el zoom factor - // per evitar que la textura quedi estirada o desalineada amb el nou viewport. - if (event.type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && Screen::get() != nullptr) { - Screen::get()->handleWindowResized(); - } - // Connexió/desconnexió de gamepads: cal enrutar-los a Input perquè // afegisca el dispositiu a gamepads_. Sense això, en wasm els gamepads // mai es detecten (la Gamepad API del navegador només els exposa