Remove leftover unconditional assignment that clobbered the value
computed from rxkb_layout_get_brief() with short_name, which made
short_description always equal short_name and defeated
format-<shortDescription> / {shortDescription}.
146 lines
4.6 KiB
C++
146 lines
4.6 KiB
C++
#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;
|
|
}
|
|
|
|
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
|