diff options
Diffstat (limited to 'platform/web')
-rw-r--r-- | platform/web/detect.py | 8 | ||||
-rw-r--r-- | platform/web/display_server_web.cpp | 1 | ||||
-rw-r--r-- | platform/web/display_server_web.h | 2 | ||||
-rw-r--r-- | platform/web/doc_classes/EditorExportPlatformWeb.xml | 8 | ||||
-rw-r--r-- | platform/web/emscripten_helpers.py | 20 | ||||
-rw-r--r-- | platform/web/export/export_plugin.cpp | 1 | ||||
-rw-r--r-- | platform/web/js/libs/library_godot_fetch.js | 16 | ||||
-rw-r--r-- | platform/web/js/libs/library_godot_input.js | 104 |
8 files changed, 93 insertions, 67 deletions
diff --git a/platform/web/detect.py b/platform/web/detect.py index 735e2eaf4f..26bbbccffa 100644 --- a/platform/web/detect.py +++ b/platform/web/detect.py @@ -14,6 +14,7 @@ from emscripten_helpers import ( from SCons.Util import WhereIs from methods import get_compiler_version, print_error, print_warning +from platform_methods import validate_arch if TYPE_CHECKING: from SCons.Script.SConscript import SConsEnvironment @@ -86,12 +87,7 @@ def get_flags(): def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["wasm32"] - if env["arch"] not in supported_arches: - print_error( - 'Unsupported CPU architecture "%s" for Web. Supported architectures are: %s.' - % (env["arch"], ", ".join(supported_arches)) - ) - sys.exit(255) + validate_arch(env["arch"], get_name(), supported_arches) try: env["initial_memory"] = int(env["initial_memory"]) diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index 4e55cc137a..b2db62ea2f 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -1133,6 +1133,7 @@ bool DisplayServerWeb::has_feature(Feature p_feature) const { //case FEATURE_NATIVE_DIALOG: //case FEATURE_NATIVE_DIALOG_INPUT: //case FEATURE_NATIVE_DIALOG_FILE: + //case FEATURE_NATIVE_DIALOG_FILE_EXTRA: //case FEATURE_NATIVE_ICON: //case FEATURE_WINDOW_TRANSPARENCY: //case FEATURE_KEEP_SCREEN_ON: diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h index 352b3fe523..c28a6fd082 100644 --- a/platform/web/display_server_web.h +++ b/platform/web/display_server_web.h @@ -209,6 +209,7 @@ public: virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; virtual float screen_get_refresh_rate(int p_screen = SCREEN_OF_MAIN_WINDOW) const override; + virtual void screen_set_keep_on(bool p_enable) override {} virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1) override; virtual void virtual_keyboard_hide() override; @@ -265,6 +266,7 @@ public: virtual bool can_any_window_draw() const override; + virtual void window_set_vsync_mode(VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override {} virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override; // events diff --git a/platform/web/doc_classes/EditorExportPlatformWeb.xml b/platform/web/doc_classes/EditorExportPlatformWeb.xml index 755308de9a..955e3a0232 100644 --- a/platform/web/doc_classes/EditorExportPlatformWeb.xml +++ b/platform/web/doc_classes/EditorExportPlatformWeb.xml @@ -60,15 +60,15 @@ </member> <member name="progressive_web_app/icon_144x144" type="String" setter="" getter=""> File path to the smallest icon for this web application. If not defined, defaults to the project icon. - [b]Note:[/b] If the icon is not 144x144, it will be automatically resized for the final build. + [b]Note:[/b] If the icon is not 144×144, it will be automatically resized for the final build. </member> <member name="progressive_web_app/icon_180x180" type="String" setter="" getter=""> File path to the small icon for this web application. If not defined, defaults to the project icon. - [b]Note:[/b] If the icon is not 180x180, it will be automatically resized for the final build. + [b]Note:[/b] If the icon is not 180×180, it will be automatically resized for the final build. </member> <member name="progressive_web_app/icon_512x512" type="String" setter="" getter=""> - File path to the smallest icon for this web application. If not defined, defaults to the project icon. - [b]Note:[/b] If the icon is not 512x512, it will be automatically resized for the final build. + File path to the largest icon for this web application. If not defined, defaults to the project icon. + [b]Note:[/b] If the icon is not 512×512, it will be automatically resized for the final build. </member> <member name="progressive_web_app/offline_page" type="String" setter="" getter=""> The page to display, should the server hosting the page not be available. This page is saved in the client's machine. diff --git a/platform/web/emscripten_helpers.py b/platform/web/emscripten_helpers.py index 8fcabb21c7..3122271a71 100644 --- a/platform/web/emscripten_helpers.py +++ b/platform/web/emscripten_helpers.py @@ -3,6 +3,8 @@ import os from SCons.Util import WhereIs +from platform_methods import get_build_version + def run_closure_compiler(target, source, env, for_signature): closure_bin = os.path.join( @@ -21,22 +23,6 @@ def run_closure_compiler(target, source, env, for_signature): return " ".join(cmd) -def get_build_version(): - import version - - name = "custom_build" - if os.getenv("BUILD_NAME") is not None: - name = os.getenv("BUILD_NAME") - v = "%d.%d" % (version.major, version.minor) - if version.patch > 0: - v += ".%d" % version.patch - status = version.status - if os.getenv("GODOT_VERSION_STATUS") is not None: - status = str(os.getenv("GODOT_VERSION_STATUS")) - v += ".%s.%s" % (status, name) - return v - - def create_engine_file(env, target, source, externs, threads_enabled): if env["use_closure_compiler"]: return env.BuildJS(target, source, JSEXTERNS=externs) @@ -84,7 +70,7 @@ def create_template_zip(env, js, wasm, worker, side): cache.append("godot.editor.worker.js") opt_cache = ["godot.editor.wasm"] subst_dict = { - "___GODOT_VERSION___": get_build_version(), + "___GODOT_VERSION___": get_build_version(False), "___GODOT_NAME___": "GodotEngine", "___GODOT_CACHE___": json.dumps(cache), "___GODOT_OPT_CACHE___": json.dumps(opt_cache), diff --git a/platform/web/export/export_plugin.cpp b/platform/web/export/export_plugin.cpp index efe3c95496..a6835a28b2 100644 --- a/platform/web/export/export_plugin.cpp +++ b/platform/web/export/export_plugin.cpp @@ -169,6 +169,7 @@ void EditorExportPlatformWeb::_fix_html(Vector<uint8_t> &p_html, const Ref<Edito replaces["$GODOT_PROJECT_NAME"] = GLOBAL_GET("application/config/name"); replaces["$GODOT_HEAD_INCLUDE"] = head_include + custom_head_include; replaces["$GODOT_CONFIG"] = str_config; + replaces["$GODOT_SPLASH_COLOR"] = "#" + Color(GLOBAL_GET("application/boot_splash/bg_color")).to_html(false); replaces["$GODOT_SPLASH"] = p_name + ".png"; if (p_preset->get("variant/thread_support")) { diff --git a/platform/web/js/libs/library_godot_fetch.js b/platform/web/js/libs/library_godot_fetch.js index 00616bc1a5..eeb3978256 100644 --- a/platform/web/js/libs/library_godot_fetch.js +++ b/platform/web/js/libs/library_godot_fetch.js @@ -59,7 +59,12 @@ const GodotFetch = { }); obj.status = response.status; obj.response = response; - obj.reader = response.body.getReader(); + // `body` can be null per spec (for example, in cases where the request method is HEAD). + // As of the time of writing, Chromium (127.0.6533.72) does not follow the spec but Firefox (131.0.3) does. + // See godotengine/godot#76825 for more information. + // See Chromium revert (of the change to follow the spec): + // https://chromium.googlesource.com/chromium/src/+/135354b7bdb554cd03c913af7c90aceead03c4d4 + obj.reader = response.body?.getReader(); obj.chunked = chunked; }, @@ -121,6 +126,10 @@ const GodotFetch = { } obj.reading = true; obj.reader.read().then(GodotFetch.onread.bind(null, id)).catch(GodotFetch.onerror.bind(null, id)); + } else if (obj.reader == null && obj.response.body == null) { + // Emulate a stream closure to maintain the request lifecycle. + obj.reading = true; + GodotFetch.onread(id, { value: undefined, done: true }); } }, }, @@ -159,7 +168,10 @@ const GodotFetch = { if (!obj.response) { return 0; } - if (obj.reader) { + // If the reader is nullish, but there is no body, and the request is not marked as done, + // the same status should be returned as though the request is currently being read + // so that the proper lifecycle closure can be handled in `read()`. + if (obj.reader || (obj.response.body == null && !obj.done)) { return 1; } if (obj.done) { diff --git a/platform/web/js/libs/library_godot_input.js b/platform/web/js/libs/library_godot_input.js index 6e3b97023d..8134631f1b 100644 --- a/platform/web/js/libs/library_godot_input.js +++ b/platform/web/js/libs/library_godot_input.js @@ -38,41 +38,57 @@ const GodotIME = { $GodotIME: { ime: null, active: false, + focusTimerIntervalId: -1, getModifiers: function (evt) { return (evt.shiftKey + 0) + ((evt.altKey + 0) << 1) + ((evt.ctrlKey + 0) << 2) + ((evt.metaKey + 0) << 3); }, ime_active: function (active) { - function focus_timer() { - GodotIME.active = true; - GodotIME.ime.focus(); + function clearFocusTimerInterval() { + clearInterval(GodotIME.focusTimerIntervalId); + GodotIME.focusTimerIntervalId = -1; } - if (GodotIME.ime) { - if (active) { - GodotIME.ime.style.display = 'block'; - setInterval(focus_timer, 100); - } else { - GodotIME.ime.style.display = 'none'; - GodotConfig.canvas.focus(); - GodotIME.active = false; + function focusTimer() { + if (GodotIME.ime == null) { + clearFocusTimerInterval(); + return; } + GodotIME.ime.focus(); + } + + if (GodotIME.focusTimerIntervalId > -1) { + clearFocusTimerInterval(); + } + + if (GodotIME.ime == null) { + return; + } + + GodotIME.active = active; + if (active) { + GodotIME.ime.style.display = 'block'; + GodotIME.focusTimerIntervalId = setInterval(focusTimer, 100); + } else { + GodotIME.ime.style.display = 'none'; + GodotConfig.canvas.focus(); } }, ime_position: function (x, y) { - if (GodotIME.ime) { - const canvas = GodotConfig.canvas; - const rect = canvas.getBoundingClientRect(); - const rw = canvas.width / rect.width; - const rh = canvas.height / rect.height; - const clx = (x / rw) + rect.x; - const cly = (y / rh) + rect.y; - - GodotIME.ime.style.left = `${clx}px`; - GodotIME.ime.style.top = `${cly}px`; + if (GodotIME.ime == null) { + return; } + const canvas = GodotConfig.canvas; + const rect = canvas.getBoundingClientRect(); + const rw = canvas.width / rect.width; + const rh = canvas.height / rect.height; + const clx = (x / rw) + rect.x; + const cly = (y / rh) + rect.y; + + GodotIME.ime.style.left = `${clx}px`; + GodotIME.ime.style.top = `${cly}px`; }, init: function (ime_cb, key_cb, code, key) { @@ -84,20 +100,27 @@ const GodotIME = { evt.preventDefault(); } function ime_event_cb(event) { - if (GodotIME.ime) { - if (event.type === 'compositionstart') { - ime_cb(0, null); - GodotIME.ime.innerHTML = ''; - } else if (event.type === 'compositionupdate') { - const ptr = GodotRuntime.allocString(event.data); - ime_cb(1, ptr); - GodotRuntime.free(ptr); - } else if (event.type === 'compositionend') { - const ptr = GodotRuntime.allocString(event.data); - ime_cb(2, ptr); - GodotRuntime.free(ptr); - GodotIME.ime.innerHTML = ''; - } + if (GodotIME.ime == null) { + return; + } + switch (event.type) { + case 'compositionstart': + ime_cb(0, null); + GodotIME.ime.innerHTML = ''; + break; + case 'compositionupdate': { + const ptr = GodotRuntime.allocString(event.data); + ime_cb(1, ptr); + GodotRuntime.free(ptr); + } break; + case 'compositionend': { + const ptr = GodotRuntime.allocString(event.data); + ime_cb(2, ptr); + GodotRuntime.free(ptr); + GodotIME.ime.innerHTML = ''; + } break; + default: + // Do nothing. } } @@ -133,10 +156,15 @@ const GodotIME = { }, clear: function () { - if (GodotIME.ime) { - GodotIME.ime.remove(); - GodotIME.ime = null; + if (GodotIME.ime == null) { + return; + } + if (GodotIME.focusTimerIntervalId > -1) { + clearInterval(GodotIME.focusTimerIntervalId); + GodotIME.focusTimerIntervalId = -1; } + GodotIME.ime.remove(); + GodotIME.ime = null; }, }, }; |