From 9cb5b3897004029fb53dc80750859290661c234e Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Mon, 9 May 2022 15:25:49 +0200 Subject: [PATCH] effects: Port EffectFrame to OffscreenQuickView This allows to toss a large amount of custom rendering code. Furthermore, it removes the build-time dependency on Plasma Framework for FrameSvg and Theme from KWin core as it's pulled in through QML imports now. It also cleans up the API and removes functions that are effectively unused or no-op after this change. For instance, effects often destroy their effect frames in pre/postPaintScreen, which would now destroy an `OffscreenQuickView`, which changes GL context. This is alleviated by delaying detruction of the internal view. Support for the features of text cross-fade and selection frame, which are not used by any of the built-in effects, is dropped. Signed-off-by: Eike Hein --- src/CMakeLists.txt | 2 +- src/effects.cpp | 455 ++++++++++++-------- src/effects.h | 150 ++++--- src/effects/backgroundcontrast/contrast.cpp | 6 - src/effects/backgroundcontrast/contrast.h | 1 - src/effects/blur/blur.cpp | 13 - src/effects/blur/blur.h | 1 - src/effects/invert/invert.cpp | 11 - src/effects/invert/invert.h | 1 - src/libkwineffects/kwineffects.cpp | 15 - src/libkwineffects/kwineffects.h | 56 +-- src/qml/CMakeLists.txt | 2 +- src/qml/frames/plasma/frame_none.qml | 39 ++ src/qml/frames/plasma/frame_styled.qml | 60 +++ src/qml/frames/plasma/frame_unstyled.qml | 53 +++ src/scene.cpp | 12 - src/scene.h | 23 - src/scenes/opengl/scene_opengl.cpp | 441 ------------------- src/scenes/opengl/scene_opengl.h | 39 -- src/scenes/qpainter/scene_qpainter.cpp | 82 ---- src/scenes/qpainter/scene_qpainter.h | 30 -- 21 files changed, 521 insertions(+), 971 deletions(-) create mode 100644 src/qml/frames/plasma/frame_none.qml create mode 100644 src/qml/frames/plasma/frame_styled.qml create mode 100644 src/qml/frames/plasma/frame_unstyled.qml diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a2b4953308..471a1f7eba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -179,7 +179,7 @@ target_link_libraries(kwin KF5::GlobalAccelPrivate KF5::I18n KF5::Package - KF5::Plasma + KF5::Service KF5::WindowSystem KDecoration2::KDecoration diff --git a/src/effects.cpp b/src/effects.cpp index b090d8834f..c44f237d5b 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -42,7 +42,6 @@ #include "inputmethod.h" #include "inputpanelv1window.h" #include "kwinglutils.h" -#include "kwinoffscreenquickview.h" #include "platform.h" #include "utils/xcbutils.h" #include "virtualdesktops.h" @@ -52,13 +51,15 @@ #include "windowitem.h" #include "workspace.h" -#include - #include #include #include #include +#include +#include +#include +#include #include namespace KWin @@ -408,17 +409,6 @@ void EffectsHandlerImpl::paintWindow(EffectWindow *w, int mask, const QRegion &r } } -void EffectsHandlerImpl::paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) -{ - if (m_currentPaintEffectFrameIterator != m_activeEffects.constEnd()) { - (*m_currentPaintEffectFrameIterator++)->paintEffectFrame(frame, region, opacity, frameOpacity); - --m_currentPaintEffectFrameIterator; - } else { - const EffectFrameImpl *frameImpl = static_cast(frame); - frameImpl->finalRender(region, opacity, frameOpacity); - } -} - void EffectsHandlerImpl::postPaintWindow(EffectWindow *w) { if (m_currentPaintWindowIterator != m_activeEffects.constEnd()) { @@ -471,7 +461,6 @@ void EffectsHandlerImpl::startPaint() m_currentDrawWindowIterator = m_activeEffects.constBegin(); m_currentPaintWindowIterator = m_activeEffects.constBegin(); m_currentPaintScreenIterator = m_activeEffects.constBegin(); - m_currentPaintEffectFrameIterator = m_activeEffects.constBegin(); } void EffectsHandlerImpl::slotClientMaximized(Window *window, MaximizeMode maxMode) @@ -2289,240 +2278,356 @@ EffectWindowList EffectWindowGroupImpl::members() const // EffectFrameImpl //**************************************** -EffectFrameImpl::EffectFrameImpl(EffectFrameStyle style, bool staticSize, QPoint position, Qt::Alignment alignment) - : QObject(nullptr) - , EffectFrame() +EffectFrameQuickScene::EffectFrameQuickScene(EffectFrameStyle style, bool staticSize, QPoint position, + Qt::Alignment alignment, QObject *parent) + : OffscreenQuickScene(parent) , m_style(style) , m_static(staticSize) , m_point(position) , m_alignment(alignment) - , m_shader(nullptr) - , m_theme(new Plasma::Theme(this)) { - if (m_style == EffectFrameStyled) { - m_frame.setImagePath(QStringLiteral("widgets/background")); - m_frame.setCacheAllRenderedFrames(true); - connect(m_theme, &Plasma::Theme::themeChanged, this, &EffectFrameImpl::plasmaThemeChanged); + + QString name; + switch (style) { + case EffectFrameNone: + name = QStringLiteral("none"); + break; + case EffectFrameUnstyled: + name = QStringLiteral("unstyled"); + break; + case EffectFrameStyled: + name = QStringLiteral("styled"); + break; } - m_selection.setImagePath(QStringLiteral("widgets/viewitem")); - m_selection.setElementPrefix(QStringLiteral("hover")); - m_selection.setCacheAllRenderedFrames(true); - m_selection.setEnabledBorders(Plasma::FrameSvg::AllBorders); - m_sceneFrame = Compositor::self()->scene()->createEffectFrame(this); + const QString defaultPath = QStringLiteral(KWIN_NAME "/frames/plasma/frame_%1.qml").arg(name); + // TODO read from kwinApp()->config() "QmlPath" like Outline/OnScreenNotification + // *if* someone really needs this to be configurable. + const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, defaultPath); + + setSource(QUrl::fromLocalFile(path), QVariantMap{{QStringLiteral("effectFrame"), QVariant::fromValue(this)}}); + + if (rootItem()) { + connect(rootItem(), &QQuickItem::implicitWidthChanged, this, &EffectFrameQuickScene::reposition); + connect(rootItem(), &QQuickItem::implicitHeightChanged, this, &EffectFrameQuickScene::reposition); + } } -EffectFrameImpl::~EffectFrameImpl() +EffectFrameQuickScene::~EffectFrameQuickScene() = default; + +EffectFrameStyle EffectFrameQuickScene::style() const { - delete m_sceneFrame; + return m_style; } -const QFont &EffectFrameImpl::font() const +bool EffectFrameQuickScene::isStatic() const +{ + return m_static; +} + +const QFont &EffectFrameQuickScene::font() const { return m_font; } -void EffectFrameImpl::setFont(const QFont &font) +void EffectFrameQuickScene::setFont(const QFont &font) { if (m_font == font) { return; } + m_font = font; - QRect oldGeom = m_geometry; - if (!m_text.isEmpty()) { - autoResize(); + Q_EMIT fontChanged(font); + reposition(); +} + +const QIcon &EffectFrameQuickScene::icon() const +{ + return m_icon; +} + +void EffectFrameQuickScene::setIcon(const QIcon &icon) +{ + m_icon = icon; + Q_EMIT iconChanged(icon); + reposition(); +} + +const QSize &EffectFrameQuickScene::iconSize() const +{ + return m_iconSize; +} + +void EffectFrameQuickScene::setIconSize(const QSize &iconSize) +{ + if (m_iconSize == iconSize) { + return; } - if (oldGeom == m_geometry) { - // Wasn't updated in autoResize() - m_sceneFrame->freeTextFrame(); + + m_iconSize = iconSize; + Q_EMIT iconSizeChanged(iconSize); + reposition(); +} + +const QString &EffectFrameQuickScene::text() const +{ + return m_text; +} + +void EffectFrameQuickScene::setText(const QString &text) +{ + if (m_text == text) { + return; } + + m_text = text; + Q_EMIT textChanged(text); + reposition(); +} + +qreal EffectFrameQuickScene::frameOpacity() const +{ + return m_frameOpacity; +} + +void EffectFrameQuickScene::setFrameOpacity(qreal frameOpacity) +{ + if (m_frameOpacity != frameOpacity) { + m_frameOpacity = frameOpacity; + Q_EMIT frameOpacityChanged(frameOpacity); + } +} + +bool EffectFrameQuickScene::crossFadeEnabled() const +{ + return m_crossFadeEnabled; +} + +void EffectFrameQuickScene::setCrossFadeEnabled(bool enabled) +{ + if (m_crossFadeEnabled != enabled) { + m_crossFadeEnabled = enabled; + Q_EMIT crossFadeEnabledChanged(enabled); + } +} + +qreal EffectFrameQuickScene::crossFadeProgress() const +{ + return m_crossFadeProgress; +} + +void EffectFrameQuickScene::setCrossFadeProgress(qreal progress) +{ + if (m_crossFadeProgress != progress) { + m_crossFadeProgress = progress; + Q_EMIT crossFadeProgressChanged(progress); + } +} + +Qt::Alignment EffectFrameQuickScene::alignment() const +{ + return m_alignment; +} + +void EffectFrameQuickScene::setAlignment(Qt::Alignment alignment) +{ + if (m_alignment == alignment) { + return; + } + + m_alignment = alignment; + reposition(); +} + +QPoint EffectFrameQuickScene::position() const +{ + return m_point; +} + +void EffectFrameQuickScene::setPosition(const QPoint &point) +{ + if (m_point == point) { + return; + } + + m_point = point; + reposition(); +} + +void EffectFrameQuickScene::reposition() +{ + if (!rootItem() || m_point.x() < 0 || m_point.y() < 0) { + return; + } + + QSizeF size; + if (m_static) { + size = rootItem()->size(); + } else { + size = QSizeF(rootItem()->implicitWidth(), rootItem()->implicitHeight()); + } + + QRect geometry(QPoint(), size.toSize()); + + if (m_alignment & Qt::AlignLeft) + geometry.moveLeft(m_point.x()); + else if (m_alignment & Qt::AlignRight) + geometry.moveLeft(m_point.x() - geometry.width()); + else + geometry.moveLeft(m_point.x() - geometry.width() / 2); + if (m_alignment & Qt::AlignTop) + geometry.moveTop(m_point.y()); + else if (m_alignment & Qt::AlignBottom) + geometry.moveTop(m_point.y() - geometry.height()); + else + geometry.moveTop(m_point.y() - geometry.height() / 2); + + if (geometry == this->geometry()) { + return; + } + + setGeometry(geometry); +} + +EffectFrameImpl::EffectFrameImpl(EffectFrameStyle style, bool staticSize, QPoint position, Qt::Alignment alignment) + : QObject(nullptr) + , EffectFrame() + , m_view(new EffectFrameQuickScene(style, staticSize, position, alignment, nullptr)) +{ + connect(m_view, &OffscreenQuickScene::repaintNeeded, this, [this] { + effects->addRepaint(geometry()); + }); + connect(m_view, &OffscreenQuickScene::geometryChanged, this, [this](const QRect &oldGeometry, const QRect &newGeometry) { + effects->addRepaint(oldGeometry); + m_geometry = newGeometry; + effects->addRepaint(newGeometry); + }); +} + +EffectFrameImpl::~EffectFrameImpl() +{ + // Effects often destroy their cached TextFrames in pre/postPaintScreen. + // Destroying an OffscreenQuickView changes GL context, which we + // must not do during effect rendering. + // Delay destruction of the view until after the rendering. + m_view->deleteLater(); +} + +Qt::Alignment EffectFrameImpl::alignment() const +{ + return m_view->alignment(); +} + +void EffectFrameImpl::setAlignment(Qt::Alignment alignment) +{ + m_view->setAlignment(alignment); +} + +const QFont &EffectFrameImpl::font() const +{ + return m_view->font(); +} + +void EffectFrameImpl::setFont(const QFont &font) +{ + m_view->setFont(font); } void EffectFrameImpl::free() { - m_sceneFrame->free(); + m_view->hide(); } const QRect &EffectFrameImpl::geometry() const { + // Can't forward to OffscreenQuickScene::geometry() because we return a reference. return m_geometry; } void EffectFrameImpl::setGeometry(const QRect &geometry, bool force) { - QRect oldGeom = m_geometry; - m_geometry = geometry; - if (m_geometry == oldGeom && !force) { - return; - } - effects->addRepaint(oldGeom); - effects->addRepaint(m_geometry); - if (m_geometry.size() == oldGeom.size() && !force) { - return; - } - - if (m_style == EffectFrameStyled) { - qreal left, top, right, bottom; - m_frame.getMargins(left, top, right, bottom); // m_geometry is the inner geometry - m_frame.resizeFrame(m_geometry.adjusted(-left, -top, right, bottom).size()); - } - - free(); + Q_UNUSED(force) + m_view->setGeometry(geometry); } const QIcon &EffectFrameImpl::icon() const { - return m_icon; + return m_view->icon(); } void EffectFrameImpl::setIcon(const QIcon &icon) { - m_icon = icon; - if (isCrossFade()) { - m_sceneFrame->crossFadeIcon(); + m_view->setIcon(icon); + + if (m_view->iconSize().isEmpty() && !icon.availableSizes().isEmpty()) { // Set a size if we don't already have one + setIconSize(icon.availableSizes().constFirst()); } - if (m_iconSize.isEmpty() && !m_icon.availableSizes().isEmpty()) { // Set a size if we don't already have one - setIconSize(m_icon.availableSizes().constFirst()); - } - m_sceneFrame->freeIconFrame(); } const QSize &EffectFrameImpl::iconSize() const { - return m_iconSize; + return m_view->iconSize(); } void EffectFrameImpl::setIconSize(const QSize &size) { - if (m_iconSize == size) { - return; - } - m_iconSize = size; - autoResize(); - m_sceneFrame->freeIconFrame(); -} - -void EffectFrameImpl::plasmaThemeChanged() -{ - free(); -} - -void EffectFrameImpl::render(const QRegion ®ion, double opacity, double frameOpacity) -{ - if (m_geometry.isEmpty()) { - return; // Nothing to display - } - m_shader = nullptr; - setScreenProjectionMatrix(static_cast(effects)->scene()->screenProjectionMatrix()); - effects->paintEffectFrame(this, region, opacity, frameOpacity); -} - -void EffectFrameImpl::finalRender(QRegion region, double opacity, double frameOpacity) const -{ - region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL - - m_sceneFrame->render(region, opacity, frameOpacity); -} - -Qt::Alignment EffectFrameImpl::alignment() const -{ - return m_alignment; -} - -void EffectFrameImpl::align(QRect &geometry) -{ - if (m_alignment & Qt::AlignLeft) { - geometry.moveLeft(m_point.x()); - } else if (m_alignment & Qt::AlignRight) { - geometry.moveLeft(m_point.x() - geometry.width()); - } else { - geometry.moveLeft(m_point.x() - geometry.width() / 2); - } - if (m_alignment & Qt::AlignTop) { - geometry.moveTop(m_point.y()); - } else if (m_alignment & Qt::AlignBottom) { - geometry.moveTop(m_point.y() - geometry.height()); - } else { - geometry.moveTop(m_point.y() - geometry.height() / 2); - } -} - -void EffectFrameImpl::setAlignment(Qt::Alignment alignment) -{ - m_alignment = alignment; - align(m_geometry); - setGeometry(m_geometry); + m_view->setIconSize(size); } void EffectFrameImpl::setPosition(const QPoint &point) { - m_point = point; - QRect geometry = m_geometry; // this is important, setGeometry need call repaint for old & new geometry - align(geometry); - setGeometry(geometry); + m_view->setPosition(point); +} + +void EffectFrameImpl::render(const QRegion ®ion, double opacity, double frameOpacity) +{ + Q_UNUSED(region); + + if (!m_view->rootItem()) { + return; + } + + m_view->show(); + + m_view->setOpacity(opacity); + m_view->setFrameOpacity(frameOpacity); + + effects->renderOffscreenQuickView(m_view); } const QString &EffectFrameImpl::text() const { - return m_text; + return m_view->text(); } void EffectFrameImpl::setText(const QString &text) { - if (m_text == text) { - return; - } - if (isCrossFade()) { - m_sceneFrame->crossFadeText(); - } - m_text = text; - QRect oldGeom = m_geometry; - autoResize(); - if (oldGeom == m_geometry) { - // Wasn't updated in autoResize() - m_sceneFrame->freeTextFrame(); - } + m_view->setText(text); } -void EffectFrameImpl::setSelection(const QRect &selection) +EffectFrameStyle EffectFrameImpl::style() const { - if (selection == m_selectionGeometry) { - return; - } - m_selectionGeometry = selection; - if (m_selectionGeometry.size() != m_selection.frameSize().toSize()) { - m_selection.resizeFrame(m_selectionGeometry.size()); - } - // TODO; optimize to only recreate when resizing - m_sceneFrame->freeSelection(); + return m_view->style(); } -void EffectFrameImpl::autoResize() +bool EffectFrameImpl::isCrossFade() const { - if (m_static) { - return; // Not automatically resizing - } - - QRect geometry; - // Set size - if (!m_text.isEmpty()) { - QFontMetrics metrics(m_font); - geometry.setSize(metrics.size(0, m_text)); - } - if (!m_icon.isNull() && !m_iconSize.isEmpty()) { - geometry.setLeft(-m_iconSize.width()); - if (m_iconSize.height() > geometry.height()) { - geometry.setHeight(m_iconSize.height()); - } - } - - align(geometry); - setGeometry(geometry); + return m_view->crossFadeEnabled(); } -QColor EffectFrameImpl::styledTextColor() +void EffectFrameImpl::enableCrossFade(bool enable) { - return m_theme->color(Plasma::Theme::TextColor); + m_view->setCrossFadeEnabled(enable); +} + +qreal EffectFrameImpl::crossFadeProgress() const +{ + return m_view->crossFadeProgress(); +} + +void EffectFrameImpl::setCrossFadeProgress(qreal progress) +{ + m_view->setCrossFadeProgress(progress); } } // namespace diff --git a/src/effects.h b/src/effects.h index c407fbd9c2..55a7d067b1 100644 --- a/src/effects.h +++ b/src/effects.h @@ -13,9 +13,10 @@ #include "kwineffects.h" +#include "kwinoffscreenquickview.h" #include "scene.h" -#include +#include #include #include @@ -23,11 +24,6 @@ class QMouseEvent; class QWheelEvent; -namespace Plasma -{ -class Theme; -} - namespace KWaylandServer { class Display; @@ -65,7 +61,6 @@ public: void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void paintWindow(EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; void postPaintWindow(EffectWindow *w) override; - void paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) override; Effect *provides(Effect::Feature ef); @@ -341,7 +336,6 @@ private: EffectsList m_activeEffects; EffectsIterator m_currentDrawWindowIterator; EffectsIterator m_currentPaintWindowIterator; - EffectsIterator m_currentPaintEffectFrameIterator; EffectsIterator m_currentPaintScreenIterator; typedef QHash> PropertyEffectMap; PropertyEffectMap m_propertiesForEffects; @@ -530,6 +524,81 @@ private: Group *group; }; +class EffectFrameQuickScene : public OffscreenQuickScene +{ + Q_OBJECT + + Q_PROPERTY(QFont font READ font NOTIFY fontChanged) + Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged) + Q_PROPERTY(QSize iconSize READ iconSize NOTIFY iconSizeChanged) + Q_PROPERTY(QString text READ text NOTIFY textChanged) + Q_PROPERTY(qreal frameOpacity READ frameOpacity NOTIFY frameOpacityChanged) + Q_PROPERTY(bool crossFadeEnabled READ crossFadeEnabled NOTIFY crossFadeEnabledChanged) + Q_PROPERTY(qreal crossFadeProgress READ crossFadeProgress NOTIFY crossFadeProgressChanged) + +public: + EffectFrameQuickScene(EffectFrameStyle style, bool staticSize, QPoint position, + Qt::Alignment alignment, QObject *parent = nullptr); + ~EffectFrameQuickScene() override; + + EffectFrameStyle style() const; + bool isStatic() const; + + // has to be const-ref to match EffectFrameImpl... + const QFont &font() const; + void setFont(const QFont &font); + Q_SIGNAL void fontChanged(const QFont &font); + + const QIcon &icon() const; + void setIcon(const QIcon &icon); + Q_SIGNAL void iconChanged(const QIcon &icon); + + const QSize &iconSize() const; + void setIconSize(const QSize &iconSize); + Q_SIGNAL void iconSizeChanged(const QSize &iconSize); + + const QString &text() const; + void setText(const QString &text); + Q_SIGNAL void textChanged(const QString &text); + + qreal frameOpacity() const; + void setFrameOpacity(qreal frameOpacity); + Q_SIGNAL void frameOpacityChanged(qreal frameOpacity); + + bool crossFadeEnabled() const; + void setCrossFadeEnabled(bool enabled); + Q_SIGNAL void crossFadeEnabledChanged(bool enabled); + + qreal crossFadeProgress() const; + void setCrossFadeProgress(qreal progress); + Q_SIGNAL void crossFadeProgressChanged(qreal progress); + + Qt::Alignment alignment() const; + void setAlignment(Qt::Alignment alignment); + + QPoint position() const; + void setPosition(const QPoint &point); + +private: + void reposition(); + + EffectFrameStyle m_style; + + // Position + bool m_static; + QPoint m_point; + Qt::Alignment m_alignment; + + // Contents + QFont m_font; + QIcon m_icon; + QSize m_iconSize; + QString m_text; + qreal m_frameOpacity = 0.0; + bool m_crossFadeEnabled = false; + qreal m_crossFadeProgress = 0.0; +}; + class KWIN_EXPORT EffectFrameImpl : public QObject, public EffectFrame @@ -555,70 +624,17 @@ public: void setPosition(const QPoint &point) override; const QString &text() const override; void setText(const QString &text) override; - EffectFrameStyle style() const override - { - return m_style; - } - Plasma::FrameSvg &frame() - { - return m_frame; - } - bool isStatic() const - { - return m_static; - } - void finalRender(QRegion region, double opacity, double frameOpacity) const; - void setShader(GLShader *shader) override - { - m_shader = shader; - } - GLShader *shader() const override - { - return m_shader; - } - void setSelection(const QRect &selection) override; - const QRect &selection() const - { - return m_selectionGeometry; - } - Plasma::FrameSvg &selectionFrame() - { - return m_selection; - } - /** - * The foreground text color as specified by the default Plasma theme. - */ - QColor styledTextColor(); - -private Q_SLOTS: - void plasmaThemeChanged(); + EffectFrameStyle style() const override; + bool isCrossFade() const override; + void enableCrossFade(bool enable) override; + qreal crossFadeProgress() const override; + void setCrossFadeProgress(qreal progress) override; private: Q_DISABLE_COPY(EffectFrameImpl) // As we need to use Qt slots we cannot copy this class - void align(QRect &geometry); // positions geometry around m_point respecting m_alignment - void autoResize(); // Auto-resize if not a static size - EffectFrameStyle m_style; - Plasma::FrameSvg m_frame; // TODO: share between all EffectFrames - Plasma::FrameSvg m_selection; - - // Position - bool m_static; - QPoint m_point; - Qt::Alignment m_alignment; + EffectFrameQuickScene *m_view; QRect m_geometry; - - // Contents - QString m_text; - QFont m_font; - QIcon m_icon; - QSize m_iconSize; - QRect m_selectionGeometry; - - Scene::EffectFrame *m_sceneFrame; - GLShader *m_shader; - - Plasma::Theme *m_theme; }; inline QList EffectsHandlerImpl::elevatedWindows() const diff --git a/src/effects/backgroundcontrast/contrast.cpp b/src/effects/backgroundcontrast/contrast.cpp index 0500f47129..987c18a9a5 100644 --- a/src/effects/backgroundcontrast/contrast.cpp +++ b/src/effects/backgroundcontrast/contrast.cpp @@ -409,12 +409,6 @@ void ContrastEffect::drawWindow(EffectWindow *w, int mask, const QRegion ®ion effects->drawWindow(w, mask, region, data); } -void ContrastEffect::paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) -{ - // FIXME: this is a no-op for now, it should figure out the right contrast, intensity, saturation - effects->paintEffectFrame(frame, region, opacity, frameOpacity); -} - void ContrastEffect::doContrast(EffectWindow *w, const QRegion &shape, const QRect &screen, const float opacity, const QMatrix4x4 &screenProjection) { const QRegion actualShape = shape & screen; diff --git a/src/effects/backgroundcontrast/contrast.h b/src/effects/backgroundcontrast/contrast.h index 7f912c113f..d8dcb5e6c1 100644 --- a/src/effects/backgroundcontrast/contrast.h +++ b/src/effects/backgroundcontrast/contrast.h @@ -37,7 +37,6 @@ public: static QMatrix4x4 colorMatrix(qreal contrast, qreal intensity, qreal saturation); void drawWindow(EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; - void paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) override; bool provides(Feature feature) override; bool isActive() const override; diff --git a/src/effects/blur/blur.cpp b/src/effects/blur/blur.cpp index 2fefd8485f..42c28dffb7 100644 --- a/src/effects/blur/blur.cpp +++ b/src/effects/blur/blur.cpp @@ -649,19 +649,6 @@ void BlurEffect::drawWindow(EffectWindow *w, int mask, const QRegion ®ion, Wi effects->drawWindow(w, mask, region, data); } -void BlurEffect::paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) -{ - const QRect screen = effects->virtualScreenGeometry(); - bool valid = m_renderTargetsValid && m_shader && m_shader->isValid(); - - QRegion shape = frame->geometry().adjusted(-borderSize, -borderSize, borderSize, borderSize) & screen; - - if (valid && !shape.isEmpty() && region.intersects(shape.boundingRect()) && frame->style() != EffectFrameNone) { - doBlur(shape, screen, opacity * frameOpacity, frame->screenProjectionMatrix(), false, frame->geometry()); - } - effects->paintEffectFrame(frame, region, opacity, frameOpacity); -} - void BlurEffect::generateNoiseTexture() { if (m_noiseStrength == 0) { diff --git a/src/effects/blur/blur.h b/src/effects/blur/blur.h index 84f99aadcb..7cdcf9cae3 100644 --- a/src/effects/blur/blur.h +++ b/src/effects/blur/blur.h @@ -43,7 +43,6 @@ public: void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime) override; void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) override; void drawWindow(EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; - void paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) override; bool provides(Feature feature) override; bool isActive() const override; diff --git a/src/effects/invert/invert.cpp b/src/effects/invert/invert.cpp index ef2049d664..56b6efb5f0 100644 --- a/src/effects/invert/invert.cpp +++ b/src/effects/invert/invert.cpp @@ -102,17 +102,6 @@ void InvertEffect::drawWindow(EffectWindow *w, int mask, const QRegion ®ion, } } -void InvertEffect::paintEffectFrame(KWin::EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) -{ - if (m_valid && m_allWindows) { - frame->setShader(m_shader); - ShaderBinder binder(m_shader); - effects->paintEffectFrame(frame, region, opacity, frameOpacity); - } else { - effects->paintEffectFrame(frame, region, opacity, frameOpacity); - } -} - void InvertEffect::slotWindowClosed(EffectWindow *w) { m_windows.removeOne(w); diff --git a/src/effects/invert/invert.h b/src/effects/invert/invert.h index bb5d5b19b5..f6ac8595dc 100644 --- a/src/effects/invert/invert.h +++ b/src/effects/invert/invert.h @@ -30,7 +30,6 @@ public: ~InvertEffect() override; void drawWindow(EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) override; - void paintEffectFrame(KWin::EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) override; bool isActive() const override; bool provides(Feature) override; diff --git a/src/libkwineffects/kwineffects.cpp b/src/libkwineffects/kwineffects.cpp index 2681caf2fe..c415c2039e 100644 --- a/src/libkwineffects/kwineffects.cpp +++ b/src/libkwineffects/kwineffects.cpp @@ -584,11 +584,6 @@ void Effect::postPaintWindow(EffectWindow *w) effects->postPaintWindow(w); } -void Effect::paintEffectFrame(KWin::EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) -{ - effects->paintEffectFrame(frame, region, opacity, frameOpacity); -} - bool Effect::provides(Feature) { return false; @@ -1585,16 +1580,6 @@ void EffectFrame::enableCrossFade(bool enable) d->crossFading = enable; } -QMatrix4x4 EffectFrame::screenProjectionMatrix() const -{ - return d->screenProjectionMatrix; -} - -void EffectFrame::setScreenProjectionMatrix(const QMatrix4x4 &spm) -{ - d->screenProjectionMatrix = spm; -} - /*************************************************************** TimeLine ***************************************************************/ diff --git a/src/libkwineffects/kwineffects.h b/src/libkwineffects/kwineffects.h index 3109b07283..5fc14db81a 100644 --- a/src/libkwineffects/kwineffects.h +++ b/src/libkwineffects/kwineffects.h @@ -449,21 +449,6 @@ public: */ virtual void postPaintWindow(EffectWindow *w); - /** - * This method is called directly before painting an @ref EffectFrame. - * You can implement this method if you need to bind a shader or perform - * other operations before the frame is rendered. - * @param frame The EffectFrame which will be rendered - * @param region Region to restrict painting to - * @param opacity Opacity of text/icon - * @param frameOpacity Opacity of background - * @since 4.6 - * - * In OpenGL based compositing, the frameworks ensures that the context is current - * when this method is invoked. - */ - virtual void paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity); - /** * Called on Transparent resizes. * return true if your effect substitutes questioned feature @@ -877,7 +862,6 @@ public: virtual void prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime) = 0; virtual void paintWindow(EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) = 0; virtual void postPaintWindow(EffectWindow *w) = 0; - virtual void paintEffectFrame(EffectFrame *frame, const QRegion ®ion, double opacity, double frameOpacity) = 0; virtual void drawWindow(EffectWindow *w, int mask, const QRegion ®ion, WindowPaintData &data) = 0; virtual QVariant kwinOption(KWinOption kwopt) = 0; /** @@ -3736,22 +3720,6 @@ public: virtual void setIconSize(const QSize &size) = 0; virtual const QSize &iconSize() const = 0; - /** - * Sets the geometry of a selection. - * To remove the selection set a null rect. - * @param selection The geometry of the selection in screen coordinates. - */ - virtual void setSelection(const QRect &selection) = 0; - - /** - * @param shader The GLShader for rendering. - */ - virtual void setShader(GLShader *shader) = 0; - /** - * @returns The GLShader used for rendering or null if none. - */ - virtual GLShader *shader() const = 0; - /** * @returns The style of this EffectFrame. */ @@ -3766,13 +3734,13 @@ public: * @see setCrossFadeProgress * @since 4.6 */ - void enableCrossFade(bool enable); + virtual void enableCrossFade(bool enable) = 0; /** * @returns @c true if cross fading is enabled, @c false otherwise * @see enableCrossFade * @since 4.6 */ - bool isCrossFade() const; + virtual bool isCrossFade() const = 0; /** * Sets the current progress for cross fading the last used icon/text * with current icon/text to @p progress. @@ -3785,7 +3753,7 @@ public: * @see crossFadeProgress * @since 4.6 */ - void setCrossFadeProgress(qreal progress); + virtual void setCrossFadeProgress(qreal progress) = 0; /** * @returns The current progress for cross fading * @see setCrossFadeProgress @@ -3793,23 +3761,7 @@ public: * @see isCrossFade * @since 4.6 */ - qreal crossFadeProgress() const; - - /** - * Returns The projection matrix as used by the current screen painting pass - * including screen transformations. - * - * This matrix is only valid during a rendering pass started by render. - * - * @since 5.6 - * @see render - * @see EffectsHandler::paintEffectFrame - * @see Effect::paintEffectFrame - */ - QMatrix4x4 screenProjectionMatrix() const; - -protected: - void setScreenProjectionMatrix(const QMatrix4x4 &projection); + virtual qreal crossFadeProgress() const = 0; private: EffectFramePrivate *const d; diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt index 6b8edd828b..3b9e8ff0f6 100644 --- a/src/qml/CMakeLists.txt +++ b/src/qml/CMakeLists.txt @@ -1,3 +1,3 @@ install(DIRECTORY outline/plasma DESTINATION ${KDE_INSTALL_DATADIR}/${KWIN_NAME}/outline) install(DIRECTORY onscreennotification/plasma DESTINATION ${KDE_INSTALL_DATADIR}/${KWIN_NAME}/onscreennotification) - +install(DIRECTORY frames/plasma DESTINATION ${KDE_INSTALL_DATADIR}/${KWIN_NAME}/frames) diff --git a/src/qml/frames/plasma/frame_none.qml b/src/qml/frames/plasma/frame_none.qml new file mode 100644 index 0000000000..88194a6117 --- /dev/null +++ b/src/qml/frames/plasma/frame_none.qml @@ -0,0 +1,39 @@ +/* + SPDX-FileCopyrightText: 2022 MBition GmbH + SPDX-FileContributor: Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 as QQC2 + +import org.kde.kirigami 2.12 as Kirigami + +ColumnLayout { + id: root + + property QtObject effectFrame: null + + spacing: 5 + + Kirigami.Icon { + id: icon + Layout.preferredWidth: root.effectFrame.iconSize.width + Layout.preferredHeight: root.effectFrame.iconSize.height + Layout.alignment: Qt.AlignHCenter + visible: valid + source: root.effectFrame.icon + } + + QQC2.Label { + id: label + Layout.fillWidth: true + textFormat: Text.PlainText + elide: Text.ElideRight + font: root.effectFrame.font + visible: text !== "" + text: root.effectFrame.text + } +} diff --git a/src/qml/frames/plasma/frame_styled.qml b/src/qml/frames/plasma/frame_styled.qml new file mode 100644 index 0000000000..8cb1e930f2 --- /dev/null +++ b/src/qml/frames/plasma/frame_styled.qml @@ -0,0 +1,60 @@ +/* + SPDX-FileCopyrightText: 2022 MBition GmbH + SPDX-FileContributor: Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 3.0 as PlasmaComponents + +Item { + id: root + + property QtObject effectFrame: null + + implicitWidth: layout.implicitWidth + layout.anchors.leftMargin + layout.anchors.rightMargin + implicitHeight: layout.implicitHeight + layout.anchors.topMargin + layout.anchors.bottomMargin + + PlasmaCore.FrameSvgItem { + id: frameSvg + imagePath: "widgets/background" + opacity: root.effectFrame.frameOpacity + anchors.fill: parent + } + + RowLayout { + id: layout + anchors { + fill: parent + leftMargin: frameSvg.fixedMargins.left + rightMargin: frameSvg.fixedMargins.top + topMargin: frameSvg.fixedMargins.top + bottomMargin: frameSvg.fixedMargins.bottom + } + spacing: PlasmaCore.Units.smallSpacing + + PlasmaCore.IconItem { + id: icon + Layout.preferredWidth: root.effectFrame.iconSize.width + Layout.preferredHeight: root.effectFrame.iconSize.height + Layout.alignment: Qt.AlignHCenter + animated: root.effectFrame.crossFadeEnabled + visible: valid + source: root.effectFrame.icon + } + + PlasmaComponents.Label { + id: label + Layout.fillWidth: true + textFormat: Text.PlainText + elide: Text.ElideRight + font: root.effectFrame.font + visible: text !== "" + text: root.effectFrame.text + } + } +} diff --git a/src/qml/frames/plasma/frame_unstyled.qml b/src/qml/frames/plasma/frame_unstyled.qml new file mode 100644 index 0000000000..87ba237b29 --- /dev/null +++ b/src/qml/frames/plasma/frame_unstyled.qml @@ -0,0 +1,53 @@ +/* + SPDX-FileCopyrightText: 2022 MBition GmbH + SPDX-FileContributor: Kai Uwe Broulik + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 as QQC2 + +import org.kde.kirigami 2.12 as Kirigami + +Rectangle { + id: root + + property QtObject effectFrame: null + + implicitWidth: layout.implicitWidth + 2 * layout.anchors.margins + implicitHeight: layout.implicitHeight + 2 * layout.anchors.margins + + color: Qt.rgba(0, 0, 0, effectFrame.frameOpacity) + radius: layout.anchors.margins + + RowLayout { + id: layout + anchors { + fill: parent + margins: layout.spacing + } + spacing: 5 + + Kirigami.Icon { + id: icon + Layout.preferredWidth: root.effectFrame.iconSize.width + Layout.preferredHeight: root.effectFrame.iconSize.height + Layout.alignment: Qt.AlignHCenter + visible: valid + source: root.effectFrame.icon + } + + QQC2.Label { + id: label + Layout.fillWidth: true + color: "white" + textFormat: Text.PlainText + elide: Text.ElideRight + font: root.effectFrame.font + visible: text !== "" + text: root.effectFrame.text + } + } +} diff --git a/src/scene.cpp b/src/scene.cpp index 4bbfcbfdb2..a1c6011b16 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -737,16 +737,4 @@ void SceneWindow::updateWindowPosition() m_windowItem->setPosition(pos()); } -//**************************************** -// Scene::EffectFrame -//**************************************** -Scene::EffectFrame::EffectFrame(EffectFrameImpl *frame) - : m_effectFrame(frame) -{ -} - -Scene::EffectFrame::~EffectFrame() -{ -} - } // namespace diff --git a/src/scene.h b/src/scene.h index c713eabd6c..df21b99d31 100644 --- a/src/scene.h +++ b/src/scene.h @@ -103,12 +103,6 @@ public: void postPaint(); virtual void paint(RenderTarget *renderTarget, const QRegion ®ion) = 0; - /** - * @brief Creates the Scene backend of an EffectFrame. - * - * @param frame The EffectFrame this Scene::EffectFrame belongs to. - */ - virtual Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) = 0; /** * @brief Creates the Scene specific Shadow subclass. * @@ -290,23 +284,6 @@ private: Q_DISABLE_COPY(SceneWindow) }; -class Scene::EffectFrame -{ -public: - EffectFrame(EffectFrameImpl *frame); - virtual ~EffectFrame(); - virtual void render(const QRegion ®ion, double opacity, double frameOpacity) = 0; - virtual void free() = 0; - virtual void freeIconFrame() = 0; - virtual void freeTextFrame() = 0; - virtual void freeSelection() = 0; - virtual void crossFadeIcon() = 0; - virtual void crossFadeText() = 0; - -protected: - EffectFrameImpl *m_effectFrame; -}; - inline int SceneWindow::x() const { return m_window->x(); diff --git a/src/scenes/opengl/scene_opengl.cpp b/src/scenes/opengl/scene_opengl.cpp index 9d24d43f9c..b3cf5865d4 100644 --- a/src/scenes/opengl/scene_opengl.cpp +++ b/src/scenes/opengl/scene_opengl.cpp @@ -75,7 +75,6 @@ SceneOpenGL::~SceneOpenGL() if (init_ok) { makeOpenGLContextCurrent(); } - SceneOpenGL::EffectFrame::cleanup(); } SceneOpenGL *SceneOpenGL::createScene(OpenGLBackend *backend, QObject *parent) @@ -196,11 +195,6 @@ bool SceneOpenGL::supportsNativeFence() const return m_backend->supportsNativeFence(); } -Scene::EffectFrame *SceneOpenGL::createEffectFrame(EffectFrameImpl *frame) -{ - return new SceneOpenGL::EffectFrame(frame, this); -} - Shadow *SceneOpenGL::createShadow(Window *window) { return new SceneOpenGLShadow(window); @@ -627,441 +621,6 @@ void SceneOpenGL::render(Item *item, int mask, const QRegion ®ion, const Wind } } -//**************************************** -// SceneOpenGL::EffectFrame -//**************************************** - -GLTexture *SceneOpenGL::EffectFrame::m_unstyledTexture = nullptr; -QPixmap *SceneOpenGL::EffectFrame::m_unstyledPixmap = nullptr; - -SceneOpenGL::EffectFrame::EffectFrame(EffectFrameImpl *frame, SceneOpenGL *scene) - : Scene::EffectFrame(frame) - , m_texture(nullptr) - , m_textTexture(nullptr) - , m_oldTextTexture(nullptr) - , m_textPixmap(nullptr) - , m_iconTexture(nullptr) - , m_oldIconTexture(nullptr) - , m_selectionTexture(nullptr) - , m_unstyledVBO(nullptr) - , m_scene(scene) -{ -} - -SceneOpenGL::EffectFrame::~EffectFrame() -{ - delete m_texture; - delete m_textTexture; - delete m_textPixmap; - delete m_oldTextTexture; - delete m_iconTexture; - delete m_oldIconTexture; - delete m_selectionTexture; - delete m_unstyledVBO; -} - -void SceneOpenGL::EffectFrame::free() -{ - glFlush(); - delete m_texture; - m_texture = nullptr; - delete m_textTexture; - m_textTexture = nullptr; - delete m_textPixmap; - m_textPixmap = nullptr; - delete m_iconTexture; - m_iconTexture = nullptr; - delete m_selectionTexture; - m_selectionTexture = nullptr; - delete m_unstyledVBO; - m_unstyledVBO = nullptr; - delete m_oldIconTexture; - m_oldIconTexture = nullptr; - delete m_oldTextTexture; - m_oldTextTexture = nullptr; -} - -void SceneOpenGL::EffectFrame::freeIconFrame() -{ - delete m_iconTexture; - m_iconTexture = nullptr; -} - -void SceneOpenGL::EffectFrame::freeTextFrame() -{ - delete m_textTexture; - m_textTexture = nullptr; - delete m_textPixmap; - m_textPixmap = nullptr; -} - -void SceneOpenGL::EffectFrame::freeSelection() -{ - delete m_selectionTexture; - m_selectionTexture = nullptr; -} - -void SceneOpenGL::EffectFrame::crossFadeIcon() -{ - delete m_oldIconTexture; - m_oldIconTexture = m_iconTexture; - m_iconTexture = nullptr; -} - -void SceneOpenGL::EffectFrame::crossFadeText() -{ - delete m_oldTextTexture; - m_oldTextTexture = m_textTexture; - m_textTexture = nullptr; -} - -void SceneOpenGL::EffectFrame::render(const QRegion &_region, double opacity, double frameOpacity) -{ - if (m_effectFrame->geometry().isEmpty()) { - return; // Nothing to display - } - - Q_UNUSED(_region); // TODO: Old region doesn't seem to work with OpenGL - - GLShader *shader = m_effectFrame->shader(); - if (!shader) { - shader = ShaderManager::instance()->pushShader(ShaderTrait::MapTexture | ShaderTrait::Modulate); - } else if (shader) { - ShaderManager::instance()->pushShader(shader); - } - - if (shader) { - shader->setUniform(GLShader::ModulationConstant, QVector4D(1.0, 1.0, 1.0, 1.0)); - shader->setUniform(GLShader::Saturation, 1.0f); - } - const QMatrix4x4 projection = m_scene->renderTargetProjectionMatrix(); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // Render the actual frame - if (m_effectFrame->style() == EffectFrameUnstyled) { - if (!m_unstyledTexture) { - updateUnstyledTexture(); - } - - if (!m_unstyledVBO) { - m_unstyledVBO = new GLVertexBuffer(GLVertexBuffer::Static); - QRect area = m_effectFrame->geometry(); - area.moveTo(0, 0); - area.adjust(-5, -5, 5, 5); - - const int roundness = 5; - QVector verts, texCoords; - verts.reserve(84); - texCoords.reserve(84); - - // top left - verts << area.left() << area.top(); - texCoords << 0.0f << 0.0f; - verts << area.left() << area.top() + roundness; - texCoords << 0.0f << 0.5f; - verts << area.left() + roundness << area.top(); - texCoords << 0.5f << 0.0f; - verts << area.left() + roundness << area.top() + roundness; - texCoords << 0.5f << 0.5f; - verts << area.left() << area.top() + roundness; - texCoords << 0.0f << 0.5f; - verts << area.left() + roundness << area.top(); - texCoords << 0.5f << 0.0f; - // top - verts << area.left() + roundness << area.top(); - texCoords << 0.5f << 0.0f; - verts << area.left() + roundness << area.top() + roundness; - texCoords << 0.5f << 0.5f; - verts << area.right() - roundness << area.top(); - texCoords << 0.5f << 0.0f; - verts << area.left() + roundness << area.top() + roundness; - texCoords << 0.5f << 0.5f; - verts << area.right() - roundness << area.top() + roundness; - texCoords << 0.5f << 0.5f; - verts << area.right() - roundness << area.top(); - texCoords << 0.5f << 0.0f; - // top right - verts << area.right() - roundness << area.top(); - texCoords << 0.5f << 0.0f; - verts << area.right() - roundness << area.top() + roundness; - texCoords << 0.5f << 0.5f; - verts << area.right() << area.top(); - texCoords << 1.0f << 0.0f; - verts << area.right() - roundness << area.top() + roundness; - texCoords << 0.5f << 0.5f; - verts << area.right() << area.top() + roundness; - texCoords << 1.0f << 0.5f; - verts << area.right() << area.top(); - texCoords << 1.0f << 0.0f; - // bottom left - verts << area.left() << area.bottom() - roundness; - texCoords << 0.0f << 0.5f; - verts << area.left() << area.bottom(); - texCoords << 0.0f << 1.0f; - verts << area.left() + roundness << area.bottom() - roundness; - texCoords << 0.5f << 0.5f; - verts << area.left() + roundness << area.bottom(); - texCoords << 0.5f << 1.0f; - verts << area.left() << area.bottom(); - texCoords << 0.0f << 1.0f; - verts << area.left() + roundness << area.bottom() - roundness; - texCoords << 0.5f << 0.5f; - // bottom - verts << area.left() + roundness << area.bottom() - roundness; - texCoords << 0.5f << 0.5f; - verts << area.left() + roundness << area.bottom(); - texCoords << 0.5f << 1.0f; - verts << area.right() - roundness << area.bottom() - roundness; - texCoords << 0.5f << 0.5f; - verts << area.left() + roundness << area.bottom(); - texCoords << 0.5f << 1.0f; - verts << area.right() - roundness << area.bottom(); - texCoords << 0.5f << 1.0f; - verts << area.right() - roundness << area.bottom() - roundness; - texCoords << 0.5f << 0.5f; - // bottom right - verts << area.right() - roundness << area.bottom() - roundness; - texCoords << 0.5f << 0.5f; - verts << area.right() - roundness << area.bottom(); - texCoords << 0.5f << 1.0f; - verts << area.right() << area.bottom() - roundness; - texCoords << 1.0f << 0.5f; - verts << area.right() - roundness << area.bottom(); - texCoords << 0.5f << 1.0f; - verts << area.right() << area.bottom(); - texCoords << 1.0f << 1.0f; - verts << area.right() << area.bottom() - roundness; - texCoords << 1.0f << 0.5f; - // center - verts << area.left() << area.top() + roundness; - texCoords << 0.0f << 0.5f; - verts << area.left() << area.bottom() - roundness; - texCoords << 0.0f << 0.5f; - verts << area.right() << area.top() + roundness; - texCoords << 1.0f << 0.5f; - verts << area.left() << area.bottom() - roundness; - texCoords << 0.0f << 0.5f; - verts << area.right() << area.bottom() - roundness; - texCoords << 1.0f << 0.5f; - verts << area.right() << area.top() + roundness; - texCoords << 1.0f << 0.5f; - - m_unstyledVBO->setData(verts.count() / 2, 2, verts.data(), texCoords.data()); - } - - if (shader) { - const float a = opacity * frameOpacity; - shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); - } - - m_unstyledTexture->bind(); - const QPoint pt = m_effectFrame->geometry().topLeft(); - - QMatrix4x4 mvp(projection); - mvp.translate(pt.x(), pt.y()); - shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); - - m_unstyledVBO->render(GL_TRIANGLES); - m_unstyledTexture->unbind(); - } else if (m_effectFrame->style() == EffectFrameStyled) { - if (!m_texture) { // Lazy creation - updateTexture(); - } - - if (shader) { - const float a = opacity * frameOpacity; - shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); - } - m_texture->bind(); - qreal left, top, right, bottom; - m_effectFrame->frame().getMargins(left, top, right, bottom); // m_geometry is the inner geometry - const QRect rect = m_effectFrame->geometry().adjusted(-left, -top, right, bottom); - - QMatrix4x4 mvp(projection); - mvp.translate(rect.x(), rect.y()); - shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); - - m_texture->render(rect); - m_texture->unbind(); - } - if (!m_effectFrame->selection().isNull()) { - if (!m_selectionTexture) { // Lazy creation - QPixmap pixmap = m_effectFrame->selectionFrame().framePixmap(); - if (!pixmap.isNull()) { - m_selectionTexture = new GLTexture(pixmap); - } - } - if (m_selectionTexture) { - if (shader) { - const float a = opacity * frameOpacity; - shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); - } - QMatrix4x4 mvp(projection); - mvp.translate(m_effectFrame->selection().x(), m_effectFrame->selection().y()); - shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - m_selectionTexture->bind(); - m_selectionTexture->render(m_effectFrame->selection()); - m_selectionTexture->unbind(); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - } - - // Render icon - if (!m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty()) { - QPoint topLeft(m_effectFrame->geometry().x(), - m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2); - - QMatrix4x4 mvp(projection); - mvp.translate(topLeft.x(), topLeft.y()); - shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); - - if (m_effectFrame->isCrossFade() && m_oldIconTexture) { - if (shader) { - const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress()); - shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); - } - - m_oldIconTexture->bind(); - m_oldIconTexture->render(QRect(topLeft, m_effectFrame->iconSize())); - m_oldIconTexture->unbind(); - if (shader) { - const float a = opacity * m_effectFrame->crossFadeProgress(); - shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); - } - } else { - if (shader) { - const QVector4D constant(opacity, opacity, opacity, opacity); - shader->setUniform(GLShader::ModulationConstant, constant); - } - } - - if (!m_iconTexture) { // lazy creation - m_iconTexture = new GLTexture(m_effectFrame->icon().pixmap(m_effectFrame->iconSize())); - } - m_iconTexture->bind(); - m_iconTexture->render(QRect(topLeft, m_effectFrame->iconSize())); - m_iconTexture->unbind(); - } - - // Render text - if (!m_effectFrame->text().isEmpty()) { - QMatrix4x4 mvp(projection); - mvp.translate(m_effectFrame->geometry().x(), m_effectFrame->geometry().y()); - shader->setUniform(GLShader::ModelViewProjectionMatrix, mvp); - if (m_effectFrame->isCrossFade() && m_oldTextTexture) { - if (shader) { - const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress()); - shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); - } - - m_oldTextTexture->bind(); - m_oldTextTexture->render(m_effectFrame->geometry()); - m_oldTextTexture->unbind(); - if (shader) { - const float a = opacity * m_effectFrame->crossFadeProgress(); - shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); - } - } else { - if (shader) { - const QVector4D constant(opacity, opacity, opacity, opacity); - shader->setUniform(GLShader::ModulationConstant, constant); - } - } - if (!m_textTexture) { // Lazy creation - updateTextTexture(); - } - - if (m_textTexture) { - m_textTexture->bind(); - m_textTexture->render(m_effectFrame->geometry()); - m_textTexture->unbind(); - } - } - - if (shader) { - ShaderManager::instance()->popShader(); - } - glDisable(GL_BLEND); -} - -void SceneOpenGL::EffectFrame::updateTexture() -{ - delete m_texture; - m_texture = nullptr; - if (m_effectFrame->style() == EffectFrameStyled) { - QPixmap pixmap = m_effectFrame->frame().framePixmap(); - m_texture = new GLTexture(pixmap); - } -} - -void SceneOpenGL::EffectFrame::updateTextTexture() -{ - delete m_textTexture; - m_textTexture = nullptr; - delete m_textPixmap; - m_textPixmap = nullptr; - - if (m_effectFrame->text().isEmpty()) { - return; - } - - // Determine position on texture to paint text - QRect rect(QPoint(0, 0), m_effectFrame->geometry().size()); - if (!m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty()) { - rect.setLeft(m_effectFrame->iconSize().width()); - } - - // If static size elide text as required - QString text = m_effectFrame->text(); - if (m_effectFrame->isStatic()) { - QFontMetrics metrics(m_effectFrame->font()); - text = metrics.elidedText(text, Qt::ElideRight, rect.width()); - } - - m_textPixmap = new QPixmap(m_effectFrame->geometry().size()); - m_textPixmap->fill(Qt::transparent); - QPainter p(m_textPixmap); - p.setFont(m_effectFrame->font()); - if (m_effectFrame->style() == EffectFrameStyled) { - p.setPen(m_effectFrame->styledTextColor()); - } else { // TODO: What about no frame? Custom color setting required - p.setPen(Qt::white); - } - p.drawText(rect, m_effectFrame->alignment(), text); - p.end(); - m_textTexture = new GLTexture(*m_textPixmap); -} - -void SceneOpenGL::EffectFrame::updateUnstyledTexture() -{ - delete m_unstyledTexture; - m_unstyledTexture = nullptr; - delete m_unstyledPixmap; - m_unstyledPixmap = nullptr; - // Based off circle() from kwinxrenderutils.cpp - const int CS = 8; - m_unstyledPixmap = new QPixmap(2 * CS, 2 * CS); - m_unstyledPixmap->fill(Qt::transparent); - QPainter p(m_unstyledPixmap); - p.setRenderHint(QPainter::Antialiasing); - p.setPen(Qt::NoPen); - p.setBrush(Qt::black); - p.drawEllipse(m_unstyledPixmap->rect()); - p.end(); - m_unstyledTexture = new GLTexture(*m_unstyledPixmap); -} - -void SceneOpenGL::EffectFrame::cleanup() -{ - delete m_unstyledTexture; - m_unstyledTexture = nullptr; - delete m_unstyledPixmap; - m_unstyledPixmap = nullptr; -} - //**************************************** // SceneOpenGL::Shadow //**************************************** diff --git a/src/scenes/opengl/scene_opengl.h b/src/scenes/opengl/scene_opengl.h index 32772f0718..5a3e380fbf 100644 --- a/src/scenes/opengl/scene_opengl.h +++ b/src/scenes/opengl/scene_opengl.h @@ -54,7 +54,6 @@ public: ~SceneOpenGL() override; bool initFailed() const override; void paint(RenderTarget *renderTarget, const QRegion ®ion) override; - Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override; Shadow *createShadow(Window *window) override; bool makeOpenGLContextCurrent() override; void doneOpenGLContextCurrent() override; @@ -104,44 +103,6 @@ private: bool m_blendingEnabled = false; }; -class SceneOpenGL::EffectFrame - : public Scene::EffectFrame -{ -public: - EffectFrame(EffectFrameImpl *frame, SceneOpenGL *scene); - ~EffectFrame() override; - - void free() override; - void freeIconFrame() override; - void freeTextFrame() override; - void freeSelection() override; - - void render(const QRegion ®ion, double opacity, double frameOpacity) override; - - void crossFadeIcon() override; - void crossFadeText() override; - - static void cleanup(); - -private: - void updateTexture(); - void updateTextTexture(); - - GLTexture *m_texture; - GLTexture *m_textTexture; - GLTexture *m_oldTextTexture; - QPixmap *m_textPixmap; // need to keep the pixmap around to workaround some driver problems - GLTexture *m_iconTexture; - GLTexture *m_oldIconTexture; - GLTexture *m_selectionTexture; - GLVertexBuffer *m_unstyledVBO; - SceneOpenGL *m_scene; - - static GLTexture *m_unstyledTexture; - static QPixmap *m_unstyledPixmap; // need to keep the pixmap around to workaround some driver problems - static void updateUnstyledTexture(); // Update OpenGL unstyled frame texture -}; - /** * @short OpenGL implementation of Shadow. * diff --git a/src/scenes/qpainter/scene_qpainter.cpp b/src/scenes/qpainter/scene_qpainter.cpp index 0bf5346549..64e32868f7 100644 --- a/src/scenes/qpainter/scene_qpainter.cpp +++ b/src/scenes/qpainter/scene_qpainter.cpp @@ -98,11 +98,6 @@ void SceneQPainter::paintOffscreenQuickView(OffscreenQuickView *w) painter->restore(); } -Scene::EffectFrame *SceneQPainter::createEffectFrame(EffectFrameImpl *frame) -{ - return new QPainterEffectFrame(frame, this); -} - Shadow *SceneQPainter::createShadow(Window *window) { return new SceneQPainterShadow(window); @@ -249,83 +244,6 @@ SurfaceTexture *SceneQPainter::createSurfaceTextureWayland(SurfacePixmapWayland return m_backend->createSurfaceTextureWayland(pixmap); } -QPainterEffectFrame::QPainterEffectFrame(EffectFrameImpl *frame, SceneQPainter *scene) - : Scene::EffectFrame(frame) - , m_scene(scene) -{ -} - -QPainterEffectFrame::~QPainterEffectFrame() -{ -} - -void QPainterEffectFrame::render(const QRegion ®ion, double opacity, double frameOpacity) -{ - Q_UNUSED(region) - Q_UNUSED(opacity) - // TODO: adjust opacity - if (m_effectFrame->geometry().isEmpty()) { - return; // Nothing to display - } - QPainter *painter = m_scene->scenePainter(); - - // Render the actual frame - if (m_effectFrame->style() == EffectFrameUnstyled) { - painter->save(); - painter->setPen(Qt::NoPen); - QColor color(Qt::black); - color.setAlphaF(frameOpacity); - painter->setBrush(color); - painter->setRenderHint(QPainter::Antialiasing); - painter->drawRoundedRect(m_effectFrame->geometry().adjusted(-5, -5, 5, 5), 5.0, 5.0); - painter->restore(); - } else if (m_effectFrame->style() == EffectFrameStyled) { - qreal left, top, right, bottom; - m_effectFrame->frame().getMargins(left, top, right, bottom); // m_geometry is the inner geometry - QRect geom = m_effectFrame->geometry().adjusted(-left, -top, right, bottom); - painter->drawPixmap(geom, m_effectFrame->frame().framePixmap()); - } - if (!m_effectFrame->selection().isNull()) { - painter->drawPixmap(m_effectFrame->selection(), m_effectFrame->selectionFrame().framePixmap()); - } - - // Render icon - if (!m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty()) { - const QPoint topLeft(m_effectFrame->geometry().x(), - m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2); - - const QRect geom = QRect(topLeft, m_effectFrame->iconSize()); - painter->drawPixmap(geom, m_effectFrame->icon().pixmap(m_effectFrame->iconSize())); - } - - // Render text - if (!m_effectFrame->text().isEmpty()) { - // Determine position on texture to paint text - QRect rect(QPoint(0, 0), m_effectFrame->geometry().size()); - if (!m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty()) { - rect.setLeft(m_effectFrame->iconSize().width()); - } - - // If static size elide text as required - QString text = m_effectFrame->text(); - if (m_effectFrame->isStatic()) { - QFontMetrics metrics(m_effectFrame->text()); - text = metrics.elidedText(text, Qt::ElideRight, rect.width()); - } - - painter->save(); - painter->setFont(m_effectFrame->font()); - if (m_effectFrame->style() == EffectFrameStyled) { - painter->setPen(m_effectFrame->styledTextColor()); - } else { - // TODO: What about no frame? Custom color setting required - painter->setPen(Qt::white); - } - painter->drawText(rect.translated(m_effectFrame->geometry().topLeft()), m_effectFrame->alignment(), text); - painter->restore(); - } -} - //**************************************** // QPainterShadow //**************************************** diff --git a/src/scenes/qpainter/scene_qpainter.h b/src/scenes/qpainter/scene_qpainter.h index ed2ca9f2a2..1f0754708f 100644 --- a/src/scenes/qpainter/scene_qpainter.h +++ b/src/scenes/qpainter/scene_qpainter.h @@ -27,7 +27,6 @@ public: void paint(RenderTarget *renderTarget, const QRegion ®ion) override; void paintGenericScreen(int mask, const ScreenPaintData &data) override; bool initFailed() const override; - EffectFrame *createEffectFrame(EffectFrameImpl *frame) override; Shadow *createShadow(Window *window) override; DecorationRenderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override; SurfaceTexture *createSurfaceTextureInternal(SurfacePixmapInternal *pixmap) override; @@ -63,35 +62,6 @@ private: QScopedPointer m_painter; }; -class QPainterEffectFrame : public Scene::EffectFrame -{ -public: - QPainterEffectFrame(EffectFrameImpl *frame, SceneQPainter *scene); - ~QPainterEffectFrame() override; - void crossFadeIcon() override - { - } - void crossFadeText() override - { - } - void free() override - { - } - void freeIconFrame() override - { - } - void freeTextFrame() override - { - } - void freeSelection() override - { - } - void render(const QRegion ®ion, double opacity, double frameOpacity) override; - -private: - SceneQPainter *m_scene; -}; - class SceneQPainterShadow : public Shadow { public: