aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-06-09 22:28:51 +0200
committerVaxry <[email protected]>2024-06-10 00:06:42 +0200
commit1423707dbefc0329e80895451903a77ab684f7ea (patch)
tree046e0592451a0470387a0ac649535d7263582e9e
parent121c6ac3eae1601a1498e52a9be7030ebfed242c (diff)
downloadHyprland-1423707dbefc0329e80895451903a77ab684f7ea.tar.gz
Hyprland-1423707dbefc0329e80895451903a77ab684f7ea.zip
output: remove wl_output globals for mirrored displays
ref #6387
-rw-r--r--src/helpers/Monitor.cpp5
-rw-r--r--src/managers/ProtocolManager.cpp30
-rw-r--r--src/managers/ProtocolManager.hpp7
-rw-r--r--src/protocols/core/Output.cpp4
-rw-r--r--src/protocols/core/Output.hpp1
-rw-r--r--src/render/Renderer.cpp5
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;
}