diff options
| author | Andre Weissflog <floooh@gmail.com> | 2025-09-01 20:26:38 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-01 20:26:38 +0200 |
| commit | 52e84e5a79fcaaf5fcccdc29bf80f37e79c0006a (patch) | |
| tree | bb7d2a6e537004da65915ddd581c1d582548034e | |
| parent | 017962e85ca9f5f29b58c758d8da6e8721786d1f (diff) | |
| parent | b7a3672cba11b90b6e7cc78d9cfaae5ad8b202ee (diff) | |
Merge pull request #1324 from floooh/Seb-degraff-sapp-fullscreen-web
Merge branch for #1322 (web fullscreen support)
| -rw-r--r-- | CHANGELOG.md | 8 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | sokol_app.h | 82 |
3 files changed, 90 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e739665..5c19bf56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,14 @@ restored when moving the mouse outside a window and then back in. Again, many thanks to @Seb-degraff for identifying the issue and providing a fix via PR https://github.com/floooh/sokol/pull/1323! +- ...and another sokol_app.h update: `sapp_toggle_fullscreen()` now works on the web + (with the usual web platform caveats: the function needs to be called within + or 'near' an input event, and the user may leave fullscreen mode at any time, + and Safari on iOS doesn't support fullscreen mode at all). + + Many thanks again to @Seb-degraff for kicking this off! Original PR: + https://github.com/floooh/sokol/pull/1322, merge branch PR with additional + fixes: https://github.com/floooh/sokol/pull/1324 ### 29-Aug-2025 @@ -6,7 +6,7 @@ # Sokol -[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**01-Sep-2025**: custom mouse cursors in sokol_app.h) +[**See what's new**](https://github.com/floooh/sokol/blob/master/CHANGELOG.md) (**01-Sep-2025**: custom mouse cursors in and web fullscreen support in sokol_app.h) [](/../../actions/workflows/main.yml) [](/../../actions/workflows/gen_bindings.yml) [](https://github.com/floooh/sokol-zig/actions/workflows/main.yml) [](https://github.com/floooh/sokol-nim/actions/workflows/main.yml) [](https://github.com/floooh/sokol-odin/actions/workflows/main.yml)[](https://github.com/floooh/sokol-rust/actions/workflows/main.yml)[](https://github.com/kassane/sokol-d/actions/workflows/build.yml)[](https://github.com/floooh/sokol-c3/actions/workflows/build.yml) diff --git a/sokol_app.h b/sokol_app.h index 3fd1be57..7a7e0e8e 100644 --- a/sokol_app.h +++ b/sokol_app.h @@ -133,7 +133,7 @@ IME | TODO | TODO? | TODO | ??? | TODO | ??? key repeat flag | YES | YES | YES | --- | --- | YES windowed | YES | YES | YES | --- | --- | YES - fullscreen | YES | YES | YES | YES | YES | --- + fullscreen | YES | YES | YES | YES | YES | YES(3) mouse hide | YES | YES | YES | --- | --- | YES mouse lock | YES | YES | YES | --- | --- | YES set cursor type | YES | YES | YES | --- | --- | YES @@ -147,6 +147,7 @@ (1) macOS has no regular window icons, instead the dock icon is changed (2) supported with EGL only (not GLX) + (3) fullscreen in the browser not supported on iphones STEP BY STEP ============ @@ -864,6 +865,15 @@ To check if the application window is currently in fullscreen mode, call sapp_is_fullscreen(). + On the web, sapp_desc.fullscreen will have no effect, and the application + will always start in non-fullscreen mode. Call sapp_toggle_fullscreen() + from within or 'near' an input event to switch to fullscreen programatically. + Note that on the web, the fullscreen state may change back to windowed at + any time (either because the browser had rejected switching into fullscreen, + or the user leaves fullscreen via Esc), this means that the result + of sapp_is_fullscreen() may change also without calling sapp_toggle_fullscreen()! + + WINDOW ICON SUPPORT =================== Some sokol_app.h backends allow to change the window icon programmatically: @@ -5381,6 +5391,12 @@ EMSCRIPTEN_KEEPALIVE void _sapp_emsc_invoke_fetch_cb(int index, int success, int callback(&response); } +// will be called after the request/exitFullscreen promise rejects +// to restore the _sapp.fullscreen flag to the actual fullscreen state +EMSCRIPTEN_KEEPALIVE void _sapp_emsc_set_fullscreen_flag(int f) { + _sapp.fullscreen = (bool)f; +} + #ifdef __cplusplus } /* extern "C" */ #endif @@ -5713,6 +5729,65 @@ _SOKOL_PRIVATE void _sapp_emsc_destroy_custom_mouse_cursor(sapp_mouse_cursor cur sapp_js_destroy_custom_mouse_cursor((int) cursor); } +// NOTE: this callback is needed to react to the user actively leaving fullscreen mode via Esc +_SOKOL_PRIVATE EM_BOOL _sapp_emsc_fullscreenchange_cb(int emsc_type, const EmscriptenFullscreenChangeEvent* emsc_event, void* user_data) { + _SOKOL_UNUSED(emsc_type); + _SOKOL_UNUSED(user_data); + _sapp.fullscreen = emsc_event->isFullscreen; + return true; +} + +EM_JS(void, sapp_js_toggle_fullscreen, (void), { + const canvas = Module.sapp_emsc_target; + if (canvas) { + // NOTE: Safari had the prefix until 2023, Firefox until 2018 + const fullscreenElement = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement; + let p = undefined; + if (!fullscreenElement) { + if (canvas.requestFullscreen) { + p = canvas.requestFullscreen(); + } else if (canvas.webkitRequestFullscreen) { + p = canvas.webkitRequestFullscreen(); + } else if (canvas.mozRequestFullScreen) { + p = canvas.mozRequestFullScreen(); + } + if (p) { + p.catch((err) => { + console.warn('sapp_js_toggle_fullscreen(): failed to enter fullscreen mode with', err); + __sapp_emsc_set_fullscreen_flag(0); + }); + } else { + console.warn('sapp_js_toogle_fullscreen(): browser has no [webkit|moz]requestFullscreen function'); + __sapp_emsc_set_fullscreen_flag(0); + } + } else { + if (document.exitFullscreen) { + p = document.exitFullscreen(); + } else if (document.webkitExitFullscreen) { + p = document.webkitExitFullscreen(); + } else if (document.mozCancelFullScreen) { + p = document.mozCancelFullScreen(); + } + if (p) { + p.catch((err) => { + console.warn('sapp_js_toggle_fullscreen(): failed to exit fullscreen mode with', err); + __sapp_emsc_set_fullscreen_flag(1); + }); + } else { + console.warn('sapp_js_toggle_fullscreen(): browser has no [wekbit|moz]exitFullscreen'); + // NOTE: don't need to explicitly set the fullscreen flag here + } + } + } +}) + +_SOKOL_PRIVATE void _sapp_emsc_toggle_fullscreen(void) { + // toggle the fullscreen flag preliminary, this may be undone + // when requesting/exiting fullscreen mode actually fails + _sapp.fullscreen = !_sapp.fullscreen; + sapp_js_toggle_fullscreen(); +} + /* JS helper functions to update browser tab favicon */ EM_JS(void, sapp_js_clear_favicon, (void), { const link = document.getElementById('sokol-app-favicon'); @@ -6253,6 +6328,7 @@ _SOKOL_PRIVATE void _sapp_emsc_register_eventhandlers(void) { emscripten_set_pointerlockerror_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, _sapp_emsc_pointerlockerror_cb); emscripten_set_focus_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_focus_cb); emscripten_set_blur_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, _sapp_emsc_blur_cb); + emscripten_set_fullscreenchange_callback(_sapp.html5_canvas_selector, 0, true, _sapp_emsc_fullscreenchange_cb); sapp_js_add_beforeunload_listener(); if (_sapp.clipboard.enabled) { sapp_js_add_clipboard_listener(); @@ -6284,6 +6360,7 @@ _SOKOL_PRIVATE void _sapp_emsc_unregister_eventhandlers(void) { emscripten_set_pointerlockerror_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, 0, true, 0); emscripten_set_focus_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); emscripten_set_blur_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); + emscripten_set_fullscreenchange_callback(_sapp.html5_canvas_selector, 0, true, 0); if (!_sapp.desc.html5_canvas_resize) { emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, true, 0); } @@ -6339,6 +6416,7 @@ _SOKOL_PRIVATE void _sapp_emsc_frame_main_loop(void) { _SOKOL_PRIVATE void _sapp_emsc_run(const sapp_desc* desc) { _sapp_init_state(desc); + _sapp.fullscreen = false; // override user provided fullscreen state: can't start in fullscreen on the web! const char* document_title = desc->html5_update_document_title ? _sapp.window_title : 0; sapp_js_init(_sapp.html5_canvas_selector, document_title); double w, h; @@ -12316,6 +12394,8 @@ SOKOL_API_IMPL void sapp_toggle_fullscreen(void) { _sapp_win32_toggle_fullscreen(); #elif defined(_SAPP_LINUX) _sapp_x11_toggle_fullscreen(); + #elif defined(_SAPP_EMSCRIPTEN) + _sapp_emsc_toggle_fullscreen(); #endif } |