File indexing completed on 2024-11-10 04:56:42
0001 /* 0002 SPDX-FileCopyrightText: 2006 Lubos Lunak <l.lunak@kde.org> 0003 SPDX-FileCopyrightText: 2010, 2011 Martin Gräßlin <mgraesslin@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "effect/effectframe.h" 0009 #include "effect/effecthandler.h" 0010 0011 #include <QQuickItem> 0012 #include <QStandardPaths> 0013 0014 namespace KWin 0015 { 0016 0017 EffectFrameQuickScene::EffectFrameQuickScene(EffectFrameStyle style, bool staticSize, QPoint position, Qt::Alignment alignment) 0018 : m_style(style) 0019 , m_static(staticSize) 0020 , m_point(position) 0021 , m_alignment(alignment) 0022 { 0023 0024 QString name; 0025 switch (style) { 0026 case EffectFrameNone: 0027 name = QStringLiteral("none"); 0028 break; 0029 case EffectFrameUnstyled: 0030 name = QStringLiteral("unstyled"); 0031 break; 0032 case EffectFrameStyled: 0033 name = QStringLiteral("styled"); 0034 break; 0035 } 0036 0037 const QString defaultPath = QStringLiteral("kwin/frames/plasma/frame_%1.qml").arg(name); 0038 // TODO read from kwinApp()->config() "QmlPath" like Outline/OnScreenNotification 0039 // *if* someone really needs this to be configurable. 0040 const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, defaultPath); 0041 0042 setSource(QUrl::fromLocalFile(path), QVariantMap{{QStringLiteral("effectFrame"), QVariant::fromValue(this)}}); 0043 0044 if (rootItem()) { 0045 connect(rootItem(), &QQuickItem::implicitWidthChanged, this, &EffectFrameQuickScene::reposition); 0046 connect(rootItem(), &QQuickItem::implicitHeightChanged, this, &EffectFrameQuickScene::reposition); 0047 } 0048 } 0049 0050 EffectFrameQuickScene::~EffectFrameQuickScene() = default; 0051 0052 EffectFrameStyle EffectFrameQuickScene::style() const 0053 { 0054 return m_style; 0055 } 0056 0057 bool EffectFrameQuickScene::isStatic() const 0058 { 0059 return m_static; 0060 } 0061 0062 QFont EffectFrameQuickScene::font() const 0063 { 0064 return m_font; 0065 } 0066 0067 void EffectFrameQuickScene::setFont(const QFont &font) 0068 { 0069 if (m_font == font) { 0070 return; 0071 } 0072 0073 m_font = font; 0074 Q_EMIT fontChanged(font); 0075 reposition(); 0076 } 0077 0078 QIcon EffectFrameQuickScene::icon() const 0079 { 0080 return m_icon; 0081 } 0082 0083 void EffectFrameQuickScene::setIcon(const QIcon &icon) 0084 { 0085 m_icon = icon; 0086 Q_EMIT iconChanged(icon); 0087 reposition(); 0088 } 0089 0090 QSize EffectFrameQuickScene::iconSize() const 0091 { 0092 return m_iconSize; 0093 } 0094 0095 void EffectFrameQuickScene::setIconSize(const QSize &iconSize) 0096 { 0097 if (m_iconSize == iconSize) { 0098 return; 0099 } 0100 0101 m_iconSize = iconSize; 0102 Q_EMIT iconSizeChanged(iconSize); 0103 reposition(); 0104 } 0105 0106 QString EffectFrameQuickScene::text() const 0107 { 0108 return m_text; 0109 } 0110 0111 void EffectFrameQuickScene::setText(const QString &text) 0112 { 0113 if (m_text == text) { 0114 return; 0115 } 0116 0117 m_text = text; 0118 Q_EMIT textChanged(text); 0119 reposition(); 0120 } 0121 0122 qreal EffectFrameQuickScene::frameOpacity() const 0123 { 0124 return m_frameOpacity; 0125 } 0126 0127 void EffectFrameQuickScene::setFrameOpacity(qreal frameOpacity) 0128 { 0129 if (m_frameOpacity != frameOpacity) { 0130 m_frameOpacity = frameOpacity; 0131 Q_EMIT frameOpacityChanged(frameOpacity); 0132 } 0133 } 0134 0135 bool EffectFrameQuickScene::crossFadeEnabled() const 0136 { 0137 return m_crossFadeEnabled; 0138 } 0139 0140 void EffectFrameQuickScene::setCrossFadeEnabled(bool enabled) 0141 { 0142 if (m_crossFadeEnabled != enabled) { 0143 m_crossFadeEnabled = enabled; 0144 Q_EMIT crossFadeEnabledChanged(enabled); 0145 } 0146 } 0147 0148 qreal EffectFrameQuickScene::crossFadeProgress() const 0149 { 0150 return m_crossFadeProgress; 0151 } 0152 0153 void EffectFrameQuickScene::setCrossFadeProgress(qreal progress) 0154 { 0155 if (m_crossFadeProgress != progress) { 0156 m_crossFadeProgress = progress; 0157 Q_EMIT crossFadeProgressChanged(progress); 0158 } 0159 } 0160 0161 Qt::Alignment EffectFrameQuickScene::alignment() const 0162 { 0163 return m_alignment; 0164 } 0165 0166 void EffectFrameQuickScene::setAlignment(Qt::Alignment alignment) 0167 { 0168 if (m_alignment == alignment) { 0169 return; 0170 } 0171 0172 m_alignment = alignment; 0173 reposition(); 0174 } 0175 0176 QPoint EffectFrameQuickScene::position() const 0177 { 0178 return m_point; 0179 } 0180 0181 void EffectFrameQuickScene::setPosition(const QPoint &point) 0182 { 0183 if (m_point == point) { 0184 return; 0185 } 0186 0187 m_point = point; 0188 reposition(); 0189 } 0190 0191 void EffectFrameQuickScene::reposition() 0192 { 0193 if (!rootItem() || m_point.x() < 0 || m_point.y() < 0) { 0194 return; 0195 } 0196 0197 QSizeF size; 0198 if (m_static) { 0199 size = rootItem()->size(); 0200 } else { 0201 size = QSizeF(rootItem()->implicitWidth(), rootItem()->implicitHeight()); 0202 } 0203 0204 QRect geometry(QPoint(), size.toSize()); 0205 0206 if (m_alignment & Qt::AlignLeft) 0207 geometry.moveLeft(m_point.x()); 0208 else if (m_alignment & Qt::AlignRight) 0209 geometry.moveLeft(m_point.x() - geometry.width()); 0210 else 0211 geometry.moveLeft(m_point.x() - geometry.width() / 2); 0212 if (m_alignment & Qt::AlignTop) 0213 geometry.moveTop(m_point.y()); 0214 else if (m_alignment & Qt::AlignBottom) 0215 geometry.moveTop(m_point.y() - geometry.height()); 0216 else 0217 geometry.moveTop(m_point.y() - geometry.height() / 2); 0218 0219 if (geometry == this->geometry()) { 0220 return; 0221 } 0222 0223 setGeometry(geometry); 0224 } 0225 0226 EffectFrame::EffectFrame(EffectFrameStyle style, bool staticSize, QPoint position, Qt::Alignment alignment) 0227 : m_view(new EffectFrameQuickScene(style, staticSize, position, alignment)) 0228 { 0229 connect(m_view, &OffscreenQuickScene::repaintNeeded, this, [this] { 0230 effects->addRepaint(geometry()); 0231 }); 0232 connect(m_view, &OffscreenQuickScene::geometryChanged, this, [](const QRect &oldGeometry, const QRect &newGeometry) { 0233 effects->addRepaint(oldGeometry); 0234 effects->addRepaint(newGeometry); 0235 }); 0236 } 0237 0238 EffectFrame::~EffectFrame() 0239 { 0240 // Effects often destroy their cached TextFrames in pre/postPaintScreen. 0241 // Destroying an OffscreenQuickView changes GL context, which we 0242 // must not do during effect rendering. 0243 // Delay destruction of the view until after the rendering. 0244 m_view->deleteLater(); 0245 } 0246 0247 Qt::Alignment EffectFrame::alignment() const 0248 { 0249 return m_view->alignment(); 0250 } 0251 0252 void EffectFrame::setAlignment(Qt::Alignment alignment) 0253 { 0254 m_view->setAlignment(alignment); 0255 } 0256 0257 QFont EffectFrame::font() const 0258 { 0259 return m_view->font(); 0260 } 0261 0262 void EffectFrame::setFont(const QFont &font) 0263 { 0264 m_view->setFont(font); 0265 } 0266 0267 void EffectFrame::free() 0268 { 0269 m_view->hide(); 0270 } 0271 0272 QRect EffectFrame::geometry() const 0273 { 0274 return m_view->geometry(); 0275 } 0276 0277 void EffectFrame::setGeometry(const QRect &geometry, bool force) 0278 { 0279 m_view->setGeometry(geometry); 0280 } 0281 0282 QIcon EffectFrame::icon() const 0283 { 0284 return m_view->icon(); 0285 } 0286 0287 void EffectFrame::setIcon(const QIcon &icon) 0288 { 0289 m_view->setIcon(icon); 0290 0291 if (m_view->iconSize().isEmpty() && !icon.availableSizes().isEmpty()) { // Set a size if we don't already have one 0292 setIconSize(icon.availableSizes().constFirst()); 0293 } 0294 } 0295 0296 QSize EffectFrame::iconSize() const 0297 { 0298 return m_view->iconSize(); 0299 } 0300 0301 void EffectFrame::setIconSize(const QSize &size) 0302 { 0303 m_view->setIconSize(size); 0304 } 0305 0306 void EffectFrame::setPosition(const QPoint &point) 0307 { 0308 m_view->setPosition(point); 0309 } 0310 0311 void EffectFrame::render(const RenderTarget &renderTarget, const RenderViewport &viewport, const QRegion ®ion, double opacity, double frameOpacity) 0312 { 0313 if (!m_view->rootItem()) { 0314 return; 0315 } 0316 0317 m_view->show(); 0318 0319 m_view->setOpacity(opacity); 0320 m_view->setFrameOpacity(frameOpacity); 0321 0322 effects->renderOffscreenQuickView(renderTarget, viewport, m_view); 0323 } 0324 0325 QString EffectFrame::text() const 0326 { 0327 return m_view->text(); 0328 } 0329 0330 void EffectFrame::setText(const QString &text) 0331 { 0332 m_view->setText(text); 0333 } 0334 0335 EffectFrameStyle EffectFrame::style() const 0336 { 0337 return m_view->style(); 0338 } 0339 0340 bool EffectFrame::isCrossFade() const 0341 { 0342 return m_view->crossFadeEnabled(); 0343 } 0344 0345 void EffectFrame::enableCrossFade(bool enable) 0346 { 0347 m_view->setCrossFadeEnabled(enable); 0348 } 0349 0350 qreal EffectFrame::crossFadeProgress() const 0351 { 0352 return m_view->crossFadeProgress(); 0353 } 0354 0355 void EffectFrame::setCrossFadeProgress(qreal progress) 0356 { 0357 m_view->setCrossFadeProgress(progress); 0358 } 0359 0360 } // namespace KWin 0361 0362 #include "moc_effectframe.cpp"