From b27366e1e6a2e196696a624b8dbc71c0c8376f23 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 21 Feb 2023 13:20:02 +0300 Subject: [PATCH] rsx/overlays: Enable input hijacking --- rpcs3/Emu/RSX/Overlays/overlay_manager.cpp | 35 ++++++++++++++++++++-- rpcs3/Emu/RSX/Overlays/overlay_manager.h | 2 ++ rpcs3/Emu/RSX/Overlays/overlays.cpp | 6 ++-- rpcs3/Emu/RSX/Overlays/overlays.h | 7 ++++- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/RSX/Overlays/overlay_manager.cpp b/rpcs3/Emu/RSX/Overlays/overlay_manager.cpp index cd86a1842b..ffdbb27968 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_manager.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_manager.cpp @@ -158,6 +158,7 @@ namespace rsx { if (auto iface = std::dynamic_pointer_cast(get(uid))) { + // TODO: Hijack input immediately! m_input_token_stack.push( name, std::move(iface), @@ -181,6 +182,10 @@ namespace rsx void display_manager::input_thread_loop() { + // Avoid tail recursion by reinserting pushed-down items + std::vector interrupted_items; + bool in_interrupted_mode = false; + while (!m_input_thread_abort) { for (auto&& input_context : m_input_token_stack.pop_all_reversed()) @@ -190,9 +195,17 @@ namespace rsx continue; } - if (input_context.input_loop_prologue) + if (in_interrupted_mode) + { + interrupted_items.push_back(input_context); + continue; + } + + if (input_context.input_loop_prologue && + !input_context.prologue_completed) { input_context.input_loop_prologue(); + input_context.prologue_completed = true; } s32 result = 0; @@ -205,6 +218,14 @@ namespace rsx result = input_context.input_loop_override(); } + if (result == user_interface::selection_code::interrupted) + { + // Push back the items onto the stack + in_interrupted_mode = true; + interrupted_items.push_back(input_context); + continue; + } + if (input_context.input_loop_epilogue) { input_context.input_loop_epilogue(result); @@ -215,7 +236,17 @@ namespace rsx } } - m_input_token_stack.wait(); + if (in_interrupted_mode) + { + for (const auto& iface : interrupted_items) + { + m_input_token_stack.push(iface); + } + } + else + { + m_input_token_stack.wait(); + } } } } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_manager.h b/rpcs3/Emu/RSX/Overlays/overlay_manager.h index 5c7d1cc869..d2b0738f54 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_manager.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_manager.h @@ -175,6 +175,8 @@ namespace rsx std::function input_loop_prologue = nullptr; std::function input_loop_epilogue = nullptr; std::function input_loop_override = nullptr; + + bool prologue_completed = false; }; lf_queue m_input_token_stack; diff --git a/rpcs3/Emu/RSX/Overlays/overlays.cpp b/rpcs3/Emu/RSX/Overlays/overlays.cpp index 894f999e87..798782d2e5 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlays.cpp @@ -122,7 +122,7 @@ namespace rsx last_button_state[pad_index][button_id] = pressed; }; - while (!m_stop_input_loop) + while (!m_stop_input_loop && !m_input_loop_interrupted) { if (Emu.IsStopped()) { @@ -363,7 +363,9 @@ namespace rsx m_interactive = false; - return 0; + return (m_input_loop_interrupted && !m_stop_input_loop) + ? selection_code::interrupted + : selection_code::ok; } void user_interface::close(bool use_callback, bool stop_pad_interception) diff --git a/rpcs3/Emu/RSX/Overlays/overlays.h b/rpcs3/Emu/RSX/Overlays/overlays.h index 4b2c5810c6..fca32b5ca4 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.h +++ b/rpcs3/Emu/RSX/Overlays/overlays.h @@ -84,9 +84,11 @@ namespace rsx // Move this somewhere to avoid duplication enum selection_code { + ok = 0, new_save = -1, canceled = -2, - error = -3 + error = -3, + interrupted = -4 }; protected: @@ -113,6 +115,7 @@ namespace rsx bool m_start_pad_interception = true; atomic_t m_stop_pad_interception = false; atomic_t m_input_thread_detached = false; + atomic_t m_input_loop_interrupted = false; atomic_t thread_bits = 0; bool m_keyboard_input_enabled = false; // Allow keyboard input bool m_keyboard_pad_handler_active = true; // Initialized as true to prevent keyboard input until proven otherwise. @@ -149,6 +152,8 @@ namespace rsx bool is_detached() const { return m_input_thread_detached; } void detach_input() { m_input_thread_detached.store(true); } + void on_input_interrupted() { m_input_loop_interrupted.store(true); } + void on_input_resumed() { m_input_loop_interrupted.store(false); } void update() override {}