KWin
Loading...
Searching...
No Matches
renderlayer.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#include "renderlayer.h"
8#include "outputlayer.h"
10#include "renderloop.h"
11
12namespace KWin
13{
14
16 : m_loop(loop)
17{
19}
20
22{
23 const auto sublayers = m_sublayers;
24 for (RenderLayer *sublayer : sublayers) {
25 sublayer->setSuperlayer(superlayer());
26 }
27 setSuperlayer(nullptr);
28}
29
31{
32 return m_outputLayer;
33}
34
36{
37 if (m_outputLayer == layer) {
38 return;
39 }
40 if (m_outputLayer) {
41 m_outputLayer->addRepaint(mapToGlobal(boundingRect()).toAlignedRect());
42 }
43 m_outputLayer = layer;
44 for (RenderLayer *sublayer : std::as_const(m_sublayers)) {
45 sublayer->setOutputLayer(layer);
46 }
47}
48
50{
51 return m_superlayer;
52}
53
55{
56 if (m_superlayer == layer) {
57 return;
58 }
59 if (m_superlayer) {
60 m_superlayer->removeSublayer(this);
61 }
62 m_superlayer = layer;
63 if (m_superlayer) {
64 m_superlayer->addSublayer(this);
65 }
66 updateEffectiveVisibility();
67}
68
69QList<RenderLayer *> RenderLayer::sublayers() const
70{
71 return m_sublayers;
72}
73
74void RenderLayer::addSublayer(RenderLayer *sublayer)
75{
76 m_sublayers.append(sublayer);
77 sublayer->setOutputLayer(m_outputLayer);
78 updateBoundingRect();
79}
80
81void RenderLayer::removeSublayer(RenderLayer *sublayer)
82{
83 m_sublayers.removeOne(sublayer);
84 sublayer->setOutputLayer(nullptr);
85 updateBoundingRect();
86}
87
89{
90 return m_loop;
91}
92
94{
95 return m_delegate.get();
96}
97
98void RenderLayer::setDelegate(std::unique_ptr<RenderLayerDelegate> delegate)
99{
100 m_delegate = std::move(delegate);
101 m_delegate->setLayer(this);
102}
103
104QRectF RenderLayer::rect() const
105{
106 return QRect(0, 0, m_geometry.width(), m_geometry.height());
107}
108
110{
111 return m_boundingRect;
112}
113
115{
116 return m_geometry;
117}
118
119void RenderLayer::setGeometry(const QRectF &geometry)
120{
121 if (m_geometry == geometry) {
122 return;
123 }
124 if (m_effectiveVisible && m_outputLayer) {
125 m_outputLayer->addRepaint(mapToGlobal(boundingRect()).toAlignedRect());
126 }
127
128 m_geometry = geometry;
130
131 updateBoundingRect();
132 if (m_superlayer) {
133 m_superlayer->updateBoundingRect();
134 }
135}
136
138{
139 m_repaintScheduled = true;
140 m_loop->scheduleRepaint(item);
141}
142
144{
145 if (m_repaintScheduled) {
146 return true;
147 }
148 if (!m_repaints.isEmpty()) {
149 return true;
150 }
151 return std::any_of(m_sublayers.constBegin(), m_sublayers.constEnd(), [](RenderLayer *layer) {
152 return layer->needsRepaint();
153 });
154}
155
156void RenderLayer::updateBoundingRect()
157{
158 QRectF boundingRect = rect();
159 for (const RenderLayer *sublayer : std::as_const(m_sublayers)) {
160 boundingRect |= sublayer->boundingRect().translated(sublayer->geometry().topLeft());
161 }
162
163 if (m_boundingRect != boundingRect) {
164 m_boundingRect = boundingRect;
165 if (m_superlayer) {
166 m_superlayer->updateBoundingRect();
167 }
168 }
169}
170
172{
173 addRepaint(rect().toAlignedRect());
174}
175
176void RenderLayer::addRepaint(int x, int y, int width, int height)
177{
178 addRepaint(QRegion(x, y, width, height));
179}
180
181void RenderLayer::addRepaint(const QRect &rect)
182{
183 addRepaint(QRegion(rect));
184}
185
186void RenderLayer::addRepaint(const QRegion &region)
187{
188 if (!m_effectiveVisible) {
189 return;
190 }
191 if (!region.isEmpty()) {
192 m_repaints += region;
193 m_loop->scheduleRepaint();
194 }
195}
196
198{
199 return m_repaints;
200}
201
203{
204 m_repaints = QRegion();
205 m_repaintScheduled = false;
206}
207
209{
210 return m_effectiveVisible;
211}
212
213void RenderLayer::setVisible(bool visible)
214{
215 if (m_explicitVisible != visible) {
216 m_explicitVisible = visible;
217 updateEffectiveVisibility();
218 }
219}
220
221bool RenderLayer::computeEffectiveVisibility() const
222{
223 return m_explicitVisible && (!m_superlayer || m_superlayer->isVisible());
224}
225
226void RenderLayer::updateEffectiveVisibility()
227{
228 const bool effectiveVisible = computeEffectiveVisibility();
229 if (m_effectiveVisible == effectiveVisible) {
230 return;
231 }
232
233 m_effectiveVisible = effectiveVisible;
234
235 if (effectiveVisible) {
237 } else {
238 if (m_outputLayer) {
239 m_outputLayer->addRepaint(mapToGlobal(boundingRect()).toAlignedRect());
240 m_loop->scheduleRepaint();
241 }
242 }
243
244 for (RenderLayer *sublayer : std::as_const(m_sublayers)) {
245 sublayer->updateEffectiveVisibility();
246 }
247}
248
249QPoint RenderLayer::mapToGlobal(const QPoint &point) const
250{
251 return mapToGlobal(QPointF(point)).toPoint();
252}
253
254QPointF RenderLayer::mapToGlobal(const QPointF &point) const
255{
256 QPointF result = point;
257 const RenderLayer *layer = this;
258 while (layer) {
259 result += layer->geometry().topLeft();
260 layer = layer->superlayer();
261 }
262 return result;
263}
264
265QRect RenderLayer::mapToGlobal(const QRect &rect) const
266{
267 return rect.translated(mapToGlobal(QPoint(0, 0)));
268}
269
270QRectF RenderLayer::mapToGlobal(const QRectF &rect) const
271{
272 return rect.translated(mapToGlobal(QPointF(0, 0)));
273}
274
275QRegion RenderLayer::mapToGlobal(const QRegion &region) const
276{
277 if (region.isEmpty()) {
278 return QRegion();
279 }
280 return region.translated(mapToGlobal(QPoint(0, 0)));
281}
282
283QPoint RenderLayer::mapFromGlobal(const QPoint &point) const
284{
285 return mapFromGlobal(QPointF(point)).toPoint();
286}
287
288QPointF RenderLayer::mapFromGlobal(const QPointF &point) const
289{
290 QPointF result = point;
291 const RenderLayer *layer = this;
292 while (layer) {
293 result -= layer->geometry().topLeft();
294 layer = layer->superlayer();
295 }
296 return result;
297}
298
299QRect RenderLayer::mapFromGlobal(const QRect &rect) const
300{
301 return rect.translated(mapFromGlobal(QPoint(0, 0)));
302}
303
304QRectF RenderLayer::mapFromGlobal(const QRectF &rect) const
305{
306 return rect.translated(mapFromGlobal(QPointF(0, 0)));
307}
308
309QRegion RenderLayer::mapFromGlobal(const QRegion &region) const
310{
311 if (region.isEmpty()) {
312 return QRegion();
313 }
314 return region.translated(mapFromGlobal(QPoint(0, 0)));
315}
316
317} // namespace KWin
318
319#include "moc_renderlayer.cpp"
void setOutputLayer(OutputLayer *layer)
void setVisible(bool visible)
RenderLoop * loop() const
OutputLayer * outputLayer() const
void setGeometry(const QRectF &rect)
RenderLayer(RenderLoop *loop, RenderLayer *superlayer=nullptr)
void addRepaint(const QRegion &region)
QRegion repaints() const
QList< RenderLayer * > sublayers() const
void setDelegate(std::unique_ptr< RenderLayerDelegate > delegate)
QPoint mapFromGlobal(const QPoint &point) const
QRectF boundingRect() const
QRectF rect() const
QRectF geometry() const
void setSuperlayer(RenderLayer *layer)
~RenderLayer() override
QPoint mapToGlobal(const QPoint &point) const
void scheduleRepaint(Item *item)
RenderLayerDelegate * delegate() const
RenderLayer * superlayer() const
bool needsRepaint() const
bool isVisible() const
void scheduleRepaint(Item *item=nullptr)