17#include <KConfigGroup> 
   18#include <KSharedConfig> 
   31    , m_cleanupTimer(new QTimer(this))
 
   34    m_cleanupTimer->setInterval(5000);
 
   35    m_cleanupTimer->setSingleShot(
true);
 
   36    connect(m_cleanupTimer, &QTimer::timeout, 
this, &ScreenEdgeEffect::cleanup);
 
 
   49void ScreenEdgeEffect::ensureGlowSvg()
 
   52        m_glow = 
new KSvg::Svg(
this);
 
   53        m_glow->imageSet()->setBasePath(QStringLiteral(
"plasma/desktoptheme"));
 
   55        const QString groupName = QStringLiteral(
"Theme");
 
   56        KSharedConfig::Ptr config = KSharedConfig::openConfig(QStringLiteral(
"plasmarc"));
 
   57        KConfigGroup cg = KConfigGroup(config, groupName);
 
   58        m_glow->imageSet()->setImageSetName(cg.readEntry(
"name", QStringLiteral(
"default")));
 
   60        m_configWatcher = KConfigWatcher::create(config);
 
   62        connect(m_configWatcher.data(), &KConfigWatcher::configChanged, 
this, [
this](
const KConfigGroup &group, 
const QByteArrayList &names) {
 
   63            if (group.name() != QStringLiteral(
"Theme") || !names.contains(QStringLiteral(
"name"))) {
 
   66            m_glow->imageSet()->setImageSetName(group.readEntry(
"name", QStringLiteral(
"default")));
 
   69        m_glow->setImagePath(QStringLiteral(
"widgets/glowbar"));
 
   73void ScreenEdgeEffect::cleanup()
 
   75    for (
auto &[border, glow] : m_borders) {
 
   81void ScreenEdgeEffect::prePaintScreen(
ScreenPrePaintData &data, std::chrono::milliseconds presentTime)
 
   84    for (
auto &[border, glow] : m_borders) {
 
   85        if (glow->strength == 0.0) {
 
   88        data.
paint += glow->geometry;
 
 
   95    for (
auto &[border, glow] : m_borders) {
 
   96        const qreal opacity = glow->strength;
 
  106            glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
  107            ShaderBinder binder(ShaderTrait::MapTexture | ShaderTrait::Modulate | ShaderTrait::TransformColorspace);
 
  109            const QVector4D constant(opacity, opacity, opacity, opacity);
 
  110            binder.
shader()->
setUniform(GLShader::Vec4Uniform::ModulationConstant, constant);
 
  111            const auto scale = viewport.
scale();
 
  113            mvp.translate(glow->geometry.x() * scale, glow->geometry.y() * scale);
 
  114            binder.
shader()->
setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mvp);
 
  115            texture->
render(glow->geometry.size() * scale);
 
  118            QImage tmp(glow->image.size(), QImage::Format_ARGB32_Premultiplied);
 
  119            tmp.fill(Qt::transparent);
 
  121            p.drawImage(0, 0, glow->image);
 
  122            QColor color(Qt::transparent);
 
  123            color.setAlphaF(opacity);
 
  124            p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
 
  125            p.fillRect(QRect(QPoint(0, 0), tmp.size()), color);
 
  129            const QRect &rect = glow->geometry;
 
  130            const QSize &size = glow->pictureSize;
 
  133            switch (glow->border) {
 
  135                x = rect.x() + rect.width() - size.width();
 
  138                x = rect.x() + rect.width() - size.width();
 
  139                y = rect.y() + rect.height() - size.height();
 
  142                y = rect.y() + rect.height() - size.height();
 
  148            painter->drawImage(QPoint(x, y), tmp);
 
 
  153void ScreenEdgeEffect::edgeApproaching(
ElectricBorder border, qreal factor, 
const QRect &geometry)
 
  155    auto it = m_borders.find(border);
 
  156    if (it != m_borders.end()) {
 
  157        Glow *glow = it->second.get();
 
  164            if (border == ElectricLeft || border == ElectricRight || border == ElectricTop || border == ElectricBottom) {
 
  166                    glow->
texture = GLTexture::upload(createEdgeGlow(border, geometry.size()));
 
  168                    glow->
image = createEdgeGlow(border, geometry.size());
 
  173            m_cleanupTimer->start();
 
  175            m_cleanupTimer->stop();
 
  177    } 
else if (factor != 0.0) {
 
  179        std::unique_ptr<Glow> glow = createGlow(border, factor, geometry);
 
  182            m_borders[border] = std::move(glow);
 
  187std::unique_ptr<Glow> ScreenEdgeEffect::createGlow(ElectricBorder border, qreal factor, 
const QRect &geometry)
 
  189    auto glow = std::make_unique<Glow>();
 
  190    glow->border = border;
 
  191    glow->strength = factor;
 
  192    glow->geometry = geometry;
 
  197        if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
 
  198            glow->texture = GLTexture::upload(createCornerGlow(border));
 
  200            glow->texture = GLTexture::upload(createEdgeGlow(border, geometry.size()));
 
  202        if (!glow->texture) {
 
  205        glow->texture->setWrapMode(GL_CLAMP_TO_EDGE);
 
  207        if (border == ElectricTopLeft || border == ElectricTopRight || border == ElectricBottomRight || border == ElectricBottomLeft) {
 
  208            glow->image = createCornerGlow(border);
 
  209            glow->pictureSize = cornerGlowSize(border);
 
  211            glow->image = createEdgeGlow(border, geometry.size());
 
  212            glow->pictureSize = geometry.size();
 
  214        if (glow->image.isNull()) {
 
  222QImage ScreenEdgeEffect::createCornerGlow(ElectricBorder border)
 
  228        return m_glow->pixmap(QStringLiteral(
"bottomright")).toImage();
 
  230        return m_glow->pixmap(QStringLiteral(
"bottomleft")).toImage();
 
  232        return m_glow->pixmap(QStringLiteral(
"topleft")).toImage();
 
  234        return m_glow->pixmap(QStringLiteral(
"topright")).toImage();
 
  240QSize ScreenEdgeEffect::cornerGlowSize(ElectricBorder border)
 
  246        return m_glow->elementSize(QStringLiteral(
"bottomright")).toSize();
 
  248        return m_glow->elementSize(QStringLiteral(
"bottomleft")).toSize();
 
  250        return m_glow->elementSize(QStringLiteral(
"topleft")).toSize();
 
  252        return m_glow->elementSize(QStringLiteral(
"topright")).toSize();
 
  258QImage ScreenEdgeEffect::createEdgeGlow(ElectricBorder border, 
const QSize &size)
 
  262    const bool stretchBorder = m_glow->hasElement(QStringLiteral(
"hint-stretch-borders"));
 
  264    QPoint pixmapPosition(0, 0);
 
  268        l = m_glow->pixmap(QStringLiteral(
"bottomleft"));
 
  269        r = m_glow->pixmap(QStringLiteral(
"bottomright"));
 
  270        c = m_glow->pixmap(QStringLiteral(
"bottom"));
 
  273        l = m_glow->pixmap(QStringLiteral(
"topleft"));
 
  274        r = m_glow->pixmap(QStringLiteral(
"topright"));
 
  275        c = m_glow->pixmap(QStringLiteral(
"top"));
 
  276        pixmapPosition = QPoint(0, size.height() - c.height());
 
  279        l = m_glow->pixmap(QStringLiteral(
"topright"));
 
  280        r = m_glow->pixmap(QStringLiteral(
"bottomright"));
 
  281        c = m_glow->pixmap(QStringLiteral(
"right"));
 
  284        l = m_glow->pixmap(QStringLiteral(
"topleft"));
 
  285        r = m_glow->pixmap(QStringLiteral(
"bottomleft"));
 
  286        c = m_glow->pixmap(QStringLiteral(
"left"));
 
  287        pixmapPosition = QPoint(size.width() - c.width(), 0);
 
  293    image.fill(Qt::transparent);
 
  296    if (border == ElectricBottom || border == ElectricTop) {
 
  297        p.drawPixmap(pixmapPosition, l);
 
  298        const QRect cRect(l.width(), pixmapPosition.y(), size.width() - l.width() - r.width(), c.height());
 
  300            p.drawPixmap(cRect, c);
 
  302            p.drawTiledPixmap(cRect, c);
 
  304        p.drawPixmap(QPoint(size.width() - r.width(), pixmapPosition.y()), r);
 
  306        p.drawPixmap(pixmapPosition, l);
 
  307        const QRect cRect(pixmapPosition.x(), l.height(), c.width(), size.height() - l.height() - r.height());
 
  309            p.drawPixmap(cRect, c);
 
  311            p.drawTiledPixmap(cRect, c);
 
  313        p.drawPixmap(QPoint(pixmapPosition.x(), size.height() - r.height()), r);
 
  316    return image.toImage();
 
  319bool ScreenEdgeEffect::isActive()
 const 
 
  326#include "moc_screenedgeeffect.cpp" 
Base class for all KWin effects.
void screenLockingChanged(bool locked)
void paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion ®ion, Output *screen)
Q_SCRIPTABLE void addRepaint(const QRectF &r)
bool makeOpenGLContextCurrent()
Makes the OpenGL compositing context current.
CompositingType compositingType
bool isScreenLocked() const
void prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime)
bool isOpenGLCompositing() const
Whether the Compositor is OpenGL based (either GL 1 or 2).
void screenEdgeApproaching(ElectricBorder border, qreal factor, const QRect &geometry)
QPainter * scenePainter()
Provides access to the QPainter which is rendering to the back buffer.
bool setColorspaceUniformsFromSRGB(const ColorDescription &dst)
bool setUniform(const char *name, float value)
void render(const QSizeF &size)
std::unique_ptr< GLTexture > texture
const ColorDescription & colorDescription() const
QMatrix4x4 projectionMatrix() const
~ScreenEdgeEffect() override