File indexing completed on 2024-12-01 11:10:42
0001 /* 0002 SPDX-FileCopyrightText: 2011 Aaron Seigo <aseigo@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "panelshadows_p.h" 0008 0009 #include <QDebug> 0010 #include <KWindowShadow> 0011 0012 class PanelShadows::Private 0013 { 0014 public: 0015 Private(PanelShadows *shadows) 0016 : q(shadows) 0017 { 0018 } 0019 0020 ~Private() 0021 { 0022 } 0023 0024 void clearTiles(); 0025 void setupTiles(); 0026 void initTile(const QString &element); 0027 void updateShadow(QWindow *window, Plasma::FrameSvg::EnabledBorders); 0028 void clearShadow(QWindow *window); 0029 void updateShadows(); 0030 bool hasShadows() const; 0031 0032 PanelShadows *q; 0033 0034 QHash<QWindow *, Plasma::FrameSvg::EnabledBorders> m_windows; 0035 QHash<QWindow *, KWindowShadow *> m_shadows; 0036 QVector<KWindowShadowTile::Ptr> m_tiles; 0037 }; 0038 0039 class PanelShadowsSingleton 0040 { 0041 public: 0042 PanelShadowsSingleton() 0043 { 0044 } 0045 0046 PanelShadows self; 0047 }; 0048 0049 Q_GLOBAL_STATIC(PanelShadowsSingleton, privatePanelShadowsSelf) 0050 0051 PanelShadows::PanelShadows(QObject *parent, const QString &prefix) 0052 : Plasma::Svg(parent) 0053 , d(new Private(this)) 0054 { 0055 setImagePath(prefix); 0056 connect(this, &Plasma::Svg::repaintNeeded, this, [this]() { 0057 d->updateShadows(); 0058 }); 0059 } 0060 0061 PanelShadows::~PanelShadows() 0062 { 0063 delete d; 0064 } 0065 0066 PanelShadows *PanelShadows::self() 0067 { 0068 return &privatePanelShadowsSelf->self; 0069 } 0070 0071 void PanelShadows::addWindow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) 0072 { 0073 if (!window) { 0074 return; 0075 } 0076 0077 d->m_windows[window] = enabledBorders; 0078 d->updateShadow(window, enabledBorders); 0079 connect(window, &QObject::destroyed, this, [this, window]() { 0080 d->m_windows.remove(window); 0081 d->clearShadow(window); 0082 if (d->m_windows.isEmpty()) { 0083 d->clearTiles(); 0084 } 0085 }); 0086 } 0087 0088 void PanelShadows::removeWindow(QWindow *window) 0089 { 0090 if (!d->m_windows.contains(window)) { 0091 return; 0092 } 0093 0094 d->m_windows.remove(window); 0095 disconnect(window, nullptr, this, nullptr); 0096 d->clearShadow(window); 0097 0098 if (d->m_windows.isEmpty()) { 0099 d->clearTiles(); 0100 } 0101 } 0102 0103 void PanelShadows::setEnabledBorders(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) 0104 { 0105 if (!window || !d->m_windows.contains(window)) { 0106 return; 0107 } 0108 0109 d->m_windows[window] = enabledBorders; 0110 d->updateShadow(window, enabledBorders); 0111 } 0112 0113 void PanelShadows::Private::updateShadows() 0114 { 0115 const bool hadShadowsBefore = !m_tiles.isEmpty(); 0116 0117 // has shadows now? 0118 if (hasShadows()) { 0119 if (hadShadowsBefore) { 0120 clearTiles(); 0121 } 0122 for (auto i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) { 0123 updateShadow(i.key(), i.value()); 0124 } 0125 } else { 0126 if (hadShadowsBefore) { 0127 for (auto i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) { 0128 clearShadow(i.key()); 0129 } 0130 clearTiles(); 0131 } 0132 } 0133 } 0134 0135 void PanelShadows::Private::initTile(const QString &element) 0136 { 0137 const QImage image = q->pixmap(element).toImage(); 0138 0139 KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create(); 0140 tile->setImage(image); 0141 0142 m_tiles << tile; 0143 } 0144 0145 void PanelShadows::Private::setupTiles() 0146 { 0147 clearTiles(); 0148 0149 initTile(QStringLiteral("shadow-top")); 0150 initTile(QStringLiteral("shadow-topright")); 0151 initTile(QStringLiteral("shadow-right")); 0152 initTile(QStringLiteral("shadow-bottomright")); 0153 initTile(QStringLiteral("shadow-bottom")); 0154 initTile(QStringLiteral("shadow-bottomleft")); 0155 initTile(QStringLiteral("shadow-left")); 0156 initTile(QStringLiteral("shadow-topleft")); 0157 } 0158 0159 void PanelShadows::Private::clearTiles() 0160 { 0161 m_tiles.clear(); 0162 } 0163 0164 void PanelShadows::Private::updateShadow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) 0165 { 0166 if (!hasShadows()) { 0167 return; 0168 } 0169 0170 if (m_tiles.isEmpty()) { 0171 setupTiles(); 0172 } 0173 0174 KWindowShadow *&shadow = m_shadows[window]; 0175 0176 if (!shadow) { 0177 shadow = new KWindowShadow(q); 0178 } 0179 0180 if (shadow->isCreated()) { 0181 shadow->destroy(); 0182 } 0183 0184 if (enabledBorders & Plasma::FrameSvg::TopBorder) { 0185 shadow->setTopTile(m_tiles.at(0)); 0186 } else { 0187 shadow->setTopTile(nullptr); 0188 } 0189 0190 if (enabledBorders & Plasma::FrameSvg::TopBorder && enabledBorders & Plasma::FrameSvg::RightBorder) { 0191 shadow->setTopRightTile(m_tiles.at(1)); 0192 } else { 0193 shadow->setTopRightTile(nullptr); 0194 } 0195 0196 if (enabledBorders & Plasma::FrameSvg::RightBorder) { 0197 shadow->setRightTile(m_tiles.at(2)); 0198 } else { 0199 shadow->setRightTile(nullptr); 0200 } 0201 0202 if (enabledBorders & Plasma::FrameSvg::BottomBorder && enabledBorders & Plasma::FrameSvg::RightBorder) { 0203 shadow->setBottomRightTile(m_tiles.at(3)); 0204 } else { 0205 shadow->setBottomRightTile(nullptr); 0206 } 0207 0208 if (enabledBorders & Plasma::FrameSvg::BottomBorder) { 0209 shadow->setBottomTile(m_tiles.at(4)); 0210 } else { 0211 shadow->setBottomTile(nullptr); 0212 } 0213 0214 if (enabledBorders & Plasma::FrameSvg::BottomBorder && enabledBorders & Plasma::FrameSvg::LeftBorder) { 0215 shadow->setBottomLeftTile(m_tiles.at(5)); 0216 } else { 0217 shadow->setBottomLeftTile(nullptr); 0218 } 0219 0220 if (enabledBorders & Plasma::FrameSvg::LeftBorder) { 0221 shadow->setLeftTile(m_tiles.at(6)); 0222 } else { 0223 shadow->setLeftTile(nullptr); 0224 } 0225 0226 if (enabledBorders & Plasma::FrameSvg::TopBorder && enabledBorders & Plasma::FrameSvg::LeftBorder) { 0227 shadow->setTopLeftTile(m_tiles.at(7)); 0228 } else { 0229 shadow->setTopLeftTile(nullptr); 0230 } 0231 0232 QMargins padding; 0233 0234 if (enabledBorders & Plasma::FrameSvg::TopBorder) { 0235 const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin")); 0236 if (marginHint.isValid()) { 0237 padding.setTop(marginHint.height()); 0238 } else { 0239 padding.setTop(m_tiles[0]->image().height()); 0240 } 0241 } 0242 0243 if (enabledBorders & Plasma::FrameSvg::RightBorder) { 0244 const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin")); 0245 if (marginHint.isValid()) { 0246 padding.setRight(marginHint.width()); 0247 } else { 0248 padding.setRight(m_tiles[2]->image().width()); 0249 } 0250 } 0251 0252 if (enabledBorders & Plasma::FrameSvg::BottomBorder) { 0253 const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin")); 0254 if (marginHint.isValid()) { 0255 padding.setBottom(marginHint.height()); 0256 } else { 0257 padding.setBottom(m_tiles[4]->image().height()); 0258 } 0259 } 0260 0261 if (enabledBorders & Plasma::FrameSvg::LeftBorder) { 0262 const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin")); 0263 if (marginHint.isValid()) { 0264 padding.setLeft(marginHint.width()); 0265 } else { 0266 padding.setLeft(m_tiles[6]->image().width()); 0267 } 0268 } 0269 0270 shadow->setPadding(padding); 0271 shadow->setWindow(window); 0272 0273 if (!shadow->create()) { 0274 qDebug() << "Couldn't create KWindowShadow for" << window; 0275 } 0276 } 0277 0278 void PanelShadows::Private::clearShadow(QWindow *window) 0279 { 0280 delete m_shadows.take(window); 0281 } 0282 0283 bool PanelShadows::Private::hasShadows() const 0284 { 0285 return q->hasElement(QStringLiteral("shadow-left")); 0286 } 0287 0288 #include "moc_panelshadows_p.cpp"