idle-inhibit: fix and cleanup visibility logic

fixes #5878
This commit is contained in:
Vaxry 2024-05-04 23:46:10 +01:00
parent a3309b51a2
commit 0b215c5f24
9 changed files with 73 additions and 27 deletions

View file

@ -90,7 +90,7 @@ PHLLS CLayerSurface::create(wlr_layer_surface_v1* pWLRLS) {
pLS->alpha.setValueAndWarp(0.f);
pLS->surface.assign(pWLRLS->surface);
pLS->surface.assign(pWLRLS->surface, pLS);
return pLS;
}

View file

@ -71,8 +71,8 @@ void CPopup::initAllSignals() {
if (!m_pWLR) {
if (!m_pWindowOwner.expired())
hyprListener_newPopup.initCallback(&m_pWindowOwner.lock()->m_uSurface.xdg->events.new_popup, ::onNewPopup, this, "CPopup Head");
else if (m_pLayerOwner)
hyprListener_newPopup.initCallback(&m_pLayerOwner->layerSurface->events.new_popup, ::onNewPopup, this, "CPopup Head");
else if (!m_pLayerOwner.expired())
hyprListener_newPopup.initCallback(&m_pLayerOwner.lock()->layerSurface->events.new_popup, ::onNewPopup, this, "CPopup Head");
else
ASSERT(false);
@ -119,8 +119,8 @@ void CPopup::onMap() {
unconstrain();
sendScale();
if (m_pLayerOwner && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
if (!m_pLayerOwner.expired() && m_pLayerOwner.lock()->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner.lock()->layer));
}
void CPopup::onUnmap() {
@ -136,8 +136,8 @@ void CPopup::onUnmap() {
g_pInputManager->simulateMouseMovement();
if (m_pLayerOwner && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
if (!m_pLayerOwner.expired() && m_pLayerOwner.lock()->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner.lock()->layer));
}
void CPopup::onCommit(bool ignoreSiblings) {
@ -178,8 +178,8 @@ void CPopup::onCommit(bool ignoreSiblings) {
m_bRequestedReposition = false;
if (m_pLayerOwner && m_pLayerOwner->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner->layer));
if (!m_pLayerOwner.expired() && m_pLayerOwner.lock()->layer < ZWLR_LAYER_SHELL_V1_LAYER_TOP)
g_pHyprOpenGL->markBlurDirtyForMonitor(g_pCompositor->getMonitorFromID(m_pLayerOwner.lock()->layer));
}
void CPopup::onReposition() {
@ -232,8 +232,8 @@ Vector2D CPopup::localToGlobal(const Vector2D& rel) {
Vector2D CPopup::t1ParentCoords() {
if (!m_pWindowOwner.expired())
return m_pWindowOwner.lock()->m_vRealPosition.value();
if (m_pLayerOwner)
return m_pLayerOwner->realPosition.value();
if (!m_pLayerOwner.expired())
return m_pLayerOwner.lock()->realPosition.value();
ASSERT(false);
return {};
@ -262,8 +262,19 @@ Vector2D CPopup::size() {
void CPopup::sendScale() {
if (!m_pWindowOwner.expired())
g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pWindowOwner.lock()->m_pWLSurface.m_fLastScale);
else if (m_pLayerOwner)
g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pLayerOwner->surface.m_fLastScale);
else if (!m_pLayerOwner.expired())
g_pCompositor->setPreferredScaleForSurface(m_sWLSurface.wlr(), m_pLayerOwner.lock()->surface.m_fLastScale);
else
UNREACHABLE();
}
bool CPopup::visible() {
if (!m_pWindowOwner.expired())
return g_pHyprRenderer->shouldRenderWindow(m_pWindowOwner.lock());
if (!m_pLayerOwner.expired())
return true;
if (m_pParent)
return m_pParent->visible();
return false;
}

View file

@ -29,12 +29,14 @@ class CPopup {
void recheckTree();
bool visible();
CWLSurface m_sWLSurface;
private:
// T1 owners, each popup has to have one of these
PHLWINDOWREF m_pWindowOwner;
PHLLS m_pLayerOwner;
PHLLSREF m_pLayerOwner;
// T2 owners
CPopup* m_pParent = nullptr;

View file

@ -227,3 +227,14 @@ void CSubsurface::initExistingSubsurfaces(wlr_surface* pSurface) {
Vector2D CSubsurface::size() {
return {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height};
}
bool CSubsurface::visible() {
if (!m_pWindowParent.expired())
return g_pHyprRenderer->shouldRenderWindow(m_pWindowParent.lock());
if (m_pPopupParent)
return m_pPopupParent->visible();
if (m_pParent)
return m_pParent->visible();
return false;
}

View file

@ -29,6 +29,8 @@ class CSubsurface {
void onMap();
void onUnmap();
bool visible();
void recheckDamageForSubsurfaces();
private:

View file

@ -197,3 +197,15 @@ void CWLSurface::onCommit() {
std::shared_ptr<CPointerConstraint> CWLSurface::constraint() {
return m_pConstraint.lock();
}
bool CWLSurface::visible() {
if (!m_pWindowOwner.expired())
return g_pHyprRenderer->shouldRenderWindow(m_pWindowOwner.lock());
if (!m_pLayerOwner.expired())
return true;
if (m_pPopupOwner)
return m_pPopupOwner->visible();
if (m_pSubsurfaceOwner)
return m_pSubsurfaceOwner->visible();
return true; // non-desktop, we don't know much.
}

View file

@ -33,6 +33,7 @@ class CWLSurface {
Vector2D getViewporterCorrectedSize() const;
CRegion logicalDamage() const;
void onCommit();
bool visible();
// getters for owners.
PHLWINDOW getWindow();

View file

@ -14,26 +14,33 @@ void CInputManager::newIdleInhibitor(std::any inhibitor) {
recheckIdleInhibitorStatus();
});
const auto PWINDOW = g_pCompositor->getWindowFromSurface(PINHIBIT->inhibitor->surface);
auto WLSurface = CWLSurface::surfaceFromWlr(PINHIBIT->inhibitor->surface);
if (!WLSurface) {
Debug::log(LOG, "Inhibitor has no HL Surface attached to it, likely meaning it's a non-desktop element. Ignoring.");
PINHIBIT->inert = true;
recheckIdleInhibitorStatus();
return;
}
PINHIBIT->surfaceDestroyListener = WLSurface->events.destroy.registerListener(
[this, PINHIBIT](std::any data) { std::erase_if(m_vIdleInhibitors, [PINHIBIT](const auto& other) { return other.get() == PINHIBIT; }); });
if (PWINDOW) {
PINHIBIT->pWindow = PWINDOW;
PINHIBIT->windowDestroyListener = PWINDOW->events.destroy.registerListener([PINHIBIT](std::any data) {
Debug::log(WARN, "Inhibitor got its window destroyed before its inhibitor resource.");
PINHIBIT->pWindow.reset();
});
} else
Debug::log(WARN, "Inhibitor is for no window?");
recheckIdleInhibitorStatus();
}
void CInputManager::recheckIdleInhibitorStatus() {
for (auto& ii : m_vIdleInhibitors) {
if (ii->pWindow.expired())
if (ii->inert)
continue;
if (g_pHyprRenderer->shouldRenderWindow(ii->pWindow.lock())) {
auto WLSurface = CWLSurface::surfaceFromWlr(ii->inhibitor->surface);
if (!WLSurface)
continue;
if (WLSurface->visible()) {
PROTO::idle->setInhibit(true);
return;
}

View file

@ -242,8 +242,8 @@ class CInputManager {
// idle inhibitors
struct SIdleInhibitor {
std::shared_ptr<CIdleInhibitor> inhibitor;
PHLWINDOWREF pWindow;
CHyprSignalListener windowDestroyListener;
bool inert = false;
CHyprSignalListener surfaceDestroyListener;
};
std::vector<std::unique_ptr<SIdleInhibitor>> m_vIdleInhibitors;