fix: no restaurava la pantalla en emscripten al eixir de fullscreen
This commit is contained in:
@@ -33,22 +33,60 @@
|
|||||||
Screen* Screen::screen = nullptr;
|
Screen* Screen::screen = nullptr;
|
||||||
|
|
||||||
#ifdef __EMSCRIPTEN__
|
#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
|
// Restauració del canvas en wasm/Emscripten
|
||||||
// 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.
|
// Problema: SDL3 + Emscripten no notifica de manera fiable els canvis de mida
|
||||||
|
// del canvas HTML. En concret:
|
||||||
|
// - SDL_EVENT_WINDOW_LEAVE_FULLSCREEN no s'emet quan l'usuari surt de
|
||||||
|
// fullscreen amb Esc/F11 (libsdl-org/SDL#13300).
|
||||||
|
// - SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED i SDL_EVENT_DISPLAY_ORIENTATION
|
||||||
|
// tampoc es disparen de manera fiable (libsdl-org/SDL#11389).
|
||||||
|
// - Resultat: en sortir de fullscreen el canvas queda a la mida correcta
|
||||||
|
// però SDL encara creu que està en fullscreen amb la resolució anterior,
|
||||||
|
// i el joc es veu minúscul fins que l'usuari força un refresh manual
|
||||||
|
// (p. ex., canviant el mode d'escalat amb F7).
|
||||||
|
//
|
||||||
|
// Solució: registrem callbacks natius d'Emscripten (fullscreenchange, resize,
|
||||||
|
// orientationchange) que re-sincronitzen SDL amb l'estat real del navegador.
|
||||||
|
// Tots delegen en Screen::handleCanvasResized(), que crida setVideoMode()
|
||||||
|
// amb l'estat de fullscreen actualitzat — això és el que realment restaura
|
||||||
|
// la finestra SDL perquè dins setVideoMode es crida SDL_SetWindowFullscreen,
|
||||||
|
// que és imprescindible per treure SDL del seu estat intern de fullscreen.
|
||||||
|
//
|
||||||
|
// Els callbacks diferixen la feina amb emscripten_async_call(0ms) perquè
|
||||||
|
// quan l'event es dispara el navegador encara no ha acabat de redimensionar
|
||||||
|
// el canvas: llegir la mida en aquest instant donaria un valor obsolet.
|
||||||
|
// Posposar al següent tick del event loop garanteix que el canvas ja està
|
||||||
|
// estable quan actuem.
|
||||||
|
//
|
||||||
|
// Referències:
|
||||||
|
// - https://github.com/libsdl-org/SDL/issues/13300
|
||||||
|
// - https://github.com/libsdl-org/SDL/issues/11389
|
||||||
|
// - https://discourse.libsdl.org/t/sdl-emscripten-allow-resize-events-on-fullscreen-windows/66279
|
||||||
|
// ============================================================================
|
||||||
namespace {
|
namespace {
|
||||||
auto onEmFullscreenChange(int /*event_type*/, const EmscriptenFullscreenChangeEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
|
void deferredCanvasResize(void* /*user_data*/) {
|
||||||
if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); }
|
if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
auto onEmFullscreenChange(int /*event_type*/, const EmscriptenFullscreenChangeEvent* event, void* /*user_data*/) -> EM_BOOL {
|
||||||
|
// Actualitzem Options::video.fullscreen amb l'estat real del navegador
|
||||||
|
// abans de diferir la restauració: quan l'usuari surt amb Esc no passem
|
||||||
|
// per setVideoMode() i l'estat intern quedaria desincronitzat.
|
||||||
|
Options::video.fullscreen = (event != nullptr && event->isFullscreen != 0);
|
||||||
|
emscripten_async_call(deferredCanvasResize, nullptr, 0);
|
||||||
return EM_FALSE;
|
return EM_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto onEmResize(int /*event_type*/, const EmscriptenUiEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
|
auto onEmResize(int /*event_type*/, const EmscriptenUiEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
|
||||||
if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); }
|
emscripten_async_call(deferredCanvasResize, nullptr, 0);
|
||||||
return EM_FALSE;
|
return EM_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto onEmOrientationChange(int /*event_type*/, const EmscriptenOrientationChangeEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
|
auto onEmOrientationChange(int /*event_type*/, const EmscriptenOrientationChangeEvent* /*event*/, void* /*user_data*/) -> EM_BOOL {
|
||||||
if (Screen::get() != nullptr) { Screen::get()->handleCanvasResized(); }
|
emscripten_async_call(deferredCanvasResize, nullptr, 0);
|
||||||
return EM_FALSE;
|
return EM_FALSE;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -194,23 +232,18 @@ void Screen::toggleVideoMode() {
|
|||||||
setVideoMode(Options::video.fullscreen);
|
setVideoMode(Options::video.fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-sincronitza la finestra SDL amb la mida real del canvas HTML. Només cal en
|
// Re-sincronitza SDL amb l'estat real del canvas del navegador. L'invoquen els
|
||||||
// emscripten: quan l'usuari surt de fullscreen amb Esc, rota el dispositiu o
|
// callbacks natius d'Emscripten definits a dalt (vegeu el bloc de documentació
|
||||||
// canvia la mida del canvas, SDL3 no emet SDL_EVENT_WINDOW_LEAVE_FULLSCREEN ni
|
// just després dels includes) quan es detecta un fullscreenchange, resize o
|
||||||
// SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED de manera fiable (issues libsdl-org/SDL
|
// orientationchange. Delegar a setVideoMode() és el que realment restaura la
|
||||||
// #13300 i #11389), així que els callbacks d'Emscripten criden aquest mètode
|
// finestra: per sota crida SDL_SetWindowFullscreen, imprescindible perquè
|
||||||
// directament. Llegim la mida real del canvas per CSS i l'apliquem a la finestra
|
// SDL tregui el seu estat intern de fullscreen quan l'usuari ha sortit amb
|
||||||
// SDL perquè el logical presentation s'escali al nou viewport.
|
// Esc sense passar pel nostre toggleVideoMode(). No fem res fora d'emscripten
|
||||||
|
// perquè en desktop SDL ja emet SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED correctament.
|
||||||
void Screen::handleCanvasResized() {
|
void Screen::handleCanvasResized() {
|
||||||
#ifdef __EMSCRIPTEN__
|
#ifdef __EMSCRIPTEN__
|
||||||
double css_w = 0.0;
|
setVideoMode(Options::video.fullscreen);
|
||||||
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<int>(css_w), static_cast<int>(css_h));
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
adjustRenderLogicalSize();
|
|
||||||
updateZoomFactor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduce el tamaño de la ventana
|
// Reduce el tamaño de la ventana
|
||||||
@@ -788,17 +821,21 @@ auto Screen::initSDLVideo() -> bool {
|
|||||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
|
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
|
||||||
SDL_SetRenderVSync(renderer_, Options::video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
SDL_SetRenderVSync(renderer_, Options::video.vertical_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
||||||
|
|
||||||
|
registerEmscriptenEventCallbacks();
|
||||||
|
|
||||||
|
std::cout << "Video system initialized successfully\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Registra els callbacks natius d'Emscripten que restauren el canvas quan
|
||||||
|
// SDL3 no emet els events equivalents. Fora d'Emscripten és un no-op.
|
||||||
|
// Vegeu el bloc de documentació a dalt del fitxer per al context complet.
|
||||||
|
void Screen::registerEmscriptenEventCallbacks() { // NOLINT(readability-convert-member-functions-to-static)
|
||||||
#ifdef __EMSCRIPTEN__
|
#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_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_TRUE, onEmFullscreenChange);
|
||||||
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_TRUE, onEmResize);
|
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_TRUE, onEmResize);
|
||||||
emscripten_set_orientationchange_callback(nullptr, EM_TRUE, onEmOrientationChange);
|
emscripten_set_orientationchange_callback(nullptr, EM_TRUE, onEmOrientationChange);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::cout << "Video system initialized successfully\n";
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea el objeto de texto
|
// Crea el objeto de texto
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class Screen {
|
|||||||
// Video y ventana
|
// Video y ventana
|
||||||
void setVideoMode(bool mode); // Establece el modo de video
|
void setVideoMode(bool mode); // Establece el modo de video
|
||||||
void toggleVideoMode(); // Cambia entre pantalla completa y ventana
|
void toggleVideoMode(); // Cambia entre pantalla completa y ventana
|
||||||
void handleCanvasResized(); // Re-sincronitza SDL amb la mida real del canvas (emscripten: sortida de fullscreen, rotació, resize)
|
void handleCanvasResized(); // Restaura el canvas quan SDL3 no reporta el canvi (emscripten only: sortida de fullscreen amb Esc, rotació, resize); no-op fora d'emscripten
|
||||||
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
|
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
|
||||||
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
|
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
|
||||||
auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana
|
auto decWindowZoom() -> bool; // Reduce el tamaño de la ventana
|
||||||
@@ -137,6 +137,7 @@ class Screen {
|
|||||||
void applyCurrentCrtPiPreset(); // Aplica los parámetros del preset CrtPi actual al backend
|
void applyCurrentCrtPiPreset(); // Aplica los parámetros del preset CrtPi actual al backend
|
||||||
void getDisplayInfo(); // Obtiene información sobre la pantalla
|
void getDisplayInfo(); // Obtiene información sobre la pantalla
|
||||||
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
|
auto initSDLVideo() -> bool; // Arranca SDL VIDEO y crea la ventana
|
||||||
|
void registerEmscriptenEventCallbacks(); // Registra els callbacks natius per restaurar el canvas en wasm (no-op fora d'emscripten)
|
||||||
void createText(); // Crea el objeto de texto
|
void createText(); // Crea el objeto de texto
|
||||||
|
|
||||||
// Constructor y destructor
|
// Constructor y destructor
|
||||||
|
|||||||
Reference in New Issue
Block a user