Merge pull request #76400 from RandomShaper/fix_android_input_anr_3.x

[3.x] Allow concurrent buffering and dispatch of input events
This commit is contained in:
Rémi Verschelde 2023-05-08 14:58:02 +02:00
commit 793a45dbbd
No known key found for this signature in database
GPG Key ID: C3336907360768E1
1 changed files with 24 additions and 1 deletions

View File

@ -36,6 +36,10 @@
#include "scene/resources/texture.h" #include "scene/resources/texture.h"
#include "servers/visual_server.h" #include "servers/visual_server.h"
#ifdef DEV_ENABLED
#include "core/os/thread.h"
#endif
void InputDefault::SpeedTrack::update(const Vector2 &p_delta_p) { void InputDefault::SpeedTrack::update(const Vector2 &p_delta_p) {
uint64_t tick = OS::get_singleton()->get_ticks_usec(); uint64_t tick = OS::get_singleton()->get_ticks_usec();
uint32_t tdiff = tick - last_tick; uint32_t tdiff = tick - last_tick;
@ -311,6 +315,10 @@ Vector3 InputDefault::get_gyroscope() const {
} }
void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated) { void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated) {
// This function does the final delivery of the input event to user land.
// Regardless where the event came from originally, this has to happen on the main thread.
DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id());
// Notes on mouse-touch emulation: // Notes on mouse-touch emulation:
// - Emulated mouse events are parsed, that is, re-routed to this method, so they make the same effects // - Emulated mouse events are parsed, that is, re-routed to this method, so they make the same effects
// as true mouse events. The only difference is the situation is flagged as emulated so they are not // as true mouse events. The only difference is the situation is flagged as emulated so they are not
@ -354,7 +362,9 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool
touch_event->set_pressed(mb->is_pressed()); touch_event->set_pressed(mb->is_pressed());
touch_event->set_position(mb->get_position()); touch_event->set_position(mb->get_position());
touch_event->set_double_tap(mb->is_doubleclick()); touch_event->set_double_tap(mb->is_doubleclick());
_THREAD_SAFE_UNLOCK_
main_loop->input_event(touch_event); main_loop->input_event(touch_event);
_THREAD_SAFE_LOCK_
} }
} }
@ -376,7 +386,9 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool
drag_event->set_relative(relative); drag_event->set_relative(relative);
drag_event->set_speed(get_last_mouse_speed()); drag_event->set_speed(get_last_mouse_speed());
_THREAD_SAFE_UNLOCK_
main_loop->input_event(drag_event); main_loop->input_event(drag_event);
_THREAD_SAFE_LOCK_
} }
} }
@ -472,7 +484,9 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool
if (ge.is_valid()) { if (ge.is_valid()) {
if (main_loop) { if (main_loop) {
_THREAD_SAFE_UNLOCK_
main_loop->input_event(ge); main_loop->input_event(ge);
_THREAD_SAFE_LOCK_
} }
} }
@ -495,7 +509,9 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool
} }
if (main_loop) { if (main_loop) {
_THREAD_SAFE_UNLOCK_
main_loop->input_event(p_event); main_loop->input_event(p_event);
_THREAD_SAFE_LOCK_
} }
} }
@ -747,8 +763,15 @@ void InputDefault::flush_buffered_events() {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
while (buffered_events.front()) { while (buffered_events.front()) {
_parse_input_event_impl(buffered_events.front()->get(), false); // The final delivery of the input event involves releasing the lock.
// While the lock is released, another thread may lock it and add new events to the back.
// Therefore, we get each event and pop it while we still have the lock,
// to ensure the list is in a consistent state.
List<Ref<InputEvent>>::Element *E = buffered_events.front();
Ref<InputEvent> e = E->get();
buffered_events.pop_front(); buffered_events.pop_front();
_parse_input_event_impl(e, false);
} }
} }