diff --git a/include/factory.hpp b/include/factory.hpp index b572a573..971f14df 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -2,7 +2,8 @@ #include #include "modules/clock.hpp" -#include "modules/workspaces.hpp" +#include "modules/sway/workspaces.hpp" +#include "modules/sway/window.hpp" #include "modules/battery.hpp" #include "modules/memory.hpp" #include "modules/cpu.hpp" diff --git a/include/ipc/client.hpp b/include/modules/sway/ipc/client.hpp similarity index 100% rename from include/ipc/client.hpp rename to include/modules/sway/ipc/client.hpp diff --git a/include/ipc/ipc.hpp b/include/modules/sway/ipc/ipc.hpp similarity index 100% rename from include/ipc/ipc.hpp rename to include/modules/sway/ipc/ipc.hpp diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp new file mode 100644 index 00000000..a4892002 --- /dev/null +++ b/include/modules/sway/window.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include "bar.hpp" +#include "client.hpp" +#include "util/chrono.hpp" +#include "util/json.hpp" +#include "IModule.hpp" + +namespace waybar::modules::sway { + + class Window : public IModule { + public: + Window(waybar::Bar &bar, Json::Value config); + auto update() -> void; + operator Gtk::Widget &(); + private: + std::string _getFocusedNode(Json::Value nodes); + void _getFocusedWindow(); + Bar &_bar; + Json::Value _config; + waybar::util::SleeperThread _thread; + Gtk::Label _label; + util::JsonParser _parser; + int _ipcfd; + int _ipcEventfd; + std::string _window; + }; + +} diff --git a/include/modules/workspaces.hpp b/include/modules/sway/workspaces.hpp similarity index 90% rename from include/modules/workspaces.hpp rename to include/modules/sway/workspaces.hpp index 8c1d08e9..33d3fadb 100644 --- a/include/modules/workspaces.hpp +++ b/include/modules/sway/workspaces.hpp @@ -7,7 +7,7 @@ #include "util/json.hpp" #include "IModule.hpp" -namespace waybar::modules { +namespace waybar::modules::sway { class Workspaces : public IModule { public: @@ -17,7 +17,6 @@ namespace waybar::modules { private: void _addWorkspace(Json::Value node); std::string _getIcon(std::string name); - Json::Value _getWorkspaces(const std::string data); bool _handleScroll(GdkEventScroll *e); int _getPrevWorkspace(); int _getNextWorkspace(); diff --git a/resources/config b/resources/config index a86b908e..d845d851 100644 --- a/resources/config +++ b/resources/config @@ -4,7 +4,8 @@ // "height": 30, // Waybar height // "width": 1280, // Waybar width // Choose the order of the modules - "modules-left": ["workspaces", "custom/spotify"], + "modules-left": ["sway/workspaces", "custom/spotify"], + "modules-center": ["sway/window"], "modules-right": ["pulseaudio", "network", "cpu", "memory", "battery", "clock"], // Modules configuration "workspaces": { diff --git a/src/factory.cpp b/src/factory.cpp index cce540f9..540bc199 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -9,8 +9,10 @@ waybar::IModule *waybar::Factory::makeModule(std::string name) try { if (name == "battery") return new waybar::modules::Battery(_config[name]); - if (name == "workspaces") - return new waybar::modules::Workspaces(_bar, _config[name]); + if (name == "sway/workspaces") + return new waybar::modules::sway::Workspaces(_bar, _config[name]); + if (name == "sway/window") + return new waybar::modules::sway::Window(_bar, _config[name]); if (name == "memory") return new waybar::modules::Memory(_config[name]); if (name == "cpu") diff --git a/src/ipc/client.cpp b/src/modules/sway/ipc/client.cpp similarity index 98% rename from src/ipc/client.cpp rename to src/modules/sway/ipc/client.cpp index ab4a2761..f6485cfb 100644 --- a/src/ipc/client.cpp +++ b/src/modules/sway/ipc/client.cpp @@ -3,7 +3,7 @@ #include #include #include -#include "ipc/client.hpp" +#include "modules/sway/ipc/client.hpp" static const char ipc_magic[] = {'i', '3', '-', 'i', 'p', 'c'}; static const size_t ipc_header_size = sizeof(ipc_magic)+8; diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp new file mode 100644 index 00000000..f49e622f --- /dev/null +++ b/src/modules/sway/window.cpp @@ -0,0 +1,66 @@ +#include "modules/sway/window.hpp" +#include "modules/sway/ipc/client.hpp" + +waybar::modules::sway::Window::Window(Bar &bar, Json::Value config) + : _bar(bar), _config(config) +{ + _label.set_name("window"); + std::string socketPath = get_socketpath(); + _ipcfd = ipc_open_socket(socketPath); + _ipcEventfd = ipc_open_socket(socketPath); + const char *subscribe = "[ \"window\" ]"; + uint32_t len = strlen(subscribe); + ipc_single_command(_ipcEventfd, IPC_SUBSCRIBE, subscribe, &len); + _getFocusedWindow(); + _thread = [this] { + try { + if (_bar.outputName.empty()) { + // Wait for the name of the output + while (_bar.outputName.empty()) + _thread.sleep_for(chrono::milliseconds(150)); + } + auto res = ipc_recv_response(_ipcEventfd); + auto parsed = _parser.parse(res.payload); + if (parsed["change"] != "focus") + return; + _window = parsed["container"]["name"].asString(); + Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Window::update)); + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + } + }; +} + +auto waybar::modules::sway::Window::update() -> void +{ + _label.set_text(_window); +} + +std::string waybar::modules::sway::Window::_getFocusedNode(Json::Value nodes) +{ + for (auto &node : nodes) { + if (node["focused"].asBool()) + return node["name"].asString(); + auto res = _getFocusedNode(node["nodes"]); + if (!res.empty()) + return res; + } + return std::string(); +} + +void waybar::modules::sway::Window::_getFocusedWindow() +{ + try { + uint32_t len = 0; + auto res = ipc_single_command(_ipcfd, IPC_GET_TREE, nullptr, &len); + auto parsed = _parser.parse(res); + _window = _getFocusedNode(parsed["nodes"]); + Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Window::update)); + } catch (const std::exception &e) { + std::cerr << e.what() << std::endl; + } +} + +waybar::modules::sway::Window::operator Gtk::Widget &() { + return _label; +} diff --git a/src/modules/workspaces.cpp b/src/modules/sway/workspaces.cpp similarity index 85% rename from src/modules/workspaces.cpp rename to src/modules/sway/workspaces.cpp index a227f6f6..3579de53 100644 --- a/src/modules/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -1,7 +1,7 @@ -#include "modules/workspaces.hpp" -#include "ipc/client.hpp" +#include "modules/sway/workspaces.hpp" +#include "modules/sway/ipc/client.hpp" -waybar::modules::Workspaces::Workspaces(Bar &bar, Json::Value config) +waybar::modules::sway::Workspaces::Workspaces(Bar &bar, Json::Value config) : _bar(bar), _config(config), _scrolling(false) { _box.set_name("workspaces"); @@ -22,15 +22,16 @@ waybar::modules::Workspaces::Workspaces(Bar &bar, Json::Value config) uint32_t len = 0; std::lock_guard lock(_mutex); auto str = ipc_single_command(_ipcfd, IPC_GET_WORKSPACES, nullptr, &len); - _workspaces = _getWorkspaces(str); - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Workspaces::update)); + _workspaces = _parser.parse(str); + Glib::signal_idle() + .connect_once(sigc::mem_fun(*this, &Workspaces::update)); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } }; } -auto waybar::modules::Workspaces::update() -> void +auto waybar::modules::sway::Workspaces::update() -> void { std::lock_guard lock(_mutex); bool needReorder = false; @@ -73,7 +74,7 @@ auto waybar::modules::Workspaces::update() -> void _scrolling = false; } -void waybar::modules::Workspaces::_addWorkspace(Json::Value node) +void waybar::modules::sway::Workspaces::_addWorkspace(Json::Value node) { auto icon = _getIcon(node["name"].asString()); auto pair = _buttons.emplace(node["num"].asInt(), icon); @@ -105,7 +106,7 @@ void waybar::modules::Workspaces::_addWorkspace(Json::Value node) button.show(); } -std::string waybar::modules::Workspaces::_getIcon(std::string name) +std::string waybar::modules::sway::Workspaces::_getIcon(std::string name) { if (_config["format-icons"][name]) return _config["format-icons"][name].asString(); @@ -114,7 +115,7 @@ std::string waybar::modules::Workspaces::_getIcon(std::string name) return name; } -bool waybar::modules::Workspaces::_handleScroll(GdkEventScroll *e) +bool waybar::modules::sway::Workspaces::_handleScroll(GdkEventScroll *e) { std::lock_guard lock(_mutex); // Avoid concurrent scroll event @@ -155,7 +156,7 @@ bool waybar::modules::Workspaces::_handleScroll(GdkEventScroll *e) return true; } -int waybar::modules::Workspaces::_getPrevWorkspace() +int waybar::modules::sway::Workspaces::_getPrevWorkspace() { int current = -1; for (uint16_t i = 0; i != _workspaces.size(); i += 1) @@ -168,7 +169,7 @@ int waybar::modules::Workspaces::_getPrevWorkspace() return current; } -int waybar::modules::Workspaces::_getNextWorkspace() +int waybar::modules::sway::Workspaces::_getNextWorkspace() { int current = -1; for (uint16_t i = 0; i != _workspaces.size(); i += 1) @@ -181,18 +182,6 @@ int waybar::modules::Workspaces::_getNextWorkspace() return current; } -Json::Value waybar::modules::Workspaces::_getWorkspaces(const std::string data) -{ - Json::Value res; - try { - std::string err; - res = _parser.parse(data); - } catch (const std::exception& e) { - std::cerr << e.what() << std::endl; - } - return res; -} - -waybar::modules::Workspaces::operator Gtk::Widget &() { +waybar::modules::sway::Workspaces::operator Gtk::Widget &() { return _box; }