Idempotent bar show/hide via configurable user kill signals

This commit is contained in:
Martynas Maciulevičius
2025-02-09 13:05:36 +02:00
parent c336bc5466
commit aaea814217
5 changed files with 109 additions and 8 deletions

View File

@ -14,6 +14,7 @@
#include "AModule.hpp" #include "AModule.hpp"
#include "group.hpp" #include "group.hpp"
#include "util/kill_signal.hpp"
#include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h"
namespace waybar { namespace waybar {
@ -68,7 +69,11 @@ class Bar : public sigc::trackable {
void setMode(const std::string &mode); void setMode(const std::string &mode);
void setVisible(bool value); void setVisible(bool value);
void toggle(); void toggle();
void show();
void hide();
void handleSignal(int); void handleSignal(int);
util::KillSignalAction getOnSigusr1Action();
util::KillSignalAction getOnSigusr2Action();
struct waybar_output *output; struct waybar_output *output;
Json::Value config; Json::Value config;
@ -118,6 +123,9 @@ class Bar : public sigc::trackable {
std::unique_ptr<BarIpcClient> _ipc_client; std::unique_ptr<BarIpcClient> _ipc_client;
#endif #endif
std::vector<std::shared_ptr<waybar::AModule>> modules_all_; std::vector<std::shared_ptr<waybar::AModule>> modules_all_;
waybar::util::KillSignalAction onSigusr1;
waybar::util::KillSignalAction onSigusr2;
}; };
} // namespace waybar } // namespace waybar

View File

@ -0,0 +1,26 @@
#pragma once
#include <json/value.h>
#include <cstdint>
namespace waybar::util {
enum class KillSignalAction : std::uint8_t {
TOGGLE,
RELOAD,
SHOW,
HIDE,
NOOP,
};
const std::map<std::string, KillSignalAction> 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

View File

@ -8,6 +8,8 @@
#include "client.hpp" #include "client.hpp"
#include "factory.hpp" #include "factory.hpp"
#include "group.hpp" #include "group.hpp"
#include "util/enum.hpp"
#include "util/kill_signal.hpp"
#ifdef HAVE_SWAY #ifdef HAVE_SWAY
#include "modules/sway/bar.hpp" #include "modules/sway/bar.hpp"
@ -277,6 +279,30 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
} }
#endif #endif
waybar::util::EnumParser<util::KillSignalAction> 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(); setupWidgets();
window.show_all(); window.show_all();
@ -422,6 +448,8 @@ void waybar::Bar::setVisible(bool value) {
} }
void waybar::Bar::toggle() { setVisible(!visible); } 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 // Converting string to button code rn as to avoid doing it later
void waybar::Bar::setupAltFormatKeyForModule(const std::string& module_name) { 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, void waybar::Bar::getModules(const Factory& factory, const std::string& pos,
waybar::Group* group = nullptr) { waybar::Group* group = nullptr) {
auto module_list = group != nullptr ? config[pos]["modules"] : config[pos]; auto module_list = group != nullptr ? config[pos]["modules"] : config[pos];

View File

@ -7,8 +7,10 @@
#include <list> #include <list>
#include <mutex> #include <mutex>
#include "bar.hpp"
#include "client.hpp" #include "client.hpp"
#include "util/SafeSignal.hpp" #include "util/SafeSignal.hpp"
#include "util/backend_common.hpp"
std::mutex reap_mtx; std::mutex reap_mtx;
std::list<pid_t> reap; std::list<pid_t> reap;
@ -71,6 +73,45 @@ static void catchSignals(waybar::SafeSignal<int>& 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. // Must be called on the main thread.
// //
// If this signal should restart or close the bar, this function will write // 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) { for (auto& bar : waybar::Client::inst()->bars) {
bar->handleSignal(signum); bar->handleSignal(signum);
} }
return; return;
} }
switch (signum) { switch (signum) {
case SIGUSR1: case SIGUSR1:
spdlog::debug("Visibility toggled"); handleUserSignal(SIGUSR1, reload);
for (auto& bar : waybar::Client::inst()->bars) {
bar->toggle();
}
break; break;
case SIGUSR2: case SIGUSR2:
spdlog::info("Reloading..."); handleUserSignal(SIGUSR2, reload);
reload = true;
waybar::Client::inst()->reset();
break; break;
case SIGINT: case SIGINT:
spdlog::info("Quitting."); spdlog::info("Quitting.");

View File

@ -41,5 +41,6 @@ EnumType EnumParser<EnumType>::parseStringToEnum(const std::string& str,
// Explicit instantiations for specific EnumType types you intend to use // Explicit instantiations for specific EnumType types you intend to use
// Add explicit instantiations for all relevant EnumType types // Add explicit instantiations for all relevant EnumType types
template struct EnumParser<modules::hyprland::Workspaces::SortMethod>; template struct EnumParser<modules::hyprland::Workspaces::SortMethod>;
template struct EnumParser<util::KillSignalAction>;
} // namespace waybar::util } // namespace waybar::util