From d109e7d69bb34fb9d5b32005ea2589ca53a406ca Mon Sep 17 00:00:00 2001 From: Vlad Zahorodnii Date: Wed, 26 May 2021 12:27:27 +0300 Subject: [PATCH] Introduce Item visible property This property can be used to control the visibility of an item and its child subtree. --- src/item.cpp | 44 +++++++++++++++++++++++++++++++++++++ src/item.h | 9 ++++++++ src/surfaceitem_wayland.cpp | 4 ---- src/surfaceitem_x11.cpp | 4 ---- src/windowitem.cpp | 7 ++++++ src/windowitem.h | 1 + 6 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/item.cpp b/src/item.cpp index 013c7f8579..a27f3c13f0 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -126,6 +126,7 @@ void Item::setParentItem(Item *item) if (m_parentItem) { m_parentItem->addChild(this); } + updateEffectiveVisibility(); } void Item::addChild(Item *item) @@ -343,6 +344,13 @@ void Item::stackChildren(const QList &children) } void Item::scheduleRepaint(const QRegion ®ion) +{ + if (isVisible()) { + scheduleRepaintInternal(region); + } +} + +void Item::scheduleRepaintInternal(const QRegion ®ion) { const QRegion globalRegion = mapToGlobal(region); if (kwinApp()->platform()->isPerScreenRenderingEnabled()) { @@ -366,6 +374,9 @@ void Item::scheduleRepaint(const QRegion ®ion) void Item::scheduleFrame() { + if (!isVisible()) { + return; + } if (kwinApp()->platform()->isPerScreenRenderingEnabled()) { const QRect geometry = mapToGlobal(rect()); const QVector outputs = kwinApp()->platform()->enabledOutputs(); @@ -416,4 +427,37 @@ void Item::reallocRepaints() m_repaints.fill(infiniteRegion()); } +bool Item::isVisible() const +{ + return m_effectiveVisible; +} + +void Item::setVisible(bool visible) +{ + if (m_visible != visible) { + m_visible = visible; + updateEffectiveVisibility(); + } +} + +bool Item::computeEffectiveVisibility() const +{ + return m_visible && (!m_parentItem || m_parentItem->isVisible()); +} + +void Item::updateEffectiveVisibility() +{ + const bool effectiveVisible = computeEffectiveVisibility(); + if (m_effectiveVisible == effectiveVisible) { + return; + } + + m_effectiveVisible = effectiveVisible; + scheduleRepaintInternal(boundingRect()); + + for (Item *childItem : qAsConst(m_childItems)) { + childItem->updateEffectiveVisibility(); + } +} + } // namespace KWin diff --git a/src/item.h b/src/item.h index 74db62f0e4..3e50a68f61 100644 --- a/src/item.h +++ b/src/item.h @@ -91,6 +91,9 @@ public: */ void stackChildren(const QList &children); + bool isVisible() const; + void setVisible(bool visible); + void scheduleRepaint(const QRegion ®ion); void scheduleFrame(); QRegion repaints(int screen) const; @@ -128,8 +131,12 @@ private: void addChild(Item *item); void removeChild(Item *item); void updateBoundingRect(); + void scheduleRepaintInternal(const QRegion ®ion); void reallocRepaints(); + bool computeEffectiveVisibility() const; + void updateEffectiveVisibility(); + Scene::Window *m_window; QPointer m_parentItem; QList m_childItems; @@ -138,6 +145,8 @@ private: int m_y = 0; int m_width = 0; int m_height = 0; + bool m_visible = true; + bool m_effectiveVisible = true; QVector m_repaints; friend class Scene::Window; diff --git a/src/surfaceitem_wayland.cpp b/src/surfaceitem_wayland.cpp index 9689d85a4f..d5ea9346a9 100644 --- a/src/surfaceitem_wayland.cpp +++ b/src/surfaceitem_wayland.cpp @@ -206,10 +206,6 @@ SurfaceItemXwayland::SurfaceItemXwayland(Scene::Window *window, Item *parent) QRegion SurfaceItemXwayland::shape() const { const Toplevel *toplevel = window()->window(); - if (window()->isShaded()) { - return QRegion(); - } - const QRect clipRect = toplevel->clientGeometry().translated(-toplevel->bufferGeometry().topLeft()); const QRegion shape = toplevel->shapeRegion(); diff --git a/src/surfaceitem_x11.cpp b/src/surfaceitem_x11.cpp index 280aa6b944..bce26234d5 100644 --- a/src/surfaceitem_x11.cpp +++ b/src/surfaceitem_x11.cpp @@ -122,10 +122,6 @@ QPointF SurfaceItemX11::mapToBuffer(const QPointF &point) const QRegion SurfaceItemX11::shape() const { const Toplevel *toplevel = window()->window(); - if (window()->isShaded()) { - return QRegion(); - } - const QRect clipRect = toplevel->clientGeometry().translated(-toplevel->bufferGeometry().topLeft()); const QRegion shape = toplevel->shapeRegion(); diff --git a/src/windowitem.cpp b/src/windowitem.cpp index 8db229ff60..1bd86f2a80 100644 --- a/src/windowitem.cpp +++ b/src/windowitem.cpp @@ -46,10 +46,12 @@ void WindowItem::updateSurfaceItem(SurfaceItem *surfaceItem) m_surfaceItem.reset(surfaceItem); + connect(toplevel, &Toplevel::shadeChanged, this, &WindowItem::updateSurfaceVisibility); connect(toplevel, &Toplevel::bufferGeometryChanged, this, &WindowItem::updateSurfacePosition); connect(toplevel, &Toplevel::frameGeometryChanged, this, &WindowItem::updateSurfacePosition); updateSurfacePosition(); + updateSurfaceVisibility(); } void WindowItem::updateSurfacePosition() @@ -62,6 +64,11 @@ void WindowItem::updateSurfacePosition() m_surfaceItem->setPosition(bufferGeometry.topLeft() - frameGeometry.topLeft()); } +void WindowItem::updateSurfaceVisibility() +{ + m_surfaceItem->setVisible(!window()->window()->isShade()); +} + void WindowItem::setShadow(Shadow *shadow) { if (shadow) { diff --git a/src/windowitem.h b/src/windowitem.h index 5e98f204f0..3d9a506c7e 100644 --- a/src/windowitem.h +++ b/src/windowitem.h @@ -41,6 +41,7 @@ protected: private Q_SLOTS: void updateDecorationItem(); void updateSurfacePosition(); + void updateSurfaceVisibility(); private: QScopedPointer m_surfaceItem;