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 kwinoffscreenquickview.cpp
kwinquickeffect.cpp kwinquickeffect.cpp
logging.cpp logging.cpp
sharedqmlengine.cpp
) )
add_library(kwineffects SHARED ${kwin_EFFECTSLIB_SRCS}) add_library(kwineffects SHARED ${kwin_EFFECTSLIB_SRCS})
@ -55,7 +56,7 @@ target_link_libraries(kwineffects
XCB::XCB XCB::XCB
PRIVATE PRIVATE
Qt::Quick Qt::Quick
KF5::Declarative KF5::I18n
kwinglutils kwinglutils
) )
set_target_properties(kwineffects PROPERTIES set_target_properties(kwineffects PROPERTIES

View file

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

View file

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