mirror of
https://github.com/qmlnet/qmlnet.git
synced 2026-05-21 06:45:32 -06:00
Support for QCoreApplication, QGuiApplication, and QApplication.
This commit is contained in:
parent
28a2ae29b7
commit
72bee3f7af
10 changed files with 391 additions and 247 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
QT += gui qml core-private quickcontrols2
|
QT += gui qml core-private quickcontrols2 widgets
|
||||||
|
|
||||||
CONFIG(enable-webengine) {
|
CONFIG(enable-webengine) {
|
||||||
QT += webengine
|
QT += webengine
|
||||||
|
|
|
||||||
132
src/native/QmlNet/QmlNet/qml/QCoreApplication.cpp
Normal file
132
src/native/QmlNet/QmlNet/qml/QCoreApplication.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
#include <QmlNet/qml/QCoreApplication.h>
|
||||||
|
#include <QmlNet/qml/NetVariantList.h>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
GuiThreadContextTriggerCallback::GuiThreadContextTriggerCallback() :
|
||||||
|
callback(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void GuiThreadContextTriggerCallback::trigger() {
|
||||||
|
if (callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
Q_DECL_EXPORT QGuiApplicationContainer* qapp_fromExisting(QCoreApplication* rawPointer)
|
||||||
|
{
|
||||||
|
QGuiApplicationContainer* result = new QGuiApplicationContainer();
|
||||||
|
result->ownsApp = false;
|
||||||
|
result->app = rawPointer;
|
||||||
|
|
||||||
|
result->callback = QSharedPointer<GuiThreadContextTriggerCallback>(new GuiThreadContextTriggerCallback());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT QGuiApplicationContainer* qapp_create(NetVariantListContainer* argsContainer, int flags, int type)
|
||||||
|
{
|
||||||
|
QGuiApplicationContainer* result = new QGuiApplicationContainer();
|
||||||
|
|
||||||
|
// Build our args
|
||||||
|
if(argsContainer != nullptr) {
|
||||||
|
QSharedPointer<NetVariantList> args = argsContainer->list;
|
||||||
|
for(int x = 0; x < args->count(); x++) {
|
||||||
|
QByteArray arg = args->get(x)->getString().toLatin1();
|
||||||
|
result->args.append(arg);
|
||||||
|
char* cstr = new char [size_t(arg.size())+1];
|
||||||
|
memcpy(cstr, arg.data(), size_t(arg.size())+1);
|
||||||
|
result->argsPointer.push_back(cstr);
|
||||||
|
}
|
||||||
|
result->argCount = result->args.size();
|
||||||
|
} else {
|
||||||
|
result->argCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->ownsApp = true;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
result->app = new QCoreApplication(result->argCount, &result->argsPointer[0], flags);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
result->app = new QGuiApplication(result->argCount, &result->argsPointer[0], flags);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
result->app = new QApplication(result->argCount, &result->argsPointer[0], flags);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
qCritical("invalid app type %d", type);
|
||||||
|
delete result;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
result->callback = QSharedPointer<GuiThreadContextTriggerCallback>(new GuiThreadContextTriggerCallback());
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT void qapp_destroy(QGuiApplicationContainer* container)
|
||||||
|
{
|
||||||
|
for (auto i : container->argsPointer) {
|
||||||
|
delete[] i;
|
||||||
|
}
|
||||||
|
container->callback.clear();
|
||||||
|
if(container->ownsApp) {
|
||||||
|
delete container->app;
|
||||||
|
}
|
||||||
|
delete container;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT int qapp_getType(QGuiApplicationContainer* container, QCoreApplication* rawPointer)
|
||||||
|
{
|
||||||
|
if (!container && !rawPointer) {
|
||||||
|
qCritical("invalid container and/or rawPointer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (container && rawPointer) {
|
||||||
|
qCritical("invalid container and/or rawPointer");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(!rawPointer && container) {
|
||||||
|
rawPointer = container->app;
|
||||||
|
}
|
||||||
|
if (qobject_cast<QApplication*>(rawPointer) != nullptr){
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if (qobject_cast<QGuiApplication*>(rawPointer) != nullptr){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// QCoreApplication
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT int qapp_exec()
|
||||||
|
{
|
||||||
|
return QGuiApplication::exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT void qapp_addTriggerCallback(QGuiApplicationContainer* container, guiThreadTriggerCb callback)
|
||||||
|
{
|
||||||
|
container->callback->callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT void qapp_requestTrigger(QGuiApplicationContainer* container)
|
||||||
|
{
|
||||||
|
QMetaObject::invokeMethod(container->callback.data(), "trigger", Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT void qapp_exit(int returnCode)
|
||||||
|
{
|
||||||
|
QGuiApplication::exit(returnCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_DECL_EXPORT QCoreApplication* qapp_internalPointer(QGuiApplicationContainer* container)
|
||||||
|
{
|
||||||
|
return container->app;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -20,8 +20,8 @@ struct QGuiApplicationContainer {
|
||||||
int argCount;
|
int argCount;
|
||||||
QList<QString> args;
|
QList<QString> args;
|
||||||
std::vector<char*> argsPointer;
|
std::vector<char*> argsPointer;
|
||||||
QGuiApplication* guiApp;
|
QCoreApplication* app;
|
||||||
bool ownsGuiApp;
|
bool ownsApp;
|
||||||
QSharedPointer<GuiThreadContextTriggerCallback> callback;
|
QSharedPointer<GuiThreadContextTriggerCallback> callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
#include <QmlNet/qml/QGuiApplication.h>
|
|
||||||
#include <QmlNet/qml/NetVariantList.h>
|
|
||||||
#include <QGuiApplication>
|
|
||||||
|
|
||||||
GuiThreadContextTriggerCallback::GuiThreadContextTriggerCallback() :
|
|
||||||
callback(nullptr) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void GuiThreadContextTriggerCallback::trigger() {
|
|
||||||
if (callback) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
Q_DECL_EXPORT QGuiApplicationContainer* qguiapplication_create(NetVariantListContainer* argsContainer, QGuiApplication* existingApp) {
|
|
||||||
QGuiApplicationContainer* result = new QGuiApplicationContainer();
|
|
||||||
|
|
||||||
if (existingApp != nullptr) {
|
|
||||||
result->ownsGuiApp = false;
|
|
||||||
result->guiApp = existingApp;
|
|
||||||
} else {
|
|
||||||
result->ownsGuiApp = true;
|
|
||||||
// Build our args
|
|
||||||
if(argsContainer != nullptr) {
|
|
||||||
QSharedPointer<NetVariantList> args = argsContainer->list;
|
|
||||||
for(int x = 0; x < args->count(); x++) {
|
|
||||||
QByteArray arg = args->get(x)->getString().toLatin1();
|
|
||||||
result->args.append(arg);
|
|
||||||
char* cstr = new char [size_t(arg.size())+1];
|
|
||||||
memcpy(cstr, arg.data(), size_t(arg.size())+1);
|
|
||||||
result->argsPointer.push_back(cstr);
|
|
||||||
}
|
|
||||||
result->argCount = result->args.size();
|
|
||||||
} else {
|
|
||||||
result->argCount = 0;
|
|
||||||
}
|
|
||||||
result->guiApp = new QGuiApplication(result->argCount, &result->argsPointer[0], 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
result->callback = QSharedPointer<GuiThreadContextTriggerCallback>(new GuiThreadContextTriggerCallback());
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECL_EXPORT void qguiapplication_destroy(QGuiApplicationContainer* container) {
|
|
||||||
for (auto i : container->argsPointer) {
|
|
||||||
delete[] i;
|
|
||||||
}
|
|
||||||
container->callback.clear();
|
|
||||||
if(container->ownsGuiApp) {
|
|
||||||
delete container->guiApp;
|
|
||||||
}
|
|
||||||
delete container;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECL_EXPORT int qguiapplication_exec() {
|
|
||||||
return QGuiApplication::exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECL_EXPORT void qguiapplication_addTriggerCallback(QGuiApplicationContainer* container, guiThreadTriggerCb callback) {
|
|
||||||
container->callback->callback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECL_EXPORT void qguiapplication_requestTrigger(QGuiApplicationContainer* container) {
|
|
||||||
QMetaObject::invokeMethod(container->callback.data(), "trigger", Qt::QueuedConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECL_EXPORT void qguiapplication_exit(int returnCode) {
|
|
||||||
QGuiApplication::exit(returnCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
Q_DECL_EXPORT QGuiApplication* qguiapplication_internalPointer(QGuiApplicationContainer* container) {
|
|
||||||
return container->guiApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/QGuiApplication.h \
|
|
||||||
$$PWD/QQmlApplicationEngine.h \
|
$$PWD/QQmlApplicationEngine.h \
|
||||||
$$PWD/NetVariant.h \
|
$$PWD/NetVariant.h \
|
||||||
$$PWD/NetValue.h \
|
$$PWD/NetValue.h \
|
||||||
|
|
@ -14,10 +13,10 @@ HEADERS += \
|
||||||
$$PWD/NetValueMetaObjectPacker.h \
|
$$PWD/NetValueMetaObjectPacker.h \
|
||||||
$$PWD/QCommon.h \
|
$$PWD/QCommon.h \
|
||||||
$$PWD/NetListModel.h \
|
$$PWD/NetListModel.h \
|
||||||
$$PWD/QtWebEngine.h
|
$$PWD/QtWebEngine.h \
|
||||||
|
$$PWD/QCoreApplication.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
$$PWD/QGuiApplication.cpp \
|
|
||||||
$$PWD/QQmlApplicationEngine.cpp \
|
$$PWD/QQmlApplicationEngine.cpp \
|
||||||
$$PWD/NetVariant.cpp \
|
$$PWD/NetVariant.cpp \
|
||||||
$$PWD/NetValue.cpp \
|
$$PWD/NetValue.cpp \
|
||||||
|
|
@ -32,4 +31,5 @@ SOURCES += \
|
||||||
$$PWD/NetValueMetaObjectPacker.cpp \
|
$$PWD/NetValueMetaObjectPacker.cpp \
|
||||||
$$PWD/QCommon.cpp \
|
$$PWD/QCommon.cpp \
|
||||||
$$PWD/NetListModel.cpp \
|
$$PWD/NetListModel.cpp \
|
||||||
$$PWD/QtWebEngine.cpp
|
$$PWD/QtWebEngine.cpp \
|
||||||
|
$$PWD/QCoreApplication.cpp
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using NetNativeLibLoader.Loader;
|
using NetNativeLibLoader.Loader;
|
||||||
using NetNativeLibLoader.PathResolver;
|
using NetNativeLibLoader.PathResolver;
|
||||||
|
using Qml.Net.Internal;
|
||||||
|
|
||||||
namespace Qml.Net
|
namespace Qml.Net
|
||||||
{
|
{
|
||||||
|
|
@ -47,7 +48,7 @@ namespace Qml.Net
|
||||||
|
|
||||||
public delegate int NetRunCallbackDelegate();
|
public delegate int NetRunCallbackDelegate();
|
||||||
|
|
||||||
public static int Run(string[] args, Func<string[], QGuiApplication, QQmlApplicationEngine, NetRunCallbackDelegate, int> action)
|
public static int Run(string[] args, Func<string[], QCoreApplication, QQmlApplicationEngine, NetRunCallbackDelegate, int> action)
|
||||||
{
|
{
|
||||||
if (args.Length < 4)
|
if (args.Length < 4)
|
||||||
{
|
{
|
||||||
|
|
@ -60,7 +61,23 @@ namespace Qml.Net
|
||||||
var exportedSymbolPtr = new IntPtr((long)ulong.Parse(args[3]));
|
var exportedSymbolPtr = new IntPtr((long)ulong.Parse(args[3]));
|
||||||
GetExportedSymbol = Marshal.GetDelegateForFunctionPointer<GetExportedSymbolDelegate>(exportedSymbolPtr);
|
GetExportedSymbol = Marshal.GetDelegateForFunctionPointer<GetExportedSymbolDelegate>(exportedSymbolPtr);
|
||||||
|
|
||||||
using (var app = new QGuiApplication(appPtr))
|
QCoreApplication app = null;
|
||||||
|
switch (Interop.QCoreApplication.GetAppType(IntPtr.Zero, appPtr))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
app = new QCoreApplication(appPtr);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
app = new QGuiApplication(appPtr);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
app = new QApplication(appPtr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Invalid app type");
|
||||||
|
}
|
||||||
|
|
||||||
|
using (app)
|
||||||
{
|
{
|
||||||
using (var engine = new QQmlApplicationEngine(enginePtr))
|
using (var engine = new QQmlApplicationEngine(enginePtr))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ namespace Qml.Net.Internal
|
||||||
NetMethodInfo = LoadInteropType<NetMethodInfoInterop>(library, loader);
|
NetMethodInfo = LoadInteropType<NetMethodInfoInterop>(library, loader);
|
||||||
NetPropertyInfo = LoadInteropType<NetPropertyInfoInterop>(library, loader);
|
NetPropertyInfo = LoadInteropType<NetPropertyInfoInterop>(library, loader);
|
||||||
NetTypeManager = LoadInteropType<NetTypeManagerInterop>(library, loader);
|
NetTypeManager = LoadInteropType<NetTypeManagerInterop>(library, loader);
|
||||||
QGuiApplication = LoadInteropType<QGuiApplicationInterop>(library, loader);
|
QCoreApplication = LoadInteropType<QCoreApplicationInterop>(library, loader);
|
||||||
QQmlApplicationEngine = LoadInteropType<QQmlApplicationEngineInterop>(library, loader);
|
QQmlApplicationEngine = LoadInteropType<QQmlApplicationEngineInterop>(library, loader);
|
||||||
NetVariant = LoadInteropType<NetVariantInterop>(library, loader);
|
NetVariant = LoadInteropType<NetVariantInterop>(library, loader);
|
||||||
NetReference = LoadInteropType<NetReferenceInterop>(library, loader);
|
NetReference = LoadInteropType<NetReferenceInterop>(library, loader);
|
||||||
|
|
@ -136,7 +136,7 @@ namespace Qml.Net.Internal
|
||||||
|
|
||||||
public static NetTypeManagerInterop NetTypeManager { get; }
|
public static NetTypeManagerInterop NetTypeManager { get; }
|
||||||
|
|
||||||
public static QGuiApplicationInterop QGuiApplication { get; }
|
public static QCoreApplicationInterop QCoreApplication { get; }
|
||||||
|
|
||||||
public static QQmlApplicationEngineInterop QQmlApplicationEngine { get; }
|
public static QQmlApplicationEngineInterop QQmlApplicationEngine { get; }
|
||||||
|
|
||||||
|
|
|
||||||
25
src/net/Qml.Net/QApplication.cs
Normal file
25
src/net/Qml.Net/QApplication.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using Qml.Net.Internal;
|
||||||
|
|
||||||
|
namespace Qml.Net
|
||||||
|
{
|
||||||
|
public class QApplication : QCoreApplication
|
||||||
|
{
|
||||||
|
public QApplication()
|
||||||
|
: this(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public QApplication(string[] args, int flags = 0)
|
||||||
|
: base(1, args, flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal QApplication(IntPtr existingApp)
|
||||||
|
: base(existingApp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
202
src/net/Qml.Net/QCoreApplication.cs
Normal file
202
src/net/Qml.Net/QCoreApplication.cs
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
|
using Qml.Net.Internal;
|
||||||
|
using Qml.Net.Internal.Qml;
|
||||||
|
|
||||||
|
namespace Qml.Net
|
||||||
|
{
|
||||||
|
public class QCoreApplication : BaseDisposable
|
||||||
|
{
|
||||||
|
private readonly Queue<Action> _actionQueue = new Queue<Action>();
|
||||||
|
private readonly SynchronizationContext _oldSynchronizationContext;
|
||||||
|
private GCHandle _triggerHandle;
|
||||||
|
|
||||||
|
protected QCoreApplication(IntPtr handle, bool ownsHandle)
|
||||||
|
: base(handle, ownsHandle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public QCoreApplication()
|
||||||
|
: this(null)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public QCoreApplication(string[] args, int flags = 0)
|
||||||
|
: this(0, args, flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
internal QCoreApplication(int type, string[] args, int flags)
|
||||||
|
: base(Create(type, args?.ToList(), flags))
|
||||||
|
{
|
||||||
|
TriggerDelegate triggerDelegate = Trigger;
|
||||||
|
_triggerHandle = GCHandle.Alloc(triggerDelegate);
|
||||||
|
|
||||||
|
Interop.QCoreApplication.AddTriggerCallback(Handle, Marshal.GetFunctionPointerForDelegate(triggerDelegate));
|
||||||
|
|
||||||
|
_oldSynchronizationContext = SynchronizationContext.Current;
|
||||||
|
SynchronizationContext.SetSynchronizationContext(new QtSynchronizationContext(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal QCoreApplication(IntPtr existingApp)
|
||||||
|
: base(CreateFromExisting(existingApp))
|
||||||
|
{
|
||||||
|
TriggerDelegate triggerDelegate = Trigger;
|
||||||
|
_triggerHandle = GCHandle.Alloc(triggerDelegate);
|
||||||
|
|
||||||
|
Interop.QCoreApplication.AddTriggerCallback(Handle, Marshal.GetFunctionPointerForDelegate(triggerDelegate));
|
||||||
|
|
||||||
|
_oldSynchronizationContext = SynchronizationContext.Current;
|
||||||
|
SynchronizationContext.SetSynchronizationContext(new QtSynchronizationContext(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Exec()
|
||||||
|
{
|
||||||
|
return Interop.QCoreApplication.Exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispatch(Action action)
|
||||||
|
{
|
||||||
|
lock (_actionQueue)
|
||||||
|
{
|
||||||
|
_actionQueue.Enqueue(action);
|
||||||
|
}
|
||||||
|
RequestTrigger();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Exit(int returnCode = 0)
|
||||||
|
{
|
||||||
|
Interop.QCoreApplication.Exit(returnCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Quit()
|
||||||
|
{
|
||||||
|
Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RequestTrigger()
|
||||||
|
{
|
||||||
|
Interop.QCoreApplication.RequestTrigger(Handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IntPtr InternalPointer => Interop.QCoreApplication.InternalPointer(Handle);
|
||||||
|
|
||||||
|
private void Trigger()
|
||||||
|
{
|
||||||
|
Action action;
|
||||||
|
lock (_actionQueue)
|
||||||
|
{
|
||||||
|
action = _actionQueue.Dequeue();
|
||||||
|
}
|
||||||
|
action?.Invoke();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DisposeUnmanaged(IntPtr ptr)
|
||||||
|
{
|
||||||
|
SynchronizationContext.SetSynchronizationContext(_oldSynchronizationContext);
|
||||||
|
Interop.QCoreApplication.Destroy(ptr);
|
||||||
|
_triggerHandle.Free();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr CreateFromExisting(IntPtr app)
|
||||||
|
{
|
||||||
|
return Interop.QCoreApplication.FromExisting(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IntPtr Create(int type, List<string> args, int flags)
|
||||||
|
{
|
||||||
|
if (args == null)
|
||||||
|
{
|
||||||
|
args = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default, the argv[0] should be the process name.
|
||||||
|
// .NET doesn't pass that name, but Qt should get it
|
||||||
|
// since it does in a normal Qt environment.
|
||||||
|
args.Insert(0, System.Diagnostics.Process.GetCurrentProcess().ProcessName);
|
||||||
|
|
||||||
|
using (var strings = new NetVariantList())
|
||||||
|
{
|
||||||
|
foreach (var arg in args)
|
||||||
|
{
|
||||||
|
using (var variant = new NetVariant())
|
||||||
|
{
|
||||||
|
variant.String = arg;
|
||||||
|
strings.Add(variant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Interop.QCoreApplication.Create(strings.Handle, flags, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
|
private delegate void TriggerDelegate();
|
||||||
|
|
||||||
|
private class QtSynchronizationContext : SynchronizationContext
|
||||||
|
{
|
||||||
|
readonly QCoreApplication _app;
|
||||||
|
|
||||||
|
public QtSynchronizationContext(QCoreApplication guiApp)
|
||||||
|
{
|
||||||
|
_app = guiApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Post(SendOrPostCallback d, object state)
|
||||||
|
{
|
||||||
|
_app.Dispatch(() => d.Invoke(state));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class QCoreApplicationInterop
|
||||||
|
{
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_fromExisting")]
|
||||||
|
public FromExistingDel FromExisting { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr FromExistingDel(IntPtr rawPointer);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_create")]
|
||||||
|
public CreateDel Create { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr CreateDel(IntPtr args, int flags, int type);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_destroy")]
|
||||||
|
public DestroyDel Destroy { get; set; }
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_getType")]
|
||||||
|
public GetAppTypeDel GetAppType { get; set; }
|
||||||
|
|
||||||
|
public delegate int GetAppTypeDel(IntPtr container, IntPtr rawPointer);
|
||||||
|
|
||||||
|
public delegate void DestroyDel(IntPtr container);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_exec")]
|
||||||
|
public ExecDel Exec { get; set; }
|
||||||
|
|
||||||
|
public delegate int ExecDel();
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_addTriggerCallback")]
|
||||||
|
public AddTriggerCallbackDel AddTriggerCallback { get; set; }
|
||||||
|
|
||||||
|
public delegate void AddTriggerCallbackDel(IntPtr app, IntPtr callback);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_requestTrigger")]
|
||||||
|
public RequestTriggerDel RequestTrigger { get; set; }
|
||||||
|
|
||||||
|
public delegate void RequestTriggerDel(IntPtr app);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_exit")]
|
||||||
|
public ExitDel Exit { get; set; }
|
||||||
|
|
||||||
|
public delegate void ExitDel(int returnCode);
|
||||||
|
|
||||||
|
[NativeSymbol(Entrypoint = "qapp_internalPointer")]
|
||||||
|
public InternalPointerDel InternalPointer { get; set; }
|
||||||
|
|
||||||
|
public delegate IntPtr InternalPointerDel(IntPtr app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,175 +8,21 @@ using Qml.Net.Internal.Qml;
|
||||||
|
|
||||||
namespace Qml.Net
|
namespace Qml.Net
|
||||||
{
|
{
|
||||||
public sealed class QGuiApplication : BaseDisposable
|
public class QGuiApplication : QCoreApplication
|
||||||
{
|
{
|
||||||
readonly Queue<Action> _actionQueue = new Queue<Action>();
|
|
||||||
GCHandle _triggerHandle;
|
|
||||||
readonly SynchronizationContext _oldSynchronizationContext;
|
|
||||||
|
|
||||||
public QGuiApplication()
|
public QGuiApplication()
|
||||||
: this(null)
|
: this(null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public QGuiApplication(string[] args)
|
public QGuiApplication(string[] args, int flags = 0)
|
||||||
: base(Create(args?.ToList()))
|
: base(1, args, flags)
|
||||||
{
|
{
|
||||||
TriggerDelegate triggerDelegate = Trigger;
|
|
||||||
_triggerHandle = GCHandle.Alloc(triggerDelegate);
|
|
||||||
|
|
||||||
Interop.QGuiApplication.AddTriggerCallback(Handle, Marshal.GetFunctionPointerForDelegate(triggerDelegate));
|
|
||||||
|
|
||||||
_oldSynchronizationContext = SynchronizationContext.Current;
|
|
||||||
SynchronizationContext.SetSynchronizationContext(new QtSynchronizationContext(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal QGuiApplication(IntPtr existingApp)
|
internal QGuiApplication(IntPtr existingApp)
|
||||||
: base(CreateFromExisting(existingApp))
|
: base(existingApp)
|
||||||
{
|
{
|
||||||
TriggerDelegate triggerDelegate = Trigger;
|
|
||||||
_triggerHandle = GCHandle.Alloc(triggerDelegate);
|
|
||||||
|
|
||||||
Interop.QGuiApplication.AddTriggerCallback(Handle, Marshal.GetFunctionPointerForDelegate(triggerDelegate));
|
|
||||||
|
|
||||||
_oldSynchronizationContext = SynchronizationContext.Current;
|
|
||||||
SynchronizationContext.SetSynchronizationContext(new QtSynchronizationContext(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int Exec()
|
|
||||||
{
|
|
||||||
return Interop.QGuiApplication.Exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispatch(Action action)
|
|
||||||
{
|
|
||||||
lock (_actionQueue)
|
|
||||||
{
|
|
||||||
_actionQueue.Enqueue(action);
|
|
||||||
}
|
|
||||||
RequestTrigger();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Exit(int returnCode = 0)
|
|
||||||
{
|
|
||||||
Interop.QGuiApplication.Exit(returnCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Quit()
|
|
||||||
{
|
|
||||||
Exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RequestTrigger()
|
|
||||||
{
|
|
||||||
Interop.QGuiApplication.RequestTrigger(Handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IntPtr InternalPointer => Interop.QGuiApplication.InternalPointer(Handle);
|
|
||||||
|
|
||||||
private void Trigger()
|
|
||||||
{
|
|
||||||
Action action;
|
|
||||||
lock (_actionQueue)
|
|
||||||
{
|
|
||||||
action = _actionQueue.Dequeue();
|
|
||||||
}
|
|
||||||
action?.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void DisposeUnmanaged(IntPtr ptr)
|
|
||||||
{
|
|
||||||
SynchronizationContext.SetSynchronizationContext(_oldSynchronizationContext);
|
|
||||||
Interop.QGuiApplication.Destroy(ptr);
|
|
||||||
_triggerHandle.Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IntPtr CreateFromExisting(IntPtr app)
|
|
||||||
{
|
|
||||||
return Interop.QGuiApplication.Create(IntPtr.Zero, app);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IntPtr Create(List<string> args)
|
|
||||||
{
|
|
||||||
if (args == null)
|
|
||||||
{
|
|
||||||
args = new List<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// By default, the argv[0] should be the process name.
|
|
||||||
// .NET doesn't pass that name, but Qt should get it
|
|
||||||
// since it does in a normal Qt environment.
|
|
||||||
args.Insert(0, System.Diagnostics.Process.GetCurrentProcess().ProcessName);
|
|
||||||
|
|
||||||
using (var strings = new NetVariantList())
|
|
||||||
{
|
|
||||||
foreach (var arg in args)
|
|
||||||
{
|
|
||||||
using (var variant = new NetVariant())
|
|
||||||
{
|
|
||||||
variant.String = arg;
|
|
||||||
strings.Add(variant);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Interop.QGuiApplication.Create(strings.Handle, IntPtr.Zero);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
|
||||||
private delegate void TriggerDelegate();
|
|
||||||
|
|
||||||
private class QtSynchronizationContext : SynchronizationContext
|
|
||||||
{
|
|
||||||
readonly QGuiApplication _guiApp;
|
|
||||||
|
|
||||||
public QtSynchronizationContext(QGuiApplication guiApp)
|
|
||||||
{
|
|
||||||
_guiApp = guiApp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Post(SendOrPostCallback d, object state)
|
|
||||||
{
|
|
||||||
_guiApp.Dispatch(() => d.Invoke(state));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class QGuiApplicationInterop
|
|
||||||
{
|
|
||||||
[NativeSymbol(Entrypoint = "qguiapplication_create")]
|
|
||||||
public CreateDel Create { get; set; }
|
|
||||||
|
|
||||||
public delegate IntPtr CreateDel(IntPtr args, IntPtr existingApp);
|
|
||||||
|
|
||||||
[NativeSymbol(Entrypoint = "qguiapplication_destroy")]
|
|
||||||
public DestroyDel Destroy { get; set; }
|
|
||||||
|
|
||||||
public delegate void DestroyDel(IntPtr app);
|
|
||||||
|
|
||||||
[NativeSymbol(Entrypoint = "qguiapplication_exec")]
|
|
||||||
public ExecDel Exec { get; set; }
|
|
||||||
|
|
||||||
public delegate int ExecDel();
|
|
||||||
|
|
||||||
[NativeSymbol(Entrypoint = "qguiapplication_addTriggerCallback")]
|
|
||||||
public AddTriggerCallbackDel AddTriggerCallback { get; set; }
|
|
||||||
|
|
||||||
public delegate void AddTriggerCallbackDel(IntPtr app, IntPtr callback);
|
|
||||||
|
|
||||||
[NativeSymbol(Entrypoint = "qguiapplication_requestTrigger")]
|
|
||||||
public RequestTriggerDel RequestTrigger { get; set; }
|
|
||||||
|
|
||||||
public delegate void RequestTriggerDel(IntPtr app);
|
|
||||||
|
|
||||||
[NativeSymbol(Entrypoint = "qguiapplication_exit")]
|
|
||||||
public ExitDel Exit { get; set; }
|
|
||||||
|
|
||||||
public delegate void ExitDel(int returnCode);
|
|
||||||
|
|
||||||
[NativeSymbol(Entrypoint = "qguiapplication_internalPointer")]
|
|
||||||
public InternalPointerDel InternalPointer { get; set; }
|
|
||||||
|
|
||||||
public delegate IntPtr InternalPointerDel(IntPtr app);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue