Merge pull request #4883 from Cprakhar/feat/custom-format-icons-keyboard
feat: add custom format-icons for each key in keyboard-state module
This commit is contained in:
@@ -36,8 +36,7 @@ class KeyboardState : public AModule {
|
|||||||
std::string capslock_format_;
|
std::string capslock_format_;
|
||||||
std::string scrolllock_format_;
|
std::string scrolllock_format_;
|
||||||
const std::chrono::seconds interval_;
|
const std::chrono::seconds interval_;
|
||||||
std::string icon_locked_;
|
std::unordered_map<std::string, std::vector<std::string>> key_icon_states_;
|
||||||
std::string icon_unlocked_;
|
|
||||||
std::string devices_path_;
|
std::string devices_path_;
|
||||||
|
|
||||||
struct libinput* libinput_;
|
struct libinput* libinput_;
|
||||||
|
|||||||
@@ -26,7 +26,10 @@ You must be a member of the input group to use this module.
|
|||||||
*format-icons*: ++
|
*format-icons*: ++
|
||||||
typeof: object ++
|
typeof: object ++
|
||||||
default: {"locked": "locked", "unlocked": "unlocked"} ++
|
default: {"locked": "locked", "unlocked": "unlocked"} ++
|
||||||
Based on the keyboard state, the corresponding icon gets selected. The same set of icons is used for number, caps, and scroll lock, but the icon is selected from the set independently for each. See *icons*.
|
Based on the keyboard state, the corresponding icon gets selected. Supports two syntaxes:
|
||||||
|
- Common format-icons: "locked" and "unlocked" keys apply to all lock types.
|
||||||
|
- Per-lock-type format-icons: per-lock-type objects with "numlock", "capslock", "scrolllock" keys, each containing "locked" and "unlocked" icons.
|
||||||
|
See *icons*.
|
||||||
|
|
||||||
*numlock*: ++
|
*numlock*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
@@ -68,15 +71,21 @@ You must be a member of the input group to use this module.
|
|||||||
|
|
||||||
The following *format-icons* can be set.
|
The following *format-icons* can be set.
|
||||||
|
|
||||||
|
## Common format-icons for all lock types:
|
||||||
- *locked*: Will be shown when the keyboard state is locked. Default "locked".
|
- *locked*: Will be shown when the keyboard state is locked. Default "locked".
|
||||||
- *unlocked*: Will be shown when the keyboard state is not locked. Default "unlocked"
|
- *unlocked*: Will be shown when the keyboard state is not locked. Default "unlocked".
|
||||||
|
|
||||||
|
## Per-lock-type format-icons:
|
||||||
|
- *numlock*, *capslock*, *scrolllock*: Object containing "locked" and "unlocked" keys for lock-type-specific icons. Defaults to {"locked": "locked", "unlocked": "unlocked"} for each lock type.
|
||||||
|
|
||||||
# EXAMPLE:
|
# EXAMPLE:
|
||||||
|
|
||||||
|
## Common format-icons for all lock types:
|
||||||
```
|
```
|
||||||
"keyboard-state": {
|
"keyboard-state": {
|
||||||
"numlock": true,
|
"numlock": true,
|
||||||
"capslock": true,
|
"capslock": true,
|
||||||
|
"scrolllock": true,
|
||||||
"format": "{name} {icon}",
|
"format": "{name} {icon}",
|
||||||
"format-icons": {
|
"format-icons": {
|
||||||
"locked": "",
|
"locked": "",
|
||||||
@@ -85,6 +94,30 @@ The following *format-icons* can be set.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Per-lock-type format-icons:
|
||||||
|
```
|
||||||
|
"keyboard-state": {
|
||||||
|
"numlock": true,
|
||||||
|
"capslock": true,
|
||||||
|
"scrolllock": true,
|
||||||
|
"format": "{name} {icon}",
|
||||||
|
"format-icons": {
|
||||||
|
"numlock": {
|
||||||
|
"locked": "1",
|
||||||
|
"unlocked": "0"
|
||||||
|
},
|
||||||
|
"capslock": {
|
||||||
|
"locked": "A",
|
||||||
|
"unlocked": "a"
|
||||||
|
},
|
||||||
|
"scrolllock": {
|
||||||
|
"locked": "S",
|
||||||
|
"unlocked": "s"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
# STYLE
|
# STYLE
|
||||||
|
|
||||||
- *#keyboard-state*
|
- *#keyboard-state*
|
||||||
|
|||||||
@@ -78,6 +78,53 @@ auto supportsLockStates(const libevdev* dev) -> bool {
|
|||||||
libevdev_has_event_code(dev, EV_LED, LED_SCROLLL);
|
libevdev_has_event_code(dev, EV_LED, LED_SCROLLL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto isCommonFormatIcons(const Json::Value& config) -> bool {
|
||||||
|
return config["format-icons"].isObject() && (config["format-icons"]["locked"].isString() ||
|
||||||
|
config["format-icons"]["unlocked"].isString());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto keyStateToIcons(const Json::Value& config)
|
||||||
|
-> std::unordered_map<std::string, std::vector<std::string>> {
|
||||||
|
std::unordered_map<std::string, std::vector<std::string>> key_icon_states;
|
||||||
|
std::vector<std::string> default_icons = {"unlocked", "locked"};
|
||||||
|
|
||||||
|
if (isCommonFormatIcons(config)) {
|
||||||
|
std::vector<std::string> icons = {
|
||||||
|
config["format-icons"]["unlocked"].isString()
|
||||||
|
? config["format-icons"]["unlocked"].asString()
|
||||||
|
: "unlocked",
|
||||||
|
config["format-icons"]["locked"].isString() ? config["format-icons"]["locked"].asString()
|
||||||
|
: "locked",
|
||||||
|
};
|
||||||
|
key_icon_states["Lock"] = icons;
|
||||||
|
return key_icon_states;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found_any = false;
|
||||||
|
for (const auto& key : std::vector<std::string>{"numlock", "capslock", "scrolllock"}) {
|
||||||
|
std::string map_key = key.substr(0, key.length() - 4);
|
||||||
|
map_key[0] = std::toupper(map_key[0]);
|
||||||
|
if (config["format-icons"].isObject() && config["format-icons"][key].isObject()) {
|
||||||
|
std::string unlocked = config["format-icons"][key]["unlocked"].isString()
|
||||||
|
? config["format-icons"][key]["unlocked"].asString()
|
||||||
|
: "unlocked";
|
||||||
|
std::string locked = config["format-icons"][key]["locked"].isString()
|
||||||
|
? config["format-icons"][key]["locked"].asString()
|
||||||
|
: "locked";
|
||||||
|
key_icon_states[map_key] = {unlocked, locked};
|
||||||
|
found_any = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_any) {
|
||||||
|
key_icon_states["Num"] = default_icons;
|
||||||
|
key_icon_states["Caps"] = default_icons;
|
||||||
|
key_icon_states["Scroll"] = default_icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
return key_icon_states;
|
||||||
|
}
|
||||||
|
|
||||||
waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar,
|
waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar,
|
||||||
const Json::Value& config)
|
const Json::Value& config)
|
||||||
: AModule(config, "keyboard-state", id, false, !config["disable-scroll"].asBool()),
|
: AModule(config, "keyboard-state", id, false, !config["disable-scroll"].asBool()),
|
||||||
@@ -98,12 +145,7 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar&
|
|||||||
: "{name} {icon}"),
|
: "{name} {icon}"),
|
||||||
interval_(
|
interval_(
|
||||||
std::chrono::seconds(config_["interval"].isUInt() ? config_["interval"].asUInt() : 1)),
|
std::chrono::seconds(config_["interval"].isUInt() ? config_["interval"].asUInt() : 1)),
|
||||||
icon_locked_(config_["format-icons"]["locked"].isString()
|
key_icon_states_(keyStateToIcons(config_)),
|
||||||
? config_["format-icons"]["locked"].asString()
|
|
||||||
: "locked"),
|
|
||||||
icon_unlocked_(config_["format-icons"]["unlocked"].isString()
|
|
||||||
? config_["format-icons"]["unlocked"].asString()
|
|
||||||
: "unlocked"),
|
|
||||||
devices_path_("/dev/input/"),
|
devices_path_("/dev/input/"),
|
||||||
libinput_(nullptr),
|
libinput_(nullptr),
|
||||||
libinput_devices_({}) {
|
libinput_devices_({}) {
|
||||||
@@ -290,7 +332,7 @@ auto waybar::modules::KeyboardState::update() -> void {
|
|||||||
bool state;
|
bool state;
|
||||||
Gtk::Label& label;
|
Gtk::Label& label;
|
||||||
const std::string& format;
|
const std::string& format;
|
||||||
const char* name;
|
const std::string name;
|
||||||
} label_states[] = {
|
} label_states[] = {
|
||||||
{(bool)numl, numlock_label_, numlock_format_, "Num"},
|
{(bool)numl, numlock_label_, numlock_format_, "Num"},
|
||||||
{(bool)capsl, capslock_label_, capslock_format_, "Caps"},
|
{(bool)capsl, capslock_label_, capslock_format_, "Caps"},
|
||||||
@@ -298,8 +340,21 @@ auto waybar::modules::KeyboardState::update() -> void {
|
|||||||
};
|
};
|
||||||
for (auto& label_state : label_states) {
|
for (auto& label_state : label_states) {
|
||||||
std::string text;
|
std::string text;
|
||||||
|
std::string map_key = isCommonFormatIcons(config_) ? "Lock" : label_state.name;
|
||||||
|
|
||||||
|
if (key_icon_states_.find(map_key) == key_icon_states_.end()) {
|
||||||
|
spdlog::warn("keyboard-state: Missing icon configuration for '{}'", map_key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& icons = key_icon_states_[map_key];
|
||||||
|
if (icons.size() < 2) {
|
||||||
|
spdlog::warn("keyboard-state: Invalid icon vector size for '{}'", map_key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
text = fmt::format(fmt::runtime(label_state.format),
|
text = fmt::format(fmt::runtime(label_state.format),
|
||||||
fmt::arg("icon", label_state.state ? icon_locked_ : icon_unlocked_),
|
fmt::arg("icon", label_state.state ? icons[1] : icons[0]),
|
||||||
fmt::arg("name", label_state.name));
|
fmt::arg("name", label_state.name));
|
||||||
label_state.label.set_markup(text);
|
label_state.label.set_markup(text);
|
||||||
if (label_state.state) {
|
if (label_state.state) {
|
||||||
|
|||||||
Reference in New Issue
Block a user