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");
216 QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
217 QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL);
219#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && \
220 (defined(QGC_HAS_GST_GLMEMORY_GPU_PATH) || defined(QGC_HAS_GST_DMABUF_GPU_PATH))
224 else if (!qEnvironmentVariableIsSet(
"QSG_RHI_BACKEND")) {
225 QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
230#if defined(QGC_HAS_GST_GLMEMORY_GPU_PATH) || defined(QGC_HAS_GST_DMABUF_GPU_PATH)
231 QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
233 QCoreApplication::setAttribute(Qt::AA_CompressTabletEvents);
240#if !defined(Q_OS_IOS) && !defined(Q_OS_ANDROID)
246#if (defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_ANDROID)
247bool Platform::isRunningAsRoot()
249 return ::getuid() == 0;
252int Platform::showRootError([[maybe_unused]]
int argc, [[maybe_unused]]
char *argv[])
254 const QString message = QCoreApplication::translate(
"main",
255 "You are running %1 as root. "
256 "You should not do this since it will cause other issues with %1. "
257 "%1 will now exit.").arg(QLatin1String(QGC_APP_NAME));
258 showLinuxErrorDialog(message.toLocal8Bit());
263#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
266 const QString message = QCoreApplication::translate(
"main",
267 "A second instance of %1 is already running. "
268 "Please close the other instance and try again.").arg(QLatin1String(QGC_APP_NAME));
269#if defined(Q_OS_MACOS)
271 fprintf(stderr,
"Error: %s\n", message.toLocal8Bit().constData());
272 CFStringRef cfMessage = CFStringCreateWithCString(
nullptr, message.toUtf8().constData(), kCFStringEncodingUTF8);
273 CFUserNotificationDisplayAlert(0, kCFUserNotificationStopAlertLevel,
274 nullptr,
nullptr,
nullptr,
275 CFSTR(
"Error"), cfMessage,
276 nullptr,
nullptr,
nullptr,
nullptr);
277 CFRelease(cfMessage);
278#elif defined(Q_OS_WIN)
280 fprintf(stderr,
"Error: %s\n", message.toLocal8Bit().constData());
281 MessageBoxW(
nullptr, message.toStdWString().c_str(), L
"Error", MB_OK | MB_ICONERROR);
283 showLinuxErrorDialog(message.toLocal8Bit());
294 static const QString runguardString = QStringLiteral(
"%1 RunGuardKey").arg(QLatin1String(QGC_APP_NAME));
295 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 OpenGL.
bool onscreen
Show test windows on screen (skip offscreen override)