Show bar if a workspace becomes urgent

Add a second reason to show the bar besides visible by modifier.
Update the visibility based on changes in the workspace urgency.
Check all workspaces for urgency and keep the bar visible if at least
one has an urgency hint.
This commit is contained in:
Tobias Wölfel 2022-04-06 15:53:49 +02:00
parent d87cf8a8f2
commit e3700b924e
2 changed files with 69 additions and 14 deletions

View File

@ -30,8 +30,10 @@ class BarIpcClient {
private: private:
void onInitialConfig(const struct Ipc::ipc_response& res); void onInitialConfig(const struct Ipc::ipc_response& res);
void onIpcEvent(const struct Ipc::ipc_response&); void onIpcEvent(const struct Ipc::ipc_response&);
void onCmd(const struct Ipc::ipc_response&);
void onConfigUpdate(const swaybar_config& config); void onConfigUpdate(const swaybar_config& config);
void onVisibilityUpdate(bool visible_by_modifier); void onVisibilityUpdate(bool visible_by_modifier);
void onUrgencyUpdate(bool visible_by_urgency);
void update(); void update();
Bar& bar_; Bar& bar_;
@ -40,8 +42,10 @@ class BarIpcClient {
swaybar_config bar_config_; swaybar_config bar_config_;
bool visible_by_modifier_ = false; bool visible_by_modifier_ = false;
bool visible_by_urgency_ = false;
SafeSignal<bool> signal_visible_; SafeSignal<bool> signal_visible_;
SafeSignal<bool> signal_urgency_;
SafeSignal<swaybar_config> signal_config_; SafeSignal<swaybar_config> signal_config_;
}; };

View File

@ -21,9 +21,11 @@ BarIpcClient::BarIpcClient(waybar::Bar& bar) : bar_{bar} {
signal_config_.connect(sigc::mem_fun(*this, &BarIpcClient::onConfigUpdate)); signal_config_.connect(sigc::mem_fun(*this, &BarIpcClient::onConfigUpdate));
signal_visible_.connect(sigc::mem_fun(*this, &BarIpcClient::onVisibilityUpdate)); signal_visible_.connect(sigc::mem_fun(*this, &BarIpcClient::onVisibilityUpdate));
signal_urgency_.connect(sigc::mem_fun(*this, &BarIpcClient::onUrgencyUpdate));
ipc_.subscribe(R"(["bar_state_update", "barconfig_update"])"); ipc_.subscribe(R"(["bar_state_update", "barconfig_update", "workspace"])");
ipc_.signal_event.connect(sigc::mem_fun(*this, &BarIpcClient::onIpcEvent)); ipc_.signal_event.connect(sigc::mem_fun(*this, &BarIpcClient::onIpcEvent));
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &BarIpcClient::onCmd));
// Launch worker // Launch worker
ipc_.setWorker([this] { ipc_.setWorker([this] {
try { try {
@ -61,23 +63,66 @@ void BarIpcClient::onInitialConfig(const struct Ipc::ipc_response& res) {
void BarIpcClient::onIpcEvent(const struct Ipc::ipc_response& res) { void BarIpcClient::onIpcEvent(const struct Ipc::ipc_response& res) {
try { try {
auto payload = parser_.parse(res.payload); auto payload = parser_.parse(res.payload);
if (auto id = payload["id"]; id.isString() && id.asString() != bar_.bar_id) { switch (res.type) {
spdlog::trace("swaybar ipc: ignore event for {}", id.asString()); case IPC_EVENT_WORKSPACE:
return; if (payload.isMember("change")) {
} // only check and send signal if the workspace update reason was because of a urgent
if (payload.isMember("visible_by_modifier")) { // change
// visibility change for hidden bar if (payload["change"] == "urgent") {
signal_visible_(payload["visible_by_modifier"].asBool()); auto urgent = payload["current"]["urgent"];
} else { if (urgent.asBool()) {
// configuration update // Event for a new urgency, update the visibly
auto config = parseConfig(payload); signal_urgency_(true);
signal_config_(std::move(config)); } else if (!urgent.asBool() && visible_by_urgency_) {
// Event clearing an urgency, bar is visible, check if another workspace still has
// the urgency hint set
ipc_.sendCmd(IPC_GET_WORKSPACES);
}
}
}
break;
case IPC_EVENT_BAR_STATE_UPDATE:
case IPC_EVENT_BARCONFIG_UPDATE:
if (auto id = payload["id"]; id.isString() && id.asString() != bar_.bar_id) {
spdlog::trace("swaybar ipc: ignore event for {}", id.asString());
return;
}
if (payload.isMember("visible_by_modifier")) {
// visibility change for hidden bar
signal_visible_(payload["visible_by_modifier"].asBool());
} else {
// configuration update
auto config = parseConfig(payload);
signal_config_(std::move(config));
}
break;
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {
spdlog::error("BarIpcClient::onEvent {}", e.what()); spdlog::error("BarIpcClient::onEvent {}", e.what());
} }
} }
void BarIpcClient::onCmd(const struct Ipc::ipc_response& res) {
if (res.type == IPC_GET_WORKSPACES) {
try {
auto payload = parser_.parse(res.payload);
for (auto& ws : payload) {
if (ws["urgent"].asBool()) {
spdlog::debug("Found workspace {} with urgency set. Stopping search.", ws["name"]);
// Found one workspace with urgency set, signal bar visibility
signal_urgency_(true);
return;
}
}
// Command to get workspaces was sent after a change in workspaces was based on "urgent",
// if no workspace has this flag set to true, all flags must be cleared.
signal_urgency_(false);
} catch (const std::exception& e) {
spdlog::error("Bar: {}", e.what());
}
}
}
void BarIpcClient::onConfigUpdate(const swaybar_config& config) { void BarIpcClient::onConfigUpdate(const swaybar_config& config) {
spdlog::info("config update for {}: id {}, mode {}, hidden_state {}", bar_.bar_id, config.id, spdlog::info("config update for {}: id {}, mode {}, hidden_state {}", bar_.bar_id, config.id,
config.mode, config.hidden_state); config.mode, config.hidden_state);
@ -86,13 +131,19 @@ void BarIpcClient::onConfigUpdate(const swaybar_config& config) {
} }
void BarIpcClient::onVisibilityUpdate(bool visible_by_modifier) { void BarIpcClient::onVisibilityUpdate(bool visible_by_modifier) {
spdlog::debug("visiblity update for {}: {}", bar_.bar_id, visible_by_modifier); spdlog::debug("visibility update for {}: {}", bar_.bar_id, visible_by_modifier);
visible_by_modifier_ = visible_by_modifier; visible_by_modifier_ = visible_by_modifier;
update(); update();
} }
void BarIpcClient::onUrgencyUpdate(bool visible_by_urgency) {
spdlog::debug("urgency update for {}: {}", bar_.bar_id, visible_by_urgency);
visible_by_urgency_ = visible_by_urgency;
update();
}
void BarIpcClient::update() { void BarIpcClient::update() {
bool visible = visible_by_modifier_; bool visible = visible_by_modifier_ || visible_by_urgency_;
if (bar_config_.mode == "invisible") { if (bar_config_.mode == "invisible") {
visible = false; visible = false;
} else if (bar_config_.mode != "hide" || bar_config_.hidden_state != "hide") { } else if (bar_config_.mode != "hide" || bar_config_.hidden_state != "hide") {