summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorPedro J. Estébanez <pedrojrulez@gmail.com>2023-04-24 12:46:01 +0200
committerRémi Verschelde <rverschelde@gmail.com>2023-05-12 12:11:58 +0200
commitd07d4d90d030575296a6118580b158d6ff77c851 (patch)
tree1f5fabd5213d11a8607fb8b7842d1655cada89cc /core
parent4b11fc65f19e7bdef94a7af293498dcadd79cf56 (diff)
Allow concurrent buffering and dispatch of input events
(cherry picked from commit f369ed9223146a644cfa3f922e0aacbb002f688c)
Diffstat (limited to 'core')
-rw-r--r--core/input/input.cpp25
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);
}
}