diff options
Diffstat (limited to 'src/yuzu/main.cpp')
| -rw-r--r-- | src/yuzu/main.cpp | 134 |
1 files changed, 125 insertions, 9 deletions
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index e56fcabff..dc7b343d9 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -1,6 +1,5 @@ -// Copyright 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. +// SPDX-FileCopyrightText: 2014 Citra Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later #include <cinttypes> #include <clocale> @@ -9,6 +8,10 @@ #ifdef __APPLE__ #include <unistd.h> // for chdir #endif +#ifdef __linux__ +#include <csignal> +#include <sys/socket.h> +#endif // VFS includes must be before glad as they will conflict with Windows file api, which uses defines. #include "applets/qt_controller.h" @@ -260,6 +263,10 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) config{std::make_unique<Config>(*system)}, vfs{std::make_shared<FileSys::RealVfsFilesystem>()}, provider{std::make_unique<FileSys::ManualContentProvider>()} { +#ifdef __linux__ + SetupSigInterrupts(); +#endif + Common::Log::Initialize(); LoadTranslation(); @@ -379,6 +386,8 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) SDL_EnableScreenSaver(); #endif + SetupPrepareForSleep(); + Common::Log::Start(); QStringList args = QApplication::arguments(); @@ -463,7 +472,13 @@ GMainWindow::~GMainWindow() { if (render_window->parent() == nullptr) { delete render_window; } + system->GetRoomNetwork().Shutdown(); + +#ifdef __linux__ + ::close(sig_interrupt_fds[0]); + ::close(sig_interrupt_fds[1]); +#endif } void GMainWindow::RegisterMetaTypes() { @@ -1061,12 +1076,26 @@ void GMainWindow::InitializeHotkeys() { [] { Settings::values.audio_muted = !Settings::values.audio_muted; }); connect_shortcut(QStringLiteral("Audio Volume Down"), [] { const auto current_volume = static_cast<int>(Settings::values.volume.GetValue()); - const auto new_volume = std::max(current_volume - 5, 0); + int step = 5; + if (current_volume <= 30) { + step = 2; + } + if (current_volume <= 6) { + step = 1; + } + const auto new_volume = std::max(current_volume - step, 0); Settings::values.volume.SetValue(static_cast<u8>(new_volume)); }); connect_shortcut(QStringLiteral("Audio Volume Up"), [] { const auto current_volume = static_cast<int>(Settings::values.volume.GetValue()); - const auto new_volume = std::min(current_volume + 5, 100); + int step = 5; + if (current_volume < 30) { + step = 2; + } + if (current_volume < 6) { + step = 1; + } + const auto new_volume = std::min(current_volume + step, 100); Settings::values.volume.SetValue(static_cast<u8>(new_volume)); }); connect_shortcut(QStringLiteral("Toggle Framerate Limit"), [] { @@ -1314,6 +1343,43 @@ void GMainWindow::OnDisplayTitleBars(bool show) { } } +void GMainWindow::SetupPrepareForSleep() { +#ifdef __linux__ + auto bus = QDBusConnection::systemBus(); + if (bus.isConnected()) { + const bool success = bus.connect( + QStringLiteral("org.freedesktop.login1"), QStringLiteral("/org/freedesktop/login1"), + QStringLiteral("org.freedesktop.login1.Manager"), QStringLiteral("PrepareForSleep"), + QStringLiteral("b"), this, SLOT(OnPrepareForSleep(bool))); + + if (!success) { + LOG_WARNING(Frontend, "Couldn't register PrepareForSleep signal"); + } + } else { + LOG_WARNING(Frontend, "QDBusConnection system bus is not connected"); + } +#endif // __linux__ +} + +void GMainWindow::OnPrepareForSleep(bool prepare_sleep) { + if (emu_thread == nullptr) { + return; + } + + if (prepare_sleep) { + if (emu_thread->IsRunning()) { + auto_paused = true; + OnPauseGame(); + } + } else { + if (!emu_thread->IsRunning() && auto_paused) { + auto_paused = false; + RequestGameResume(); + OnStartGame(); + } + } +} + #ifdef __linux__ static std::optional<QDBusObjectPath> HoldWakeLockLinux(u32 window_id = 0) { if (!QDBusConnection::sessionBus().isConnected()) { @@ -1353,6 +1419,52 @@ static void ReleaseWakeLockLinux(QDBusObjectPath lock) { QString::fromLatin1("org.freedesktop.portal.Request")); unlocker.call(QString::fromLatin1("Close")); } + +std::array<int, 3> GMainWindow::sig_interrupt_fds{0, 0, 0}; + +void GMainWindow::SetupSigInterrupts() { + if (sig_interrupt_fds[2] == 1) { + return; + } + socketpair(AF_UNIX, SOCK_STREAM, 0, sig_interrupt_fds.data()); + sig_interrupt_fds[2] = 1; + + struct sigaction sa; + sa.sa_handler = &GMainWindow::HandleSigInterrupt; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESETHAND; + sigaction(SIGINT, &sa, nullptr); + sigaction(SIGTERM, &sa, nullptr); + + sig_interrupt_notifier = new QSocketNotifier(sig_interrupt_fds[1], QSocketNotifier::Read, this); + connect(sig_interrupt_notifier, &QSocketNotifier::activated, this, + &GMainWindow::OnSigInterruptNotifierActivated); + connect(this, &GMainWindow::SigInterrupt, this, &GMainWindow::close); +} + +void GMainWindow::HandleSigInterrupt(int sig) { + if (sig == SIGINT) { + exit(1); + } + + // Calling into Qt directly from a signal handler is not safe, + // so wake up a QSocketNotifier with this hacky write call instead. + char a = 1; + int ret = write(sig_interrupt_fds[0], &a, sizeof(a)); + (void)ret; +} + +void GMainWindow::OnSigInterruptNotifierActivated() { + sig_interrupt_notifier->setEnabled(false); + + char a; + int ret = read(sig_interrupt_fds[1], &a, sizeof(a)); + (void)ret; + + sig_interrupt_notifier->setEnabled(true); + + emit SigInterrupt(); +} #endif // __linux__ void GMainWindow::PreventOSSleep() { @@ -1476,17 +1588,18 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p return true; } -void GMainWindow::SelectAndSetCurrentUser() { +bool GMainWindow::SelectAndSetCurrentUser() { QtProfileSelectionDialog dialog(system->HIDCore(), this); dialog.setWindowFlags(Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint); dialog.setWindowModality(Qt::WindowModal); if (dialog.exec() == QDialog::Rejected) { - return; + return false; } Settings::values.current_user = dialog.GetIndex(); + return true; } void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t program_index, @@ -1520,11 +1633,14 @@ void GMainWindow::BootGame(const QString& filename, u64 program_id, std::size_t Settings::LogSettings(); if (UISettings::values.select_user_on_boot) { - SelectAndSetCurrentUser(); + if (SelectAndSetCurrentUser() == false) { + return; + } } - if (!LoadROM(filename, program_id, program_index)) + if (!LoadROM(filename, program_id, program_index)) { return; + } system->SetShuttingDown(false); |
