diff --git a/main/input_default.cpp b/main/input_default.cpp index 126b5ef0a1d4..606921cea15c 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -36,6 +36,10 @@ #include "scene/resources/texture.h" #include "servers/visual_server.h" +#ifdef DEV_ENABLED +#include "core/os/thread.h" +#endif + void InputDefault::SpeedTrack::update(const Vector2 &p_delta_p) { uint64_t tick = OS::get_singleton()->get_ticks_usec(); uint32_t tdiff = tick - last_tick; @@ -311,6 +315,10 @@ Vector3 InputDefault::get_gyroscope() const { } void InputDefault::_parse_input_event_impl(const Ref &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: // - 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 @@ -354,7 +362,9 @@ void InputDefault::_parse_input_event_impl(const Ref &p_event, bool touch_event->set_pressed(mb->is_pressed()); touch_event->set_position(mb->get_position()); touch_event->set_double_tap(mb->is_doubleclick()); + _THREAD_SAFE_UNLOCK_ main_loop->input_event(touch_event); + _THREAD_SAFE_LOCK_ } } @@ -376,7 +386,9 @@ void InputDefault::_parse_input_event_impl(const Ref &p_event, bool drag_event->set_relative(relative); drag_event->set_speed(get_last_mouse_speed()); + _THREAD_SAFE_UNLOCK_ main_loop->input_event(drag_event); + _THREAD_SAFE_LOCK_ } } @@ -472,7 +484,9 @@ void InputDefault::_parse_input_event_impl(const Ref &p_event, bool if (ge.is_valid()) { if (main_loop) { + _THREAD_SAFE_UNLOCK_ main_loop->input_event(ge); + _THREAD_SAFE_LOCK_ } } @@ -495,7 +509,9 @@ void InputDefault::_parse_input_event_impl(const Ref &p_event, bool } if (main_loop) { + _THREAD_SAFE_UNLOCK_ main_loop->input_event(p_event); + _THREAD_SAFE_LOCK_ } } @@ -747,8 +763,15 @@ void InputDefault::flush_buffered_events() { _THREAD_SAFE_METHOD_ 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>::Element *E = buffered_events.front(); + Ref e = E->get(); buffered_events.pop_front(); + + _parse_input_event_impl(e, false); } }