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; | 
