feat: add mango modules: workspace,language,keymode,window,layout
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
#include "modules/mango/language.hpp"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <xkbcommon/xkbregistry.h>
|
||||
|
||||
#include "util/string.hpp"
|
||||
|
||||
namespace waybar::modules::mango {
|
||||
|
||||
Language::Language(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
: ALabel(config, "language", id, "{}", 0, false), bar_(bar), rxkb_ctx_(nullptr) {
|
||||
rxkb_ctx_ = rxkb_context_new(RXKB_CONTEXT_LOAD_EXOTIC_RULES);
|
||||
if (rxkb_ctx_) {
|
||||
rxkb_context_parse_default_ruleset(rxkb_ctx_);
|
||||
}
|
||||
|
||||
IPC::getInstance().registerForIPC("monitor", this);
|
||||
updateFromIPC();
|
||||
dp.emit();
|
||||
}
|
||||
|
||||
Language::~Language() {
|
||||
IPC::getInstance().unregisterForIPC(this);
|
||||
if (rxkb_ctx_) rxkb_context_unref(rxkb_ctx_);
|
||||
}
|
||||
|
||||
void Language::updateFromIPC() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::string layout = IPC::getInstance().getKeyboardLayout();
|
||||
|
||||
layouts_.clear();
|
||||
if (!layout.empty()) {
|
||||
Layout l = getLayout(layout);
|
||||
layouts_.push_back(l);
|
||||
current_idx_ = 0;
|
||||
} else {
|
||||
current_idx_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Language::doUpdate() {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (layouts_.empty() || current_idx_ >= layouts_.size()) {
|
||||
label_.hide();
|
||||
return;
|
||||
}
|
||||
const auto& layout = layouts_[current_idx_];
|
||||
|
||||
if (!last_short_name_.empty()) label_.get_style_context()->remove_class(last_short_name_);
|
||||
if (!layout.short_name.empty()) {
|
||||
label_.get_style_context()->add_class(layout.short_name);
|
||||
last_short_name_ = layout.short_name;
|
||||
}
|
||||
|
||||
std::string layoutName;
|
||||
std::string variant_key = "format-" + layout.short_description + "-" + layout.variant;
|
||||
if (!layout.variant.empty() && config_.isMember(variant_key)) {
|
||||
layoutName =
|
||||
fmt::format(fmt::runtime(config_[variant_key].asString()),
|
||||
fmt::arg("long", layout.full_name), fmt::arg("short", layout.short_name),
|
||||
fmt::arg("shortDescription", layout.short_description),
|
||||
fmt::arg("variant", layout.variant));
|
||||
} else if (config_.isMember("format-" + layout.short_description)) {
|
||||
std::string key = "format-" + layout.short_description;
|
||||
layoutName =
|
||||
fmt::format(fmt::runtime(config_[key].asString()), fmt::arg("long", layout.full_name),
|
||||
fmt::arg("short", layout.short_name),
|
||||
fmt::arg("shortDescription", layout.short_description),
|
||||
fmt::arg("variant", layout.variant));
|
||||
} else {
|
||||
layoutName = fmt::format(fmt::runtime(format_), fmt::arg("long", layout.full_name),
|
||||
fmt::arg("short", layout.short_name),
|
||||
fmt::arg("shortDescription", layout.short_description),
|
||||
fmt::arg("variant", layout.variant));
|
||||
}
|
||||
|
||||
if (!layoutName.empty()) {
|
||||
label_.show();
|
||||
label_.set_markup(layoutName);
|
||||
} else {
|
||||
label_.hide();
|
||||
}
|
||||
}
|
||||
|
||||
void Language::update() {
|
||||
updateFromIPC();
|
||||
doUpdate();
|
||||
ALabel::update();
|
||||
}
|
||||
|
||||
void Language::onEvent(const Json::Value& ev) {
|
||||
updateFromIPC();
|
||||
dp.emit();
|
||||
}
|
||||
|
||||
Language::Layout Language::getLayout(const std::string& fullName) {
|
||||
if (rxkb_ctx_) {
|
||||
rxkb_layout* layout = rxkb_layout_first(rxkb_ctx_);
|
||||
while (layout != nullptr) {
|
||||
std::string desc = rxkb_layout_get_description(layout);
|
||||
if (desc == fullName) {
|
||||
std::string short_name = rxkb_layout_get_name(layout);
|
||||
const char* variant_ptr = rxkb_layout_get_variant(layout);
|
||||
std::string variant = variant_ptr ? variant_ptr : "";
|
||||
const char* brief_ptr = rxkb_layout_get_brief(layout);
|
||||
std::string short_description = brief_ptr ? brief_ptr : "";
|
||||
|
||||
if (short_description.empty()) {
|
||||
short_description = short_name;
|
||||
}
|
||||
|
||||
short_description = short_name;
|
||||
|
||||
Layout info{desc, short_name, variant, short_description};
|
||||
return info;
|
||||
}
|
||||
layout = rxkb_layout_next(layout);
|
||||
}
|
||||
}
|
||||
|
||||
spdlog::warn("mango language: rxkb failed to find layout '{}', using string parsing fallback",
|
||||
fullName);
|
||||
|
||||
Layout l;
|
||||
l.full_name = fullName;
|
||||
l.variant = "";
|
||||
|
||||
size_t paren_start = fullName.find('(');
|
||||
size_t paren_end = fullName.find(')');
|
||||
if (paren_start != std::string::npos && paren_end != std::string::npos &&
|
||||
paren_end > paren_start) {
|
||||
l.short_name = fullName.substr(paren_start + 1, paren_end - paren_start - 1);
|
||||
} else if (fullName.length() >= 2) {
|
||||
l.short_name = fullName.substr(0, 2);
|
||||
} else {
|
||||
l.short_name = fullName;
|
||||
}
|
||||
|
||||
std::transform(l.short_name.begin(), l.short_name.end(), l.short_name.begin(),
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
l.short_description = l.short_name;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
} // namespace waybar::modules::mango
|
||||
Reference in New Issue
Block a user