浏览代码

Refactor canvas ID and locale handling.

Fabio Alessandrelli 5 年之前
父节点
当前提交
fd92270b0a

+ 23 - 45
platform/javascript/display_server_javascript.cpp

@@ -44,17 +44,13 @@
 #define DOM_BUTTON_XBUTTON1 3
 #define DOM_BUTTON_XBUTTON2 4
 
+char DisplayServerJavaScript::canvas_id[256] = { 0 };
+
 DisplayServerJavaScript *DisplayServerJavaScript::get_singleton() {
 	return static_cast<DisplayServerJavaScript *>(DisplayServer::get_singleton());
 }
 
 // Window (canvas)
-extern "C" EMSCRIPTEN_KEEPALIVE void _set_canvas_id(uint8_t *p_data, int p_data_size) {
-	DisplayServerJavaScript *display = DisplayServerJavaScript::get_singleton();
-	display->canvas_id.parse_utf8((const char *)p_data, p_data_size);
-	display->canvas_id = "#" + display->canvas_id;
-}
-
 static void focus_canvas() {
 	/* clang-format off */
 	EM_ASM(
@@ -71,8 +67,7 @@ static bool is_canvas_focused() {
 	/* clang-format on */
 }
 
-static Point2 compute_position_in_canvas(int x, int y) {
-	DisplayServerJavaScript *display = DisplayServerJavaScript::get_singleton();
+Point2 DisplayServerJavaScript::compute_position_in_canvas(int p_x, int p_y) {
 	int canvas_x = EM_ASM_INT({
 		return Module['canvas'].getBoundingClientRect().x;
 	});
@@ -81,14 +76,14 @@ static Point2 compute_position_in_canvas(int x, int y) {
 	});
 	int canvas_width;
 	int canvas_height;
-	emscripten_get_canvas_element_size(display->canvas_id.utf8().get_data(), &canvas_width, &canvas_height);
+	emscripten_get_canvas_element_size(canvas_id, &canvas_width, &canvas_height);
 
 	double element_width;
 	double element_height;
-	emscripten_get_element_css_size(display->canvas_id.utf8().get_data(), &element_width, &element_height);
+	emscripten_get_element_css_size(canvas_id, &element_width, &element_height);
 
-	return Point2((int)(canvas_width / element_width * (x - canvas_x)),
-			(int)(canvas_height / element_height * (y - canvas_y)));
+	return Point2((int)(canvas_width / element_width * (p_x - canvas_x)),
+			(int)(canvas_height / element_height * (p_y - canvas_y)));
 }
 
 static bool cursor_inside_canvas = true;
@@ -97,7 +92,8 @@ EM_BOOL DisplayServerJavaScript::fullscreen_change_callback(int p_event_type, co
 	DisplayServerJavaScript *display = get_singleton();
 	// Empty ID is canvas.
 	String target_id = String::utf8(p_event->id);
-	if (target_id.empty() || "#" + target_id == display->canvas_id) {
+	String canvas_str_id = String::utf8(canvas_id);
+	if (target_id.empty() || target_id == canvas_str_id) {
 		// This event property is the only reliable data on
 		// browser fullscreen state.
 		if (p_event->isFullscreen) {
@@ -820,23 +816,6 @@ DisplayServer *DisplayServerJavaScript::create_func(const String &p_rendering_dr
 }
 
 DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
-	/* clang-format off */
-	EM_ASM({
-		const canvas = Module['canvas'];
-		var enc = new TextEncoder("utf-8");
-		var buffer = new Uint8Array(enc.encode(canvas.id));
-		var len = buffer.byteLength;
-		var out = _malloc(len);
-		HEAPU8.set(buffer, out);
-		ccall("_set_canvas_id",
-			"void",
-			["number", "number"],
-			[out, len]
-		);
-		_free(out);
-	});
-	/* clang-format on */
-
 	RasterizerDummy::make_current(); // TODO GLES2 in Godot 4.0... or webgpu?
 #if 0
 	EmscriptenWebGLContextAttributes attributes;
@@ -859,7 +838,7 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
 		gl_initialization_error = true;
 	}
 
-	EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(canvas_id.utf8().get_data(), &attributes);
+	EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(canvas_id, &attributes);
 	if (emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS) {
 		gl_initialization_error = true;
 	}
@@ -881,7 +860,6 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
 	}
 
 	EMSCRIPTEN_RESULT result;
-	CharString id = canvas_id.utf8();
 #define EM_CHECK(ev)                         \
 	if (result != EMSCRIPTEN_RESULT_SUCCESS) \
 		ERR_PRINT("Error while setting " #ev " callback: Code " + itos(result));
@@ -895,16 +873,16 @@ DisplayServerJavaScript::DisplayServerJavaScript(const String &p_rendering_drive
 	// JavaScript APIs. For APIs that are not (sufficiently) exposed, EM_ASM
 	// is used below.
 	SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mousemove, mousemove_callback)
-	SET_EM_CALLBACK(id.get_data(), mousedown, mouse_button_callback)
+	SET_EM_CALLBACK(canvas_id, mousedown, mouse_button_callback)
 	SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mouseup, mouse_button_callback)
-	SET_EM_CALLBACK(id.get_data(), wheel, wheel_callback)
-	SET_EM_CALLBACK(id.get_data(), touchstart, touch_press_callback)
-	SET_EM_CALLBACK(id.get_data(), touchmove, touchmove_callback)
-	SET_EM_CALLBACK(id.get_data(), touchend, touch_press_callback)
-	SET_EM_CALLBACK(id.get_data(), touchcancel, touch_press_callback)
-	SET_EM_CALLBACK(id.get_data(), keydown, keydown_callback)
-	SET_EM_CALLBACK(id.get_data(), keypress, keypress_callback)
-	SET_EM_CALLBACK(id.get_data(), keyup, keyup_callback)
+	SET_EM_CALLBACK(canvas_id, wheel, wheel_callback)
+	SET_EM_CALLBACK(canvas_id, touchstart, touch_press_callback)
+	SET_EM_CALLBACK(canvas_id, touchmove, touchmove_callback)
+	SET_EM_CALLBACK(canvas_id, touchend, touch_press_callback)
+	SET_EM_CALLBACK(canvas_id, touchcancel, touch_press_callback)
+	SET_EM_CALLBACK(canvas_id, keydown, keydown_callback)
+	SET_EM_CALLBACK(canvas_id, keypress, keypress_callback)
+	SET_EM_CALLBACK(canvas_id, keyup, keyup_callback)
 	SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, fullscreenchange, fullscreen_change_callback)
 	SET_EM_CALLBACK_NOTARGET(gamepadconnected, gamepad_change_callback)
 	SET_EM_CALLBACK_NOTARGET(gamepaddisconnected, gamepad_change_callback)
@@ -1012,7 +990,7 @@ Size2i DisplayServerJavaScript::screen_get_size(int p_screen) const {
 
 Rect2i DisplayServerJavaScript::screen_get_usable_rect(int p_screen) const {
 	int canvas[2];
-	emscripten_get_canvas_element_size(canvas_id.utf8().get_data(), canvas, canvas + 1);
+	emscripten_get_canvas_element_size(canvas_id, canvas, canvas + 1);
 	return Rect2i(0, 0, canvas[0], canvas[1]);
 }
 
@@ -1103,12 +1081,12 @@ Size2i DisplayServerJavaScript::window_get_min_size(WindowID p_window) const {
 }
 
 void DisplayServerJavaScript::window_set_size(const Size2i p_size, WindowID p_window) {
-	emscripten_set_canvas_element_size(canvas_id.utf8().get_data(), p_size.x, p_size.y);
+	emscripten_set_canvas_element_size(canvas_id, p_size.x, p_size.y);
 }
 
 Size2i DisplayServerJavaScript::window_get_size(WindowID p_window) const {
 	int canvas[2];
-	emscripten_get_canvas_element_size(canvas_id.utf8().get_data(), canvas, canvas + 1);
+	emscripten_get_canvas_element_size(canvas_id, canvas, canvas + 1);
 	return Size2(canvas[0], canvas[1]);
 }
 
@@ -1134,7 +1112,7 @@ void DisplayServerJavaScript::window_set_mode(WindowMode p_mode, WindowID p_wind
 			strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
 			strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
 			strategy.canvasResizedCallback = nullptr;
-			EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(canvas_id.utf8().get_data(), false, &strategy);
+			EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(canvas_id, false, &strategy);
 			ERR_FAIL_COND_MSG(result == EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED, "Enabling fullscreen is only possible from an input callback for the HTML5 platform.");
 			ERR_FAIL_COND_MSG(result != EMSCRIPTEN_RESULT_SUCCESS, "Enabling fullscreen is only possible from an input callback for the HTML5 platform.");
 		} break;

+ 2 - 1
platform/javascript/display_server_javascript.h

@@ -53,6 +53,7 @@ class DisplayServerJavaScript : public DisplayServer {
 	double last_click_ms = 0;
 	int last_click_button_index = -1;
 
+	static Point2 compute_position_in_canvas(int p_x, int p_y);
 	static EM_BOOL fullscreen_change_callback(int p_event_type, const EmscriptenFullscreenChangeEvent *p_event, void *p_user_data);
 
 	static EM_BOOL keydown_callback(int p_event_type, const EmscriptenKeyboardEvent *p_event, void *p_user_data);
@@ -81,11 +82,11 @@ protected:
 public:
 	// Override return type to make writing static callbacks less tedious.
 	static DisplayServerJavaScript *get_singleton();
+	static char canvas_id[256];
 
 	WindowMode window_mode = WINDOW_MODE_WINDOWED;
 
 	String clipboard;
-	String canvas_id;
 
 	Callable window_event_callback;
 	Callable input_event_callback;

+ 20 - 2
platform/javascript/javascript_main.cpp

@@ -30,7 +30,8 @@
 
 #include "core/io/resource_loader.h"
 #include "main/main.h"
-#include "os_javascript.h"
+#include "platform/javascript/display_server_javascript.h"
+#include "platform/javascript/os_javascript.h"
 
 #include <emscripten/emscripten.h>
 
@@ -79,10 +80,10 @@ extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) {
 	ResourceLoader::set_abort_on_missing_resources(false);
 	Main::start();
 	os->get_main_loop()->init();
-	emscripten_resume_main_loop();
 	// Immediately run the first iteration.
 	// We are inside an animation frame, we want to immediately draw on the newly setup canvas.
 	main_loop_callback();
+	emscripten_resume_main_loop();
 }
 
 int main(int argc, char *argv[]) {
@@ -91,6 +92,23 @@ int main(int argc, char *argv[]) {
 		FS.mkdir('/userfs');
 		FS.mount(IDBFS, {}, '/userfs');
 	});
+
+	// Configure locale.
+	char locale_ptr[16];
+	/* clang-format off */
+	EM_ASM({
+		stringToUTF8(Module['locale'], $0, 16);
+	}, locale_ptr);
+	/* clang-format on */
+	setenv("LANG", locale_ptr, true);
+
+	// Ensure the canvas ID.
+	/* clang-format off */
+	EM_ASM({
+		stringToUTF8("#" + Module['canvas'].id, $0, 255);
+	}, DisplayServerJavaScript::canvas_id);
+	/* clang-format on */
+
 	os = new OS_JavaScript();
 	Main::setup(argv[0], argc - 1, &argv[1], false);
 	emscripten_set_main_loop(main_loop_callback, -1, false);

+ 0 - 8
platform/javascript/os_javascript.cpp

@@ -74,14 +74,6 @@ void OS_JavaScript::initialize() {
 	EngineDebugger::register_uri_handler("ws://", RemoteDebuggerPeerWebSocket::create);
 	EngineDebugger::register_uri_handler("wss://", RemoteDebuggerPeerWebSocket::create);
 #endif
-
-	char locale_ptr[16];
-	/* clang-format off */
-	EM_ASM({
-		stringToUTF8(Module['locale'], $0, 16);
-	}, locale_ptr);
-	/* clang-format on */
-	setenv("LANG", locale_ptr, true);
 }
 
 void OS_JavaScript::resume_audio() {