From 29106c5c1e9819d5d0f9226bb33c75ebb9e6860b Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Thu, 4 Jun 2026 16:22:24 -0700 Subject: [PATCH] perf(sway/window): avoid tree fetches for simple events --- include/modules/sway/window.hpp | 1 + src/modules/sway/window.cpp | 54 ++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp index 60cd267967..251b0ef643 100644 --- a/include/modules/sway/window.hpp +++ b/include/modules/sway/window.hpp @@ -22,6 +22,7 @@ class Window : public AAppIconLabel, public sigc::trackable { void setClass(const std::string& classname, bool enable); void onEvent(const struct Ipc::ipc_response&); void onCmd(const struct Ipc::ipc_response&); + bool handleWindowEvent(const Json::Value&); std::tuple getFocusedNode(const Json::Value& nodes, std::string& output); diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index 2908b85c2f..d9b95bf5c6 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -34,7 +34,20 @@ Window::Window(const std::string& id, const Bar& bar, const Json::Value& config) }); } -void Window::onEvent(const struct Ipc::ipc_response& res) { getTree(); } +void Window::onEvent(const struct Ipc::ipc_response& res) { + if (res.type == IPC_EVENT_WINDOW) { + try { + const auto payload = parser_.parse(res.payload); + if (handleWindowEvent(payload)) { + return; + } + } catch (const std::exception& e) { + spdlog::warn("Window: failed to process window event payload: {}", e.what()); + } + } + + getTree(); +} void Window::onCmd(const struct Ipc::ipc_response& res) { try { @@ -192,6 +205,45 @@ std::tuple getWindowInfo( return {app_id, app_class, shell, marks}; } +bool Window::handleWindowEvent(const Json::Value& payload) { + const auto change = payload["change"].isString() ? payload["change"].asString() : ""; + const auto& container = payload["container"]; + + if (change == "fullscreen_mode" || change == "urgent") { + return true; + } + + if (change != "title" && change != "mark") { + return false; + } + + if (!container.isObject() || !container["id"].isInt() || !container["focused"].isBool()) { + return false; + } + + if (!container["focused"].asBool()) { + // A title change on an unfocused window cannot affect the focused-window label. + return change == "title"; + } + + std::lock_guard lock(mutex_); + if (container["id"].asInt() != windowId_) { + return false; + } + + const auto [app_id, app_class, shell, marks] = + getWindowInfo(container, config_["show-hidden-marks"].asBool()); + window_ = Glib::Markup::escape_text(container["name"].asString()); + app_id_ = app_id; + app_class_ = app_class; + shell_ = shell; + marks_ = marks; + updateAppIconName(app_id_, app_class_); + dp.emit(); + + return true; +} + std::tuple gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Value& config_,