Skip to content

Commit

Permalink
feat(swaybar-ipc): add swaybar IPC client
Browse files Browse the repository at this point in the history
  • Loading branch information
alebastr committed Sep 15, 2021
1 parent 8cff64e commit 4d53677
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 0 deletions.
9 changes: 9 additions & 0 deletions include/client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@
#include <gdk/gdkwayland.h>
#include <wayland-client.h>

#include <optional>

#include "bar.hpp"
#include "config.hpp"
#ifdef HAVE_SWAY
#include "modules/sway/bar.hpp"
#endif

struct zwlr_layer_shell_v1;
struct zwp_idle_inhibitor_v1;
Expand Down Expand Up @@ -52,6 +57,10 @@ class Client {
Glib::RefPtr<Gtk::StyleContext> style_context_;
Glib::RefPtr<Gtk::CssProvider> css_provider_;
std::list<struct waybar_output> outputs_;
#ifdef HAVE_SWAY
using BarIpcClient = waybar::modules::sway::BarIpcClient;
std::optional<BarIpcClient> bar_ipc_client_;
#endif
};

} // namespace waybar
46 changes: 46 additions & 0 deletions include/modules/sway/bar.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once
#include <string>

#include "modules/sway/ipc/client.hpp"
#include "util/SafeSignal.hpp"
#include "util/json.hpp"

namespace waybar {

class Client;

namespace modules::sway {

/*
* Supported subset of i3/sway IPC barconfig object
*/
struct swaybar_config {
std::string id;
std::string mode;
std::string position;
};

/**
* swaybar IPC client
*/
class BarIpcClient {
public:
BarIpcClient(waybar::Client& client, const std::string& bar_id, bool get_initial_config = true);

private:
void onInitialConfig(const struct Ipc::ipc_response& res);
void onIpcEvent(const struct Ipc::ipc_response&);
void onConfigUpdate(const swaybar_config& config);
void onVisibilityUpdate(bool visible_by_modifier);

const Client& client_;
const std::string bar_id_;
util::JsonParser parser_;
Ipc ipc_;

SafeSignal<bool> signal_visible_;
SafeSignal<swaybar_config> signal_config_;
};

} // namespace modules::sway
} // namespace waybar
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ endif
add_project_arguments('-DHAVE_SWAY', language: 'cpp')
src_files += [
'src/modules/sway/ipc/client.cpp',
'src/modules/sway/bar.cpp',
'src/modules/sway/mode.cpp',
'src/modules/sway/language.cpp',
'src/modules/sway/window.cpp',
Expand Down
10 changes: 10 additions & 0 deletions src/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,16 @@ int waybar::Client::main(int argc, char *argv[]) {
config.load(config_opt);
auto css_file = getStyle(style_opt);
setupCss(css_file);
#ifdef HAVE_SWAY
// FIXME: temporary hack
// Need to do something better about the configuration and conditions:
// * add config flag to disable swaybar ipc client
// * read initial configuration from sway
// * merge initial configuration from sway with json config before creating bars
if (!bar_id.empty() && modules::sway::Ipc::available()) {
bar_ipc_client_.emplace(*this, bar_id, true);
}
#endif
bindInterfaces();
gtk_app->hold();
gtk_app->run();
Expand Down
92 changes: 92 additions & 0 deletions src/modules/sway/bar.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#include "modules/sway/bar.hpp"

#include <fmt/ostream.h>
#include <spdlog/spdlog.h>

#include "client.hpp"
#include "modules/sway/ipc/ipc.hpp"

namespace waybar::modules::sway {

BarIpcClient::BarIpcClient(waybar::Client& client, const std::string& bar_id,
bool get_initial_config)
: client_{client}, bar_id_{bar_id} {
if (get_initial_config) {
sigc::connection handle =
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &BarIpcClient::onInitialConfig));
ipc_.sendCmd(IPC_GET_BAR_CONFIG, bar_id);

handle.disconnect();
}

signal_config_.connect(sigc::mem_fun(*this, &BarIpcClient::onConfigUpdate));
signal_visible_.connect(sigc::mem_fun(*this, &BarIpcClient::onVisibilityUpdate));

ipc_.subscribe(R"(["bar_state_update", "barconfig_update"])");
ipc_.signal_event.connect(sigc::mem_fun(*this, &BarIpcClient::onIpcEvent));
// Launch worker
ipc_.setWorker([this] {
try {
ipc_.handleEvent();
} catch (const std::exception& e) {
spdlog::error("BarIpcClient::handleEvent {}", e.what());
}
});
}

struct swaybar_config parseConfig(const Json::Value& payload) {
swaybar_config conf;
if (auto id = payload["id"]; id.isString()) {
conf.id = id.asString();
}
if (auto mode = payload["mode"]; mode.isString()) {
conf.mode = mode.asString();
}
if (auto position = payload["position"]; position.isString()) {
conf.position = position.asString();
}
return conf;
}

void BarIpcClient::onInitialConfig(const struct Ipc::ipc_response& res) {
try {
auto payload = parser_.parse(res.payload);
auto config = parseConfig(payload);
spdlog::debug("swaybar ipc: initial config: {}", payload);
onConfigUpdate(config);
} catch (const std::exception& e) {
spdlog::error("BarIpcClient::onInitialConfig {}", e.what());
}
}

void BarIpcClient::onIpcEvent(const struct Ipc::ipc_response& res) {
try {
auto payload = parser_.parse(res.payload);
if (auto id = payload["id"]; id.isString() && id.asString() != 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_(config);
}
} catch (const std::exception& e) {
spdlog::error("BarIpcClient::onEvent {}", e.what());
}
}

void BarIpcClient::onConfigUpdate(const swaybar_config& config) {
spdlog::info("config update: {} {} {}", config.id, config.mode, config.position);
// TODO: pass config to bars
}

void BarIpcClient::onVisibilityUpdate(bool visible_by_modifier) {
spdlog::trace("visiblity update: {}", visible_by_modifier);
// TODO: pass visibility to bars
}

} // namespace waybar::modules::sway

0 comments on commit 4d53677

Please sign in to comment.