diff --git a/examples/application_exit/CMakeLists.txt b/examples/application_exit/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..cd7380cb6e1dbe3872db65133281aa2c2c7faf33 --- /dev/null +++ b/examples/application_exit/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.16) + +project(application_exit) + +find_package(Qt6 REQUIRED COMPONENTS Quick) + +qt_standard_project_setup(REQUIRES 6.6) + +qt_add_executable(application_exit + main.cpp +) + +qt_add_qml_module(application_exit + URI applicationexit + VERSION 1.0 + QML_FILES Main.qml +) + +target_link_libraries(application_exit + PRIVATE Qt6::Quick +) + diff --git a/examples/application_exit/Main.qml b/examples/application_exit/Main.qml new file mode 100644 index 0000000000000000000000000000000000000000..ecc308d8875027ac31a2eec6348a3188547e1b55 --- /dev/null +++ b/examples/application_exit/Main.qml @@ -0,0 +1,22 @@ +import QtQuick +import QtQuick.Window + +Window { + width: 640 + height: 480 + visible: true + + Text { + text: "Click To Quit" + anchors.fill: parent + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + MouseArea { + anchors.fill: parent + onClicked: { + deleter.quit(); + } + } +} diff --git a/examples/application_exit/main.cpp b/examples/application_exit/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15d029a6d28ba6b5777f3b5d0b1688d87ed2713f --- /dev/null +++ b/examples/application_exit/main.cpp @@ -0,0 +1,57 @@ +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QQmlContext> + +#include <emscripten.h> + +class Deleter; + +QGuiApplication *g_app = nullptr; +QQmlApplicationEngine *g_engine = nullptr; + +class Deleter : public QObject +{ + Q_OBJECT +public: + explicit Deleter(QObject *parent = nullptr) + : QObject(parent) {} + + Q_INVOKABLE void quit() { + + // QCoreApplication does not support deleting itself from inside + // an event callback. Make a native zero-timer callback to make sure + // we are deleting without Qt on the stack. + emscripten_async_call([](void *deleter){ + + // Delete self + delete static_cast<Deleter *>(deleter); + + // Delete the QQmlApplicationEngine and QGuiApplication instances. + delete g_engine; g_engine = nullptr; + delete g_app; g_app = nullptr; + + // Optinally trigger runtime exit as well. + emscripten_force_exit(0); + }, this, 0); + } +}; + +int main(int argc, char *argv[]) +{ + // This example demonstrates how to cleanly exit a Qt application. + // + // This is done by creating the QML application engine and Qt application + // on the heap, and then returning from main() without calling exec(). + // + // Qt for WebAssembly supports omitting the exec() call, since the native + // event loop is already running by the time main() is called. Emscripten + // supports returning from main() without exiting the runtime, see the + // EXIT_RUNTIME linker option. + + g_app = new QGuiApplication(argc, argv); + g_engine = new QQmlApplicationEngine(); + g_engine->loadFromModule("applicationexit", "Main"); + g_engine->rootContext()->setContextProperty("deleter", new Deleter); +} + +#include "main.moc"