mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 17:41:12 +02:00
Merge pull request #11319 from jherico/async_qml_load_crash
Fix potential crash on asynchronous QML loads
This commit is contained in:
commit
12d720805c
5 changed files with 39 additions and 36 deletions
|
@ -7389,7 +7389,10 @@ void Application::updateDisplayMode() {
|
||||||
getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
|
getApplicationCompositor().setDisplayPlugin(newDisplayPlugin);
|
||||||
_displayPlugin = newDisplayPlugin;
|
_displayPlugin = newDisplayPlugin;
|
||||||
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
|
connect(_displayPlugin.get(), &DisplayPlugin::presented, this, &Application::onPresent);
|
||||||
offscreenUi->getDesktop()->setProperty("repositionLocked", wasRepositionLocked);
|
auto desktop = offscreenUi->getDesktop();
|
||||||
|
if (desktop) {
|
||||||
|
desktop->setProperty("repositionLocked", wasRepositionLocked);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isHmd = _displayPlugin->isHmd();
|
bool isHmd = _displayPlugin->isHmd();
|
||||||
|
|
|
@ -169,12 +169,14 @@ void LoginDialog::openUrl(const QString& url) const {
|
||||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
|
||||||
if (tablet->getToolbarMode()) {
|
if (tablet->getToolbarMode()) {
|
||||||
auto browser = offscreenUi->load("Browser.qml");
|
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||||
browser->setProperty("url", url);
|
newObject->setProperty("url", url);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
if (!hmd->getShouldShowTablet() && !qApp->isHMDMode()) {
|
if (!hmd->getShouldShowTablet() && !qApp->isHMDMode()) {
|
||||||
auto browser = offscreenUi->load("Browser.qml");
|
offscreenUi->load("Browser.qml", [=](QQmlContext* context, QObject* newObject) {
|
||||||
browser->setProperty("url", url);
|
newObject->setProperty("url", url);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
tablet->gotoWebScreen(url);
|
tablet->gotoWebScreen(url);
|
||||||
}
|
}
|
||||||
|
|
|
@ -554,20 +554,19 @@ void OffscreenUi::createDesktop(const QUrl& url) {
|
||||||
getSurfaceContext()->setContextProperty("DebugQML", QVariant(false));
|
getSurfaceContext()->setContextProperty("DebugQML", QVariant(false));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_desktop = dynamic_cast<QQuickItem*>(load(url));
|
load(url, [=](QQmlContext* context, QObject* newObject) {
|
||||||
Q_ASSERT(_desktop);
|
_desktop = static_cast<QQuickItem*>(newObject);
|
||||||
getSurfaceContext()->setContextProperty("desktop", _desktop);
|
getSurfaceContext()->setContextProperty("desktop", _desktop);
|
||||||
|
_toolWindow = _desktop->findChild<QQuickItem*>("ToolWindow");
|
||||||
|
|
||||||
_toolWindow = _desktop->findChild<QQuickItem*>("ToolWindow");
|
_vrMenu = new VrMenu(this);
|
||||||
|
for (const auto& menuInitializer : _queuedMenuInitializers) {
|
||||||
|
menuInitializer(_vrMenu);
|
||||||
|
}
|
||||||
|
|
||||||
_vrMenu = new VrMenu(this);
|
new KeyboardFocusHack();
|
||||||
for (const auto& menuInitializer : _queuedMenuInitializers) {
|
connect(_desktop, SIGNAL(showDesktop()), this, SIGNAL(showDesktop()));
|
||||||
menuInitializer(_vrMenu);
|
});
|
||||||
}
|
|
||||||
|
|
||||||
new KeyboardFocusHack();
|
|
||||||
|
|
||||||
connect(_desktop, SIGNAL(showDesktop()), this, SIGNAL(showDesktop()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickItem* OffscreenUi::getDesktop() {
|
QQuickItem* OffscreenUi::getDesktop() {
|
||||||
|
|
|
@ -639,7 +639,7 @@ void OffscreenQmlSurface::setBaseUrl(const QUrl& baseUrl) {
|
||||||
_qmlContext->setBaseUrl(baseUrl);
|
_qmlContext->setBaseUrl(baseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f) {
|
void OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
qCWarning(uiLogging) << "Called load on a non-surface thread";
|
qCWarning(uiLogging) << "Called load on a non-surface thread";
|
||||||
}
|
}
|
||||||
|
@ -662,32 +662,32 @@ QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, bool createNewContext,
|
||||||
[this, qmlComponent, targetContext, f](QQmlComponent::Status) {
|
[this, qmlComponent, targetContext, f](QQmlComponent::Status) {
|
||||||
finishQmlLoad(qmlComponent, targetContext, f);
|
finishQmlLoad(qmlComponent, targetContext, f);
|
||||||
});
|
});
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return finishQmlLoad(qmlComponent, targetContext, f);
|
finishQmlLoad(qmlComponent, targetContext, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
void OffscreenQmlSurface::loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||||
return load(qmlSource, true, f);
|
load(qmlSource, true, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
void OffscreenQmlSurface::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
|
||||||
return load(qmlSource, false, f);
|
load(qmlSource, false, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::clearCache() {
|
void OffscreenQmlSurface::clearCache() {
|
||||||
_qmlContext->engine()->clearComponentCache();
|
_qmlContext->engine()->clearComponentCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
QObject* OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f) {
|
void OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f) {
|
||||||
disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0);
|
disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0);
|
||||||
if (qmlComponent->isError()) {
|
if (qmlComponent->isError()) {
|
||||||
for (const auto& error : qmlComponent->errors()) {
|
for (const auto& error : qmlComponent->errors()) {
|
||||||
qCWarning(uiLogging) << error.url() << error.line() << error;
|
qCWarning(uiLogging) << error.url() << error.line() << error;
|
||||||
}
|
}
|
||||||
qmlComponent->deleteLater();
|
qmlComponent->deleteLater();
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -700,7 +700,7 @@ QObject* OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlCon
|
||||||
qFatal("Unable to finish loading QML root");
|
qFatal("Unable to finish loading QML root");
|
||||||
}
|
}
|
||||||
qmlComponent->deleteLater();
|
qmlComponent->deleteLater();
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
qmlContext->engine()->setObjectOwnership(this, QQmlEngine::CppOwnership);
|
||||||
|
@ -726,19 +726,19 @@ QObject* OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlCon
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we already have a root, just set a couple of flags and the ancestry
|
// If we already have a root, just set a couple of flags and the ancestry
|
||||||
if (_rootItem) {
|
if (newItem && _rootItem) {
|
||||||
// Allow child windows to be destroyed from JS
|
// Allow child windows to be destroyed from JS
|
||||||
QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership);
|
QQmlEngine::setObjectOwnership(newObject, QQmlEngine::JavaScriptOwnership);
|
||||||
newObject->setParent(_rootItem);
|
newObject->setParent(_rootItem);
|
||||||
if (newItem) {
|
if (newItem) {
|
||||||
newItem->setParentItem(_rootItem);
|
newItem->setParentItem(_rootItem);
|
||||||
}
|
}
|
||||||
return newObject;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!newItem) {
|
if (!newItem) {
|
||||||
qFatal("Could not load object as root item");
|
qFatal("Could not load object as root item");
|
||||||
return nullptr;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
connect(newItem, SIGNAL(sendToScript(QVariant)), this, SIGNAL(fromQml(QVariant)));
|
||||||
|
@ -747,7 +747,6 @@ QObject* OffscreenQmlSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlCon
|
||||||
_rootItem = newItem;
|
_rootItem = newItem;
|
||||||
_rootItem->setParentItem(_quickWindow->contentItem());
|
_rootItem->setParentItem(_quickWindow->contentItem());
|
||||||
_rootItem->setSize(_quickWindow->renderTargetSize());
|
_rootItem->setSize(_quickWindow->renderTargetSize());
|
||||||
return _rootItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OffscreenQmlSurface::updateQuick() {
|
void OffscreenQmlSurface::updateQuick() {
|
||||||
|
|
|
@ -50,10 +50,10 @@ public:
|
||||||
void resize(const QSize& size, bool forceResize = false);
|
void resize(const QSize& size, bool forceResize = false);
|
||||||
QSize size() const;
|
QSize size() const;
|
||||||
|
|
||||||
Q_INVOKABLE QObject* load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
Q_INVOKABLE void load(const QUrl& qmlSource, bool createNewContext, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||||
Q_INVOKABLE QObject* loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
Q_INVOKABLE void loadInNewContext(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||||
Q_INVOKABLE QObject* load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
Q_INVOKABLE void load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||||
Q_INVOKABLE QObject* load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
|
Q_INVOKABLE void load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
|
||||||
return load(QUrl(qmlSourceFile), f);
|
return load(QUrl(qmlSourceFile), f);
|
||||||
}
|
}
|
||||||
void clearCache();
|
void clearCache();
|
||||||
|
@ -120,7 +120,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
static QOpenGLContext* getSharedContext();
|
static QOpenGLContext* getSharedContext();
|
||||||
|
|
||||||
QObject* finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f);
|
void finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, std::function<void(QQmlContext*, QObject*)> f);
|
||||||
QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject);
|
QPointF mapWindowToUi(const QPointF& sourcePosition, QObject* sourceObject);
|
||||||
void setupFbo();
|
void setupFbo();
|
||||||
bool allowNewFrame(uint8_t fps);
|
bool allowNewFrame(uint8_t fps);
|
||||||
|
|
Loading…
Reference in a new issue