devilhorns pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=90551ff49ca66dfef84ff7e6b6ee78468c46304d
commit 90551ff49ca66dfef84ff7e6b6ee78468c46304d Author: Chris Michael <cp.mich...@samsung.com> Date: Mon Mar 10 09:56:50 2014 +0000 ecore-drm: Add code pass along key events to ecore_event @feature: Add keyboard input handling to ecore-drm library This adds code to ecore_drm library to process keyboard events and pass them to ecore_event so that ecore_evas can receive keyboard input Signed-off-by: Chris Michael <cp.mich...@samsung.com> --- src/lib/ecore_drm/ecore_drm_evdev.c | 158 +++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 1 deletion(-) diff --git a/src/lib/ecore_drm/ecore_drm_evdev.c b/src/lib/ecore_drm/ecore_drm_evdev.c index c363d02..83c11fe 100644 --- a/src/lib/ecore_drm/ecore_drm_evdev.c +++ b/src/lib/ecore_drm/ecore_drm_evdev.c @@ -15,8 +15,54 @@ #include "ecore_drm_private.h" #include <sys/ioctl.h> #include <linux/input.h> +#include <ctype.h> /* local functions */ +static void +_device_keyboard_setup(Ecore_Drm_Evdev *edev) +{ + Ecore_Drm_Input *input; + + if ((!edev) || (!edev->seat)) return; + if (!(input = edev->seat->input)) return; + if (!input->dev->xkb_ctx) return; + + /* create keymap from xkb context */ + edev->xkb.keymap = xkb_map_new_from_names(input->dev->xkb_ctx, NULL, 0); + if (!edev->xkb.keymap) + { + ERR("Failed to create keymap: %m"); + return; + } + + /* create xkb state */ + if (!(edev->xkb.state = xkb_state_new(edev->xkb.keymap))) + { + ERR("Failed to create xkb state: %m"); + return; + } + + /* FIXME: setup modifiers ? */ + edev->xkb.modifiers = 0; + + edev->xkb.ctrl_mask = + 1 << xkb_map_mod_get_index(edev->xkb.keymap, XKB_MOD_NAME_CTRL); + edev->xkb.alt_mask = + 1 << xkb_map_mod_get_index(edev->xkb.keymap, XKB_MOD_NAME_ALT); + edev->xkb.shift_mask = + 1 << xkb_map_mod_get_index(edev->xkb.keymap, XKB_MOD_NAME_SHIFT); + edev->xkb.win_mask = + 1 << xkb_map_mod_get_index(edev->xkb.keymap, XKB_MOD_NAME_LOGO); + edev->xkb.scroll_mask = + 1 << xkb_map_mod_get_index(edev->xkb.keymap, XKB_LED_NAME_SCROLL); + edev->xkb.num_mask = + 1 << xkb_map_mod_get_index(edev->xkb.keymap, XKB_LED_NAME_NUM); + edev->xkb.caps_mask = + 1 << xkb_map_mod_get_index(edev->xkb.keymap, XKB_MOD_NAME_CAPS); + edev->xkb.altgr_mask = + 1 << xkb_map_mod_get_index(edev->xkb.keymap, "ISO_Level3_Shift"); +} + static Eina_Bool _device_configure(Ecore_Drm_Evdev *edev) { @@ -36,6 +82,7 @@ _device_configure(Ecore_Drm_Evdev *edev) { DBG("Input device %s is a keyboard", edev->name); edev->seat_caps |= EVDEV_SEAT_KEYBOARD; + _device_keyboard_setup(edev); ret = EINA_TRUE; } @@ -155,13 +202,119 @@ _device_handle(Ecore_Drm_Evdev *edev) return EINA_TRUE; } +static int +_device_keysym_translate(xkb_keysym_t keysym, unsigned int modifiers, char *buffer, int bytes) +{ + unsigned long hbytes = 0; + unsigned char c; + + if (!keysym) return 0; + hbytes = (keysym >> 8); + + if (!(bytes && + ((hbytes == 0) || + ((hbytes == 0xFF) && + (((keysym >= XKB_KEY_BackSpace) && (keysym <= XKB_KEY_Clear)) || + (keysym == XKB_KEY_Return) || (keysym == XKB_KEY_Escape) || + (keysym == XKB_KEY_KP_Space) || (keysym == XKB_KEY_KP_Tab) || + (keysym == XKB_KEY_KP_Enter) || + ((keysym >= XKB_KEY_KP_Multiply) && (keysym <= XKB_KEY_KP_9)) || + (keysym == XKB_KEY_KP_Equal) || (keysym == XKB_KEY_Delete)))))) + return 0; + + if (keysym == XKB_KEY_KP_Space) + c = (XKB_KEY_space & 0x7F); + else if (hbytes == 0xFF) + c = (keysym & 0x7F); + else + c = (keysym & 0xFF); + + if (modifiers & ECORE_EVENT_MODIFIER_CTRL) + { + if (((c >= '@') && (c < '\177')) || c == ' ') + c &= 0x1F; + else if (c == '2') + c = '\000'; + else if ((c >= '3') && (c <= '7')) + c -= ('3' - '\033'); + else if (c == '8') + c = '\177'; + else if (c == '/') + c = '_' & 0x1F; + } + buffer[0] = c; + return 1; +} + static void -_device_notify_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp EINA_UNUSED) +_device_notify_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp) { + unsigned int code, nsyms; + const xkb_keysym_t *syms; + xkb_keysym_t sym = XKB_KEY_NoSymbol; + char key[256], keyname[256], compose[256]; + Ecore_Event_Key *e; + + /* FIXME: This will probably need to handle modifiers also */ + DBG("Key Event"); DBG("\tCode: %d", event->code); DBG("\tValue: %d", event->value); + /* xkb rules reflect X broken keycodes, so offset by 8 */ + code = event->code + 8; + + /* get the keysym for this code */ + nsyms = xkb_key_get_syms(dev->xkb.state, code, &syms); + if (nsyms == 1) sym = syms[0]; + + /* get the keyname for this sym */ + memset(key, 0, sizeof(key)); + xkb_keysym_get_name(sym, key, sizeof(key)); + + memset(keyname, 0, sizeof(keyname)); + memcpy(keyname, key, sizeof(keyname)); + + if (keyname[0] == '\0') + snprintf(keyname, sizeof(keyname), "Keycode-%u", code); + + /* if shift is active, we need to transform the key to lower */ + if (xkb_state_mod_index_is_active(dev->xkb.state, + xkb_map_mod_get_index(dev->xkb.keymap, + XKB_MOD_NAME_SHIFT), + XKB_STATE_MODS_EFFECTIVE)) + { + if (keyname[0] != '\0') + keyname[0] = tolower(keyname[0]); + } + + memset(compose, 0, sizeof(compose)); + _device_keysym_translate(sym, dev->xkb.modifiers, compose, sizeof(compose)); + + e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + + ((compose[0] != '\0') ? strlen(compose) : 0) + 3); + if (!e) return; + + e->keyname = (char *)(e + 1); + e->key = e->keyname + strlen(keyname) + 1; + e->compose = strlen(compose) ? e->key + strlen(key) + 1 : NULL; + e->string = e->compose; + + strcpy((char *)e->keyname, keyname); + strcpy((char *)e->key, key); + if (strlen(compose)) strcpy((char *)e->compose, compose); + + /* e->window = win->id; */ + /* e->event_window = win->id; */ + e->timestamp = timestamp; + + e->modifiers = dev->xkb.modifiers; + + if (event->value) + ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL); + else + ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL); + if ((event->code >= KEY_ESC) && (event->code <= KEY_COMPOSE)) { /* ignore key repeat */ @@ -352,6 +505,9 @@ _ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *dev) { if (!dev) return; + if (dev->xkb.state) xkb_state_unref(dev->xkb.state); + if (dev->xkb.keymap) xkb_map_unref(dev->xkb.keymap); + if (dev->path) eina_stringshare_del(dev->path); if (dev->name) eina_stringshare_del(dev->name); if (dev->hdlr) ecore_main_fd_handler_del(dev->hdlr); --