summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2025-10-26 13:52:09 +0000
committerVaxry <vaxry@vaxry.net>2025-10-26 13:52:09 +0000
commit05aa4e1c54da31d95663f9b4bc757e2a6ca65538 (patch)
treebfc9a4f456b2057aea7d4417f5acabb1cbc2569d
parent748d2f656ee4952090eb4ce8702ee05c82d228cb (diff)
compositor: check for monitor layout issues post rule apply
fixes #12108
-rw-r--r--src/Compositor.cpp32
-rw-r--r--src/Compositor.hpp2
-rw-r--r--src/helpers/Monitor.cpp6
3 files changed, 37 insertions, 3 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 5ea88b11..78b19c71 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -2842,6 +2842,38 @@ PHLWINDOW CCompositor::getForceFocus() {
return nullptr;
}
+void CCompositor::scheduleMonitorStateRecheck() {
+ static bool scheduled = false;
+
+ if (!scheduled) {
+ scheduled = true;
+ g_pEventLoopManager->doLater([this] {
+ arrangeMonitors();
+ checkMonitorOverlaps();
+
+ scheduled = false;
+ });
+ }
+}
+
+void CCompositor::checkMonitorOverlaps() {
+ CRegion monitorRegion;
+
+ for (const auto& m : m_monitors) {
+ if (!monitorRegion.copy().intersect(m->logicalBox()).empty()) {
+ Debug::log(ERR, "Monitor {}: detected overlap with layout", m->m_name);
+ g_pHyprNotificationOverlay->addNotification(std::format("Your monitor layout is set up incorrectly. Monitor {} overlaps with other monitor(s) in the "
+ "layout.\nPlease see the wiki (Monitors page) for more. This will cause issues.",
+ m->m_name),
+ CHyprColor{}, 15000, ICON_WARNING);
+
+ break;
+ }
+
+ monitorRegion.add(m->logicalBox());
+ }
+}
+
void CCompositor::arrangeMonitors() {
static auto* const PXWLFORCESCALEZERO = rc<Hyprlang::INT* const*>(g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling"));
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index b3e048b2..49222d05 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -156,7 +156,9 @@ class CCompositor {
void performUserChecks();
void moveWindowToWorkspaceSafe(PHLWINDOW pWindow, PHLWORKSPACE pWorkspace);
PHLWINDOW getForceFocus();
+ void scheduleMonitorStateRecheck();
void arrangeMonitors();
+ void checkMonitorOverlaps();
void enterUnsafeState();
void leaveUnsafeState();
void setPreferredScaleForSurface(SP<CWLSurfaceResource> pSurface, double scale);
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index 1ec035fd..ac9c065f 100644
--- a/src/helpers/Monitor.cpp
+++ b/src/helpers/Monitor.cpp
@@ -344,7 +344,7 @@ void CMonitor::onDisconnect(bool destroy) {
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremoved", m_name});
g_pEventManager->postEvent(SHyprIPCEvent{"monitorremovedv2", std::format("{},{},{}", m_id, m_name, m_shortDescription)});
EMIT_HOOK_EVENT("monitorRemoved", m_self.lock());
- g_pCompositor->arrangeMonitors();
+ g_pCompositor->scheduleMonitorStateRecheck();
}};
m_frameScheduler.reset();
@@ -955,7 +955,7 @@ bool CMonitor::applyMonitorRule(SMonitorRule* pMonitorRule, bool force) {
if (WAS10B != m_enabled10bit || OLDRES != m_pixelSize)
g_pHyprOpenGL->destroyMonitorResources(m_self);
- g_pCompositor->arrangeMonitors();
+ g_pCompositor->scheduleMonitorStateRecheck();
m_damage.setSize(m_transformedSize);
@@ -1181,7 +1181,7 @@ void CMonitor::setMirror(const std::string& mirrorOf) {
// remove from mvmonitors
std::erase_if(g_pCompositor->m_monitors, [&](const auto& other) { return other == m_self; });
- g_pCompositor->arrangeMonitors();
+ g_pCompositor->scheduleMonitorStateRecheck();
g_pCompositor->setActiveMonitor(g_pCompositor->m_monitors.front());