From 2c043ca2057af6338ad8ff43c044d3b0f602898c Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 26 May 2016 12:36:51 -0400 Subject: [PATCH] elput: Add APIs to support keyboard key remapping This patch adds 2 new API functions which can enable keyboard key remapping, and set which keys are to be remapped. @feature Signed-off-by: Chris Michael --- src/lib/elput/Elput.h | 28 +++++++++++++++ src/lib/elput/elput_evdev.c | 21 ++++++++++- src/lib/elput/elput_input.c | 66 +++++++++++++++++++++++++++++++++++ src/lib/elput/elput_private.h | 3 ++ 4 files changed, 117 insertions(+), 1 deletion(-) diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h index 8d3d6f6669..a7f0b7e4da 100644 --- a/src/lib/elput/Elput.h +++ b/src/lib/elput/Elput.h @@ -351,6 +351,34 @@ EAPI void elput_input_pointer_max_set(Elput_Manager *manager, int maxw, int maxh */ EAPI void elput_input_devices_calibrate(Elput_Manager *manager, int w, int h); +/** + * Enable key remap functionality + * + * @param manager + * @param enable + * + * @return EINA_TRUE on success, EINA_FALSE otherwise + * + * @ingroup Elput_Input_Group + * @since 1.18 + */ +EAPI Eina_Bool elput_input_key_remap_enable(Elput_Manager *manager, Eina_Bool enable); + +/** + * Set a given set of keys as remapped keys + * + * @param manager + * @param from_keys + * @param to_keys + * @param num + * + * @return EINA_TRUE on success, EINA_FALSE otherwise + * + * @ingroup Elput_Input_Group + * @since 1.18 + */ +EAPI Eina_Bool elput_input_key_remap_set(Elput_Manager *manager, int *from_keys, int *to_keys, int num); + # endif # undef EAPI diff --git a/src/lib/elput/elput_evdev.c b/src/lib/elput/elput_evdev.c index 82768d6b35..c083a1783b 100644 --- a/src/lib/elput/elput_evdev.c +++ b/src/lib/elput/elput_evdev.c @@ -383,6 +383,20 @@ _keyboard_keymap_update(Elput_Seat *seat) _keyboard_modifiers_send(kbd); } +static int +_keyboard_remapped_key_get(Elput_Device *edev, int code) +{ + void *ret = NULL; + + if (!edev) return code; + if (!edev->key_remap) return code; + if (!edev->key_remap_hash) return code; + + ret = eina_hash_find(edev->key_remap_hash, &code); + if (ret) code = (int)(intptr_t)ret; + return code; +} + static int _keyboard_keysym_translate(xkb_keysym_t keysym, unsigned int modifiers, char *buffer, int bytes) { @@ -456,7 +470,9 @@ _keyboard_key(struct libinput_device *idevice, struct libinput_event_keyboard *e ((state == LIBINPUT_KEY_STATE_RELEASED) && (count != 0))) return; - code = libinput_event_keyboard_get_key(event) + 8; + code = libinput_event_keyboard_get_key(event); + code = _keyboard_remapped_key_get(dev, code) + 8; + timestamp = libinput_event_keyboard_get_time(event); if (state == LIBINPUT_KEY_STATE_PRESSED) @@ -1280,6 +1296,9 @@ _evdev_device_destroy(Elput_Device *edev) libinput_device_unref(edev->device); eina_stringshare_del(edev->output_name); + + if (edev->key_remap_hash) eina_hash_free(edev->key_remap_hash); + free(edev); } diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c index b427c38ed1..e838c9b212 100644 --- a/src/lib/elput/elput_input.c +++ b/src/lib/elput/elput_input.c @@ -510,3 +510,69 @@ elput_input_devices_calibrate(Elput_Manager *manager, int w, int h) } } } + +EAPI Eina_Bool +elput_input_key_remap_enable(Elput_Manager *manager, Eina_Bool enable) +{ + Elput_Seat *eseat; + Elput_Device *edev; + Eina_List *l, *ll; + + EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE); + + EINA_LIST_FOREACH(manager->input.seats, l, eseat) + { + EINA_LIST_FOREACH(eseat->devices, ll, edev) + { + if (!(edev->caps & EVDEV_SEAT_KEYBOARD)) continue; + + edev->key_remap = enable; + if ((!enable) && (edev->key_remap_hash)) + { + eina_hash_free(edev->key_remap_hash); + edev->key_remap_hash = NULL; + } + } + } + + return EINA_TRUE; +} + +EAPI Eina_Bool +elput_input_key_remap_set(Elput_Manager *manager, int *from_keys, int *to_keys, int num) +{ + Elput_Seat *eseat; + Elput_Device *edev; + Eina_List *l, *ll; + int i = 0; + + EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(from_keys, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(to_keys, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL((num <= 0), EINA_FALSE); + + EINA_LIST_FOREACH(manager->input.seats, l, eseat) + { + EINA_LIST_FOREACH(eseat->devices, ll, edev) + { + if (!(edev->caps & EVDEV_SEAT_KEYBOARD)) continue; + + if (!edev->key_remap) continue; + if (!edev->key_remap_hash) + edev->key_remap_hash = eina_hash_int32_new(NULL); + if (!edev->key_remap_hash) continue; + + for (i = 0; i < num; i++) + { + if ((!from_keys[i]) || (!to_keys[i])) + continue; + } + + for (i = 0; i < num; i++) + eina_hash_add(edev->key_remap_hash, &from_keys[i], + (void *)(intptr_t)to_keys[i]); + } + } + + return EINA_TRUE; +} diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h index dc34f24099..2d9de141f9 100644 --- a/src/lib/elput/elput_private.h +++ b/src/lib/elput/elput_private.h @@ -217,7 +217,10 @@ struct _Elput_Device Elput_Device_Capability caps; + Eina_Hash *key_remap_hash; + Eina_Bool left_handed : 1; + Eina_Bool key_remap : 1; }; struct _Elput_Manager