summaryrefslogtreecommitdiff
path: root/src/devices/IKeyboard.cpp
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2024-05-03 22:34:10 +0100
committerVaxry <vaxry@vaxry.net>2024-05-03 22:40:27 +0100
commit1237732b97fcf21a19aed16f2ef966118a3ca2aa (patch)
tree15a3a29377af7f0ce3dd428229587e476ce92db3 /src/devices/IKeyboard.cpp
parent1d2acbe19355c8640d54a4b6cba225c6f4370c85 (diff)
input: Introduce basic hyprland HID classes
Implements an intermediary HID class for mice, keyboards and touch devices, removing the old structs from WLClasses.hpp Yes, virtual ones are duplicated a bit, but will likely be de-duped once wlr_input_device is not used anymore.
Diffstat (limited to 'src/devices/IKeyboard.cpp')
-rw-r--r--src/devices/IKeyboard.cpp134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/devices/IKeyboard.cpp b/src/devices/IKeyboard.cpp
new file mode 100644
index 00000000..790766bc
--- /dev/null
+++ b/src/devices/IKeyboard.cpp
@@ -0,0 +1,134 @@
+#include "IKeyboard.hpp"
+#include "../defines.hpp"
+#include "../helpers/VarList.hpp"
+#include "../managers/input/InputManager.hpp"
+
+uint32_t IKeyboard::getCapabilities() {
+ return HID_INPUT_CAPABILITY_KEYBOARD;
+}
+
+IKeyboard::~IKeyboard() {
+ events.destroy.emit();
+
+ if (!xkbTranslationState)
+ return;
+
+ xkb_state_unref(xkbTranslationState);
+ xkbTranslationState = nullptr;
+}
+
+void IKeyboard::updateXKBTranslationState(xkb_keymap* const keymap) {
+
+ if (xkbTranslationState)
+ xkb_state_unref(xkbTranslationState);
+
+ if (keymap) {
+ Debug::log(LOG, "Updating keyboard {:x}'s translation state from a provided keymap", (uintptr_t)this);
+ xkbTranslationState = xkb_state_new(keymap);
+ return;
+ }
+
+ const auto WLRKB = wlr();
+ const auto KEYMAP = WLRKB->keymap;
+ const auto STATE = WLRKB->xkb_state;
+ const auto LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
+
+ const auto PCONTEXT = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+
+ for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
+ if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) {
+ Debug::log(LOG, "Updating keyboard {:x}'s translation state from an active index {}", (uintptr_t)this, i);
+
+ CVarList keyboardLayouts(currentRules.layout, 0, ',');
+ CVarList keyboardModels(currentRules.model, 0, ',');
+ CVarList keyboardVariants(currentRules.variant, 0, ',');
+
+ xkb_rule_names rules = {.rules = "", .model = "", .layout = "", .variant = "", .options = ""};
+
+ std::string layout, model, variant;
+ layout = keyboardLayouts[i % keyboardLayouts.size()];
+ model = keyboardModels[i % keyboardModels.size()];
+ variant = keyboardVariants[i % keyboardVariants.size()];
+
+ rules.layout = layout.c_str();
+ rules.model = model.c_str();
+ rules.variant = variant.c_str();
+
+ auto KEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, 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);
+ }
+
+ 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);
+ }
+
+ xkbTranslationState = xkb_state_new(KEYMAP);
+
+ xkb_keymap_unref(KEYMAP);
+ xkb_context_unref(PCONTEXT);
+
+ return;
+ }
+ }
+
+ Debug::log(LOG, "Updating keyboard {:x}'s translation state from an unknown index", (uintptr_t)this);
+
+ xkb_rule_names rules = {
+ .rules = currentRules.rules.c_str(),
+ .model = currentRules.model.c_str(),
+ .layout = currentRules.layout.c_str(),
+ .variant = currentRules.variant.c_str(),
+ .options = currentRules.options.c_str(),
+ };
+
+ const auto NEWKEYMAP = xkb_keymap_new_from_names(PCONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS);
+
+ xkbTranslationState = 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 LAYOUTSNUM = xkb_keymap_num_layouts(KEYMAP);
+
+ for (uint32_t i = 0; i < LAYOUTSNUM; ++i) {
+ if (xkb_state_layout_index_is_active(STATE, i, XKB_STATE_LAYOUT_EFFECTIVE)) {
+ const auto LAYOUTNAME = xkb_keymap_layout_get_name(KEYMAP, i);
+
+ if (LAYOUTNAME)
+ return std::string(LAYOUTNAME);
+ return "error";
+ }
+ }
+
+ return "none";
+}
+
+void IKeyboard::updateLEDs() {
+ auto keyboard = wlr();
+
+ if (keyboard->xkb_state == 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]))
+ leds |= (1 << i);
+ }
+
+ if (isVirtual() && g_pInputManager->shouldIgnoreVirtualKeyboard(self.lock()))
+ return;
+
+ wlr_keyboard_led_update(wlr(), leds);
+}