File indexing completed on 2024-11-10 04:56:42

0001 /*
0002     SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org>
0003     SPDX-FileCopyrightText: 2009 Lucas Murray <lmurray@undefinedfire.com>
0004     SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "effect/effect.h"
0010 #include "effect/effecthandler.h"
0011 
0012 #include <KConfigGroup>
0013 
0014 #include <QMatrix4x4>
0015 #include <QVector3D>
0016 
0017 namespace KWin
0018 {
0019 
0020 void WindowPrePaintData::setTranslucent()
0021 {
0022     mask |= Effect::PAINT_WINDOW_TRANSLUCENT;
0023     mask &= ~Effect::PAINT_WINDOW_OPAQUE;
0024     opaque = QRegion(); // cannot clip, will be transparent
0025 }
0026 
0027 void WindowPrePaintData::setTransformed()
0028 {
0029     mask |= Effect::PAINT_WINDOW_TRANSFORMED;
0030 }
0031 
0032 class PaintDataPrivate
0033 {
0034 public:
0035     PaintDataPrivate()
0036         : scale(1., 1., 1.)
0037         , rotationAxis(0, 0, 1.)
0038         , rotationAngle(0.)
0039     {
0040     }
0041     QVector3D scale;
0042     QVector3D translation;
0043 
0044     QVector3D rotationAxis;
0045     QVector3D rotationOrigin;
0046     qreal rotationAngle;
0047 };
0048 
0049 PaintData::PaintData()
0050     : d(std::make_unique<PaintDataPrivate>())
0051 {
0052 }
0053 
0054 PaintData::~PaintData() = default;
0055 
0056 qreal PaintData::xScale() const
0057 {
0058     return d->scale.x();
0059 }
0060 
0061 qreal PaintData::yScale() const
0062 {
0063     return d->scale.y();
0064 }
0065 
0066 qreal PaintData::zScale() const
0067 {
0068     return d->scale.z();
0069 }
0070 
0071 void PaintData::setScale(const QVector2D &scale)
0072 {
0073     d->scale.setX(scale.x());
0074     d->scale.setY(scale.y());
0075 }
0076 
0077 void PaintData::setScale(const QVector3D &scale)
0078 {
0079     d->scale = scale;
0080 }
0081 void PaintData::setXScale(qreal scale)
0082 {
0083     d->scale.setX(scale);
0084 }
0085 
0086 void PaintData::setYScale(qreal scale)
0087 {
0088     d->scale.setY(scale);
0089 }
0090 
0091 void PaintData::setZScale(qreal scale)
0092 {
0093     d->scale.setZ(scale);
0094 }
0095 
0096 const QVector3D &PaintData::scale() const
0097 {
0098     return d->scale;
0099 }
0100 
0101 void PaintData::setXTranslation(qreal translate)
0102 {
0103     d->translation.setX(translate);
0104 }
0105 
0106 void PaintData::setYTranslation(qreal translate)
0107 {
0108     d->translation.setY(translate);
0109 }
0110 
0111 void PaintData::setZTranslation(qreal translate)
0112 {
0113     d->translation.setZ(translate);
0114 }
0115 
0116 void PaintData::translate(qreal x, qreal y, qreal z)
0117 {
0118     translate(QVector3D(x, y, z));
0119 }
0120 
0121 void PaintData::translate(const QVector3D &t)
0122 {
0123     d->translation += t;
0124 }
0125 
0126 qreal PaintData::xTranslation() const
0127 {
0128     return d->translation.x();
0129 }
0130 
0131 qreal PaintData::yTranslation() const
0132 {
0133     return d->translation.y();
0134 }
0135 
0136 qreal PaintData::zTranslation() const
0137 {
0138     return d->translation.z();
0139 }
0140 
0141 const QVector3D &PaintData::translation() const
0142 {
0143     return d->translation;
0144 }
0145 
0146 qreal PaintData::rotationAngle() const
0147 {
0148     return d->rotationAngle;
0149 }
0150 
0151 QVector3D PaintData::rotationAxis() const
0152 {
0153     return d->rotationAxis;
0154 }
0155 
0156 QVector3D PaintData::rotationOrigin() const
0157 {
0158     return d->rotationOrigin;
0159 }
0160 
0161 void PaintData::setRotationAngle(qreal angle)
0162 {
0163     d->rotationAngle = angle;
0164 }
0165 
0166 void PaintData::setRotationAxis(Qt::Axis axis)
0167 {
0168     switch (axis) {
0169     case Qt::XAxis:
0170         setRotationAxis(QVector3D(1, 0, 0));
0171         break;
0172     case Qt::YAxis:
0173         setRotationAxis(QVector3D(0, 1, 0));
0174         break;
0175     case Qt::ZAxis:
0176         setRotationAxis(QVector3D(0, 0, 1));
0177         break;
0178     }
0179 }
0180 
0181 void PaintData::setRotationAxis(const QVector3D &axis)
0182 {
0183     d->rotationAxis = axis;
0184 }
0185 
0186 void PaintData::setRotationOrigin(const QVector3D &origin)
0187 {
0188     d->rotationOrigin = origin;
0189 }
0190 
0191 QMatrix4x4 PaintData::toMatrix(qreal deviceScale) const
0192 {
0193     QMatrix4x4 ret;
0194     if (d->translation != QVector3D(0, 0, 0)) {
0195         ret.translate(d->translation * deviceScale);
0196     }
0197     if (d->scale != QVector3D(1, 1, 1)) {
0198         ret.scale(d->scale);
0199     }
0200 
0201     if (d->rotationAngle != 0) {
0202         ret.translate(d->rotationOrigin * deviceScale);
0203         ret.rotate(d->rotationAngle, d->rotationAxis);
0204         ret.translate(-d->rotationOrigin * deviceScale);
0205     }
0206 
0207     return ret;
0208 }
0209 
0210 class WindowPaintDataPrivate
0211 {
0212 public:
0213     qreal opacity;
0214     qreal saturation;
0215     qreal brightness;
0216     int screen;
0217     qreal crossFadeProgress;
0218     QMatrix4x4 projectionMatrix;
0219 };
0220 
0221 WindowPaintData::WindowPaintData()
0222     : WindowPaintData(QMatrix4x4())
0223 {
0224 }
0225 
0226 WindowPaintData::WindowPaintData(const QMatrix4x4 &projectionMatrix)
0227     : PaintData()
0228     , d(std::make_unique<WindowPaintDataPrivate>())
0229 {
0230     setProjectionMatrix(projectionMatrix);
0231     setOpacity(1.0);
0232     setSaturation(1.0);
0233     setBrightness(1.0);
0234     setScreen(0);
0235     setCrossFadeProgress(0.0);
0236 }
0237 
0238 WindowPaintData::WindowPaintData(const WindowPaintData &other)
0239     : PaintData()
0240     , d(std::make_unique<WindowPaintDataPrivate>())
0241 {
0242     setXScale(other.xScale());
0243     setYScale(other.yScale());
0244     setZScale(other.zScale());
0245     translate(other.translation());
0246     setRotationOrigin(other.rotationOrigin());
0247     setRotationAxis(other.rotationAxis());
0248     setRotationAngle(other.rotationAngle());
0249     setOpacity(other.opacity());
0250     setSaturation(other.saturation());
0251     setBrightness(other.brightness());
0252     setScreen(other.screen());
0253     setCrossFadeProgress(other.crossFadeProgress());
0254     setProjectionMatrix(other.projectionMatrix());
0255 }
0256 
0257 WindowPaintData::~WindowPaintData() = default;
0258 
0259 qreal WindowPaintData::opacity() const
0260 {
0261     return d->opacity;
0262 }
0263 
0264 qreal WindowPaintData::saturation() const
0265 {
0266     return d->saturation;
0267 }
0268 
0269 qreal WindowPaintData::brightness() const
0270 {
0271     return d->brightness;
0272 }
0273 
0274 int WindowPaintData::screen() const
0275 {
0276     return d->screen;
0277 }
0278 
0279 void WindowPaintData::setOpacity(qreal opacity)
0280 {
0281     d->opacity = opacity;
0282 }
0283 
0284 void WindowPaintData::setSaturation(qreal saturation) const
0285 {
0286     d->saturation = saturation;
0287 }
0288 
0289 void WindowPaintData::setBrightness(qreal brightness)
0290 {
0291     d->brightness = brightness;
0292 }
0293 
0294 void WindowPaintData::setScreen(int screen) const
0295 {
0296     d->screen = screen;
0297 }
0298 
0299 qreal WindowPaintData::crossFadeProgress() const
0300 {
0301     return d->crossFadeProgress;
0302 }
0303 
0304 void WindowPaintData::setCrossFadeProgress(qreal factor)
0305 {
0306     d->crossFadeProgress = std::clamp(factor, 0.0, 1.0);
0307 }
0308 
0309 qreal WindowPaintData::multiplyOpacity(qreal factor)
0310 {
0311     d->opacity *= factor;
0312     return d->opacity;
0313 }
0314 
0315 qreal WindowPaintData::multiplySaturation(qreal factor)
0316 {
0317     d->saturation *= factor;
0318     return d->saturation;
0319 }
0320 
0321 qreal WindowPaintData::multiplyBrightness(qreal factor)
0322 {
0323     d->brightness *= factor;
0324     return d->brightness;
0325 }
0326 
0327 void WindowPaintData::setProjectionMatrix(const QMatrix4x4 &matrix)
0328 {
0329     d->projectionMatrix = matrix;
0330 }
0331 
0332 QMatrix4x4 WindowPaintData::projectionMatrix() const
0333 {
0334     return d->projectionMatrix;
0335 }
0336 
0337 QMatrix4x4 &WindowPaintData::rprojectionMatrix()
0338 {
0339     return d->projectionMatrix;
0340 }
0341 
0342 WindowPaintData &WindowPaintData::operator*=(qreal scale)
0343 {
0344     this->setXScale(this->xScale() * scale);
0345     this->setYScale(this->yScale() * scale);
0346     this->setZScale(this->zScale() * scale);
0347     return *this;
0348 }
0349 
0350 WindowPaintData &WindowPaintData::operator*=(const QVector2D &scale)
0351 {
0352     this->setXScale(this->xScale() * scale.x());
0353     this->setYScale(this->yScale() * scale.y());
0354     return *this;
0355 }
0356 
0357 WindowPaintData &WindowPaintData::operator*=(const QVector3D &scale)
0358 {
0359     this->setXScale(this->xScale() * scale.x());
0360     this->setYScale(this->yScale() * scale.y());
0361     this->setZScale(this->zScale() * scale.z());
0362     return *this;
0363 }
0364 
0365 WindowPaintData &WindowPaintData::operator+=(const QPointF &translation)
0366 {
0367     return this->operator+=(QVector3D(translation));
0368 }
0369 
0370 WindowPaintData &WindowPaintData::operator+=(const QPoint &translation)
0371 {
0372     return this->operator+=(QVector3D(translation));
0373 }
0374 
0375 WindowPaintData &WindowPaintData::operator+=(const QVector2D &translation)
0376 {
0377     return this->operator+=(QVector3D(translation));
0378 }
0379 
0380 WindowPaintData &WindowPaintData::operator+=(const QVector3D &translation)
0381 {
0382     translate(translation);
0383     return *this;
0384 }
0385 
0386 Effect::Effect(QObject *parent)
0387     : QObject(parent)
0388 {
0389 }
0390 
0391 Effect::~Effect()
0392 {
0393 }
0394 
0395 void Effect::reconfigure(ReconfigureFlags)
0396 {
0397 }
0398 
0399 void Effect::windowInputMouseEvent(QEvent *)
0400 {
0401 }
0402 
0403 void Effect::grabbedKeyboardEvent(QKeyEvent *)
0404 {
0405 }
0406 
0407 bool Effect::borderActivated(ElectricBorder)
0408 {
0409     return false;
0410 }
0411 
0412 void Effect::prePaintScreen(ScreenPrePaintData &data, std::chrono::milliseconds presentTime)
0413 {
0414     effects->prePaintScreen(data, presentTime);
0415 }
0416 
0417 void Effect::paintScreen(const RenderTarget &renderTarget, const RenderViewport &viewport, int mask, const QRegion &region, Output *screen)
0418 {
0419     effects->paintScreen(renderTarget, viewport, mask, region, screen);
0420 }
0421 
0422 void Effect::postPaintScreen()
0423 {
0424     effects->postPaintScreen();
0425 }
0426 
0427 void Effect::prePaintWindow(EffectWindow *w, WindowPrePaintData &data, std::chrono::milliseconds presentTime)
0428 {
0429     effects->prePaintWindow(w, data, presentTime);
0430 }
0431 
0432 void Effect::paintWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, QRegion region, WindowPaintData &data)
0433 {
0434     effects->paintWindow(renderTarget, viewport, w, mask, region, data);
0435 }
0436 
0437 void Effect::postPaintWindow(EffectWindow *w)
0438 {
0439     effects->postPaintWindow(w);
0440 }
0441 
0442 bool Effect::provides(Feature)
0443 {
0444     return false;
0445 }
0446 
0447 bool Effect::isActive() const
0448 {
0449     return true;
0450 }
0451 
0452 QString Effect::debug(const QString &) const
0453 {
0454     return QString();
0455 }
0456 
0457 void Effect::drawWindow(const RenderTarget &renderTarget, const RenderViewport &viewport, EffectWindow *w, int mask, const QRegion &region, WindowPaintData &data)
0458 {
0459     effects->drawWindow(renderTarget, viewport, w, mask, region, data);
0460 }
0461 
0462 void Effect::setPositionTransformations(WindowPaintData &data, QRect &region, EffectWindow *w,
0463                                         const QRect &r, Qt::AspectRatioMode aspect)
0464 {
0465     QSizeF size = w->size();
0466     size.scale(r.size(), aspect);
0467     data.setXScale(size.width() / double(w->width()));
0468     data.setYScale(size.height() / double(w->height()));
0469     int width = int(w->width() * data.xScale());
0470     int height = int(w->height() * data.yScale());
0471     int x = r.x() + (r.width() - width) / 2;
0472     int y = r.y() + (r.height() - height) / 2;
0473     region = QRect(x, y, width, height);
0474     data.setXTranslation(x - w->x());
0475     data.setYTranslation(y - w->y());
0476 }
0477 
0478 QPointF Effect::cursorPos()
0479 {
0480     return effects->cursorPos();
0481 }
0482 
0483 double Effect::animationTime(const KConfigGroup &cfg, const QString &key, int defaultTime)
0484 {
0485     int time = cfg.readEntry(key, 0);
0486     return time != 0 ? time : std::max(defaultTime * effects->animationTimeFactor(), 1.);
0487 }
0488 
0489 double Effect::animationTime(int defaultTime)
0490 {
0491     // at least 1ms, otherwise 0ms times can break some things
0492     return std::max(defaultTime * effects->animationTimeFactor(), 1.);
0493 }
0494 
0495 int Effect::requestedEffectChainPosition() const
0496 {
0497     return 0;
0498 }
0499 
0500 bool Effect::touchDown(qint32 id, const QPointF &pos, std::chrono::microseconds time)
0501 {
0502     return false;
0503 }
0504 
0505 bool Effect::touchMotion(qint32 id, const QPointF &pos, std::chrono::microseconds time)
0506 {
0507     return false;
0508 }
0509 
0510 bool Effect::touchUp(qint32 id, std::chrono::microseconds time)
0511 {
0512     return false;
0513 }
0514 
0515 bool Effect::perform(Feature feature, const QVariantList &arguments)
0516 {
0517     return false;
0518 }
0519 
0520 bool Effect::tabletToolEvent(QTabletEvent *event)
0521 {
0522     return false;
0523 }
0524 
0525 bool Effect::tabletToolButtonEvent(uint button, bool pressed, quint64 tabletToolId)
0526 {
0527     return false;
0528 }
0529 
0530 bool Effect::tabletPadButtonEvent(uint button, bool pressed, void *tabletPadId)
0531 {
0532     return false;
0533 }
0534 
0535 bool Effect::tabletPadStripEvent(int number, int position, bool isFinger, void *tabletPadId)
0536 {
0537     return false;
0538 }
0539 
0540 bool Effect::tabletPadRingEvent(int number, int position, bool isFinger, void *tabletPadId)
0541 {
0542     return false;
0543 }
0544 
0545 bool Effect::blocksDirectScanout() const
0546 {
0547     return true;
0548 }
0549 
0550 EffectPluginFactory::EffectPluginFactory()
0551 {
0552 }
0553 
0554 EffectPluginFactory::~EffectPluginFactory()
0555 {
0556 }
0557 
0558 bool EffectPluginFactory::enabledByDefault() const
0559 {
0560     return true;
0561 }
0562 
0563 bool EffectPluginFactory::isSupported() const
0564 {
0565     return true;
0566 }
0567 
0568 } // namespace KWin
0569 
0570 #include "moc_effect.cpp"