From 68e1e6dc2696d0c8afac386a11fecae59760b70c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 08:50:37 +0000 Subject: [PATCH 1/5] Initial plan From 330c77c87ae46693cfc211833122bc0216906eb3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 08:54:36 +0000 Subject: [PATCH 2/5] Fix thread safety in Hyprland modules to prevent corrupted double-linked list crash - Move GTK operations from IPC thread to GTK main thread in Window module - Move GTK operations from IPC thread to GTK main thread in WindowCount module - Move GTK style class operations from IPC thread to GTK main thread in Submap module - Language and Workspaces modules already safe (only update internal state) Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com> --- include/modules/hyprland/submap.hpp | 1 + src/modules/hyprland/submap.cpp | 17 +++++++++++------ src/modules/hyprland/window.cpp | 4 ++-- src/modules/hyprland/windowcount.cpp | 3 +-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/include/modules/hyprland/submap.hpp b/include/modules/hyprland/submap.hpp index 7e3425ef..0dcb5d5a 100644 --- a/include/modules/hyprland/submap.hpp +++ b/include/modules/hyprland/submap.hpp @@ -26,6 +26,7 @@ class Submap : public waybar::ALabel, public EventHandler { const Bar& bar_; util::JsonParser parser_; std::string submap_; + std::string prev_submap_; bool always_on_ = false; std::string default_submap_ = "Default"; diff --git a/src/modules/hyprland/submap.cpp b/src/modules/hyprland/submap.cpp index eb9b1de8..5d587d02 100644 --- a/src/modules/hyprland/submap.cpp +++ b/src/modules/hyprland/submap.cpp @@ -44,6 +44,17 @@ auto Submap::parseConfig(const Json::Value& config) -> void { auto Submap::update() -> void { std::lock_guard lg(mutex_); + // Handle style class changes + if (!prev_submap_.empty()) { + label_.get_style_context()->remove_class(prev_submap_); + } + + if (!submap_.empty()) { + label_.get_style_context()->add_class(submap_); + } + + prev_submap_ = submap_; + if (submap_.empty()) { event_box_.hide(); } else { @@ -66,18 +77,12 @@ void Submap::onEvent(const std::string& ev) { auto submapName = ev.substr(ev.find_first_of('>') + 2); - if (!submap_.empty()) { - label_.get_style_context()->remove_class(submap_); - } - submap_ = submapName; if (submap_.empty() && always_on_) { submap_ = default_submap_; } - label_.get_style_context()->add_class(submap_); - spdlog::debug("hyprland submap onevent with {}", submap_); dp.emit(); diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index 23437c5f..e02a7691 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -45,6 +45,8 @@ Window::~Window() { auto Window::update() -> void { std::shared_lock windowIpcShareLock(windowIpcSmtx); + queryActiveWorkspace(); + std::string windowName = waybar::util::sanitize_string(workspace_.last_window_title); std::string windowAddress = workspace_.last_window; @@ -236,8 +238,6 @@ void Window::queryActiveWorkspace() { } void Window::onEvent(const std::string& ev) { - queryActiveWorkspace(); - dp.emit(); } diff --git a/src/modules/hyprland/windowcount.cpp b/src/modules/hyprland/windowcount.cpp index b2721aea..91589189 100644 --- a/src/modules/hyprland/windowcount.cpp +++ b/src/modules/hyprland/windowcount.cpp @@ -37,7 +37,7 @@ WindowCount::~WindowCount() { } auto WindowCount::update() -> void { - std::lock_guard lg(mutex_); + queryActiveWorkspace(); std::string format = config_["format"].asString(); std::string formatEmpty = config_["format-empty"].asString(); @@ -126,7 +126,6 @@ void WindowCount::queryActiveWorkspace() { } void WindowCount::onEvent(const std::string& ev) { - queryActiveWorkspace(); dp.emit(); } From c1240a98aad66672f39ac3d545ee38413d3f5ff3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 08:56:17 +0000 Subject: [PATCH 3/5] Fix mutex locking in WindowCount module Ensure workspace_ accesses are properly protected by mutex after queryActiveWorkspace call Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com> --- src/modules/hyprland/windowcount.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/hyprland/windowcount.cpp b/src/modules/hyprland/windowcount.cpp index 91589189..5d9ee1c3 100644 --- a/src/modules/hyprland/windowcount.cpp +++ b/src/modules/hyprland/windowcount.cpp @@ -44,6 +44,8 @@ auto WindowCount::update() -> void { std::string formatWindowed = config_["format-windowed"].asString(); std::string formatFullscreen = config_["format-fullscreen"].asString(); + std::lock_guard lg(mutex_); + setClass("empty", workspace_.windows == 0); setClass("fullscreen", workspace_.hasfullscreen); From da8fd864c62d0d52e0376213b7379d4c11f09c68 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 08:57:53 +0000 Subject: [PATCH 4/5] Simplify mutex locking in WindowCount module - Acquire lock once at start of update() and hold for entire function - Remove redundant lock from queryActiveWorkspace() since it's only called from update() This addresses code review feedback and makes the locking strategy clearer Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com> --- src/modules/hyprland/windowcount.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/hyprland/windowcount.cpp b/src/modules/hyprland/windowcount.cpp index 5d9ee1c3..487b0083 100644 --- a/src/modules/hyprland/windowcount.cpp +++ b/src/modules/hyprland/windowcount.cpp @@ -37,6 +37,8 @@ WindowCount::~WindowCount() { } auto WindowCount::update() -> void { + std::lock_guard lg(mutex_); + queryActiveWorkspace(); std::string format = config_["format"].asString(); @@ -44,8 +46,6 @@ auto WindowCount::update() -> void { std::string formatWindowed = config_["format-windowed"].asString(); std::string formatFullscreen = config_["format-fullscreen"].asString(); - std::lock_guard lg(mutex_); - setClass("empty", workspace_.windows == 0); setClass("fullscreen", workspace_.hasfullscreen); @@ -118,8 +118,6 @@ auto WindowCount::Workspace::parse(const Json::Value& value) -> WindowCount::Wor } void WindowCount::queryActiveWorkspace() { - std::lock_guard lg(mutex_); - if (separateOutputs_) { workspace_ = getActiveWorkspace(this->bar_.output->name); } else { From cb54b98fd5bdb42bf6a2d040ba11d8ab0b8bcbd9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 09:00:09 +0000 Subject: [PATCH 5/5] Final updates - thread safety fix complete Co-authored-by: Alexays <13947260+Alexays@users.noreply.github.com> --- _codeql_detected_source_root | 1 + 1 file changed, 1 insertion(+) create mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file