Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Allow concurrent buffering and dispatch of input events #76400

Merged
merged 1 commit into from
May 8, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion main/input_default.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -311,6 +315,10 @@ Vector3 InputDefault::get_gyroscope() const {
}

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:
// - 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
Expand Down Expand Up @@ -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_position(mb->get_position());
touch_event->set_double_tap(mb->is_doubleclick());
_THREAD_SAFE_UNLOCK_
main_loop->input_event(touch_event);
_THREAD_SAFE_LOCK_
}
}

Expand All @@ -376,7 +386,9 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &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_
}
}

Expand Down Expand Up @@ -472,7 +484,9 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool

if (ge.is_valid()) {
if (main_loop) {
_THREAD_SAFE_UNLOCK_
main_loop->input_event(ge);
_THREAD_SAFE_LOCK_
}
}

Expand All @@ -495,7 +509,9 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool
}

if (main_loop) {
_THREAD_SAFE_UNLOCK_
main_loop->input_event(p_event);
_THREAD_SAFE_LOCK_
}
}

Expand Down Expand Up @@ -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<Ref<InputEvent>>::Element *E = buffered_events.front();
Ref<InputEvent> e = E->get();
buffered_events.pop_front();

_parse_input_event_impl(e, false);
}
}

Expand Down