Introduce SharedQmlEngine class

Allows to drop the direct dependency on KDeclarative only used
for `QmlObjectSharedEngine` outside of `KCModuleQML`

Signed-off-by: Eike Hein <eike.hein@mbition.io>
This commit is contained in:
Kai Uwe Broulik 2022-02-15 11:03:18 +01:00 committed by Kai Uwe Broulik
parent 158f1db513
commit 6ab7119d89
5 changed files with 103 additions and 22 deletions

View file

@ -43,6 +43,7 @@ set(kwin_EFFECTSLIB_SRCS
kwinoffscreenquickview.cpp
kwinquickeffect.cpp
logging.cpp
sharedqmlengine.cpp
)
add_library(kwineffects SHARED ${kwin_EFFECTSLIB_SRCS})
@ -55,7 +56,7 @@ target_link_libraries(kwineffects
XCB::XCB
PRIVATE
Qt::Quick
KF5::Declarative
KF5::I18n
kwinglutils
)
set_target_properties(kwineffects PROPERTIES

View file

@ -11,12 +11,14 @@
#include "kwinglutils.h"
#include "logging_p.h"
#include "sharedqmlengine.h"
#include <QGuiApplication>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQmlContext>
#include <QQmlComponent>
#include <QQmlEngine>
#include <QQuickView>
#include <QQuickRenderControl>
#include <QStyleHints>
@ -26,8 +28,6 @@
#include <QOpenGLFramebufferObject>
#include <QTimer>
#include <KDeclarative/QmlObjectSharedEngine>
namespace KWin
{
@ -87,7 +87,15 @@ public:
class Q_DECL_HIDDEN OffscreenQuickScene::Private
{
public:
KDeclarative::QmlObjectSharedEngine *qmlObject = nullptr;
Private()
: qmlEngine(SharedQmlEngine::engine())
{
}
SharedQmlEngine::Ptr qmlEngine;
QScopedPointer<QQmlComponent> qmlComponent;
QScopedPointer<QQuickItem> quickItem;
};
OffscreenQuickView::OffscreenQuickView(QObject *parent)
@ -541,44 +549,53 @@ OffscreenQuickScene::OffscreenQuickScene(QObject *parent)
: OffscreenQuickView(parent)
, d(new OffscreenQuickScene::Private)
{
d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this);
}
OffscreenQuickScene::OffscreenQuickScene(QObject *parent, QWindow *renderWindow)
: OffscreenQuickView(parent, renderWindow)
, d(new OffscreenQuickScene::Private)
{
d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this);
}
OffscreenQuickScene::OffscreenQuickScene(QObject *parent, QWindow *renderWindow, ExportMode exportMode)
: OffscreenQuickView(parent, renderWindow, exportMode)
, d(new OffscreenQuickScene::Private)
{
d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this);
}
OffscreenQuickScene::OffscreenQuickScene(QObject *parent, OffscreenQuickView::ExportMode exportMode)
: OffscreenQuickView(parent, exportMode)
, d(new OffscreenQuickScene::Private)
{
d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this);
}
OffscreenQuickScene::~OffscreenQuickScene()
{
delete d->qmlObject;
}
OffscreenQuickScene::~OffscreenQuickScene() = default;
void OffscreenQuickScene::setSource(const QUrl &source)
{
d->qmlObject->setSource(source);
if (!d->qmlComponent) {
d->qmlComponent.reset(new QQmlComponent(d->qmlEngine.data()));
}
QQuickItem *item = rootItem();
if (!item) {
qCDebug(LIBKWINEFFECTS) << "Could not load effect quick view" << source;
d->qmlComponent->loadUrl(source);
if (d->qmlComponent->isError()) {
qCWarning(LIBKWINEFFECTS).nospace() << "Failed to load effect quick view " << source << ": " << d->qmlComponent->errors();
d->qmlComponent.reset();
return;
}
d->quickItem.reset();
QScopedPointer<QObject> qmlObject(d->qmlComponent->create());
QQuickItem *item = qobject_cast<QQuickItem *>(qmlObject.data());
if (!item) {
qCWarning(LIBKWINEFFECTS) << "Root object of effect quick view" << source << "is not a QQuickItem";
return;
}
qmlObject.take();
d->quickItem.reset(item);
item->setParentItem(contentItem());
auto updateSize = [item, this]() { item->setSize(contentItem()->size()); };
@ -589,12 +606,12 @@ void OffscreenQuickScene::setSource(const QUrl &source)
QQmlContext *OffscreenQuickScene::rootContext() const
{
return d->qmlObject->rootContext();
return d->qmlEngine->rootContext();
}
QQuickItem *OffscreenQuickScene::rootItem() const
{
return qobject_cast<QQuickItem *>(d->qmlObject->rootObject());
return d->quickItem.data();
}
} // namespace KWin

View file

@ -6,9 +6,10 @@
#include "kwinquickeffect.h"
#include <KDeclarative/QmlObjectSharedEngine>
#include "sharedqmlengine.h"
#include <QQuickItem>
#include <QQmlEngine>
#include <QWindow>
namespace KWin
@ -19,7 +20,7 @@ class QuickSceneEffectPrivate
public:
static QuickSceneEffectPrivate *get(QuickSceneEffect *effect) { return effect->d.data(); }
QScopedPointer<KDeclarative::QmlObjectSharedEngine> qmlEngine;
SharedQmlEngine::Ptr qmlEngine;
QScopedPointer<QQmlComponent> qmlComponent;
QUrl source;
QHash<EffectScreen *, QuickSceneView *> views;
@ -254,11 +255,11 @@ void QuickSceneEffect::startInternal()
}
if (!d->qmlEngine) {
d->qmlEngine.reset(new KDeclarative::QmlObjectSharedEngine(this));
d->qmlEngine = SharedQmlEngine::engine();
}
if (!d->qmlComponent) {
d->qmlComponent.reset(new QQmlComponent(d->qmlEngine->engine()));
d->qmlComponent.reset(new QQmlComponent(d->qmlEngine.data()));
d->qmlComponent->loadUrl(d->source);
if (d->qmlComponent->isError()) {
qWarning().nospace() << "Failed to load " << d->source << ": " << d->qmlComponent->errors();

View file

@ -0,0 +1,35 @@
/*
SPDX-FileCopyrightText: 2022 MBition GmbH
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "sharedqmlengine.h"
#include <QQmlContext>
#include <QQmlEngine>
#include <KLocalizedContext>
namespace KWin
{
QWeakPointer<QQmlEngine> SharedQmlEngine::s_engine;
SharedQmlEngine::Ptr SharedQmlEngine::engine()
{
if (!s_engine) {
Ptr ptr(new QQmlEngine());
auto *i18nContext = new KLocalizedContext(ptr.data());
ptr->rootContext()->setContextObject(i18nContext);
s_engine = ptr;
return ptr;
}
return s_engine.toStrongRef();
}
} // namespace KWin

View file

@ -0,0 +1,27 @@
/*
SPDX-FileCopyrightText: 2022 MBition GmbH
SPDX-FileContributor: Kai Uwe Broulik <kai_uwe.broulik@mbition.io>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QSharedPointer>
class QQmlEngine;
namespace KWin
{
class SharedQmlEngine
{
public:
using Ptr = QSharedPointer<QQmlEngine>;
static Ptr engine();
private:
static QWeakPointer<QQmlEngine> s_engine;
};
} // namespace KWin