From 0c0fb99919bc00578ef80aafa39526b072a04505 Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Sat, 11 Feb 2023 14:05:54 +0200 Subject: [PATCH] kwineffects: Add SceneView attached property SceneView attached property is a more script friendly way to pass the information about a screen view from C++ to QML code. --- src/libkwineffects/kwinquickeffect.cpp | 57 +++++++++++++++++++++----- src/libkwineffects/kwinquickeffect.h | 11 ++++- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/libkwineffects/kwinquickeffect.cpp b/src/libkwineffects/kwinquickeffect.cpp index df7d1c8369..2902e26049 100644 --- a/src/libkwineffects/kwinquickeffect.cpp +++ b/src/libkwineffects/kwinquickeffect.cpp @@ -18,22 +18,41 @@ namespace KWin { +static QHash s_views; + class QuickSceneViewIncubator : public QQmlIncubator { public: - QuickSceneViewIncubator(const std::function &statusChangedCallback) + QuickSceneViewIncubator(QuickSceneEffect *effect, EffectScreen *screen, const std::function &statusChangedCallback) : QQmlIncubator(QQmlIncubator::Asynchronous) + , m_effect(effect) + , m_screen(screen) , m_statusChangedCallback(statusChangedCallback) { } + std::unique_ptr result() + { + return std::move(m_view); + } + + void setInitialState(QObject *object) override + { + m_view = std::make_unique(m_effect, m_screen); + m_view->setAutomaticRepaint(false); + m_view->setRootItem(qobject_cast(object)); + } + void statusChanged(QQmlIncubator::Status status) override { m_statusChangedCallback(this); } private: + QuickSceneEffect *m_effect; + EffectScreen *m_screen; std::function m_statusChangedCallback; + std::unique_ptr m_view; }; class QuickSceneEffectPrivate @@ -74,10 +93,13 @@ QuickSceneView::QuickSceneView(QuickSceneEffect *effect, EffectScreen *screen) connect(screen, &EffectScreen::geometryChanged, this, [this, screen]() { setGeometry(screen->geometry()); }); + + s_views.insert(window(), this); } QuickSceneView::~QuickSceneView() { + s_views.remove(window()); } QQuickItem *QuickSceneView::rootItem() const @@ -130,6 +152,23 @@ void QuickSceneView::scheduleRepaint() effects->addRepaint(geometry()); } +QuickSceneView *QuickSceneView::findView(QQuickItem *item) +{ + return s_views.value(item->window()); +} + +QuickSceneView *QuickSceneView::qmlAttachedProperties(QObject *object) +{ + QQuickItem *item = qobject_cast(object); + if (item) { + if (QuickSceneView *view = findView(item)) { + return view; + } + } + qCWarning(LIBKWINEFFECTS) << "Could not find SceneView for" << object; + return nullptr; +} + QuickSceneEffect::QuickSceneEffect(QObject *parent) : Effect(parent) , d(new QuickSceneEffectPrivate) @@ -366,21 +405,19 @@ void QuickSceneEffect::addScreen(EffectScreen *screen) properties["width"] = screen->geometry().width(); properties["height"] = screen->geometry().height(); - auto incubator = new QuickSceneViewIncubator([this, screen](QuickSceneViewIncubator *incubator) { + auto incubator = new QuickSceneViewIncubator(this, screen, [this, screen](QuickSceneViewIncubator *incubator) { if (incubator->isReady()) { - auto view = new QuickSceneView(this, screen); - view->setRootItem(qobject_cast(incubator->object())); + auto view = incubator->result(); if (view->contentItem()) { view->contentItem()->setFocus(false); } - view->setAutomaticRepaint(false); - connect(view, &QuickSceneView::repaintNeeded, this, [view]() { - effects->addRepaint(view->geometry()); + connect(view.get(), &QuickSceneView::repaintNeeded, this, [screen]() { + effects->addRepaint(screen->geometry()); }); - connect(view, &QuickSceneView::renderRequested, view, &QuickSceneView::scheduleRepaint); - connect(view, &QuickSceneView::sceneChanged, view, &QuickSceneView::scheduleRepaint); + connect(view.get(), &QuickSceneView::renderRequested, view.get(), &QuickSceneView::scheduleRepaint); + connect(view.get(), &QuickSceneView::sceneChanged, view.get(), &QuickSceneView::scheduleRepaint); view->scheduleRepaint(); - d->views[screen].reset(view); + d->views[screen] = std::move(view); } else if (incubator->isError()) { qCWarning(LIBKWINEFFECTS) << "Could not create a view for QML file" << d->qmlComponent->url(); qCWarning(LIBKWINEFFECTS) << incubator->errors(); diff --git a/src/libkwineffects/kwinquickeffect.h b/src/libkwineffects/kwinquickeffect.h index 008a07bb22..61f092a8e3 100644 --- a/src/libkwineffects/kwinquickeffect.h +++ b/src/libkwineffects/kwinquickeffect.h @@ -9,6 +9,8 @@ #include "kwineffects.h" #include "kwinoffscreenquickview.h" +#include + namespace KWin { @@ -26,6 +28,8 @@ class QuickSceneEffectPrivate; class KWINEFFECTS_EXPORT QuickSceneView : public OffscreenQuickView { Q_OBJECT + Q_PROPERTY(QuickSceneEffect *effect READ effect CONSTANT) + Q_PROPERTY(EffectScreen *screen READ screen CONSTANT) public: explicit QuickSceneView(QuickSceneEffect *effect, EffectScreen *screen); @@ -41,6 +45,9 @@ public: void markDirty(); void resetDirty(); + static QuickSceneView *findView(QQuickItem *item); + static QuickSceneView *qmlAttachedProperties(QObject *object); + public Q_SLOTS: void scheduleRepaint(); @@ -96,7 +103,7 @@ public: /** * Get a view at the given direction from the active view - * Returns null if no other views exist in the given direction + * Returns null if no other views exist in the given direction */ Q_INVOKABLE KWin::QuickSceneView *getView(Qt::Edge edge); @@ -166,3 +173,5 @@ private: }; } // namespace KWin + +QML_DECLARE_TYPEINFO(KWin::QuickSceneView, QML_HAS_ATTACHED_PROPERTIES)