diff --git a/.gitignore b/.gitignore index 9fcd83ad..e980e122 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_Store *~ +vgcore.* *.swp packagecache /subprojects/fmt-4.1.0 diff --git a/.vscode/settings.json b/.vscode/settings.json index 3d99a247..d1dab300 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,14 @@ { "files.associations": { - "atomic": "cpp" + "atomic": "cpp", + "array": "cpp", + "hash_map": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "initializer_list": "cpp", + "string_view": "cpp", + "valarray": "cpp" } } \ No newline at end of file diff --git a/include/IModule.hpp b/include/IModule.hpp new file mode 100644 index 00000000..e0b4dc24 --- /dev/null +++ b/include/IModule.hpp @@ -0,0 +1,10 @@ +#pragma once + +namespace waybar { + class IModule { + public: + virtual ~IModule() {} + virtual auto update() -> void = 0; + virtual operator Gtk::Widget &() = 0; + }; +} diff --git a/include/bar.hpp b/include/bar.hpp index cc6ae2c5..ca59feeb 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include "wlr-layer-shell-unstable-v1-client-protocol.h" @@ -19,9 +20,11 @@ namespace waybar { auto setWidth(int) -> void; auto toggle() -> void; private: + auto _setupConfig() -> void; auto _setupWidgets() -> void; auto _setupCss() -> void; int _width = 10; + Json::Value _config; Glib::RefPtr _styleContext; Glib::RefPtr _cssProvider; }; diff --git a/include/client.hpp b/include/client.hpp index 9d4af23b..81eabd2e 100644 --- a/include/client.hpp +++ b/include/client.hpp @@ -21,7 +21,8 @@ namespace waybar { struct Client { uint32_t height = 30; - std::string css_file = "./resources/style.css"; + std::string cssFile = "./resources/style.css"; + std::string configFile = "./resources/config"; Gtk::Main gtk_main; diff --git a/include/factory.hpp b/include/factory.hpp new file mode 100644 index 00000000..d1ef5b28 --- /dev/null +++ b/include/factory.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include "modules/clock.hpp" +#include "modules/workspaces.hpp" +#include "modules/battery.hpp" +#include "modules/memory.hpp" +#include "modules/cpu.hpp" + +namespace waybar { + + class Factory { + public: + Factory(Bar &bar, Json::Value config); + IModule &makeModule(std::string name); + private: + Bar &_bar; + Json::Value _config; + }; + +} diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index 6047b7e0..83f6b737 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -6,12 +6,13 @@ #include #include #include "util/chrono.hpp" +#include "IModule.hpp" namespace waybar::modules { namespace fs = std::filesystem; - class Battery { + class Battery : public IModule { public: Battery(); auto update() -> void; diff --git a/include/modules/clock.hpp b/include/modules/clock.hpp index 59bc1ab1..ec6abedc 100644 --- a/include/modules/clock.hpp +++ b/include/modules/clock.hpp @@ -4,12 +4,14 @@ #include #include #include "util/chrono.hpp" +#include "IModule.hpp" namespace waybar::modules { - class Clock { + class Clock : public IModule { public: Clock(); + auto update() -> void; operator Gtk::Widget &(); private: Gtk::Label _label; diff --git a/include/modules/cpu.hpp b/include/modules/cpu.hpp index adf21b1b..e975ad56 100644 --- a/include/modules/cpu.hpp +++ b/include/modules/cpu.hpp @@ -5,12 +5,14 @@ #include #include #include "util/chrono.hpp" +#include "IModule.hpp" namespace waybar::modules { - class Cpu { + class Cpu : public IModule { public: Cpu(); + auto update() -> void; operator Gtk::Widget &(); private: Gtk::Label _label; diff --git a/include/modules/memory.hpp b/include/modules/memory.hpp index 367dfec5..1c40dac3 100644 --- a/include/modules/memory.hpp +++ b/include/modules/memory.hpp @@ -5,12 +5,14 @@ #include #include #include "util/chrono.hpp" +#include "IModule.hpp" namespace waybar::modules { - class Memory { + class Memory : public IModule { public: Memory(); + auto update() -> void; operator Gtk::Widget &(); private: Gtk::Label _label; diff --git a/include/modules/workspaces.hpp b/include/modules/workspaces.hpp index b596db97..71b2f6b6 100644 --- a/include/modules/workspaces.hpp +++ b/include/modules/workspaces.hpp @@ -1,16 +1,16 @@ #pragma once -#include #include #include "bar.hpp" #include "client.hpp" #include "util/chrono.hpp" +#include "IModule.hpp" namespace waybar::modules { - class WorkspaceSelector { + class Workspaces : public IModule { public: - WorkspaceSelector(waybar::Bar &bar); + Workspaces(waybar::Bar &bar); auto update() -> void; void updateThread(); operator Gtk::Widget &(); diff --git a/resources/config b/resources/config new file mode 100644 index 00000000..e29c97e1 --- /dev/null +++ b/resources/config @@ -0,0 +1,4 @@ +{ + "modules-left": ["workspaces"], + "modules-right": ["cpu", "memory", "battery", "clock"] +} diff --git a/src/bar.cpp b/src/bar.cpp index d8130c42..76bac20d 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -1,14 +1,11 @@ #include #include #include +#include #include "bar.hpp" #include "client.hpp" +#include "factory.hpp" #include "util/chrono.hpp" -#include "modules/clock.hpp" -#include "modules/workspaces.hpp" -#include "modules/battery.hpp" -#include "modules/memory.hpp" -#include "modules/cpu.hpp" static void handleGeometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, @@ -82,6 +79,7 @@ waybar::Bar::Bar(Client &client, std::unique_ptr &&p_output) wl_output_add_listener(*output, &outputListener, this); window.set_title("waybar"); window.set_decorated(false); + _setupConfig(); _setupCss(); _setupWidgets(); gtk_widget_realize(GTK_WIDGET(window.gobj())); @@ -100,19 +98,6 @@ waybar::Bar::Bar(Client &client, std::unique_ptr &&p_output) wl_surface_commit(surface); } -auto waybar::Bar::_setupCss() -> void -{ - _cssProvider = Gtk::CssProvider::create(); - _styleContext = Gtk::StyleContext::create(); - - // load our css file, wherever that may be hiding - if (_cssProvider->load_from_path(client.css_file)) { - Glib::RefPtr screen = window.get_screen(); - _styleContext->add_provider_for_screen(screen, _cssProvider, - GTK_STYLE_PROVIDER_PRIORITY_USER); - } -} - auto waybar::Bar::setWidth(int width) -> void { if (width == this->_width) return; @@ -132,6 +117,36 @@ auto waybar::Bar::toggle() -> void wl_surface_commit(surface); } +auto waybar::Bar::_setupConfig() -> void +{ + Json::Value root; + Json::CharReaderBuilder builder; + Json::CharReader* reader = builder.newCharReader(); + std::string err; + std::ifstream file(client.configFile); + if (!file.is_open()) + throw std::runtime_error("Can't open config file"); + std::string str((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); + bool res = reader->parse(str.c_str(), str.c_str() + str.size(), &_config, &err); + delete reader; + if (!res) + throw std::runtime_error(err); +} + +auto waybar::Bar::_setupCss() -> void +{ + _cssProvider = Gtk::CssProvider::create(); + _styleContext = Gtk::StyleContext::create(); + + // load our css file, wherever that may be hiding + if (_cssProvider->load_from_path(client.cssFile)) { + Glib::RefPtr screen = window.get_screen(); + _styleContext->add_provider_for_screen(screen, _cssProvider, + GTK_STYLE_PROVIDER_PRIORITY_USER); + } +} + auto waybar::Bar::_setupWidgets() -> void { auto &left = *Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 0)); @@ -145,16 +160,25 @@ auto waybar::Bar::_setupWidgets() -> void box1.pack_start(center, false, false); box1.pack_end(right, true, true); - auto &clock = *new waybar::modules::Clock(); - auto &workspace_selector = *new waybar::modules::WorkspaceSelector(*this); - auto &battery = *new waybar::modules::Battery(); - auto &memory = *new waybar::modules::Memory(); - auto &cpu = *new waybar::modules::Cpu(); + Factory factory(*this, _config); - left.pack_start(workspace_selector, false, true, 0); - // center.pack_start(workspace_selector, true, false, 10); - right.pack_end(clock, false, false, 0); - right.pack_end(battery, false, false, 0); - right.pack_end(memory, false, false, 0); - right.pack_end(cpu, false, false, 0); + if (_config["modules-left"]) { + for (auto name : _config["modules-left"]) { + auto &module = factory.makeModule(name.asString()); + left.pack_start(module, false, true, 0); + } + } + if (_config["modules-center"]) { + for (auto name : _config["modules-center"]) { + auto &module = factory.makeModule(name.asString()); + center.pack_start(module, true, false, 10); + } + } + if (_config["modules-right"]) { + std::reverse(_config["modules-right"].begin(), _config["modules-right"].end()); + for (auto name : _config["modules-right"]) { + auto &module = factory.makeModule(name.asString()); + right.pack_end(module, false, false, 0); + } + } } diff --git a/src/factory.cpp b/src/factory.cpp new file mode 100644 index 00000000..a181a6e8 --- /dev/null +++ b/src/factory.cpp @@ -0,0 +1,20 @@ +#include "factory.hpp" + +waybar::Factory::Factory(Bar &bar, Json::Value config) + : _bar(bar), _config(config) +{} + +waybar::IModule &waybar::Factory::makeModule(std::string name) +{ + if (name == "battery") + return *new waybar::modules::Battery(); + if (name == "workspaces") + return *new waybar::modules::Workspaces(_bar); + if (name == "memory") + return *new waybar::modules::Memory(); + if (name == "cpu") + return *new waybar::modules::Cpu(); + if (name == "clock") + return *new waybar::modules::Clock(); + throw std::runtime_error("Unknown module: " + name); +} diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 2fc32f86..c652e844 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -4,17 +4,22 @@ waybar::modules::Clock::Clock() { _label.get_style_context()->add_class("clock"); _thread = [this] { + update(); auto now = waybar::chrono::clock::now(); - auto t = std::time(nullptr); - auto localtime = std::localtime(&t); - _label.set_text( - fmt::format("{:02}:{:02}", localtime->tm_hour, localtime->tm_min)); auto timeout = std::chrono::floor(now + std::chrono::minutes(1)); _thread.sleep_until(timeout); }; }; +auto waybar::modules::Clock::update() -> void +{ + auto t = std::time(nullptr); + auto localtime = std::localtime(&t); + _label.set_text( + fmt::format("{:02}:{:02}", localtime->tm_hour, localtime->tm_min)); +} + waybar::modules::Clock::operator Gtk::Widget &() { return _label; } diff --git a/src/modules/cpu.cpp b/src/modules/cpu.cpp index dc7e7bbf..cde31287 100644 --- a/src/modules/cpu.cpp +++ b/src/modules/cpu.cpp @@ -5,16 +5,21 @@ waybar::modules::Cpu::Cpu() { _label.get_style_context()->add_class("cpu"); _thread = [this] { - struct sysinfo info; - if (!sysinfo(&info)) { - float f_load = 1.f / (1 << SI_LOAD_SHIFT); - _label.set_text(fmt::format("{:.{}f}% ", - info.loads[0] * f_load * 100 / get_nprocs(), 0)); - } + update(); _thread.sleep_for(chrono::seconds(10)); }; }; +auto waybar::modules::Cpu::update() -> void +{ + struct sysinfo info; + if (!sysinfo(&info)) { + float f_load = 1.f / (1 << SI_LOAD_SHIFT); + _label.set_text(fmt::format("{:.{}f}% ", + info.loads[0] * f_load * 100 / get_nprocs(), 0)); + } +} + waybar::modules::Cpu::operator Gtk::Widget &() { return _label; } diff --git a/src/modules/memory.cpp b/src/modules/memory.cpp index 36387b0d..104c973c 100644 --- a/src/modules/memory.cpp +++ b/src/modules/memory.cpp @@ -5,15 +5,20 @@ waybar::modules::Memory::Memory() { _label.get_style_context()->add_class("memory"); _thread = [this] { - struct sysinfo info; - if (!sysinfo(&info)) { - double available = (double)info.freeram / (double)info.totalram; - _label.set_text(fmt::format("{:.{}f}% ", available * 100, 0)); - } + update(); _thread.sleep_for(chrono::seconds(30)); }; }; +auto waybar::modules::Memory::update() -> void +{ + struct sysinfo info; + if (!sysinfo(&info)) { + double available = (double)info.freeram / (double)info.totalram; + _label.set_text(fmt::format("{:.{}f}% ", available * 100, 0)); + } +} + waybar::modules::Memory::operator Gtk::Widget &() { return _label; } diff --git a/src/modules/workspaces.cpp b/src/modules/workspaces.cpp index 53135899..340921b6 100644 --- a/src/modules/workspaces.cpp +++ b/src/modules/workspaces.cpp @@ -2,7 +2,7 @@ #include "ipc/client.hpp" static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) { - auto o = reinterpret_cast(data); + auto o = reinterpret_cast(data); if (o->thread) { delete o->thread; o->thread = nullptr; @@ -10,7 +10,7 @@ static void handle_idle(void *data, struct org_kde_kwin_idle_timeout *timer) { } static void handle_resume(void *data, struct org_kde_kwin_idle_timeout *timer) { - auto o = reinterpret_cast(data); + auto o = reinterpret_cast(data); if (!o->thread) { o->updateThread(); } @@ -21,7 +21,7 @@ static const struct org_kde_kwin_idle_timeout_listener idle_timer_listener = { .resumed = handle_resume, }; -waybar::modules::WorkspaceSelector::WorkspaceSelector(Bar &bar) +waybar::modules::Workspaces::Workspaces(Bar &bar) : thread(nullptr), _bar(bar), _box(Gtk::manage(new Gtk::Box)) { _box->get_style_context()->add_class("workspaces"); @@ -39,7 +39,7 @@ waybar::modules::WorkspaceSelector::WorkspaceSelector(Bar &bar) updateThread(); } -void waybar::modules::WorkspaceSelector::updateThread() +void waybar::modules::Workspaces::updateThread() { thread = new waybar::util::SleeperThread([this] { update(); @@ -47,7 +47,7 @@ void waybar::modules::WorkspaceSelector::updateThread() }); } -auto waybar::modules::WorkspaceSelector::update() -> void +auto waybar::modules::Workspaces::update() -> void { Json::Value workspaces = _getWorkspaces(); for (auto it = _buttons.begin(); it != _buttons.end(); ++it) { @@ -74,7 +74,7 @@ auto waybar::modules::WorkspaceSelector::update() -> void } } -void waybar::modules::WorkspaceSelector::_addWorkspace(Json::Value node) +void waybar::modules::Workspaces::_addWorkspace(Json::Value node) { auto pair = _buttons.emplace(node["num"].asInt(), node["name"].asString()); auto &button = pair.first->second; @@ -92,7 +92,7 @@ void waybar::modules::WorkspaceSelector::_addWorkspace(Json::Value node) button.show(); } -Json::Value waybar::modules::WorkspaceSelector::_getWorkspaces() +Json::Value waybar::modules::Workspaces::_getWorkspaces() { uint32_t len = 0; Json::Value root; @@ -110,6 +110,6 @@ Json::Value waybar::modules::WorkspaceSelector::_getWorkspaces() return root; } -waybar::modules::WorkspaceSelector::operator Gtk::Widget &() { +waybar::modules::Workspaces::operator Gtk::Widget &() { return *_box; }