summaryrefslogtreecommitdiffstats
path: root/platform/web/display_server_web.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/web/display_server_web.cpp')
-rw-r--r--platform/web/display_server_web.cpp258
1 files changed, 211 insertions, 47 deletions
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index aac1401f23..022e044185 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -35,6 +35,7 @@
#include "os_web.h"
#include "core/config/project_settings.h"
+#include "core/object/callable_method_pointer.h"
#include "scene/resources/atlas_texture.h"
#include "servers/rendering/dummy/rasterizer_dummy.h"
@@ -59,16 +60,26 @@ DisplayServerWeb *DisplayServerWeb::get_singleton() {
bool DisplayServerWeb::check_size_force_redraw() {
bool size_changed = godot_js_display_size_update() != 0;
if (size_changed && !rect_changed_callback.is_null()) {
- Variant size = Rect2i(Point2i(), window_get_size()); // TODO use window_get_position if implemented.
- Variant *vp = &size;
- Variant ret;
- Callable::CallError ce;
- rect_changed_callback.callp((const Variant **)&vp, 1, ret, ce);
+ Size2i window_size = window_get_size();
+ Variant size = Rect2i(Point2i(), window_size); // TODO use window_get_position if implemented.
+ rect_changed_callback.call(size);
+ emscripten_set_canvas_element_size(canvas_id, window_size.x, window_size.y);
}
return size_changed;
}
void DisplayServerWeb::fullscreen_change_callback(int p_fullscreen) {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_fullscreen_change_callback).bind(p_fullscreen).call_deferred();
+ return;
+ }
+#endif
+
+ _fullscreen_change_callback(p_fullscreen);
+}
+
+void DisplayServerWeb::_fullscreen_change_callback(int p_fullscreen) {
DisplayServerWeb *display = get_singleton();
if (p_fullscreen) {
display->window_mode = WINDOW_MODE_FULLSCREEN;
@@ -78,7 +89,23 @@ void DisplayServerWeb::fullscreen_change_callback(int p_fullscreen) {
}
// Drag and drop callback.
-void DisplayServerWeb::drop_files_js_callback(char **p_filev, int p_filec) {
+void DisplayServerWeb::drop_files_js_callback(const char **p_filev, int p_filec) {
+ Vector<String> files;
+ for (int i = 0; i < p_filec; i++) {
+ files.push_back(String::utf8(p_filev[i]));
+ }
+
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_drop_files_js_callback).bind(files).call_deferred();
+ return;
+ }
+#endif
+
+ _drop_files_js_callback(files);
+}
+
+void DisplayServerWeb::_drop_files_js_callback(const Vector<String> &p_files) {
DisplayServerWeb *ds = get_singleton();
if (!ds) {
ERR_FAIL_MSG("Unable to drop files because the DisplayServer is not active");
@@ -86,26 +113,26 @@ void DisplayServerWeb::drop_files_js_callback(char **p_filev, int p_filec) {
if (ds->drop_files_callback.is_null()) {
return;
}
- Vector<String> files;
- for (int i = 0; i < p_filec; i++) {
- files.push_back(String::utf8(p_filev[i]));
- }
- Variant v = files;
- Variant *vp = &v;
- Variant ret;
- Callable::CallError ce;
- ds->drop_files_callback.callp((const Variant **)&vp, 1, ret, ce);
+ ds->drop_files_callback.call(p_files);
}
// Web quit request callback.
void DisplayServerWeb::request_quit_callback() {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_request_quit_callback).call_deferred();
+ return;
+ }
+#endif
+
+ _request_quit_callback();
+}
+
+void DisplayServerWeb::_request_quit_callback() {
DisplayServerWeb *ds = get_singleton();
if (ds && !ds->window_event_callback.is_null()) {
Variant event = int(DisplayServer::WINDOW_EVENT_CLOSE_REQUEST);
- Variant *eventp = &event;
- Variant ret;
- Callable::CallError ce;
- ds->window_event_callback.callp((const Variant **)&eventp, 1, ret, ce);
+ ds->window_event_callback.call(event);
}
}
@@ -129,17 +156,32 @@ void DisplayServerWeb::dom2godot_mod(Ref<InputEventWithModifiers> ev, int p_mod,
void DisplayServerWeb::key_callback(int p_pressed, int p_repeat, int p_modifiers) {
DisplayServerWeb *ds = get_singleton();
JSKeyEvent &key_event = ds->key_event;
+
+ const String code = String::utf8(key_event.code);
+ const String key = String::utf8(key_event.key);
+
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_key_callback).bind(code, key, p_pressed, p_repeat, p_modifiers).call_deferred();
+ return;
+ }
+#endif
+
+ _key_callback(code, key, p_pressed, p_repeat, p_modifiers);
+}
+
+void DisplayServerWeb::_key_callback(const String &p_key_event_code, const String &p_key_event_key, int p_pressed, int p_repeat, int p_modifiers) {
// Resume audio context after input in case autoplay was denied.
OS_Web::get_singleton()->resume_audio();
char32_t c = 0x00;
- String unicode = String::utf8(key_event.key);
+ String unicode = p_key_event_key;
if (unicode.length() == 1) {
c = unicode[0];
}
- Key keycode = dom_code2godot_scancode(key_event.code, key_event.key, false);
- Key scancode = dom_code2godot_scancode(key_event.code, key_event.key, true);
+ Key keycode = dom_code2godot_scancode(p_key_event_code.utf8().get_data(), p_key_event_key.utf8().get_data(), false);
+ Key scancode = dom_code2godot_scancode(p_key_event_code.utf8().get_data(), p_key_event_key.utf8().get_data(), true);
Ref<InputEventKey> ev;
ev.instantiate();
@@ -160,6 +202,17 @@ void DisplayServerWeb::key_callback(int p_pressed, int p_repeat, int p_modifiers
// Mouse
int DisplayServerWeb::mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers) {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_mouse_button_callback).bind(p_pressed, p_button, p_x, p_y, p_modifiers).call_deferred();
+ return true;
+ }
+#endif
+
+ return _mouse_button_callback(p_pressed, p_button, p_x, p_y, p_modifiers);
+}
+
+int DisplayServerWeb::_mouse_button_callback(int p_pressed, int p_button, double p_x, double p_y, int p_modifiers) {
DisplayServerWeb *ds = get_singleton();
Point2 pos(p_x, p_y);
@@ -236,6 +289,17 @@ int DisplayServerWeb::mouse_button_callback(int p_pressed, int p_button, double
}
void DisplayServerWeb::mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers) {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_mouse_move_callback).bind(p_x, p_y, p_rel_x, p_rel_y, p_modifiers).call_deferred();
+ return;
+ }
+#endif
+
+ _mouse_move_callback(p_x, p_y, p_rel_x, p_rel_y, p_modifiers);
+}
+
+void DisplayServerWeb::_mouse_move_callback(double p_x, double p_y, double p_rel_x, double p_rel_y, int p_modifiers) {
BitField<MouseButtonMask> input_mask = Input::get_singleton()->get_mouse_button_mask();
// For motion outside the canvas, only read mouse movement if dragging
// started inside the canvas; imitating desktop app behavior.
@@ -311,9 +375,25 @@ bool DisplayServerWeb::tts_is_paused() const {
}
void DisplayServerWeb::update_voices_callback(int p_size, const char **p_voice) {
- get_singleton()->voices.clear();
+ Vector<String> voices;
for (int i = 0; i < p_size; i++) {
- Vector<String> tokens = String::utf8(p_voice[i]).split(";", true, 2);
+ voices.append(String::utf8(p_voice[i]));
+ }
+
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_update_voices_callback).bind(voices).call_deferred();
+ return;
+ }
+#endif
+
+ _update_voices_callback(voices);
+}
+
+void DisplayServerWeb::_update_voices_callback(const Vector<String> &p_voices) {
+ get_singleton()->voices.clear();
+ for (int i = 0; i < p_voices.size(); i++) {
+ Vector<String> tokens = p_voices[i].split(";", true, 2);
if (tokens.size() == 2) {
Dictionary voice_d;
voice_d["name"] = tokens[1];
@@ -344,7 +424,7 @@ void DisplayServerWeb::tts_speak(const String &p_text, const String &p_voice, in
CharString string = p_text.utf8();
utterance_ids[p_utterance_id] = string;
- godot_js_tts_speak(string.get_data(), p_voice.utf8().get_data(), CLAMP(p_volume, 0, 100), CLAMP(p_pitch, 0.f, 2.f), CLAMP(p_rate, 0.1f, 10.f), p_utterance_id, DisplayServerWeb::_js_utterance_callback);
+ godot_js_tts_speak(string.get_data(), p_voice.utf8().get_data(), CLAMP(p_volume, 0, 100), CLAMP(p_pitch, 0.f, 2.f), CLAMP(p_rate, 0.1f, 10.f), p_utterance_id, DisplayServerWeb::js_utterance_callback);
}
void DisplayServerWeb::tts_pause() {
@@ -366,6 +446,17 @@ void DisplayServerWeb::tts_stop() {
godot_js_tts_stop();
}
+void DisplayServerWeb::js_utterance_callback(int p_event, int p_id, int p_pos) {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_js_utterance_callback).bind(p_event, p_id, p_pos).call_deferred();
+ return;
+ }
+#endif
+
+ _js_utterance_callback(p_event, p_id, p_pos);
+}
+
void DisplayServerWeb::_js_utterance_callback(int p_event, int p_id, int p_pos) {
DisplayServerWeb *ds = (DisplayServerWeb *)DisplayServer::get_singleton();
if (ds->utterance_ids.has(p_id)) {
@@ -517,6 +608,17 @@ Point2i DisplayServerWeb::mouse_get_position() const {
// Wheel
int DisplayServerWeb::mouse_wheel_callback(double p_delta_x, double p_delta_y) {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_mouse_wheel_callback).bind(p_delta_x, p_delta_y).call_deferred();
+ return true;
+ }
+#endif
+
+ return _mouse_wheel_callback(p_delta_x, p_delta_y);
+}
+
+int DisplayServerWeb::_mouse_wheel_callback(double p_delta_x, double p_delta_y) {
if (!godot_js_display_canvas_is_focused()) {
if (get_singleton()->cursor_inside_canvas) {
godot_js_display_canvas_focus();
@@ -569,6 +671,17 @@ int DisplayServerWeb::mouse_wheel_callback(double p_delta_x, double p_delta_y) {
// Touch
void DisplayServerWeb::touch_callback(int p_type, int p_count) {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_touch_callback).bind(p_type, p_count).call_deferred();
+ return;
+ }
+#endif
+
+ _touch_callback(p_type, p_count);
+}
+
+void DisplayServerWeb::_touch_callback(int p_type, int p_count) {
DisplayServerWeb *ds = get_singleton();
const JSTouchEvent &touch_event = ds->touch_event;
@@ -613,16 +726,25 @@ bool DisplayServerWeb::is_touchscreen_available() const {
// Virtual Keyboard
void DisplayServerWeb::vk_input_text_callback(const char *p_text, int p_cursor) {
+ String text = p_text;
+
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_vk_input_text_callback).bind(text, p_cursor).call_deferred();
+ return;
+ }
+#endif
+
+ _vk_input_text_callback(text, p_cursor);
+}
+
+void DisplayServerWeb::_vk_input_text_callback(const String &p_text, int p_cursor) {
DisplayServerWeb *ds = DisplayServerWeb::get_singleton();
if (!ds || ds->input_text_callback.is_null()) {
return;
}
// Call input_text
- Variant event = String::utf8(p_text);
- Variant *eventp = &event;
- Variant ret;
- Callable::CallError ce;
- ds->input_text_callback.callp((const Variant **)&eventp, 1, ret, ce);
+ ds->input_text_callback.call(p_text);
// Insert key right to reach position.
Input *input = Input::get_singleton();
Ref<InputEventKey> k;
@@ -649,14 +771,39 @@ void DisplayServerWeb::virtual_keyboard_hide() {
}
void DisplayServerWeb::window_blur_callback() {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_window_blur_callback).call_deferred();
+ return;
+ }
+#endif
+
+ _window_blur_callback();
+}
+
+void DisplayServerWeb::_window_blur_callback() {
Input::get_singleton()->release_pressed_events();
}
// Gamepad
void DisplayServerWeb::gamepad_callback(int p_index, int p_connected, const char *p_id, const char *p_guid) {
+ String id = p_id;
+ String guid = p_guid;
+
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_gamepad_callback).bind(p_index, p_connected, id, guid).call_deferred();
+ return;
+ }
+#endif
+
+ _gamepad_callback(p_index, p_connected, id, guid);
+}
+
+void DisplayServerWeb::_gamepad_callback(int p_index, int p_connected, const String &p_id, const String &p_guid) {
Input *input = Input::get_singleton();
if (p_connected) {
- input->joy_connection_changed(p_index, true, String::utf8(p_id), String::utf8(p_guid));
+ input->joy_connection_changed(p_index, true, p_id, p_guid);
} else {
input->joy_connection_changed(p_index, false, "");
}
@@ -700,7 +847,20 @@ Vector<String> DisplayServerWeb::get_rendering_drivers_func() {
// Clipboard
void DisplayServerWeb::update_clipboard_callback(const char *p_text) {
- get_singleton()->clipboard = String::utf8(p_text);
+ String text = p_text;
+
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_update_clipboard_callback).bind(text).call_deferred();
+ return;
+ }
+#endif
+
+ _update_clipboard_callback(text);
+}
+
+void DisplayServerWeb::_update_clipboard_callback(const String &p_text) {
+ get_singleton()->clipboard = p_text;
}
void DisplayServerWeb::clipboard_set(const String &p_text) {
@@ -715,6 +875,17 @@ String DisplayServerWeb::clipboard_get() const {
}
void DisplayServerWeb::send_window_event_callback(int p_notification) {
+#ifdef PROXY_TO_PTHREAD_ENABLED
+ if (!Thread::is_main_thread()) {
+ callable_mp_static(DisplayServerWeb::_send_window_event_callback).bind(p_notification).call_deferred();
+ return;
+ }
+#endif
+
+ _send_window_event_callback(p_notification);
+}
+
+void DisplayServerWeb::_send_window_event_callback(int p_notification) {
DisplayServerWeb *ds = get_singleton();
if (!ds) {
return;
@@ -724,10 +895,7 @@ void DisplayServerWeb::send_window_event_callback(int p_notification) {
}
if (!ds->window_event_callback.is_null()) {
Variant event = int(p_notification);
- Variant *eventp = &event;
- Variant ret;
- Callable::CallError ce;
- ds->window_event_callback.callp((const Variant **)&eventp, 1, ret, ce);
+ ds->window_event_callback.call(event);
}
}
@@ -770,12 +938,8 @@ void DisplayServerWeb::set_icon(const Ref<Image> &p_icon) {
void DisplayServerWeb::_dispatch_input_event(const Ref<InputEvent> &p_event) {
Callable cb = get_singleton()->input_event_callback;
- if (!cb.is_null()) {
- Variant ev = p_event;
- Variant *evp = &ev;
- Variant ret;
- Callable::CallError ce;
- cb.callp((const Variant **)&evp, 1, ret, ce);
+ if (cb.is_valid()) {
+ cb.call(p_event);
}
}
@@ -836,19 +1000,19 @@ DisplayServerWeb::DisplayServerWeb(const String &p_rendering_driver, WindowMode
godot_js_input_mouse_wheel_cb(&DisplayServerWeb::mouse_wheel_callback);
godot_js_input_touch_cb(&DisplayServerWeb::touch_callback, touch_event.identifier, touch_event.coords);
godot_js_input_key_cb(&DisplayServerWeb::key_callback, key_event.code, key_event.key);
- godot_js_input_paste_cb(update_clipboard_callback);
- godot_js_input_drop_files_cb(drop_files_js_callback);
+ godot_js_input_paste_cb(&DisplayServerWeb::update_clipboard_callback);
+ godot_js_input_drop_files_cb(&DisplayServerWeb::drop_files_js_callback);
godot_js_input_gamepad_cb(&DisplayServerWeb::gamepad_callback);
// JS Display interface (js/libs/library_godot_display.js)
godot_js_display_fullscreen_cb(&DisplayServerWeb::fullscreen_change_callback);
- godot_js_display_window_blur_cb(&window_blur_callback);
- godot_js_display_notification_cb(&send_window_event_callback,
+ godot_js_display_window_blur_cb(&DisplayServerWeb::window_blur_callback);
+ godot_js_display_notification_cb(&DisplayServerWeb::send_window_event_callback,
WINDOW_EVENT_MOUSE_ENTER,
WINDOW_EVENT_MOUSE_EXIT,
WINDOW_EVENT_FOCUS_IN,
WINDOW_EVENT_FOCUS_OUT);
- godot_js_display_vk_cb(&vk_input_text_callback);
+ godot_js_display_vk_cb(&DisplayServerWeb::vk_input_text_callback);
Input::get_singleton()->set_event_dispatch_function(_dispatch_input_event);
}