2#include "qgc_version.h"
4#include <QtCore/QCoreApplication>
5#include <QtCore/QProcessEnvironment>
6#include <QtQuick/QQuickWindow>
7#include <QtQuick/QSGRendererInterface>
17#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)
22#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
24 #include <sys/types.h>
28#if defined(Q_OS_MACOS)
29 #include <CoreFoundation/CoreFoundation.h>
30#elif defined(Q_OS_WIN)
31 #include <qt_windows.h>
43#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
44static void showLinuxErrorDialog(
const QByteArray& msg)
48 const pid_t pid = fork();
50 const QByteArray zenityText = QByteArrayLiteral(
"--text=") + msg;
51 execlp(
"zenity",
"zenity",
"--error",
"--title=Error", zenityText.constData(),
nullptr);
52 execlp(
"kdialog",
"kdialog",
"--error", msg.constData(),
nullptr);
53 execlp(
"xmessage",
"xmessage",
"-center", msg.constData(),
nullptr);
57 (void) waitpid(pid, &status, 0);
60 fprintf(stderr,
"Error: %s\n", msg.constData());
64#if defined(Q_OS_MACOS)
65void disableAppNapViaInfoDict()
67 CFBundleRef bundle = CFBundleGetMainBundle();
71 CFMutableDictionaryRef infoDict =
const_cast<CFMutableDictionaryRef
>(CFBundleGetInfoDictionary(bundle));
73 CFDictionarySetValue(infoDict, CFSTR(
"NSAppSleepDisabled"), kCFBooleanTrue);
83int __cdecl WindowsCrtReportHook(
int reportType,
char* message,
int* returnValue)
86 std::cerr << message << std::endl;
88 if (reportType == _CRT_ASSERT) {
98void __cdecl WindowsPurecallHandler()
100 (void) OutputDebugStringW(L
"QGC: _purecall\n");
103void WindowsInvalidParameterHandler([[maybe_unused]]
const wchar_t* expression,
104 [[maybe_unused]]
const wchar_t* function,
105 [[maybe_unused]]
const wchar_t* file,
106 [[maybe_unused]]
unsigned int line,
107 [[maybe_unused]] uintptr_t pReserved)
113LPTOP_LEVEL_EXCEPTION_FILTER g_prevUef =
nullptr;
115LONG WINAPI WindowsUnhandledExceptionFilter(EXCEPTION_POINTERS* ep)
117 const DWORD code = (ep && ep->ExceptionRecord) ? ep->ExceptionRecord->ExceptionCode : 0;
118 wchar_t buf[128] = {};
120 (void) _snwprintf_s(buf, _TRUNCATE, L
"QGC: unhandled SEH 0x%08lX\n",
static_cast<unsigned long>(code));
122 (void) swprintf(buf,
static_cast<int>(std::size(buf)), L
"QGC: unhandled SEH 0x%08lX\n",
static_cast<unsigned long>(code));
124 (void) OutputDebugStringW(buf);
126 const HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
127 if (h && (h != INVALID_HANDLE_VALUE)) {
129 const char narrow[] =
"QGC: unhandled SEH\n";
130 (void) WriteFile(h, narrow, (DWORD)
sizeof(narrow) - 1, &ignored,
nullptr);
133 return EXCEPTION_EXECUTE_HANDLER;
136void setWindowsErrorModes(
bool quietWindowsAsserts)
138 (void) SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
139 g_prevUef = SetUnhandledExceptionFilter(WindowsUnhandledExceptionFilter);
142 (void) _set_invalid_parameter_handler(WindowsInvalidParameterHandler);
143 (void) _set_purecall_handler(WindowsPurecallHandler);
145 if (quietWindowsAsserts) {
146 (void) _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
147 (void) _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
148 (void) _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
149 (void) _CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, WindowsCrtReportHook);
150 (void) _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
151 (void) _set_error_mode(_OUT_TO_STDERR);
154 Q_UNUSED(quietWindowsAsserts);
164#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
165 if (isRunningAsRoot()) {
166 return showRootError(argc, argv);
170#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
184 if (!qEnvironmentVariableIsSet(
"QT_ASSUME_STDERR_HAS_CONSOLE")) {
185 (void) qputenv(
"QT_ASSUME_STDERR_HAS_CONSOLE",
"1");
187 if (!qEnvironmentVariableIsSet(
"QT_FORCE_STDERR_LOGGING")) {
188 (void) qputenv(
"QT_FORCE_STDERR_LOGGING",
"1");
194 if (!qEnvironmentVariableIsSet(
"QT_WIN_DEBUG_CONSOLE")) {
195 (void) qputenv(
"QT_WIN_DEBUG_CONSOLE",
"attach");
197 if (qEnvironmentVariable(
"QSG_RHI_BACKEND").compare(QLatin1String(
"d3d12"), Qt::CaseInsensitive) == 0) {
200 QQuickWindow::setGraphicsApi(QSGRendererInterface::Direct3D12);
206 disableAppNapViaInfoDict();
209#ifdef QGC_UNITTEST_BUILD
211 if (!qEnvironmentVariableIsSet(
"QT_QPA_PLATFORM")) {
212 (void) qputenv(
"QT_QPA_PLATFORM",
"offscreen");
220 QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
221 QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
223#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && \
224 (defined(QGC_HAS_GST_GLMEMORY_GPU_PATH) || defined(QGC_HAS_GST_DMABUF_GPU_PATH))
228 else if (!qEnvironmentVariableIsSet(
"QSG_RHI_BACKEND")) {
229 QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
234#if defined(QGC_HAS_GST_GLMEMORY_GPU_PATH) || defined(QGC_HAS_GST_DMABUF_GPU_PATH)
235 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
237 QCoreApplication::setAttribute(Qt::AA_CompressTabletEvents);
244#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)
254#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
255bool Platform::isRunningAsRoot()
257 return ::getuid() == 0;
260int Platform::showRootError([[maybe_unused]]
int argc, [[maybe_unused]]
char *argv[])
262 const QString message = QCoreApplication::translate(
"main",
263 "You are running %1 as root. "
264 "You should not do this since it will cause other issues with %1. "
265 "%1 will now exit.").arg(QLatin1String(QGC_APP_NAME));
266 showLinuxErrorDialog(message.toLocal8Bit());
271#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
274 const QString message = QCoreApplication::translate(
"main",
275 "A second instance of %1 is already running. "
276 "Please close the other instance and try again.").arg(QLatin1String(QGC_APP_NAME));
277#if defined(Q_OS_MACOS)
279 fprintf(stderr,
"Error: %s\n", message.toLocal8Bit().constData());
280 CFStringRef cfMessage = CFStringCreateWithCString(
nullptr, message.toUtf8().constData(), kCFStringEncodingUTF8);
281 CFUserNotificationDisplayAlert(0, kCFUserNotificationStopAlertLevel,
282 nullptr,
nullptr,
nullptr,
283 CFSTR(
"Error"), cfMessage,
284 nullptr,
nullptr,
nullptr,
nullptr);
285 CFRelease(cfMessage);
286#elif defined(Q_OS_WIN)
288 fprintf(stderr,
"Error: %s\n", message.toLocal8Bit().constData());
289 MessageBoxW(
nullptr, message.toStdWString().c_str(), L
"Error", MB_OK | MB_ICONERROR);
291 showLinuxErrorDialog(message.toLocal8Bit());
302 static const QString runguardString = QStringLiteral(
"%1 RunGuardKey").arg(QLatin1String(QGC_APP_NAME));
303 static RunGuard guard(runguardString);
int setupSignalHandlers()
bool checkStoragePermissions()
Result of parsing command-line arguments.
bool quietWindowsAsserts
Windows only: Disable assert dialogs.
bool listTests
List available tests and exit.
bool useSwRast
Windows/macOS: Force software OpenGL.
bool onscreen
Show test windows on screen (skip offscreen override)