From aaea81421776eb3b5a97317948a42bd6e0c09290 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Maciulevi=C4=8Dius?= Date: Sun, 9 Feb 2025 13:05:36 +0200 Subject: [PATCH] Idempotent bar show/hide via configurable user kill signals --- include/bar.hpp | 8 ++++++ include/util/kill_signal.hpp | 26 ++++++++++++++++++ src/bar.cpp | 31 ++++++++++++++++++++++ src/main.cpp | 51 ++++++++++++++++++++++++++++++------ src/util/enum.cpp | 1 + 5 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 include/util/kill_signal.hpp diff --git a/include/bar.hpp b/include/bar.hpp index 9b407abf..c2dc0ae1 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -14,6 +14,7 @@ #include "AModule.hpp" #include "group.hpp" +#include "util/kill_signal.hpp" #include "xdg-output-unstable-v1-client-protocol.h" namespace waybar { @@ -68,7 +69,11 @@ class Bar : public sigc::trackable { void setMode(const std::string &mode); void setVisible(bool value); void toggle(); + void show(); + void hide(); void handleSignal(int); + util::KillSignalAction getOnSigusr1Action(); + util::KillSignalAction getOnSigusr2Action(); struct waybar_output *output; Json::Value config; @@ -118,6 +123,9 @@ class Bar : public sigc::trackable { std::unique_ptr _ipc_client; #endif std::vector> modules_all_; + + waybar::util::KillSignalAction onSigusr1; + waybar::util::KillSignalAction onSigusr2; }; } // namespace waybar diff --git a/include/util/kill_signal.hpp b/include/util/kill_signal.hpp new file mode 100644 index 00000000..26d156e9 --- /dev/null +++ b/include/util/kill_signal.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include + +namespace waybar::util { + +enum class KillSignalAction : std::uint8_t { + TOGGLE, + RELOAD, + SHOW, + HIDE, + NOOP, +}; +const std::map userKillSignalActions = { + {"TOGGLE", KillSignalAction::TOGGLE}, + {"RELOAD", KillSignalAction::RELOAD}, + {"SHOW", KillSignalAction::SHOW}, + {"HIDE", KillSignalAction::HIDE}, + {"NOOP", KillSignalAction::NOOP}}; + +const KillSignalAction SIGNALACTION_DEFAULT_SIGUSR1 = KillSignalAction::TOGGLE; +const KillSignalAction SIGNALACTION_DEFAULT_SIGUSR2 = KillSignalAction::RELOAD; + +}; // namespace waybar::util diff --git a/src/bar.cpp b/src/bar.cpp index 3c3ab690..5ca2ec04 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -8,6 +8,8 @@ #include "client.hpp" #include "factory.hpp" #include "group.hpp" +#include "util/enum.hpp" +#include "util/kill_signal.hpp" #ifdef HAVE_SWAY #include "modules/sway/bar.hpp" @@ -277,6 +279,30 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) } #endif + waybar::util::EnumParser m_signalActionEnumParser; + const auto& configSigusr1 = config["on_sigusr1"]; + if (configSigusr1.isString()) { + auto strSigusr1 = configSigusr1.asString(); + try { + onSigusr1 = + m_signalActionEnumParser.parseStringToEnum(strSigusr1, util::userKillSignalActions); + } catch (const std::invalid_argument& e) { + onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1; + spdlog::warn("Invalid string representation for on_sigusr1. Falling back to default mode."); + } + } + const auto& configSigusr2 = config["on_sigusr2"]; + if (configSigusr2.isString()) { + auto strSigusr2 = configSigusr2.asString(); + try { + onSigusr2 = + m_signalActionEnumParser.parseStringToEnum(strSigusr2, util::userKillSignalActions); + } catch (const std::invalid_argument& e) { + onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2; + spdlog::warn("Invalid string representation for on_sigusr2. Falling back to default mode."); + } + } + setupWidgets(); window.show_all(); @@ -422,6 +448,8 @@ void waybar::Bar::setVisible(bool value) { } void waybar::Bar::toggle() { setVisible(!visible); } +void waybar::Bar::show() { setVisible(true); } +void waybar::Bar::hide() { setVisible(false); } // Converting string to button code rn as to avoid doing it later void waybar::Bar::setupAltFormatKeyForModule(const std::string& module_name) { @@ -479,6 +507,9 @@ void waybar::Bar::handleSignal(int signal) { } } +waybar::util::KillSignalAction waybar::Bar::getOnSigusr1Action() { return this->onSigusr1; } +waybar::util::KillSignalAction waybar::Bar::getOnSigusr2Action() { return this->onSigusr2; } + void waybar::Bar::getModules(const Factory& factory, const std::string& pos, waybar::Group* group = nullptr) { auto module_list = group != nullptr ? config[pos]["modules"] : config[pos]; diff --git a/src/main.cpp b/src/main.cpp index 6e7650a9..7ac948b4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,8 +7,10 @@ #include #include +#include "bar.hpp" #include "client.hpp" #include "util/SafeSignal.hpp" +#include "util/backend_common.hpp" std::mutex reap_mtx; std::list reap; @@ -71,6 +73,45 @@ static void catchSignals(waybar::SafeSignal& signal_handler) { } } +waybar::util::KillSignalAction getActionForBar(waybar::Bar* bar, int signal) { + switch (signal) { + case SIGUSR1: + return bar->getOnSigusr1Action(); + case SIGUSR2: + return bar->getOnSigusr2Action(); + default: + return waybar::util::KillSignalAction::NOOP; + } +} + +void handleUserSignal(int signal, bool& reload) { + int i = 0; + for (auto& bar : waybar::Client::inst()->bars) { + switch (getActionForBar(bar.get(), signal)) { + case waybar::util::KillSignalAction::HIDE: + spdlog::debug("Visibility 'hide' for bar ", i); + bar->hide(); + break; + case waybar::util::KillSignalAction::SHOW: + spdlog::debug("Visibility 'show' for bar ", i); + bar->show(); + break; + case waybar::util::KillSignalAction::TOGGLE: + spdlog::debug("Visibility 'toggle' for bar ", i); + bar->toggle(); + break; + case waybar::util::KillSignalAction::RELOAD: + spdlog::info("Reloading..."); + reload = true; + waybar::Client::inst()->reset(); + return; + case waybar::util::KillSignalAction::NOOP: + break; + } + i++; + } +} + // Must be called on the main thread. // // If this signal should restart or close the bar, this function will write @@ -80,21 +121,15 @@ static void handleSignalMainThread(int signum, bool& reload) { for (auto& bar : waybar::Client::inst()->bars) { bar->handleSignal(signum); } - return; } switch (signum) { case SIGUSR1: - spdlog::debug("Visibility toggled"); - for (auto& bar : waybar::Client::inst()->bars) { - bar->toggle(); - } + handleUserSignal(SIGUSR1, reload); break; case SIGUSR2: - spdlog::info("Reloading..."); - reload = true; - waybar::Client::inst()->reset(); + handleUserSignal(SIGUSR2, reload); break; case SIGINT: spdlog::info("Quitting."); diff --git a/src/util/enum.cpp b/src/util/enum.cpp index dc3eae0c..1e28d66e 100644 --- a/src/util/enum.cpp +++ b/src/util/enum.cpp @@ -41,5 +41,6 @@ EnumType EnumParser::parseStringToEnum(const std::string& str, // Explicit instantiations for specific EnumType types you intend to use // Add explicit instantiations for all relevant EnumType types template struct EnumParser; +template struct EnumParser; } // namespace waybar::util