File indexing completed on 2025-03-23 11:13:33
0001 /* 0002 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "renderlayer.h" 0008 #include "outputlayer.h" 0009 #include "renderlayerdelegate.h" 0010 #include "renderloop.h" 0011 0012 namespace KWin 0013 { 0014 0015 RenderLayer::RenderLayer(RenderLoop *loop, RenderLayer *superlayer) 0016 : m_loop(loop) 0017 { 0018 setSuperlayer(superlayer); 0019 } 0020 0021 RenderLayer::~RenderLayer() 0022 { 0023 const auto sublayers = m_sublayers; 0024 for (RenderLayer *sublayer : sublayers) { 0025 sublayer->setSuperlayer(superlayer()); 0026 } 0027 setSuperlayer(nullptr); 0028 } 0029 0030 OutputLayer *RenderLayer::outputLayer() const 0031 { 0032 return m_outputLayer; 0033 } 0034 0035 void RenderLayer::setOutputLayer(OutputLayer *layer) 0036 { 0037 if (m_outputLayer == layer) { 0038 return; 0039 } 0040 if (m_outputLayer) { 0041 m_outputLayer->addRepaint(mapToGlobal(boundingRect())); 0042 } 0043 m_outputLayer = layer; 0044 for (RenderLayer *sublayer : std::as_const(m_sublayers)) { 0045 sublayer->setOutputLayer(layer); 0046 } 0047 } 0048 0049 RenderLayer *RenderLayer::superlayer() const 0050 { 0051 return m_superlayer; 0052 } 0053 0054 void RenderLayer::setSuperlayer(RenderLayer *layer) 0055 { 0056 if (m_superlayer == layer) { 0057 return; 0058 } 0059 if (m_superlayer) { 0060 m_superlayer->removeSublayer(this); 0061 } 0062 m_superlayer = layer; 0063 if (m_superlayer) { 0064 m_superlayer->addSublayer(this); 0065 } 0066 updateEffectiveVisibility(); 0067 } 0068 0069 QList<RenderLayer *> RenderLayer::sublayers() const 0070 { 0071 return m_sublayers; 0072 } 0073 0074 void RenderLayer::addSublayer(RenderLayer *sublayer) 0075 { 0076 m_sublayers.append(sublayer); 0077 sublayer->setOutputLayer(m_outputLayer); 0078 updateBoundingRect(); 0079 } 0080 0081 void RenderLayer::removeSublayer(RenderLayer *sublayer) 0082 { 0083 m_sublayers.removeOne(sublayer); 0084 sublayer->setOutputLayer(nullptr); 0085 updateBoundingRect(); 0086 } 0087 0088 RenderLoop *RenderLayer::loop() const 0089 { 0090 return m_loop; 0091 } 0092 0093 RenderLayerDelegate *RenderLayer::delegate() const 0094 { 0095 return m_delegate.get(); 0096 } 0097 0098 void RenderLayer::setDelegate(std::unique_ptr<RenderLayerDelegate> delegate) 0099 { 0100 m_delegate = std::move(delegate); 0101 m_delegate->setLayer(this); 0102 } 0103 0104 QRect RenderLayer::rect() const 0105 { 0106 return QRect(0, 0, m_geometry.width(), m_geometry.height()); 0107 } 0108 0109 QRect RenderLayer::boundingRect() const 0110 { 0111 return m_boundingRect; 0112 } 0113 0114 QRect RenderLayer::geometry() const 0115 { 0116 return m_geometry; 0117 } 0118 0119 void RenderLayer::setGeometry(const QRect &geometry) 0120 { 0121 if (m_geometry == geometry) { 0122 return; 0123 } 0124 if (m_effectiveVisible && m_outputLayer) { 0125 m_outputLayer->addRepaint(mapToGlobal(boundingRect())); 0126 } 0127 0128 m_geometry = geometry; 0129 addRepaintFull(); 0130 0131 updateBoundingRect(); 0132 if (m_superlayer) { 0133 m_superlayer->updateBoundingRect(); 0134 } 0135 } 0136 0137 void RenderLayer::updateBoundingRect() 0138 { 0139 QRect boundingRect = rect(); 0140 for (const RenderLayer *sublayer : std::as_const(m_sublayers)) { 0141 boundingRect |= sublayer->boundingRect().translated(sublayer->geometry().topLeft()); 0142 } 0143 0144 if (m_boundingRect != boundingRect) { 0145 m_boundingRect = boundingRect; 0146 if (m_superlayer) { 0147 m_superlayer->updateBoundingRect(); 0148 } 0149 } 0150 } 0151 0152 void RenderLayer::addRepaintFull() 0153 { 0154 addRepaint(rect()); 0155 } 0156 0157 void RenderLayer::addRepaint(int x, int y, int width, int height) 0158 { 0159 addRepaint(QRegion(x, y, width, height)); 0160 } 0161 0162 void RenderLayer::addRepaint(const QRect &rect) 0163 { 0164 addRepaint(QRegion(rect)); 0165 } 0166 0167 void RenderLayer::addRepaint(const QRegion ®ion) 0168 { 0169 if (!m_effectiveVisible) { 0170 return; 0171 } 0172 if (!region.isEmpty()) { 0173 m_repaints += region; 0174 m_loop->scheduleRepaint(); 0175 } 0176 } 0177 0178 QRegion RenderLayer::repaints() const 0179 { 0180 return m_repaints; 0181 } 0182 0183 void RenderLayer::resetRepaints() 0184 { 0185 m_repaints = QRegion(); 0186 } 0187 0188 bool RenderLayer::isVisible() const 0189 { 0190 return m_effectiveVisible; 0191 } 0192 0193 void RenderLayer::setVisible(bool visible) 0194 { 0195 if (m_explicitVisible != visible) { 0196 m_explicitVisible = visible; 0197 updateEffectiveVisibility(); 0198 } 0199 } 0200 0201 bool RenderLayer::computeEffectiveVisibility() const 0202 { 0203 return m_explicitVisible && (!m_superlayer || m_superlayer->isVisible()); 0204 } 0205 0206 void RenderLayer::updateEffectiveVisibility() 0207 { 0208 const bool effectiveVisible = computeEffectiveVisibility(); 0209 if (m_effectiveVisible == effectiveVisible) { 0210 return; 0211 } 0212 0213 m_effectiveVisible = effectiveVisible; 0214 0215 if (effectiveVisible) { 0216 addRepaintFull(); 0217 } else { 0218 if (m_outputLayer) { 0219 m_outputLayer->addRepaint(mapToGlobal(boundingRect())); 0220 } 0221 } 0222 0223 for (RenderLayer *sublayer : std::as_const(m_sublayers)) { 0224 sublayer->updateEffectiveVisibility(); 0225 } 0226 } 0227 0228 QPoint RenderLayer::mapToGlobal(const QPoint &point) const 0229 { 0230 QPoint result = point; 0231 const RenderLayer *layer = this; 0232 while (layer) { 0233 result += layer->geometry().topLeft(); 0234 layer = layer->superlayer(); 0235 } 0236 return result; 0237 } 0238 0239 QRect RenderLayer::mapToGlobal(const QRect &rect) const 0240 { 0241 return rect.translated(mapToGlobal(QPoint(0, 0))); 0242 } 0243 0244 QRegion RenderLayer::mapToGlobal(const QRegion ®ion) const 0245 { 0246 if (region.isEmpty()) { 0247 return QRegion(); 0248 } 0249 return region.translated(mapToGlobal(QPoint(0, 0))); 0250 } 0251 0252 QPoint RenderLayer::mapFromGlobal(const QPoint &point) const 0253 { 0254 QPoint result = point; 0255 const RenderLayer *layer = this; 0256 while (layer) { 0257 result -= layer->geometry().topLeft(); 0258 layer = layer->superlayer(); 0259 } 0260 return result; 0261 } 0262 0263 QRect RenderLayer::mapFromGlobal(const QRect &rect) const 0264 { 0265 return rect.translated(mapFromGlobal(QPoint(0, 0))); 0266 } 0267 0268 QRegion RenderLayer::mapFromGlobal(const QRegion ®ion) const 0269 { 0270 if (region.isEmpty()) { 0271 return QRegion(); 0272 } 0273 return region.translated(mapFromGlobal(QPoint(0, 0))); 0274 } 0275 0276 } // namespace KWin