diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index 284a8295b95..09a18477fc4 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -51,6 +51,11 @@ void IKeyboard::clearManuallyAllocd() { } void IKeyboard::setKeymap(const SStringRuleNames& rules) { + if (keymapOverridden) { + Debug::log(LOG, "Ignoring setKeymap: keymap is overridden"); + return; + } + currentRules = rules; xkb_rule_names XKBRULES = { .rules = rules.rules.c_str(), @@ -103,10 +108,6 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS); } - // set internal translation state - // demo sunao ni ienai - xkbStaticState = xkb_state_new(xkbKeymap); - updateXKBTranslationState(xkbKeymap); const auto NUMLOCKON = g_pConfigManager->getDeviceInt(hlName, "numlock_by_default", "input:numlock_by_default"); @@ -131,6 +132,20 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i)); } + updateKeymapFD(); + + xkb_context_unref(CONTEXT); + + g_pSeatManager->updateActiveKeyboardData(); +} + +void IKeyboard::updateKeymapFD() { + Debug::log(LOG, "Updating keymap fd for keyboard {}", deviceName); + + if (xkbKeymapFD >= 0) + close(xkbKeymapFD); + xkbKeymapFD = -1; + auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1); xkbKeymapString = cKeymapStr; free(cKeymapStr); @@ -151,21 +166,24 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) { } } - xkb_context_unref(CONTEXT); - - g_pSeatManager->updateActiveKeyboardData(); + Debug::log(LOG, "Updated keymap fd to {}", xkbKeymapFD); } void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { + if (xkbStaticState) + xkb_state_unref(xkbStaticState); + if (xkbState) xkb_state_unref(xkbState); - xkbState = nullptr; + xkbState = nullptr; + xkbStaticState = nullptr; if (keymap) { Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); - xkbState = xkb_state_new(keymap); + xkbStaticState = xkb_state_new(keymap); + xkbState = xkb_state_new(keymap); return; } @@ -209,7 +227,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); } - xkbState = xkb_state_new(KEYMAP); + xkbState = xkb_state_new(KEYMAP); + xkbStaticState = xkb_state_new(KEYMAP); xkb_keymap_unref(KEYMAP); xkb_context_unref(PCONTEXT); @@ -230,7 +249,8 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkbState = xkb_state_new(NEWKEYMAP); + xkbState = xkb_state_new(NEWKEYMAP); + xkbStaticState = xkb_state_new(NEWKEYMAP); xkb_keymap_unref(NEWKEYMAP); xkb_context_unref(PCONTEXT); diff --git a/src/devices/IKeyboard.hpp b/src/devices/IKeyboard.hpp index 1ae6c7bc521..2ff8a190bd1 100644 --- a/src/devices/IKeyboard.hpp +++ b/src/devices/IKeyboard.hpp @@ -61,18 +61,24 @@ class IKeyboard : public IHID { std::string rules = ""; }; - void setKeymap(const SStringRuleNames& rules); - void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); - std::string getActiveLayout(); - void updateLEDs(); - void updateLEDs(uint32_t leds); - uint32_t getModifiers(); - void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); - bool updateModifiersState(); // rets whether changed - void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); - - bool active = false; - bool enabled = true; + void setKeymap(const SStringRuleNames& rules); + void updateXKBTranslationState(xkb_keymap* const keymap = nullptr); + std::string getActiveLayout(); + void updateLEDs(); + void updateLEDs(uint32_t leds); + uint32_t getModifiers(); + void updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group); + bool updateModifiersState(); // rets whether changed + void updateXkbStateWithKey(uint32_t xkbKey, bool pressed); + void updateKeymapFD(); + + bool active = false; + bool enabled = true; + + // if the keymap is overridden by the implementation, + // don't try to set keyboard rules anymore, to avoid overwriting the requested one. + // e.g. Virtual keyboards with custom maps. + bool keymapOverridden = false; xkb_layout_index_t activeLayout = 0; xkb_state * xkbState = nullptr, *xkbStaticState /* Static state: never gets modifiers or layout changes sent, used for keybinds. */ = nullptr; diff --git a/src/devices/VirtualKeyboard.cpp b/src/devices/VirtualKeyboard.cpp index 654ca9f5cbd..548711c259b 100644 --- a/src/devices/VirtualKeyboard.cpp +++ b/src/devices/VirtualKeyboard.cpp @@ -31,8 +31,13 @@ CVirtualKeyboard::CVirtualKeyboard(SP keeb_) : keybo }); }); listeners.keymap = keeb_->events.keymap.registerListener([this](std::any d) { - auto E = std::any_cast(d); - xkbKeymap = xkb_keymap_ref(E.keymap); + auto E = std::any_cast(d); + if (xkbKeymap) + xkb_keymap_unref(xkbKeymap); + xkbKeymap = xkb_keymap_ref(E.keymap); + keymapOverridden = true; + updateXKBTranslationState(xkbKeymap); + updateKeymapFD(); keyboardEvents.keymap.emit(d); });