diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2024-07-21 13:09:54 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-21 13:09:54 +0200 |
| commit | 016da234d0e852de3ef20eb2e89ac58d2a85f6e7 (patch) | |
| tree | 496085987176551b0794fffc069877d44943e2f1 /src/devices/IKeyboard.cpp | |
| parent | f642fb97df5c69267a03452533de383ff8023570 (diff) | |
Core: Move to aquamarine (#6608)
Moves Hyprland from wlroots to aquamarine for the backend.
---------
Signed-off-by: Vaxry <vaxry@vaxry.net>
Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
Co-authored-by: Jan Beich <jbeich@FreeBSD.org>
Co-authored-by: vaxerski <vaxerski@users.noreply.github.com>
Co-authored-by: UjinT34 <41110182+UjinT34@users.noreply.github.com>
Co-authored-by: Tom Englund <tomenglund26@gmail.com>
Co-authored-by: Ikalco <73481042+ikalco@users.noreply.github.com>
Co-authored-by: diniamo <diniamo53@gmail.com>
Diffstat (limited to 'src/devices/IKeyboard.cpp')
| -rw-r--r-- | src/devices/IKeyboard.cpp | 254 |
1 files changed, 231 insertions, 23 deletions
diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp index cb294d1a..284a8295 100644 --- a/src/devices/IKeyboard.cpp +++ b/src/devices/IKeyboard.cpp @@ -2,7 +2,21 @@ #include "../defines.hpp" #include "../helpers/varlist/VarList.hpp" #include "../managers/input/InputManager.hpp" +#include "../managers/SeatManager.hpp" +#include "../config/ConfigManager.hpp" +#include <sys/mman.h> +#include <aquamarine/input/Input.hpp> +#include <cstring> +#define LED_COUNT 3 + +constexpr static std::array<const char*, 8> MODNAMES = { + XKB_MOD_NAME_SHIFT, XKB_MOD_NAME_CAPS, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_ALT, XKB_MOD_NAME_NUM, "Mod3", XKB_MOD_NAME_LOGO, "Mod5", +}; + +constexpr static std::array<const char*, 3> LEDNAMES = {XKB_LED_NAME_NUM, XKB_LED_NAME_CAPS, XKB_LED_NAME_SCROLL}; + +// uint32_t IKeyboard::getCapabilities() { return HID_INPUT_CAPABILITY_KEYBOARD; } @@ -14,27 +28,149 @@ eHIDType IKeyboard::getType() { IKeyboard::~IKeyboard() { events.destroy.emit(); - if (!xkbTranslationState) + clearManuallyAllocd(); +} + +void IKeyboard::clearManuallyAllocd() { + if (xkbStaticState) + xkb_state_unref(xkbStaticState); + + if (xkbState) + xkb_state_unref(xkbState); + + if (xkbKeymap) + xkb_keymap_unref(xkbKeymap); + + if (xkbKeymapFD >= 0) + close(xkbKeymapFD); + + xkbKeymap = nullptr; + xkbState = nullptr; + xkbStaticState = nullptr; + xkbKeymapFD = -1; +} + +void IKeyboard::setKeymap(const SStringRuleNames& rules) { + currentRules = rules; + xkb_rule_names XKBRULES = { + .rules = rules.rules.c_str(), + .model = rules.model.c_str(), + .layout = rules.layout.c_str(), + .variant = rules.variant.c_str(), + .options = rules.options.c_str(), + }; + + const auto CONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + + if (!CONTEXT) { + Debug::log(ERR, "setKeymap: CONTEXT null??"); return; + } + + clearManuallyAllocd(); + + Debug::log(LOG, "Attempting to create a keymap for layout {} with variant {} (rules: {}, model: {}, options: {})", rules.layout, rules.variant, rules.rules, rules.model, + rules.options); + + if (!xkbFilePath.empty()) { + auto path = absolutePath(xkbFilePath, g_pConfigManager->configCurrentPath); + + if (FILE* const KEYMAPFILE = fopen(path.c_str(), "r"); !KEYMAPFILE) + Debug::log(ERR, "Cannot open input:kb_file= file for reading"); + else { + xkbKeymap = xkb_keymap_new_from_file(CONTEXT, KEYMAPFILE, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); + fclose(KEYMAPFILE); + } + } + + if (!xkbKeymap) + xkbKeymap = xkb_keymap_new_from_names(CONTEXT, &XKBRULES, XKB_KEYMAP_COMPILE_NO_FLAGS); + + if (!xkbKeymap) { + g_pConfigManager->addParseError("Invalid keyboard layout passed. ( rules: " + rules.rules + ", model: " + rules.model + ", variant: " + rules.variant + + ", options: " + rules.options + ", layout: " + rules.layout + " )"); + + Debug::log(ERR, "Keyboard layout {} with variant {} (rules: {}, model: {}, options: {}) couldn't have been loaded.", rules.layout, rules.variant, rules.rules, rules.model, + rules.options); + memset(&XKBRULES, 0, sizeof(XKBRULES)); + + currentRules.rules = ""; + currentRules.model = ""; + currentRules.variant = ""; + currentRules.options = ""; + currentRules.layout = "us"; + + 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"); + + if (NUMLOCKON == 1) { + // lock numlock + const auto IDX = xkb_map_mod_get_index(xkbKeymap, XKB_MOD_NAME_NUM); + + if (IDX != XKB_MOD_INVALID) + modifiersState.locked |= (uint32_t)1 << IDX; + + updateModifiers(modifiersState.depressed, modifiersState.latched, modifiersState.locked, modifiersState.group); + } + + for (size_t i = 0; i < LEDNAMES.size(); ++i) { + ledIndexes.at(i) = xkb_map_led_get_index(xkbKeymap, LEDNAMES.at(i)); + Debug::log(LOG, "xkb: LED index {} (name {}) got index {}", i, LEDNAMES.at(i), ledIndexes.at(i)); + } + + for (size_t i = 0; i < MODNAMES.size(); ++i) { + modIndexes.at(i) = xkb_map_mod_get_index(xkbKeymap, MODNAMES.at(i)); + Debug::log(LOG, "xkb: Mod index {} (name {}) got index {}", i, MODNAMES.at(i), modIndexes.at(i)); + } - xkb_state_unref(xkbTranslationState); - xkbTranslationState = nullptr; + auto cKeymapStr = xkb_keymap_get_as_string(xkbKeymap, XKB_KEYMAP_FORMAT_TEXT_V1); + xkbKeymapString = cKeymapStr; + free(cKeymapStr); + + int rw, ro; + if (!allocateSHMFilePair(xkbKeymapString.length() + 1, &rw, &ro)) + Debug::log(ERR, "IKeyboard: failed to allocate shm pair for the keymap"); + else { + auto keymapFDDest = mmap(nullptr, xkbKeymapString.length() + 1, PROT_READ | PROT_WRITE, MAP_SHARED, rw, 0); + close(rw); + if (keymapFDDest == MAP_FAILED) { + Debug::log(ERR, "IKeyboard: failed to mmap a shm pair for the keymap"); + close(ro); + } else { + memcpy(keymapFDDest, xkbKeymapString.c_str(), xkbKeymapString.length()); + munmap(keymapFDDest, xkbKeymapString.length() + 1); + xkbKeymapFD = ro; + } + } + + xkb_context_unref(CONTEXT); + + g_pSeatManager->updateActiveKeyboardData(); } void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { - if (xkbTranslationState) - xkb_state_unref(xkbTranslationState); + if (xkbState) + xkb_state_unref(xkbState); + + xkbState = nullptr; if (keymap) { Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this); - xkbTranslationState = xkb_state_new(keymap); + xkbState = xkb_state_new(keymap); return; } - const auto WLRKB = wlr(); - const auto KEYMAP = WLRKB->keymap; - const auto STATE = WLRKB->xkb_state; + const auto KEYMAP = xkbKeymap; + const auto STATE = xkbState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS); @@ -73,7 +209,7 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); } - xkbTranslationState = xkb_state_new(KEYMAP); + xkbState = xkb_state_new(KEYMAP); xkb_keymap_unref(KEYMAP); xkb_context_unref(PCONTEXT); @@ -94,16 +230,15 @@ void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) { const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); - xkbTranslationState = xkb_state_new(NEWKEYMAP); + xkbState = 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 KEYMAP = xkbKeymap; + const auto STATE = xkbState; const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP); for (uint32_t i = 0; i < LAYOUTSNUM; ++i) { @@ -120,14 +255,12 @@ std::string IKeyboard::getActiveLayout() { } void IKeyboard::updateLEDs() { - auto keyboard = wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (xkbState == 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])) + for (uint32_t i = 0; i < LED_COUNT; ++i) { + if (xkb_state_led_index_is_active(xkbState, ledIndexes.at(i))) leds |= (1 << i); } @@ -135,13 +268,88 @@ void IKeyboard::updateLEDs() { } void IKeyboard::updateLEDs(uint32_t leds) { - auto keyboard = wlr(); - - if (!keyboard || keyboard->xkb_state == nullptr) + if (!xkbState) return; if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock())) return; - wlr_keyboard_led_update(keyboard, leds); + if (!aq()) + return; + + aq()->updateLEDs(leds); +} + +uint32_t IKeyboard::getModifiers() { + uint32_t modMask = modifiersState.depressed | modifiersState.latched; + uint32_t mods = 0; + for (size_t i = 0; i < modIndexes.size(); ++i) { + if (modIndexes.at(i) == XKB_MOD_INVALID) + continue; + + if (!(modMask & (1 << modIndexes.at(i)))) + continue; + + mods |= (1 << i); + } + + return mods; +} + +void IKeyboard::updateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, uint32_t group) { + if (!xkbState) + return; + + xkb_state_update_mask(xkbState, depressed, latched, locked, 0, 0, group); + + if (!updateModifiersState()) + return; + + updateLEDs(); +} + +bool IKeyboard::updateModifiersState() { + if (!xkbState) + return false; + + auto depressed = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_DEPRESSED); + auto latched = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LATCHED); + auto locked = xkb_state_serialize_mods(xkbState, XKB_STATE_MODS_LOCKED); + auto group = xkb_state_serialize_layout(xkbState, XKB_STATE_LAYOUT_EFFECTIVE); + + if (depressed == modifiersState.depressed && latched == modifiersState.latched && locked == modifiersState.locked && group == modifiersState.group) + return false; + + modifiersState.depressed = depressed; + modifiersState.latched = latched; + modifiersState.locked = locked; + modifiersState.group = group; + + return true; +} + +void IKeyboard::updateXkbStateWithKey(uint32_t xkbKey, bool pressed) { + + const auto contains = std::find(pressedXKB.begin(), pressedXKB.end(), xkbKey) != pressedXKB.end(); + + if (contains && pressed) + return; + if (!contains && !pressed) + return; + + if (contains) + std::erase(pressedXKB, xkbKey); + else + pressedXKB.emplace_back(xkbKey); + + xkb_state_update_key(xkbState, xkbKey, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); + + if (updateModifiersState()) { + keyboardEvents.modifiers.emit(SModifiersEvent{ + .depressed = modifiersState.depressed, + .latched = modifiersState.latched, + .locked = modifiersState.locked, + .group = modifiersState.group, + }); + } } |
