KWin
Loading...
Searching...
No Matches
item.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 "scene/item.h"
8#include "core/renderlayer.h"
9#include "scene/scene.h"
10#include "utils/common.h"
11
12namespace KWin
13{
14
15Item::Item(Scene *scene, Item *parent)
16 : m_scene(scene)
17{
18 setParentItem(parent);
19 connect(m_scene, &Scene::delegateRemoved, this, &Item::removeRepaints);
20}
21
23{
24 setParentItem(nullptr);
25 for (const auto &dirty : std::as_const(m_repaints)) {
26 if (!dirty.isEmpty()) {
27 m_scene->addRepaint(dirty);
28 }
29 }
30}
31
33{
34 return m_scene;
35}
36
37qreal Item::opacity() const
38{
39 return m_opacity;
40}
41
42void Item::setOpacity(qreal opacity)
43{
44 if (m_opacity != opacity) {
45 m_opacity = opacity;
47 }
48}
49
50int Item::z() const
51{
52 return m_z;
53}
54
55void Item::setZ(int z)
56{
57 if (m_z == z) {
58 return;
59 }
60 m_z = z;
61 if (m_parentItem) {
62 m_parentItem->markSortedChildItemsDirty();
63 }
65}
66
68{
69 return m_parentItem;
70}
71
73{
74 if (m_parentItem == item) {
75 return;
76 }
77 if (m_parentItem) {
78 m_parentItem->removeChild(this);
79 }
80 m_parentItem = item;
81 if (m_parentItem) {
82 Q_ASSERT(m_parentItem->m_scene == m_scene);
83 m_parentItem->addChild(this);
84 }
85 updateEffectiveVisibility();
86}
87
88void Item::addChild(Item *item)
89{
90 Q_ASSERT(!m_childItems.contains(item));
91
92 m_childItems.append(item);
93 markSortedChildItemsDirty();
94
95 updateBoundingRect();
96 scheduleRepaint(item->boundingRect().translated(item->position()));
97
98 Q_EMIT childAdded(item);
99}
100
101void Item::removeChild(Item *item)
102{
103 Q_ASSERT(m_childItems.contains(item));
104 scheduleRepaint(item->boundingRect().translated(item->position()));
105
106 m_childItems.removeOne(item);
107 markSortedChildItemsDirty();
108
109 updateBoundingRect();
110}
111
112QList<Item *> Item::childItems() const
113{
114 return m_childItems;
115}
116
117QPointF Item::position() const
118{
119 return m_position;
120}
121
122void Item::setPosition(const QPointF &point)
123{
124 if (m_position != point) {
126 m_position = point;
127 if (m_parentItem) {
128 m_parentItem->updateBoundingRect();
129 }
131 Q_EMIT positionChanged();
132 }
133}
134
135QSizeF Item::size() const
136{
137 return m_size;
138}
139
140void Item::setSize(const QSizeF &size)
141{
142 if (m_size != size) {
144 m_size = size;
145 updateBoundingRect();
147 discardQuads();
148 Q_EMIT sizeChanged();
149 }
150}
151
152QRectF Item::rect() const
153{
154 return QRectF(QPoint(0, 0), size());
155}
156
157QRectF Item::boundingRect() const
158{
159 return m_boundingRect;
160}
161
162void Item::updateBoundingRect()
163{
164 QRectF boundingRect = rect();
165 for (Item *item : std::as_const(m_childItems)) {
166 boundingRect |= item->boundingRect().translated(item->position());
167 }
168 if (m_boundingRect != boundingRect) {
169 m_boundingRect = boundingRect;
170 Q_EMIT boundingRectChanged();
171 if (m_parentItem) {
172 m_parentItem->updateBoundingRect();
173 }
174 }
175}
176
177QList<QRectF> Item::shape() const
178{
179 return QList<QRectF>();
180}
181
182QRegion Item::opaque() const
183{
184 return QRegion();
185}
186
187QPointF Item::rootPosition() const
188{
189 QPointF ret = position();
190
191 Item *parent = parentItem();
192 while (parent) {
193 ret += parent->position();
194 parent = parent->parentItem();
195 }
196
197 return ret;
198}
199
200QMatrix4x4 Item::transform() const
201{
202 return m_transform;
203}
204
205void Item::setTransform(const QMatrix4x4 &transform)
206{
207 m_transform = transform;
208}
209
210QRegion Item::mapToGlobal(const QRegion &region) const
211{
212 if (region.isEmpty()) {
213 return QRegion();
214 }
215 return region.translated(rootPosition().toPoint());
216}
217
218QRectF Item::mapToGlobal(const QRectF &rect) const
219{
220 if (rect.isEmpty()) {
221 return QRect();
222 }
223 return rect.translated(rootPosition());
224}
225
226QRectF Item::mapFromGlobal(const QRectF &rect) const
227{
228 if (rect.isEmpty()) {
229 return QRect();
230 }
231 return rect.translated(-rootPosition());
232}
233
235{
236 if (Q_UNLIKELY(!sibling)) {
237 qCDebug(KWIN_CORE) << Q_FUNC_INFO << "requires a valid sibling";
238 return;
239 }
240 if (Q_UNLIKELY(!sibling->parentItem() || sibling->parentItem() != parentItem())) {
241 qCDebug(KWIN_CORE) << Q_FUNC_INFO << "requires items to be siblings";
242 return;
243 }
244 if (Q_UNLIKELY(sibling == this)) {
245 return;
246 }
247
248 const int selfIndex = m_parentItem->m_childItems.indexOf(this);
249 const int siblingIndex = m_parentItem->m_childItems.indexOf(sibling);
250
251 if (selfIndex == siblingIndex - 1) {
252 return;
253 }
254
255 m_parentItem->m_childItems.move(selfIndex, selfIndex > siblingIndex ? siblingIndex : siblingIndex - 1);
256 markSortedChildItemsDirty();
257
259 sibling->scheduleRepaint(sibling->boundingRect());
260}
261
262void Item::stackAfter(Item *sibling)
263{
264 if (Q_UNLIKELY(!sibling)) {
265 qCDebug(KWIN_CORE) << Q_FUNC_INFO << "requires a valid sibling";
266 return;
267 }
268 if (Q_UNLIKELY(!sibling->parentItem() || sibling->parentItem() != parentItem())) {
269 qCDebug(KWIN_CORE) << Q_FUNC_INFO << "requires items to be siblings";
270 return;
271 }
272 if (Q_UNLIKELY(sibling == this)) {
273 return;
274 }
275
276 const int selfIndex = m_parentItem->m_childItems.indexOf(this);
277 const int siblingIndex = m_parentItem->m_childItems.indexOf(sibling);
278
279 if (selfIndex == siblingIndex + 1) {
280 return;
281 }
282
283 m_parentItem->m_childItems.move(selfIndex, selfIndex > siblingIndex ? siblingIndex + 1 : siblingIndex);
284 markSortedChildItemsDirty();
285
287 sibling->scheduleRepaint(sibling->boundingRect());
288}
289
290void Item::scheduleRepaint(const QRegion &region)
291{
292 if (isVisible()) {
293 scheduleRepaintInternal(region);
294 }
295}
296
297void Item::scheduleRepaint(SceneDelegate *delegate, const QRegion &region)
298{
299 if (isVisible()) {
300 scheduleRepaintInternal(delegate, region);
301 }
302}
303
304void Item::scheduleRepaintInternal(const QRegion &region)
305{
306 const QRegion globalRegion = mapToGlobal(region);
307 const QList<SceneDelegate *> delegates = m_scene->delegates();
308 for (SceneDelegate *delegate : delegates) {
309 const QRegion dirtyRegion = globalRegion & delegate->viewport();
310 if (!dirtyRegion.isEmpty()) {
311 m_repaints[delegate] += dirtyRegion;
312 delegate->layer()->scheduleRepaint(this);
313 }
314 }
315}
316
317void Item::scheduleRepaintInternal(SceneDelegate *delegate, const QRegion &region)
318{
319 const QRegion globalRegion = mapToGlobal(region);
320 const QRegion dirtyRegion = globalRegion & delegate->viewport();
321 if (!dirtyRegion.isEmpty()) {
322 m_repaints[delegate] += dirtyRegion;
323 delegate->layer()->scheduleRepaint(this);
324 }
325}
326
328{
329 if (!isVisible()) {
330 return;
331 }
332 const QRect geometry = mapToGlobal(rect()).toRect();
333 const QList<SceneDelegate *> delegates = m_scene->delegates();
334 for (SceneDelegate *delegate : delegates) {
335 if (delegate->viewport().intersects(geometry)) {
336 delegate->layer()->scheduleRepaint(this);
337 }
338 }
339}
340
342{
343}
344
346{
347 return WindowQuadList();
348}
349
351{
352 m_quads.reset();
353}
354
356{
357 if (!m_quads.has_value()) {
358 m_quads = buildQuads();
359 }
360 return m_quads.value();
361}
362
363QRegion Item::repaints(SceneDelegate *delegate) const
364{
365 return m_repaints.value(delegate);
366}
367
369{
370 m_repaints.insert(delegate, QRegion());
371}
372
373void Item::removeRepaints(SceneDelegate *delegate)
374{
375 m_repaints.remove(delegate);
376}
377
379{
380 return m_explicitVisible;
381}
382
383bool Item::isVisible() const
384{
385 return m_effectiveVisible;
386}
387
388void Item::setVisible(bool visible)
389{
390 if (m_explicitVisible != visible) {
391 m_explicitVisible = visible;
392 updateEffectiveVisibility();
393 }
394}
395
396void Item::scheduleRepaint(const QRectF &region)
397{
398 scheduleRepaint(QRegion(region.toAlignedRect()));
399}
400
401bool Item::computeEffectiveVisibility() const
402{
403 return m_explicitVisible && (!m_parentItem || m_parentItem->isVisible());
404}
405
406void Item::updateEffectiveVisibility()
407{
408 const bool effectiveVisible = computeEffectiveVisibility();
409 if (m_effectiveVisible == effectiveVisible) {
410 return;
411 }
412
413 m_effectiveVisible = effectiveVisible;
414 if (!m_effectiveVisible) {
415 m_scene->addRepaint(mapToGlobal(boundingRect()).toAlignedRect());
416 } else {
417 scheduleRepaintInternal(boundingRect().toAlignedRect());
418 }
419
420 for (Item *childItem : std::as_const(m_childItems)) {
421 childItem->updateEffectiveVisibility();
422 }
423}
424
425static bool compareZ(const Item *a, const Item *b)
426{
427 return a->z() < b->z();
428}
429
430QList<Item *> Item::sortedChildItems() const
431{
432 if (!m_sortedChildItems.has_value()) {
433 QList<Item *> items = m_childItems;
434 std::stable_sort(items.begin(), items.end(), compareZ);
435 m_sortedChildItems = items;
436 }
437 return m_sortedChildItems.value();
438}
439
440void Item::markSortedChildItemsDirty()
441{
442 m_sortedChildItems.reset();
443}
444
446{
447 return m_colorDescription;
448}
449
451{
452 m_colorDescription = description;
453}
454
456{
457 return m_presentationHint;
458}
459
461{
462 m_presentationHint = hint;
463}
464
465} // namespace KWin
466
467#include "moc_item.cpp"
void sizeChanged()
void setColorDescription(const ColorDescription &description)
Definition item.cpp:450
virtual void preprocess()
Definition item.cpp:341
QPointF position() const
Definition item.cpp:117
qreal opacity() const
Definition item.cpp:37
QList< Item * > sortedChildItems() const
Definition item.cpp:430
void childAdded(Item *item)
void positionChanged()
virtual QRegion opaque() const
Definition item.cpp:182
Scene * scene() const
Definition item.cpp:32
void setParentItem(Item *parent)
Definition item.cpp:72
PresentationModeHint presentationHint() const
Definition item.cpp:455
QRectF boundingRect() const
Definition item.cpp:157
bool isVisible() const
Definition item.cpp:383
void setVisible(bool visible)
Definition item.cpp:388
bool explicitVisible() const
Definition item.cpp:378
void scheduleFrame()
Definition item.cpp:327
QRegion mapToGlobal(const QRegion &region) const
Definition item.cpp:210
Item(Scene *scene, Item *parent=nullptr)
Definition item.cpp:15
~Item() override
Definition item.cpp:22
QRectF mapFromGlobal(const QRectF &rect) const
Definition item.cpp:226
WindowQuadList quads() const
Definition item.cpp:355
virtual WindowQuadList buildQuads() const
Definition item.cpp:345
QRectF rect() const
Definition item.cpp:152
Item * parentItem() const
Definition item.cpp:67
void stackAfter(Item *sibling)
Definition item.cpp:262
void setPresentationHint(PresentationModeHint hint)
Definition item.cpp:460
void resetRepaints(SceneDelegate *delegate)
Definition item.cpp:368
QRegion repaints(SceneDelegate *delegate) const
Definition item.cpp:363
QPointF rootPosition() const
Definition item.cpp:187
void setSize(const QSizeF &size)
Definition item.cpp:140
int z() const
Definition item.cpp:50
void discardQuads()
Definition item.cpp:350
const ColorDescription & colorDescription() const
Definition item.cpp:445
QList< Item * > childItems() const
Definition item.cpp:112
void setZ(int z)
Definition item.cpp:55
void setOpacity(qreal opacity)
Definition item.cpp:42
QSizeF size() const
Definition item.cpp:135
void scheduleRepaint(const QRectF &region)
Definition item.cpp:396
void stackBefore(Item *sibling)
Definition item.cpp:234
void setPosition(const QPointF &point)
Definition item.cpp:122
void setTransform(const QMatrix4x4 &transform)
Definition item.cpp:205
virtual QList< QRectF > shape() const
Definition item.cpp:177
QMatrix4x4 transform() const
Definition item.cpp:200
void boundingRectChanged()
QList< SceneDelegate * > delegates() const
Definition scene.cpp:121
void addRepaint(const QRegion &region)
Definition scene.cpp:91
void delegateRemoved(SceneDelegate *delegate)
PresentationModeHint
Definition globals.h:299