diff --git a/include/factory.hpp b/include/factory.hpp index 3efe6cbd..7eed15a5 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -6,6 +6,7 @@ #include "modules/sway/mode.hpp" #include "modules/sway/window.hpp" #include "modules/sway/workspaces.hpp" +#include "modules/sway/language.hpp" #endif #ifdef HAVE_WLR #include "modules/wlr/taskbar.hpp" diff --git a/include/modules/sway/language.hpp b/include/modules/sway/language.hpp new file mode 100644 index 00000000..7cd6bf62 --- /dev/null +++ b/include/modules/sway/language.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include "ALabel.hpp" +#include "bar.hpp" +#include "client.hpp" +#include "modules/sway/ipc/client.hpp" +#include "util/json.hpp" + +namespace waybar::modules::sway { + +class Language : public ALabel, public sigc::trackable { + public: + Language(const std::string& id, const Json::Value& config); + ~Language() = default; + auto update() -> void; + + private: + void onEvent(const struct Ipc::ipc_response&); + void onCmd(const struct Ipc::ipc_response&); + + std::string lang_; + util::JsonParser parser_; + std::mutex mutex_; + Ipc ipc_; +}; + +} // namespace waybar::modules::sway diff --git a/meson.build b/meson.build index 023894cd..e563de07 100644 --- a/meson.build +++ b/meson.build @@ -172,6 +172,7 @@ add_project_arguments('-DHAVE_SWAY', language: 'cpp') src_files += [ 'src/modules/sway/ipc/client.cpp', 'src/modules/sway/mode.cpp', + 'src/modules/sway/language.cpp', 'src/modules/sway/window.cpp', 'src/modules/sway/workspaces.cpp' ] diff --git a/resources/config b/resources/config index 36c4f967..f3c0a778 100644 --- a/resources/config +++ b/resources/config @@ -6,7 +6,7 @@ // Choose the order of the modules "modules-left": ["sway/workspaces", "sway/mode", "custom/media"], "modules-center": ["sway/window"], - "modules-right": ["mpd", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "battery", "battery#bat2", "clock", "tray"], + "modules-right": ["mpd", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "sway/language", "battery", "battery#bat2", "clock", "tray"], // Modules configuration // "sway/workspaces": { // "disable-scroll": true, diff --git a/resources/style.css b/resources/style.css index e21ae00e..a16afd09 100644 --- a/resources/style.css +++ b/resources/style.css @@ -200,3 +200,11 @@ label:focus { #mpd.paused { background-color: #51a37a; } + +#language { + background: #00b093; + color: #740864; + padding: 0 5px; + margin: 0 5px; + min-width: 16px; +} diff --git a/src/factory.cpp b/src/factory.cpp index 8a5e8250..1f907894 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -22,6 +22,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { if (ref == "sway/window") { return new waybar::modules::sway::Window(id, bar_, config_[name]); } + if (ref == "sway/language") { + return new waybar::modules::sway::Language(id, config_[name]); + } #endif #ifdef HAVE_WLR if (ref == "wlr/taskbar") { diff --git a/src/modules/sway/language.cpp b/src/modules/sway/language.cpp new file mode 100644 index 00000000..a3186477 --- /dev/null +++ b/src/modules/sway/language.cpp @@ -0,0 +1,70 @@ +#include "modules/sway/language.hpp" +#include + +namespace waybar::modules::sway { + +Language::Language(const std::string& id, const Json::Value& config) + : ALabel(config, "language", id, "{}", 0, true) { + ipc_.subscribe(R"(["input"])"); + ipc_.signal_event.connect(sigc::mem_fun(*this, &Language::onEvent)); + ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Language::onCmd)); + ipc_.sendCmd(IPC_GET_INPUTS); + // Launch worker + ipc_.setWorker([this] { + try { + ipc_.handleEvent(); + } catch (const std::exception& e) { + spdlog::error("Language: {}", e.what()); + } + }); + dp.emit(); +} + +void Language::onCmd(const struct Ipc::ipc_response& res) { + try { + auto payload = parser_.parse(res.payload); + //Display current layout of a device with a maximum count of layouts, expecting that all will be OK + Json::Value::ArrayIndex maxId = 0, max = 0; + for(Json::Value::ArrayIndex i = 0; i < payload.size(); i++) { + if(payload[i]["xkb_layout_names"].size() > max) { + max = payload[i]["xkb_layout_names"].size(); + maxId = i; + } + } + auto layout_name = payload[maxId]["xkb_active_layout_name"].asString().substr(0,2); + lang_ = Glib::Markup::escape_text(layout_name); + dp.emit(); + } catch (const std::exception& e) { + spdlog::error("Language: {}", e.what()); + } +} + +void Language::onEvent(const struct Ipc::ipc_response& res) { + try { + std::lock_guard lock(mutex_); + auto payload = parser_.parse(res.payload)["input"]; + if (payload["type"].asString() == "keyboard") { + auto layout_name = payload["xkb_active_layout_name"].asString().substr(0,2); + lang_ = Glib::Markup::escape_text(layout_name); + } + dp.emit(); + } catch (const std::exception& e) { + spdlog::error("Language: {}", e.what()); + } +} + +auto Language::update() -> void { + if (lang_.empty()) { + event_box_.hide(); + } else { + label_.set_markup(fmt::format(format_, lang_)); + if (tooltipEnabled()) { + label_.set_tooltip_text(lang_); + } + event_box_.show(); + } + // Call parent update + ALabel::update(); +} + +} // namespace waybar::modules::sway