aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorVaxry <[email protected]>2024-07-25 13:02:05 +0200
committerVaxry <[email protected]>2024-07-25 13:02:10 +0200
commitdaf5fad19034def8062acfd32e66bea78c62aaff (patch)
tree566871bbe62ab75d6c5745de25c6b19a24d92441
parent4beac91cbd791657cc53d6e483eb41bf4df1ec0c (diff)
downloadHyprland-daf5fad19034def8062acfd32e66bea78c62aaff.tar.gz
Hyprland-daf5fad19034def8062acfd32e66bea78c62aaff.zip
keyboard: properly update keymap state and fd on keymap changes
needed for virtual keyboards that impose their own layouts. fixes #6991
-rw-r--r--src/devices/IKeyboard.cpp42
-rw-r--r--src/devices/IKeyboard.hpp30
-rw-r--r--src/devices/VirtualKeyboard.cpp9
3 files changed, 56 insertions, 25 deletions
diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp
index 284a8295..09a18477 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 1ae6c7bc..2ff8a190 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 654ca9f5..548711c2 100644
--- a/src/devices/VirtualKeyboard.cpp
+++ b/src/devices/VirtualKeyboard.cpp
@@ -31,8 +31,13 @@ CVirtualKeyboard::CVirtualKeyboard(SP<CVirtualKeyboardV1Resource> keeb_) : keybo
});
});
listeners.keymap = keeb_->events.keymap.registerListener([this](std::any d) {
- auto E = std::any_cast<SKeymapEvent>(d);
- xkbKeymap = xkb_keymap_ref(E.keymap);
+ auto E = std::any_cast<SKeymapEvent>(d);
+ if (xkbKeymap)
+ xkb_keymap_unref(xkbKeymap);
+ xkbKeymap = xkb_keymap_ref(E.keymap);
+ keymapOverridden = true;
+ updateXKBTranslationState(xkbKeymap);
+ updateKeymapFD();
keyboardEvents.keymap.emit(d);
});