From dd25e69e667891e583fd6029ccd2ab36d4fbab9b Mon Sep 17 00:00:00 2001 From: gibbed Date: Fri, 27 Nov 2020 05:20:17 -0600 Subject: [PATCH] [HID] Pass 'is active' callback to input drivers. --- src/xenia/emulator.cc | 5 ++++- src/xenia/hid/input_driver.h | 17 ++++++++++++++++- src/xenia/hid/sdl/sdl_input_driver.cc | 12 ++++++------ src/xenia/hid/winkey/winkey_input_driver.cc | 6 +++--- src/xenia/kernel/xam/xam_module.cc | 4 ++++ src/xenia/kernel/xam/xam_module.h | 2 ++ src/xenia/kernel/xam/xam_private.h | 2 ++ src/xenia/kernel/xam/xam_ui.cc | 4 ++-- 8 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index aca6bd52a..44f284d34 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -184,7 +184,10 @@ X_STATUS Emulator::Setup( if (input_driver_factory) { auto input_drivers = input_driver_factory(display_window_); for (size_t i = 0; i < input_drivers.size(); ++i) { - input_system_->AddDriver(std::move(input_drivers[i])); + auto& input_driver = input_drivers[i]; + input_driver->set_is_active_callback( + []() -> bool { return !xe::kernel::xam::xeXamIsUIActive(); }); + input_system_->AddDriver(std::move(input_driver)); } } diff --git a/src/xenia/hid/input_driver.h b/src/xenia/hid/input_driver.h index 6de322ab1..aef8cffeb 100644 --- a/src/xenia/hid/input_driver.h +++ b/src/xenia/hid/input_driver.h @@ -10,7 +10,10 @@ #ifndef XENIA_HID_INPUT_DRIVER_H_ #define XENIA_HID_INPUT_DRIVER_H_ +#include + #include "xenia/hid/input.h" +#include "xenia/ui/window.h" #include "xenia/xbox.h" namespace xe { @@ -38,10 +41,22 @@ class InputDriver { virtual X_RESULT GetKeystroke(uint32_t user_index, uint32_t flags, X_INPUT_KEYSTROKE* out_keystroke) = 0; + void set_is_active_callback(std::function is_active_callback) { + is_active_callback_ = is_active_callback; + } + + private: + xe::ui::Window* window_ = nullptr; + std::function is_active_callback_ = nullptr; + protected: explicit InputDriver(xe::ui::Window* window); - xe::ui::Window* window_ = nullptr; + xe::ui::Window* window() const { return window_; } + + bool is_active() const { + return !is_active_callback_ || is_active_callback_(); + } }; } // namespace hid diff --git a/src/xenia/hid/sdl/sdl_input_driver.cc b/src/xenia/hid/sdl/sdl_input_driver.cc index 470892588..fb77397da 100644 --- a/src/xenia/hid/sdl/sdl_input_driver.cc +++ b/src/xenia/hid/sdl/sdl_input_driver.cc @@ -65,7 +65,7 @@ X_STATUS SDLInputDriver::Setup() { // SDL_PumpEvents should only be run in the thread that initialized SDL - we // are hijacking the window loop thread for that. - window_->loop()->PostSynchronous([&]() { + window()->loop()->PostSynchronous([&]() { if (!xe::helper::sdl::SDLHelper::Prepare()) { return; } @@ -385,7 +385,7 @@ X_RESULT SDLInputDriver::GetKeystroke(uint32_t users, uint32_t flags, } void SDLInputDriver::OnControllerDeviceAdded(SDL_Event* event) { - assert(window_->loop()->is_on_loop_thread()); + assert(window()->loop()->is_on_loop_thread()); std::unique_lock guard(controllers_mutex_); // Open the controller. @@ -424,7 +424,7 @@ void SDLInputDriver::OnControllerDeviceAdded(SDL_Event* event) { } void SDLInputDriver::OnControllerDeviceRemoved(SDL_Event* event) { - assert(window_->loop()->is_on_loop_thread()); + assert(window()->loop()->is_on_loop_thread()); std::unique_lock guard(controllers_mutex_); // Find the disconnected gamecontroller and close it. @@ -436,7 +436,7 @@ void SDLInputDriver::OnControllerDeviceRemoved(SDL_Event* event) { } void SDLInputDriver::OnControllerDeviceAxisMotion(SDL_Event* event) { - assert(window_->loop()->is_on_loop_thread()); + assert(window()->loop()->is_on_loop_thread()); std::unique_lock guard(controllers_mutex_); auto [found, i] = GetControllerIndexFromInstanceID(event->caxis.which); @@ -469,7 +469,7 @@ void SDLInputDriver::OnControllerDeviceAxisMotion(SDL_Event* event) { } void SDLInputDriver::OnControllerDeviceButtonChanged(SDL_Event* event) { - assert(window_->loop()->is_on_loop_thread()); + assert(window()->loop()->is_on_loop_thread()); std::unique_lock guard(controllers_mutex_); // Define a lookup table to map between SDL and XInput button codes. @@ -569,7 +569,7 @@ void SDLInputDriver::QueueControllerUpdate() { bool is_queued = false; sdl_pumpevents_queued_.compare_exchange_strong(is_queued, true); if (!is_queued) { - window_->loop()->Post([this]() { + window()->loop()->Post([this]() { SDL_PumpEvents(); sdl_pumpevents_queued_ = false; }); diff --git a/src/xenia/hid/winkey/winkey_input_driver.cc b/src/xenia/hid/winkey/winkey_input_driver.cc index 30ce09309..525e03ae6 100644 --- a/src/xenia/hid/winkey/winkey_input_driver.cc +++ b/src/xenia/hid/winkey/winkey_input_driver.cc @@ -21,7 +21,7 @@ namespace winkey { WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window) : InputDriver(window), packet_number_(1) { // Register a key listener. - window_->on_key_down.AddListener([this](ui::KeyEvent* evt) { + window->on_key_down.AddListener([this](ui::KeyEvent* evt) { auto global_lock = global_critical_region_.Acquire(); KeyEvent key; @@ -31,7 +31,7 @@ WinKeyInputDriver::WinKeyInputDriver(xe::ui::Window* window) key.repeat_count = evt->repeat_count(); key_events_.push(key); }); - window_->on_key_up.AddListener([this](ui::KeyEvent* evt) { + window->on_key_up.AddListener([this](ui::KeyEvent* evt) { auto global_lock = global_critical_region_.Acquire(); KeyEvent key; @@ -88,7 +88,7 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index, int16_t thumb_rx = 0; int16_t thumb_ry = 0; - if (window_->has_focus()) { + if (window()->has_focus()) { if (IS_KEY_TOGGLED(VK_CAPITAL) || IS_KEY_DOWN(VK_SHIFT)) { // dpad toggled if (IS_KEY_DOWN('A')) { diff --git a/src/xenia/kernel/xam/xam_module.cc b/src/xenia/kernel/xam/xam_module.cc index 1bb7dbdc6..b38de2160 100644 --- a/src/xenia/kernel/xam/xam_module.cc +++ b/src/xenia/kernel/xam/xam_module.cc @@ -19,6 +19,10 @@ namespace xe { namespace kernel { namespace xam { +std::atomic xam_dialogs_shown_ = {0}; + +bool xeXamIsUIActive() { return xam_dialogs_shown_ > 0; } + XamModule::XamModule(Emulator* emulator, KernelState* kernel_state) : KernelModule(kernel_state, "xe:\\xam.xex"), loader_data_() { RegisterExportTable(export_resolver_); diff --git a/src/xenia/kernel/xam/xam_module.h b/src/xenia/kernel/xam/xam_module.h index 8c9fd6550..6c5d88cbb 100644 --- a/src/xenia/kernel/xam/xam_module.h +++ b/src/xenia/kernel/xam/xam_module.h @@ -21,6 +21,8 @@ namespace xe { namespace kernel { namespace xam { +bool xeXamIsUIActive(); + class XamModule : public KernelModule { public: XamModule(Emulator* emulator, KernelState* kernel_state); diff --git a/src/xenia/kernel/xam/xam_private.h b/src/xenia/kernel/xam/xam_private.h index b82f44bfd..6006d635b 100644 --- a/src/xenia/kernel/xam/xam_private.h +++ b/src/xenia/kernel/xam/xam_private.h @@ -18,6 +18,8 @@ namespace xe { namespace kernel { namespace xam { +bool xeXamIsUIActive(); + xe::cpu::Export* RegisterExport_xam(xe::cpu::Export* export_entry); // Registration functions, one per file. diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index 86ebd1253..0b17135ae 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -41,7 +41,7 @@ namespace xam { // We deliberately delay the XN_SYS_UI = false notification to give games time // to create a listener (if they're insane enough do this). -std::atomic xam_dialogs_shown_ = {0}; +extern std::atomic xam_dialogs_shown_; class XamDialog : public xe::ui::ImGuiDialog { public: @@ -192,7 +192,7 @@ X_RESULT xeXamDispatchHeadlessEx( } } -dword_result_t XamIsUIActive() { return xam_dialogs_shown_ > 0 ? 1 : 0; } +dword_result_t XamIsUIActive() { return xeXamIsUIActive(); } DECLARE_XAM_EXPORT2(XamIsUIActive, kUI, kImplemented, kHighFrequency); class MessageBoxDialog : public XamDialog {