iOS: Send window-system event also when embedded in native iOS app

The iOS event dispatcher has been split into two; one dealing with the
QPA event processing, which we should always do, and one dealing with
the longjumping that we do when running the user's main on a separate
stack.

Change-Id: I1f819db33c608aad130ff23cbbadcf84363a32d2
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
(cherry picked from commit 5414d372d4)
This commit is contained in:
Tor Arne Vestbø 2018-04-09 15:27:00 +02:00
parent dc55000140
commit 0b1342f374
3 changed files with 52 additions and 34 deletions

View File

@ -49,18 +49,29 @@ class QIOSEventDispatcher : public QEventDispatcherCoreFoundation
Q_OBJECT
public:
explicit QIOSEventDispatcher(QObject *parent = 0);
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
static QIOSEventDispatcher* create();
bool processPostedEvents() override;
protected:
explicit QIOSEventDispatcher(QObject *parent = 0);
};
class QIOSJumpingEventDispatcher : public QIOSEventDispatcher
{
Q_OBJECT
public:
QIOSJumpingEventDispatcher(QObject *parent = 0);
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
// Public since we can't friend Objective-C methods
void handleRunLoopExit(CFRunLoopActivity activity);
void interruptEventLoopExec();
private:
uint m_processEventLevel;
RunLoopObserver<QIOSEventDispatcher> m_runLoopExitObserver;
RunLoopObserver<QIOSJumpingEventDispatcher> m_runLoopExitObserver;
};
QT_END_NAMESPACE

View File

@ -403,7 +403,7 @@ static const char kApplicationWillTerminateExitCode = char(SIGTERM | 0x80);
// so we'll never see the exit activity and have a chance to return from
// QEventLoop::exec(). We initiate the return manually as a workaround.
qCDebug(lcEventDispatcher) << "Manually triggering return from event loop exec";
static_cast<QIOSEventDispatcher *>(qApp->eventDispatcher())->interruptEventLoopExec();
static_cast<QIOSJumpingEventDispatcher *>(qApp->eventDispatcher())->interruptEventLoopExec();
break;
case kJumpedFromUserMainTrampoline:
// The user's main has returned, so we're ready to let iOS terminate the application
@ -419,20 +419,48 @@ static const char kApplicationWillTerminateExitCode = char(SIGTERM | 0x80);
QT_BEGIN_NAMESPACE
QT_USE_NAMESPACE
QIOSEventDispatcher *QIOSEventDispatcher::create()
{
if (isQtApplication() && rootLevelRunLoopIntegration())
return new QIOSJumpingEventDispatcher;
return new QIOSEventDispatcher;
}
QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent)
: QEventDispatcherCoreFoundation(parent)
, m_processEventLevel(0)
, m_runLoopExitObserver(this, &QIOSEventDispatcher::handleRunLoopExit, kCFRunLoopExit)
{
// We want all delivery of events from the system to be handled synchronously
QWindowSystemInterface::setSynchronousWindowSystemEvents(true);
}
bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
/*!
Override of the CoreFoundation posted events runloop source callback
so that we can send window system (QPA) events in addition to sending
normal Qt events.
*/
bool QIOSEventDispatcher::processPostedEvents()
{
if (!rootLevelRunLoopIntegration())
return QEventDispatcherCoreFoundation::processEvents(flags);
// Don't send window system events if the base CF dispatcher has determined
// that events should not be sent for this pass of the runloop source.
if (!QEventDispatcherCoreFoundation::processPostedEvents())
return false;
qCDebug(lcEventDispatcher) << "Sending window system events for" << m_processEvents.flags;
QWindowSystemInterface::sendWindowSystemEvents(m_processEvents.flags);
return true;
}
QIOSJumpingEventDispatcher::QIOSJumpingEventDispatcher(QObject *parent)
: QIOSEventDispatcher(parent)
, m_processEventLevel(0)
, m_runLoopExitObserver(this, &QIOSJumpingEventDispatcher::handleRunLoopExit, kCFRunLoopExit)
{
}
bool __attribute__((returns_twice)) QIOSJumpingEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
{
if (applicationAboutToTerminate) {
qCDebug(lcEventDispatcher) << "Detected QEventLoop exec after application termination";
// Re-issue exit, and return immediately
@ -475,25 +503,7 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
return processedEvents;
}
/*!
Override of the CoreFoundation posted events runloop source callback
so that we can send window system (QPA) events in addition to sending
normal Qt events.
*/
bool QIOSEventDispatcher::processPostedEvents()
{
// Don't send window system events if the base CF dispatcher has determined
// that events should not be sent for this pass of the runloop source.
if (!QEventDispatcherCoreFoundation::processPostedEvents())
return false;
qCDebug(lcEventDispatcher) << "Sending window system events for" << m_processEvents.flags;
QWindowSystemInterface::sendWindowSystemEvents(m_processEvents.flags);
return true;
}
void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
void QIOSJumpingEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
{
Q_UNUSED(activity);
Q_ASSERT(activity == kCFRunLoopExit);
@ -502,7 +512,7 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
interruptEventLoopExec();
}
void QIOSEventDispatcher::interruptEventLoopExec()
void QIOSJumpingEventDispatcher::interruptEventLoopExec()
{
Q_ASSERT(m_processEventLevel == 1);

View File

@ -217,10 +217,7 @@ QPlatformOffscreenSurface *QIOSIntegration::createPlatformOffscreenSurface(QOffs
QAbstractEventDispatcher *QIOSIntegration::createEventDispatcher() const
{
if (isQtApplication())
return new QIOSEventDispatcher;
else
return new QEventDispatcherCoreFoundation;
return QIOSEventDispatcher::create();
}
QPlatformFontDatabase * QIOSIntegration::fontDatabase() const