mirror of https://github.com/PCSX2/pcsx2.git
Qt: Add option to pause when controller is disconnected
This commit is contained in:
parent
b9d7b63b32
commit
f084e76f36
|
@ -218,11 +218,11 @@ std::optional<WindowInfo> Host::GetTopLevelWindowInfo()
|
||||||
return GSRunner::GetPlatformWindowInfo();
|
return GSRunner::GetPlatformWindowInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name)
|
void Host::OnInputDeviceConnected(const std::string_view identifier, const std::string_view device_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
|
void Host::OnInputDeviceDisconnected(const InputBindingKey key, const std::string_view identifier)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -424,6 +424,7 @@ void MainWindow::connectSignals()
|
||||||
void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
||||||
{
|
{
|
||||||
connect(thread, &EmuThread::messageConfirmed, this, &MainWindow::confirmMessage, Qt::BlockingQueuedConnection);
|
connect(thread, &EmuThread::messageConfirmed, this, &MainWindow::confirmMessage, Qt::BlockingQueuedConnection);
|
||||||
|
connect(thread, &EmuThread::statusMessage, this, &MainWindow::onStatusMessage);
|
||||||
connect(thread, &EmuThread::onAcquireRenderWindowRequested, this, &MainWindow::acquireRenderWindow, Qt::BlockingQueuedConnection);
|
connect(thread, &EmuThread::onAcquireRenderWindowRequested, this, &MainWindow::acquireRenderWindow, Qt::BlockingQueuedConnection);
|
||||||
connect(thread, &EmuThread::onReleaseRenderWindowRequested, this, &MainWindow::releaseRenderWindow, Qt::BlockingQueuedConnection);
|
connect(thread, &EmuThread::onReleaseRenderWindowRequested, this, &MainWindow::releaseRenderWindow, Qt::BlockingQueuedConnection);
|
||||||
connect(thread, &EmuThread::onResizeRenderWindowRequested, this, &MainWindow::displayResizeRequested);
|
connect(thread, &EmuThread::onResizeRenderWindowRequested, this, &MainWindow::displayResizeRequested);
|
||||||
|
@ -438,7 +439,6 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
|
||||||
connect(thread, &EmuThread::onCaptureStarted, this, &MainWindow::onCaptureStarted);
|
connect(thread, &EmuThread::onCaptureStarted, this, &MainWindow::onCaptureStarted);
|
||||||
connect(thread, &EmuThread::onCaptureStopped, this, &MainWindow::onCaptureStopped);
|
connect(thread, &EmuThread::onCaptureStopped, this, &MainWindow::onCaptureStopped);
|
||||||
connect(thread, &EmuThread::onAchievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
|
connect(thread, &EmuThread::onAchievementsLoginRequested, this, &MainWindow::onAchievementsLoginRequested);
|
||||||
connect(thread, &EmuThread::onAchievementsLoginSucceeded, this, &MainWindow::onAchievementsLoginSucceeded);
|
|
||||||
connect(thread, &EmuThread::onAchievementsHardcoreModeChanged, this, &MainWindow::onAchievementsHardcoreModeChanged);
|
connect(thread, &EmuThread::onAchievementsHardcoreModeChanged, this, &MainWindow::onAchievementsHardcoreModeChanged);
|
||||||
connect(thread, &EmuThread::onCoverDownloaderOpenRequested, this, &MainWindow::onToolsCoverDownloaderTriggered);
|
connect(thread, &EmuThread::onCoverDownloaderOpenRequested, this, &MainWindow::onToolsCoverDownloaderTriggered);
|
||||||
connect(thread, &EmuThread::onCreateMemoryCardOpenRequested, this, &MainWindow::onCreateMemoryCardOpenRequested);
|
connect(thread, &EmuThread::onCreateMemoryCardOpenRequested, this, &MainWindow::onCreateMemoryCardOpenRequested);
|
||||||
|
@ -763,13 +763,6 @@ void MainWindow::onAchievementsLoginRequested(Achievements::LoginRequestReason r
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onAchievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points, quint32 unread_messages)
|
|
||||||
{
|
|
||||||
const QString message =
|
|
||||||
tr("RA: Logged in as %1 (%2 pts, softcore: %3 pts). %4 unread messages.").arg(display_name).arg(points).arg(sc_points).arg(unread_messages);
|
|
||||||
m_ui.statusBar->showMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onAchievementsHardcoreModeChanged(bool enabled)
|
void MainWindow::onAchievementsHardcoreModeChanged(bool enabled)
|
||||||
{
|
{
|
||||||
// disable debugger while hardcore mode is active
|
// disable debugger while hardcore mode is active
|
||||||
|
@ -1143,6 +1136,11 @@ bool MainWindow::confirmMessage(const QString& title, const QString& message)
|
||||||
return (QMessageBox::question(this, title, message) == QMessageBox::Yes);
|
return (QMessageBox::question(this, title, message) == QMessageBox::Yes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onStatusMessage(const QString& message)
|
||||||
|
{
|
||||||
|
m_ui.statusBar->showMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::runOnUIThread(const std::function<void()>& func)
|
void MainWindow::runOnUIThread(const std::function<void()>& func)
|
||||||
{
|
{
|
||||||
func();
|
func();
|
||||||
|
|
|
@ -110,6 +110,8 @@ public Q_SLOTS:
|
||||||
void cancelGameListRefresh();
|
void cancelGameListRefresh();
|
||||||
void reportError(const QString& title, const QString& message);
|
void reportError(const QString& title, const QString& message);
|
||||||
bool confirmMessage(const QString& title, const QString& message);
|
bool confirmMessage(const QString& title, const QString& message);
|
||||||
|
void onStatusMessage(const QString& message);
|
||||||
|
|
||||||
void runOnUIThread(const std::function<void()>& func);
|
void runOnUIThread(const std::function<void()>& func);
|
||||||
void requestReset();
|
void requestReset();
|
||||||
bool requestShutdown(bool allow_confirm = true, bool allow_save_to_state = true, bool default_save_to_state = true);
|
bool requestShutdown(bool allow_confirm = true, bool allow_save_to_state = true, bool default_save_to_state = true);
|
||||||
|
@ -190,7 +192,6 @@ private Q_SLOTS:
|
||||||
void onCaptureStopped();
|
void onCaptureStopped();
|
||||||
|
|
||||||
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||||
void onAchievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points, quint32 unread_messages);
|
|
||||||
void onAchievementsHardcoreModeChanged(bool enabled);
|
void onAchievementsHardcoreModeChanged(bool enabled);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1107,7 +1107,14 @@ void Host::OnAchievementsLoginRequested(Achievements::LoginRequestReason reason)
|
||||||
|
|
||||||
void Host::OnAchievementsLoginSuccess(const char* username, u32 points, u32 sc_points, u32 unread_messages)
|
void Host::OnAchievementsLoginSuccess(const char* username, u32 points, u32 sc_points, u32 unread_messages)
|
||||||
{
|
{
|
||||||
emit g_emu_thread->onAchievementsLoginSucceeded(QString::fromUtf8(username), points, sc_points, unread_messages);
|
const QString message =
|
||||||
|
qApp->translate("QtHost", "RA: Logged in as %1 (%2 pts, softcore: %3 pts). %4 unread messages.")
|
||||||
|
.arg(QString::fromUtf8(username))
|
||||||
|
.arg(points)
|
||||||
|
.arg(sc_points)
|
||||||
|
.arg(unread_messages);
|
||||||
|
|
||||||
|
emit g_emu_thread->statusMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnAchievementsRefreshed()
|
void Host::OnAchievementsRefreshed()
|
||||||
|
@ -1671,15 +1678,44 @@ std::optional<WindowInfo> Host::GetTopLevelWindowInfo()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name)
|
void Host::OnInputDeviceConnected(const std::string_view identifier, const std::string_view device_name)
|
||||||
{
|
{
|
||||||
emit g_emu_thread->onInputDeviceConnected(identifier.empty() ? QString() : QString::fromUtf8(identifier.data(), identifier.size()),
|
emit g_emu_thread->onInputDeviceConnected(identifier.empty() ? QString() : QString::fromUtf8(identifier.data(), identifier.size()),
|
||||||
device_name.empty() ? QString() : QString::fromUtf8(device_name.data(), device_name.size()));
|
device_name.empty() ? QString() : QString::fromUtf8(device_name.data(), device_name.size()));
|
||||||
|
|
||||||
|
|
||||||
|
if (VMManager::HasValidVM() || g_emu_thread->isRunningFullscreenUI())
|
||||||
|
{
|
||||||
|
Host::AddIconOSDMessage(fmt::format("controller_connected_{}", identifier), ICON_FA_GAMEPAD,
|
||||||
|
fmt::format(TRANSLATE_FS("QtHost", "Controller {} connected."), identifier),
|
||||||
|
Host::OSD_INFO_DURATION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
|
void Host::OnInputDeviceDisconnected(const InputBindingKey key, const std::string_view identifier)
|
||||||
{
|
{
|
||||||
emit g_emu_thread->onInputDeviceDisconnected(identifier.empty() ? QString() : QString::fromUtf8(identifier.data(), identifier.size()));
|
emit g_emu_thread->onInputDeviceDisconnected(identifier.empty() ? QString() : QString::fromUtf8(identifier.data(), identifier.size()));
|
||||||
|
|
||||||
|
if (VMManager::GetState() == VMState::Running && Host::GetBoolSettingValue("UI", "PauseOnControllerDisconnection", false) &&
|
||||||
|
InputManager::HasAnyBindingsForSource(key))
|
||||||
|
{
|
||||||
|
std::string message =
|
||||||
|
fmt::format(TRANSLATE_FS("QtHost", "System paused because controller {} was disconnected."), identifier);
|
||||||
|
Host::RunOnCPUThread([message = QString::fromStdString(message)]() {
|
||||||
|
VMManager::SetPaused(true);
|
||||||
|
|
||||||
|
// has to be done after pause, otherwise pause message takes precedence
|
||||||
|
emit g_emu_thread->statusMessage(message);
|
||||||
|
});
|
||||||
|
Host::AddIconOSDMessage(fmt::format("controller_connected_{}", identifier), ICON_FA_GAMEPAD, std::move(message),
|
||||||
|
Host::OSD_WARNING_DURATION);
|
||||||
|
}
|
||||||
|
else if (VMManager::HasValidVM() || g_emu_thread->isRunningFullscreenUI())
|
||||||
|
{
|
||||||
|
Host::AddIconOSDMessage(fmt::format("controller_connected_{}", identifier), ICON_FA_GAMEPAD,
|
||||||
|
fmt::format(TRANSLATE_FS("QtHost", "Controller {} disconnected."), identifier),
|
||||||
|
Host::OSD_INFO_DURATION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
|
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
|
||||||
|
|
|
@ -117,6 +117,7 @@ public Q_SLOTS:
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
bool messageConfirmed(const QString& title, const QString& message);
|
bool messageConfirmed(const QString& title, const QString& message);
|
||||||
|
void statusMessage(const QString& message);
|
||||||
|
|
||||||
std::optional<WindowInfo> onAcquireRenderWindowRequested(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
|
std::optional<WindowInfo> onAcquireRenderWindowRequested(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
|
||||||
void onResizeRenderWindowRequested(qint32 width, qint32 height);
|
void onResizeRenderWindowRequested(qint32 width, qint32 height);
|
||||||
|
@ -161,9 +162,6 @@ Q_SIGNALS:
|
||||||
/// Called when achievements login is requested.
|
/// Called when achievements login is requested.
|
||||||
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||||
|
|
||||||
/// Called when achievements login succeeds. Also happens on startup.
|
|
||||||
void onAchievementsLoginSucceeded(const QString& display_name, quint32 points, quint32 sc_points, quint32 unread_messages);
|
|
||||||
|
|
||||||
/// Called when achievements are reloaded/refreshed (e.g. game change, login, option change).
|
/// Called when achievements are reloaded/refreshed (e.g. game change, login, option change).
|
||||||
void onAchievementsRefreshed(quint32 id, const QString& game_info_string);
|
void onAchievementsRefreshed(quint32 id, const QString& game_info_string);
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
const char* InterfaceSettingsWidget::THEME_NAMES[] = {
|
const char* InterfaceSettingsWidget::THEME_NAMES[] = {
|
||||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Native"),
|
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Native"),
|
||||||
//: Ignore what Crowdin says in this string about "[Light]/[Dark]" being untouchable here, these are not variables in this case and must be translated.
|
//: Ignore what Crowdin says in this string about "[Light]/[Dark]" being untouchable here, these are not variables in this case and must be translated.
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Classic Windows"),
|
QT_TRANSLATE_NOOP("InterfaceSettingsWidget", "Classic Windows"),
|
||||||
#endif
|
#endif
|
||||||
|
@ -75,6 +75,7 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.confirmShutdown, "UI", "ConfirmShutdown", true);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.confirmShutdown, "UI", "ConfirmShutdown", true);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.saveStateOnShutdown, "EmuCore", "SaveStateOnShutdown", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.saveStateOnShutdown, "EmuCore", "SaveStateOnShutdown", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnFocusLoss, "UI", "PauseOnFocusLoss", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnFocusLoss, "UI", "PauseOnFocusLoss", false);
|
||||||
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.pauseOnControllerDisconnection, "UI", "PauseOnControllerDisconnection", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.backupSaveStates, "EmuCore", "BackupSavestate", true);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.backupSaveStates, "EmuCore", "BackupSavestate", true);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.discordPresence, "EmuCore", "EnableDiscordPresence", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.discordPresence, "EmuCore", "EnableDiscordPresence", false);
|
||||||
|
|
||||||
|
@ -147,6 +148,8 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget
|
||||||
dialog->registerWidgetHelp(m_ui.pauseOnFocusLoss, tr("Pause On Focus Loss"), tr("Unchecked"),
|
dialog->registerWidgetHelp(m_ui.pauseOnFocusLoss, tr("Pause On Focus Loss"), tr("Unchecked"),
|
||||||
tr("Pauses the emulator when you minimize the window or switch to another application, "
|
tr("Pauses the emulator when you minimize the window or switch to another application, "
|
||||||
"and unpauses when you switch back."));
|
"and unpauses when you switch back."));
|
||||||
|
dialog->registerWidgetHelp(m_ui.pauseOnControllerDisconnection, tr("Pause On Controller Disconnection"),
|
||||||
|
tr("Unchecked"), tr("Pauses the emulator when a controller with bindings is disconnected."));
|
||||||
dialog->registerWidgetHelp(m_ui.backupSaveStates, tr("Create Save State Backups"), tr("Checked"),
|
dialog->registerWidgetHelp(m_ui.backupSaveStates, tr("Create Save State Backups"), tr("Checked"),
|
||||||
//: Do not translate the ".backup" extension.
|
//: Do not translate the ".backup" extension.
|
||||||
tr("Creates a backup copy of a save state if it already exists when the save is created. The backup copy has a .backup suffix."));
|
tr("Creates a backup copy of a save state if it already exists when the save is created. The backup copy has a .backup suffix."));
|
||||||
|
@ -164,10 +167,10 @@ InterfaceSettingsWidget::InterfaceSettingsWidget(SettingsWindow* dialog, QWidget
|
||||||
m_ui.discordPresence, tr("Enable Discord Presence"), tr("Unchecked"),
|
m_ui.discordPresence, tr("Enable Discord Presence"), tr("Unchecked"),
|
||||||
tr("Shows the game you are currently playing as part of your profile in Discord."));
|
tr("Shows the game you are currently playing as part of your profile in Discord."));
|
||||||
dialog->registerWidgetHelp(
|
dialog->registerWidgetHelp(
|
||||||
m_ui.doubleClickTogglesFullscreen, tr("Double-Click Toggles Fullscreen"), tr("Checked"),
|
m_ui.doubleClickTogglesFullscreen, tr("Double-Click Toggles Fullscreen"), tr("Checked"),
|
||||||
tr("Allows switching in and out of fullscreen mode by double-clicking the game window."));
|
tr("Allows switching in and out of fullscreen mode by double-clicking the game window."));
|
||||||
dialog->registerWidgetHelp(
|
dialog->registerWidgetHelp(
|
||||||
m_ui.disableWindowResizing, tr("Disable Window Resizing"), tr("Unchecked"),
|
m_ui.disableWindowResizing, tr("Disable Window Resizing"), tr("Unchecked"),
|
||||||
tr("Prevents the main window from being resized."));
|
tr("Prevents the main window from being resized."));
|
||||||
|
|
||||||
onRenderToSeparateWindowChanged();
|
onRenderToSeparateWindowChanged();
|
||||||
|
|
|
@ -29,28 +29,28 @@
|
||||||
<string>Behaviour</string>
|
<string>Behaviour</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="formLayout_4">
|
<layout class="QGridLayout" name="formLayout_4">
|
||||||
<item row="3" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QCheckBox" name="pauseOnFocusLoss">
|
|
||||||
<property name="text">
|
|
||||||
<string>Pause On Focus Loss</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QCheckBox" name="inhibitScreensaver">
|
|
||||||
<property name="text">
|
|
||||||
<string>Inhibit Screensaver</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QCheckBox" name="saveStateOnShutdown">
|
<widget class="QCheckBox" name="saveStateOnShutdown">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Save State On Shutdown</string>
|
<string>Save State On Shutdown</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="inhibitScreensaver">
|
||||||
|
<property name="text">
|
||||||
|
<string>Inhibit Screensaver</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QCheckBox" name="confirmShutdown">
|
||||||
|
<property name="text">
|
||||||
|
<string>Confirm Shutdown</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
<widget class="QCheckBox" name="pauseOnStart">
|
<widget class="QCheckBox" name="pauseOnStart">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Pause On Start</string>
|
<string>Pause On Start</string>
|
||||||
|
@ -58,26 +58,33 @@
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QCheckBox" name="confirmShutdown">
|
<widget class="QCheckBox" name="pauseOnFocusLoss">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Confirm Shutdown</string>
|
<string>Pause On Focus Loss</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="2" column="1">
|
||||||
<widget class="QCheckBox" name="backupSaveStates">
|
<widget class="QCheckBox" name="pauseOnControllerDisconnection">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Create Save State Backups</string>
|
<string>Pause On Controller Disconnection</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="3" column="1">
|
||||||
<widget class="QCheckBox" name="discordPresence">
|
<widget class="QCheckBox" name="discordPresence">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable Discord Presence</string>
|
<string>Enable Discord Presence</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="backupSaveStates">
|
||||||
|
<property name="text">
|
||||||
|
<string>Create Save State Backups</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -215,7 +222,7 @@
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Orientation::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" stdset="0">
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
|
|
|
@ -3101,6 +3101,8 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_EYE, "Pause On Focus Loss"),
|
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_EYE, "Pause On Focus Loss"),
|
||||||
FSUI_CSTR("Pauses the emulator when you minimize the window or switch to another application, and unpauses when you switch back."),
|
FSUI_CSTR("Pauses the emulator when you minimize the window or switch to another application, and unpauses when you switch back."),
|
||||||
"UI", "PauseOnFocusLoss", false);
|
"UI", "PauseOnFocusLoss", false);
|
||||||
|
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_GAMEPAD, "Pause On Controller Disconnection"),
|
||||||
|
FSUI_CSTR("Pauses the emulator when a controller with bindings is disconnected."), "UI", "PauseOnControllerDisconnection", false);
|
||||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_LIST_ALT, "Pause On Menu"),
|
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_LIST_ALT, "Pause On Menu"),
|
||||||
FSUI_CSTR("Pauses the emulator when you open the quick menu, and unpauses when you close it."), "UI", "PauseOnMenu", true);
|
FSUI_CSTR("Pauses the emulator when you open the quick menu, and unpauses when you close it."), "UI", "PauseOnMenu", true);
|
||||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_POWER_OFF, "Confirm Shutdown"),
|
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_POWER_OFF, "Confirm Shutdown"),
|
||||||
|
@ -6898,6 +6900,7 @@ TRANSLATE_NOOP("FullscreenUI", "Prevents the screen saver from activating and th
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Shows the game you are currently playing as part of your profile on Discord.");
|
TRANSLATE_NOOP("FullscreenUI", "Shows the game you are currently playing as part of your profile on Discord.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when a game is started.");
|
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when a game is started.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when you minimize the window or switch to another application, and unpauses when you switch back.");
|
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when you minimize the window or switch to another application, and unpauses when you switch back.");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when a controller with bindings is disconnected.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when you open the quick menu, and unpauses when you close it.");
|
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when you open the quick menu, and unpauses when you close it.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Determines whether a prompt will be displayed to confirm shutting down the emulator/game when the hotkey is pressed.");
|
TRANSLATE_NOOP("FullscreenUI", "Determines whether a prompt will be displayed to confirm shutting down the emulator/game when the hotkey is pressed.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Automatically saves the emulator state when powering down or exiting. You can then resume directly from where you left off next time.");
|
TRANSLATE_NOOP("FullscreenUI", "Automatically saves the emulator state when powering down or exiting. You can then resume directly from where you left off next time.");
|
||||||
|
@ -7140,10 +7143,11 @@ TRANSLATE_NOOP("FullscreenUI", "Synchronization");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Changes when SPU samples are generated relative to system emulation.");
|
TRANSLATE_NOOP("FullscreenUI", "Changes when SPU samples are generated relative to system emulation.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Buffer Size");
|
TRANSLATE_NOOP("FullscreenUI", "Buffer Size");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Determines the amount of audio buffered before being pulled by the host API.");
|
TRANSLATE_NOOP("FullscreenUI", "Determines the amount of audio buffered before being pulled by the host API.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Minimal Output Latency");
|
TRANSLATE_NOOP("FullscreenUI", "%d ms");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "When enabled, the minimum supported output latency will be used for the host API.");
|
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Output Latency");
|
TRANSLATE_NOOP("FullscreenUI", "Output Latency");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Determines how much latency there is between the audio being picked up by the host API, and played through speakers.");
|
TRANSLATE_NOOP("FullscreenUI", "Determines how much latency there is between the audio being picked up by the host API, and played through speakers.");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "Minimal Output Latency");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "When enabled, the minimum supported output latency will be used for the host API.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Settings and Operations");
|
TRANSLATE_NOOP("FullscreenUI", "Settings and Operations");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Creates a new memory card file or folder.");
|
TRANSLATE_NOOP("FullscreenUI", "Creates a new memory card file or folder.");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Simulates a larger memory card by filtering saves only to the current game.");
|
TRANSLATE_NOOP("FullscreenUI", "Simulates a larger memory card by filtering saves only to the current game.");
|
||||||
|
@ -7561,6 +7565,7 @@ TRANSLATE_NOOP("FullscreenUI", "Inhibit Screensaver");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Enable Discord Presence");
|
TRANSLATE_NOOP("FullscreenUI", "Enable Discord Presence");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Pause On Start");
|
TRANSLATE_NOOP("FullscreenUI", "Pause On Start");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Pause On Focus Loss");
|
TRANSLATE_NOOP("FullscreenUI", "Pause On Focus Loss");
|
||||||
|
TRANSLATE_NOOP("FullscreenUI", "Pause On Controller Disconnection");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Pause On Menu");
|
TRANSLATE_NOOP("FullscreenUI", "Pause On Menu");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Confirm Shutdown");
|
TRANSLATE_NOOP("FullscreenUI", "Confirm Shutdown");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Save State On Shutdown");
|
TRANSLATE_NOOP("FullscreenUI", "Save State On Shutdown");
|
||||||
|
@ -7683,6 +7688,5 @@ TRANSLATE_NOOP("FullscreenUI", "Game not loaded or no RetroAchievements availabl
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Card Enabled");
|
TRANSLATE_NOOP("FullscreenUI", "Card Enabled");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Card Name");
|
TRANSLATE_NOOP("FullscreenUI", "Card Name");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "Eject Card");
|
TRANSLATE_NOOP("FullscreenUI", "Eject Card");
|
||||||
TRANSLATE_NOOP("FullscreenUI", "%d ms");
|
|
||||||
// TRANSLATION-STRING-AREA-END
|
// TRANSLATION-STRING-AREA-END
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -145,7 +145,9 @@ void DInputSource::Shutdown()
|
||||||
{
|
{
|
||||||
while (!m_controllers.empty())
|
while (!m_controllers.empty())
|
||||||
{
|
{
|
||||||
InputManager::OnInputDeviceDisconnected(GetDeviceIdentifier(static_cast<u32>(m_controllers.size() - 1)));
|
const u32 index = static_cast<u32>(m_controllers.size() - 1);
|
||||||
|
InputManager::OnInputDeviceDisconnected({{.source_type = InputSourceType::DInput, .source_index = index}},
|
||||||
|
GetDeviceIdentifier(index));
|
||||||
m_controllers.pop_back();
|
m_controllers.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,7 +247,9 @@ void DInputSource::PollEvents()
|
||||||
|
|
||||||
if (hr != DI_OK)
|
if (hr != DI_OK)
|
||||||
{
|
{
|
||||||
InputManager::OnInputDeviceDisconnected(GetDeviceIdentifier(static_cast<u32>(i)));
|
InputManager::OnInputDeviceDisconnected(
|
||||||
|
{{.source_type = InputSourceType::DInput, .source_index = static_cast<u32>(i)}},
|
||||||
|
GetDeviceIdentifier(static_cast<u32>(i)));
|
||||||
m_controllers.erase(m_controllers.begin() + i);
|
m_controllers.erase(m_controllers.begin() + i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1199,7 +1199,7 @@ void InputManager::UpdatePointerRelativeDelta(u32 index, InputPointerAxis axis,
|
||||||
ImGuiManager::UpdateMousePosition(s_host_pointer_positions[0][0], s_host_pointer_positions[0][1]);
|
ImGuiManager::UpdateMousePosition(s_host_pointer_positions[0][0], s_host_pointer_positions[0][1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name)
|
void InputManager::OnInputDeviceConnected(const std::string_view identifier, const std::string_view device_name)
|
||||||
{
|
{
|
||||||
if (VMManager::HasValidVM())
|
if (VMManager::HasValidVM())
|
||||||
USB::InputDeviceConnected(identifier);
|
USB::InputDeviceConnected(identifier);
|
||||||
|
@ -1207,12 +1207,12 @@ void InputManager::OnInputDeviceConnected(const std::string_view& identifier, co
|
||||||
Host::OnInputDeviceConnected(identifier, device_name);
|
Host::OnInputDeviceConnected(identifier, device_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputManager::OnInputDeviceDisconnected(const std::string_view& identifier)
|
void InputManager::OnInputDeviceDisconnected(const InputBindingKey key, const std::string_view identifier)
|
||||||
{
|
{
|
||||||
if (VMManager::HasValidVM())
|
if (VMManager::HasValidVM())
|
||||||
USB::InputDeviceDisconnected(identifier);
|
USB::InputDeviceDisconnected(identifier);
|
||||||
|
|
||||||
Host::OnInputDeviceDisconnected(identifier);
|
Host::OnInputDeviceDisconnected(key, identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
|
@ -289,10 +289,10 @@ namespace InputManager
|
||||||
void UpdateHostMouseMode();
|
void UpdateHostMouseMode();
|
||||||
|
|
||||||
/// Called when a new input device is connected.
|
/// Called when a new input device is connected.
|
||||||
void OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name);
|
void OnInputDeviceConnected(const std::string_view identifier, const std::string_view device_name);
|
||||||
|
|
||||||
/// Called when an input device is disconnected.
|
/// Called when an input device is disconnected.
|
||||||
void OnInputDeviceDisconnected(const std::string_view& identifier);
|
void OnInputDeviceDisconnected(const InputBindingKey key, const std::string_view identifier);
|
||||||
} // namespace InputManager
|
} // namespace InputManager
|
||||||
|
|
||||||
namespace Host
|
namespace Host
|
||||||
|
@ -301,10 +301,10 @@ namespace Host
|
||||||
std::optional<WindowInfo> GetTopLevelWindowInfo();
|
std::optional<WindowInfo> GetTopLevelWindowInfo();
|
||||||
|
|
||||||
/// Called when a new input device is connected.
|
/// Called when a new input device is connected.
|
||||||
void OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name);
|
void OnInputDeviceConnected(const std::string_view identifier, const std::string_view device_name);
|
||||||
|
|
||||||
/// Called when an input device is disconnected.
|
/// Called when an input device is disconnected.
|
||||||
void OnInputDeviceDisconnected(const std::string_view& identifier);
|
void OnInputDeviceDisconnected(const InputBindingKey key, const std::string_view identifier);
|
||||||
|
|
||||||
/// Enables relative mouse mode in the host, and/or hides the cursor.
|
/// Enables relative mouse mode in the host, and/or hides the cursor.
|
||||||
void SetMouseMode(bool relative_mode, bool hide_cursor);
|
void SetMouseMode(bool relative_mode, bool hide_cursor);
|
||||||
|
|
|
@ -657,7 +657,7 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
|
||||||
|
|
||||||
if (!gcontroller && !joystick)
|
if (!gcontroller && !joystick)
|
||||||
{
|
{
|
||||||
Console.Error("(SDLInputSource) Failed to open controller %d", index);
|
ERROR_LOG("(SDLInputSource) Failed to open controller {}", index);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,7 +667,7 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
|
||||||
{
|
{
|
||||||
if (it->joystick_id == joystick_id)
|
if (it->joystick_id == joystick_id)
|
||||||
{
|
{
|
||||||
Console.Error("(SDLInputSource) Controller %d, instance %d, player %d already connected, ignoring.", index, joystick_id, player_id);
|
ERROR_LOG("(SDLInputSource) Controller {}, instance {}, player {} already connected, ignoring.", index, joystick_id, player_id);
|
||||||
if (gcontroller)
|
if (gcontroller)
|
||||||
SDL_GameControllerClose(gcontroller);
|
SDL_GameControllerClose(gcontroller);
|
||||||
else
|
else
|
||||||
|
@ -680,8 +680,8 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
|
||||||
if (player_id < 0 || GetControllerDataForPlayerId(player_id) != m_controllers.end())
|
if (player_id < 0 || GetControllerDataForPlayerId(player_id) != m_controllers.end())
|
||||||
{
|
{
|
||||||
const int free_player_id = GetFreePlayerId();
|
const int free_player_id = GetFreePlayerId();
|
||||||
Console.Warning("(SDLInputSource) Controller %d (joystick %d) returned player ID %d, which is invalid or in "
|
WARNING_LOG("(SDLInputSource) Controller {} (joystick {}) returned player ID {}, which is invalid or in "
|
||||||
"use. Using ID %d instead.",
|
"use. Using ID {} instead.",
|
||||||
index, joystick_id, player_id, free_player_id);
|
index, joystick_id, player_id, free_player_id);
|
||||||
player_id = free_player_id;
|
player_id = free_player_id;
|
||||||
}
|
}
|
||||||
|
@ -690,7 +690,7 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
|
||||||
if (!name)
|
if (!name)
|
||||||
name = "Unknown Device";
|
name = "Unknown Device";
|
||||||
|
|
||||||
Console.WriteLn("(SDLInputSource) Opened %s %d (instance id %d, player id %d): %s", is_gamecontroller ? "game controller" : "joystick",
|
INFO_LOG("(SDLInputSource) Opened {} {} (instance id {}, player id {}): {}", is_gamecontroller ? "game controller" : "joystick",
|
||||||
index, joystick_id, player_id, name);
|
index, joystick_id, player_id, name);
|
||||||
|
|
||||||
ControllerData cd = {};
|
ControllerData cd = {};
|
||||||
|
@ -717,7 +717,7 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
|
||||||
for (size_t i = 0; i < std::size(s_sdl_button_names); i++)
|
for (size_t i = 0; i < std::size(s_sdl_button_names); i++)
|
||||||
mark_bind(SDL_GameControllerGetBindForButton(gcontroller, static_cast<SDL_GameControllerButton>(i)));
|
mark_bind(SDL_GameControllerGetBindForButton(gcontroller, static_cast<SDL_GameControllerButton>(i)));
|
||||||
|
|
||||||
Console.WriteLn("(SDLInputSource) Controller %d has %d axes and %d buttons", player_id, num_axes, num_buttons);
|
INFO_LOG("(SDLInputSource) Controller {} has {} axes and {} buttons", player_id, num_axes, num_buttons);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -726,14 +726,14 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
|
||||||
if (num_hats > 0)
|
if (num_hats > 0)
|
||||||
cd.last_hat_state.resize(static_cast<size_t>(num_hats), u8(0));
|
cd.last_hat_state.resize(static_cast<size_t>(num_hats), u8(0));
|
||||||
|
|
||||||
Console.WriteLn("(SDLInputSource) Joystick %d has %d axes, %d buttons and %d hats", player_id,
|
INFO_LOG("(SDLInputSource) Joystick {} has {} axes, {} buttons and {} hats", player_id,
|
||||||
SDL_JoystickNumAxes(joystick), SDL_JoystickNumButtons(joystick), num_hats);
|
SDL_JoystickNumAxes(joystick), SDL_JoystickNumButtons(joystick), num_hats);
|
||||||
}
|
}
|
||||||
|
|
||||||
cd.use_game_controller_rumble = (gcontroller && SDL_GameControllerRumble(gcontroller, 0, 0, 0) == 0);
|
cd.use_game_controller_rumble = (gcontroller && SDL_GameControllerRumble(gcontroller, 0, 0, 0) == 0);
|
||||||
if (cd.use_game_controller_rumble)
|
if (cd.use_game_controller_rumble)
|
||||||
{
|
{
|
||||||
Console.WriteLn("(SDLInputSource) Rumble is supported on '%s' via gamecontroller", name);
|
INFO_LOG("(SDLInputSource) Rumble is supported on '{}' via gamecontroller", name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -752,25 +752,25 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.Error("(SDLInputSource) Failed to create haptic left/right effect: %s", SDL_GetError());
|
ERROR_LOG("(SDLInputSource) Failed to create haptic left/right effect: {}", SDL_GetError());
|
||||||
if (SDL_HapticRumbleSupported(haptic) && SDL_HapticRumbleInit(haptic) != 0)
|
if (SDL_HapticRumbleSupported(haptic) && SDL_HapticRumbleInit(haptic) != 0)
|
||||||
{
|
{
|
||||||
cd.haptic = haptic;
|
cd.haptic = haptic;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.Error("(SDLInputSource) No haptic rumble supported: %s", SDL_GetError());
|
ERROR_LOG("(SDLInputSource) No haptic rumble supported: {}", SDL_GetError());
|
||||||
SDL_HapticClose(haptic);
|
SDL_HapticClose(haptic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cd.haptic)
|
if (cd.haptic)
|
||||||
Console.WriteLn("(SDLInputSource) Rumble is supported on '%s' via haptic", name);
|
INFO_LOG("(SDLInputSource) Rumble is supported on '{}' via haptic", name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cd.haptic && !cd.use_game_controller_rumble)
|
if (!cd.haptic && !cd.use_game_controller_rumble)
|
||||||
Console.Warning("(SDLInputSource) Rumble is not supported on '%s'", name);
|
WARNING_LOG("(SDLInputSource) Rumble is not supported on '{}'", name);
|
||||||
|
|
||||||
if (player_id >= 0 && static_cast<u32>(player_id) < MAX_LED_COLORS && gcontroller && SDL_GameControllerHasLED(gcontroller))
|
if (player_id >= 0 && static_cast<u32>(player_id) < MAX_LED_COLORS && gcontroller && SDL_GameControllerHasLED(gcontroller))
|
||||||
{
|
{
|
||||||
|
@ -779,7 +779,7 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
|
||||||
|
|
||||||
m_controllers.push_back(std::move(cd));
|
m_controllers.push_back(std::move(cd));
|
||||||
|
|
||||||
InputManager::OnInputDeviceConnected(StringUtil::StdStringFromFormat("SDL-%d", player_id), name);
|
InputManager::OnInputDeviceConnected(fmt::format("SDL-{}", player_id), name);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,7 +789,9 @@ bool SDLInputSource::CloseDevice(int joystick_index)
|
||||||
if (it == m_controllers.end())
|
if (it == m_controllers.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
InputManager::OnInputDeviceDisconnected(StringUtil::StdStringFromFormat("SDL-%d", it->player_id));
|
InputManager::OnInputDeviceDisconnected(
|
||||||
|
{{.source_type = InputSourceType::SDL, .source_index = static_cast<u32>(it->player_id)}},
|
||||||
|
fmt::format("SDL-{}", it->player_id));
|
||||||
|
|
||||||
if (it->haptic)
|
if (it->haptic)
|
||||||
SDL_HapticClose(it->haptic);
|
SDL_HapticClose(it->haptic);
|
||||||
|
|
|
@ -226,7 +226,7 @@ void XInputSource::PollEvents()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (result != ERROR_DEVICE_NOT_CONNECTED)
|
if (result != ERROR_DEVICE_NOT_CONNECTED)
|
||||||
Console.Warning("XInputGetState(%u) failed: 0x%08X / 0x%08X", i, result, GetLastError());
|
WARNING_LOG("XInputGetState({}) failed: 0x{:08X} / 0x{:08X}", i, result, GetLastError());
|
||||||
|
|
||||||
if (was_connected)
|
if (was_connected)
|
||||||
HandleControllerDisconnection(i);
|
HandleControllerDisconnection(i);
|
||||||
|
@ -424,11 +424,11 @@ bool XInputSource::GetGenericBindingMapping(const std::string_view& device, Inpu
|
||||||
|
|
||||||
void XInputSource::HandleControllerConnection(u32 index)
|
void XInputSource::HandleControllerConnection(u32 index)
|
||||||
{
|
{
|
||||||
Console.WriteLn("XInput controller %u connected.", index);
|
INFO_LOG("XInput controller {} connected.", index);
|
||||||
|
|
||||||
XINPUT_CAPABILITIES caps = {};
|
XINPUT_CAPABILITIES caps = {};
|
||||||
if (m_xinput_get_capabilities(index, 0, &caps) != ERROR_SUCCESS)
|
if (m_xinput_get_capabilities(index, 0, &caps) != ERROR_SUCCESS)
|
||||||
Console.Warning("Failed to get XInput capabilities for controller %u", index);
|
WARNING_LOG("Failed to get XInput capabilities for controller {}", index);
|
||||||
|
|
||||||
ControllerData& cd = m_controllers[index];
|
ControllerData& cd = m_controllers[index];
|
||||||
cd.connected = true;
|
cd.connected = true;
|
||||||
|
@ -438,13 +438,17 @@ void XInputSource::HandleControllerConnection(u32 index)
|
||||||
cd.last_state_scp = {};
|
cd.last_state_scp = {};
|
||||||
|
|
||||||
InputManager::OnInputDeviceConnected(
|
InputManager::OnInputDeviceConnected(
|
||||||
StringUtil::StdStringFromFormat("XInput-%u", index), StringUtil::StdStringFromFormat("XInput Controller %u", index));
|
fmt::format("XInput-{}", index), fmt::format("XInput Controller {}", index));
|
||||||
}
|
}
|
||||||
|
|
||||||
void XInputSource::HandleControllerDisconnection(u32 index)
|
void XInputSource::HandleControllerDisconnection(u32 index)
|
||||||
{
|
{
|
||||||
Console.WriteLn("XInput controller %u disconnected.", index);
|
INFO_LOG("XInput controller {} disconnected.", index);
|
||||||
InputManager::OnInputDeviceDisconnected(StringUtil::StdStringFromFormat("XInput-%u", index));
|
InputManager::OnInputDeviceDisconnected({{
|
||||||
|
.source_type = InputSourceType::XInput,
|
||||||
|
.source_index = index,
|
||||||
|
}},
|
||||||
|
fmt::format("XInput-{}", index));
|
||||||
m_controllers[index] = {};
|
m_controllers[index] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,7 +489,7 @@ void XInputSource::CheckForStateChanges(u32 index, const XINPUT_STATE& new_state
|
||||||
{
|
{
|
||||||
const GenericInputBinding generic_key = (button < std::size(s_xinput_generic_binding_button_mapping)) ?
|
const GenericInputBinding generic_key = (button < std::size(s_xinput_generic_binding_button_mapping)) ?
|
||||||
s_xinput_generic_binding_button_mapping[button] :
|
s_xinput_generic_binding_button_mapping[button] :
|
||||||
GenericInputBinding::Unknown;
|
GenericInputBinding::Unknown;
|
||||||
const float value = ((new_button_bits & button_mask) != 0) ? 1.0f : 0.0f;
|
const float value = ((new_button_bits & button_mask) != 0) ? 1.0f : 0.0f;
|
||||||
InputManager::InvokeEvents(MakeGenericControllerButtonKey(InputSourceType::XInput, index, button), value, generic_key);
|
InputManager::InvokeEvents(MakeGenericControllerButtonKey(InputSourceType::XInput, index, button), value, generic_key);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,11 +64,11 @@ std::optional<WindowInfo> Host::GetTopLevelWindowInfo()
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnInputDeviceConnected(const std::string_view& identifier, const std::string_view& device_name)
|
void Host::OnInputDeviceConnected(const std::string_view identifier, const std::string_view device_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
|
void Host::OnInputDeviceDisconnected(const InputBindingKey key, const std::string_view identifier)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue