summaryrefslogtreecommitdiffhomepage
path: root/gui/init.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gui/init.cpp')
-rw-r--r--gui/init.cpp301
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;
}
-