diff options
| author | Vaxry <vaxry@vaxry.net> | 2025-10-26 13:52:09 +0000 |
|---|---|---|
| committer | Vaxry <vaxry@vaxry.net> | 2025-10-26 13:52:09 +0000 |
| commit | 05aa4e1c54da31d95663f9b4bc757e2a6ca65538 (patch) | |
| tree | bfc9a4f456b2057aea7d4417f5acabb1cbc2569d | |
| parent | 748d2f656ee4952090eb4ce8702ee05c82d228cb (diff) | |
compositor: check for monitor layout issues post rule apply
fixes #12108
| -rw-r--r-- | src/Compositor.cpp | 32 | ||||
| -rw-r--r-- | src/Compositor.hpp | 2 | ||||
| -rw-r--r-- | src/helpers/Monitor.cpp | 6 |
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()); |
