3
0
mirror of https://github.com/hyprwm/Hyprland.git synced 2025-10-29 11:22:47 +00:00

compositor: check for monitor layout issues post rule apply

fixes #12108
This commit is contained in:
Vaxry 2025-10-26 13:52:09 +00:00
parent 748d2f656e
commit 05aa4e1c54
No known key found for this signature in database
GPG Key ID: 665806380871D640
3 changed files with 37 additions and 3 deletions

View File

@ -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"));

View File

@ -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);

View File

@ -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());