corregit bug de fullscreen en emscripten
This commit is contained in:
@@ -10,6 +10,53 @@
|
||||
#include "mouse.hpp" // for Mouse::cursorVisible, Mouse::lastMouseMoveTime
|
||||
#include "text.h" // for Text, TXT_CENTER, TXT_COLOR, TXT_STROKE
|
||||
|
||||
#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 cridar setVideoMode() amb el flag de fullscreen actualitzat. La crida
|
||||
// interna a SDL_SetWindowFullscreen(false) és la peça que realment fa eixir
|
||||
// SDL del seu estat intern de fullscreen — sense això res més funciona.
|
||||
namespace {
|
||||
Screen *g_screen_instance = nullptr;
|
||||
|
||||
void deferredCanvasResize(void * /*userData*/) {
|
||||
if (g_screen_instance) {
|
||||
g_screen_instance->handleCanvasResized();
|
||||
}
|
||||
}
|
||||
|
||||
EM_BOOL onEmFullscreenChange(int /*eventType*/, const EmscriptenFullscreenChangeEvent *event, void * /*userData*/) {
|
||||
if (g_screen_instance && event) {
|
||||
g_screen_instance->syncFullscreenFlagFromBrowser(event->isFullscreen != 0);
|
||||
}
|
||||
emscripten_async_call(deferredCanvasResize, nullptr, 0);
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
EM_BOOL onEmResize(int /*eventType*/, const EmscriptenUiEvent * /*event*/, void * /*userData*/) {
|
||||
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__
|
||||
|
||||
// Constructor
|
||||
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options) {
|
||||
// Inicializa variables
|
||||
@@ -47,6 +94,9 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options
|
||||
notificationOutlineColor = {0x00, 0x00, 0x00};
|
||||
notificationEndTime = 0;
|
||||
notificationY = 2;
|
||||
|
||||
// Registra callbacks natius d'Emscripten per a fullscreen/resize/orientation
|
||||
registerEmscriptenEventCallbacks();
|
||||
}
|
||||
|
||||
// Destructor
|
||||
@@ -254,6 +304,35 @@ void Screen::clearNotification() {
|
||||
notificationMessage.clear();
|
||||
}
|
||||
|
||||
// --- Fix per a fullscreen/resize en Emscripten ---
|
||||
// Vore el bloc de comentaris a dalt i l'anonymous namespace amb els callbacks.
|
||||
|
||||
void Screen::handleCanvasResized() {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// La crida a SDL_SetWindowFullscreen + SDL_SetRenderLogicalPresentation
|
||||
// que fa setVideoMode és l'única manera de resincronitzar l'estat intern
|
||||
// de SDL amb el canvas HTML real.
|
||||
setVideoMode(options->videoMode);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::syncFullscreenFlagFromBrowser(bool isFullscreen) {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
options->videoMode = isFullscreen ? SDL_WINDOW_FULLSCREEN : 0;
|
||||
#else
|
||||
(void)isFullscreen;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::registerEmscriptenEventCallbacks() {
|
||||
#ifdef __EMSCRIPTEN__
|
||||
g_screen_instance = this;
|
||||
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_FALSE, onEmFullscreenChange);
|
||||
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_FALSE, onEmResize);
|
||||
emscripten_set_orientationchange_callback(nullptr, EM_FALSE, onEmOrientationChange);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Dibuja la notificación activa (si la hay) sobre el gameCanvas
|
||||
void Screen::renderNotification() {
|
||||
if (SDL_GetTicks() >= notificationEndTime) {
|
||||
|
||||
Reference in New Issue
Block a user