From eea0a6a70412574baabea2b83d2c52003c98d46f Mon Sep 17 00:00:00 2001
From: Alessio Molinari <alessio.molinari@strg.at>
Date: Thu, 23 May 2024 21:15:31 +0200
Subject: [PATCH] internal: Replace monitor rule when disabling head. (#6136)

Closes #5978
---
 src/config/ConfigManager.cpp       | 12 ++++++++++++
 src/config/ConfigManager.hpp       |  1 +
 src/protocols/OutputManagement.cpp |  9 ++++++++-
 3 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp
index 77aa2fb36..fd70da771 100644
--- a/src/config/ConfigManager.cpp
+++ b/src/config/ConfigManager.cpp
@@ -1264,6 +1264,18 @@ void CConfigManager::appendMonitorRule(const SMonitorRule& r) {
     m_dMonitorRules.emplace_back(r);
 }
 
+bool CConfigManager::replaceMonitorRule(const SMonitorRule& newrule) {
+    // Looks for an existing monitor rule (compared by name).
+    // If the rule exists, it is replaced with the input rule.
+    for (auto& r : m_dMonitorRules) {
+        if (r.name == newrule.name) {
+            r = newrule;
+            return true;
+        }
+    }
+    return false;
+}
+
 void CConfigManager::performMonitorReload() {
 
     bool overAgain = false;
diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp
index 7fc132c6f..45b100eef 100644
--- a/src/config/ConfigManager.hpp
+++ b/src/config/ConfigManager.hpp
@@ -128,6 +128,7 @@ class CConfigManager {
 
     void                      performMonitorReload();
     void                      appendMonitorRule(const SMonitorRule&);
+    bool                      replaceMonitorRule(const SMonitorRule&);
     bool                      m_bWantsMonitorReload = false;
     bool                      m_bForceReload        = false;
     bool                      m_bNoMonitorReload    = false;
diff --git a/src/protocols/OutputManagement.cpp b/src/protocols/OutputManagement.cpp
index e77797262..68c501936 100644
--- a/src/protocols/OutputManagement.cpp
+++ b/src/protocols/OutputManagement.cpp
@@ -106,6 +106,9 @@ COutputHead::COutputHead(SP<CZwlrOutputHeadV1> resource_, CMonitor* pMonitor_) :
         }
 
         pMonitor = nullptr;
+        for (auto& m : PROTO::outputManagement->m_vManagers) {
+            m->sendDone();
+        }
     });
 
     listeners.monitorModeChange = pMonitor->events.modeChanged.registerListener([this](std::any d) { updateMode(); });
@@ -305,6 +308,8 @@ COutputConfiguration::COutputConfiguration(SP<CZwlrOutputConfigurationV1> resour
         LOGM(LOG, "disableHead on {}", PMONITOR->szName);
 
         PMONITOR->activeMonitorRule.disabled = true;
+        if (!g_pConfigManager->replaceMonitorRule(PMONITOR->activeMonitorRule))
+            g_pConfigManager->appendMonitorRule(PMONITOR->activeMonitorRule);
         g_pHyprRenderer->applyMonitorRule(PMONITOR, &PMONITOR->activeMonitorRule, false);
     });
 
@@ -356,6 +361,7 @@ bool COutputConfiguration::applyTestConfiguration(bool test) {
 
         SMonitorRule newRule = PMONITOR->activeMonitorRule;
         newRule.name         = PMONITOR->szName;
+        newRule.disabled     = false;
 
         if (head->committedProperties & COutputConfigurationHead::eCommittedProperties::OUTPUT_HEAD_COMMITTED_MODE) {
             newRule.resolution  = {head->state.mode->getMode()->width, head->state.mode->getMode()->height};
@@ -380,7 +386,8 @@ bool COutputConfiguration::applyTestConfiguration(bool test) {
         // reset properties for next set.
         head->committedProperties = 0;
 
-        g_pConfigManager->appendMonitorRule(newRule);
+        if (!g_pConfigManager->replaceMonitorRule(newRule))
+            g_pConfigManager->appendMonitorRule(newRule);
         g_pConfigManager->m_bWantsMonitorReload = true;
     }