corregit bug de fullscreen en emscripten
This commit is contained in:
@@ -10,6 +10,53 @@
|
|||||||
#include "mouse.hpp" // for Mouse::cursorVisible, Mouse::lastMouseMoveTime
|
#include "mouse.hpp" // for Mouse::cursorVisible, Mouse::lastMouseMoveTime
|
||||||
#include "text.h" // for Text, TXT_CENTER, TXT_COLOR, TXT_STROKE
|
#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
|
// Constructor
|
||||||
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options) {
|
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options) {
|
||||||
// Inicializa variables
|
// Inicializa variables
|
||||||
@@ -47,6 +94,9 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options
|
|||||||
notificationOutlineColor = {0x00, 0x00, 0x00};
|
notificationOutlineColor = {0x00, 0x00, 0x00};
|
||||||
notificationEndTime = 0;
|
notificationEndTime = 0;
|
||||||
notificationY = 2;
|
notificationY = 2;
|
||||||
|
|
||||||
|
// Registra callbacks natius d'Emscripten per a fullscreen/resize/orientation
|
||||||
|
registerEmscriptenEventCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
@@ -254,6 +304,35 @@ void Screen::clearNotification() {
|
|||||||
notificationMessage.clear();
|
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
|
// Dibuja la notificación activa (si la hay) sobre el gameCanvas
|
||||||
void Screen::renderNotification() {
|
void Screen::renderNotification() {
|
||||||
if (SDL_GetTicks() >= notificationEndTime) {
|
if (SDL_GetTicks() >= notificationEndTime) {
|
||||||
|
|||||||
@@ -95,4 +95,19 @@ class Screen {
|
|||||||
|
|
||||||
// Limpia la notificación actual
|
// Limpia la notificación actual
|
||||||
void clearNotification();
|
void clearNotification();
|
||||||
|
|
||||||
|
// En Emscripten, reaplica setVideoMode tras un canvi del navegador (eixida
|
||||||
|
// de fullscreen amb Esc, resize, canvi d'orientació). Fora d'Emscripten
|
||||||
|
// és un no-op. Vore screen.cpp per al perquè del fix.
|
||||||
|
void handleCanvasResized();
|
||||||
|
|
||||||
|
// Sincronitza el flag intern de fullscreen amb l'estat real del navegador.
|
||||||
|
// Ha de cridar-se abans de diferir handleCanvasResized perquè
|
||||||
|
// setVideoMode llija el valor correcte. No-op fora d'Emscripten.
|
||||||
|
void syncFullscreenFlagFromBrowser(bool isFullscreen);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Registra els callbacks natius d'Emscripten per a fullscreenchange,
|
||||||
|
// resize i orientationchange. No-op fora d'Emscripten.
|
||||||
|
void registerEmscriptenEventCallbacks();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user