aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Weissflog <floooh@gmail.com>2025-09-01 20:26:38 +0200
committerGitHub <noreply@github.com>2025-09-01 20:26:38 +0200
commit52e84e5a79fcaaf5fcccdc29bf80f37e79c0006a (patch)
treebb7d2a6e537004da65915ddd581c1d582548034e
parent017962e85ca9f5f29b58c758d8da6e8721786d1f (diff)
parentb7a3672cba11b90b6e7cc78d9cfaae5ad8b202ee (diff)
Merge pull request #1324 from floooh/Seb-degraff-sapp-fullscreen-web
Merge branch for #1322 (web fullscreen support)
-rw-r--r--CHANGELOG.md8
-rw-r--r--README.md2
-rw-r--r--sokol_app.h82
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
diff --git a/README.md b/README.md
index d1d522d5..1e811658 100644
--- a/README.md
+++ b/README.md
@@ -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)
[![Build](/../../actions/workflows/main.yml/badge.svg)](/../../actions/workflows/main.yml) [![Bindings](/../../actions/workflows/gen_bindings.yml/badge.svg)](/../../actions/workflows/gen_bindings.yml) [![build](https://github.com/floooh/sokol-zig/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-zig/actions/workflows/main.yml) [![build](https://github.com/floooh/sokol-nim/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-nim/actions/workflows/main.yml) [![Odin](https://github.com/floooh/sokol-odin/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-odin/actions/workflows/main.yml)[![Rust](https://github.com/floooh/sokol-rust/actions/workflows/main.yml/badge.svg)](https://github.com/floooh/sokol-rust/actions/workflows/main.yml)[![Dlang](https://github.com/kassane/sokol-d/actions/workflows/build.yml/badge.svg)](https://github.com/kassane/sokol-d/actions/workflows/build.yml)[![C3](https://github.com/floooh/sokol-c3/actions/workflows/build.yml/badge.svg)](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
}