summaryrefslogtreecommitdiffstats
path: root/platform/web
diff options
context:
space:
mode:
Diffstat (limited to 'platform/web')
-rw-r--r--platform/web/detect.py8
-rw-r--r--platform/web/display_server_web.cpp1
-rw-r--r--platform/web/display_server_web.h2
-rw-r--r--platform/web/doc_classes/EditorExportPlatformWeb.xml8
-rw-r--r--platform/web/emscripten_helpers.py20
-rw-r--r--platform/web/export/export_plugin.cpp1
-rw-r--r--platform/web/js/libs/library_godot_fetch.js16
-rw-r--r--platform/web/js/libs/library_godot_input.js104
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;
},
},
};