diff options
Diffstat (limited to 'src/yuzu')
-rw-r--r-- | src/yuzu/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/yuzu/bootmanager.cpp | 208 | ||||
-rw-r--r-- | src/yuzu/bootmanager.h | 29 | ||||
-rw-r--r-- | src/yuzu/configuration/config.cpp | 10 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_dialog.cpp | 2 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_general.cpp | 4 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_graphics.cpp | 3 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_graphics.ui | 7 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_hotkeys.cpp | 19 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_hotkeys.h | 3 | ||||
-rw-r--r-- | src/yuzu/game_list.cpp | 5 | ||||
-rw-r--r-- | src/yuzu/game_list_p.h | 2 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 39 | ||||
-rw-r--r-- | src/yuzu/main.h | 4 | ||||
-rw-r--r-- | src/yuzu/ui_settings.h | 4 |
15 files changed, 228 insertions, 117 deletions
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 2eb86d6e5..31b65c04c 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -151,6 +151,12 @@ target_link_libraries(yuzu PRIVATE common core input_common video_core) target_link_libraries(yuzu PRIVATE Boost::boost glad Qt5::OpenGL Qt5::Widgets) target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) +target_compile_definitions(yuzu PRIVATE + # Use QStringBuilder for string concatenation to reduce + # the overall number of temporary strings created. + -DQT_USE_QSTRINGBUILDER +) + if (YUZU_ENABLE_COMPATIBILITY_REPORTING) target_compile_definitions(yuzu PRIVATE -DYUZU_ENABLE_COMPATIBILITY_REPORTING) endif() diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 7438fbc0a..c29f2d2dc 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -1,6 +1,13 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #include <QApplication> #include <QHBoxLayout> #include <QKeyEvent> +#include <QOffscreenSurface> +#include <QOpenGLWindow> +#include <QPainter> #include <QScreen> #include <QWindow> #include <fmt/format.h> @@ -82,13 +89,36 @@ void EmuThread::run() { render_window->moveContext(); } +class GGLContext : public Core::Frontend::GraphicsContext { +public: + explicit GGLContext(QOpenGLContext* shared_context) : surface() { + context = std::make_unique<QOpenGLContext>(shared_context); + surface.setFormat(shared_context->format()); + surface.create(); + } + + void MakeCurrent() override { + context->makeCurrent(&surface); + } + + void DoneCurrent() override { + context->doneCurrent(); + } + + void SwapBuffers() override {} + +private: + std::unique_ptr<QOpenGLContext> context; + QOffscreenSurface surface; +}; + // This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL // context. // The corresponding functionality is handled in EmuThread instead -class GGLWidgetInternal : public QGLWidget { +class GGLWidgetInternal : public QOpenGLWindow { public: - GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) - : QGLWidget(fmt, parent), parent(parent) {} + GGLWidgetInternal(GRenderWindow* parent, QOpenGLContext* shared_context) + : QOpenGLWindow(shared_context), parent(parent) {} void paintEvent(QPaintEvent* ev) override { if (do_painting) { @@ -101,9 +131,51 @@ public: parent->OnFramebufferSizeChanged(); } + void keyPressEvent(QKeyEvent* event) override { + InputCommon::GetKeyboard()->PressKey(event->key()); + } + + void keyReleaseEvent(QKeyEvent* event) override { + InputCommon::GetKeyboard()->ReleaseKey(event->key()); + } + + void mousePressEvent(QMouseEvent* event) override { + if (event->source() == Qt::MouseEventSynthesizedBySystem) + return; // touch input is handled in TouchBeginEvent + + const auto pos{event->pos()}; + if (event->button() == Qt::LeftButton) { + const auto [x, y] = parent->ScaleTouch(pos); + parent->TouchPressed(x, y); + } else if (event->button() == Qt::RightButton) { + InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y()); + } + } + + void mouseMoveEvent(QMouseEvent* event) override { + if (event->source() == Qt::MouseEventSynthesizedBySystem) + return; // touch input is handled in TouchUpdateEvent + + const auto pos{event->pos()}; + const auto [x, y] = parent->ScaleTouch(pos); + parent->TouchMoved(x, y); + InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y()); + } + + void mouseReleaseEvent(QMouseEvent* event) override { + if (event->source() == Qt::MouseEventSynthesizedBySystem) + return; // touch input is handled in TouchEndEvent + + if (event->button() == Qt::LeftButton) + parent->TouchReleased(); + else if (event->button() == Qt::RightButton) + InputCommon::GetMotionEmu()->EndTilt(); + } + void DisablePainting() { do_painting = false; } + void EnablePainting() { do_painting = true; } @@ -114,7 +186,7 @@ private: }; GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) - : QWidget(parent), child(nullptr), emu_thread(emu_thread) { + : QWidget(parent), child(nullptr), context(nullptr), emu_thread(emu_thread) { setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); @@ -137,19 +209,19 @@ void GRenderWindow::moveContext() { auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) ? emu_thread : qApp->thread(); - child->context()->moveToThread(thread); + context->moveToThread(thread); } void GRenderWindow::SwapBuffers() { - // In our multi-threaded QGLWidget use case we shouldn't need to call `makeCurrent`, + // In our multi-threaded QWidget use case we shouldn't need to call `makeCurrent`, // since we never call `doneCurrent` in this thread. // However: // - The Qt debug runtime prints a bogus warning on the console if `makeCurrent` wasn't called // since the last time `swapBuffers` was executed; // - On macOS, if `makeCurrent` isn't called explicitely, resizing the buffer breaks. - child->makeCurrent(); + context->makeCurrent(child); - child->swapBuffers(); + context->swapBuffers(child); if (!first_frame) { emit FirstFrameDisplayed(); first_frame = true; @@ -157,11 +229,11 @@ void GRenderWindow::SwapBuffers() { } void GRenderWindow::MakeCurrent() { - child->makeCurrent(); + context->makeCurrent(child); } void GRenderWindow::DoneCurrent() { - child->doneCurrent(); + context->doneCurrent(); } void GRenderWindow::PollEvents() {} @@ -174,14 +246,26 @@ void GRenderWindow::PollEvents() {} void GRenderWindow::OnFramebufferSizeChanged() { // Screen changes potentially incur a change in screen DPI, hence we should update the // framebuffer size - qreal pixelRatio = windowPixelRatio(); + qreal pixelRatio = GetWindowPixelRatio(); unsigned width = child->QPaintDevice::width() * pixelRatio; unsigned height = child->QPaintDevice::height() * pixelRatio; UpdateCurrentFramebufferLayout(width, height); } +void GRenderWindow::ForwardKeyPressEvent(QKeyEvent* event) { + if (child) { + child->keyPressEvent(event); + } +} + +void GRenderWindow::ForwardKeyReleaseEvent(QKeyEvent* event) { + if (child) { + child->keyReleaseEvent(event); + } +} + void GRenderWindow::BackupGeometry() { - geometry = ((QGLWidget*)this)->saveGeometry(); + geometry = ((QWidget*)this)->saveGeometry(); } void GRenderWindow::RestoreGeometry() { @@ -199,18 +283,18 @@ QByteArray GRenderWindow::saveGeometry() { // If we are a top-level widget, store the current geometry // otherwise, store the last backup if (parent() == nullptr) - return ((QGLWidget*)this)->saveGeometry(); + return ((QWidget*)this)->saveGeometry(); else return geometry; } -qreal GRenderWindow::windowPixelRatio() const { +qreal GRenderWindow::GetWindowPixelRatio() const { // windowHandle() might not be accessible until the window is displayed to screen. return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f; } std::pair<unsigned, unsigned> GRenderWindow::ScaleTouch(const QPointF pos) const { - const qreal pixel_ratio = windowPixelRatio(); + const qreal pixel_ratio = GetWindowPixelRatio(); return {static_cast<unsigned>(std::max(std::round(pos.x() * pixel_ratio), qreal{0.0})), static_cast<unsigned>(std::max(std::round(pos.y() * pixel_ratio), qreal{0.0}))}; } @@ -220,47 +304,6 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { QWidget::closeEvent(event); } -void GRenderWindow::keyPressEvent(QKeyEvent* event) { - InputCommon::GetKeyboard()->PressKey(event->key()); -} - -void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { - InputCommon::GetKeyboard()->ReleaseKey(event->key()); -} - -void GRenderWindow::mousePressEvent(QMouseEvent* event) { - if (event->source() == Qt::MouseEventSynthesizedBySystem) - return; // touch input is handled in TouchBeginEvent - - auto pos = event->pos(); - if (event->button() == Qt::LeftButton) { - const auto [x, y] = ScaleTouch(pos); - this->TouchPressed(x, y); - } else if (event->button() == Qt::RightButton) { - InputCommon::GetMotionEmu()->BeginTilt(pos.x(), pos.y()); - } -} - -void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { - if (event->source() == Qt::MouseEventSynthesizedBySystem) - return; // touch input is handled in TouchUpdateEvent - - auto pos = event->pos(); - const auto [x, y] = ScaleTouch(pos); - this->TouchMoved(x, y); - InputCommon::GetMotionEmu()->Tilt(pos.x(), pos.y()); -} - -void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { - if (event->source() == Qt::MouseEventSynthesizedBySystem) - return; // touch input is handled in TouchEndEvent - - if (event->button() == Qt::LeftButton) - this->TouchReleased(); - else if (event->button() == Qt::RightButton) - InputCommon::GetMotionEmu()->EndTilt(); -} - void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { // TouchBegin always has exactly one touch point, so take the .first() const auto [x, y] = ScaleTouch(event->touchPoints().first().pos()); @@ -313,35 +356,60 @@ void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) { NotifyClientAreaSizeChanged(std::make_pair(width, height)); } +std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const { + return std::make_unique<GGLContext>(shared_context.get()); +} + void GRenderWindow::InitRenderTarget() { - if (child) { - delete child; - } + shared_context.reset(); + context.reset(); - if (layout()) { - delete layout(); - } + delete child; + child = nullptr; + + delete container; + container = nullptr; + + delete layout(); first_frame = false; // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, // WA_DontShowOnScreen, WA_DeleteOnClose - QGLFormat fmt; + QSurfaceFormat fmt; fmt.setVersion(4, 3); - fmt.setProfile(QGLFormat::CoreProfile); + fmt.setProfile(QSurfaceFormat::CoreProfile); + // TODO: expose a setting for buffer value (ie default/single/double/triple) + fmt.setSwapBehavior(QSurfaceFormat::DefaultSwapBehavior); + shared_context = std::make_unique<QOpenGLContext>(); + shared_context->setFormat(fmt); + shared_context->create(); + context = std::make_unique<QOpenGLContext>(); + context->setShareContext(shared_context.get()); + context->setFormat(fmt); + context->create(); fmt.setSwapInterval(false); - // Requests a forward-compatible context, which is required to get a 3.2+ context on OS X - fmt.setOption(QGL::NoDeprecatedFunctions); + child = new GGLWidgetInternal(this, shared_context.get()); + container = QWidget::createWindowContainer(child, this); - child = new GGLWidgetInternal(fmt, this); QBoxLayout* layout = new QHBoxLayout(this); - - resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height); - layout->addWidget(child); + layout->addWidget(container); layout->setMargin(0); setLayout(layout); + // Reset minimum size to avoid unwanted resizes when this function is called for a second time. + setMinimumSize(1, 1); + + // Show causes the window to actually be created and the OpenGL context as well, but we don't + // want the widget to be shown yet, so immediately hide it. + show(); + hide(); + + resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height); + child->resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height); + container->resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height); + OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); OnFramebufferSizeChanged(); diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 3183621bc..9608b959f 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -7,9 +7,9 @@ #include <atomic> #include <condition_variable> #include <mutex> -#include <QGLWidget> #include <QImage> #include <QThread> +#include <QWidget> #include "common/thread.h" #include "core/core.h" #include "core/frontend/emu_window.h" @@ -21,6 +21,8 @@ class QTouchEvent; class GGLWidgetInternal; class GMainWindow; class GRenderWindow; +class QSurface; +class QOpenGLContext; namespace VideoCore { enum class LoadCallbackStage; @@ -121,25 +123,21 @@ public: void MakeCurrent() override; void DoneCurrent() override; void PollEvents() override; + std::unique_ptr<Core::Frontend::GraphicsContext> CreateSharedContext() const override; + + void ForwardKeyPressEvent(QKeyEvent* event); + void ForwardKeyReleaseEvent(QKeyEvent* event); void BackupGeometry(); void RestoreGeometry(); void restoreGeometry(const QByteArray& geometry); // overridden QByteArray saveGeometry(); // overridden - qreal windowPixelRatio() const; + qreal GetWindowPixelRatio() const; + std::pair<unsigned, unsigned> ScaleTouch(const QPointF pos) const; void closeEvent(QCloseEvent* event) override; - - void keyPressEvent(QKeyEvent* event) override; - void keyReleaseEvent(QKeyEvent* event) override; - - void mousePressEvent(QMouseEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; - void mouseReleaseEvent(QMouseEvent* event) override; - bool event(QEvent* event) override; - void focusOutEvent(QFocusEvent* event) override; void OnClientAreaResized(unsigned width, unsigned height); @@ -161,7 +159,6 @@ signals: void FirstFrameDisplayed(); private: - std::pair<unsigned, unsigned> ScaleTouch(const QPointF pos) const; void TouchBeginEvent(const QTouchEvent* event); void TouchUpdateEvent(const QTouchEvent* event); void TouchEndEvent(); @@ -169,11 +166,17 @@ private: void OnMinimalClientAreaChangeRequest( const std::pair<unsigned, unsigned>& minimal_size) override; - GGLWidgetInternal* child; + QWidget* container = nullptr; + GGLWidgetInternal* child = nullptr; QByteArray geometry; EmuThread* emu_thread; + // Context that backs the GGLWidgetInternal (and will be used by core to render) + std::unique_ptr<QOpenGLContext> context; + // Context that will be shared between all newly created contexts. This should never be made + // current + std::unique_ptr<QOpenGLContext> shared_context; /// Temporary storage of the screenshot taken QImage screenshot_image; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 802db3945..8725a78dc 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -394,6 +394,7 @@ void Config::ReadValues() { ReadSetting("use_accurate_gpu_emulation", false).toBool(); Settings::values.use_asynchronous_gpu_emulation = ReadSetting("use_asynchronous_gpu_emulation", false).toBool(); + Settings::values.force_30fps_mode = ReadSetting("force_30fps_mode", false).toBool(); Settings::values.bg_red = ReadSetting("bg_red", 0.0).toFloat(); Settings::values.bg_green = ReadSetting("bg_green", 0.0).toFloat(); @@ -523,8 +524,8 @@ void Config::ReadValues() { qt_config->beginGroup("Paths"); UISettings::values.roms_path = ReadSetting("romsPath").toString(); UISettings::values.symbols_path = ReadSetting("symbolsPath").toString(); - UISettings::values.gamedir = ReadSetting("gameListRootDir", ".").toString(); - UISettings::values.gamedir_deepscan = ReadSetting("gameListDeepScan", false).toBool(); + UISettings::values.game_directory_path = ReadSetting("gameListRootDir", ".").toString(); + UISettings::values.game_directory_deepscan = ReadSetting("gameListDeepScan", false).toBool(); UISettings::values.recent_files = ReadSetting("recentFiles").toStringList(); qt_config->endGroup(); @@ -664,6 +665,7 @@ void Config::SaveValues() { WriteSetting("use_accurate_gpu_emulation", Settings::values.use_accurate_gpu_emulation, false); WriteSetting("use_asynchronous_gpu_emulation", Settings::values.use_asynchronous_gpu_emulation, false); + WriteSetting("force_30fps_mode", Settings::values.force_30fps_mode, false); // Cast to double because Qt's written float values are not human-readable WriteSetting("bg_red", (double)Settings::values.bg_red, 0.0); @@ -768,8 +770,8 @@ void Config::SaveValues() { WriteSetting("romsPath", UISettings::values.roms_path); WriteSetting("symbolsPath", UISettings::values.symbols_path); WriteSetting("screenshotPath", UISettings::values.screenshot_path); - WriteSetting("gameListRootDir", UISettings::values.gamedir, "."); - WriteSetting("gameListDeepScan", UISettings::values.gamedir_deepscan, false); + WriteSetting("gameListRootDir", UISettings::values.game_directory_path, "."); + WriteSetting("gameListDeepScan", UISettings::values.game_directory_deepscan, false); WriteSetting("recentFiles", UISettings::values.recent_files); qt_config->endGroup(); diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 51bd1f121..a5218b051 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -12,7 +12,7 @@ #include "yuzu/hotkeys.h" ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry) - : QDialog(parent), registry(registry), ui(new Ui::ConfigureDialog) { + : QDialog(parent), ui(new Ui::ConfigureDialog), registry(registry) { ui->setupUi(this); ui->hotkeysTab->Populate(registry); this->setConfiguration(); diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index eeb038afb..e48f4f5a3 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -28,7 +28,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) ConfigureGeneral::~ConfigureGeneral() = default; void ConfigureGeneral::setConfiguration() { - ui->toggle_deepscan->setChecked(UISettings::values.gamedir_deepscan); + ui->toggle_deepscan->setChecked(UISettings::values.game_directory_deepscan); ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot); ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); @@ -36,7 +36,7 @@ void ConfigureGeneral::setConfiguration() { } void ConfigureGeneral::applyConfiguration() { - UISettings::values.gamedir_deepscan = ui->toggle_deepscan->isChecked(); + UISettings::values.game_directory_deepscan = ui->toggle_deepscan->isChecked(); UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); UISettings::values.select_user_on_boot = ui->toggle_user_on_boot->isChecked(); UISettings::values.theme = diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index dd1d67488..0a9883d37 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -77,6 +77,8 @@ void ConfigureGraphics::setConfiguration() { ui->use_accurate_gpu_emulation->setChecked(Settings::values.use_accurate_gpu_emulation); ui->use_asynchronous_gpu_emulation->setEnabled(!Core::System::GetInstance().IsPoweredOn()); ui->use_asynchronous_gpu_emulation->setChecked(Settings::values.use_asynchronous_gpu_emulation); + ui->force_30fps_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn()); + ui->force_30fps_mode->setChecked(Settings::values.force_30fps_mode); UpdateBackgroundColorButton(QColor::fromRgbF(Settings::values.bg_red, Settings::values.bg_green, Settings::values.bg_blue)); } @@ -90,6 +92,7 @@ void ConfigureGraphics::applyConfiguration() { Settings::values.use_accurate_gpu_emulation = ui->use_accurate_gpu_emulation->isChecked(); Settings::values.use_asynchronous_gpu_emulation = ui->use_asynchronous_gpu_emulation->isChecked(); + Settings::values.force_30fps_mode = ui->force_30fps_mode->isChecked(); Settings::values.bg_red = static_cast<float>(bg_color.redF()); Settings::values.bg_green = static_cast<float>(bg_color.greenF()); Settings::values.bg_blue = static_cast<float>(bg_color.blueF()); diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index c6767e0ca..15ab18ecd 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -71,6 +71,13 @@ </widget> </item> <item> + <widget class="QCheckBox" name="force_30fps_mode"> + <property name="text"> + <string>Force 30 FPS mode</string> + </property> + </widget> + </item> + <item> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="label"> diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp index bfb562535..a7a8752e5 100644 --- a/src/yuzu/configuration/configure_hotkeys.cpp +++ b/src/yuzu/configuration/configure_hotkeys.cpp @@ -66,20 +66,21 @@ void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) { } void ConfigureHotkeys::Configure(QModelIndex index) { - if (index.parent() == QModelIndex()) + if (!index.parent().isValid()) { return; + } index = index.sibling(index.row(), 1); - auto* model = ui->hotkey_list->model(); - auto previous_key = model->data(index); - - auto* hotkey_dialog = new SequenceDialog; - int return_code = hotkey_dialog->exec(); + auto* const model = ui->hotkey_list->model(); + const auto previous_key = model->data(index); - auto key_sequence = hotkey_dialog->GetSequence(); + SequenceDialog hotkey_dialog{this}; - if (return_code == QDialog::Rejected || key_sequence.isEmpty()) + const int return_code = hotkey_dialog.exec(); + const auto key_sequence = hotkey_dialog.GetSequence(); + if (return_code == QDialog::Rejected || key_sequence.isEmpty()) { return; + } if (IsUsedKey(key_sequence) && key_sequence != QKeySequence(previous_key.toString())) { QMessageBox::critical(this, tr("Error in inputted key"), @@ -90,7 +91,7 @@ void ConfigureHotkeys::Configure(QModelIndex index) { } } -bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) { +bool ConfigureHotkeys::IsUsedKey(QKeySequence key_sequence) const { return GetUsedKeyList().contains(key_sequence); } diff --git a/src/yuzu/configuration/configure_hotkeys.h b/src/yuzu/configuration/configure_hotkeys.h index cd203aad6..73fb8a175 100644 --- a/src/yuzu/configuration/configure_hotkeys.h +++ b/src/yuzu/configuration/configure_hotkeys.h @@ -6,7 +6,6 @@ #include <memory> #include <QWidget> -#include "core/settings.h" namespace Ui { class ConfigureHotkeys; @@ -39,7 +38,7 @@ signals: private: void Configure(QModelIndex index); - bool IsUsedKey(QKeySequence key_sequence); + bool IsUsedKey(QKeySequence key_sequence) const; QList<QKeySequence> GetUsedKeyList() const; std::unique_ptr<Ui::ConfigureHotkeys> ui; diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 4b67656ac..b0ca766ec 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp @@ -467,9 +467,10 @@ void GameList::LoadInterfaceLayout() { const QStringList GameList::supported_file_extensions = {"nso", "nro", "nca", "xci", "nsp"}; void GameList::RefreshGameDirectory() { - if (!UISettings::values.gamedir.isEmpty() && current_worker != nullptr) { + if (!UISettings::values.game_directory_path.isEmpty() && current_worker != nullptr) { LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list."); search_field->clear(); - PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); + PopulateAsync(UISettings::values.game_directory_path, + UISettings::values.game_directory_deepscan); } } diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index 3db0e90da..2cf5c58a0 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h @@ -95,7 +95,7 @@ public: if (row2.isEmpty()) return row1; - return row1 + "\n " + row2; + return QString(row1 + "\n " + row2); } return GameListItem::data(role); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index ca231d710..bdee44b04 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -213,7 +213,8 @@ GMainWindow::GMainWindow() OnReinitializeKeys(ReinitializeKeyBehavior::NoWarning); game_list->LoadCompatibilityList(); - game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); + game_list->PopulateAsync(UISettings::values.game_directory_path, + UISettings::values.game_directory_deepscan); // Show one-time "callout" messages to the user ShowTelemetryCallout(); @@ -1278,8 +1279,8 @@ void GMainWindow::OnGameListOpenPerGameProperties(const std::string& file) { const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); if (reload) { - game_list->PopulateAsync(UISettings::values.gamedir, - UISettings::values.gamedir_deepscan); + game_list->PopulateAsync(UISettings::values.game_directory_path, + UISettings::values.game_directory_deepscan); } config->Save(); @@ -1367,7 +1368,8 @@ void GMainWindow::OnMenuInstallToNAND() { const auto success = [this]() { QMessageBox::information(this, tr("Successfully Installed"), tr("The file was successfully installed.")); - game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); + game_list->PopulateAsync(UISettings::values.game_directory_path, + UISettings::values.game_directory_deepscan); }; const auto failed = [this]() { @@ -1494,8 +1496,8 @@ void GMainWindow::OnMenuInstallToNAND() { void GMainWindow::OnMenuSelectGameListRoot() { QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory")); if (!dir_path.isEmpty()) { - UISettings::values.gamedir = dir_path; - game_list->PopulateAsync(dir_path, UISettings::values.gamedir_deepscan); + UISettings::values.game_directory_path = dir_path; + game_list->PopulateAsync(dir_path, UISettings::values.game_directory_deepscan); } } @@ -1517,7 +1519,8 @@ void GMainWindow::OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target) : FileUtil::UserPath::NANDDir, dir_path.toStdString()); Service::FileSystem::CreateFactories(*vfs); - game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); + game_list->PopulateAsync(UISettings::values.game_directory_path, + UISettings::values.game_directory_deepscan); } } @@ -1669,8 +1672,8 @@ void GMainWindow::OnConfigure() { const auto reload = UISettings::values.is_game_list_reload_pending.exchange(false); if (reload) { - game_list->PopulateAsync(UISettings::values.gamedir, - UISettings::values.gamedir_deepscan); + game_list->PopulateAsync(UISettings::values.game_directory_path, + UISettings::values.game_directory_deepscan); } config->Save(); @@ -1920,7 +1923,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { Service::FileSystem::CreateFactories(*vfs); if (behavior == ReinitializeKeyBehavior::Warning) { - game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan); + game_list->PopulateAsync(UISettings::values.game_directory_path, + UISettings::values.game_directory_deepscan); } } @@ -2027,6 +2031,18 @@ void GMainWindow::dragMoveEvent(QDragMoveEvent* event) { event->acceptProposedAction(); } +void GMainWindow::keyPressEvent(QKeyEvent* event) { + if (render_window) { + render_window->ForwardKeyPressEvent(event); + } +} + +void GMainWindow::keyReleaseEvent(QKeyEvent* event) { + if (render_window) { + render_window->ForwardKeyReleaseEvent(event); + } +} + bool GMainWindow::ConfirmChangeGame() { if (emu_thread == nullptr) return true; @@ -2094,7 +2110,8 @@ int main(int argc, char* argv[]) { QCoreApplication::setOrganizationName("yuzu team"); QCoreApplication::setApplicationName("yuzu"); - QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); + // Enables the core to make the qt created contexts current on std::threads + QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); QApplication app(argc, argv); // Qt changes the locale and causes issues in float conversion using std::to_string() when diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 85e3810f2..ce5045819 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -252,4 +252,8 @@ protected: void dropEvent(QDropEvent* event) override; void dragEnterEvent(QDragEnterEvent* event) override; void dragMoveEvent(QDragMoveEvent* event) override; + + // Overrides used to forward signals to the render window when the focus moves out. + void keyPressEvent(QKeyEvent* event) override; + void keyReleaseEvent(QKeyEvent* event) override; }; diff --git a/src/yuzu/ui_settings.h b/src/yuzu/ui_settings.h index 45e705b61..dbd318e20 100644 --- a/src/yuzu/ui_settings.h +++ b/src/yuzu/ui_settings.h @@ -55,8 +55,8 @@ struct Values { QString roms_path; QString symbols_path; QString screenshot_path; - QString gamedir; - bool gamedir_deepscan; + QString game_directory_path; + bool game_directory_deepscan; QStringList recent_files; QString theme; |