From a9ef11a2b387593a50dde6ff1ce22f434a840bd8 Mon Sep 17 00:00:00 2001 From: Will Wernert Date: Wed, 17 Dec 2025 22:17:35 -0500 Subject: [PATCH] fix: prevent duplicate layer surfaces on monitor hotplug The monitor signal handlers (signal_monitor_added, signal_monitor_removed) were never disconnected during SIGUSR2 reload. Each reload accumulated additional handlers, causing multiple layer surfaces to be created when monitors were hotplugged. This fix: - Stores signal connections as class members - Disconnects them before reconnecting in bindInterfaces() - Clears stale outputs_ on reload --- include/client.hpp | 2 ++ src/client.cpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/client.hpp b/include/client.hpp index 0e68f002..9dd09355 100644 --- a/include/client.hpp +++ b/include/client.hpp @@ -56,6 +56,8 @@ class Client { std::list outputs_; std::unique_ptr m_cssReloadHelper; std::string m_cssFile; + sigc::connection monitor_added_connection_; + sigc::connection monitor_removed_connection_; }; } // namespace waybar diff --git a/src/client.cpp b/src/client.cpp index 5136cfd8..f60e01a3 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -219,13 +219,22 @@ void waybar::Client::bindInterfaces() { if (xdg_output_manager == nullptr) { throw std::runtime_error("Failed to acquire required resources."); } + + // Disconnect previous signal handlers to prevent duplicate handlers on reload + monitor_added_connection_.disconnect(); + monitor_removed_connection_.disconnect(); + + // Clear stale outputs from previous run + outputs_.clear(); + // add existing outputs and subscribe to updates for (auto i = 0; i < gdk_display->get_n_monitors(); ++i) { auto monitor = gdk_display->get_monitor(i); handleMonitorAdded(monitor); } - gdk_display->signal_monitor_added().connect(sigc::mem_fun(*this, &Client::handleMonitorAdded)); - gdk_display->signal_monitor_removed().connect( + monitor_added_connection_ = gdk_display->signal_monitor_added().connect( + sigc::mem_fun(*this, &Client::handleMonitorAdded)); + monitor_removed_connection_ = gdk_display->signal_monitor_removed().connect( sigc::mem_fun(*this, &Client::handleMonitorRemoved)); }