scene: Introduce z-property
This allows placing child items below their parent item by setting negative Z values.
This commit is contained in:
parent
2a1f9f1646
commit
4ebe5d32b4
4 changed files with 82 additions and 6 deletions
44
src/item.cpp
44
src/item.cpp
|
@ -39,6 +39,23 @@ Item::~Item()
|
|||
}
|
||||
}
|
||||
|
||||
int Item::z() const
|
||||
{
|
||||
return m_z;
|
||||
}
|
||||
|
||||
void Item::setZ(int z)
|
||||
{
|
||||
if (m_z == z) {
|
||||
return;
|
||||
}
|
||||
m_z = z;
|
||||
if (m_parentItem) {
|
||||
m_parentItem->markSortedChildItemsDirty();
|
||||
}
|
||||
scheduleRepaint(boundingRect());
|
||||
}
|
||||
|
||||
Item *Item::parentItem() const
|
||||
{
|
||||
return m_parentItem;
|
||||
|
@ -64,6 +81,8 @@ void Item::addChild(Item *item)
|
|||
Q_ASSERT(!m_childItems.contains(item));
|
||||
|
||||
m_childItems.append(item);
|
||||
markSortedChildItemsDirty();
|
||||
|
||||
updateBoundingRect();
|
||||
scheduleRepaint(item->boundingRect().translated(item->position()));
|
||||
}
|
||||
|
@ -74,6 +93,7 @@ void Item::removeChild(Item *item)
|
|||
scheduleRepaint(item->boundingRect().translated(item->position()));
|
||||
|
||||
m_childItems.removeOne(item);
|
||||
markSortedChildItemsDirty();
|
||||
|
||||
updateBoundingRect();
|
||||
}
|
||||
|
@ -191,6 +211,7 @@ void Item::stackBefore(Item *sibling)
|
|||
}
|
||||
|
||||
m_parentItem->m_childItems.move(selfIndex, selfIndex > siblingIndex ? siblingIndex : siblingIndex - 1);
|
||||
markSortedChildItemsDirty();
|
||||
|
||||
scheduleRepaint(boundingRect());
|
||||
sibling->scheduleRepaint(sibling->boundingRect());
|
||||
|
@ -218,6 +239,7 @@ void Item::stackAfter(Item *sibling)
|
|||
}
|
||||
|
||||
m_parentItem->m_childItems.move(selfIndex, selfIndex > siblingIndex ? siblingIndex + 1 : siblingIndex);
|
||||
markSortedChildItemsDirty();
|
||||
|
||||
scheduleRepaint(boundingRect());
|
||||
sibling->scheduleRepaint(sibling->boundingRect());
|
||||
|
@ -237,6 +259,8 @@ void Item::stackChildren(const QList<Item *> &children)
|
|||
#endif
|
||||
|
||||
m_childItems = children;
|
||||
discardQuads();
|
||||
markSortedChildItemsDirty();
|
||||
}
|
||||
|
||||
void Item::scheduleRepaint(const QRegion ®ion)
|
||||
|
@ -369,4 +393,24 @@ void Item::updateEffectiveVisibility()
|
|||
}
|
||||
}
|
||||
|
||||
static bool compareZ(const Item *a, const Item *b)
|
||||
{
|
||||
return a->z() < b->z();
|
||||
}
|
||||
|
||||
QList<Item *> Item::sortedChildItems() const
|
||||
{
|
||||
if (!m_sortedChildItems.has_value()) {
|
||||
QList<Item *> items = m_childItems;
|
||||
std::stable_sort(items.begin(), items.end(), compareZ);
|
||||
m_sortedChildItems = items;
|
||||
}
|
||||
return m_sortedChildItems.value();
|
||||
}
|
||||
|
||||
void Item::markSortedChildItemsDirty()
|
||||
{
|
||||
m_sortedChildItems.reset();
|
||||
}
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -30,6 +30,9 @@ public:
|
|||
QSize size() const;
|
||||
void setSize(const QSize &size);
|
||||
|
||||
int z() const;
|
||||
void setZ(int z);
|
||||
|
||||
/**
|
||||
* Returns the enclosing rectangle of the item. The rect equals QRect(0, 0, width(), height()).
|
||||
*/
|
||||
|
@ -46,6 +49,7 @@ public:
|
|||
Item *parentItem() const;
|
||||
void setParentItem(Item *parent);
|
||||
QList<Item *> childItems() const;
|
||||
QList<Item *> sortedChildItems() const;
|
||||
|
||||
Scene::Window *window() const;
|
||||
QPoint rootPosition() const;
|
||||
|
@ -112,6 +116,7 @@ private:
|
|||
void updateBoundingRect();
|
||||
void scheduleRepaintInternal(const QRegion ®ion);
|
||||
void reallocRepaints();
|
||||
void markSortedChildItemsDirty();
|
||||
|
||||
bool computeEffectiveVisibility() const;
|
||||
void updateEffectiveVisibility();
|
||||
|
@ -122,10 +127,12 @@ private:
|
|||
QRect m_boundingRect;
|
||||
QPoint m_position;
|
||||
QSize m_size = QSize(0, 0);
|
||||
int m_z = 0;
|
||||
bool m_visible = true;
|
||||
bool m_effectiveVisible = true;
|
||||
QVector<QRegion> m_repaints;
|
||||
mutable std::optional<WindowQuadList> m_quads;
|
||||
mutable std::optional<QList<Item *>> m_sortedChildItems;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
|
|
@ -940,8 +940,18 @@ static WindowQuadList clipQuads(const Item *item, const OpenGLWindow::RenderCont
|
|||
|
||||
void OpenGLWindow::createRenderNode(Item *item, RenderContext *context)
|
||||
{
|
||||
item->preprocess();
|
||||
const QList<Item *> sortedChildItems = item->sortedChildItems();
|
||||
|
||||
for (Item *childItem : sortedChildItems) {
|
||||
if (childItem->z() >= 0) {
|
||||
break;
|
||||
}
|
||||
if (childItem->isVisible()) {
|
||||
createRenderNode(childItem, context);
|
||||
}
|
||||
}
|
||||
|
||||
item->preprocess();
|
||||
if (auto shadowItem = qobject_cast<ShadowItem *>(item)) {
|
||||
WindowQuadList quads = clipQuads(item, context);
|
||||
if (!quads.isEmpty()) {
|
||||
|
@ -985,8 +995,10 @@ void OpenGLWindow::createRenderNode(Item *item, RenderContext *context)
|
|||
}
|
||||
}
|
||||
|
||||
const QList<Item *> childItems = item->childItems();
|
||||
for (Item *childItem : childItems) {
|
||||
for (Item *childItem : sortedChildItems) {
|
||||
if (childItem->z() < 0) {
|
||||
continue;
|
||||
}
|
||||
if (childItem->isVisible()) {
|
||||
createRenderNode(childItem, context);
|
||||
}
|
||||
|
|
|
@ -245,18 +245,31 @@ void SceneQPainter::Window::performPaint(int mask, const QRegion &_region, const
|
|||
|
||||
void SceneQPainter::Window::renderItem(QPainter *painter, Item *item) const
|
||||
{
|
||||
item->preprocess();
|
||||
const QList<Item *> sortedChildItems = item->sortedChildItems();
|
||||
|
||||
painter->save();
|
||||
painter->translate(item->position());
|
||||
|
||||
for (Item *childItem : sortedChildItems) {
|
||||
if (childItem->z() >= 0) {
|
||||
break;
|
||||
}
|
||||
if (childItem->isVisible()) {
|
||||
renderItem(painter, childItem);
|
||||
}
|
||||
}
|
||||
|
||||
item->preprocess();
|
||||
if (auto surfaceItem = qobject_cast<SurfaceItem *>(item)) {
|
||||
renderSurfaceItem(painter, surfaceItem);
|
||||
} else if (auto decorationItem = qobject_cast<DecorationItem *>(item)) {
|
||||
renderDecorationItem(painter, decorationItem);
|
||||
}
|
||||
|
||||
const QList<Item *> childItems = item->childItems();
|
||||
for (Item *childItem : childItems) {
|
||||
for (Item *childItem : sortedChildItems) {
|
||||
if (childItem->z() < 0) {
|
||||
continue;
|
||||
}
|
||||
if (childItem->isVisible()) {
|
||||
renderItem(painter, childItem);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue