Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qioseventdispatcher.mm
Go to the documentation of this file.
1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7#include "qiosglobal.h"
8
9#if defined(Q_OS_VISIONOS)
10#include "qiosswiftintegration.h"
11#endif
12
13#include <QtCore/qprocessordetection.h>
14#include <QtCore/private/qcoreapplication_p.h>
15#include <QtCore/private/qsystemerror_p.h>
16#include <QtCore/private/qthread_p.h>
17#include <QtCore/private/qiosrunloopintegration_p.h>
18
19#include <qpa/qwindowsysteminterface.h>
20
21#import <Foundation/NSArray.h>
22#import <Foundation/NSString.h>
23#import <Foundation/NSProcessInfo.h>
24#import <Foundation/NSThread.h>
25#import <Foundation/NSNotification.h>
26
27#import <UIKit/UIApplication.h>
28
29using namespace QT_PREPEND_NAMESPACE(QtPrivate);
30
31QT_BEGIN_NAMESPACE
32QT_USE_NAMESPACE
33
34QIOSEventDispatcher *QIOSEventDispatcher::create()
35{
36 if (isQtApplication() && [UIApplication qt_rootLevelRunLoopIntegration])
37 return new QIOSJumpingEventDispatcher;
38
39 return new QIOSEventDispatcher;
40}
41
42QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent)
43 : QEventDispatcherCoreFoundation(parent)
44{
45 // We want all delivery of events from the system to be handled synchronously
46 QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
47}
48
49bool QIOSEventDispatcher::isQtApplication()
50{
51 // Determines whether the app was started via our qt_main_wrapper
52 // in the entrypoint static library
53 static const bool result = [UIApplication.class respondsToSelector:
54 @selector(qt_rootLevelRunLoopIntegration)];
55 return result;
56}
57
58/*!
59 Override of the CoreFoundation posted events runloop source callback
60 so that we can send window system (QPA) events in addition to sending
61 normal Qt events.
62*/
63bool QIOSEventDispatcher::processPostedEvents()
64{
65 // Don't send window system events if the base CF dispatcher has determined
66 // that events should not be sent for this pass of the runloop source.
67 if (!QEventDispatcherCoreFoundation::processPostedEvents())
68 return false;
69
70 QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "sendWindowSystemEvents");
71 QEventLoop::ProcessEventsFlags flags
72 = QEventLoop::ProcessEventsFlags(m_processEvents.flags.loadRelaxed());
73 qCDebug(lcEventDispatcher) << "Sending window system events for" << flags;
74 QWindowSystemInterface::sendWindowSystemEvents(flags);
75
76 return true;
77}
78
79QIOSJumpingEventDispatcher::QIOSJumpingEventDispatcher(QObject *parent)
80 : QIOSEventDispatcher(parent)
81 , m_processEventLevel(0)
82 , m_runLoopExitObserver(this, &QIOSJumpingEventDispatcher::handleRunLoopExit, kCFRunLoopExit)
83{
84}
85
86bool __attribute__((returns_twice)) QIOSJumpingEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
87{
88 if ([UIApplication qt_applicationAboutToTerminate]) {
89 qCDebug(lcEventDispatcher) << "Detected QEventLoop exec after application termination";
90 // Re-issue exit, and return immediately
91 qApp->exit([UIApplication qt_applicationWillTerminateExitCode]);
92 return false;
93 }
94
95 const bool rootLevelProcessEvents = !m_processEventLevel;
96
97 ++m_processEventLevel;
98 bool processedEvents = false;
99
100 if (rootLevelProcessEvents && (flags & QEventLoop::EventLoopExec)) {
101 QT_APPLE_SCOPED_LOG_ACTIVITY(lcEventDispatcher().isDebugEnabled(), "processEvents");
102 qCDebug(lcEventDispatcher) << "Processing events with flags" << flags;
103
104 m_runLoopExitObserver.addToMode(kCFRunLoopCommonModes);
105 processedEvents = [UIApplication qt_eventDispatcherEnteredProcessEvents];
106 m_runLoopExitObserver.removeFromMode(kCFRunLoopCommonModes);
107 } else {
108 processedEvents = QEventDispatcherCoreFoundation::processEvents(flags);
109 }
110
111 --m_processEventLevel;
112 return processedEvents;
113}
114
115void QIOSJumpingEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
116{
117 Q_UNUSED(activity);
118 Q_ASSERT(activity == kCFRunLoopExit);
119
120 if (m_processEventLevel == 1 && !currentEventLoop()->isRunning())
121 [UIApplication qt_eventDispatcherInterruptEventLoopExec];
122}
123
124QT_END_NAMESPACE
void handleRunLoopExit(CFRunLoopActivity activity)
bool __attribute__((returns_twice)) QIOSJumpingEventDispatcher