diff --git a/include/modules/hyprland/backend.hpp b/include/modules/hyprland/backend.hpp index 11e73d8f6..cfd0b2584 100644 --- a/include/modules/hyprland/backend.hpp +++ b/include/modules/hyprland/backend.hpp @@ -2,9 +2,9 @@ #include #include -#include #include #include +#include #include #include "util/json.hpp" @@ -19,7 +19,9 @@ class EventHandler { class IPC { public: - IPC() { startIPC(); } + IPC(); + ~IPC(); + static IPC& inst(); void registerForIPC(const std::string& ev, EventHandler* ev_handler); void unregisterForIPC(EventHandler* handler); @@ -32,14 +34,16 @@ class IPC { static std::filesystem::path socketFolder_; private: - void startIPC(); + void socketListener(); void parseIPC(const std::string&); + std::thread ipcThread_; std::mutex callbackMutex_; util::JsonParser parser_; std::list> callbacks_; + int socketfd_; // the hyprland socket file descriptor + bool running_ = true; }; -inline std::unique_ptr gIPC; inline bool modulesReady = false; }; // namespace waybar::modules::hyprland diff --git a/include/modules/hyprland/language.hpp b/include/modules/hyprland/language.hpp index 47a4d69c3..ec59e5c3a 100644 --- a/include/modules/hyprland/language.hpp +++ b/include/modules/hyprland/language.hpp @@ -37,6 +37,8 @@ class Language : public waybar::ALabel, public EventHandler { util::JsonParser parser_; Layout layout_; + + IPC& m_ipc; }; } // namespace waybar::modules::hyprland diff --git a/include/modules/hyprland/submap.hpp b/include/modules/hyprland/submap.hpp index ce980f36f..7e3425ef7 100644 --- a/include/modules/hyprland/submap.hpp +++ b/include/modules/hyprland/submap.hpp @@ -28,6 +28,8 @@ class Submap : public waybar::ALabel, public EventHandler { std::string submap_; bool always_on_ = false; std::string default_submap_ = "Default"; + + IPC& m_ipc; }; } // namespace waybar::modules::hyprland diff --git a/include/modules/hyprland/window.hpp b/include/modules/hyprland/window.hpp index f2c266bd2..2be645942 100644 --- a/include/modules/hyprland/window.hpp +++ b/include/modules/hyprland/window.hpp @@ -60,6 +60,8 @@ class Window : public waybar::AAppIconLabel, public EventHandler { bool swallowing_; bool fullscreen_; bool focused_; + + IPC& m_ipc; }; } // namespace waybar::modules::hyprland diff --git a/include/modules/hyprland/workspace.hpp b/include/modules/hyprland/workspace.hpp index f1fea4e8c..3dedba4c5 100644 --- a/include/modules/hyprland/workspace.hpp +++ b/include/modules/hyprland/workspace.hpp @@ -83,6 +83,7 @@ class Workspace { Gtk::Button m_button; Gtk::Box m_content; Gtk::Label m_label; + IPC& m_ipc; }; } // namespace waybar::modules::hyprland diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index f5c20f69c..3f0252c87 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -150,6 +150,7 @@ class Workspaces : public AModule, public EventHandler { std::mutex m_mutex; const Bar& m_bar; Gtk::Box m_box; + IPC& m_ipc; }; } // namespace waybar::modules::hyprland diff --git a/src/modules/hyprland/backend.cpp b/src/modules/hyprland/backend.cpp index 39341a14b..2bd3b5095 100644 --- a/src/modules/hyprland/backend.cpp +++ b/src/modules/hyprland/backend.cpp @@ -11,7 +11,6 @@ #include #include -#include namespace waybar::modules::hyprland { @@ -44,71 +43,96 @@ std::filesystem::path IPC::getSocketFolder(const char* instanceSig) { return socketFolder_; } -void IPC::startIPC() { +IPC::IPC() { // will start IPC and relay events to parseIPC + ipcThread_ = std::thread([this]() { socketListener(); }); +} - std::thread([&]() { - // check for hyprland - const char* his = getenv("HYPRLAND_INSTANCE_SIGNATURE"); - - if (his == nullptr) { - spdlog::warn("Hyprland is not running, Hyprland IPC will not be available."); - return; +IPC::~IPC() { + running_ = false; + spdlog::info("Hyprland IPC stopping..."); + if (socketfd_ != -1) { + spdlog::trace("Shutting down socket"); + if (shutdown(socketfd_, SHUT_RDWR) == -1) { + spdlog::error("Hyprland IPC: Couldn't shutdown socket"); + } + spdlog::trace("Closing socket"); + if (close(socketfd_) == -1) { + spdlog::error("Hyprland IPC: Couldn't close socket"); } + } + ipcThread_.join(); +} - if (!modulesReady) return; +IPC& IPC::inst() { + static IPC ipc; + return ipc; +} - spdlog::info("Hyprland IPC starting"); +void IPC::socketListener() { + // check for hyprland + const char* his = getenv("HYPRLAND_INSTANCE_SIGNATURE"); - struct sockaddr_un addr; - int socketfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (his == nullptr) { + spdlog::warn("Hyprland is not running, Hyprland IPC will not be available."); + return; + } - if (socketfd == -1) { - spdlog::error("Hyprland IPC: socketfd failed"); - return; - } + if (!modulesReady) return; - addr.sun_family = AF_UNIX; + spdlog::info("Hyprland IPC starting"); - auto socketPath = IPC::getSocketFolder(his) / ".socket2.sock"; - strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); + struct sockaddr_un addr; + socketfd_ = socket(AF_UNIX, SOCK_STREAM, 0); - addr.sun_path[sizeof(addr.sun_path) - 1] = 0; + if (socketfd_ == -1) { + spdlog::error("Hyprland IPC: socketfd failed"); + return; + } - int l = sizeof(struct sockaddr_un); + addr.sun_family = AF_UNIX; - if (connect(socketfd, (struct sockaddr*)&addr, l) == -1) { - spdlog::error("Hyprland IPC: Unable to connect?"); - return; - } + auto socketPath = IPC::getSocketFolder(his) / ".socket2.sock"; + strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1); - auto* file = fdopen(socketfd, "r"); + addr.sun_path[sizeof(addr.sun_path) - 1] = 0; - while (true) { - std::array buffer; // Hyprland socket2 events are max 1024 bytes + int l = sizeof(struct sockaddr_un); - auto* receivedCharPtr = fgets(buffer.data(), buffer.size(), file); + if (connect(socketfd_, (struct sockaddr*)&addr, l) == -1) { + spdlog::error("Hyprland IPC: Unable to connect?"); + return; + } + auto* file = fdopen(socketfd_, "r"); + if (file == nullptr) { + spdlog::error("Hyprland IPC: Couldn't open file descriptor"); + return; + } + while (running_) { + std::array buffer; // Hyprland socket2 events are max 1024 bytes - if (receivedCharPtr == nullptr) { - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - continue; - } + auto* receivedCharPtr = fgets(buffer.data(), buffer.size(), file); - std::string messageReceived(buffer.data()); - messageReceived = messageReceived.substr(0, messageReceived.find_first_of('\n')); - spdlog::debug("hyprland IPC received {}", messageReceived); + if (receivedCharPtr == nullptr) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + continue; + } - try { - parseIPC(messageReceived); - } catch (std::exception& e) { - spdlog::warn("Failed to parse IPC message: {}, reason: {}", messageReceived, e.what()); - } catch (...) { - throw; - } + std::string messageReceived(buffer.data()); + messageReceived = messageReceived.substr(0, messageReceived.find_first_of('\n')); + spdlog::debug("hyprland IPC received {}", messageReceived); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + try { + parseIPC(messageReceived); + } catch (std::exception& e) { + spdlog::warn("Failed to parse IPC message: {}, reason: {}", messageReceived, e.what()); + } catch (...) { + throw; } - }).detach(); + + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + spdlog::debug("Hyprland IPC stopped"); } void IPC::parseIPC(const std::string& ev) { diff --git a/src/modules/hyprland/language.cpp b/src/modules/hyprland/language.cpp index d86393af5..da56e578c 100644 --- a/src/modules/hyprland/language.cpp +++ b/src/modules/hyprland/language.cpp @@ -10,13 +10,9 @@ namespace waybar::modules::hyprland { Language::Language(const std::string& id, const Bar& bar, const Json::Value& config) - : ALabel(config, "language", id, "{}", 0, true), bar_(bar) { + : ALabel(config, "language", id, "{}", 0, true), bar_(bar), m_ipc(IPC::inst()) { modulesReady = true; - if (!gIPC) { - gIPC = std::make_unique(); - } - // get the active layout when open initLanguage(); @@ -24,11 +20,11 @@ Language::Language(const std::string& id, const Bar& bar, const Json::Value& con update(); // register for hyprland ipc - gIPC->registerForIPC("activelayout", this); + m_ipc.registerForIPC("activelayout", this); } Language::~Language() { - gIPC->unregisterForIPC(this); + m_ipc.unregisterForIPC(this); // wait for possible event handler to finish std::lock_guard lg(mutex_); } @@ -85,7 +81,7 @@ void Language::onEvent(const std::string& ev) { } void Language::initLanguage() { - const auto inputDevices = gIPC->getSocket1Reply("devices"); + const auto inputDevices = m_ipc.getSocket1Reply("devices"); const auto kbName = config_["keyboard-name"].asString(); diff --git a/src/modules/hyprland/submap.cpp b/src/modules/hyprland/submap.cpp index 96677d127..97c4bb623 100644 --- a/src/modules/hyprland/submap.cpp +++ b/src/modules/hyprland/submap.cpp @@ -7,15 +7,11 @@ namespace waybar::modules::hyprland { Submap::Submap(const std::string& id, const Bar& bar, const Json::Value& config) - : ALabel(config, "submap", id, "{}", 0, true), bar_(bar) { + : ALabel(config, "submap", id, "{}", 0, true), bar_(bar), m_ipc(IPC::inst()) { modulesReady = true; parseConfig(config); - if (!gIPC) { - gIPC = std::make_unique(); - } - label_.hide(); ALabel::update(); @@ -27,12 +23,12 @@ Submap::Submap(const std::string& id, const Bar& bar, const Json::Value& config) } // register for hyprland ipc - gIPC->registerForIPC("submap", this); + m_ipc.registerForIPC("submap", this); dp.emit(); } Submap::~Submap() { - gIPC->unregisterForIPC(this); + m_ipc.unregisterForIPC(this); // wait for possible event handler to finish std::lock_guard lg(mutex_); } diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index 08c993630..815fbad82 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include "modules/hyprland/backend.hpp" @@ -19,22 +18,18 @@ namespace waybar::modules::hyprland { std::shared_mutex windowIpcSmtx; Window::Window(const std::string& id, const Bar& bar, const Json::Value& config) - : AAppIconLabel(config, "window", id, "{title}", 0, true), bar_(bar) { + : AAppIconLabel(config, "window", id, "{title}", 0, true), bar_(bar), m_ipc(IPC::inst()) { std::unique_lock windowIpcUniqueLock(windowIpcSmtx); modulesReady = true; separateOutputs_ = config["separate-outputs"].asBool(); - if (!gIPC) { - gIPC = std::make_unique(); - } - // register for hyprland ipc - gIPC->registerForIPC("activewindow", this); - gIPC->registerForIPC("closewindow", this); - gIPC->registerForIPC("movewindow", this); - gIPC->registerForIPC("changefloatingmode", this); - gIPC->registerForIPC("fullscreen", this); + m_ipc.registerForIPC("activewindow", this); + m_ipc.registerForIPC("closewindow", this); + m_ipc.registerForIPC("movewindow", this); + m_ipc.registerForIPC("changefloatingmode", this); + m_ipc.registerForIPC("fullscreen", this); windowIpcUniqueLock.unlock(); @@ -45,7 +40,7 @@ Window::Window(const std::string& id, const Bar& bar, const Json::Value& config) Window::~Window() { std::unique_lock windowIpcUniqueLock(windowIpcSmtx); - gIPC->unregisterForIPC(this); + m_ipc.unregisterForIPC(this); } auto Window::update() -> void { @@ -76,11 +71,12 @@ auto Window::update() -> void { tooltip_format = config_["tooltip-format"].asString(); } if (!tooltip_format.empty()) { - label_.set_tooltip_text(fmt::format(fmt::runtime(tooltip_format), fmt::arg("title", windowName), - fmt::arg("initialTitle", windowData_.initial_title), - fmt::arg("class", windowData_.class_name), - fmt::arg("initialClass", windowData_.initial_class_name))); - } else if (!label_text.empty()){ + label_.set_tooltip_text( + fmt::format(fmt::runtime(tooltip_format), fmt::arg("title", windowName), + fmt::arg("initialTitle", windowData_.initial_title), + fmt::arg("class", windowData_.class_name), + fmt::arg("initialClass", windowData_.initial_class_name))); + } else if (!label_text.empty()) { label_.set_tooltip_text(label_text); } } @@ -114,7 +110,7 @@ auto Window::update() -> void { } auto Window::getActiveWorkspace() -> Workspace { - const auto workspace = gIPC->getSocket1JsonReply("activeworkspace"); + const auto workspace = IPC::inst().getSocket1JsonReply("activeworkspace"); if (workspace.isObject()) { return Workspace::parse(workspace); @@ -124,24 +120,33 @@ auto Window::getActiveWorkspace() -> Workspace { } auto Window::getActiveWorkspace(const std::string& monitorName) -> Workspace { - const auto monitors = gIPC->getSocket1JsonReply("monitors"); + const auto monitors = IPC::inst().getSocket1JsonReply("monitors"); if (monitors.isArray()) { - auto monitor = std::find_if(monitors.begin(), monitors.end(), [&](Json::Value monitor) { - return monitor["name"] == monitorName; - }); + auto monitor = std::ranges::find_if( + monitors, [&](Json::Value monitor) { return monitor["name"] == monitorName; }); if (monitor == std::end(monitors)) { spdlog::warn("Monitor not found: {}", monitorName); - return Workspace{-1, 0, "", ""}; + return Workspace{ + .id = -1, + .windows = 0, + .last_window = "", + .last_window_title = "", + }; } const int id = (*monitor)["activeWorkspace"]["id"].asInt(); - const auto workspaces = gIPC->getSocket1JsonReply("workspaces"); + const auto workspaces = IPC::inst().getSocket1JsonReply("workspaces"); if (workspaces.isArray()) { - auto workspace = std::find_if(workspaces.begin(), workspaces.end(), - [&](Json::Value workspace) { return workspace["id"] == id; }); + auto workspace = std::ranges::find_if( + workspaces, [&](Json::Value workspace) { return workspace["id"] == id; }); if (workspace == std::end(workspaces)) { spdlog::warn("No workspace with id {}", id); - return Workspace{-1, 0, "", ""}; + return Workspace{ + .id = -1, + .windows = 0, + .last_window = "", + .last_window_title = "", + }; } return Workspace::parse(*workspace); }; @@ -152,18 +157,22 @@ auto Window::getActiveWorkspace(const std::string& monitorName) -> Workspace { auto Window::Workspace::parse(const Json::Value& value) -> Window::Workspace { return Workspace{ - value["id"].asInt(), - value["windows"].asInt(), - value["lastwindow"].asString(), - value["lastwindowtitle"].asString(), + .id = value["id"].asInt(), + .windows = value["windows"].asInt(), + .last_window = value["lastwindow"].asString(), + .last_window_title = value["lastwindowtitle"].asString(), }; } auto Window::WindowData::parse(const Json::Value& value) -> Window::WindowData { - return WindowData{value["floating"].asBool(), value["monitor"].asInt(), - value["class"].asString(), value["initialClass"].asString(), - value["title"].asString(), value["initialTitle"].asString(), - value["fullscreen"].asBool(), !value["grouped"].empty()}; + return WindowData{.floating = value["floating"].asBool(), + .monitor = value["monitor"].asInt(), + .class_name = value["class"].asString(), + .initial_class_name = value["initialClass"].asString(), + .title = value["title"].asString(), + .initial_title = value["initialTitle"].asString(), + .fullscreen = value["fullscreen"].asBool(), + .grouped = !value["grouped"].empty()}; } void Window::queryActiveWorkspace() { @@ -177,11 +186,10 @@ void Window::queryActiveWorkspace() { focused_ = true; if (workspace_.windows > 0) { - const auto clients = gIPC->getSocket1JsonReply("clients"); + const auto clients = m_ipc.getSocket1JsonReply("clients"); if (clients.isArray()) { - auto activeWindow = std::find_if(clients.begin(), clients.end(), [&](Json::Value window) { - return window["address"] == workspace_.last_window; - }); + auto activeWindow = std::ranges::find_if( + clients, [&](Json::Value window) { return window["address"] == workspace_.last_window; }); if (activeWindow == std::end(clients)) { focused_ = false; @@ -191,22 +199,19 @@ void Window::queryActiveWorkspace() { windowData_ = WindowData::parse(*activeWindow); updateAppIconName(windowData_.class_name, windowData_.initial_class_name); std::vector workspaceWindows; - std::copy_if(clients.begin(), clients.end(), std::back_inserter(workspaceWindows), - [&](Json::Value window) { - return window["workspace"]["id"] == workspace_.id && window["mapped"].asBool(); - }); - swallowing_ = - std::any_of(workspaceWindows.begin(), workspaceWindows.end(), [&](Json::Value window) { - return !window["swallowing"].isNull() && window["swallowing"].asString() != "0x0"; - }); + std::ranges::copy_if(clients, std::back_inserter(workspaceWindows), [&](Json::Value window) { + return window["workspace"]["id"] == workspace_.id && window["mapped"].asBool(); + }); + swallowing_ = std::ranges::any_of(workspaceWindows, [&](Json::Value window) { + return !window["swallowing"].isNull() && window["swallowing"].asString() != "0x0"; + }); std::vector visibleWindows; - std::copy_if(workspaceWindows.begin(), workspaceWindows.end(), - std::back_inserter(visibleWindows), - [&](Json::Value window) { return !window["hidden"].asBool(); }); + std::ranges::copy_if(workspaceWindows, std::back_inserter(visibleWindows), + [&](Json::Value window) { return !window["hidden"].asBool(); }); solo_ = 1 == std::count_if(visibleWindows.begin(), visibleWindows.end(), [&](Json::Value window) { return !window["floating"].asBool(); }); - allFloating_ = std::all_of(visibleWindows.begin(), visibleWindows.end(), - [&](Json::Value window) { return window["floating"].asBool(); }); + allFloating_ = std::ranges::all_of( + visibleWindows, [&](Json::Value window) { return window["floating"].asBool(); }); fullscreen_ = windowData_.fullscreen; // Fullscreen windows look like they are solo @@ -219,7 +224,7 @@ void Window::queryActiveWorkspace() { } else { soloClass_ = ""; } - }; + } } else { focused_ = false; windowData_ = WindowData{}; diff --git a/src/modules/hyprland/workspace.cpp b/src/modules/hyprland/workspace.cpp index e575d1c4d..4655096f4 100644 --- a/src/modules/hyprland/workspace.cpp +++ b/src/modules/hyprland/workspace.cpp @@ -18,7 +18,8 @@ Workspace::Workspace(const Json::Value &workspace_data, Workspaces &workspace_ma m_windows(workspace_data["windows"].asInt()), m_isActive(true), m_isPersistentRule(workspace_data["persistent-rule"].asBool()), - m_isPersistentConfig(workspace_data["persistent-config"].asBool()) { + m_isPersistentConfig(workspace_data["persistent-config"].asBool()), + m_ipc(IPC::inst()) { if (m_name.starts_with("name:")) { m_name = m_name.substr(5); } else if (m_name.starts_with("special")) { @@ -58,20 +59,20 @@ bool Workspace::handleClicked(GdkEventButton *bt) const { try { if (id() > 0) { // normal if (m_workspaceManager.moveToMonitor()) { - gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor " + std::to_string(id())); + m_ipc.getSocket1Reply("dispatch focusworkspaceoncurrentmonitor " + std::to_string(id())); } else { - gIPC->getSocket1Reply("dispatch workspace " + std::to_string(id())); + m_ipc.getSocket1Reply("dispatch workspace " + std::to_string(id())); } } else if (!isSpecial()) { // named (this includes persistent) if (m_workspaceManager.moveToMonitor()) { - gIPC->getSocket1Reply("dispatch focusworkspaceoncurrentmonitor name:" + name()); + m_ipc.getSocket1Reply("dispatch focusworkspaceoncurrentmonitor name:" + name()); } else { - gIPC->getSocket1Reply("dispatch workspace name:" + name()); + m_ipc.getSocket1Reply("dispatch workspace name:" + name()); } } else if (id() != -99) { // named special - gIPC->getSocket1Reply("dispatch togglespecialworkspace " + name()); + m_ipc.getSocket1Reply("dispatch togglespecialworkspace " + name()); } else { // special - gIPC->getSocket1Reply("dispatch togglespecialworkspace"); + m_ipc.getSocket1Reply("dispatch togglespecialworkspace"); } return true; } catch (const std::exception &e) { diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 66851c226..57abb2288 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -13,7 +13,10 @@ namespace waybar::modules::hyprland { Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config) - : AModule(config, "workspaces", id, false, false), m_bar(bar), m_box(bar.orientation, 0) { + : AModule(config, "workspaces", id, false, false), + m_bar(bar), + m_box(bar.orientation, 0), + m_ipc(IPC::inst()) { modulesReady = true; parseConfig(config); @@ -24,23 +27,19 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value m_box.get_style_context()->add_class(MODULE_CLASS); event_box_.add(m_box); - if (!gIPC) { - gIPC = std::make_unique(); - } - setCurrentMonitorId(); init(); registerIpc(); } Workspaces::~Workspaces() { - gIPC->unregisterForIPC(this); + m_ipc.unregisterForIPC(this); // wait for possible event handler to finish std::lock_guard lg(m_mutex); } void Workspaces::init() { - m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString(); + m_activeWorkspaceName = (m_ipc.getSocket1JsonReply("activeworkspace"))["name"].asString(); initializeWorkspaces(); dp.emit(); @@ -161,7 +160,7 @@ std::string Workspaces::getRewrite(std::string window_class, std::string window_ std::vector Workspaces::getVisibleWorkspaces() { std::vector visibleWorkspaces; - auto monitors = gIPC->getSocket1JsonReply("monitors"); + auto monitors = IPC::inst().getSocket1JsonReply("monitors"); for (const auto &monitor : monitors) { auto ws = monitor["activeWorkspace"]; if (ws.isObject() && ws["name"].isString()) { @@ -185,8 +184,8 @@ void Workspaces::initializeWorkspaces() { } // get all current workspaces - auto const workspacesJson = gIPC->getSocket1JsonReply("workspaces"); - auto const clientsJson = gIPC->getSocket1JsonReply("clients"); + auto const workspacesJson = m_ipc.getSocket1JsonReply("workspaces"); + auto const clientsJson = m_ipc.getSocket1JsonReply("clients"); for (Json::Value workspaceJson : workspacesJson) { std::string workspaceName = workspaceJson["name"].asString(); @@ -285,7 +284,7 @@ void Workspaces::loadPersistentWorkspacesFromConfig(Json::Value const &clientsJs void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value &clientsJson) { spdlog::info("Loading persistent workspaces from Hyprland workspace rules"); - auto const workspaceRules = gIPC->getSocket1JsonReply("workspacerules"); + auto const workspaceRules = m_ipc.getSocket1JsonReply("workspacerules"); for (Json::Value const &rule : workspaceRules) { if (!rule["workspaceString"].isString()) { spdlog::warn("Workspace rules: invalid workspaceString, skipping: {}", rule); @@ -366,10 +365,10 @@ void Workspaces::onWorkspaceDestroyed(std::string const &payload) { void Workspaces::onWorkspaceCreated(std::string const &workspaceName, Json::Value const &clientsData) { spdlog::debug("Workspace created: {}", workspaceName); - auto const workspacesJson = gIPC->getSocket1JsonReply("workspaces"); + auto const workspacesJson = m_ipc.getSocket1JsonReply("workspaces"); if (!isWorkspaceIgnored(workspaceName)) { - auto const workspaceRules = gIPC->getSocket1JsonReply("workspacerules"); + auto const workspaceRules = m_ipc.getSocket1JsonReply("workspacerules"); for (Json::Value workspaceJson : workspacesJson) { std::string name = workspaceJson["name"].asString(); if (name == workspaceName) { @@ -401,7 +400,7 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) { spdlog::debug("Workspace moved: {}", payload); // Update active workspace - m_activeWorkspaceName = (gIPC->getSocket1JsonReply("activeworkspace"))["name"].asString(); + m_activeWorkspaceName = (m_ipc.getSocket1JsonReply("activeworkspace"))["name"].asString(); if (allOutputs()) return; @@ -409,7 +408,7 @@ void Workspaces::onWorkspaceMoved(std::string const &payload) { std::string monitorName = payload.substr(payload.find(',') + 1); if (m_bar.output->name == monitorName) { - Json::Value clientsData = gIPC->getSocket1JsonReply("clients"); + Json::Value clientsData = m_ipc.getSocket1JsonReply("clients"); onWorkspaceCreated(workspaceName, clientsData); } else { spdlog::debug("Removing workspace because it was moved to another monitor: {}"); @@ -438,7 +437,7 @@ void Workspaces::onMonitorFocused(std::string const &payload) { spdlog::trace("Monitor focused: {}", payload); m_activeWorkspaceName = payload.substr(payload.find(',') + 1); - for (Json::Value &monitor : gIPC->getSocket1JsonReply("monitors")) { + for (Json::Value &monitor : m_ipc.getSocket1JsonReply("monitors")) { if (monitor["name"].asString() == payload.substr(0, payload.find(','))) { auto name = monitor["specialWorkspace"]["name"].asString(); m_activeSpecialWorkspaceName = !name.starts_with("special:") ? name : name.substr(8); @@ -546,7 +545,7 @@ void Workspaces::onWindowTitleEvent(std::string const &payload) { } if (inserter.has_value()) { - Json::Value clientsData = gIPC->getSocket1JsonReply("clients"); + Json::Value clientsData = m_ipc.getSocket1JsonReply("clients"); std::string jsonWindowAddress = fmt::format("0x{}", payload); auto client = @@ -664,24 +663,24 @@ void Workspaces::registerOrphanWindow(WindowCreationPayload create_window_payloa } auto Workspaces::registerIpc() -> void { - gIPC->registerForIPC("workspace", this); - gIPC->registerForIPC("activespecial", this); - gIPC->registerForIPC("createworkspace", this); - gIPC->registerForIPC("destroyworkspace", this); - gIPC->registerForIPC("focusedmon", this); - gIPC->registerForIPC("moveworkspace", this); - gIPC->registerForIPC("renameworkspace", this); - gIPC->registerForIPC("openwindow", this); - gIPC->registerForIPC("closewindow", this); - gIPC->registerForIPC("movewindow", this); - gIPC->registerForIPC("urgent", this); - gIPC->registerForIPC("configreloaded", this); + m_ipc.registerForIPC("workspace", this); + m_ipc.registerForIPC("activespecial", this); + m_ipc.registerForIPC("createworkspace", this); + m_ipc.registerForIPC("destroyworkspace", this); + m_ipc.registerForIPC("focusedmon", this); + m_ipc.registerForIPC("moveworkspace", this); + m_ipc.registerForIPC("renameworkspace", this); + m_ipc.registerForIPC("openwindow", this); + m_ipc.registerForIPC("closewindow", this); + m_ipc.registerForIPC("movewindow", this); + m_ipc.registerForIPC("urgent", this); + m_ipc.registerForIPC("configreloaded", this); if (windowRewriteConfigUsesTitle()) { spdlog::info( "Registering for Hyprland's 'windowtitle' events because a user-defined window " "rewrite rule uses the 'title' field."); - gIPC->registerForIPC("windowtitle", this); + m_ipc.registerForIPC("windowtitle", this); } } @@ -716,7 +715,7 @@ void Workspaces::removeWorkspace(std::string const &name) { void Workspaces::setCurrentMonitorId() { // get monitor ID from name (used by persistent workspaces) m_monitorId = 0; - auto monitors = gIPC->getSocket1JsonReply("monitors"); + auto monitors = m_ipc.getSocket1JsonReply("monitors"); auto currentMonitor = std::find_if( monitors.begin(), monitors.end(), [this](const Json::Value &m) { return m["name"].asString() == m_bar.output->name; }); @@ -792,7 +791,7 @@ void Workspaces::sortWorkspaces() { } void Workspaces::setUrgentWorkspace(std::string const &windowaddress) { - const Json::Value clientsJson = gIPC->getSocket1JsonReply("clients"); + const Json::Value clientsJson = m_ipc.getSocket1JsonReply("clients"); int workspaceId = -1; for (Json::Value clientJson : clientsJson) { @@ -816,7 +815,7 @@ auto Workspaces::update() -> void { } void Workspaces::updateWindowCount() { - const Json::Value workspacesJson = gIPC->getSocket1JsonReply("workspaces"); + const Json::Value workspacesJson = m_ipc.getSocket1JsonReply("workspaces"); for (auto &workspace : m_workspaces) { auto workspaceJson = std::find_if(workspacesJson.begin(), workspacesJson.end(), [&](Json::Value const &x) { @@ -863,7 +862,7 @@ bool Workspaces::updateWindowsToCreate() { void Workspaces::updateWorkspaceStates() { const std::vector visibleWorkspaces = getVisibleWorkspaces(); - auto updatedWorkspaces = gIPC->getSocket1JsonReply("workspaces"); + auto updatedWorkspaces = m_ipc.getSocket1JsonReply("workspaces"); for (auto &workspace : m_workspaces) { workspace->setActive(workspace->name() == m_activeWorkspaceName || workspace->name() == m_activeSpecialWorkspaceName);