From 2f591d33d356e81a5a4c9688fa36fd556f27aacb Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Wed, 29 Oct 2025 13:16:57 +0100 Subject: [PATCH] [meta] Add option to FORCE X11 as Graphics Backend (#2820) * save the option on a external file because settings are loaded AFTER Qt window is created and then the graphics backend is already applied Signed-off-by: Caio Oliveira Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2820 Reviewed-by: MaranBr Reviewed-by: Shinmegumi Co-authored-by: Caio Oliveira Co-committed-by: Caio Oliveira --- src/common/settings.h | 4 ++ src/qt_common/CMakeLists.txt | 4 ++ src/qt_common/config/shared_translation.cpp | 4 ++ src/qt_common/gui_settings.cpp | 25 ++++++++ src/qt_common/gui_settings.h | 15 +++++ src/yuzu/main.cpp | 64 +++++++++++++++++++++ src/yuzu/main.h | 3 + 7 files changed, 119 insertions(+) create mode 100644 src/qt_common/gui_settings.cpp create mode 100644 src/qt_common/gui_settings.h diff --git a/src/common/settings.h b/src/common/settings.h index 1dc3bdca20..b5c8db5cec 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -622,6 +622,10 @@ struct Values { // Linux SwitchableSetting enable_gamemode{linkage, true, "enable_gamemode", Category::Linux}; +#ifdef __unix__ + SwitchableSetting gui_force_x11{linkage, false, "gui_force_x11", Category::Linux}; + Setting gui_hide_backend_warning{linkage, false, "gui_hide_backend_warning", Category::Linux}; +#endif // Controls InputSetting> players; diff --git a/src/qt_common/CMakeLists.txt b/src/qt_common/CMakeLists.txt index 75ef717583..895320703a 100644 --- a/src/qt_common/CMakeLists.txt +++ b/src/qt_common/CMakeLists.txt @@ -30,6 +30,10 @@ add_library(qt_common STATIC util/fs.h util/fs.cpp ) +if (UNIX) + target_sources(qt_common PRIVATE gui_settings.cpp gui_settings.h) +endif() + create_target_directory_groups(qt_common) if (USE_DISCORD_PRESENCE) diff --git a/src/qt_common/config/shared_translation.cpp b/src/qt_common/config/shared_translation.cpp index 4a16d94f9a..2d54fc2a30 100644 --- a/src/qt_common/config/shared_translation.cpp +++ b/src/qt_common/config/shared_translation.cpp @@ -424,6 +424,10 @@ std::unique_ptr InitializeTranslations(QObject* parent) // Linux INSERT(Settings, enable_gamemode, tr("Enable Gamemode"), QString()); +#ifdef __unix__ + INSERT(Settings, gui_force_x11, tr("Force X11 as Graphics Backend"), QString()); + INSERT(Settings, gui_hide_backend_warning, QString(), QString()); +#endif // Ui Debugging diff --git a/src/qt_common/gui_settings.cpp b/src/qt_common/gui_settings.cpp new file mode 100644 index 0000000000..982d28bbcb --- /dev/null +++ b/src/qt_common/gui_settings.cpp @@ -0,0 +1,25 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "gui_settings.h" +#include "common/fs/fs.h" +#include "common/fs/path_util.h" + +namespace FS = Common::FS; + +namespace GraphicsBackend { + +QString GuiConfigPath() { + return QString::fromStdString(FS::PathToUTF8String(FS::GetEdenPath(FS::EdenPath::ConfigDir) / "gui_config.ini")); +} + +void SetForceX11(bool state) { + (void)FS::CreateParentDir(GuiConfigPath().toStdString()); + QSettings(GuiConfigPath(), QSettings::IniFormat).setValue("gui_force_x11", state); +} + +bool GetForceX11() { + return QSettings(GuiConfigPath(), QSettings::IniFormat).value("gui_force_x11", false).toBool(); +} + +} // namespace GraphicsBackend diff --git a/src/qt_common/gui_settings.h b/src/qt_common/gui_settings.h new file mode 100644 index 0000000000..d7d471d9ab --- /dev/null +++ b/src/qt_common/gui_settings.h @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include + +namespace GraphicsBackend { + +QString GuiConfigPath(); +void SetForceX11(bool state); +bool GetForceX11(); + +} // namespace GraphicsBackend diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 521c677c2a..a4800d4b29 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -25,6 +25,7 @@ #ifdef __unix__ #include #include +#include "qt_common/gui_settings.h" #endif #ifdef __linux__ #include "common/linux/gamemode.h" @@ -552,6 +553,10 @@ GMainWindow::GMainWindow(bool has_broken_vulkan) // Gen keys if necessary OnCheckFirmwareDecryption(); +#ifdef __unix__ + OnCheckGraphicsBackend(); +#endif + // Check for orphaned profiles and reset profile data if necessary QtCommon::Content::FixProfiles(); @@ -3497,6 +3502,9 @@ void GMainWindow::OnConfigure() { #ifdef __linux__ const bool old_gamemode = Settings::values.enable_gamemode.GetValue(); #endif +#ifdef __unix__ + const bool old_force_x11 = Settings::values.gui_force_x11.GetValue(); +#endif Settings::SetConfiguringGlobal(true); ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(), @@ -3561,6 +3569,11 @@ void GMainWindow::OnConfigure() { SetGamemodeEnabled(Settings::values.enable_gamemode.GetValue()); } #endif +#ifdef __unix__ + if (Settings::values.gui_force_x11.GetValue() != old_force_x11) { + GraphicsBackend::SetForceX11(Settings::values.gui_force_x11.GetValue()); + } +#endif if (!multiplayer_state->IsHostingPublicRoom()) { multiplayer_state->UpdateCredentials(); @@ -4536,6 +4549,54 @@ void GMainWindow::OnCheckFirmwareDecryption() { UpdateMenuState(); } +#ifdef __unix__ +void GMainWindow::OnCheckGraphicsBackend() { + const QString platformName = QGuiApplication::platformName(); + const QByteArray qtPlatform = qgetenv("QT_QPA_PLATFORM"); + + if (platformName == QStringLiteral("xcb") || qtPlatform == "xcb") + return; + + const bool isWayland = platformName.startsWith(QStringLiteral("wayland"), Qt::CaseInsensitive) || qtPlatform.startsWith("wayland"); + if (!isWayland) + return; + + const bool currently_hidden = Settings::values.gui_hide_backend_warning.GetValue(); + if (currently_hidden) + return; + + QMessageBox msgbox(this); + msgbox.setWindowTitle(tr("Wayland Detected!")); + msgbox.setText(tr("Wayland is known to have significant performance issues and mysterious bugs.\n" + "It's recommended to use X11 instead.\n\n" + "Would you like to force it for future launches?")); + msgbox.setIcon(QMessageBox::Warning); + + QPushButton* okButton = msgbox.addButton(tr("Use X11"), QMessageBox::AcceptRole); + msgbox.addButton(tr("Continue with Wayland"), QMessageBox::RejectRole); + msgbox.setDefaultButton(okButton); + + QCheckBox* cb = new QCheckBox(tr("Don't show again"), &msgbox); + cb->setChecked(currently_hidden); + msgbox.setCheckBox(cb); + + msgbox.exec(); + + const bool hide = cb->isChecked(); + if (hide != currently_hidden) { + Settings::values.gui_hide_backend_warning.SetValue(hide); + } + + if (msgbox.clickedButton() == okButton) { + Settings::values.gui_force_x11.SetValue(true); + GraphicsBackend::SetForceX11(true); + QMessageBox::information(this, + tr("Restart Required"), + tr("Restart Eden to apply the X11 backend.")); + } +} +#endif + bool GMainWindow::CheckFirmwarePresence() { return FirmwareManager::CheckFirmwarePresence(*QtCommon::system.get()); } @@ -5029,6 +5090,9 @@ int main(int argc, char* argv[]) { qputenv("DISPLAY", ":0"); } + if (GraphicsBackend::GetForceX11() && qEnvironmentVariableIsEmpty("QT_QPA_PLATFORM")) + qputenv("QT_QPA_PLATFORM", "xcb"); + // Fix the Wayland appId. This needs to match the name of the .desktop file without the .desktop // suffix. QGuiApplication::setDesktopFileName(QStringLiteral("dev.eden_emu.eden")); diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 5a802c2e96..a0ddef6309 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -411,6 +411,9 @@ private slots: void OnCreateHomeMenuApplicationMenuShortcut(); void OnCaptureScreenshot(); void OnCheckFirmwareDecryption(); +#ifdef __unix__ + void OnCheckGraphicsBackend(); +#endif void OnLanguageChanged(const QString& locale); void OnMouseActivity(); bool OnShutdownBegin();