You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.6 KiB
170 lines
5.6 KiB
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#include <QApplication>
|
|
#include "startup_checks.h"
|
|
|
|
#if YUZU_ROOM
|
|
#include "dedicated_room/yuzu_room.h"
|
|
#include <common/detached_tasks.h>
|
|
#include <cstring>
|
|
#endif
|
|
|
|
#ifdef __unix__
|
|
#include "qt_common/gui_settings.h"
|
|
#endif
|
|
|
|
#include "main_window.h"
|
|
|
|
static void SetHighDPIAttributes() {
|
|
#ifdef _WIN32
|
|
// For Windows, we want to avoid scaling artifacts on fractional scaling ratios.
|
|
// This is done by setting the optimal scaling policy for the primary screen.
|
|
|
|
// Create a temporary QApplication.
|
|
int temp_argc = 0;
|
|
char** temp_argv = nullptr;
|
|
QApplication temp{temp_argc, temp_argv};
|
|
|
|
// Get the current screen geometry.
|
|
const QScreen* primary_screen = QGuiApplication::primaryScreen();
|
|
if (primary_screen == nullptr) {
|
|
return;
|
|
}
|
|
|
|
const QRect screen_rect = primary_screen->geometry();
|
|
const int real_width = screen_rect.width();
|
|
const int real_height = screen_rect.height();
|
|
const float real_ratio = primary_screen->logicalDotsPerInch() / 96.0f;
|
|
|
|
// Recommended minimum width and height for proper window fit.
|
|
// Any screen with a lower resolution than this will still have a scale of 1.
|
|
constexpr float minimum_width = 1350.0f;
|
|
constexpr float minimum_height = 900.0f;
|
|
|
|
const float width_ratio = (std::max)(1.0f, real_width / minimum_width);
|
|
const float height_ratio = (std::max)(1.0f, real_height / minimum_height);
|
|
|
|
// Get the lower of the 2 ratios and truncate, this is the maximum integer scale.
|
|
const float max_ratio = std::trunc((std::min)(width_ratio, height_ratio));
|
|
|
|
if (max_ratio > real_ratio) {
|
|
QApplication::setHighDpiScaleFactorRoundingPolicy(
|
|
Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
|
} else {
|
|
QApplication::setHighDpiScaleFactorRoundingPolicy(
|
|
Qt::HighDpiScaleFactorRoundingPolicy::Floor);
|
|
}
|
|
#else
|
|
// Other OSes should be better than Windows at fractional scaling.
|
|
QApplication::setHighDpiScaleFactorRoundingPolicy(
|
|
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
|
#endif
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
#if YUZU_ROOM
|
|
bool launch_room = false;
|
|
for (int i = 1; i < argc; i++) {
|
|
if (strcmp(argv[i], "--room") == 0) {
|
|
launch_room = true;
|
|
}
|
|
}
|
|
|
|
if (launch_room) {
|
|
LaunchRoom(argc, argv, true);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
bool has_broken_vulkan = false;
|
|
bool is_child = false;
|
|
if (CheckEnvVars(&is_child)) {
|
|
return 0;
|
|
}
|
|
|
|
if (StartupChecks(argv[0], &has_broken_vulkan,
|
|
Settings::values.perform_vulkan_check.GetValue())) {
|
|
return 0;
|
|
}
|
|
|
|
#ifdef YUZU_CRASH_DUMPS
|
|
Breakpad::InstallCrashHandler();
|
|
#endif
|
|
|
|
Common::DetachedTasks detached_tasks;
|
|
|
|
// Init settings params
|
|
QCoreApplication::setOrganizationName(QStringLiteral("eden"));
|
|
QCoreApplication::setApplicationName(QStringLiteral("eden"));
|
|
|
|
#ifdef _WIN32
|
|
// Increases the maximum open file limit to 8192
|
|
_setmaxstdio(8192);
|
|
#elif defined(__APPLE__)
|
|
// If you start a bundle (binary) on OSX without the Terminal, the working directory is "/".
|
|
// But since we require the working directory to be the executable path for the location of
|
|
// the user folder in the Qt Frontend, we need to cd into that working directory
|
|
const auto bin_path = Common::FS::GetBundleDirectory() / "..";
|
|
chdir(Common::FS::PathToUTF8String(bin_path).c_str());
|
|
#elif defined(__unix__) && !defined(__ANDROID__)
|
|
// Set the DISPLAY variable in order to open web browsers
|
|
// TODO (lat9nq): Find a better solution for AppImages to start external applications
|
|
if (QString::fromLocal8Bit(qgetenv("DISPLAY")).isEmpty()) {
|
|
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"));
|
|
#endif
|
|
|
|
SetHighDPIAttributes();
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
// Disables the "?" button on all dialogs. Disabled by default on Qt6.
|
|
QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
|
|
#endif
|
|
|
|
// Enables the core to make the qt created contexts current on std::threads
|
|
QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
|
|
|
|
#ifdef _WIN32
|
|
QApplication::setStyle(QStringLiteral("windowsvista"));
|
|
#endif
|
|
|
|
QApplication app(argc, argv);
|
|
|
|
#ifdef _WIN32
|
|
OverrideWindowsFont();
|
|
#endif
|
|
|
|
// Workaround for QTBUG-85409, for Suzhou numerals the number 1 is actually \u3021
|
|
// so we can see if we get \u3008 instead
|
|
// TL;DR all other number formats are consecutive in unicode code points
|
|
// This bug is fixed in Qt6, specifically 6.0.0-alpha1
|
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
const QLocale locale = QLocale::system();
|
|
if (QStringLiteral("\u3008") == locale.toString(1)) {
|
|
QLocale::setDefault(QLocale::system().name());
|
|
}
|
|
#endif
|
|
|
|
// Qt changes the locale and causes issues in float conversion using std::to_string() when
|
|
// generating shaders
|
|
setlocale(LC_ALL, "C");
|
|
|
|
MainWindow main_window{has_broken_vulkan};
|
|
// After settings have been loaded by GMainWindow, apply the filter
|
|
main_window.show();
|
|
|
|
app.connect(&app, &QGuiApplication::applicationStateChanged, &main_window,
|
|
&MainWindow::OnAppFocusStateChanged);
|
|
|
|
int result = app.exec();
|
|
detached_tasks.WaitForAllTasks();
|
|
return result;
|
|
}
|