input: support xkb v2 format (#11482)

This commit is contained in:
usering-around 2025-09-11 20:42:20 +03:00 committed by GitHub
parent c7b9969129
commit 38169c8fdd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 62 additions and 28 deletions

View file

@ -429,7 +429,7 @@ inline static const std::vector<SConfigOptionDescription> CONFIG_OPTIONS = {
},
SConfigOptionDescription{
.value = "input:kb_file",
.description = "Appropriate XKB keymap parameter",
.description = "Appropriate XKB keymap file",
.type = CONFIG_OPTION_STRING_LONG,
.data = SConfigOptionDescription::SStringData{""}, //##TODO UNSET?
},

View file

@ -43,14 +43,19 @@ void IKeyboard::clearManuallyAllocd() {
if (m_xkbKeymap)
xkb_keymap_unref(m_xkbKeymap);
if (m_xkbKeymapV1)
xkb_keymap_unref(m_xkbKeymapV1);
if (m_xkbSymState)
xkb_state_unref(m_xkbSymState);
m_xkbSymState = nullptr;
m_xkbKeymap = nullptr;
m_xkbKeymapV1 = nullptr;
m_xkbState = nullptr;
m_xkbStaticState = nullptr;
m_xkbKeymapFD.reset();
m_xkbKeymapV1FD.reset();
}
void IKeyboard::setKeymap(const SStringRuleNames& rules) {
@ -86,13 +91,13 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) {
if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE)
Debug::log(ERR, "Cannot open input:kb_file= file for reading");
else {
m_xkbKeymap = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
m_xkbKeymap = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
fclose(KEYMAPFILE);
}
}
if (!m_xkbKeymap)
m_xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS);
m_xkbKeymap = xkb_keymap_new_from_names2(CONTEXT, &XKBRULES, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!m_xkbKeymap) {
g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + rules.rules + ", model: " + rules.model + ", variant: " + rules.variant +
@ -108,7 +113,16 @@ void IKeyboard::setKeymap(const SStringRuleNames& rules) {
m_currentRules.options = "";
m_currentRules.layout = "us";
m_xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS);
m_xkbKeymap = xkb_keymap_new_from_names2(CONTEXT, &XKBRULES, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
auto cKeymapStr = xkb_keymap_get_as_string(m_xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1);
if (!cKeymapStr) {
Debug::log(ERR, "Couldn't convert keymap to V1 format");
m_xkbKeymapV1 = xkb_keymap_new_from_names2(CONTEXT, &XKBRULES, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
} else {
m_xkbKeymapV1 = xkb_keymap_new_from_string(CONTEXT, cKeymapStr, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
free(cKeymapStr);
}
updateXKBTranslationState(m_xkbKeymap);
@ -149,27 +163,44 @@ void IKeyboard::updateKeymapFD() {
if (m_xkbKeymapFD.isValid())
m_xkbKeymapFD.reset();
auto cKeymapStr = xkb_keymap_get_as_string(m_xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1);
if (m_xkbKeymapV1FD.isValid())
m_xkbKeymapV1FD.reset();
auto cKeymapStr = xkb_keymap_get_as_string(m_xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V2);
m_xkbKeymapString = cKeymapStr;
free(cKeymapStr);
auto cKeymapV1Str = xkb_keymap_get_as_string(m_xkbKeymapV1, XKB_KEYMAP_FORMAT_TEXT_V1);
m_xkbKeymapV1String = cKeymapV1Str;
free(cKeymapV1Str);
CFileDescriptor rw, ro;
CFileDescriptor rw, ro, rwV1, roV1;
if (!allocateSHMFilePair(m_xkbKeymapString.length() + 1, rw, ro))
Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap");
else {
auto keymapFDDest = mmap(nullptr, m_xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw.get(), 0);
else if (!allocateSHMFilePair(m_xkbKeymapV1String.length() + 1, rwV1, roV1)) {
ro.reset();
rw.reset();
if (keymapFDDest == MAP_FAILED) {
Debug::log(ERR, "IKeyboard: failed to allocate shm pair for keymap V1");
} else {
auto keymapFDDest = mmap(nullptr, m_xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw.get(), 0);
auto keymapV1FDDest = mmap(nullptr, m_xkbKeymapV1String.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rwV1.get(), 0);
rw.reset();
rwV1.reset();
if (keymapFDDest == MAP_FAILED || keymapV1FDDest == MAP_FAILED) {
Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap");
ro.reset();
roV1.reset();
} else {
memcpy(keymapFDDest, m_xkbKeymapString.c_str(), m_xkbKeymapString.length());
munmap(keymapFDDest, m_xkbKeymapString.length() + 1);
m_xkbKeymapFD = std::move(ro);
memcpy(keymapV1FDDest, m_xkbKeymapV1String.c_str(), m_xkbKeymapV1String.length());
munmap(keymapV1FDDest, m_xkbKeymapV1String.length() + 1);
m_xkbKeymapV1FD = std::move(roV1);
}
}
Debug::log(LOG, "Updated keymap fd to {}", m_xkbKeymapFD.get());
Debug::log(LOG, "Updated keymap fd to {}, keymap V1 to: {}", m_xkbKeymapFD.get(), m_xkbKeymapV1FD.get());
}
void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
@ -220,19 +251,19 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
rules.model = model.c_str();
rules.variant = variant.c_str();
auto KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
auto KEYMAP = xkb_keymap_new_from_names2(PCONTEXT, &rules, XKB_KEYMAP_FORMAT_TEXT_V2, 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);
KEYMAP = xkb_keymap_new_from_names2(PCONTEXT, &rules, XKB_KEYMAP_FORMAT_TEXT_V2, 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);
KEYMAP = xkb_keymap_new_from_names2(PCONTEXT, &rules, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
m_xkbState = xkb_state_new(KEYMAP);
@ -256,7 +287,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
.options = m_currentRules.options.c_str(),
};
const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
const auto NEWKEYMAP = xkb_keymap_new_from_names2(PCONTEXT, &rules, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
m_xkbState = xkb_state_new(NEWKEYMAP);
m_xkbStaticState = xkb_state_new(NEWKEYMAP);

View file

@ -99,7 +99,8 @@ class IKeyboard : public IHID {
xkb_state* m_xkbStaticState = nullptr;
xkb_state* m_xkbSymState = nullptr; // same as static but gets layouts
xkb_keymap* m_xkbKeymap = nullptr;
xkb_keymap* m_xkbKeymap = nullptr;
xkb_keymap* m_xkbKeymapV1 = nullptr;
struct {
uint32_t depressed = 0, latched = 0, locked = 0, group = 0;
@ -113,6 +114,9 @@ class IKeyboard : public IHID {
std::string m_xkbKeymapString = "";
Hyprutils::OS::CFileDescriptor m_xkbKeymapFD;
std::string m_xkbKeymapV1String = "";
Hyprutils::OS::CFileDescriptor m_xkbKeymapV1FD;
SStringRuleNames m_currentRules;
int m_repeatRate = 0;
int m_repeatDelay = 0;

View file

@ -291,8 +291,8 @@ void CKeybindManager::updateXKBTranslationState() {
const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
FILE* const KEYMAPFILE = FILEPATH.empty() ? nullptr : fopen(absolutePath(FILEPATH, g_pConfigManager->m_configCurrentPath).c_str(), "r");
auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS) :
xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
auto PKEYMAP = KEYMAPFILE ? xkb_keymap_new_from_file(PCONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS) :
xkb_keymap_new_from_names2(PCONTEXT, &rules, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (KEYMAPFILE)
fclose(KEYMAPFILE);
@ -305,7 +305,7 @@ void CKeybindManager::updateXKBTranslationState() {
rules.rules, rules.model, rules.options);
memset(&rules, 0, sizeof(rules));
PKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
PKEYMAP = xkb_keymap_new_from_names2(PCONTEXT, &rules, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
}
xkb_context_unref(PCONTEXT);

View file

@ -1108,7 +1108,6 @@ void CInputManager::applyConfigToKeyboard(SP<IKeyboard> pKeyboard) {
pKeyboard->m_repeatDelay = std::max(0, REPEATDELAY);
pKeyboard->m_numlockOn = NUMLOCKON;
pKeyboard->m_xkbFilePath = FILEPATH;
pKeyboard->setKeymap(IKeyboard::SStringRuleNames{LAYOUT, MODEL, VARIANT, OPTIONS, RULES});
const auto LAYOUTSTR = pKeyboard->getActiveLayout();

View file

@ -33,22 +33,22 @@ void CInputMethodKeyboardGrabV2::sendKeyboardData(SP<IKeyboard> keyboard) {
m_lastKeyboard = keyboard;
auto keymapFD = allocateSHMFile(keyboard->m_xkbKeymapString.length() + 1);
auto keymapFD = allocateSHMFile(keyboard->m_xkbKeymapV1String.length() + 1);
if UNLIKELY (!keymapFD.isValid()) {
LOGM(ERR, "Failed to create a keymap file for keyboard grab");
return;
}
void* data = mmap(nullptr, keyboard->m_xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD.get(), 0);
void* data = mmap(nullptr, keyboard->m_xkbKeymapV1String.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, keymapFD.get(), 0);
if UNLIKELY (data == MAP_FAILED) {
LOGM(ERR, "Failed to mmap a keymap file for keyboard grab");
return;
}
memcpy(data, keyboard->m_xkbKeymapString.c_str(), keyboard->m_xkbKeymapString.length());
munmap(data, keyboard->m_xkbKeymapString.length() + 1);
memcpy(data, keyboard->m_xkbKeymapV1String.c_str(), keyboard->m_xkbKeymapV1String.length());
munmap(data, keyboard->m_xkbKeymapV1String.length() + 1);
m_resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD.get(), keyboard->m_xkbKeymapString.length() + 1);
m_resource->sendKeymap(WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymapFD.get(), keyboard->m_xkbKeymapV1String.length() + 1);
sendMods(keyboard->m_modifiersState.depressed, keyboard->m_modifiersState.latched, keyboard->m_modifiersState.locked, keyboard->m_modifiersState.group);

View file

@ -88,7 +88,7 @@ CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP<CZwpVirtualKeyboardV1>
return;
}
auto xkbKeymap = xkb_keymap_new_from_string(xkbContext, sc<const char*>(keymapData), XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
auto xkbKeymap = xkb_keymap_new_from_string(xkbContext, sc<const char*>(keymapData), XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(keymapData, len);
if UNLIKELY (!xkbKeymap) {

View file

@ -333,9 +333,9 @@ void CWLKeyboardResource::sendKeymap(SP<IKeyboard> keyboard) {
if (!(PROTO::seat->m_currentCaps & eHIDCapabilityType::HID_INPUT_CAPABILITY_KEYBOARD))
return;
std::string_view keymap = keyboard->m_xkbKeymapString;
Hyprutils::OS::CFileDescriptor& fd = keyboard->m_xkbKeymapFD;
uint32_t size = keyboard->m_xkbKeymapString.length() + 1;
std::string_view keymap = keyboard->m_xkbKeymapV1String;
Hyprutils::OS::CFileDescriptor& fd = keyboard->m_xkbKeymapV1FD;
uint32_t size = keyboard->m_xkbKeymapV1String.length() + 1;
if (keymap == m_lastKeymap)
return;