diff options
Diffstat (limited to 'gui/init.cpp')
| -rw-r--r-- | gui/init.cpp | 301 |
1 files changed, 209 insertions, 92 deletions
diff --git a/gui/init.cpp b/gui/init.cpp index 42c33c2f..b666b4a9 100644 --- a/gui/init.cpp +++ b/gui/init.cpp @@ -1,5 +1,3 @@ -#include "init.hpp" - /* Copyright (c) 2013-2017 Stanislaw Halik * * Permission to use, copy, modify, and/or distribute this software for any @@ -7,14 +5,12 @@ * copyright notice and this permission notice appear in all copies. */ -#if defined(Q_CREATOR_RUN) -# pragma clang diagnostic ignored "-Wmain" -#endif - +#include "init.hpp" #include "migration/migration.hpp" #include "options/options.hpp" using namespace options; #include "compat/library-path.hpp" +#include "compat/arch.hpp" #include <memory> #include <cstdlib> @@ -25,132 +21,240 @@ using namespace options; #include <QStyleFactory> #include <QLocale> #include <QTranslator> -#include <QApplication> #include <QDir> #include <QFile> #include <QFileDialog> #include <QString> -#include <QSysInfo> +#include <QOperatingSystemVersion> +#include <QMutex> #include <QDebug> -#if /* denormal control */ \ - /* GNU */ defined __x86_64__ || defined __SSE2__ || \ - /* MSVC */ defined _M_AMD64 || (defined _M_IX86_FP && _M_IX86_FP >= 2) -# include <xmmintrin.h> -# include <pmmintrin.h> -# include <cfloat> +#include <cfloat> +#include <cfenv> -#define OTR_HAS_DENORM_CONTROL -void set_fp_mask() +#ifdef __MINGW32__ +extern "C" __declspec(dllimport) unsigned __cdecl _controlfp(unsigned, unsigned); +#endif + +static void set_fp_mask() { - _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); +#if defined OTR_ARCH_DENORM_DAZ _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON); - _MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST); +#elif defined OTR_ARCH_DENORM_FTZ + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); +#endif + +#ifdef OTR_ARCH_FPU_MASK _MM_SET_EXCEPTION_MASK(_MM_MASK_MASK); -} #endif -void set_qt_style() +#ifdef __APPLE__ +#if defined __i386__ || defined __x86_64__ + fesetenv(FE_DFL_DISABLE_SSE_DENORMS_ENV); +#endif +#endif + +#ifdef _WIN32 +# ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wreserved-id-macro" +# endif +# ifndef _DN_FLUSH +# define _DN_FLUSH 0x01000000 +# endif +# ifndef _MCW_DN +# define _MCW_DN 0x03000000 +# endif +# ifdef __clang__ +# pragma clang diagnostic pop +# endif + _controlfp(_DN_FLUSH, _MCW_DN); +#endif +} + +#ifdef OTR_X11_THREADS +#include <X11/Xlib.h> +static void enable_x11_threads() { -#if defined _WIN32 - if (QSysInfo::WindowsVersion == QSysInfo::WV_XP) - return; + (void)XInitThreads(); +} #endif +static void set_qt_style() +{ #if defined _WIN32 || defined __APPLE__ // our layouts on OSX make some control wrongly sized -sh 20160908 { - const char* const preferred[] { "fusion", "windowsvista", "macintosh" }; + const char* const preferred[] { +#ifdef __APPLE__ + "macintosh", "fusion", "windowsvista", "windows", +#else + "fusion", "windowsvista", "windows", "windowsxp", +#endif + }; for (const char* style_name : preferred) - { - QStyle* s = QStyleFactory::create(style_name); - if (s) + if (QStyle* s = QStyleFactory::create(style_name); s != nullptr) { QApplication::setStyle(s); break; } - } } #endif } +#include <string> + #ifdef _WIN32 +# include <windows.h> +# include <malloc.h> +#else +# include <alloca.h> +#endif -void qdebug_to_console(QtMsgType, const QMessageLogContext& ctx, const QString &msg) +static void qdebug_to_console(QtMsgType loglevel, const QMessageLogContext& ctx, const QString &msg) { - const unsigned short* const str_ = msg.utf16(); - auto str = reinterpret_cast<const wchar_t* const>(str_); - static_assert(sizeof(*str_) == sizeof(*str), ""); - - std::fflush(stderr); - if (ctx.function) - std::fprintf(stderr, "[%s:%d%s]: %ls\n", ctx.file, ctx.line, ctx.function, str); - else if (ctx.file) - std::fprintf(stderr, "[%s:%d]: %ls\n", ctx.file, ctx.line, str); + const char* level; + + switch (loglevel) + { + default: + case QtDebugMsg: level = "DEBUG"; break; + case QtWarningMsg: level = "WARN"; break; + case QtCriticalMsg: level = "CRIT"; break; + case QtFatalMsg: level = "FATAL"; break; + case QtInfoMsg: level = "INFO"; break; + } + +#ifdef _WIN32 + static_assert(sizeof(wchar_t) == sizeof(decltype(*msg.utf16()))); + + if (IsDebuggerPresent()) + { + static QMutex lock; + QMutexLocker l(&lock); + + const wchar_t* const bytes = (const wchar_t*)msg.utf16(); + + OutputDebugStringW(bytes); + OutputDebugStringW(L"\n"); + } else - std::fprintf(stderr, "%ls\n", str); - std::fflush(stderr); +#endif + { +#if defined _WIN32 + const wchar_t* const bytes = (const wchar_t*)msg.utf16(); +#else + unsigned len = (unsigned)msg.size()+1; + wchar_t* const bytes = (wchar_t*)alloca(len * sizeof(wchar_t)); + bytes[len-1] = 0; + (void)msg.toWCharArray(bytes); +#endif + if (ctx.file) + std::fprintf(stderr, "%s [%s:%d]: %ls\n", level, ctx.file, ctx.line, bytes); + else + std::fprintf(stderr, "%s %ls\n", level, bytes); + std::fflush(stderr); + } } -void add_win32_path() +#ifdef _WIN32 + +static void apply_dark_windows_theme_if_needed() { - // see https://software.intel.com/en-us/articles/limitation-to-the-length-of-the-system-path-variable - static char env_path[4096] { '\0', }; + // On Windows apply dark theme if requested by user settings + QSettings settings("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", QSettings::NativeFormat); + if (settings.value("AppsUseLightTheme") == 0) { + qApp->setStyle(QStyleFactory::create("Dark")); + QPalette darkPalette; + QColor darkColor = QColor(45, 45, 45); + QColor disabledColor = QColor(127, 127, 127); + darkPalette.setColor(QPalette::Window, darkColor); + darkPalette.setColor(QPalette::WindowText, Qt::white); + darkPalette.setColor(QPalette::Base, QColor(18, 18, 18)); + darkPalette.setColor(QPalette::AlternateBase, darkColor); + darkPalette.setColor(QPalette::ToolTipBase, Qt::white); + darkPalette.setColor(QPalette::ToolTipText, Qt::white); + darkPalette.setColor(QPalette::Text, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::Text, disabledColor); + darkPalette.setColor(QPalette::Button, darkColor); + darkPalette.setColor(QPalette::ButtonText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, disabledColor); + darkPalette.setColor(QPalette::BrightText, Qt::red); + darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); + + darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::HighlightedText, Qt::black); + darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, disabledColor); + + qApp->setPalette(darkPalette); + + qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }"); + } +} + +static void add_win32_path() +{ + // see https://web.archive.org/web/20180924055536/https://software.intel.com/en-us/articles/limitation-to-the-length-of-the-system-path-variable { QString lib_path = OPENTRACK_BASE_PATH; lib_path.replace("/", "\\"); - const QByteArray lib_path_ = QFile::encodeName(lib_path); - QString mod_path = OPENTRACK_BASE_PATH + OPENTRACK_LIBRARY_PATH; mod_path.replace("/", "\\"); - const QByteArray mod_path_ = QFile::encodeName(mod_path); - - const char* contents[] { - "PATH=", - lib_path_.constData(), - ";", - mod_path_.constData(), - ";", - getenv("PATH"), - }; - bool ok = true; + const QString orig_path = qgetenv("PATH"); - for (const char* ptr : contents) - { - if (ptr) - strcat_s(env_path, sizeof(env_path), ptr); + QString env_path; env_path.reserve(4096); - if (!ptr || ptr[0] == '\0' || env_path[0] == '\0') - { - qDebug() << "bad path element" - << (ptr == nullptr ? "<null>" : ptr); - ok = false; - break; - } - } +#if 0 + qDebug() << "orig" << orig_path; + qDebug() << "libpath" << lib_path; + qDebug() << "modpath" << mod_path; +#endif - if (ok) + if (lib_path.isEmpty()) + qDebug() << "env: empty lib_path!"; + else { - const int error = _putenv(env_path); - - if (error) - qDebug() << "can't _putenv win32 path"; + if (!QFile(lib_path).exists()) + qDebug() << "env: lib_path doesn't exist, this shouldn't happen!"; + env_path += lib_path; + env_path += ';'; } + if (mod_path.isEmpty()) + qDebug() << "env: can't add mod_path to env PATH"; else - qDebug() << "can't set win32 path"; + { + if (!QFile(mod_path).exists()) + qDebug() << "env: mod_path doesn't exist, did you install it correctly?"; + env_path += mod_path; + env_path += ';'; + } + + if (orig_path.isEmpty()) + qDebug() << "env: empty PATH"; + else + env_path += orig_path; + +#if 0 + qDebug() << "data" << env_path.constData(); +#endif + + // better length limit than putenv() and SetEnvironmentVariableA + bool ret = SetEnvironmentVariableW(L"PATH", (const wchar_t*)env_path.constData()); + + if (!ret) + qDebug() << "_putenv() failed with" << (void*)GetLastError(); } } -#include <windows.h> - -void attach_parent_console() +static void attach_parent_console() { - std::fflush(stdin); - std::fflush(stderr); + if (GetConsoleWindow() != nullptr) + return; - (void)qInstallMessageHandler(qdebug_to_console); + fflush(stdin); + fflush(stderr); if (AttachConsole(ATTACH_PARENT_PROCESS)) { @@ -159,7 +263,7 @@ void attach_parent_console() _wfreopen(L"CON", L"r", stdin); freopen("CON", "w", stdout); freopen("CON", "w", stderr); - freopen("CON", "w", stderr); + freopen("CON", "r", stdin); // skip prompt in cmd.exe window fprintf(stderr, "\n"); @@ -169,35 +273,47 @@ void attach_parent_console() #endif -int run_window(QApplication& app, std::unique_ptr<QWidget> main_window) +static int run_window(std::unique_ptr<QWidget> main_window) { if (!main_window->isEnabled()) { - qDebug() << "exit before window created"; + qDebug() << "opentrack: exit before window created"; return 2; } - app.setQuitOnLastWindowClosed(true); - int status = app.exec(); + QApplication::setQuitOnLastWindowClosed(true); + int status = QApplication::exec(); return status; } -int otr_main(int argc, char** argv, std::function<QWidget*()> make_main_window) +int otr_main(int argc, char** argv, std::function<std::unique_ptr<QWidget>()> const& make_main_window) { -#if defined OTR_HAS_DENORM_CONTROL +#ifdef _WIN32 + (void)setvbuf(stderr, nullptr, _IONBF, 0); +#else + (void)setvbuf(stderr, nullptr, _IOLBF, 256); +#endif + set_fp_mask(); + +#ifdef OTR_X11_THREADS + enable_x11_threads(); #endif QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - QCoreApplication::setAttribute(Qt::AA_X11InitThreads, true); + QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication app(argc, argv); #ifdef _WIN32 - add_win32_path(); attach_parent_console(); #endif + (void)qInstallMessageHandler(qdebug_to_console); +#ifdef _WIN32 + apply_dark_windows_theme_if_needed(); + add_win32_path(); +#endif QDir::setCurrent(OPENTRACK_BASE_PATH); @@ -213,7 +329,9 @@ int otr_main(int argc, char** argv, std::function<QWidget*()> make_main_window) qDebug() << "locale:" << forced_locale; } - const bool no_i18n = group::with_global_settings_object([](QSettings& s) { + using namespace options::globals; + + const bool no_i18n = with_global_settings_object([](QSettings& s) { return s.value("disable-translation", false).toBool(); }); @@ -224,7 +342,7 @@ int otr_main(int argc, char** argv, std::function<QWidget*()> make_main_window) } } - int ret = run_window(app, std::unique_ptr<QWidget>(make_main_window())); + int ret = run_window(make_main_window()); #if 0 // msvc crashes in Qt plugin system's dtor @@ -236,4 +354,3 @@ int otr_main(int argc, char** argv, std::function<QWidget*()> make_main_window) return ret; } - |
