refactor: format && better output management

This commit is contained in:
Alex
2019-04-18 17:43:16 +02:00
parent 817c42841b
commit 807ef32357
13 changed files with 479 additions and 475 deletions

View File

@ -1,25 +1,20 @@
#include "client.hpp"
#include "util/clara.hpp"
#include <fstream>
#include <iostream>
#include "util/clara.hpp"
#include "util/json.hpp"
waybar::Client::Client(int argc, char* argv[])
: gtk_app(Gtk::Application::create(argc, argv, "fr.arouillard.waybar")),
gdk_display(Gdk::Display::get_default())
{
if (!gdk_display) {
throw std::runtime_error("Can't find display");
}
if (!GDK_IS_WAYLAND_DISPLAY(gdk_display->gobj())) {
throw std::runtime_error("Bar need to run under Wayland");
}
wl_display = gdk_wayland_display_get_wl_display(gdk_display->gobj());
waybar::Client::Client() {}
waybar::Client *waybar::Client::inst() {
static Client *c = new Client();
return c;
}
const std::string waybar::Client::getValidPath(std::vector<std::string> paths)
{
const std::string waybar::Client::getValidPath(std::vector<std::string> paths) {
wordexp_t p;
for (const std::string &path: paths) {
for (const std::string &path : paths) {
if (wordexp(path.c_str(), &p, 0) == 0) {
if (access(*p.we_wordv, F_OK) == 0) {
std::string result = *p.we_wordv;
@ -33,77 +28,189 @@ const std::string waybar::Client::getValidPath(std::vector<std::string> paths)
return std::string();
}
void waybar::Client::handleGlobal(void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version)
{
auto o = static_cast<waybar::Client *>(data);
void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, uint32_t name,
const char *interface, uint32_t version) {
auto client = static_cast<Client *>(data);
if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
o->layer_shell = static_cast<struct zwlr_layer_shell_v1 *>(
wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, version));
client->layer_shell = static_cast<struct zwlr_layer_shell_v1 *>(
wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, version));
} else if (strcmp(interface, wl_output_interface.name) == 0) {
auto output = std::make_unique<struct wl_output *>();
*output = static_cast<struct wl_output *>(wl_registry_bind(registry, name,
&wl_output_interface, version));
if (o->xdg_output_manager != nullptr) {
o->bars.emplace_back(std::make_unique<Bar>(*o, std::move(output), name));
}
auto wl_output = static_cast<struct wl_output *>(
wl_registry_bind(registry, name, &wl_output_interface, version));
client->outputs_.emplace_back(new struct waybar_output({wl_output, "", name, nullptr}));
client->handleOutput(client->outputs_.back());
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
o->seat = static_cast<struct wl_seat *>(wl_registry_bind(registry, name,
&wl_seat_interface, version));
} else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0
&& version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
o->xdg_output_manager = static_cast<struct zxdg_output_manager_v1 *>(
wl_registry_bind(registry, name,
&zxdg_output_manager_v1_interface, ZXDG_OUTPUT_V1_NAME_SINCE_VERSION));
client->seat = static_cast<struct wl_seat *>(
wl_registry_bind(registry, name, &wl_seat_interface, version));
} else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 &&
version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
client->xdg_output_manager = static_cast<struct zxdg_output_manager_v1 *>(wl_registry_bind(
registry, name, &zxdg_output_manager_v1_interface, ZXDG_OUTPUT_V1_NAME_SINCE_VERSION));
} else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) {
o->idle_inhibit_manager = static_cast<struct zwp_idle_inhibit_manager_v1 *>(
wl_registry_bind(registry, name,
&zwp_idle_inhibit_manager_v1_interface, 1));
waybar::Client::inst()->idle_inhibit_manager =
static_cast<struct zwp_idle_inhibit_manager_v1 *>(
wl_registry_bind(registry, name, &zwp_idle_inhibit_manager_v1_interface, 1));
}
}
void waybar::Client::handleGlobalRemove(void* data,
struct wl_registry* /*registry*/, uint32_t name)
{
auto o = static_cast<waybar::Client *>(data);
for (auto it = o->bars.begin(); it != o->bars.end(); ++it) {
if ((*it)->wl_name == name) {
auto output_name = (*it)->output_name;
o->bars.erase(it);
void waybar::Client::handleGlobalRemove(void *data, struct wl_registry * /*registry*/,
uint32_t name) {
auto client = static_cast<Client *>(data);
for (auto it = client->bars.begin(); it != client->bars.end();) {
if ((*it)->output->wl_name == name) {
auto output_name = (*it)->output->name;
(*it)->window.close();
it = client->bars.erase(it);
std::cout << "Bar removed from output: " + output_name << std::endl;
break;
} else {
++it;
}
}
auto it = std::find_if(client->outputs_.begin(), client->outputs_.end(),
[&name](const auto &output) { return output->wl_name == name; });
if (it != client->outputs_.end()) {
zxdg_output_v1_destroy((*it)->xdg_output);
wl_output_destroy((*it)->output);
client->outputs_.erase(it);
}
}
void waybar::Client::setupConfigs(const std::string& config, const std::string& style)
{
config_file = config.empty() ? getValidPath({
"$XDG_CONFIG_HOME/waybar/config",
"$HOME/.config/waybar/config",
"$HOME/waybar/config",
"/etc/xdg/waybar/config",
"./resources/config",
}) : config;
css_file = style.empty() ? getValidPath({
"$XDG_CONFIG_HOME/waybar/style.css",
"$HOME/.config/waybar/style.css",
"$HOME/waybar/style.css",
"/etc/xdg/waybar/style.css",
"./resources/style.css",
}) : style;
if (css_file.empty() || config_file.empty()) {
void waybar::Client::handleOutput(std::unique_ptr<struct waybar_output> &output) {
static const struct zxdg_output_v1_listener xdgOutputListener = {
.logical_position = handleLogicalPosition,
.logical_size = handleLogicalSize,
.done = handleDone,
.name = handleName,
.description = handleDescription,
};
output->xdg_output = zxdg_output_manager_v1_get_xdg_output(xdg_output_manager, output->output);
zxdg_output_v1_add_listener(output->xdg_output, &xdgOutputListener, &output->wl_name);
}
void waybar::Client::handleLogicalPosition(void * /*data*/,
struct zxdg_output_v1 * /*zxdg_output_v1*/,
int32_t /*x*/, int32_t /*y*/) {
// Nothing here
}
void waybar::Client::handleLogicalSize(void * /*data*/, struct zxdg_output_v1 * /*zxdg_output_v1*/,
int32_t /*width*/, int32_t /*height*/) {
// Nothing here
}
void waybar::Client::handleDone(void * /*data*/, struct zxdg_output_v1 * /*zxdg_output_v1*/) {
// Nothing here
}
bool waybar::Client::isValidOutput(const Json::Value &config,
std::unique_ptr<struct waybar_output> &output) {
bool found = true;
if (config["output"].isArray()) {
bool in_array = false;
for (auto const &output_conf : config["output"]) {
if (output_conf.isString() && output_conf.asString() == output->name) {
in_array = true;
break;
}
}
found = in_array;
}
if (config["output"].isString() && config["output"].asString() != output->name) {
found = false;
}
return found;
}
void waybar::Client::handleName(void *data, struct zxdg_output_v1 * /*xdg_output*/,
const char *name) {
auto wl_name = *static_cast<uint32_t *>(data);
auto client = waybar::Client::inst();
auto it = std::find_if(client->outputs_.begin(), client->outputs_.end(),
[&wl_name](const auto &output) { return output->wl_name == wl_name; });
if (it == client->outputs_.end()) {
std::cerr << "Unable to find valid output" << std::endl;
return;
}
(*it)->name = name;
bool found = true;
if (client->config_.isArray()) {
bool in_array = false;
for (auto const &config : client->config_) {
if (config.isObject() && client->isValidOutput(config, *it)) {
in_array = true;
(*it)->config = config;
break;
}
}
found = in_array;
} else {
(*it)->config = client->config_;
found = client->isValidOutput((*it)->config, *it);
}
if (!found) {
wl_output_destroy((*it)->output);
zxdg_output_v1_destroy((*it)->xdg_output);
} else {
client->bars.emplace_back(std::make_unique<Bar>(it->get()));
Glib::RefPtr<Gdk::Screen> screen = client->bars.back()->window.get_screen();
client->style_context_->add_provider_for_screen(screen, client->css_provider_,
GTK_STYLE_PROVIDER_PRIORITY_USER);
}
}
void waybar::Client::handleDescription(void * /*data*/, struct zxdg_output_v1 * /*zxdg_output_v1*/,
const char * /*description*/) {
// Nothing here
}
void waybar::Client::setupConfigs(const std::string &config, const std::string &style) {
config_file_ = config.empty() ? getValidPath({
"$XDG_CONFIG_HOME/waybar/config",
"$HOME/.config/waybar/config",
"$HOME/waybar/config",
"/etc/xdg/waybar/config",
"./resources/config",
})
: config;
css_file_ = style.empty() ? getValidPath({
"$XDG_CONFIG_HOME/waybar/style.css",
"$HOME/.config/waybar/style.css",
"$HOME/waybar/style.css",
"/etc/xdg/waybar/style.css",
"./resources/style.css",
})
: style;
if (css_file_.empty() || config_file_.empty()) {
throw std::runtime_error("Missing required resources files");
}
std::cout << "Resources files: " + config_file + ", " + css_file << std::endl;
std::cout << "Resources files: " + config_file_ + ", " + css_file_ << std::endl;
}
void waybar::Client::bindInterfaces()
{
auto waybar::Client::setupConfig() -> void {
std::ifstream file(config_file_);
if (!file.is_open()) {
throw std::runtime_error("Can't open config file");
}
std::string str((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
util::JsonParser parser;
config_ = parser.parse(str);
}
auto waybar::Client::setupCss() -> void {
css_provider_ = Gtk::CssProvider::create();
style_context_ = Gtk::StyleContext::create();
// Load our css file, wherever that may be hiding
if (!css_provider_->load_from_path(css_file_)) {
throw std::runtime_error("Can't open style file");
}
}
void waybar::Client::bindInterfaces() {
registry = wl_display_get_registry(wl_display);
static const struct wl_registry_listener registry_listener = {
.global = handleGlobal,
.global_remove = handleGlobalRemove,
.global = handleGlobal,
.global_remove = handleGlobalRemove,
};
wl_registry_add_listener(registry, &registry_listener, this);
wl_display_roundtrip(wl_display);
@ -113,18 +220,26 @@ void waybar::Client::bindInterfaces()
wl_display_roundtrip(wl_display);
}
int waybar::Client::main(int argc, char* argv[])
{
int waybar::Client::main(int argc, char *argv[]) {
gtk_app = Gtk::Application::create(argc, argv, "fr.arouillard.waybar");
gdk_display = Gdk::Display::get_default();
if (!gdk_display) {
throw std::runtime_error("Can't find display");
}
if (!GDK_IS_WAYLAND_DISPLAY(gdk_display->gobj())) {
throw std::runtime_error("Bar need to run under Wayland");
}
wl_display = gdk_wayland_display_get_wl_display(gdk_display->gobj());
bool show_help = false;
bool show_version = false;
std::string config;
std::string style;
std::string bar_id;
auto cli = clara::detail::Help(show_help)
| clara::detail::Opt(show_version)["-v"]["--version"]("Show version")
| clara::detail::Opt(config, "config")["-c"]["--config"]("Config path")
| clara::detail::Opt(style, "style")["-s"]["--style"]("Style path")
| clara::detail::Opt(bar_id, "id")["-b"]["--bar"]("Bar id");
auto cli = clara::detail::Help(show_help) |
clara::detail::Opt(show_version)["-v"]["--version"]("Show version") |
clara::detail::Opt(config, "config")["-c"]["--config"]("Config path") |
clara::detail::Opt(style, "style")["-s"]["--style"]("Style path") |
clara::detail::Opt(bar_id, "id")["-b"]["--bar"]("Bar id");
auto res = cli.parse(clara::detail::Args(argc, argv));
if (!res) {
std::cerr << "Error in command line: " << res.errorMessage() << std::endl;
@ -139,6 +254,8 @@ int waybar::Client::main(int argc, char* argv[])
return 0;
}
setupConfigs(config, style);
setupConfig();
setupCss();
bindInterfaces();
gtk_app->hold();
gtk_app->run();