diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -561,6 +561,8 @@ shortcutdialog.ui ) +qt5_add_resources(kwin_KDEINIT_SRCS qml/frame/frames.qrc) + ########### target link libraries ############### set(kwin_OWN_LIBS diff --git a/effects.h b/effects.h --- a/effects.h +++ b/effects.h @@ -193,8 +193,6 @@ bool decorationSupportsBlurBehind() const override; - EffectFrame* effectFrame(EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment) const override; - QVariant kwinOption(KWinOption kwopt) override; bool isScreenLocked() const override; @@ -536,89 +534,6 @@ Group* group; }; -class KWIN_EXPORT EffectFrameImpl - : public QObject, public EffectFrame -{ - Q_OBJECT -public: - explicit EffectFrameImpl(EffectFrameStyle style, bool staticSize = true, QPoint position = QPoint(-1, -1), - Qt::Alignment alignment = Qt::AlignCenter); - ~EffectFrameImpl() override; - - void free() override; - void render(const QRegion ®ion = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0) override; - Qt::Alignment alignment() const override; - void setAlignment(Qt::Alignment alignment) override; - const QFont& font() const override; - void setFont(const QFont& font) override; - const QRect& geometry() const override; - void setGeometry(const QRect& geometry, bool force = false) override; - const QIcon& icon() const override; - void setIcon(const QIcon& icon) override; - const QSize& iconSize() const override; - void setIconSize(const QSize& size) override; - 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(); - -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; - 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/effects.cpp b/effects.cpp --- a/effects.cpp +++ b/effects.cpp @@ -457,8 +457,7 @@ (*m_currentPaintEffectFrameIterator++)->paintEffectFrame(frame, region, opacity, frameOpacity); --m_currentPaintEffectFrameIterator; } else { - const EffectFrameImpl* frameImpl = static_cast(frame); - frameImpl->finalRender(region, opacity, frameOpacity); + frame->render(region, opacity, frameOpacity); } } @@ -1546,12 +1545,6 @@ return nullptr; } -EffectFrame* EffectsHandlerImpl::effectFrame(EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment) const -{ - return new EffectFrameImpl(style, staticSize, position, alignment); -} - - QVariant EffectsHandlerImpl::kwinOption(KWinOption kwopt) { switch (kwopt) { @@ -2170,243 +2163,4 @@ return ret; } -//**************************************** -// EffectFrameImpl -//**************************************** - -EffectFrameImpl::EffectFrameImpl(EffectFrameStyle style, bool staticSize, QPoint position, Qt::Alignment alignment) - : QObject(nullptr) - , EffectFrame() - , 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, SIGNAL(themeChanged()), this, SLOT(plasmaThemeChanged())); - } - 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); -} - -EffectFrameImpl::~EffectFrameImpl() -{ - delete m_sceneFrame; -} - -const QFont& EffectFrameImpl::font() const -{ - return m_font; -} - -void EffectFrameImpl::setFont(const QFont& font) -{ - if (m_font == font) { - return; - } - m_font = font; - QRect oldGeom = m_geometry; - if (!m_text.isEmpty()) { - autoResize(); - } - if (oldGeom == m_geometry) { - // Wasn't updated in autoResize() - m_sceneFrame->freeTextFrame(); - } -} - -void EffectFrameImpl::free() -{ - m_sceneFrame->free(); -} - -const QRect& EffectFrameImpl::geometry() const -{ - 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(); -} - -const QIcon& EffectFrameImpl::icon() const -{ - return m_icon; -} - -void EffectFrameImpl::setIcon(const QIcon& icon) -{ - m_icon = icon; - if (isCrossFade()) { - m_sceneFrame->crossFadeIcon(); - } - if (m_iconSize.isEmpty() && !m_icon.availableSizes().isEmpty()) { // Set a size if we don't already have one - setIconSize(m_icon.availableSizes().first()); - } - m_sceneFrame->freeIconFrame(); -} - -const QSize& EffectFrameImpl::iconSize() const -{ - return m_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); -} - -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); -} - -const QString& EffectFrameImpl::text() const -{ - return m_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(); - } -} - -void EffectFrameImpl::setSelection(const QRect& selection) -{ - 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(); -} - -void EffectFrameImpl::autoResize() -{ - 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); -} - -QColor EffectFrameImpl::styledTextColor() -{ - return m_theme->color(Plasma::Theme::TextColor); -} - } // namespace diff --git a/libkwineffects/kwineffectquickview.h b/libkwineffects/kwineffectquickview.h --- a/libkwineffects/kwineffectquickview.h +++ b/libkwineffects/kwineffectquickview.h @@ -26,8 +26,6 @@ #include -#include "kwineffects.h" - #include class QKeyEvent; diff --git a/libkwineffects/kwineffectquickview.cpp b/libkwineffects/kwineffectquickview.cpp --- a/libkwineffects/kwineffectquickview.cpp +++ b/libkwineffects/kwineffectquickview.cpp @@ -137,6 +137,8 @@ connect(t, &QTimer::timeout, this, &EffectQuickView::update); connect(d->m_renderControl, &QQuickRenderControl::renderRequested, t, [t]() { t->start(); }); connect(d->m_renderControl, &QQuickRenderControl::sceneChanged, t, [t]() { t->start(); }); + + effects->makeOpenGLContextCurrent(); } EffectQuickView::~EffectQuickView() @@ -146,6 +148,7 @@ d->m_renderControl->invalidate(); d->m_glcontext->doneCurrent(); } + effects->makeOpenGLContextCurrent(); } void EffectQuickView::update() @@ -340,29 +343,29 @@ } else { m_view->releaseResources(); } + effects->makeOpenGLContextCurrent(); } EffectQuickScene::EffectQuickScene(QObject *parent) : EffectQuickView(parent) , d(new EffectQuickScene::Private) { + d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this); } EffectQuickScene::EffectQuickScene(QObject *parent, EffectQuickView::ExportMode exportMode) : EffectQuickView(parent, exportMode) , d(new EffectQuickScene::Private) { + d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this); } EffectQuickScene::~EffectQuickScene() { } void EffectQuickScene::setSource(const QUrl &source) { - if (!d->qmlObject) { - d->qmlObject = new KDeclarative::QmlObjectSharedEngine(this); - } d->qmlObject->setSource(source); QQuickItem *item = rootItem(); diff --git a/libkwineffects/kwineffects.h b/libkwineffects/kwineffects.h --- a/libkwineffects/kwineffects.h +++ b/libkwineffects/kwineffects.h @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -52,6 +53,8 @@ #include #include +#include "kwineffectquickview.h" + class KConfigGroup; class QFont; class QGraphicsScale; @@ -83,6 +86,7 @@ class EffectFrame; class EffectFramePrivate; class EffectQuickView; +class EffectQuickScene; class Effect; class WindowQuad; class GLShader; @@ -1206,8 +1210,8 @@ * EffectFrame. * @since 4.6 */ - virtual EffectFrame* effectFrame(EffectFrameStyle style, bool staticSize = true, - const QPoint& position = QPoint(-1, -1), Qt::Alignment alignment = Qt::AlignCenter) const = 0; + virtual EffectFrame *effectFrame(EffectFrameStyle style, bool staticSize = true, + const QPoint& position = QPoint(-1, -1), Qt::Alignment alignment = Qt::AlignCenter) const; /** * Allows an effect to trigger a reload of itself. @@ -3404,70 +3408,79 @@ * another that doesn't. * It is recommended to use this class whenever displaying text. */ -class KWINEFFECTS_EXPORT EffectFrame +class KWINEFFECTS_EXPORT EffectFrame: public EffectQuickScene { + Q_OBJECT + Q_PROPERTY(QString text READ text NOTIFY textChanged) + 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(bool crossFadeEnabled READ isCrossFade NOTIFY crossFadeEnabledChanged) public: - EffectFrame(); - virtual ~EffectFrame(); + EffectFrame(EffectFrameStyle style, bool staticSize = true, + const QPoint& position = QPoint(-1, -1), Qt::Alignment alignment = Qt::AlignCenter); + ~EffectFrame() override; /** - * Delete any existing textures to free up graphics memory. They will - * be automatically recreated the next time they are required. + * @deprecated + * Analogous to hide */ - virtual void free() = 0; + void free(); /** * Render the frame. */ - virtual void render(const QRegion ®ion = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0) = 0; + void render(const QRegion ®ion = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0); - virtual void setPosition(const QPoint& point) = 0; + void setPosition(const QPoint& point); /** * Set the text alignment for static frames and the position alignment * for non-static. */ - virtual void setAlignment(Qt::Alignment alignment) = 0; - virtual Qt::Alignment alignment() const = 0; - virtual void setGeometry(const QRect& geometry, bool force = false) = 0; - virtual const QRect& geometry() const = 0; + void setAlignment(Qt::Alignment alignment); + Qt::Alignment alignment() const; - virtual void setText(const QString& text) = 0; - virtual const QString& text() const = 0; - virtual void setFont(const QFont& font) = 0; - virtual const QFont& font() const = 0; + //just for compat with a pointless bool argument + void setGeometry(const QRect& geometry, bool force = false); + + void setText(const QString& text); + QString text() const; + void setFont(const QFont& font); + QFont font() const; /** * Set the icon that will appear on the left-hand size of the frame. */ - virtual void setIcon(const QIcon& icon) = 0; - virtual const QIcon& icon() const = 0; - virtual void setIconSize(const QSize& size) = 0; - virtual const QSize& iconSize() const = 0; + void setIcon(const QIcon& icon); + QIcon icon() const; + void setIconSize(const QSize& size); + QSize iconSize() const; /** * Sets the geometry of a selection. * To remove the selection set a null rect. * @param selection The geometry of the selection in screen coordinates. + * + * @deprecated */ - virtual void setSelection(const QRect& selection) = 0; + void setSelection(const QRect& selection); /** * @param shader The GLShader for rendering. */ - virtual void setShader(GLShader* shader) = 0; + void setShader(GLShader* shader); /** * @returns The GLShader used for rendering or null if none. */ - virtual GLShader* shader() const = 0; + GLShader *shader() const; /** * @returns The style of this EffectFrame. */ - virtual EffectFrameStyle style() const = 0; + virtual EffectFrameStyle style() const; /** * If @p enable is @c true cross fading between icons and text is enabled * By default disabled. Use setCrossFadeProgress to cross fade. - * Cross Fading is currently only available if OpenGL is used. * @param enable @c true enables cross fading, @c false disables it again * @see isCrossFade * @see setCrossFadeProgress @@ -3480,27 +3493,17 @@ * @since 4.6 */ bool isCrossFade() const; + /** - * Sets the current progress for cross fading the last used icon/text - * with current icon/text to @p progress. - * A value of 0.0 means completely old icon/text, a value of 1.0 means - * completely current icon/text. - * Default value is 1.0. You have to enable cross fade before using it. - * Cross Fading is currently only available if OpenGL is used. - * @see enableCrossFade - * @see isCrossFade - * @see crossFadeProgress - * @since 4.6 + * @deprecated + * This is now handled automatically */ - void setCrossFadeProgress(qreal progress); + void setCrossFadeProgress(qreal) {} /** - * @returns The current progress for cross fading - * @see setCrossFadeProgress - * @see enableCrossFade - * @see isCrossFade - * @since 4.6 + * @deprecated + * This is now handled automatically */ - qreal crossFadeProgress() const; + qreal crossFadeProgress() const {return 1;} /** * Returns The projection matrix as used by the current screen painting pass @@ -3515,11 +3518,19 @@ */ QMatrix4x4 screenProjectionMatrix() const; +Q_SIGNALS: + void textChanged(); + void fontChanged(); + void iconChanged(); + void iconSizeChanged(); + void crossFadeEnabledChanged(); + protected: void setScreenProjectionMatrix(const QMatrix4x4 &projection); private: - EffectFramePrivate* const d; + void reposition(); + QScopedPointer const d; }; /** diff --git a/libkwineffects/kwineffects.cpp b/libkwineffects/kwineffects.cpp --- a/libkwineffects/kwineffects.cpp +++ b/libkwineffects/kwineffects.cpp @@ -38,6 +38,9 @@ #include #include +#include +#include + #include #include @@ -748,6 +751,13 @@ return compositing_type & OpenGLCompositing; } +EffectFrame *EffectsHandler::effectFrame(EffectFrameStyle style, bool staticSize, const QPoint &position, Qt::Alignment alignment) const +{ + auto frame = new EffectFrame(style, staticSize, position, alignment); + connect(frame, &EffectQuickScene::repaintNeeded, this, &EffectsHandler::addRepaintFull); + return frame; +} + EffectsHandler* effects = nullptr; @@ -1701,14 +1711,24 @@ EffectFramePrivate(); ~EffectFramePrivate(); - bool crossFading; - qreal crossFadeProgress; + // exposed properties for the QtQuick implementation + QString text; + QFont font; + QIcon icon; + QSize iconSize; + bool crossFading = false; + + // semantic positioning + QPoint point; + Qt::Alignment alignment; + + // render manipulation QMatrix4x4 screenProjectionMatrix; + GLShader *shader = nullptr; }; EffectFramePrivate::EffectFramePrivate() - : crossFading(false) - , crossFadeProgress(1.0) + : crossFading() { } @@ -1719,24 +1739,179 @@ /*************************************************************** EffectFrame ***************************************************************/ -EffectFrame::EffectFrame() - : d(new EffectFramePrivate) -{ +EffectFrame::EffectFrame(EffectFrameStyle style, bool staticSize, + const QPoint &position, Qt::Alignment alignment) + : EffectQuickScene(nullptr) + , d(new EffectFramePrivate) +{ + Q_UNUSED(staticSize) + + d->point = position; + d->alignment = alignment; + + rootContext()->setContextProperty("frameData", this); + + QUrl source; + switch (style) { + case EffectFrameNone: + source = QUrl("qrc:/frames/noframe.qml"); + break; + case EffectFrameUnstyled: + source = QUrl("qrc:/frames/unstyledframe.qml"); + break; + default: + source = QUrl("qrc:/frames/styledframe.qml"); + break; + } + + setSource(source); + + if (rootItem()) { + connect(rootItem(), &QQuickItem::implicitWidthChanged, this, &EffectFrame::reposition); + connect(rootItem(), &QQuickItem::implicitHeightChanged, this, &EffectFrame::reposition); + } } EffectFrame::~EffectFrame() { - delete d; } -qreal EffectFrame::crossFadeProgress() const +void EffectFrame::free() { - return d->crossFadeProgress; + hide(); +} + +void EffectFrame::render(const QRegion ®ion, double opacity, double frameOpacity) +{ + show(); + Q_UNUSED(region) + Q_UNUSED(opacity) + Q_UNUSED(frameOpacity) + effects->renderEffectQuickView(this); +} + +void EffectFrame::setPosition(const QPoint &point) +{ + if (point == d->point) { + return; + } + d->point = point; + reposition(); +} + +void EffectFrame::setAlignment(Qt::Alignment alignment) +{ + if (alignment == d->alignment) { + return; + } + d->alignment = alignment; + reposition(); +} + +Qt::Alignment EffectFrame::alignment() const +{ + return d->alignment; +} + +void EffectFrame::reposition() +{ + if (!rootItem() || d->point.x() < 0 || d->point.y() < 0) { + return; + } + const QSizeF implicitSize(rootItem()->implicitWidth(), rootItem()->implicitHeight()); + QRect geometry(QPoint(), implicitSize.toSize()); + + if (d->alignment & Qt::AlignLeft) { + geometry.moveLeft(d->point.x()); + } else if (d->alignment & Qt::AlignRight) { + geometry.moveLeft(d->point.x() - geometry.width()); + } else { + geometry.moveLeft(d->point.x() - geometry.width() / 2); + } + + if (d->alignment & Qt::AlignTop) { + geometry.moveTop(d->point.y()); + } else if (d->alignment & Qt::AlignBottom) { + geometry.moveTop(d->point.y() - geometry.height()); + } else { + geometry.moveTop(d->point.y() - geometry.height() / 2); + } + setGeometry(geometry); +} + + +void EffectFrame::setGeometry(const QRect &geometry, bool force) +{ + Q_UNUSED(force) + EffectQuickScene::setGeometry(geometry); +} + +void EffectFrame::setText(const QString &text) +{ + if (text == d->text) { + return; + } + d->text = text; + emit textChanged(); +} + +QString EffectFrame::text() const +{ + return d->text; +} + +void EffectFrame::setFont(const QFont &font) +{ + if (font == d->font) { + return; + } + d->font = font; + emit fontChanged(); +} + +QFont EffectFrame::font() const +{ + return d->font; +} + +void EffectFrame::setIcon(const QIcon &icon) +{ + d->icon = icon; + emit iconChanged(); +} + +QIcon EffectFrame::icon() const +{ + return d->icon; +} + +void EffectFrame::setIconSize(const QSize &iconSize) +{ + if (iconSize == d->iconSize) { + return; + } + d->iconSize = iconSize; + emit iconSizeChanged(); +} + +QSize EffectFrame::iconSize() const +{ + return d->iconSize; +} + +void EffectFrame::setShader(GLShader *shader) +{ + d->shader = shader; +} + +GLShader *EffectFrame::shader() const +{ + return d->shader; } -void EffectFrame::setCrossFadeProgress(qreal progress) +EffectFrameStyle EffectFrame::style() const { - d->crossFadeProgress = progress; + return EffectFrameStyled; } bool EffectFrame::isCrossFade() const @@ -1747,6 +1922,7 @@ void EffectFrame::enableCrossFade(bool enable) { d->crossFading = enable; + emit crossFadeEnabledChanged(); } QMatrix4x4 EffectFrame::screenProjectionMatrix() const diff --git a/plugins/scenes/opengl/scene_opengl.h b/plugins/scenes/opengl/scene_opengl.h --- a/plugins/scenes/opengl/scene_opengl.h +++ b/plugins/scenes/opengl/scene_opengl.h @@ -42,13 +42,11 @@ { Q_OBJECT public: - class EffectFrame; class Window; ~SceneOpenGL() override; bool initFailed() const override; bool hasPendingFlush() const override; qint64 paint(QRegion damage, QList windows) override; - Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override; Shadow *createShadow(Toplevel *toplevel) override; void screenGeometryChanged(const QSize &size) override; OverlayWindow *overlayWindow() const override; @@ -229,44 +227,6 @@ SceneOpenGL *m_scene; }; -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(QRegion region, 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/plugins/scenes/opengl/scene_opengl.cpp b/plugins/scenes/opengl/scene_opengl.cpp --- a/plugins/scenes/opengl/scene_opengl.cpp +++ b/plugins/scenes/opengl/scene_opengl.cpp @@ -371,8 +371,6 @@ if (init_ok) { makeOpenGLContextCurrent(); } - SceneOpenGL::EffectFrame::cleanup(); - delete m_syncManager; // backend might be still needed for a different scene @@ -885,11 +883,6 @@ m_backend->doneCurrent(); } -Scene::EffectFrame *SceneOpenGL::createEffectFrame(EffectFrameImpl *frame) -{ - return new SceneOpenGL::EffectFrame(frame, this); -} - Shadow *SceneOpenGL::createShadow(Toplevel *toplevel) { return new SceneOpenGLShadow(toplevel); @@ -1632,435 +1625,6 @@ return WindowPixmap::isValid(); } -//**************************************** -// 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) -{ - if (m_effectFrame->style() == EffectFrameUnstyled && !m_unstyledTexture) { - updateUnstyledTexture(); - } -} - -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(QRegion region, double opacity, double frameOpacity) -{ - if (m_effectFrame->geometry().isEmpty()) - return; // Nothing to display - - region = infiniteRegion(); // 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->projectionMatrix(); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - // Render the actual frame - if (m_effectFrame->style() == EffectFrameUnstyled) { - 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(region, 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(region, 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(region, 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(region, 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(region, 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(region, 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(region, 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 -#define 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(); -#undef CS - 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/plugins/scenes/qpainter/scene_qpainter.h b/plugins/scenes/qpainter/scene_qpainter.h --- a/plugins/scenes/qpainter/scene_qpainter.h +++ b/plugins/scenes/qpainter/scene_qpainter.h @@ -40,7 +40,6 @@ void paintGenericScreen(int mask, ScreenPaintData data) override; CompositingType compositingType() const override; bool initFailed() const override; - EffectFrame *createEffectFrame(EffectFrameImpl *frame) override; Shadow *createShadow(Toplevel *toplevel) override; Decoration::Renderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override; void screenGeometryChanged(const QSize &size) override; @@ -103,22 +102,6 @@ QImage m_image; }; -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(QRegion region, double opacity, double frameOpacity) override; -private: - SceneQPainter *m_scene; -}; - class SceneQPainterShadow : public Shadow { public: diff --git a/plugins/scenes/qpainter/scene_qpainter.cpp b/plugins/scenes/qpainter/scene_qpainter.cpp --- a/plugins/scenes/qpainter/scene_qpainter.cpp +++ b/plugins/scenes/qpainter/scene_qpainter.cpp @@ -191,11 +191,6 @@ return new SceneQPainter::Window(this, toplevel); } -Scene::EffectFrame *SceneQPainter::createEffectFrame(EffectFrameImpl *frame) -{ - return new QPainterEffectFrame(frame, this); -} - Shadow *SceneQPainter::createShadow(Toplevel *toplevel) { return new SceneQPainterShadow(toplevel); @@ -466,84 +461,6 @@ return WindowPixmap::isValid(); } -QPainterEffectFrame::QPainterEffectFrame(EffectFrameImpl *frame, SceneQPainter *scene) - : Scene::EffectFrame(frame) - , m_scene(scene) -{ -} - -QPainterEffectFrame::~QPainterEffectFrame() -{ -} - -void QPainterEffectFrame::render(QRegion region, 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/plugins/scenes/xrender/scene_xrender.h b/plugins/scenes/xrender/scene_xrender.h --- a/plugins/scenes/xrender/scene_xrender.h +++ b/plugins/scenes/xrender/scene_xrender.h @@ -148,14 +148,12 @@ { Q_OBJECT public: - class EffectFrame; ~SceneXrender() override; bool initFailed() const override; CompositingType compositingType() const override { return XRenderCompositing; } qint64 paint(QRegion damage, QList windows) override; - Scene::EffectFrame *createEffectFrame(EffectFrameImpl *frame) override; Shadow *createShadow(Toplevel *toplevel) override; void screenGeometryChanged(const QSize &size) override; xcb_render_picture_t xrenderBufferPicture() const override; @@ -225,34 +223,6 @@ xcb_render_pictformat_t m_format; }; -class SceneXrender::EffectFrame - : public Scene::EffectFrame -{ -public: - EffectFrame(EffectFrameImpl* frame); - ~EffectFrame() override; - - void free() override; - void freeIconFrame() override; - void freeTextFrame() override; - void freeSelection() override; - void crossFadeIcon() override; - void crossFadeText() override; - void render(QRegion region, double opacity, double frameOpacity) override; - static void cleanup(); - -private: - void updatePicture(); - void updateTextPicture(); - void renderUnstyled(xcb_render_picture_t pict, const QRect &rect, qreal opacity); - - XRenderPicture* m_picture; - XRenderPicture* m_textPicture; - XRenderPicture* m_iconPicture; - XRenderPicture* m_selectionPicture; - static XRenderPicture* s_effectFrameCircle; -}; - inline xcb_render_picture_t SceneXrender::xrenderBufferPicture() const { diff --git a/plugins/scenes/xrender/scene_xrender.cpp b/plugins/scenes/xrender/scene_xrender.cpp --- a/plugins/scenes/xrender/scene_xrender.cpp +++ b/plugins/scenes/xrender/scene_xrender.cpp @@ -240,7 +240,6 @@ SceneXrender::~SceneXrender() { SceneXrender::Window::cleanup(); - SceneXrender::EffectFrame::cleanup(); } bool SceneXrender::initFailed() const @@ -295,11 +294,6 @@ return new Window(toplevel, this); } -Scene::EffectFrame *SceneXrender::createEffectFrame(EffectFrameImpl *frame) -{ - return new SceneXrender::EffectFrame(frame); -} - Shadow *SceneXrender::createShadow(Toplevel *toplevel) { return new SceneXRenderShadow(toplevel); @@ -825,277 +819,6 @@ xcb_render_create_picture(connection(), m_picture, pixmap(), m_format, 0, nullptr); } -//**************************************** -// SceneXrender::EffectFrame -//**************************************** - -XRenderPicture *SceneXrender::EffectFrame::s_effectFrameCircle = nullptr; - -SceneXrender::EffectFrame::EffectFrame(EffectFrameImpl* frame) - : Scene::EffectFrame(frame) -{ - m_picture = nullptr; - m_textPicture = nullptr; - m_iconPicture = nullptr; - m_selectionPicture = nullptr; -} - -SceneXrender::EffectFrame::~EffectFrame() -{ - delete m_picture; - delete m_textPicture; - delete m_iconPicture; - delete m_selectionPicture; -} - -void SceneXrender::EffectFrame::cleanup() -{ - delete s_effectFrameCircle; - s_effectFrameCircle = nullptr; -} - -void SceneXrender::EffectFrame::free() -{ - delete m_picture; - m_picture = nullptr; - delete m_textPicture; - m_textPicture = nullptr; - delete m_iconPicture; - m_iconPicture = nullptr; - delete m_selectionPicture; - m_selectionPicture = nullptr; -} - -void SceneXrender::EffectFrame::freeIconFrame() -{ - delete m_iconPicture; - m_iconPicture = nullptr; -} - -void SceneXrender::EffectFrame::freeTextFrame() -{ - delete m_textPicture; - m_textPicture = nullptr; -} - -void SceneXrender::EffectFrame::freeSelection() -{ - delete m_selectionPicture; - m_selectionPicture = nullptr; -} - -void SceneXrender::EffectFrame::crossFadeIcon() -{ - // TODO: implement me -} - -void SceneXrender::EffectFrame::crossFadeText() -{ - // TODO: implement me -} - -void SceneXrender::EffectFrame::render(QRegion region, double opacity, double frameOpacity) -{ - Q_UNUSED(region) - if (m_effectFrame->geometry().isEmpty()) { - return; // Nothing to display - } - - // Render the actual frame - if (m_effectFrame->style() == EffectFrameUnstyled) { - renderUnstyled(effects->xrenderBufferPicture(), m_effectFrame->geometry(), opacity * frameOpacity); - } else if (m_effectFrame->style() == EffectFrameStyled) { - if (!m_picture) { // Lazy creation - updatePicture(); - } - if (m_picture) { - 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); - xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *m_picture, - XCB_RENDER_PICTURE_NONE, effects->xrenderBufferPicture(), - 0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height()); - } - } - if (!m_effectFrame->selection().isNull()) { - if (!m_selectionPicture) { // Lazy creation - const QPixmap pix = m_effectFrame->selectionFrame().framePixmap(); - if (!pix.isNull()) // don't try if there's no content - m_selectionPicture = new XRenderPicture(m_effectFrame->selectionFrame().framePixmap().toImage()); - } - if (m_selectionPicture) { - const QRect geom = m_effectFrame->selection(); - xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *m_selectionPicture, - XCB_RENDER_PICTURE_NONE, effects->xrenderBufferPicture(), - 0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height()); - } - } - - XRenderPicture fill = xRenderBlendPicture(opacity); - - // 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); - - if (!m_iconPicture) // lazy creation - m_iconPicture = new XRenderPicture(m_effectFrame->icon().pixmap(m_effectFrame->iconSize()).toImage()); - QRect geom = QRect(topLeft, m_effectFrame->iconSize()); - xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *m_iconPicture, fill, - effects->xrenderBufferPicture(), - 0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height()); - } - - // Render text - if (!m_effectFrame->text().isEmpty()) { - if (!m_textPicture) { // Lazy creation - updateTextPicture(); - } - - if (m_textPicture) { - xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *m_textPicture, fill, effects->xrenderBufferPicture(), - 0, 0, 0, 0, m_effectFrame->geometry().x(), m_effectFrame->geometry().y(), - m_effectFrame->geometry().width(), m_effectFrame->geometry().height()); - } - } -} - -void SceneXrender::EffectFrame::renderUnstyled(xcb_render_picture_t pict, const QRect &rect, qreal opacity) -{ - const int roundness = 5; - const QRect area = rect.adjusted(-roundness, -roundness, roundness, roundness); - xcb_rectangle_t rects[3]; - // center - rects[0].x = area.left(); - rects[0].y = area.top() + roundness; - rects[0].width = area.width(); - rects[0].height = area.height() - roundness * 2; - // top - rects[1].x = area.left() + roundness; - rects[1].y = area.top(); - rects[1].width = area.width() - roundness * 2; - rects[1].height = roundness; - // bottom - rects[2].x = area.left() + roundness; - rects[2].y = area.top() + area.height() - roundness; - rects[2].width = area.width() - roundness * 2; - rects[2].height = roundness; - xcb_render_color_t color = {0, 0, 0, uint16_t(opacity * 0xffff)}; - xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_OVER, pict, color, 3, rects); - - if (!s_effectFrameCircle) { - // create the circle - const int diameter = roundness * 2; - xcb_pixmap_t pix = xcb_generate_id(connection()); - xcb_create_pixmap(connection(), 32, pix, rootWindow(), diameter, diameter); - s_effectFrameCircle = new XRenderPicture(pix, 32); - xcb_free_pixmap(connection(), pix); - - // clear it with transparent - xcb_rectangle_t xrect = {0, 0, diameter, diameter}; - xcb_render_color_t tranparent = {0, 0, 0, 0}; - xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, *s_effectFrameCircle, tranparent, 1, &xrect); - - static const int num_segments = 80; - static const qreal theta = 2 * M_PI / qreal(num_segments); - static const qreal c = qCos(theta); //precalculate the sine and cosine - static const qreal s = qSin(theta); - qreal t; - - qreal x = roundness;//we start at angle = 0 - qreal y = 0; - - QVector points; - xcb_render_pointfix_t point; - point.x = DOUBLE_TO_FIXED(roundness); - point.y = DOUBLE_TO_FIXED(roundness); - points << point; - for (int ii = 0; ii <= num_segments; ++ii) { - point.x = DOUBLE_TO_FIXED(x + roundness); - point.y = DOUBLE_TO_FIXED(y + roundness); - points << point; - //apply the rotation matrix - t = x; - x = c * x - s * y; - y = s * t + c * y; - } - XRenderPicture fill = xRenderFill(Qt::black); - xcb_render_tri_fan(connection(), XCB_RENDER_PICT_OP_OVER, fill, *s_effectFrameCircle, - 0, 0, 0, points.count(), points.constData()); - } - // TODO: merge alpha mask with SceneXrender::Window::alphaMask - // alpha mask - xcb_pixmap_t pix = xcb_generate_id(connection()); - xcb_create_pixmap(connection(), 8, pix, rootWindow(), 1, 1); - XRenderPicture alphaMask(pix, 8); - xcb_free_pixmap(connection(), pix); - const uint32_t values[] = {true}; - xcb_render_change_picture(connection(), alphaMask, XCB_RENDER_CP_REPEAT, values); - color.alpha = int(opacity * 0xffff); - xcb_rectangle_t xrect = {0, 0, 1, 1}; - xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, alphaMask, color, 1, &xrect); - - // TODO: replace by lambda -#define RENDER_CIRCLE(srcX, srcY, destX, destY) \ -xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *s_effectFrameCircle, alphaMask, \ - pict, srcX, srcY, 0, 0, destX, destY, roundness, roundness) - - RENDER_CIRCLE(0, 0, area.left(), area.top()); - RENDER_CIRCLE(0, roundness, area.left(), area.top() + area.height() - roundness); - RENDER_CIRCLE(roundness, 0, area.left() + area.width() - roundness, area.top()); - RENDER_CIRCLE(roundness, roundness, - area.left() + area.width() - roundness, area.top() + area.height() - roundness); -#undef RENDER_CIRCLE -} - -void SceneXrender::EffectFrame::updatePicture() -{ - delete m_picture; - m_picture = nullptr; - if (m_effectFrame->style() == EffectFrameStyled) { - const QPixmap pix = m_effectFrame->frame().framePixmap(); - if (!pix.isNull()) - m_picture = new XRenderPicture(pix.toImage()); - } -} - -void SceneXrender::EffectFrame::updateTextPicture() -{ - // Mostly copied from SceneOpenGL::EffectFrame::updateTextTexture() above - delete m_textPicture; - m_textPicture = 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->text()); - text = metrics.elidedText(text, Qt::ElideRight, rect.width()); - } - - QPixmap pixmap(m_effectFrame->geometry().size()); - pixmap.fill(Qt::transparent); - QPainter p(&pixmap); - 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_textPicture = new XRenderPicture(pixmap.toImage()); -} - SceneXRenderShadow::SceneXRenderShadow(Toplevel *toplevel) :Shadow(toplevel) { diff --git a/qml/CMakeLists.txt b/qml/CMakeLists.txt --- a/qml/CMakeLists.txt +++ b/qml/CMakeLists.txt @@ -1,3 +1,4 @@ install(DIRECTORY outline/plasma DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/outline) install(DIRECTORY onscreennotification/plasma DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}/onscreennotification) install(DIRECTORY virtualkeyboard DESTINATION ${DATA_INSTALL_DIR}/${KWIN_NAME}) +add_subdirectory(frame) diff --git a/qml/frame/CMakeLists.txt b/qml/frame/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/qml/frame/CMakeLists.txt @@ -0,0 +1 @@ +qt5_add_resources(kwinLibs frames.qrc) diff --git a/qml/frame/frames.qrc b/qml/frame/frames.qrc new file mode 100644 --- /dev/null +++ b/qml/frame/frames.qrc @@ -0,0 +1,7 @@ + + + noframe.qml + styledframe.qml + unstyledframe.qml + + diff --git a/qml/frame/noframe.qml b/qml/frame/noframe.qml new file mode 100644 --- /dev/null +++ b/qml/frame/noframe.qml @@ -0,0 +1,25 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.2 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +RowLayout { + id: layout + anchors.centerIn: parent + width: Math.min(parent.width, implicitWidth) + height: Math.min(parent.height, implicitHeight) + + PlasmaCore.IconItem { + source: frameData.icon + animated: frameData.crossFadeEnabled + Layout.preferredWidth: frameData.iconSize.width + Layout.preferredHeight: frameData.iconSize.height + } + PlasmaComponents.Label { + Layout.fillWidth: true + visible: text != "" + text: frameData.text + font: frameData.font + elide: Text.ElideRight + } +} diff --git a/qml/frame/styledframe.qml b/qml/frame/styledframe.qml new file mode 100644 --- /dev/null +++ b/qml/frame/styledframe.qml @@ -0,0 +1,33 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.2 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +PlasmaCore.FrameSvgItem +{ + id: root + imagePath: "widgets/background" + implicitWidth: layout.implicitWidth + fixedMargins.left + fixedMargins.right + implicitHeight: layout.implicitHeight + fixedMargins.top + fixedMargins.bottom + + RowLayout { + id: layout + anchors.centerIn: parent + width: Math.min(parent.width, implicitWidth) + height: Math.min(parent.height, implicitHeight) + + PlasmaCore.IconItem { + source: frameData.icon + animated: frameData.crossFadeEnabled + Layout.preferredWidth: frameData.iconSize.width + Layout.preferredHeight: frameData.iconSize.height + } + PlasmaComponents.Label { + Layout.fillWidth: true + visible: text != "" + text: frameData.text + font: frameData.font + elide: Text.ElideRight + } + } +} diff --git a/qml/frame/unstyledframe.qml b/qml/frame/unstyledframe.qml new file mode 100644 --- /dev/null +++ b/qml/frame/unstyledframe.qml @@ -0,0 +1,37 @@ +import QtQuick 2.12 +import QtQuick.Layouts 1.2 +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.components 2.0 as PlasmaComponents + +Rectangle +{ + id: root + + implicitWidth: layout.implicitWidth + 10 + implicitHeight: layout.implicitHeight + 10 + + color: "black" + + RowLayout { + id: layout + anchors.centerIn: parent + width: Math.min(parent.width, implicitWidth) + height: Math.min(parent.height, implicitHeight) + + PlasmaCore.IconItem { + source: frameData.icon + animated: frameData.crossFadeEnabled + Layout.preferredWidth: frameData.iconSize.width + Layout.preferredHeight: frameData.iconSize.height + } + PlasmaComponents.Label { + id: label + Layout.fillWidth: true + color: "white" + visible: text != "" + text: frameData.text + font: frameData.font + elide: Text.ElideRight + } + } +} diff --git a/scene.h b/scene.h --- a/scene.h +++ b/scene.h @@ -50,7 +50,6 @@ class AbstractThumbnailItem; class Deleted; -class EffectFrameImpl; class EffectWindowImpl; class OverlayWindow; class Shadow; @@ -63,7 +62,6 @@ public: explicit Scene(QObject *parent = nullptr); ~Scene() override = 0; - class EffectFrame; class Window; // Returns true if the ctor failed to properly initialize. @@ -97,12 +95,6 @@ */ void removeToplevel(Toplevel *toplevel); - /** - * @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. * @@ -523,23 +515,6 @@ QPointer m_subSurface; }; -class Scene::EffectFrame -{ -public: - EffectFrame(EffectFrameImpl* frame); - virtual ~EffectFrame(); - virtual void render(QRegion region, 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 Scene::Window::x() const { diff --git a/scene.cpp b/scene.cpp --- a/scene.cpp +++ b/scene.cpp @@ -1153,18 +1153,6 @@ } } -//**************************************** -// Scene::EffectFrame -//**************************************** -Scene::EffectFrame::EffectFrame(EffectFrameImpl* frame) - : m_effectFrame(frame) -{ -} - -Scene::EffectFrame::~EffectFrame() -{ -} - SceneFactory::SceneFactory(QObject *parent) : QObject(parent) {