diff options
| author | Vaxry <vaxry@vaxry.net> | 2024-05-03 22:34:10 +0100 |
|---|---|---|
| committer | Vaxry <vaxry@vaxry.net> | 2024-05-03 22:40:27 +0100 |
| commit | 1237732b97fcf21a19aed16f2ef966118a3ca2aa (patch) | |
| tree | 15a3a29377af7f0ce3dd428229587e476ce92db3 /src/devices/IKeyboard.cpp | |
| parent | 1d2acbe19355c8640d54a4b6cba225c6f4370c85 (diff) | |
input: Introduce basic hyprland HID classes
Implements an intermediary HID class for mice, keyboards and touch devices, removing the old structs from WLClasses.hpp
Yes, virtual ones are duplicated a bit, but will likely be de-duped once wlr_input_device is not used anymore.
Diffstat (limited to 'src/devices/IKeyboard.cpp')
| -rw-r--r-- | src/devices/IKeyboard.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp new file mode 100644 index 00000000..790766bc --- /dev/null +++ b/src/devices/IKeyboard.cpp @@ -0,0 +1,134 @@ +#include "IKeyboard.hpp" +#include "../defines.hpp" +#include "../helpers/VarList.hpp" +#include "../managers/input/InputManager.hpp" + +uint32_t IKeyboard::getCapabilities() { + return HID_INPUT_CAPABILITY_KEYBOARD; +} + +IKeyboard::~IKeyboard() { + events.destroy.emit(); + + if (!xkbTranslationState) + return; + + xkb_state_unref(xkbTranslationState); + xkbTranslationState = nullptr; +} + +void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { + + if (xkbTranslationState) + xkb_state_unref(xkbTranslationState); + + if (keymap) { + Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); + xkbTranslationState = xkb_state_new(keymap); + return; + } + + const auto WLRKB = wlr(); + const auto KEYMAP = WLRKB->keymap; + const auto STATE = WLRKB->xkb_state; + const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); + + const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { + if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) { + Debug::log(LOG, "Updating keyboard {:x}'s translation state from an active index {}", (uintptr_t)this, i); + + CVarList keyboardLayouts(currentRules.layout, 0, ','); + CVarList keyboardModels(currentRules.model, 0, ','); + CVarList keyboardVariants(currentRules.variant, 0, ','); + + xkb_rule_names rules = {.rules = "", .model = "", .layout = "", .variant = "", .options = ""}; + + std::string layout, model, variant; + layout = keyboardLayouts[i % keyboardLayouts.size()]; + model = keyboardModels[i % keyboardModels.size()]; + variant = keyboardVariants[i % keyboardVariants.size()]; + + rules.layout = layout.c_str(); + rules.model = model.c_str(); + rules.variant = variant.c_str(); + + auto KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!KEYMAP) { + Debug::log(ERR, "updateXKBTranslationState: keymap failed 1, fallback without model/variant"); + rules.model = ""; + rules.variant = ""; + KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + } + + if (!KEYMAP) { + Debug::log(ERR, "updateXKBTranslationState: keymap failed 2, fallback to us"); + rules.layout = "us"; + KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + } + + xkbTranslationState = xkb_state_new(KEYMAP); + + xkb_keymap_unref(KEYMAP); + xkb_context_unref(PCONTEXT); + + return; + } + } + + Debug::log(LOG, "Updating keyboard {:x}'s translation state from an unknown index", (uintptr_t)this); + + xkb_rule_names rules = { + .rules = currentRules.rules.c_str(), + .model = currentRules.model.c_str(), + .layout = currentRules.layout.c_str(), + .variant = currentRules.variant.c_str(), + .options = currentRules.options.c_str(), + }; + + const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); + + xkbTranslationState = xkb_state_new(NEWKEYMAP); + + xkb_keymap_unref(NEWKEYMAP); + xkb_context_unref(PCONTEXT); +} + +std::string IKeyboard::getActiveLayout() { + const auto WLRKB = wlr(); + const auto KEYMAP = WLRKB->keymap; + const auto STATE = WLRKB->xkb_state; + const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); + + for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { + if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) { + const auto LAYOUTNAME = xkb_keymap_layout_get_name(KEYMAP, i); + + if (LAYOUTNAME) + return std::string(LAYOUTNAME); + return "error"; + } + } + + return "none"; +} + +void IKeyboard::updateLEDs() { + auto keyboard = wlr(); + + if (keyboard->xkb_state == nullptr) + return; + + uint32_t leds = 0; + for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { + if (xkb_state_led_index_is_active(keyboard->xkb_state, keyboard->led_indexes[i])) + leds |= (1 << i); + } + + if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock())) + return; + + wlr_keyboard_led_update(wlr(), leds); +} |
