afegits events de canvas d'emscripten
This commit is contained in:
@@ -12,6 +12,49 @@
|
|||||||
#include "game/options.hpp"
|
#include "game/options.hpp"
|
||||||
#include "utils/utils.hpp"
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
#include <emscripten.h>
|
||||||
|
#include <emscripten/html5.h>
|
||||||
|
|
||||||
|
// --- Fix per a fullscreen/resize en Emscripten ---
|
||||||
|
//
|
||||||
|
// SDL3 + Emscripten no emet de forma fiable SDL_EVENT_WINDOW_LEAVE_FULLSCREEN
|
||||||
|
// (libsdl-org/SDL#13300) ni SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED /
|
||||||
|
// SDL_EVENT_DISPLAY_ORIENTATION (libsdl-org/SDL#11389). Quan l'usuari ix de
|
||||||
|
// fullscreen amb Esc o rota el mòbil, el canvas HTML torna al tamany correcte
|
||||||
|
// però l'estat intern de SDL creu que segueix en fullscreen amb la resolució
|
||||||
|
// anterior i el viewport queda desencuadrat.
|
||||||
|
//
|
||||||
|
// Solució: registrar callbacks natius d'Emscripten, diferir la feina un tick
|
||||||
|
// del event loop (el canvas encara no està estable en el moment del callback)
|
||||||
|
// i re-sincronitzar SDL cridant SDL_SetWindowFullscreen + applyFallbackPresentation.
|
||||||
|
// La crida interna a SDL_SetWindowFullscreen és la peça que realment fa
|
||||||
|
// resincronitzar l'estat intern de SDL — sense això la logical presentation
|
||||||
|
// no encaixa amb el canvas real.
|
||||||
|
namespace {
|
||||||
|
Screen* g_screen_instance = nullptr;
|
||||||
|
|
||||||
|
void deferredCanvasResize(void* /*userData*/) {
|
||||||
|
if (g_screen_instance != nullptr) {
|
||||||
|
g_screen_instance->handleCanvasResized();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_BOOL onEmFullscreenChange(int /*eventType*/, const EmscriptenFullscreenChangeEvent* event, void* /*userData*/) {
|
||||||
|
if (g_screen_instance != nullptr && event != nullptr) {
|
||||||
|
g_screen_instance->syncFullscreenFlagFromBrowser(event->isFullscreen != 0);
|
||||||
|
}
|
||||||
|
emscripten_async_call(deferredCanvasResize, nullptr, 0);
|
||||||
|
return EM_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_BOOL onEmOrientationChange(int /*eventType*/, const EmscriptenOrientationChangeEvent* /*event*/, void* /*userData*/) {
|
||||||
|
emscripten_async_call(deferredCanvasResize, nullptr, 0);
|
||||||
|
return EM_FALSE;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
#endif // __EMSCRIPTEN__
|
||||||
|
|
||||||
Screen* Screen::instance_ = nullptr;
|
Screen* Screen::instance_ = nullptr;
|
||||||
|
|
||||||
void Screen::init() {
|
void Screen::init() {
|
||||||
@@ -57,9 +100,23 @@ Screen::Screen() {
|
|||||||
initShaders();
|
initShaders();
|
||||||
|
|
||||||
std::cout << "Screen initialized: " << w << "x" << h << " (zoom " << zoom_ << ", max " << max_zoom_ << ")\n";
|
std::cout << "Screen initialized: " << w << "x" << h << " (zoom " << zoom_ << ", max " << max_zoom_ << ")\n";
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
// IMPORTANT: NO registrem resize callback genèric. En mòbil, fer scroll
|
||||||
|
// fa que el navegador oculti/mostri la barra d'URL, disparant un resize
|
||||||
|
// del DOM per cada scroll. Això portaria a re-aplicar logical presentation
|
||||||
|
// per cada scroll i corrompria el viewport intern de SDL.
|
||||||
|
g_screen_instance = this;
|
||||||
|
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_TRUE, onEmFullscreenChange);
|
||||||
|
emscripten_set_orientationchange_callback(nullptr, EM_TRUE, onEmOrientationChange);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen::~Screen() {
|
Screen::~Screen() {
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
g_screen_instance = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Guarda opcions abans de destruir
|
// Guarda opcions abans de destruir
|
||||||
Options::window.zoom = zoom_;
|
Options::window.zoom = zoom_;
|
||||||
Options::window.fullscreen = fullscreen_;
|
Options::window.fullscreen = fullscreen_;
|
||||||
@@ -561,3 +618,25 @@ void Screen::calculateMaxZoom() {
|
|||||||
if (max_zoom_ < 1) max_zoom_ = 1;
|
if (max_zoom_ < 1) max_zoom_ = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
// ============================================================================
|
||||||
|
// Emscripten — fix per a fullscreen/resize (veure el bloc de comentaris al
|
||||||
|
// principi del fitxer i l'anonymous namespace amb els callbacks natius).
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
void Screen::handleCanvasResized() {
|
||||||
|
if (window_ == nullptr) return;
|
||||||
|
// Re-sincronitza l'estat intern de SDL amb el canvas HTML real. La crida
|
||||||
|
// a SDL_SetWindowFullscreen és l'única manera de forçar SDL a reconèixer
|
||||||
|
// la mida actual del canvas; després re-apliquem la logical presentation
|
||||||
|
// (el path WASM sempre va pel fallback SDL_Renderer, sense shaders GPU).
|
||||||
|
SDL_SetWindowFullscreen(window_, fullscreen_);
|
||||||
|
applyFallbackPresentation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screen::syncFullscreenFlagFromBrowser(bool is_fullscreen) {
|
||||||
|
fullscreen_ = is_fullscreen;
|
||||||
|
Options::window.fullscreen = is_fullscreen;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -52,6 +52,14 @@ class Screen {
|
|||||||
[[nodiscard]] auto getWindow() -> SDL_Window* { return window_; }
|
[[nodiscard]] auto getWindow() -> SDL_Window* { return window_; }
|
||||||
[[nodiscard]] auto getRenderer() -> SDL_Renderer* { return renderer_; }
|
[[nodiscard]] auto getRenderer() -> SDL_Renderer* { return renderer_; }
|
||||||
|
|
||||||
|
#ifdef __EMSCRIPTEN__
|
||||||
|
// Sincronització amb el canvas HTML quan el navegador canvia la mida
|
||||||
|
// (fullscreen entrant/eixint, rotació de mòbil). Cridat pels callbacks
|
||||||
|
// natius d'Emscripten registrats al constructor.
|
||||||
|
void handleCanvasResized();
|
||||||
|
void syncFullscreenFlagFromBrowser(bool is_fullscreen);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Screen();
|
Screen();
|
||||||
~Screen();
|
~Screen();
|
||||||
|
|||||||
Reference in New Issue
Block a user