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 1/6] 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 From 3c7a9bf43214c1e544fe3bd851a4f91a7ac579b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Maciulevi=C4=8Dius?= Date: Sat, 22 Feb 2025 09:28:32 +0200 Subject: [PATCH 2/6] Documentation for sigusr1 and sigusr2 config --- man/waybar.5.scd.in | 39 +++++++++++++++++++++++++++++++++++++-- src/bar.cpp | 6 ++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/man/waybar.5.scd.in b/man/waybar.5.scd.in index 6ca0aa99..002cb50b 100644 --- a/man/waybar.5.scd.in +++ b/man/waybar.5.scd.in @@ -151,6 +151,20 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles( default: *false* ++ Option to enable reloading the css style if a modification is detected on the style sheet file or any imported css files. +*on_sigusr1* ++ + typeof: string ++ + default: *toggle* ++ + Action that is performed when receiving SIGUSR1 kill signal. ++ + Possible values: *show*, *hide*, *toggle*, *reload*, *noop*. ++ + Default value: *toggle*. + +*on_sigusr2* ++ + typeof: string ++ + default: *reload* ++ + Action that is performed when receiving SIGUSR2 kill signal. ++ + Possible values: *show*, *hide*, *toggle*, *reload*, *noop*. ++ + Default value: *reload*. + # MODULE FORMAT You can use PangoMarkupFormat (See https://developer.gnome.org/pango/stable/PangoMarkupFormat.html#PangoMarkupFormat). @@ -206,14 +220,35 @@ A minimal *config* file could look like this: Waybar accepts the following signals: *SIGUSR1* - Toggles the bar visibility (hides if shown, shows if hidden) + By default toggles the bar visibility (hides if shown, shows if hidden) *SIGUSR2* - Reloads (resets) the bar + By default reloads (resets) the bar *SIGINT* Quits the bar For example, to toggle the bar programmatically, you can invoke `killall -SIGUSR1 waybar`. +## User signal configuration + +Config parameters `on_sigusr1` and `on_sigusr2` change what happens when bars receive +`SIGUSR1` and `SIGUSR2` signals. + +This means that commands `killall -SIGUSR1 waybar` and `killall -SIGUSR2 waybar` +can perform user-configured action. + +It also means that if an external script has the PID of the bar then it can +perform more complex `show`/`hide`/`reload` logic for each instance of Waybar. +One can find the PID e.g. by doing `pgrep -a waybar` which could then match +by config name or other parameters. + +### Kill parameter meanings + +*show* Switches state to visible (per bar). +*hide* Switches state to hidden (per bar). +*toggle* Switches state between visible and hidden (per bar). +*reload* Reloads whole waybar. +*noop* Does nothing when the kill signal is received. + # MULTI OUTPUT CONFIGURATION ## Limit a configuration to some outputs diff --git a/src/bar.cpp b/src/bar.cpp index 5ca2ec04..6e6e76df 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -288,7 +288,8 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) 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."); + spdlog::warn( + "Invalid string representation for on_sigusr1. Falling back to default mode (toggle)."); } } const auto& configSigusr2 = config["on_sigusr2"]; @@ -299,7 +300,8 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) 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."); + spdlog::warn( + "Invalid string representation for on_sigusr2. Falling back to default mode (reload)."); } } From 125b59e23bc5b8520ad903829afaa13a50d01ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Maciulevi=C4=8Dius?= Date: Sun, 2 Mar 2025 19:08:37 +0200 Subject: [PATCH 3/6] Add more details on how 'reload' works in signals --- man/waybar.5.scd.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/waybar.5.scd.in b/man/waybar.5.scd.in index 002cb50b..1fca6321 100644 --- a/man/waybar.5.scd.in +++ b/man/waybar.5.scd.in @@ -246,7 +246,8 @@ by config name or other parameters. *show* Switches state to visible (per bar). *hide* Switches state to hidden (per bar). *toggle* Switches state between visible and hidden (per bar). -*reload* Reloads whole waybar. +*reload* Reloads all waybars of current waybar process (basically equivalent to +restarting with updated config which sets initial visibility values). *noop* Does nothing when the kill signal is received. # MULTI OUTPUT CONFIGURATION From 7463be9b6a3777220377632cafb0447adb0f35cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Maciulevi=C4=8Dius?= Date: Fri, 7 Mar 2025 07:45:11 +0200 Subject: [PATCH 4/6] Fix initial null configuration; Fix doc compilation errors --- include/bar.hpp | 4 ++-- man/waybar.5.scd.in | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/bar.hpp b/include/bar.hpp index c2dc0ae1..9953b1f5 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -124,8 +124,8 @@ class Bar : public sigc::trackable { #endif std::vector> modules_all_; - waybar::util::KillSignalAction onSigusr1; - waybar::util::KillSignalAction onSigusr2; + waybar::util::KillSignalAction onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1; + waybar::util::KillSignalAction onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2; }; } // namespace waybar diff --git a/man/waybar.5.scd.in b/man/waybar.5.scd.in index 1fca6321..a2212f04 100644 --- a/man/waybar.5.scd.in +++ b/man/waybar.5.scd.in @@ -230,8 +230,8 @@ For example, to toggle the bar programmatically, you can invoke `killall -SIGUSR ## User signal configuration -Config parameters `on_sigusr1` and `on_sigusr2` change what happens when bars receive -`SIGUSR1` and `SIGUSR2` signals. +Config parameters *on_sigusr1* and *on_sigusr2* change what happens when bars receive +*SIGUSR1* and *SIGUSR2* signals. This means that commands `killall -SIGUSR1 waybar` and `killall -SIGUSR2 waybar` can perform user-configured action. @@ -241,7 +241,7 @@ perform more complex `show`/`hide`/`reload` logic for each instance of Waybar. One can find the PID e.g. by doing `pgrep -a waybar` which could then match by config name or other parameters. -### Kill parameter meanings +## Kill parameter meanings *show* Switches state to visible (per bar). *hide* Switches state to hidden (per bar). From b7ff47fb053fb04c4e3bba4b235084dfded3d171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Maciulevi=C4=8Dius?= Date: Thu, 26 Jun 2025 18:41:23 +0300 Subject: [PATCH 5/6] User kill signal config keys: Use underscore instead of dash --- man/waybar.5.scd.in | 6 +++--- src/bar.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/man/waybar.5.scd.in b/man/waybar.5.scd.in index a2212f04..566f7dc5 100644 --- a/man/waybar.5.scd.in +++ b/man/waybar.5.scd.in @@ -151,14 +151,14 @@ The visual display elements for waybar use a CSS stylesheet, see *waybar-styles( default: *false* ++ Option to enable reloading the css style if a modification is detected on the style sheet file or any imported css files. -*on_sigusr1* ++ +*on-sigusr1* ++ typeof: string ++ default: *toggle* ++ Action that is performed when receiving SIGUSR1 kill signal. ++ Possible values: *show*, *hide*, *toggle*, *reload*, *noop*. ++ Default value: *toggle*. -*on_sigusr2* ++ +*on-sigusr2* ++ typeof: string ++ default: *reload* ++ Action that is performed when receiving SIGUSR2 kill signal. ++ @@ -230,7 +230,7 @@ For example, to toggle the bar programmatically, you can invoke `killall -SIGUSR ## User signal configuration -Config parameters *on_sigusr1* and *on_sigusr2* change what happens when bars receive +Config parameters *on-sigusr1* and *on-sigusr2* change what happens when bars receive *SIGUSR1* and *SIGUSR2* signals. This means that commands `killall -SIGUSR1 waybar` and `killall -SIGUSR2 waybar` diff --git a/src/bar.cpp b/src/bar.cpp index 6e6e76df..bb91aa01 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -280,7 +280,7 @@ 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"]; + const auto& configSigusr1 = config["on-sigusr1"]; if (configSigusr1.isString()) { auto strSigusr1 = configSigusr1.asString(); try { @@ -289,10 +289,10 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) } catch (const std::invalid_argument& e) { onSigusr1 = util::SIGNALACTION_DEFAULT_SIGUSR1; spdlog::warn( - "Invalid string representation for on_sigusr1. Falling back to default mode (toggle)."); + "Invalid string representation for on-sigusr1. Falling back to default mode (toggle)."); } } - const auto& configSigusr2 = config["on_sigusr2"]; + const auto& configSigusr2 = config["on-sigusr2"]; if (configSigusr2.isString()) { auto strSigusr2 = configSigusr2.asString(); try { @@ -301,7 +301,7 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config) } catch (const std::invalid_argument& e) { onSigusr2 = util::SIGNALACTION_DEFAULT_SIGUSR2; spdlog::warn( - "Invalid string representation for on_sigusr2. Falling back to default mode (reload)."); + "Invalid string representation for on-sigusr2. Falling back to default mode (reload)."); } } From c8dc3e702402a936654d600b30727522eac8cb2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Maciulevi=C4=8Dius?= Date: Thu, 26 Jun 2025 21:20:18 +0300 Subject: [PATCH 6/6] Remove unused import --- src/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 7ac948b4..021f8e1a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,7 +10,6 @@ #include "bar.hpp" #include "client.hpp" #include "util/SafeSignal.hpp" -#include "util/backend_common.hpp" std::mutex reap_mtx; std::list reap;