Move event queueing out of ScreenManager. This is a prerequisite for an upcoming change.

This commit is contained in:
Henrik Rydgård
2026-08-07 14:42:17 +02:00
parent 7219cd2f5a
commit a47edbf6ef
3 changed files with 52 additions and 65 deletions
+1 -51
View File
@@ -61,7 +61,7 @@ void ScreenManager::cancelScreensAbove(Screen *screen) {
}
}
void ScreenManager::update() {
void ScreenManager::update(const std::vector<QueuedEvent> &events) {
if (cancelScreensAbove_) {
bool found = false;
for (int i = (int)stack_.size() - 1; i >= 0; i--) {
@@ -84,14 +84,6 @@ void ScreenManager::update() {
overlayScreen_->update();
}
// Process queued events.
std::deque<QueuedEvent> events;
{
std::lock_guard<std::mutex> eventGuard(eventQueueLock_);
events = std::move(eventQueue_);
eventQueue_.clear();
}
for (const QueuedEvent &ev : events) {
switch (ev.type) {
case QueuedEventType::TOUCH:
@@ -174,32 +166,6 @@ void ScreenManager::switchToNext() {
nextStack_.clear();
}
void ScreenManager::touch(const TouchInput &touch) {
QueuedEvent ev{};
ev.type = QueuedEventType::TOUCH;
ev.touch = touch;
std::lock_guard<std::mutex> guard(eventQueueLock_);
eventQueue_.push_back(ev);
}
void ScreenManager::key(const KeyInput &key) {
QueuedEvent ev{};
ev.type = QueuedEventType::KEY;
ev.key = key;
std::lock_guard<std::mutex> guard(eventQueueLock_);
eventQueue_.push_back(ev);
}
void ScreenManager::axis(const AxisInput *axes, size_t count) {
QueuedEvent ev{};
ev.type = QueuedEventType::AXIS;
std::lock_guard<std::mutex> guard(eventQueueLock_);
for (size_t i = 0; i < count; i++) {
ev.axis = axes[i];
eventQueue_.push_back(ev);
}
}
void ScreenManager::deviceLost() {
for (auto &iter : stack_)
iter.screen->deviceLost();
@@ -331,16 +297,7 @@ void ScreenManager::getFocusPosition(float &x, float &y, float &z) {
void ScreenManager::sendMessage(UIMessage message, const char *value) {
if (message == UIMessage::RECREATE_VIEWS) {
RecreateAllViews();
} else if (message == UIMessage::LOST_FOCUS) {
TouchInput input{};
input.x = -50000.0f;
input.y = -50000.0f;
input.flags = TouchInputFlags::RELEASE_ALL;
input.timestamp = time_now_d();
input.id = 0;
touch(input);
}
if (backgroundScreen_) {
backgroundScreen_->sendMessage(message, value);
}
@@ -380,13 +337,6 @@ void ScreenManager::push(Screen *screen, int layerFlags) {
// Release touches and unfocus.
UI::SetFocusedView(nullptr, UI::FocusFlags::CAUSE_SCREEN_CHANGE);
TouchInput input{};
input.x = -50000.0f;
input.y = -50000.0f;
input.flags = TouchInputFlags::RELEASE_ALL;
input.timestamp = time_now_d();
input.id = 0;
touch(input);
Layer layer = {screen, layerFlags};
+1 -9
View File
@@ -34,7 +34,7 @@ public:
virtual ~ScreenManager();
void switchScreen(Screen *screen);
void update();
void update(const std::vector<QueuedEvent> &events);
void setUIContext(UIContext *context) { uiContext_ = context; }
UIContext *getUIContext() { return uiContext_; }
@@ -62,11 +62,6 @@ public:
void finishDialog(Screen *dialog, DialogResult result = DR_OK);
Screen *dialogParent(const Screen *dialog) const;
// Instant touch, separate from the update() mechanism.
void touch(const TouchInput &touch);
void key(const KeyInput &key);
void axis(const AxisInput *axes, size_t count);
void sendMessage(UIMessage message, const char *value);
const Screen *topScreen() const {
@@ -119,8 +114,5 @@ private:
std::unordered_map<int64_t, int> lastAxis_;
std::mutex eventQueueLock_;
std::deque<QueuedEvent> eventQueue_;
InputMode passInputToMapper_ = InputMode::None;
};
+50 -5
View File
@@ -199,6 +199,9 @@ static bool g_savedAchievementsHardcoreMode = false;
static bool g_hasSavedAchievementsSettings = false;
static bool g_nativeMainThreadReady = false;
static std::mutex g_inputEventQueueLock;
static std::vector<QueuedEvent> g_inputEventQueue;
static void ApplyAchievementsRuntimeSettings() {
auto *client = Achievements::GetClient();
if (!client) {
@@ -1024,7 +1027,14 @@ void NativeFrame(GraphicsContext *graphicsContext) {
debugFlags |= Draw::DebugFlags::PROFILE_SCOPES;
g_draw->BeginFrame(debugFlags);
g_screenManager->update();
// Process queued events.
std::vector<QueuedEvent> inputEvents;
{
std::lock_guard<std::mutex> eventGuard(g_inputEventQueueLock);
inputEvents = std::move(g_inputEventQueue);
g_inputEventQueue.clear();
}
g_screenManager->update(inputEvents);
// Do this after g_screenManager.update() so we can receive setting changes before rendering.
{
@@ -1052,6 +1062,22 @@ void NativeFrame(GraphicsContext *graphicsContext) {
// TODO: Add a to-string thingy.
VERBOSE_LOG(Log::System, "Handled global message: %d / %s", (int)item.message, item.value.c_str());
}
if (item.message == UIMessage::LOST_FOCUS) {
// This is a bit of a hack, but we need to do this here so that the graphics context is valid.
TouchInput input{};
input.x = -50000.0f;
input.y = -50000.0f;
input.flags = TouchInputFlags::RELEASE_ALL;
input.timestamp = time_now_d();
input.id = 0;
std::lock_guard<std::mutex> eventGuard(g_inputEventQueueLock);
QueuedEvent q{};
q.type = QueuedEventType::TOUCH;
q.touch = input;
g_inputEventQueue.push_back(q);
}
g_screenManager->sendMessage(item.message, item.value.c_str());
}
}
@@ -1248,7 +1274,12 @@ void NativeTouch(const TouchInput &touch) {
if (my_isnan(touch.x) || my_isnan(touch.y)) {
return;
}
g_screenManager->touch(touch);
QueuedEvent ev{};
ev.type = QueuedEventType::TOUCH;
ev.touch = touch;
std::lock_guard<std::mutex> guard(g_inputEventQueueLock);
g_inputEventQueue.push_back(ev);
}
// up, down
@@ -1458,8 +1489,14 @@ bool NativeKey(const KeyInput &key) {
return false;
}
// Dispatch the key event.
g_screenManager->key(modKey);
// Queue up the key event for synchronous processing in the UI.
QueuedEvent ev{};
ev.type = QueuedEventType::KEY;
ev.key = key;
{
std::lock_guard<std::mutex> guard(g_inputEventQueueLock);
g_inputEventQueue.push_back(ev);
}
// The Mode key can have weird consequences on some devices, see #17245.
if (key.keyCode == NKCODE_BUTTON_MODE) {
@@ -1487,7 +1524,15 @@ void NativeAxis(const AxisInput *axes, size_t count) {
g_controlMapper.Axis(axes, count);
}
g_screenManager->axis(axes, count);
QueuedEvent ev{};
ev.type = QueuedEventType::AXIS;
{
std::lock_guard<std::mutex> guard(g_inputEventQueueLock);
for (size_t i = 0; i < count; i++) {
ev.axis = axes[i];
g_inputEventQueue.push_back(ev);
}
}
for (size_t i = 0; i < count; i++) {
const AxisInput &axis = axes[i];