From 46d66f4bcc95d9fb7fede18ad5c2c043796b9071 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 24 Sep 2023 18:04:38 +0100 Subject: internal: Further unsafe state improvements (#3404) Instead of allowing Hyprland to sit in a state where there are no monitors, which various parts of the code don't like, we create a fake headless output on all monitor disconnect, and then remove it when a monitor appears --- src/events/Monitors.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src/events/Monitors.cpp') diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 88ba612d..947f9e7f 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -87,13 +87,21 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled) g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR; - // ready to process cuz we have a monitor - if (PNEWMONITOR->m_bEnabled) { + // wlroots will instantly call this handler before we get a return to the wlr_output* in CCompositor::enterUnsafeState + const bool PROBABLYFALLBACK = (g_pCompositor->m_bUnsafeState && !g_pCompositor->m_pUnsafeOutput) || OUTPUT == g_pCompositor->m_pUnsafeOutput; + // ready to process if we have a real monitor + if (PNEWMONITOR->m_bEnabled && !PROBABLYFALLBACK) { + // leave unsafe state if (g_pCompositor->m_bUnsafeState) { // recover workspaces + std::vector wsp; for (auto& ws : g_pCompositor->m_vWorkspaces) { - g_pCompositor->moveWorkspaceToMonitor(ws.get(), PNEWMONITOR); + wsp.push_back(ws.get()); + } + for (auto& ws : wsp) { + // because this can realloc the vec + g_pCompositor->moveWorkspaceToMonitor(ws, PNEWMONITOR); } g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR; @@ -104,7 +112,6 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { } g_pCompositor->m_bReadyToProcess = true; - g_pCompositor->m_bUnsafeState = false; } g_pConfigManager->m_bWantsMonitorReload = true; @@ -131,8 +138,10 @@ void Events::listener_monitorFrame(void* owner, void* data) { if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { Debug::log(WARN, "Attempted to render frame on inactive session!"); - if (g_pCompositor->m_bUnsafeState) - g_pConfigManager->performMonitorReload(); + if (g_pCompositor->m_bUnsafeState && PMONITOR->output != g_pCompositor->m_pUnsafeOutput) { + // restore from unsafe state + g_pCompositor->leaveUnsafeState(); + } return; // cannot draw on session inactive (different tty) } @@ -196,6 +205,9 @@ void Events::listener_monitorDestroy(void* owner, void* data) { pMonitor->output = nullptr; pMonitor->m_bRenderingInitPassed = false; + if (g_pCompositor->m_pUnsafeOutput == OUTPUT) + g_pCompositor->m_pUnsafeOutput = nullptr; + Debug::log(LOG, "Removing monitor {} from realMonitors", pMonitor->szName); std::erase_if(g_pCompositor->m_vRealMonitors, [&](std::shared_ptr& el) { return el.get() == pMonitor; }); -- cgit v1.2.3