wayland/output: avoid sending events to dead outputs

ref #6835
This commit is contained in:
Vaxry 2024-07-22 16:56:51 +02:00
parent 83a5395eaa
commit 5bae7f150b
3 changed files with 12 additions and 7 deletions

View file

@ -66,8 +66,7 @@ void CProtocolManager::onMonitorModeChange(CMonitor* pMonitor) {
else if (!ISMIRROR && (!PROTO::outputs.contains(pMonitor->szName) || PROTO::outputs.at(pMonitor->szName)->isDefunct())) { else if (!ISMIRROR && (!PROTO::outputs.contains(pMonitor->szName) || PROTO::outputs.at(pMonitor->szName)->isDefunct())) {
if (PROTO::outputs.contains(pMonitor->szName)) if (PROTO::outputs.contains(pMonitor->szName))
PROTO::outputs.erase(pMonitor->szName); PROTO::outputs.erase(pMonitor->szName);
PROTO::outputs.emplace(pMonitor->szName, PROTO::outputs.emplace(pMonitor->szName, makeShared<CWLOutputProtocol>(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock()));
std::make_unique<CWLOutputProtocol>(&wl_output_interface, 4, std::format("WLOutput ({})", pMonitor->szName), pMonitor->self.lock()));
} }
} }
@ -86,7 +85,10 @@ CProtocolManager::CProtocolManager() {
if (PROTO::outputs.contains(M->szName)) if (PROTO::outputs.contains(M->szName))
PROTO::outputs.erase(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()));
auto ref = makeShared<CWLOutputProtocol>(&wl_output_interface, 4, std::format("WLOutput ({})", M->szName), M->self.lock());
PROTO::outputs.emplace(M->szName, ref);
ref->self = ref;
m_mModeChangeListeners[M->szName] = M->events.modeChanged.registerListener([M, this](std::any d) { onMonitorModeChange(M); }); m_mModeChangeListeners[M->szName] = M->events.modeChanged.registerListener([M, this](std::any d) { onMonitorModeChange(M); });
}); });

View file

@ -49,7 +49,7 @@ SP<CWlOutput> CWLOutputResource::getResource() {
} }
void CWLOutputResource::updateState() { void CWLOutputResource::updateState() {
if (!monitor) if (!monitor || (owner && owner->defunct))
return; return;
if (resource->version() >= 2) if (resource->version() >= 2)
@ -83,7 +83,8 @@ void CWLOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver,
return; return;
} }
RESOURCE->self = RESOURCE; RESOURCE->self = RESOURCE;
RESOURCE->owner = self;
} }
void CWLOutputProtocol::destroyResource(CWLOutputResource* resource) { void CWLOutputProtocol::destroyResource(CWLOutputResource* resource) {

View file

@ -8,6 +8,7 @@
#include "../../helpers/signal/Signal.hpp" #include "../../helpers/signal/Signal.hpp"
class CMonitor; class CMonitor;
class CWLOutputProtocol;
class CWLOutputResource { class CWLOutputResource {
public: public:
@ -20,7 +21,7 @@ class CWLOutputResource {
void updateState(); void updateState();
WP<CMonitor> monitor; WP<CMonitor> monitor;
WP<CWLOutputProtocol> owner;
WP<CWLOutputResource> self; WP<CWLOutputResource> self;
private: private:
@ -40,6 +41,7 @@ class CWLOutputProtocol : public IWaylandProtocol {
void sendDone(); void sendDone();
WP<CMonitor> monitor; WP<CMonitor> monitor;
WP<CWLOutputProtocol> self;
// will mark the protocol for removal, will be removed when no. of bound outputs is 0 (or when overwritten by a new global) // 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(); void remove();
@ -61,5 +63,5 @@ class CWLOutputProtocol : public IWaylandProtocol {
}; };
namespace PROTO { namespace PROTO {
inline std::unordered_map<std::string, UP<CWLOutputProtocol>> outputs; inline std::unordered_map<std::string, SP<CWLOutputProtocol>> outputs;
}; };