summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/CMakeLists.txt2
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp18
-rw-r--r--src/corelib/kernel/qcoreevent.cpp10
-rw-r--r--src/corelib/kernel/qcoreevent.h12
-rw-r--r--src/corelib/kernel/qcoreevent_p.h40
-rw-r--r--src/corelib/kernel/qobject.cpp1
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp29
-rw-r--r--tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h1
-rw-r--r--tests/auto/gui/kernel/qevent/tst_qevent.cpp1
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp5
10 files changed, 89 insertions, 30 deletions
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 164016a208..a4b654fb5c 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -152,7 +152,7 @@ qt_internal_add_module(Core
kernel/qcoreapplication.cpp kernel/qcoreapplication.h kernel/qcoreapplication_p.h
kernel/qcoreapplication_platform.h
kernel/qcorecmdlineargs_p.h
- kernel/qcoreevent.cpp kernel/qcoreevent.h
+ kernel/qcoreevent.cpp kernel/qcoreevent.h kernel/qcoreevent_p.h
kernel/qdeadlinetimer.cpp kernel/qdeadlinetimer.h
kernel/qelapsedtimer.cpp kernel/qelapsedtimer.h
kernel/qeventloop.cpp kernel/qeventloop.h kernel/qeventloop_p.h
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 52d0d2ac04..d532875c20 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -8,6 +8,7 @@
#ifndef QT_NO_QOBJECT
#include "qabstracteventdispatcher.h"
#include "qcoreevent.h"
+#include "qcoreevent_p.h"
#include "qeventloop.h"
#endif
#include "qmetaobject.h"
@@ -1660,7 +1661,10 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
int scopeLevel = data->scopeLevel;
if (scopeLevel == 0 && loopLevel != 0)
scopeLevel = 1;
- static_cast<QDeferredDeleteEvent *>(event)->level = loopLevel + scopeLevel;
+
+ QDeferredDeleteEvent *deleteEvent = static_cast<QDeferredDeleteEvent *>(event);
+ deleteEvent->m_loopLevel = loopLevel;
+ deleteEvent->m_scopeLevel = scopeLevel;
}
// delete the event on exceptions to protect against memory leaks till the event is
@@ -1849,13 +1853,15 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type
// events posted by the current event loop; or
// 3) if the event was posted before the outermost event loop.
- int eventLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel();
- int loopLevel = data->loopLevel + data->scopeLevel;
+ const int eventLoopLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->loopLevel();
+ const int eventScopeLevel = static_cast<QDeferredDeleteEvent *>(pe.event)->scopeLevel();
+
+ const bool postedBeforeOutermostLoop = eventLoopLevel == 0;
const bool allowDeferredDelete =
- (eventLevel > loopLevel
- || (!eventLevel && loopLevel > 0)
+ (eventLoopLevel + eventScopeLevel > data->loopLevel + data->scopeLevel
+ || (postedBeforeOutermostLoop && data->loopLevel > 0)
|| (event_type == QEvent::DeferredDelete
- && eventLevel == loopLevel));
+ && eventLoopLevel + eventScopeLevel == data->loopLevel + data->scopeLevel));
if (!allowDeferredDelete) {
// cannot send deferred delete
if (!event_type && !receiver) {
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index b01f1c2a69..46398872f7 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -3,6 +3,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qcoreevent.h"
+#include "qcoreevent_p.h"
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
@@ -637,19 +638,10 @@ Q_IMPL_EVENT_COMMON(QDynamicPropertyChangeEvent)
*/
QDeferredDeleteEvent::QDeferredDeleteEvent()
: QEvent(QEvent::DeferredDelete)
- , level(0)
{ }
Q_IMPL_EVENT_COMMON(QDeferredDeleteEvent)
-/*! \fn int QDeferredDeleteEvent::loopLevel() const
-
- Returns the loop-level in which the event was posted. The
- loop-level is set by QCoreApplication::postEvent().
-
- \sa QObject::deleteLater()
-*/
-
QT_END_NAMESPACE
#include "moc_qcoreevent.cpp"
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index 0c83919bc5..3acaa62a45 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -395,18 +395,6 @@ private:
QByteArray n;
};
-class Q_CORE_EXPORT QDeferredDeleteEvent : public QEvent
-{
- Q_DECL_EVENT_COMMON(QDeferredDeleteEvent)
-public:
- explicit QDeferredDeleteEvent();
- int loopLevel() const { return level; }
-
-private:
- int level;
- friend class QCoreApplication;
-};
-
QT_END_NAMESPACE
#endif // QCOREEVENT_H
diff --git a/src/corelib/kernel/qcoreevent_p.h b/src/corelib/kernel/qcoreevent_p.h
new file mode 100644
index 0000000000..edadc01374
--- /dev/null
+++ b/src/corelib/kernel/qcoreevent_p.h
@@ -0,0 +1,40 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QCOREEVENT_P_H
+#define QCOREEVENT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qcoreevent.h"
+
+QT_BEGIN_NAMESPACE
+
+class QCoreApplication;
+
+class Q_AUTOTEST_EXPORT QDeferredDeleteEvent : public QEvent
+{
+ Q_DECL_EVENT_COMMON(QDeferredDeleteEvent)
+public:
+ explicit QDeferredDeleteEvent();
+ int loopLevel() const { return m_loopLevel; }
+ int scopeLevel() const { return m_scopeLevel; }
+
+private:
+ int m_loopLevel = 0;
+ int m_scopeLevel = 0;
+ friend class QCoreApplication;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOREEVENT_P_H
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 2fc3d76898..873d3daeca 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -12,6 +12,7 @@
#include "qabstracteventdispatcher_p.h"
#include "qcoreapplication.h"
#include "qcoreapplication_p.h"
+#include "qcoreevent_p.h"
#include "qloggingcategory.h"
#include "qvariant.h"
#include "qmetaobject.h"
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
index edba67bf46..73fe06a83f 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp
@@ -9,6 +9,7 @@
#include <private/qabstracteventdispatcher_p.h> // for qGlobalPostedEventsCount()
#include <private/qcoreapplication_p.h>
+#include <private/qcoreevent_p.h>
#include <private/qeventloop_p.h>
#include <private/qthread_p.h>
@@ -24,9 +25,12 @@ class EventSpy : public QObject
public:
QList<int> recordedEvents;
- bool eventFilter(QObject *, QEvent *event) override
+ std::function<void(QObject *, QEvent *)> eventCallback;
+ bool eventFilter(QObject *target, QEvent *event) override
{
recordedEvents.append(event->type());
+ if (eventCallback)
+ eventCallback(target, event);
return false;
}
};
@@ -1081,6 +1085,29 @@ static void createQObjectOnDestruction()
}
Q_DESTRUCTOR_FUNCTION(createQObjectOnDestruction)
+void tst_QCoreApplication::testDeleteLaterFromBeforeOutermostEventLoop()
+{
+ int argc = 0;
+ QCoreApplication app(argc, nullptr);
+
+ EventSpy *spy = new EventSpy();
+ QPointer<QObject> spyPointer = spy;
+
+ app.installEventFilter(spy);
+ spy->eventCallback = [spy](QObject *, QEvent *event) {
+ if (event->type() == QEvent::User + 1)
+ spy->deleteLater();
+ };
+
+ QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
+ QCoreApplication::processEvents();
+
+ QEventLoop loop;
+ QTimer::singleShot(0, &loop, &QEventLoop::quit);
+ loop.exec();
+ QVERIFY(!spyPointer);
+}
+
#ifndef QT_QGUIAPPLICATIONTEST
QTEST_APPLESS_MAIN(tst_QCoreApplication)
#endif
diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
index 91d9324db4..8271c0cbb2 100644
--- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
+++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h
@@ -45,6 +45,7 @@ private slots:
void addRemoveLibPaths();
#endif
void theMainThread();
+ void testDeleteLaterFromBeforeOutermostEventLoop();
};
#endif // TST_QCOREAPPLICATION_H
diff --git a/tests/auto/gui/kernel/qevent/tst_qevent.cpp b/tests/auto/gui/kernel/qevent/tst_qevent.cpp
index f1ffb8c35e..56d483107b 100644
--- a/tests/auto/gui/kernel/qevent/tst_qevent.cpp
+++ b/tests/auto/gui/kernel/qevent/tst_qevent.cpp
@@ -14,7 +14,6 @@
X(QTimerEvent, (42)) \
X(QChildEvent, (QEvent::ChildAdded, nullptr)) \
X(QDynamicPropertyChangeEvent, ("size")) \
- X(QDeferredDeleteEvent, ()) \
/* qfutureinterface_p.h */ \
X(QFutureCallOutEvent, ()) \
/* end */
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index 3ed9743838..fe98b4a9c1 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -19,6 +19,7 @@
#if QT_CONFIG(process)
# include <QtCore/QProcess>
#endif
+#include <QtCore/private/qcoreevent_p.h>
#include <QtCore/private/qeventloop_p.h>
#include <QtGui/QFontDatabase>
@@ -94,7 +95,9 @@ private slots:
void libraryPaths_qt_plugin_path_2();
#endif
+#ifdef QT_BUILD_INTERNAL
void sendPostedEvents();
+#endif // ifdef QT_BUILD_INTERNAL
void thread();
void desktopSettingsAware();
@@ -1126,6 +1129,7 @@ void tst_QApplication::libraryPaths_qt_plugin_path_2()
}
#endif
+#ifdef QT_BUILD_INTERNAL
class SendPostedEventsTester : public QObject
{
Q_OBJECT
@@ -1171,6 +1175,7 @@ void tst_QApplication::sendPostedEvents()
(void) QCoreApplication::exec();
QVERIFY(p.isNull());
}
+#endif
void tst_QApplication::thread()
{