1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-08 12:40:44 +00:00

HTML5 callbacks rework.

Fixes compatibility with emscripten 1.39.5+ .
Most input callbacks now require a target and no longer support NULL
defaults.

This commit changes all required null targets to the expected default in
the binding phase.
Since for canvas-related callbacks there is no default, the "#canvas"
selector is used instead.
Additionally, since canvasX and canvasY event properties are no longer
supported, event positions are computed from "clientX" and "clientY" and
the "#canvas" bounding client rect.
This commit is contained in:
Fabio Alessandrelli
2020-01-17 21:25:14 +01:00
parent a6f3e1345c
commit 4a50f5ff65

View File

@@ -49,6 +49,7 @@
#define DOM_BUTTON_RIGHT 2 #define DOM_BUTTON_RIGHT 2
#define DOM_BUTTON_XBUTTON1 3 #define DOM_BUTTON_XBUTTON1 3
#define DOM_BUTTON_XBUTTON2 4 #define DOM_BUTTON_XBUTTON2 4
#define GODOT_CANVAS_SELECTOR "#canvas"
// Window (canvas) // Window (canvas)
@@ -70,18 +71,23 @@ static bool is_canvas_focused() {
/* clang-format on */ /* clang-format on */
} }
static Point2 correct_canvas_position(int x, int y) { static Point2 compute_position_in_canvas(int x, int y) {
int canvas_x = EM_ASM_INT({
return document.getElementById('canvas').getBoundingClientRect().x;
});
int canvas_y = EM_ASM_INT({
return document.getElementById('canvas').getBoundingClientRect().y;
});
int canvas_width; int canvas_width;
int canvas_height; int canvas_height;
emscripten_get_canvas_element_size(NULL, &canvas_width, &canvas_height); emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, &canvas_width, &canvas_height);
double element_width; double element_width;
double element_height; double element_height;
emscripten_get_element_css_size(NULL, &element_width, &element_height); emscripten_get_element_css_size(GODOT_CANVAS_SELECTOR, &element_width, &element_height);
x = (int)(canvas_width / element_width * x); return Point2((int)(canvas_width / element_width * (x - canvas_x)),
y = (int)(canvas_height / element_height * y); (int)(canvas_height / element_height * (y - canvas_y)));
return Point2(x, y);
} }
static bool cursor_inside_canvas = true; static bool cursor_inside_canvas = true;
@@ -135,14 +141,14 @@ void OS_JavaScript::set_window_size(const Size2 p_size) {
emscripten_exit_soft_fullscreen(); emscripten_exit_soft_fullscreen();
window_maximized = false; window_maximized = false;
} }
emscripten_set_canvas_element_size(NULL, p_size.x, p_size.y); emscripten_set_canvas_element_size(GODOT_CANVAS_SELECTOR, p_size.x, p_size.y);
} }
} }
Size2 OS_JavaScript::get_window_size() const { Size2 OS_JavaScript::get_window_size() const {
int canvas[2]; int canvas[2];
emscripten_get_canvas_element_size(NULL, canvas, canvas + 1); emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, canvas, canvas + 1);
return Size2(canvas[0], canvas[1]); return Size2(canvas[0], canvas[1]);
} }
@@ -162,7 +168,7 @@ void OS_JavaScript::set_window_maximized(bool p_enabled) {
strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
strategy.canvasResizedCallback = NULL; strategy.canvasResizedCallback = NULL;
emscripten_enter_soft_fullscreen(NULL, &strategy); emscripten_enter_soft_fullscreen(GODOT_CANVAS_SELECTOR, &strategy);
window_maximized = p_enabled; window_maximized = p_enabled;
} }
} }
@@ -191,7 +197,7 @@ void OS_JavaScript::set_window_fullscreen(bool p_enabled) {
strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
strategy.canvasResizedCallback = NULL; strategy.canvasResizedCallback = NULL;
EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(NULL, false, &strategy); EMSCRIPTEN_RESULT result = emscripten_request_fullscreen_strategy(GODOT_CANVAS_SELECTOR, 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_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."); ERR_FAIL_COND_MSG(result != EMSCRIPTEN_RESULT_SUCCESS, "Enabling fullscreen is only possible from an input callback for the HTML5 platform.");
// Not fullscreen yet, so prevent "windowed" canvas dimensions from // Not fullscreen yet, so prevent "windowed" canvas dimensions from
@@ -298,7 +304,7 @@ EM_BOOL OS_JavaScript::mouse_button_callback(int p_event_type, const EmscriptenM
Ref<InputEventMouseButton> ev; Ref<InputEventMouseButton> ev;
ev.instance(); ev.instance();
ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_MOUSEDOWN); ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_MOUSEDOWN);
ev->set_position(correct_canvas_position(p_event->canvasX, p_event->canvasY)); ev->set_position(compute_position_in_canvas(p_event->clientX, p_event->clientY));
ev->set_global_position(ev->get_position()); ev->set_global_position(ev->get_position());
dom2godot_mod(p_event, ev); dom2godot_mod(p_event, ev);
@@ -363,7 +369,7 @@ EM_BOOL OS_JavaScript::mousemove_callback(int p_event_type, const EmscriptenMous
OS_JavaScript *os = get_singleton(); OS_JavaScript *os = get_singleton();
int input_mask = os->input->get_mouse_button_mask(); int input_mask = os->input->get_mouse_button_mask();
Point2 pos = correct_canvas_position(p_event->canvasX, p_event->canvasY); Point2 pos = compute_position_in_canvas(p_event->clientX, p_event->clientY);
// For motion outside the canvas, only read mouse movement if dragging // For motion outside the canvas, only read mouse movement if dragging
// started inside the canvas; imitating desktop app behaviour. // started inside the canvas; imitating desktop app behaviour.
if (!cursor_inside_canvas && !input_mask) if (!cursor_inside_canvas && !input_mask)
@@ -697,7 +703,7 @@ EM_BOOL OS_JavaScript::touch_press_callback(int p_event_type, const EmscriptenTo
if (!touch.isChanged) if (!touch.isChanged)
continue; continue;
ev->set_index(touch.identifier); ev->set_index(touch.identifier);
ev->set_position(correct_canvas_position(touch.canvasX, touch.canvasY)); ev->set_position(compute_position_in_canvas(touch.clientX, touch.clientY));
os->touches[i] = ev->get_position(); os->touches[i] = ev->get_position();
ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_TOUCHSTART); ev->set_pressed(p_event_type == EMSCRIPTEN_EVENT_TOUCHSTART);
@@ -722,7 +728,7 @@ EM_BOOL OS_JavaScript::touchmove_callback(int p_event_type, const EmscriptenTouc
if (!touch.isChanged) if (!touch.isChanged)
continue; continue;
ev->set_index(touch.identifier); ev->set_index(touch.identifier);
ev->set_position(correct_canvas_position(touch.canvasX, touch.canvasY)); ev->set_position(compute_position_in_canvas(touch.clientX, touch.clientY));
Point2 &prev = os->touches[i]; Point2 &prev = os->touches[i];
ev->set_relative(ev->get_position() - prev); ev->set_relative(ev->get_position() - prev);
prev = ev->get_position(); prev = ev->get_position();
@@ -921,7 +927,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver,
} }
} }
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(NULL, &attributes); EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(GODOT_CANVAS_SELECTOR, &attributes);
if (emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS) { if (emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS) {
gl_initialization_error = true; gl_initialization_error = true;
} }
@@ -984,21 +990,21 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver,
// These callbacks from Emscripten's html5.h suffice to access most // These callbacks from Emscripten's html5.h suffice to access most
// JavaScript APIs. For APIs that are not (sufficiently) exposed, EM_ASM // JavaScript APIs. For APIs that are not (sufficiently) exposed, EM_ASM
// is used below. // is used below.
SET_EM_CALLBACK("#window", mousemove, mousemove_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mousemove, mousemove_callback)
SET_EM_CALLBACK("#canvas", mousedown, mouse_button_callback) SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, mousedown, mouse_button_callback)
SET_EM_CALLBACK("#window", mouseup, mouse_button_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, mouseup, mouse_button_callback)
SET_EM_CALLBACK("#window", wheel, wheel_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, wheel, wheel_callback)
SET_EM_CALLBACK("#window", touchstart, touch_press_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchstart, touch_press_callback)
SET_EM_CALLBACK("#window", touchmove, touchmove_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchmove, touchmove_callback)
SET_EM_CALLBACK("#window", touchend, touch_press_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchend, touch_press_callback)
SET_EM_CALLBACK("#window", touchcancel, touch_press_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_WINDOW, touchcancel, touch_press_callback)
SET_EM_CALLBACK("#canvas", keydown, keydown_callback) SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keydown, keydown_callback)
SET_EM_CALLBACK("#canvas", keypress, keypress_callback) SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keypress, keypress_callback)
SET_EM_CALLBACK("#canvas", keyup, keyup_callback) SET_EM_CALLBACK(GODOT_CANVAS_SELECTOR, keyup, keyup_callback)
SET_EM_CALLBACK(NULL, fullscreenchange, fullscreen_change_callback) SET_EM_CALLBACK(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, fullscreenchange, fullscreen_change_callback)
SET_EM_CALLBACK_NOTARGET(gamepadconnected, gamepad_change_callback) SET_EM_CALLBACK_NOTARGET(gamepadconnected, gamepad_change_callback)
SET_EM_CALLBACK_NOTARGET(gamepaddisconnected, gamepad_change_callback) SET_EM_CALLBACK_NOTARGET(gamepaddisconnected, gamepad_change_callback)
#undef SET_EM_CALLBACK_NODATA #undef SET_EM_CALLBACK_NOTARGET
#undef SET_EM_CALLBACK #undef SET_EM_CALLBACK
#undef EM_CHECK #undef EM_CHECK
@@ -1079,15 +1085,15 @@ bool OS_JavaScript::main_loop_iterate() {
strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF; strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT; strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
strategy.canvasResizedCallback = NULL; strategy.canvasResizedCallback = NULL;
emscripten_enter_soft_fullscreen(NULL, &strategy); emscripten_enter_soft_fullscreen(GODOT_CANVAS_SELECTOR, &strategy);
} else { } else {
emscripten_set_canvas_element_size(NULL, windowed_size.width, windowed_size.height); emscripten_set_canvas_element_size(GODOT_CANVAS_SELECTOR, windowed_size.width, windowed_size.height);
} }
just_exited_fullscreen = false; just_exited_fullscreen = false;
} }
int canvas[2]; int canvas[2];
emscripten_get_canvas_element_size(NULL, canvas, canvas + 1); emscripten_get_canvas_element_size(GODOT_CANVAS_SELECTOR, canvas, canvas + 1);
video_mode.width = canvas[0]; video_mode.width = canvas[0];
video_mode.height = canvas[1]; video_mode.height = canvas[1];
if (!window_maximized && !video_mode.fullscreen && !just_exited_fullscreen && !entering_fullscreen) { if (!window_maximized && !video_mode.fullscreen && !just_exited_fullscreen && !entering_fullscreen) {