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;
81void ScreenEdgeEffect::prePaintScreen(
ScreenPrePaintData &data, std::chrono::milliseconds presentTime) {
…}
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
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