diff options
author | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2023-04-24 12:46:01 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2023-05-12 12:11:58 +0200 |
commit | d07d4d90d030575296a6118580b158d6ff77c851 (patch) | |
tree | 1f5fabd5213d11a8607fb8b7842d1655cada89cc | |
parent | 4b11fc65f19e7bdef94a7af293498dcadd79cf56 (diff) |
Allow concurrent buffering and dispatch of input events
(cherry picked from commit f369ed9223146a644cfa3f922e0aacbb002f688c)
-rw-r--r-- | core/input/input.cpp | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp index e74523e059..5aef9a9039 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -35,6 +35,10 @@ #include "core/input/input_map.h" #include "core/os/os.h" +#ifdef DEV_ENABLED +#include "core/os/thread.h" +#endif + static const char *_joy_buttons[(size_t)JoyButton::SDL_MAX] = { "a", "b", @@ -486,6 +490,10 @@ Vector3 Input::get_gyroscope() const { } void Input::_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: // - 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 @@ -537,7 +545,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em touch_event->set_position(mb->get_position()); touch_event->set_double_tap(mb->is_double_click()); touch_event->set_device(InputEvent::DEVICE_ID_EMULATION); + _THREAD_SAFE_UNLOCK_ event_dispatch_function(touch_event); + _THREAD_SAFE_LOCK_ } } @@ -563,7 +573,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em drag_event->set_velocity(get_last_mouse_velocity()); drag_event->set_device(InputEvent::DEVICE_ID_EMULATION); + _THREAD_SAFE_UNLOCK_ event_dispatch_function(drag_event); + _THREAD_SAFE_LOCK_ } } @@ -664,7 +676,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em if (ge.is_valid()) { if (event_dispatch_function) { + _THREAD_SAFE_UNLOCK_ event_dispatch_function(ge); + _THREAD_SAFE_LOCK_ } } @@ -687,7 +701,9 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em } if (event_dispatch_function) { + _THREAD_SAFE_UNLOCK_ event_dispatch_function(p_event); + _THREAD_SAFE_LOCK_ } } @@ -937,8 +953,15 @@ void Input::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<Ref<InputEvent>>::Element *E = buffered_events.front(); + Ref<InputEvent> e = E->get(); buffered_events.pop_front(); + + _parse_input_event_impl(e, false); } } |