diff options
author | Vaxry <[email protected]> | 2024-06-09 22:28:51 +0200 |
---|---|---|
committer | Vaxry <[email protected]> | 2024-06-10 00:06:42 +0200 |
commit | 1423707dbefc0329e80895451903a77ab684f7ea (patch) | |
tree | 046e0592451a0470387a0ac649535d7263582e9e | |
parent | 121c6ac3eae1601a1498e52a9be7030ebfed242c (diff) | |
download | Hyprland-1423707dbefc0329e80895451903a77ab684f7ea.tar.gz Hyprland-1423707dbefc0329e80895451903a77ab684f7ea.zip |
output: remove wl_output globals for mirrored displays
ref #6387
-rw-r--r-- | src/helpers/Monitor.cpp | 5 | ||||
-rw-r--r-- | src/managers/ProtocolManager.cpp | 30 | ||||
-rw-r--r-- | src/managers/ProtocolManager.hpp | 7 | ||||
-rw-r--r-- | src/protocols/core/Output.cpp | 4 | ||||
-rw-r--r-- | src/protocols/core/Output.hpp | 1 | ||||
-rw-r--r-- | src/render/Renderer.cpp | 5 |
6 files changed, 49 insertions, 3 deletions
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 5962b73d..a30f1057 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -184,6 +184,9 @@ void CMonitor::onConnect(bool noRule) { forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering. // + if (!activeMonitorRule.mirrorOf.empty()) + setMirror(activeMonitorRule.mirrorOf); + g_pEventManager->postEvent(SHyprIPCEvent{"monitoradded", szName}); g_pEventManager->postEvent(SHyprIPCEvent{"monitoraddedv2", std::format("{},{},{}", ID, szName, szShortDescription)}); EMIT_HOOK_EVENT("monitorAdded", this); @@ -517,6 +520,8 @@ void CMonitor::setMirror(const std::string& mirrorOf) { g_pCompositor->sanityCheckWorkspaces(); } + + events.modeChanged.emit(); } float CMonitor::getDefaultScale() { diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp index 7946a3f7..74cebd0c 100644 --- a/src/managers/ProtocolManager.cpp +++ b/src/managers/ProtocolManager.cpp @@ -46,21 +46,47 @@ #include "../helpers/Monitor.hpp" #include "../render/Renderer.hpp" +void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) { + const bool ISMIRROR = pMonitor->isMirror(); + + // onModeChanged we check if the current mirror status matches the global. + // mirrored outputs should have their global removed, as they are not physical parts of the + // layout. + + if (ISMIRROR && PROTO::outputs.contains(pMonitor->szName)) + PROTO::outputs.at(pMonitor->szName)->remove(); + else if (!ISMIRROR && (!PROTO::outputs.contains(pMonitor->szName) || PROTO::outputs.at(pMonitor->szName)->isDefunct())) { + if (PROTO::outputs.contains(pMonitor->szName)) + PROTO::outputs.erase(pMonitor->szName); + PROTO::outputs.emplace(pMonitor->szName, + std::make_unique<CWLOutputProtocol>(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock())); + } +} + CProtocolManager::CProtocolManager() { // Outputs are a bit dumb, we have to agree. - static auto P = g_pHookSystem->hookDynamic("monitorAdded", [](void* self, SCallbackInfo& info, std::any param) { + static auto P = g_pHookSystem->hookDynamic("monitorAdded", [this](void* self, SCallbackInfo& info, std::any param) { auto M = std::any_cast<CMonitor*>(param); + + // ignore mirrored outputs. I don't think this will ever be hit as mirrors are applied after + // this event is emitted iirc. + if (M->isMirror()) + return; + if (PROTO::outputs.contains(M->szName)) PROTO::outputs.erase(M->szName); PROTO::outputs.emplace(M->szName, std::make_unique<CWLOutputProtocol>(&wl_output_interface, 4, std::format("WLOutput ({})", M->szName), M->self.lock())); + + m_mModeChangeListeners[M->szName] = M->events.modeChanged.registerListener([M, this](std::any d) { onMonitorModeChange(M); }); }); - static auto P2 = g_pHookSystem->hookDynamic("monitorRemoved", [](void* self, SCallbackInfo& info, std::any param) { + static auto P2 = g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { auto M = std::any_cast<CMonitor*>(param); if (!PROTO::outputs.contains(M->szName)) return; PROTO::outputs.at(M->szName)->remove(); + m_mModeChangeListeners.erase(M->szName); }); // Core diff --git a/src/managers/ProtocolManager.hpp b/src/managers/ProtocolManager.hpp index 9af7b928..4f668b46 100644 --- a/src/managers/ProtocolManager.hpp +++ b/src/managers/ProtocolManager.hpp @@ -5,6 +5,8 @@ #include "../protocols/TextInputV1.hpp" #include "../protocols/GlobalShortcuts.hpp" #include "../protocols/Screencopy.hpp" +#include "../helpers/memory/WeakPtr.hpp" +#include <unordered_map> class CProtocolManager { public: @@ -15,6 +17,11 @@ class CProtocolManager { std::unique_ptr<CTextInputV1ProtocolManager> m_pTextInputV1ProtocolManager; std::unique_ptr<CGlobalShortcutsProtocolManager> m_pGlobalShortcutsProtocolManager; std::unique_ptr<CScreencopyProtocolManager> m_pScreencopyProtocolManager; + + private: + std::unordered_map<std::string, CHyprSignalListener> m_mModeChangeListeners; + + void onMonitorModeChange(CMonitor* pMonitor); }; inline std::unique_ptr<CProtocolManager> g_pProtocolManager; diff --git a/src/protocols/core/Output.cpp b/src/protocols/core/Output.cpp index a1b0c7b0..90358fa5 100644 --- a/src/protocols/core/Output.cpp +++ b/src/protocols/core/Output.cpp @@ -105,3 +105,7 @@ void CWLOutputProtocol::remove() { defunct = true; removeGlobal(); } + +bool CWLOutputProtocol::isDefunct() { + return defunct; +} diff --git a/src/protocols/core/Output.hpp b/src/protocols/core/Output.hpp index 5c274612..b17a8272 100644 --- a/src/protocols/core/Output.hpp +++ b/src/protocols/core/Output.hpp @@ -40,6 +40,7 @@ class CWLOutputProtocol : public IWaylandProtocol { // will mark the protocol for removal, will be removed when no. of bound outputs is 0 (or when overwritten by a new global) void remove(); + bool isDefunct(); // true if above was called private: void destroyResource(CWLOutputResource* resource); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 17f91d48..8fac5869 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1353,7 +1353,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } else g_pHyprRenderer->renderWindow(pMonitor->solitaryClient.lock(), pMonitor, &now, false, RENDER_PASS_MAIN /* solitary = no popups */); - } else { + } else if (!pMonitor->isMirror()) { sendFrameEventsToWorkspace(pMonitor, pMonitor->activeWorkspace, &now); if (pMonitor->activeSpecialWorkspace) sendFrameEventsToWorkspace(pMonitor, pMonitor->activeSpecialWorkspace, &now); @@ -1869,6 +1869,9 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR !memcmp(&pMonitor->customDrmMode, &RULE->drmMode, sizeof(pMonitor->customDrmMode))) { Debug::log(LOG, "Not applying a new rule to {} because it's already applied!", pMonitor->szName); + + pMonitor->setMirror(RULE->mirrorOf); + return true; } |