diff options
| -rw-r--r-- | src/input_common/main.cpp | 6 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player.cpp | 318 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input_player.h | 17 | 
4 files changed, 205 insertions, 138 deletions
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index d32fd8b81..354c734fe 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -78,7 +78,7 @@ struct InputSubsystem::Impl {      [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const {          std::vector<Common::ParamPackage> devices = {              Common::ParamPackage{{"display", "Any"}, {"class", "any"}}, -            Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "key"}}, +            Common::ParamPackage{{"display", "Keyboard/Mouse"}, {"class", "keyboard"}},          };  #ifdef HAVE_SDL2          auto sdl_devices = sdl->GetInputDevices(); @@ -96,7 +96,7 @@ struct InputSubsystem::Impl {          if (!params.Has("class") || params.Get("class", "") == "any") {              return {};          } -        if (params.Get("class", "") == "key") { +        if (params.Get("class", "") == "keyboard") {              // TODO consider returning the SDL key codes for the default keybindings              return {};          } @@ -116,7 +116,7 @@ struct InputSubsystem::Impl {          if (!params.Has("class") || params.Get("class", "") == "any") {              return {};          } -        if (params.Get("class", "") == "key") { +        if (params.Get("class", "") == "keyboard") {              // TODO consider returning the SDL key codes for the default keybindings              return {};          } diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 2725fcb2b..f2932aa0b 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -242,6 +242,6 @@ void ConfigureInput::UpdateDockedState(bool is_handheld) {  void ConfigureInput::UpdateAllInputDevices() {      for (const auto& player : player_controllers) { -        player->UpdateInputDevices(); +        player->UpdateInputDeviceCombobox();      }  } diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index f58ca29d7..0de0c6999 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -477,11 +477,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i          UpdateMotionButtons();      }); -    connect(ui->comboDevices, qOverload<int>(&QComboBox::currentIndexChanged), this, +    connect(ui->comboDevices, qOverload<int>(&QComboBox::activated), this,              &ConfigureInputPlayer::UpdateMappingWithDefaults); +    ui->comboDevices->setCurrentIndex(-1); +      ui->buttonRefreshDevices->setIcon(QIcon::fromTheme(QStringLiteral("view-refresh"))); -    UpdateInputDevices();      connect(ui->buttonRefreshDevices, &QPushButton::clicked,              [this] { emit RefreshInputDevices(); }); @@ -492,14 +493,14 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i          Common::ParamPackage params;          if (input_subsystem->GetGCButtons()->IsPolling()) {              params = input_subsystem->GetGCButtons()->GetNextInput(); -            if (params.Has("engine")) { +            if (params.Has("engine") && IsInputAcceptable(params)) {                  SetPollingResult(params, false);                  return;              }          }          if (input_subsystem->GetGCAnalogs()->IsPolling()) {              params = input_subsystem->GetGCAnalogs()->GetNextInput(); -            if (params.Has("engine")) { +            if (params.Has("engine") && IsInputAcceptable(params)) {                  SetPollingResult(params, false);                  return;              } @@ -513,7 +514,7 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i          }          for (auto& poller : device_pollers) {              params = poller->GetNextInput(); -            if (params.Has("engine")) { +            if (params.Has("engine") && IsInputAcceptable(params)) {                  SetPollingResult(params, false);                  return;              } @@ -572,6 +573,14 @@ void ConfigureInputPlayer::ApplyConfiguration() {      UpdateController(Settings::ControllerType::Handheld, HANDHELD_INDEX, handheld.connected);  } +void ConfigureInputPlayer::showEvent(QShowEvent* event) { +    if (bottom_row == nullptr) { +        return; +    } +    QWidget::showEvent(event); +    ui->main->addWidget(bottom_row); +} +  void ConfigureInputPlayer::changeEvent(QEvent* event) {      if (event->type() == QEvent::LanguageChange) {          RetranslateUI(); @@ -604,6 +613,7 @@ void ConfigureInputPlayer::LoadConfiguration() {      }      UpdateUI(); +    UpdateInputDeviceCombobox();      if (debug) {          return; @@ -615,11 +625,56 @@ void ConfigureInputPlayer::LoadConfiguration() {          (player_index == 0 && Settings::values.players[HANDHELD_INDEX].connected));  } -void ConfigureInputPlayer::UpdateInputDevices() { -    input_devices = input_subsystem->GetInputDevices(); -    ui->comboDevices->clear(); -    for (auto device : input_devices) { -        ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {}); +void ConfigureInputPlayer::ConnectPlayer(bool connected) { +    ui->groupConnectedController->setChecked(connected); +} + +void ConfigureInputPlayer::UpdateInputDeviceCombobox() { +    // Skip input device persistence if "Input Devices" is set to "Any". +    if (ui->comboDevices->currentIndex() == 0) { +        UpdateInputDevices(); +        return; +    } + +    // Find the first button that isn't empty. +    const auto button_param = +        std::find_if(buttons_param.begin(), buttons_param.end(), +                     [](const Common::ParamPackage param) { return param.Has("engine"); }); +    const bool buttons_empty = button_param == buttons_param.end(); + +    const auto current_engine = button_param->Get("engine", ""); +    const auto current_guid = button_param->Get("guid", ""); +    const auto current_port = button_param->Get("port", ""); + +    UpdateInputDevices(); + +    if (buttons_empty) { +        return; +    } + +    const bool all_one_device = +        std::all_of(buttons_param.begin(), buttons_param.end(), +                    [current_engine, current_guid, current_port](const Common::ParamPackage param) { +                        return !param.Has("engine") || (param.Get("engine", "") == current_engine && +                                                        param.Get("guid", "") == current_guid && +                                                        param.Get("port", "") == current_port); +                    }); + +    if (all_one_device) { +        const auto devices_it = std::find_if( +            input_devices.begin(), input_devices.end(), +            [current_engine, current_guid, current_port](const Common::ParamPackage param) { +                return param.Get("class", "") == current_engine && +                       param.Get("guid", "") == current_guid && +                       param.Get("port", "") == current_port; +            }); +        const int device_index = +            devices_it != input_devices.end() +                ? static_cast<int>(std::distance(input_devices.begin(), devices_it)) +                : 0; +        ui->comboDevices->setCurrentIndex(device_index); +    } else { +        ui->comboDevices->setCurrentIndex(0);      }  } @@ -648,7 +703,7 @@ void ConfigureInputPlayer::RestoreDefaults() {      }      UpdateUI(); -    UpdateInputDevices(); +    UpdateInputDeviceCombobox();      ui->comboControllerType->setCurrentIndex(0);  } @@ -752,117 +807,12 @@ void ConfigureInputPlayer::UpdateUI() {      }  } -void ConfigureInputPlayer::UpdateMappingWithDefaults() { -    if (ui->comboDevices->currentIndex() < 2) { -        return; -    } -    const auto& device = input_devices[ui->comboDevices->currentIndex()]; -    auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); -    auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); -    for (std::size_t i = 0; i < buttons_param.size(); ++i) { -        buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; -    } -    for (std::size_t i = 0; i < analogs_param.size(); ++i) { -        analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; -    } - -    UpdateUI(); -} - -void ConfigureInputPlayer::HandleClick( -    QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, -    InputCommon::Polling::DeviceType type) { -    if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) { -        button->setText(tr("Shake!")); -    } else { -        button->setText(tr("[waiting]")); -    } -    button->setFocus(); - -    // The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a -    // controller, then they don't want keyboard/mouse input -    want_keyboard_mouse = ui->comboDevices->currentIndex() < 2; - -    input_setter = new_input_setter; - -    device_pollers = input_subsystem->GetPollers(type); - -    for (auto& poller : device_pollers) { -        poller->Start(); -    } - -    QWidget::grabMouse(); -    QWidget::grabKeyboard(); - -    if (type == InputCommon::Polling::DeviceType::Button) { -        input_subsystem->GetGCButtons()->BeginConfiguration(); -    } else { -        input_subsystem->GetGCAnalogs()->BeginConfiguration(); -    } - -    if (type == InputCommon::Polling::DeviceType::Motion) { -        input_subsystem->GetUDPMotions()->BeginConfiguration(); -    } - -    timeout_timer->start(2500); // Cancel after 2.5 seconds -    poll_timer->start(50);      // Check for new inputs every 50ms -} - -void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { -    timeout_timer->stop(); -    poll_timer->stop(); -    for (auto& poller : device_pollers) { -        poller->Stop(); -    } - -    QWidget::releaseMouse(); -    QWidget::releaseKeyboard(); - -    input_subsystem->GetGCButtons()->EndConfiguration(); -    input_subsystem->GetGCAnalogs()->EndConfiguration(); - -    input_subsystem->GetUDPMotions()->EndConfiguration(); - -    if (!abort) { -        (*input_setter)(params); -    } - -    UpdateUI(); -    input_setter = std::nullopt; -} - -void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { -    if (!input_setter || !event) { -        return; -    } - -    if (want_keyboard_mouse) { -        SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())}, -                         false); -    } else { -        // We don't want any mouse buttons, so don't stop polling -        return; -    } - -    SetPollingResult({}, true); -} - -void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { -    if (!input_setter || !event) { -        return; -    } - -    if (event->key() != Qt::Key_Escape) { -        if (want_keyboard_mouse) { -            SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, -                             false); -        } else { -            // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling -            return; -        } +void ConfigureInputPlayer::UpdateInputDevices() { +    input_devices = input_subsystem->GetInputDevices(); +    ui->comboDevices->clear(); +    for (auto device : input_devices) { +        ui->comboDevices->addItem(QString::fromStdString(device.Get("display", "Unknown")), {});      } - -    SetPollingResult({}, true);  }  void ConfigureInputPlayer::UpdateControllerIcon() { @@ -986,14 +936,128 @@ void ConfigureInputPlayer::UpdateMotionButtons() {      }  } -void ConfigureInputPlayer::showEvent(QShowEvent* event) { -    if (bottom_row == nullptr) { +void ConfigureInputPlayer::UpdateMappingWithDefaults() { +    if (ui->comboDevices->currentIndex() < 2) {          return;      } -    QWidget::showEvent(event); -    ui->main->addWidget(bottom_row); +    const auto& device = input_devices[ui->comboDevices->currentIndex()]; +    auto button_mapping = input_subsystem->GetButtonMappingForDevice(device); +    auto analog_mapping = input_subsystem->GetAnalogMappingForDevice(device); +    for (std::size_t i = 0; i < buttons_param.size(); ++i) { +        buttons_param[i] = button_mapping[static_cast<Settings::NativeButton::Values>(i)]; +    } +    for (std::size_t i = 0; i < analogs_param.size(); ++i) { +        analogs_param[i] = analog_mapping[static_cast<Settings::NativeAnalog::Values>(i)]; +    } + +    UpdateUI();  } -void ConfigureInputPlayer::ConnectPlayer(bool connected) { -    ui->groupConnectedController->setChecked(connected); +void ConfigureInputPlayer::HandleClick( +    QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter, +    InputCommon::Polling::DeviceType type) { +    if (button == ui->buttonMotionLeft || button == ui->buttonMotionRight) { +        button->setText(tr("Shake!")); +    } else { +        button->setText(tr("[waiting]")); +    } +    button->setFocus(); + +    // The first two input devices are always Any and Keyboard/Mouse. If the user filtered to a +    // controller, then they don't want keyboard/mouse input +    want_keyboard_mouse = ui->comboDevices->currentIndex() < 2; + +    input_setter = new_input_setter; + +    device_pollers = input_subsystem->GetPollers(type); + +    for (auto& poller : device_pollers) { +        poller->Start(); +    } + +    QWidget::grabMouse(); +    QWidget::grabKeyboard(); + +    if (type == InputCommon::Polling::DeviceType::Button) { +        input_subsystem->GetGCButtons()->BeginConfiguration(); +    } else { +        input_subsystem->GetGCAnalogs()->BeginConfiguration(); +    } + +    if (type == InputCommon::Polling::DeviceType::Motion) { +        input_subsystem->GetUDPMotions()->BeginConfiguration(); +    } + +    timeout_timer->start(2500); // Cancel after 2.5 seconds +    poll_timer->start(50);      // Check for new inputs every 50ms +} + +void ConfigureInputPlayer::SetPollingResult(const Common::ParamPackage& params, bool abort) { +    timeout_timer->stop(); +    poll_timer->stop(); +    for (auto& poller : device_pollers) { +        poller->Stop(); +    } + +    QWidget::releaseMouse(); +    QWidget::releaseKeyboard(); + +    input_subsystem->GetGCButtons()->EndConfiguration(); +    input_subsystem->GetGCAnalogs()->EndConfiguration(); + +    input_subsystem->GetUDPMotions()->EndConfiguration(); + +    if (!abort) { +        (*input_setter)(params); +    } + +    UpdateUI(); +    UpdateInputDeviceCombobox(); + +    input_setter = std::nullopt; +} + +bool ConfigureInputPlayer::IsInputAcceptable(const Common::ParamPackage& params) const { +    if (ui->comboDevices->currentIndex() == 0) { +        return true; +    } + +    const auto current_input_device = input_devices[ui->comboDevices->currentIndex()]; +    return params.Get("engine", "") == current_input_device.Get("class", "") && +           params.Get("guid", "") == current_input_device.Get("guid", "") && +           params.Get("port", "") == current_input_device.Get("port", ""); +} + +void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) { +    if (!input_setter || !event) { +        return; +    } + +    if (want_keyboard_mouse) { +        SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->button())}, +                         false); +    } else { +        // We don't want any mouse buttons, so don't stop polling +        return; +    } + +    SetPollingResult({}, true); +} + +void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) { +    if (!input_setter || !event) { +        return; +    } + +    if (event->key() != Qt::Key_Escape) { +        if (want_keyboard_mouse) { +            SetPollingResult(Common::ParamPackage{InputCommon::GenerateKeyboardParam(event->key())}, +                             false); +        } else { +            // Escape key wasn't pressed and we don't want any keyboard keys, so don't stop polling +            return; +        } +    } + +    SetPollingResult({}, true);  } diff --git a/src/yuzu/configuration/configure_input_player.h b/src/yuzu/configuration/configure_input_player.h index c19aefffa..a5414e624 100644 --- a/src/yuzu/configuration/configure_input_player.h +++ b/src/yuzu/configuration/configure_input_player.h @@ -51,8 +51,11 @@ public:      /// Save all button configurations to settings file.      void ApplyConfiguration(); +    /// Set the connection state checkbox (used to sync state). +    void ConnectPlayer(bool connected); +      /// Update the input devices combobox. -    void UpdateInputDevices(); +    void UpdateInputDeviceCombobox();      /// Restore all buttons to their default values.      void RestoreDefaults(); @@ -60,9 +63,6 @@ public:      /// Clear all input configuration.      void ClearAll(); -    /// Set the connection state checkbox (used to sync state). -    void ConnectPlayer(bool connected); -  signals:      /// Emitted when this controller is connected by the user.      void Connected(bool connected); @@ -89,6 +89,9 @@ private:      /// Finish polling and configure input using the input_setter.      void SetPollingResult(const Common::ParamPackage& params, bool abort); +    /// Checks whether a given input can be accepted. +    bool IsInputAcceptable(const Common::ParamPackage& params) const; +      /// Handle mouse button press events.      void mousePressEvent(QMouseEvent* event) override; @@ -98,8 +101,8 @@ private:      /// Update UI to reflect current configuration.      void UpdateUI(); -    /// Update the controller selection combobox -    void UpdateControllerCombobox(); +    /// Update the available input devices. +    void UpdateInputDevices();      /// Update the current controller icon.      void UpdateControllerIcon(); @@ -164,7 +167,7 @@ private:      bool want_keyboard_mouse = false;      /// List of physical devices users can map with. If a SDL backed device is selected, then you -    /// can usue this device to get a default mapping. +    /// can use this device to get a default mapping.      std::vector<Common::ParamPackage> input_devices;      /// Bottom row is where console wide settings are held, and its "owned" by the parent  | 
