8#if defined(Q_OS_VISIONOS)
9#include "qiosswiftintegration.h"
12#include <QtCore/qprocessordetection.h>
13#include <QtCore/private/qcoreapplication_p.h>
14#include <QtCore/private/qthread_p.h>
16#include <qpa/qwindowsysteminterface.h>
18#import <Foundation/NSArray.h>
19#import <Foundation/NSString.h>
20#import <Foundation/NSProcessInfo.h>
21#import <Foundation/NSThread.h>
22#import <Foundation/NSNotification.h>
24#import <UIKit/UIApplication.h>
30#define qAlignDown(val, align) val & ~(align - 1)
31#define qAlignUp(val, align) qAlignDown(val + (align - 1), align)
87 static size_t computeSize(
size_t requestedSize)
105 struct rlimit stackLimit = {0, 0};
106 if (
Q_UNLIKELY(getrlimit(RLIMIT_STACK, &stackLimit) == 0 && stackSize > stackLimit.rlim_cur))
107 qFatal(
"Unexpectedly exceeded stack limit");
114 uintptr_t memoryStart = uintptr_t(
memory);
122 if (mprotect((
void*)memoryGuardStart,
kPageSize, PROT_READ))
123 qWarning() <<
"Failed to add memory guard:" << strerror(errno);
145 static const int kScribblePattern;
149 memset_pattern4((
void*)
limit, &kScribblePattern,
size());
154 uintptr_t highWaterMark =
limit;
155 for (; highWaterMark <
base; highWaterMark += 4) {
156 if (memcmp((
void*)highWaterMark, &kScribblePattern, 4))
160 qDebug(
"main() used roughly %lu bytes of stack space", (
base - highWaterMark));
164 const int Stack::kScribblePattern = 0xfafafafa;
168 jmp_buf processEventEnterJumpPoint;
169 jmp_buf processEventExitJumpPoint;
171 bool applicationAboutToTerminate =
false;
172 jmp_buf applicationWillTerminateJumpPoint;
174 bool debugStackUsage =
false;
181 static bool s_isQtApplication =
false;
184using namespace QT_PREPEND_NAMESPACE(
QtPrivate);
188 s_isQtApplication =
true;
195 if (
infoPlistValue(
@"QtRunLoopIntegrationDisableSeparateStack",
false))
196 requestedStackSize = 0;
198 char reservedStack[Stack::computeSize(requestedStackSize)];
200 if (
sizeof(reservedStack) > 0) {
201 userMainStack.adopt(reservedStack,
sizeof(reservedStack));
203 if (
infoPlistValue(
@"QtRunLoopIntegrationDebugStackUsage",
false)) {
204 debugStackUsage =
true;
205 userMainStack.scribble();
206 qDebug(
"Effective stack size is %lu bytes", userMainStack.size());
211 lcEventDispatcher().isDebugEnabled(),
"UIApplicationMain").enter();
213#if defined(Q_OS_VISIONOS)
216 qCDebug(lcEventDispatcher) <<
"Starting Swift app";
217 QIOSIntegrationPluginSwift::runSwiftAppMain();
220 qCDebug(lcEventDispatcher) <<
"Running UIApplicationMain";
234extern "C" int main(
int argc,
char *argv[]);
240 char **argv =
new char*[argc];
242 for (
int i = 0;
i < argc; ++
i) {
245 NSStringEncoding cStringEncoding = [NSString defaultCStringEncoding];
246 unsigned int bufferSize = [
arg lengthOfBytesUsingEncoding:cStringEncoding] + 1;
247 argv[
i] =
reinterpret_cast<char *
>(malloc(bufferSize));
250 qFatal(
"Could not convert argv[%d] to C string",
i);
253 int exitCode =
main(argc, argv);
256 logActivity.applicationDidFinishLaunching.enter();
257 qCDebug(lcEventDispatcher) <<
"Returned from main with exit code " << exitCode;
260 userMainStack.printUsage();
262 logActivity.applicationDidFinishLaunching.leave();
264 if (applicationAboutToTerminate)
278 return userMainStack.isValid();
288 [[NSNotificationCenter defaultCenter]
290 selector:@selector(applicationDidFinishLaunching:)
291 name:UIApplicationDidFinishLaunchingNotification
294 [[NSNotificationCenter defaultCenter]
296 selector:@selector(applicationWillTerminate)
297 name:UIApplicationWillTerminateNotification
301#if defined(Q_PROCESSOR_X86)
302# define FUNCTION_CALL_ALIGNMENT 16
303# if defined(Q_PROCESSOR_X86_32)
304# define SET_STACK_POINTER "mov %0, %%esp"
305# elif defined(Q_PROCESSOR_X86_64)
306# define SET_STACK_POINTER "movq %0, %%rsp"
308#elif defined(Q_PROCESSOR_ARM)
310# define FUNCTION_CALL_ALIGNMENT 4
311# define SET_STACK_POINTER "mov sp, %0"
313# error "Unknown processor family"
316+ (
void)applicationDidFinishLaunching:(NSNotification *)notification
319 lcEventDispatcher().isDebugEnabled(),
"applicationDidFinishLaunching", logActivity.UIApplicationMain).enter();
321 qCDebug(lcEventDispatcher) <<
"Application launched with options" << notification.userInfo;
330 qCDebug(lcEventDispatcher) <<
"Scheduling main() on next run-loop pass";
331 CFRunLoopTimerRef userMainTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault,
332 CFAbsoluteTimeGetCurrent(), 0, 0, 0, ^(CFRunLoopTimerRef) { user_main_trampoline(); });
333 CFRunLoopAddTimer(CFRunLoopGetMain(), userMainTimer, kCFRunLoopCommonModes);
334 CFRelease(userMainTimer);
338 switch (setjmp(processEventEnterJumpPoint)) {
340 qCDebug(lcEventDispatcher) <<
"Running main() on separate stack";
347 __asm__ __volatile__(
350 :
"r" (
qAlignDown(userMainStack.base, FUNCTION_CALL_ALIGNMENT))
353 user_main_trampoline();
361 logActivity.UIApplicationMain.enter();
362 qCDebug(lcEventDispatcher) <<
"↳ Jumped from processEvents due to exec";
365 userMainStack.printUsage();
369 qFatal(
"Unexpected jump result in event loop integration");
378+ (
void)applicationWillTerminate
381 lcEventDispatcher().isDebugEnabled(),
"applicationWillTerminate", logActivity.UIApplicationMain).enter();
382 qCDebug(lcEventDispatcher) <<
"Application about to be terminated by iOS";
399 applicationAboutToTerminate =
true;
400 switch (setjmp(applicationWillTerminateJumpPoint)) {
402 qCDebug(lcEventDispatcher) <<
"Exiting qApp with SIGTERM exit code";
408 qCDebug(lcEventDispatcher) <<
"Manually triggering return from event loop exec";
409 applicationWillTerminateActivity.leave();
413 applicationWillTerminateActivity.enter();
415 qCDebug(lcEventDispatcher) <<
"kJumpedFromUserMainTrampoline, allowing iOS to terminate";
416 applicationWillTerminateActivity.leave();
419 qFatal(
"Unexpected jump result in event loop integration");
445 return s_isQtApplication;
461 QEventLoop::ProcessEventsFlags
flags
463 qCDebug(lcEventDispatcher) <<
"Sending window system events for" <<
flags;
471 , m_processEventLevel(0)
478 if (applicationAboutToTerminate) {
479 qCDebug(lcEventDispatcher) <<
"Detected QEventLoop exec after application termination";
487 qCDebug(lcEventDispatcher) <<
"Processing events with flags" <<
flags;
489 ++m_processEventLevel;
491 m_runLoopExitObserver.
addToMode(kCFRunLoopCommonModes);
495 switch (setjmp(processEventExitJumpPoint)) {
497 qCDebug(lcEventDispatcher) <<
"QEventLoop exec detected, jumping back to system runloop ↵";
505 qCDebug(lcEventDispatcher) <<
"⇢ System runloop exited, returning with eventsProcessed = true";
508 qFatal(
"Unexpected jump result in event loop integration");
514 ++m_processEventLevel;
516 --m_processEventLevel;
518 return processedEvents;
524 Q_ASSERT(activity == kCFRunLoopExit);
534 --m_processEventLevel;
541 switch (setjmp(processEventEnterJumpPoint)) {
543 qCDebug(lcEventDispatcher) <<
"Jumping into processEvents due to system runloop exit ⇢";
544 logActivity.UIApplicationMain.leave();
549 logActivity.UIApplicationMain.enter();
550 qCDebug(lcEventDispatcher) <<
"↳ Jumped from processEvents due to re-exec";
553 qFatal(
"Unexpected jump result in event loop integration");
struct capHdr __attribute__
T loadRelaxed() const noexcept
virtual bool processPostedEvents()
ProcessEventsState m_processEvents
bool processEvents(QEventLoop::ProcessEventsFlags flags) override
Processes pending events that match flags until there are no more events to process.
QEventLoop * currentEventLoop() const
static bool isQtApplication()
bool processPostedEvents() override
Override of the CoreFoundation posted events runloop source callback so that we can send window syste...
QIOSEventDispatcher(QObject *parent=nullptr)
static QIOSEventDispatcher * create()
QIOSJumpingEventDispatcher(QObject *parent=nullptr)
void interruptEventLoopExec()
bool processEvents(QEventLoop::ProcessEventsFlags flags) override
Processes pending events that match flags until there are no more events to process.
void handleRunLoopExit(CFRunLoopActivity activity)
qsizetype count() const noexcept
static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags)
static void setSynchronousWindowSystemEvents(bool enable)
void addToMode(CFStringRef mode, CFRunLoopRef runLoop=0)
void removeFromMode(CFStringRef mode, CFRunLoopRef runLoop=0)
QList< QVariant > arguments
Combined button and popup list for selecting options.
#define QT_APPLE_SCOPED_LOG_ACTIVITY(...)
#define QT_APPLE_LOG_ACTIVITY(...)
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
static const size_t kBytesPerKiloByte
#define qAlignUp(val, align)
#define qAlignDown(val, align)
int qt_main_wrapper(int argc, char *argv[])
static const char kApplicationWillTerminateExitCode
@ kJumpPointSetSuccessfully
@ kJumpedFromUserMainTrampoline
@ kJumpedFromEventLoopExecInterrupt
@ kJumpedFromEventDispatcherProcessEvents
static bool rootLevelRunLoopIntegration()
static const long kPageSize
int infoPlistValue(NSString *key, int defaultValue)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum GLsizei GLsizei GLuint memory