summaryrefslogtreecommitdiff
path: root/src/devices/IKeyboard.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2024-07-21 13:09:54 +0200
committerGitHub <noreply@github.com>2024-07-21 13:09:54 +0200
commit016da234d0e852de3ef20eb2e89ac58d2a85f6e7 (patch)
tree496085987176551b0794fffc069877d44943e2f1 /src/devices/IKeyboard.cpp
parentf642fb97df5c69267a03452533de383ff8023570 (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.cpp254
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,
+ });
+ }
}