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: