2#include "qgc_version.h"
4#include <QtCore/QCoreApplication>
5#include <QtCore/QProcessEnvironment>
6#include <QtQuick/QQuickWindow>
7#include <QtQuick/QSGRendererInterface>
13#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)
18#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
20 #include <sys/types.h>
24#if defined(Q_OS_MACOS)
25 #include <CoreFoundation/CoreFoundation.h>
26#elif defined(Q_OS_WIN)
27 #include <qt_windows.h>
39#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
40static void showLinuxErrorDialog(
const QByteArray& msg)
44 const pid_t pid = fork();
46 const QByteArray zenityText = QByteArrayLiteral(
"--text=") + msg;
47 execlp(
"zenity",
"zenity",
"--error",
"--title=Error", zenityText.constData(),
nullptr);
48 execlp(
"kdialog",
"kdialog",
"--error", msg.constData(),
nullptr);
49 execlp(
"xmessage",
"xmessage",
"-center", msg.constData(),
nullptr);
53 (void) waitpid(pid, &status, 0);
56 fprintf(stderr,
"Error: %s\n", msg.constData());
60#if defined(Q_OS_MACOS)
61void disableAppNapViaInfoDict()
63 CFBundleRef bundle = CFBundleGetMainBundle();
67 CFMutableDictionaryRef infoDict =
const_cast<CFMutableDictionaryRef
>(CFBundleGetInfoDictionary(bundle));
69 CFDictionarySetValue(infoDict, CFSTR(
"NSAppSleepDisabled"), kCFBooleanTrue);
79int __cdecl WindowsCrtReportHook(
int reportType,
char* message,
int* returnValue)
82 std::cerr << message << std::endl;
84 if (reportType == _CRT_ASSERT) {
94void __cdecl WindowsPurecallHandler()
96 (void) OutputDebugStringW(L
"QGC: _purecall\n");
99void WindowsInvalidParameterHandler([[maybe_unused]]
const wchar_t* expression,
100 [[maybe_unused]]
const wchar_t* function,
101 [[maybe_unused]]
const wchar_t* file,
102 [[maybe_unused]]
unsigned int line,
103 [[maybe_unused]] uintptr_t pReserved)
109LPTOP_LEVEL_EXCEPTION_FILTER g_prevUef =
nullptr;
111LONG WINAPI WindowsUnhandledExceptionFilter(EXCEPTION_POINTERS* ep)
113 const DWORD code = (ep && ep->ExceptionRecord) ? ep->ExceptionRecord->ExceptionCode : 0;
114 wchar_t buf[128] = {};
116 (void) _snwprintf_s(buf, _TRUNCATE, L
"QGC: unhandled SEH 0x%08lX\n",
static_cast<unsigned long>(code));
118 (void) swprintf(buf,
static_cast<int>(std::size(buf)), L
"QGC: unhandled SEH 0x%08lX\n",
static_cast<unsigned long>(code));
120 (void) OutputDebugStringW(buf);
122 const HANDLE h = GetStdHandle(STD_ERROR_HANDLE);
123 if (h && (h != INVALID_HANDLE_VALUE)) {
125 const char narrow[] =
"QGC: unhandled SEH\n";
126 (void) WriteFile(h, narrow, (DWORD)
sizeof(narrow) - 1, &ignored,
nullptr);
129 return EXCEPTION_EXECUTE_HANDLER;
132void setWindowsErrorModes(
bool quietWindowsAsserts)
134 (void) SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
135 g_prevUef = SetUnhandledExceptionFilter(WindowsUnhandledExceptionFilter);
138 (void) _set_invalid_parameter_handler(WindowsInvalidParameterHandler);
139 (void) _set_purecall_handler(WindowsPurecallHandler);
141 if (quietWindowsAsserts) {
142 (void) _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);
143 (void) _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
144 (void) _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
145 (void) _CrtSetReportHook2(_CRT_RPTHOOK_INSTALL, WindowsCrtReportHook);
146 (void) _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
147 (void) _set_error_mode(_OUT_TO_STDERR);
150 Q_UNUSED(quietWindowsAsserts);
160#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
161 if (isRunningAsRoot()) {
162 return showRootError(argc, argv);
166#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
180 if (!qEnvironmentVariableIsSet(
"QT_ASSUME_STDERR_HAS_CONSOLE")) {
181 (void) qputenv(
"QT_ASSUME_STDERR_HAS_CONSOLE",
"1");
183 if (!qEnvironmentVariableIsSet(
"QT_FORCE_STDERR_LOGGING")) {
184 (void) qputenv(
"QT_FORCE_STDERR_LOGGING",
"1");
190 if (!qEnvironmentVariableIsSet(
"QT_WIN_DEBUG_CONSOLE")) {
191 (void) qputenv(
"QT_WIN_DEBUG_CONSOLE",
"attach");
193 if (qEnvironmentVariable(
"QSG_RHI_BACKEND").compare(QLatin1String(
"d3d12"), Qt::CaseInsensitive) == 0) {
196 QQuickWindow::setGraphicsApi(QSGRendererInterface::Direct3D12);
202 disableAppNapViaInfoDict();
205#ifdef QGC_UNITTEST_BUILD
207 if (!qEnvironmentVariableIsSet(
"QT_QPA_PLATFORM")) {
208 (void) qputenv(
"QT_QPA_PLATFORM",
"offscreen");
217 (void) qputenv(
"QSG_RHI_PREFER_SOFTWARE_RENDERER",
"1");
220 QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
221 QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
224#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && \
225 (defined(QGC_HAS_GST_GLMEMORY_GPU_PATH) || defined(QGC_HAS_GST_DMABUF_GPU_PATH))
229 else if (!qEnvironmentVariableIsSet(
"QSG_RHI_BACKEND")) {
230 QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
235#if defined(QGC_HAS_GST_GLMEMORY_GPU_PATH) || defined(QGC_HAS_GST_DMABUF_GPU_PATH)
236 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
238 QCoreApplication::setAttribute(Qt::AA_CompressTabletEvents);
245#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)
251#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
252bool Platform::isRunningAsRoot()
254 return ::getuid() == 0;
257int Platform::showRootError([[maybe_unused]]
int argc, [[maybe_unused]]
char *argv[])
259 const QString message = QCoreApplication::translate(
"main",
260 "You are running %1 as root. "
261 "You should not do this since it will cause other issues with %1. "
262 "%1 will now exit.").arg(QLatin1String(QGC_APP_NAME));
263 showLinuxErrorDialog(message.toLocal8Bit());
268#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
271 const QString message = QCoreApplication::translate(
"main",
272 "A second instance of %1 is already running. "
273 "Please close the other instance and try again.").arg(QLatin1String(QGC_APP_NAME));
274#if defined(Q_OS_MACOS)
276 fprintf(stderr,
"Error: %s\n", message.toLocal8Bit().constData());
277 CFStringRef cfMessage = CFStringCreateWithCString(
nullptr, message.toUtf8().constData(), kCFStringEncodingUTF8);
278 CFUserNotificationDisplayAlert(0, kCFUserNotificationStopAlertLevel,
279 nullptr,
nullptr,
nullptr,
280 CFSTR(
"Error"), cfMessage,
281 nullptr,
nullptr,
nullptr,
nullptr);
282 CFRelease(cfMessage);
283#elif defined(Q_OS_WIN)
285 fprintf(stderr,
"Error: %s\n", message.toLocal8Bit().constData());
286 MessageBoxW(
nullptr, message.toStdWString().c_str(), L
"Error", MB_OK | MB_ICONERROR);
288 showLinuxErrorDialog(message.toLocal8Bit());
299 static const QString runguardString = QStringLiteral(
"%1 RunGuardKey").arg(QLatin1String(QGC_APP_NAME));
300 static RunGuard guard(runguardString);
int setupSignalHandlers()
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 rendering.
bool onscreen
Show test windows on screen (skip offscreen override)