File indexing completed on 2024-11-10 04:56:40
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()).toAlignedRect()); 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 QRectF RenderLayer::rect() const 0105 { 0106 return QRect(0, 0, m_geometry.width(), m_geometry.height()); 0107 } 0108 0109 QRectF RenderLayer::boundingRect() const 0110 { 0111 return m_boundingRect; 0112 } 0113 0114 QRectF RenderLayer::geometry() const 0115 { 0116 return m_geometry; 0117 } 0118 0119 void RenderLayer::setGeometry(const QRectF &geometry) 0120 { 0121 if (m_geometry == geometry) { 0122 return; 0123 } 0124 if (m_effectiveVisible && m_outputLayer) { 0125 m_outputLayer->addRepaint(mapToGlobal(boundingRect()).toAlignedRect()); 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::scheduleRepaint(Item *item) 0138 { 0139 m_repaintScheduled = true; 0140 m_loop->scheduleRepaint(item); 0141 } 0142 0143 bool RenderLayer::needsRepaint() const 0144 { 0145 if (m_repaintScheduled) { 0146 return true; 0147 } 0148 if (!m_repaints.isEmpty()) { 0149 return true; 0150 } 0151 return std::any_of(m_sublayers.constBegin(), m_sublayers.constEnd(), [](RenderLayer *layer) { 0152 return layer->needsRepaint(); 0153 }); 0154 } 0155 0156 void RenderLayer::updateBoundingRect() 0157 { 0158 QRectF boundingRect = rect(); 0159 for (const RenderLayer *sublayer : std::as_const(m_sublayers)) { 0160 boundingRect |= sublayer->boundingRect().translated(sublayer->geometry().topLeft()); 0161 } 0162 0163 if (m_boundingRect != boundingRect) { 0164 m_boundingRect = boundingRect; 0165 if (m_superlayer) { 0166 m_superlayer->updateBoundingRect(); 0167 } 0168 } 0169 } 0170 0171 void RenderLayer::addRepaintFull() 0172 { 0173 addRepaint(rect().toAlignedRect()); 0174 } 0175 0176 void RenderLayer::addRepaint(int x, int y, int width, int height) 0177 { 0178 addRepaint(QRegion(x, y, width, height)); 0179 } 0180 0181 void RenderLayer::addRepaint(const QRect &rect) 0182 { 0183 addRepaint(QRegion(rect)); 0184 } 0185 0186 void RenderLayer::addRepaint(const QRegion ®ion) 0187 { 0188 if (!m_effectiveVisible) { 0189 return; 0190 } 0191 if (!region.isEmpty()) { 0192 m_repaints += region; 0193 m_loop->scheduleRepaint(); 0194 } 0195 } 0196 0197 QRegion RenderLayer::repaints() const 0198 { 0199 return m_repaints; 0200 } 0201 0202 void RenderLayer::resetRepaints() 0203 { 0204 m_repaints = QRegion(); 0205 m_repaintScheduled = false; 0206 } 0207 0208 bool RenderLayer::isVisible() const 0209 { 0210 return m_effectiveVisible; 0211 } 0212 0213 void RenderLayer::setVisible(bool visible) 0214 { 0215 if (m_explicitVisible != visible) { 0216 m_explicitVisible = visible; 0217 updateEffectiveVisibility(); 0218 } 0219 } 0220 0221 bool RenderLayer::computeEffectiveVisibility() const 0222 { 0223 return m_explicitVisible && (!m_superlayer || m_superlayer->isVisible()); 0224 } 0225 0226 void RenderLayer::updateEffectiveVisibility() 0227 { 0228 const bool effectiveVisible = computeEffectiveVisibility(); 0229 if (m_effectiveVisible == effectiveVisible) { 0230 return; 0231 } 0232 0233 m_effectiveVisible = effectiveVisible; 0234 0235 if (effectiveVisible) { 0236 addRepaintFull(); 0237 } else { 0238 if (m_outputLayer) { 0239 m_outputLayer->addRepaint(mapToGlobal(boundingRect()).toAlignedRect()); 0240 m_loop->scheduleRepaint(); 0241 } 0242 } 0243 0244 for (RenderLayer *sublayer : std::as_const(m_sublayers)) { 0245 sublayer->updateEffectiveVisibility(); 0246 } 0247 } 0248 0249 QPoint RenderLayer::mapToGlobal(const QPoint &point) const 0250 { 0251 return mapToGlobal(QPointF(point)).toPoint(); 0252 } 0253 0254 QPointF RenderLayer::mapToGlobal(const QPointF &point) const 0255 { 0256 QPointF result = point; 0257 const RenderLayer *layer = this; 0258 while (layer) { 0259 result += layer->geometry().topLeft(); 0260 layer = layer->superlayer(); 0261 } 0262 return result; 0263 } 0264 0265 QRect RenderLayer::mapToGlobal(const QRect &rect) const 0266 { 0267 return rect.translated(mapToGlobal(QPoint(0, 0))); 0268 } 0269 0270 QRectF RenderLayer::mapToGlobal(const QRectF &rect) const 0271 { 0272 return rect.translated(mapToGlobal(QPointF(0, 0))); 0273 } 0274 0275 QRegion RenderLayer::mapToGlobal(const QRegion ®ion) const 0276 { 0277 if (region.isEmpty()) { 0278 return QRegion(); 0279 } 0280 return region.translated(mapToGlobal(QPoint(0, 0))); 0281 } 0282 0283 QPoint RenderLayer::mapFromGlobal(const QPoint &point) const 0284 { 0285 return mapFromGlobal(QPointF(point)).toPoint(); 0286 } 0287 0288 QPointF RenderLayer::mapFromGlobal(const QPointF &point) const 0289 { 0290 QPointF result = point; 0291 const RenderLayer *layer = this; 0292 while (layer) { 0293 result -= layer->geometry().topLeft(); 0294 layer = layer->superlayer(); 0295 } 0296 return result; 0297 } 0298 0299 QRect RenderLayer::mapFromGlobal(const QRect &rect) const 0300 { 0301 return rect.translated(mapFromGlobal(QPoint(0, 0))); 0302 } 0303 0304 QRectF RenderLayer::mapFromGlobal(const QRectF &rect) const 0305 { 0306 return rect.translated(mapFromGlobal(QPointF(0, 0))); 0307 } 0308 0309 QRegion RenderLayer::mapFromGlobal(const QRegion ®ion) const 0310 { 0311 if (region.isEmpty()) { 0312 return QRegion(); 0313 } 0314 return region.translated(mapFromGlobal(QPoint(0, 0))); 0315 } 0316 0317 } // namespace KWin 0318 0319 #include "moc_renderlayer.cpp"