2016-04-06 05:46:29 -07:00
|
|
|
#include "elput_private.h"
|
|
|
|
|
2017-06-02 15:23:45 -07:00
|
|
|
static void
|
|
|
|
_seat_event_free(void *d, void *ev EINA_UNUSED)
|
|
|
|
{
|
|
|
|
_udev_seat_destroy(d);
|
|
|
|
}
|
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
static void
|
|
|
|
_seat_caps_update(Elput_Seat *seat)
|
|
|
|
{
|
2016-04-06 07:26:46 -07:00
|
|
|
Elput_Event_Seat_Caps *ev;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Elput_Event_Seat_Caps));
|
|
|
|
if (!ev) return;
|
|
|
|
|
|
|
|
ev->pointer_count = seat->count.ptr;
|
|
|
|
ev->keyboard_count = seat->count.kbd;
|
|
|
|
ev->touch_count = seat->count.touch;
|
|
|
|
ev->seat = seat;
|
2017-06-02 15:23:45 -07:00
|
|
|
seat->refs++;
|
2016-04-06 07:26:46 -07:00
|
|
|
|
2017-06-02 15:23:45 -07:00
|
|
|
ecore_event_add(ELPUT_EVENT_SEAT_CAPS, ev, _seat_event_free, seat);
|
2016-04-06 05:46:29 -07:00
|
|
|
}
|
|
|
|
|
2016-04-06 07:38:08 -07:00
|
|
|
static void
|
|
|
|
_seat_frame_send(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
Elput_Event_Seat_Frame *ev;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Elput_Event_Seat_Frame));
|
|
|
|
if (!ev) return;
|
|
|
|
|
|
|
|
ev->seat = seat;
|
2017-06-02 15:23:45 -07:00
|
|
|
seat->refs++;
|
|
|
|
ecore_event_add(ELPUT_EVENT_SEAT_FRAME, ev, _seat_event_free, seat);
|
2016-04-06 07:38:08 -07:00
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
static void
|
|
|
|
_keyboard_modifiers_update(Elput_Keyboard *kbd, Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
xkb_mod_mask_t mask;
|
|
|
|
|
|
|
|
kbd->mods.depressed =
|
|
|
|
xkb_state_serialize_mods(kbd->state, XKB_STATE_DEPRESSED);
|
|
|
|
kbd->mods.latched =
|
|
|
|
xkb_state_serialize_mods(kbd->state, XKB_STATE_LATCHED);
|
|
|
|
kbd->mods.locked =
|
|
|
|
xkb_state_serialize_mods(kbd->state, XKB_STATE_LOCKED);
|
|
|
|
kbd->mods.group =
|
|
|
|
xkb_state_serialize_mods(kbd->state, XKB_STATE_EFFECTIVE);
|
|
|
|
|
|
|
|
mask = (kbd->mods.depressed | kbd->mods.latched);
|
|
|
|
|
|
|
|
seat->modifiers = 0;
|
|
|
|
if (mask & kbd->info->mods.ctrl)
|
|
|
|
seat->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
|
|
|
|
if (mask & kbd->info->mods.alt)
|
|
|
|
seat->modifiers |= ECORE_EVENT_MODIFIER_ALT;
|
|
|
|
if (mask & kbd->info->mods.shift)
|
|
|
|
seat->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
|
|
|
|
if (mask & kbd->info->mods.super)
|
|
|
|
seat->modifiers |= ECORE_EVENT_MODIFIER_WIN;
|
|
|
|
if (mask & kbd->info->mods.altgr)
|
|
|
|
seat->modifiers |= ECORE_EVENT_MODIFIER_ALTGR;
|
|
|
|
}
|
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
static int
|
|
|
|
_keyboard_fd_get(off_t size)
|
|
|
|
{
|
2017-02-08 16:27:41 -08:00
|
|
|
Eina_Tmpstr *fullname;
|
2016-07-08 20:01:51 -07:00
|
|
|
int fd = 0;
|
2017-02-08 16:27:41 -08:00
|
|
|
Efl_Vpath_File *file_obj;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
2017-02-09 15:58:29 -08:00
|
|
|
file_obj = efl_vpath_manager_fetch(EFL_VPATH_MANAGER_CLASS,
|
|
|
|
"(:run:)/elput-keymap-XXXXXX");
|
|
|
|
fd = eina_file_mkstemp(efl_vpath_file_result_get(file_obj), &fullname);
|
2017-02-08 16:27:41 -08:00
|
|
|
efl_del(file_obj);
|
2016-04-06 05:46:29 -07:00
|
|
|
|
2016-07-08 05:48:27 -07:00
|
|
|
if (fd < 0) return -1;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
2017-04-18 16:56:56 -07:00
|
|
|
if (!eina_file_close_on_exec(fd, EINA_TRUE))
|
2016-04-06 05:46:29 -07:00
|
|
|
{
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ftruncate(fd, size) < 0)
|
|
|
|
{
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-07-26 10:34:27 -07:00
|
|
|
unlink(fullname);
|
|
|
|
eina_tmpstr_del(fullname);
|
2016-04-06 05:46:29 -07:00
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Elput_Keyboard_Info *
|
2017-05-26 13:34:10 -07:00
|
|
|
_keyboard_info_create(struct xkb_keymap *keymap)
|
2016-04-06 05:46:29 -07:00
|
|
|
{
|
|
|
|
Elput_Keyboard_Info *info;
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
info = calloc(1, sizeof(Elput_Keyboard_Info));
|
|
|
|
if (!info) return NULL;
|
|
|
|
|
|
|
|
info->keymap.map = xkb_keymap_ref(keymap);
|
|
|
|
info->refs = 1;
|
|
|
|
|
|
|
|
info->mods.super =
|
|
|
|
1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_LOGO);
|
|
|
|
info->mods.shift =
|
|
|
|
1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_SHIFT);
|
|
|
|
info->mods.caps =
|
|
|
|
1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_CAPS);
|
|
|
|
info->mods.ctrl =
|
|
|
|
1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_CTRL);
|
|
|
|
info->mods.alt =
|
|
|
|
1 << xkb_keymap_mod_get_index(info->keymap.map, XKB_MOD_NAME_ALT);
|
|
|
|
info->mods.altgr =
|
|
|
|
1 << xkb_keymap_mod_get_index(info->keymap.map, "ISO_Level3_Shift");
|
|
|
|
|
|
|
|
str = xkb_keymap_get_as_string(info->keymap.map, XKB_KEYMAP_FORMAT_TEXT_V1);
|
|
|
|
if (!str) goto err;
|
|
|
|
|
|
|
|
info->keymap.size = strlen(str) + 1;
|
|
|
|
|
|
|
|
info->keymap.fd = _keyboard_fd_get(info->keymap.size);
|
|
|
|
if (info->keymap.fd < 0) goto err_fd;
|
|
|
|
|
|
|
|
info->keymap.area =
|
|
|
|
mmap(NULL, info->keymap.size, PROT_READ | PROT_WRITE,
|
|
|
|
MAP_SHARED, info->keymap.fd, 0);
|
|
|
|
if (info->keymap.area == MAP_FAILED) goto err_map;
|
|
|
|
|
|
|
|
strcpy(info->keymap.area, str);
|
|
|
|
free(str);
|
|
|
|
|
|
|
|
return info;
|
|
|
|
|
|
|
|
err_map:
|
|
|
|
close(info->keymap.fd);
|
|
|
|
err_fd:
|
|
|
|
free(str);
|
|
|
|
err:
|
|
|
|
xkb_keymap_unref(info->keymap.map);
|
|
|
|
free(info);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-05-26 13:34:10 -07:00
|
|
|
_keyboard_info_destroy(Elput_Keyboard_Info *info)
|
2016-04-06 05:46:29 -07:00
|
|
|
{
|
|
|
|
if (--info->refs > 0) return;
|
|
|
|
|
2016-05-27 06:17:46 -07:00
|
|
|
xkb_keymap_unref(info->keymap.map);
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (info->keymap.area) munmap(info->keymap.area, info->keymap.size);
|
|
|
|
if (info->keymap.fd >= 0) close(info->keymap.fd);
|
2016-04-06 05:46:29 -07:00
|
|
|
|
|
|
|
free(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_keyboard_global_build(Elput_Keyboard *kbd)
|
|
|
|
{
|
|
|
|
struct xkb_keymap *keymap;
|
|
|
|
|
|
|
|
kbd->context = xkb_context_new(0);
|
|
|
|
if (!kbd->context) return EINA_FALSE;
|
|
|
|
|
|
|
|
if (!kbd->names.rules) kbd->names.rules = strdup("evdev");
|
|
|
|
if (!kbd->names.model) kbd->names.model = strdup("pc105");
|
|
|
|
if (!kbd->names.layout) kbd->names.layout = strdup("us");
|
|
|
|
|
|
|
|
keymap = xkb_keymap_new_from_names(kbd->context, &kbd->names, 0);
|
|
|
|
if (!keymap) return EINA_FALSE;
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
kbd->info = _keyboard_info_create(keymap);
|
2016-04-06 05:46:29 -07:00
|
|
|
xkb_keymap_unref(keymap);
|
|
|
|
|
|
|
|
if (!kbd->info) return EINA_FALSE;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Elput_Keyboard *
|
|
|
|
_keyboard_create(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
Elput_Keyboard *kbd;
|
|
|
|
|
|
|
|
kbd = calloc(1, sizeof(Elput_Keyboard));
|
|
|
|
if (!kbd) return NULL;
|
|
|
|
|
|
|
|
kbd->seat = seat;
|
2016-05-27 06:12:53 -07:00
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
return kbd;
|
|
|
|
}
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
static void
|
|
|
|
_keyboard_compose_init(Elput_Keyboard *kbd)
|
|
|
|
{
|
|
|
|
const char *locale;
|
|
|
|
if (!(locale = getenv("LC_ALL")))
|
|
|
|
if (!(locale = getenv("LC_CTYPE")))
|
|
|
|
if (!(locale = getenv("LANG")))
|
|
|
|
locale = "C";
|
|
|
|
if (kbd->compose_table) xkb_compose_table_unref(kbd->compose_table);
|
|
|
|
kbd->compose_table = xkb_compose_table_new_from_locale(kbd->context, locale,
|
|
|
|
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
2017-06-02 15:23:44 -07:00
|
|
|
if (kbd->compose_state) xkb_compose_state_unref(kbd->compose_state);
|
2017-05-26 13:34:10 -07:00
|
|
|
if (kbd->compose_table)
|
2017-06-02 15:23:44 -07:00
|
|
|
kbd->compose_state = xkb_compose_state_new(kbd->compose_table, XKB_COMPOSE_STATE_NO_FLAGS);
|
|
|
|
else
|
|
|
|
kbd->compose_state = NULL;
|
2017-05-26 13:34:10 -07:00
|
|
|
}
|
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_keyboard_init(Elput_Seat *seat, struct xkb_keymap *keymap)
|
|
|
|
{
|
|
|
|
Elput_Keyboard *kbd;
|
|
|
|
|
|
|
|
if (seat->kbd)
|
|
|
|
{
|
|
|
|
seat->count.kbd += 1;
|
|
|
|
if (seat->count.kbd == 1)
|
2016-07-25 07:54:17 -07:00
|
|
|
_seat_caps_update(seat);
|
|
|
|
return EINA_TRUE;
|
2016-04-06 05:46:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
kbd = _keyboard_create(seat);
|
|
|
|
if (!kbd) return EINA_FALSE;
|
|
|
|
|
|
|
|
if (keymap)
|
|
|
|
{
|
2017-05-26 13:34:10 -07:00
|
|
|
if (seat->manager->cached.keymap == keymap)
|
|
|
|
kbd->context = xkb_context_ref(seat->manager->cached.context);
|
|
|
|
kbd->info = _keyboard_info_create(keymap);
|
2016-04-06 05:46:29 -07:00
|
|
|
if (!kbd->info) goto err;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!_keyboard_global_build(kbd)) goto err;
|
|
|
|
kbd->info->refs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
kbd->state = xkb_state_new(kbd->info->keymap.map);
|
|
|
|
if (!kbd->state) goto err;
|
2017-05-26 13:34:10 -07:00
|
|
|
kbd->maskless_state = xkb_state_new(kbd->info->keymap.map);
|
2016-04-06 05:46:29 -07:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
_keyboard_compose_init(kbd);
|
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
seat->kbd = kbd;
|
|
|
|
seat->count.kbd = 1;
|
|
|
|
|
|
|
|
_seat_caps_update(seat);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
err:
|
2017-05-26 13:34:10 -07:00
|
|
|
if (kbd->info) _keyboard_info_destroy(kbd->info);
|
2016-04-06 05:46:29 -07:00
|
|
|
free(kbd);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_keyboard_state_reset(Elput_Keyboard *kbd)
|
|
|
|
{
|
|
|
|
struct xkb_state *state;
|
|
|
|
|
|
|
|
state = xkb_state_new(kbd->info->keymap.map);
|
|
|
|
if (!state) return;
|
|
|
|
|
|
|
|
xkb_state_unref(kbd->state);
|
|
|
|
kbd->state = state;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_keyboard_release(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
seat->count.kbd--;
|
|
|
|
if (seat->count.kbd == 0)
|
|
|
|
{
|
|
|
|
_keyboard_state_reset(seat->kbd);
|
|
|
|
_seat_caps_update(seat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
static void
|
|
|
|
_keyboard_key_send(Elput_Device *dev, enum libinput_key_state state, const char *keyname, const char *key, const char *compose, unsigned int code, unsigned int timestamp)
|
|
|
|
{
|
|
|
|
Ecore_Event_Key *ev;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) +
|
|
|
|
((compose[0] != '\0') ? strlen(compose) : 0) + 3);
|
|
|
|
if (!ev) return;
|
|
|
|
|
|
|
|
ev->keyname = (char *)(ev + 1);
|
|
|
|
ev->key = ev->keyname + strlen(keyname) + 1;
|
|
|
|
ev->compose = strlen(compose) ? ev->key + strlen(key) + 1 : NULL;
|
|
|
|
ev->string = ev->compose;
|
|
|
|
|
|
|
|
strcpy((char *)ev->keyname, keyname);
|
|
|
|
strcpy((char *)ev->key, key);
|
|
|
|
if (strlen(compose)) strcpy((char *)ev->compose, compose);
|
|
|
|
|
|
|
|
ev->keycode = code;
|
|
|
|
ev->modifiers = dev->seat->modifiers;
|
|
|
|
ev->timestamp = timestamp;
|
|
|
|
ev->same_screen = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->dev = dev->evas_device;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2016-05-25 09:49:44 -07:00
|
|
|
ev->window = dev->seat->manager->window;
|
|
|
|
ev->event_window = dev->seat->manager->window;
|
|
|
|
ev->root_window = dev->seat->manager->window;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
if (state == LIBINPUT_KEY_STATE_PRESSED)
|
|
|
|
ecore_event_add(ECORE_EVENT_KEY_DOWN, ev, NULL, NULL);
|
|
|
|
else
|
|
|
|
ecore_event_add(ECORE_EVENT_KEY_UP, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_keyboard_keymap_send(Elput_Keyboard_Info *info)
|
|
|
|
{
|
|
|
|
Elput_Event_Keymap_Send *ev;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Elput_Event_Keymap_Send));
|
|
|
|
if (!ev) return;
|
|
|
|
|
|
|
|
ev->fd = info->keymap.fd;
|
|
|
|
ev->size = info->keymap.size;
|
|
|
|
ev->format = XKB_KEYMAP_FORMAT_TEXT_V1;
|
|
|
|
|
|
|
|
ecore_event_add(ELPUT_EVENT_KEYMAP_SEND, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_keyboard_modifiers_send(Elput_Keyboard *kbd)
|
|
|
|
{
|
|
|
|
Elput_Event_Modifiers_Send *ev;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Elput_Event_Modifiers_Send));
|
|
|
|
if (!ev) return;
|
|
|
|
|
|
|
|
ev->depressed = kbd->mods.depressed;
|
|
|
|
ev->latched = kbd->mods.latched;
|
|
|
|
ev->locked = kbd->mods.locked;
|
|
|
|
ev->group = kbd->mods.group;
|
|
|
|
|
|
|
|
ecore_event_add(ELPUT_EVENT_MODIFIERS_SEND, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_keyboard_state_update(Elput_Keyboard *kbd, struct xkb_keymap *map, xkb_mod_mask_t *latched, xkb_mod_mask_t *locked)
|
|
|
|
{
|
|
|
|
struct xkb_state *state, *maskless_state;
|
|
|
|
|
|
|
|
state = xkb_state_new(map);
|
|
|
|
if (!state) return EINA_FALSE;
|
|
|
|
maskless_state = xkb_state_new(map);
|
|
|
|
if (!maskless_state)
|
|
|
|
{
|
|
|
|
xkb_state_unref(state);
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
*latched = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LATCHED);
|
|
|
|
*locked = xkb_state_serialize_mods(kbd->state, XKB_STATE_MODS_LOCKED);
|
|
|
|
xkb_state_update_mask(state, 0, *latched, *locked, kbd->seat->manager->cached.group, 0, 0);
|
|
|
|
|
|
|
|
xkb_state_unref(kbd->state);
|
|
|
|
kbd->state = state;
|
|
|
|
xkb_state_unref(kbd->maskless_state);
|
|
|
|
kbd->maskless_state = maskless_state;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-04-06 08:32:42 -07:00
|
|
|
_keyboard_keymap_update(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
Elput_Keyboard *kbd;
|
2017-05-26 13:34:10 -07:00
|
|
|
Elput_Keyboard_Info *info = NULL;
|
2016-04-06 08:32:42 -07:00
|
|
|
xkb_mod_mask_t latched, locked;
|
2017-05-26 13:34:10 -07:00
|
|
|
Eina_Bool state = EINA_TRUE;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
kbd = _evdev_keyboard_get(seat);
|
|
|
|
if (!kbd) return;
|
2017-05-26 13:34:10 -07:00
|
|
|
kbd->pending_keymap = 1;
|
|
|
|
if (kbd->key_count) return;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (kbd->seat->manager->cached.keymap)
|
|
|
|
{
|
|
|
|
if (kbd->context) xkb_context_unref(kbd->context);
|
|
|
|
kbd->context = xkb_context_ref(kbd->seat->manager->cached.context);
|
|
|
|
info = _keyboard_info_create(kbd->seat->manager->cached.keymap);
|
|
|
|
if (!info) return;
|
|
|
|
state = _keyboard_state_update(kbd, info->keymap.map, &latched, &locked);
|
|
|
|
}
|
|
|
|
else if (!_keyboard_global_build(kbd)) return;
|
|
|
|
else
|
|
|
|
state = _keyboard_state_update(kbd, kbd->info->keymap.map, &latched, &locked);
|
|
|
|
kbd->pending_keymap = 0;
|
2016-04-06 08:32:42 -07:00
|
|
|
if (!state)
|
|
|
|
{
|
2017-05-26 13:34:10 -07:00
|
|
|
if (info) _keyboard_info_destroy(info);
|
2016-04-06 08:32:42 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (info)
|
|
|
|
{
|
|
|
|
_keyboard_info_destroy(kbd->info);
|
|
|
|
kbd->info = info;
|
|
|
|
}
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
_keyboard_compose_init(kbd);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
_keyboard_modifiers_update(kbd, seat);
|
|
|
|
_keyboard_keymap_send(kbd->info);
|
|
|
|
|
|
|
|
if ((!latched) && (!locked)) return;
|
|
|
|
|
|
|
|
_keyboard_modifiers_send(kbd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_keyboard_group_update(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
Elput_Keyboard *kbd;
|
|
|
|
xkb_mod_mask_t latched, locked;
|
|
|
|
Eina_Bool state;
|
|
|
|
|
|
|
|
kbd = _evdev_keyboard_get(seat);
|
|
|
|
if (!kbd) return;
|
|
|
|
|
|
|
|
state = _keyboard_state_update(kbd, kbd->info->keymap.map, &latched, &locked);
|
|
|
|
if (!state) return;
|
|
|
|
_keyboard_compose_init(kbd);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
_keyboard_modifiers_update(kbd, seat);
|
|
|
|
_keyboard_keymap_send(kbd->info);
|
|
|
|
|
|
|
|
if ((!latched) && (!locked)) return;
|
|
|
|
|
|
|
|
_keyboard_modifiers_send(kbd);
|
|
|
|
}
|
|
|
|
|
2016-05-26 09:36:51 -07:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
static int
|
|
|
|
_keyboard_keysym_translate(xkb_keysym_t keysym, unsigned int modifiers, char *buffer, int bytes)
|
|
|
|
{
|
2017-05-26 13:34:10 -07:00
|
|
|
/* this function is copied, with slight changes in variable names, from KeyBind.c in libX11
|
|
|
|
* the license from that file can be found below:
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
|
|
|
|
Copyright 1985, 1987, 1998 The Open Group
|
|
|
|
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
the above copyright notice appear in all copies and that both that
|
|
|
|
copyright notice and this permission notice appear in supporting
|
|
|
|
documentation.
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
Except as contained in this notice, the name of The Open Group shall not be
|
|
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
|
|
in this Software without prior written authorization from The Open Group.
|
|
|
|
|
|
|
|
*/
|
2016-04-06 08:32:42 -07:00
|
|
|
if (!keysym) return 0;
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
/* check for possible control codes */
|
2016-04-06 08:32:42 -07:00
|
|
|
if (modifiers & ECORE_EVENT_MODIFIER_CTRL)
|
|
|
|
{
|
2017-05-26 13:34:10 -07:00
|
|
|
Eina_Bool valid_control_code = EINA_TRUE;
|
|
|
|
unsigned long hbytes = 0;
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
/* We are building here a control code
|
|
|
|
for more details, read:
|
|
|
|
https://en.wikipedia.org/wiki/C0_and_C1_control_codes#C0_.28ASCII_and_derivatives.29
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (((c >= '@') && (c <= '_')) || /* those are the one defined in C0 with capital letters */
|
|
|
|
((c >= 'a') && (c <= 'z')) || /* the lowercase symbols (not part of the standard, but usefull */
|
|
|
|
c == ' ')
|
2016-04-06 08:32:42 -07:00
|
|
|
c &= 0x1F;
|
2017-05-26 13:34:10 -07:00
|
|
|
else if (c == '\x7f')
|
|
|
|
c = '\177';
|
|
|
|
/* following codes are alternatives, they are longer here, i dont want to change them */
|
2016-04-06 08:32:42 -07:00
|
|
|
else if (c == '2')
|
2017-05-26 13:34:10 -07:00
|
|
|
c = '\000'; /* 0 code */
|
2016-04-06 08:32:42 -07:00
|
|
|
else if ((c >= '3') && (c <= '7'))
|
2017-05-26 13:34:10 -07:00
|
|
|
c -= ('3' - '\033'); /* from escape to unitseperator code*/
|
2016-04-06 08:32:42 -07:00
|
|
|
else if (c == '8')
|
2017-05-26 13:34:10 -07:00
|
|
|
c = '\177'; /* delete code */
|
2016-04-06 08:32:42 -07:00
|
|
|
else if (c == '/')
|
2017-05-26 13:34:10 -07:00
|
|
|
c = '_' & 0x1F; /* unit seperator code */
|
|
|
|
else
|
|
|
|
valid_control_code = EINA_FALSE;
|
|
|
|
|
|
|
|
if (valid_control_code)
|
|
|
|
buffer[0] = c;
|
|
|
|
else
|
|
|
|
return 0;
|
2016-04-06 08:32:42 -07:00
|
|
|
}
|
2017-05-26 13:34:10 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* if its not a control code, try to produce a usefull output */
|
|
|
|
if (!xkb_keysym_to_utf8(keysym, buffer, bytes))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
/* from weston/clients/window.c */
|
|
|
|
/* Translate symbols appropriately if a compose sequence is being entered */
|
|
|
|
static xkb_keysym_t
|
|
|
|
process_key_press(xkb_keysym_t sym, Elput_Keyboard *kbd)
|
|
|
|
{
|
|
|
|
if (!kbd->compose_state)
|
|
|
|
return sym;
|
|
|
|
if (sym == XKB_KEY_NoSymbol)
|
|
|
|
return sym;
|
|
|
|
if (xkb_compose_state_feed(kbd->compose_state, sym) != XKB_COMPOSE_FEED_ACCEPTED)
|
|
|
|
return sym;
|
|
|
|
|
|
|
|
switch (xkb_compose_state_get_status(kbd->compose_state))
|
|
|
|
{
|
|
|
|
case XKB_COMPOSE_COMPOSING:
|
|
|
|
return XKB_KEY_NoSymbol;
|
|
|
|
case XKB_COMPOSE_COMPOSED:
|
|
|
|
return xkb_compose_state_get_one_sym(kbd->compose_state);
|
|
|
|
case XKB_COMPOSE_CANCELLED:
|
|
|
|
return XKB_KEY_NoSymbol;
|
|
|
|
case XKB_COMPOSE_NOTHING:
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
return sym;
|
|
|
|
}
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
static void
|
|
|
|
_elput_symbol_rep_find(xkb_keysym_t keysym, char *buffer, int size, unsigned int code)
|
|
|
|
{
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
n = xkb_keysym_to_utf8(keysym, buffer, size);
|
|
|
|
|
|
|
|
/* check if we are a control code */
|
|
|
|
if (n > 0 && !(
|
|
|
|
(buffer[0] > 0x0 && buffer[0] < 0x20) || /* others 0x0 to 0x1F control codes */
|
|
|
|
buffer[0] == 0x7F)) /*delete control code */
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (xkb_keysym_get_name(keysym, buffer, size) != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
snprintf(buffer, size, "Keycode-%u", code);
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
static void
|
|
|
|
_keyboard_key(struct libinput_device *idevice, struct libinput_event_keyboard *event)
|
|
|
|
{
|
|
|
|
Elput_Device *dev;
|
|
|
|
Elput_Keyboard *kbd;
|
|
|
|
enum libinput_key_state state;
|
2017-05-26 13:34:10 -07:00
|
|
|
xkb_keysym_t sym_name, sym = XKB_KEY_NoSymbol;
|
2016-04-06 08:32:42 -07:00
|
|
|
const xkb_keysym_t *syms;
|
|
|
|
unsigned int code = 0;
|
|
|
|
unsigned int nsyms;
|
|
|
|
unsigned int timestamp;
|
2017-05-26 13:34:10 -07:00
|
|
|
char key[256] = {0}, keyname[256] = {0}, compose[256] = {0};
|
2016-04-06 08:32:42 -07:00
|
|
|
int count;
|
|
|
|
|
|
|
|
dev = libinput_device_get_user_data(idevice);
|
|
|
|
if (!dev) return;
|
|
|
|
|
|
|
|
kbd = _evdev_keyboard_get(dev->seat);
|
|
|
|
if (!kbd) return;
|
|
|
|
|
|
|
|
state = libinput_event_keyboard_get_key_state(event);
|
2017-05-26 13:34:10 -07:00
|
|
|
kbd->key_count = count = libinput_event_keyboard_get_seat_key_count(event);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
/* Ignore key events that are not seat wide state changes. */
|
|
|
|
if (((state == LIBINPUT_KEY_STATE_PRESSED) && (count != 1)) ||
|
|
|
|
((state == LIBINPUT_KEY_STATE_RELEASED) && (count != 0)))
|
|
|
|
return;
|
|
|
|
|
2016-05-26 09:36:51 -07:00
|
|
|
code = libinput_event_keyboard_get_key(event);
|
|
|
|
code = _keyboard_remapped_key_get(dev, code) + 8;
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
timestamp = libinput_event_keyboard_get_time(event);
|
|
|
|
|
|
|
|
if (state == LIBINPUT_KEY_STATE_PRESSED)
|
|
|
|
xkb_state_update_key(kbd->state, code, XKB_KEY_DOWN);
|
|
|
|
else
|
|
|
|
xkb_state_update_key(kbd->state, code, XKB_KEY_UP);
|
|
|
|
|
|
|
|
nsyms = xkb_key_get_syms(kbd->state, code, &syms);
|
|
|
|
if (nsyms == 1) sym = syms[0];
|
2017-05-26 13:34:10 -07:00
|
|
|
sym_name = xkb_state_key_get_one_sym(kbd->maskless_state, code);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (state == LIBINPUT_KEY_STATE_PRESSED)
|
|
|
|
sym = process_key_press(sym, kbd);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
_elput_symbol_rep_find(sym, key, sizeof(key), code);
|
|
|
|
_elput_symbol_rep_find(sym_name, keyname, sizeof(keyname), code);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
if (keyname[0] == '\0')
|
|
|
|
snprintf(keyname, sizeof(keyname), "Keycode-%u", code);
|
|
|
|
|
|
|
|
if (xkb_state_mod_index_is_active(kbd->state, kbd->info->mods.shift,
|
|
|
|
XKB_STATE_MODS_EFFECTIVE))
|
|
|
|
{
|
|
|
|
if (keyname[0] != '\0')
|
|
|
|
keyname[0] = tolower(keyname[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
_keyboard_modifiers_update(kbd, dev->seat);
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
_keyboard_keysym_translate(sym, dev->seat->modifiers, compose, sizeof(compose));
|
2016-04-06 08:32:42 -07:00
|
|
|
_keyboard_key_send(dev, state, keyname, key, compose, code, timestamp);
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if ((kbd->pending_keymap) && (count == 0))
|
2016-04-06 08:32:42 -07:00
|
|
|
_keyboard_keymap_update(dev->seat);
|
|
|
|
|
|
|
|
if (state == LIBINPUT_KEY_STATE_PRESSED)
|
|
|
|
{
|
|
|
|
kbd->grab.key = code;
|
|
|
|
kbd->grab.timestamp = timestamp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
static Elput_Pointer *
|
|
|
|
_pointer_create(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
|
|
|
|
ptr = calloc(1, sizeof(Elput_Pointer));
|
|
|
|
if (!ptr) return NULL;
|
|
|
|
|
|
|
|
ptr->seat = seat;
|
2016-05-26 08:35:42 -07:00
|
|
|
ptr->mouse.threshold = 250;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
|
|
|
return ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_pointer_init(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
|
|
|
|
if (seat->ptr)
|
|
|
|
{
|
|
|
|
seat->count.ptr += 1;
|
|
|
|
if (seat->count.ptr == 1)
|
2016-07-25 07:54:17 -07:00
|
|
|
_seat_caps_update(seat);
|
|
|
|
return EINA_TRUE;
|
2016-04-06 05:46:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
ptr = _pointer_create(seat);
|
|
|
|
if (!ptr) return EINA_FALSE;
|
|
|
|
|
|
|
|
seat->ptr = ptr;
|
|
|
|
seat->count.ptr = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ptr->pressure = 1.0;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
|
|
|
_seat_caps_update(seat);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_pointer_release(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
seat->count.ptr--;
|
|
|
|
if (seat->count.ptr == 0)
|
|
|
|
{
|
|
|
|
seat->ptr->buttons = 0;
|
|
|
|
_seat_caps_update(seat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Elput_Touch *
|
|
|
|
_touch_create(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
Elput_Touch *touch;
|
|
|
|
|
|
|
|
touch = calloc(1, sizeof(Elput_Touch));
|
|
|
|
if (!touch) return NULL;
|
|
|
|
|
|
|
|
touch->seat = seat;
|
2017-05-26 13:34:10 -07:00
|
|
|
touch->pressure = 1.0;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
|
|
|
return touch;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_touch_init(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
Elput_Touch *touch;
|
|
|
|
|
|
|
|
if (seat->touch)
|
|
|
|
{
|
|
|
|
seat->count.touch += 1;
|
|
|
|
if (seat->count.touch == 1)
|
2016-07-25 07:54:17 -07:00
|
|
|
_seat_caps_update(seat);
|
|
|
|
return EINA_TRUE;
|
2016-04-06 05:46:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
touch = _touch_create(seat);
|
|
|
|
if (!touch) return EINA_FALSE;
|
|
|
|
|
|
|
|
seat->touch = touch;
|
|
|
|
seat->count.touch = 1;
|
|
|
|
|
|
|
|
_seat_caps_update(seat);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_touch_release(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
seat->count.touch--;
|
|
|
|
if (seat->count.touch == 0)
|
|
|
|
{
|
|
|
|
seat->touch->points = 0;
|
|
|
|
_seat_caps_update(seat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
static void
|
|
|
|
_pointer_motion_send(Elput_Device *edev)
|
|
|
|
{
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
Elput_Keyboard *kbd;
|
|
|
|
Elput_Touch *touch;
|
|
|
|
Ecore_Event_Mouse_Move *ev;
|
|
|
|
double x, y;
|
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(edev->seat);
|
|
|
|
if (!ptr) return;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Ecore_Event_Mouse_Move));
|
|
|
|
if (!ev) return;
|
|
|
|
|
|
|
|
x = ptr->x;
|
|
|
|
y = ptr->y;
|
|
|
|
|
|
|
|
if (x < ptr->minx)
|
|
|
|
x = ptr->minx;
|
2016-05-25 09:49:44 -07:00
|
|
|
else if (x >= ptr->minx + ptr->seat->manager->input.pointer_w)
|
|
|
|
x = ptr->minx + ptr->seat->manager->input.pointer_w - 1;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
if (y < ptr->miny)
|
|
|
|
y = ptr->miny;
|
2016-05-25 09:49:44 -07:00
|
|
|
else if (y >= ptr->miny + ptr->seat->manager->input.pointer_h)
|
|
|
|
y = ptr->miny + ptr->seat->manager->input.pointer_h - 1;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2016-05-20 08:28:48 -07:00
|
|
|
ptr->x = x;
|
|
|
|
ptr->y = y;
|
|
|
|
|
2016-05-25 09:49:44 -07:00
|
|
|
ev->window = edev->seat->manager->window;
|
|
|
|
ev->event_window = edev->seat->manager->window;
|
|
|
|
ev->root_window = edev->seat->manager->window;
|
2016-04-06 08:32:42 -07:00
|
|
|
ev->timestamp = ptr->timestamp;
|
|
|
|
ev->same_screen = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->dev = edev->evas_device;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2016-05-20 08:28:48 -07:00
|
|
|
ev->x = ptr->x;
|
|
|
|
ev->y = ptr->y;
|
|
|
|
ev->root.x = ptr->x;
|
|
|
|
ev->root.y = ptr->y;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
kbd = _evdev_keyboard_get(edev->seat);
|
|
|
|
if (kbd) _keyboard_modifiers_update(kbd, edev->seat);
|
|
|
|
|
|
|
|
ev->modifiers = edev->seat->modifiers;
|
|
|
|
|
|
|
|
touch = _evdev_touch_get(edev->seat);
|
|
|
|
if (touch) ev->multi.device = touch->slot;
|
|
|
|
|
|
|
|
ev->multi.radius = 1;
|
|
|
|
ev->multi.radius_x = 1;
|
|
|
|
ev->multi.radius_y = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->multi.pressure = ptr->pressure;
|
2016-04-06 08:32:42 -07:00
|
|
|
ev->multi.angle = 0.0;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->multi.x = ptr->x;
|
|
|
|
ev->multi.y = ptr->y;
|
|
|
|
ev->multi.root.x = ptr->x;
|
|
|
|
ev->multi.root.y = ptr->y;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2017-02-03 12:14:01 -08:00
|
|
|
static void
|
|
|
|
_pointer_motion_relative(struct libinput_event_pointer *event)
|
|
|
|
{
|
|
|
|
Elput_Event_Pointer_Motion *ev;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Elput_Event_Pointer_Motion));
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(ev);
|
|
|
|
|
|
|
|
ev->time_usec = libinput_event_pointer_get_time_usec(event);
|
|
|
|
ev->dx = libinput_event_pointer_get_dx(event);
|
|
|
|
ev->dy = libinput_event_pointer_get_dy(event);
|
|
|
|
ev->dx_unaccel = libinput_event_pointer_get_dx_unaccelerated(event);
|
|
|
|
ev->dy_unaccel = libinput_event_pointer_get_dy_unaccelerated(event);
|
|
|
|
|
|
|
|
ecore_event_add(ELPUT_EVENT_POINTER_MOTION, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_pointer_motion(struct libinput_device *idev, struct libinput_event_pointer *event)
|
|
|
|
{
|
|
|
|
Elput_Device *edev;
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
|
|
|
|
edev = libinput_device_get_user_data(idev);
|
|
|
|
if (!edev) return EINA_FALSE;
|
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(edev->seat);
|
|
|
|
if (!ptr) return EINA_FALSE;
|
|
|
|
|
2016-05-20 08:17:01 -07:00
|
|
|
ptr->x += libinput_event_pointer_get_dx(event);
|
|
|
|
ptr->y += libinput_event_pointer_get_dy(event);
|
2016-04-06 08:32:42 -07:00
|
|
|
ptr->timestamp = libinput_event_pointer_get_time(event);
|
|
|
|
|
|
|
|
_pointer_motion_send(edev);
|
2017-02-03 12:14:01 -08:00
|
|
|
_pointer_motion_relative(event);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_pointer_motion_abs(struct libinput_device *idev, struct libinput_event_pointer *event)
|
|
|
|
{
|
|
|
|
Elput_Device *edev;
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
|
|
|
|
edev = libinput_device_get_user_data(idev);
|
|
|
|
if (!edev) return EINA_FALSE;
|
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(edev->seat);
|
|
|
|
if (!ptr) return EINA_FALSE;
|
|
|
|
|
|
|
|
ptr->x = libinput_event_pointer_get_absolute_x_transformed(event, edev->ow);
|
|
|
|
ptr->y = libinput_event_pointer_get_absolute_y_transformed(event, edev->oh);
|
|
|
|
ptr->timestamp = libinput_event_pointer_get_time(event);
|
|
|
|
|
|
|
|
/* TODO: these needs to run a matrix transform based on output */
|
|
|
|
|
|
|
|
_pointer_motion_send(edev);
|
2017-02-03 12:14:01 -08:00
|
|
|
_pointer_motion_relative(event);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_pointer_button_send(Elput_Device *edev, enum libinput_button_state state)
|
|
|
|
{
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
Elput_Keyboard *kbd;
|
|
|
|
Elput_Touch *touch;
|
|
|
|
Ecore_Event_Mouse_Button *ev;
|
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(edev->seat);
|
|
|
|
if (!ptr) return;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
|
|
|
|
if (!ev) return;
|
|
|
|
|
2016-05-25 09:49:44 -07:00
|
|
|
ev->window = edev->seat->manager->window;
|
|
|
|
ev->event_window = edev->seat->manager->window;
|
|
|
|
ev->root_window = edev->seat->manager->window;
|
2016-04-06 08:32:42 -07:00
|
|
|
ev->timestamp = ptr->timestamp;
|
|
|
|
ev->same_screen = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->dev = edev->evas_device;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
ev->x = ptr->x;
|
|
|
|
ev->y = ptr->y;
|
|
|
|
ev->root.x = ptr->x;
|
|
|
|
ev->root.y = ptr->y;
|
|
|
|
|
|
|
|
touch = _evdev_touch_get(edev->seat);
|
|
|
|
if (touch) ev->multi.device = touch->slot;
|
|
|
|
ev->multi.radius = 1;
|
|
|
|
ev->multi.radius_x = 1;
|
|
|
|
ev->multi.radius_y = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->multi.pressure = ptr->pressure;
|
2016-04-06 08:32:42 -07:00
|
|
|
ev->multi.angle = 0.0;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->multi.x = ptr->x;
|
|
|
|
ev->multi.y = ptr->y;
|
|
|
|
ev->multi.root.x = ptr->x;
|
|
|
|
ev->multi.root.y = ptr->y;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
ev->buttons = ptr->buttons;
|
|
|
|
|
|
|
|
ev->double_click = ptr->mouse.double_click;
|
|
|
|
ev->triple_click = ptr->mouse.triple_click;
|
|
|
|
|
|
|
|
kbd = _evdev_keyboard_get(edev->seat);
|
|
|
|
if (kbd)
|
|
|
|
_keyboard_modifiers_update(kbd, edev->seat);
|
|
|
|
ev->modifiers = edev->seat->modifiers;
|
|
|
|
|
|
|
|
if (state)
|
|
|
|
ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
|
|
|
|
else
|
|
|
|
ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
static void
|
|
|
|
_pointer_click_update(Elput_Pointer *ptr, unsigned int btn)
|
|
|
|
{
|
|
|
|
unsigned int current;
|
|
|
|
|
|
|
|
current = ptr->timestamp;
|
|
|
|
ptr->mouse.double_click = EINA_FALSE;
|
|
|
|
ptr->mouse.triple_click = EINA_FALSE;
|
|
|
|
|
|
|
|
if (((current - ptr->mouse.prev_time) <= ptr->mouse.threshold) &&
|
|
|
|
(btn == ptr->mouse.prev_button))
|
|
|
|
{
|
|
|
|
ptr->mouse.double_click = EINA_TRUE;
|
|
|
|
if (((current - ptr->mouse.last_time) <=
|
|
|
|
(2 * ptr->mouse.threshold)) &&
|
|
|
|
(btn == ptr->mouse.last_button))
|
|
|
|
{
|
|
|
|
ptr->mouse.triple_click = EINA_TRUE;
|
|
|
|
ptr->mouse.prev_time = 0;
|
|
|
|
ptr->mouse.last_time = 0;
|
|
|
|
current = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr->mouse.last_time = ptr->mouse.prev_time;
|
|
|
|
ptr->mouse.prev_time = current;
|
|
|
|
ptr->mouse.last_button = ptr->mouse.prev_button;
|
|
|
|
ptr->mouse.prev_button = ptr->buttons;
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
static Eina_Bool
|
|
|
|
_pointer_button(struct libinput_device *idev, struct libinput_event_pointer *event)
|
|
|
|
{
|
|
|
|
Elput_Device *edev;
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
int count;
|
|
|
|
enum libinput_button_state state;
|
|
|
|
unsigned int btn;
|
|
|
|
|
|
|
|
edev = libinput_device_get_user_data(idev);
|
|
|
|
if (!edev) return EINA_FALSE;
|
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(edev->seat);
|
|
|
|
if (!ptr) return EINA_FALSE;
|
|
|
|
|
|
|
|
state = libinput_event_pointer_get_button_state(event);
|
|
|
|
count = libinput_event_pointer_get_seat_button_count(event);
|
|
|
|
|
|
|
|
/* Ignore button events that are not seat wide state changes. */
|
|
|
|
if (((state == LIBINPUT_BUTTON_STATE_PRESSED) && (count != 1)) ||
|
|
|
|
((state == LIBINPUT_BUTTON_STATE_RELEASED) && (count != 0)))
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
btn = libinput_event_pointer_get_button(event);
|
|
|
|
|
|
|
|
btn = ((btn & 0x00F) + 1);
|
|
|
|
if (btn == 3) btn = 2;
|
|
|
|
else if (btn == 2) btn = 3;
|
|
|
|
|
|
|
|
ptr->buttons = btn;
|
|
|
|
ptr->timestamp = libinput_event_pointer_get_time(event);
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (state) _pointer_click_update(ptr, btn);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
_pointer_button_send(edev, state);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_pointer_axis_send(Elput_Device *dev, int direction, int value)
|
|
|
|
{
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
Elput_Keyboard *kbd;
|
|
|
|
Ecore_Event_Mouse_Wheel *ev;
|
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(dev->seat);
|
|
|
|
if (!ptr) return;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Ecore_Event_Mouse_Wheel));
|
|
|
|
if (!ev) return;
|
|
|
|
|
2016-05-25 09:49:44 -07:00
|
|
|
ev->window = dev->seat->manager->window;
|
|
|
|
ev->event_window = dev->seat->manager->window;
|
|
|
|
ev->root_window = dev->seat->manager->window;
|
2016-04-06 08:32:42 -07:00
|
|
|
ev->timestamp = ptr->timestamp;
|
|
|
|
ev->same_screen = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->dev = dev->evas_device;
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
ev->x = ptr->x;
|
|
|
|
ev->y = ptr->y;
|
|
|
|
ev->root.x = ptr->x;
|
|
|
|
ev->root.y = ptr->y;
|
|
|
|
|
|
|
|
ev->z = value;
|
|
|
|
ev->direction = direction;
|
|
|
|
|
|
|
|
kbd = _evdev_keyboard_get(dev->seat);
|
|
|
|
if (kbd) _keyboard_modifiers_update(kbd, dev->seat);
|
|
|
|
|
|
|
|
ev->modifiers = dev->seat->modifiers;
|
|
|
|
|
|
|
|
ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static double
|
|
|
|
_pointer_axis_value(struct libinput_event_pointer *event, enum libinput_pointer_axis axis)
|
|
|
|
{
|
|
|
|
enum libinput_pointer_axis_source source;
|
|
|
|
double val = 0.0;
|
|
|
|
|
|
|
|
source = libinput_event_pointer_get_axis_source(event);
|
|
|
|
switch (source)
|
|
|
|
{
|
|
|
|
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
|
2016-05-14 00:35:09 -07:00
|
|
|
val = libinput_event_pointer_get_axis_value_discrete(event, axis);
|
2016-04-06 08:32:42 -07:00
|
|
|
break;
|
|
|
|
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
|
|
|
|
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
|
|
|
|
val = libinput_event_pointer_get_axis_value(event, axis);
|
|
|
|
break;
|
2017-04-19 10:16:57 -07:00
|
|
|
default:
|
|
|
|
break;
|
2016-04-06 08:32:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
|
|
_pointer_axis(struct libinput_device *idevice, struct libinput_event_pointer *event)
|
|
|
|
{
|
|
|
|
Elput_Device *dev;
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
enum libinput_pointer_axis axis;
|
|
|
|
Eina_Bool vert = EINA_FALSE, horiz = EINA_FALSE;
|
|
|
|
int dir = 0, val = 0;
|
|
|
|
|
|
|
|
dev = libinput_device_get_user_data(idevice);
|
|
|
|
if (!dev) return EINA_FALSE;
|
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(dev->seat);
|
|
|
|
if (!ptr) return EINA_FALSE;
|
|
|
|
|
|
|
|
#ifdef LIBINPUT_HIGHER_08
|
|
|
|
vert =
|
|
|
|
libinput_event_pointer_has_axis(event,
|
|
|
|
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
|
|
|
|
horiz =
|
|
|
|
libinput_event_pointer_has_axis(event,
|
|
|
|
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
|
|
|
|
if ((!vert) && (!horiz)) return EINA_FALSE;
|
|
|
|
|
|
|
|
if (vert)
|
|
|
|
{
|
|
|
|
axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
|
|
|
|
val = _pointer_axis_value(event, axis);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (horiz)
|
|
|
|
{
|
|
|
|
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
|
|
|
|
val = _pointer_axis_value(event, axis);
|
|
|
|
dir = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else
|
|
|
|
axis = libinput_event_pointer_get_axis(event);
|
|
|
|
if (axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) dir = 1;
|
|
|
|
val = libinput_event_pointer_get_axis_value(event);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ptr->timestamp = libinput_event_pointer_get_time(event);
|
|
|
|
|
|
|
|
_pointer_axis_send(dev, dir, val);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2017-01-12 07:24:18 -08:00
|
|
|
_touch_event_send(Elput_Device *dev, int type)
|
2016-04-06 08:32:42 -07:00
|
|
|
{
|
|
|
|
Elput_Touch *touch;
|
|
|
|
Ecore_Event_Mouse_Button *ev;
|
|
|
|
unsigned int btn = 0;
|
|
|
|
|
|
|
|
touch = _evdev_touch_get(dev->seat);
|
|
|
|
if (!touch) return;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Ecore_Event_Mouse_Button));
|
|
|
|
if (!ev) return;
|
|
|
|
|
2016-05-25 09:49:44 -07:00
|
|
|
ev->window = dev->seat->manager->window;
|
|
|
|
ev->event_window = dev->seat->manager->window;
|
|
|
|
ev->root_window = dev->seat->manager->window;
|
2017-01-12 07:24:18 -08:00
|
|
|
ev->timestamp = touch->timestamp;
|
2016-04-06 08:32:42 -07:00
|
|
|
ev->same_screen = 1;
|
|
|
|
|
|
|
|
ev->x = touch->x;
|
|
|
|
ev->y = touch->y;
|
|
|
|
ev->root.x = touch->x;
|
|
|
|
ev->root.y = touch->y;
|
|
|
|
|
|
|
|
ev->modifiers = dev->seat->modifiers;
|
|
|
|
|
|
|
|
ev->multi.device = touch->slot;
|
|
|
|
ev->multi.radius = 1;
|
|
|
|
ev->multi.radius_x = 1;
|
|
|
|
ev->multi.radius_y = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->multi.pressure = touch->pressure;
|
2016-04-06 08:32:42 -07:00
|
|
|
ev->multi.angle = 0.0;
|
|
|
|
ev->multi.x = ev->x;
|
|
|
|
ev->multi.y = ev->y;
|
|
|
|
ev->multi.root.x = ev->x;
|
|
|
|
ev->multi.root.y = ev->y;
|
|
|
|
|
|
|
|
btn = ((btn & 0x00F) + 1);
|
2016-07-08 19:57:30 -07:00
|
|
|
// XXX: this code is useless. above btn is set to 0 at declaration time, then
|
|
|
|
// no code changes it until the above like effectively makes it 1. it can
|
|
|
|
// only ever be 1 so the below lines are pointless. this is probably a bug
|
|
|
|
// lurking...
|
|
|
|
// if (btn == 3) btn = 2;
|
|
|
|
// else if (btn == 2) btn = 3;
|
2016-04-06 08:32:42 -07:00
|
|
|
ev->buttons = btn;
|
|
|
|
|
|
|
|
ecore_event_add(type, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2017-01-12 08:09:47 -08:00
|
|
|
static void
|
|
|
|
_touch_motion_send(Elput_Device *dev)
|
|
|
|
{
|
|
|
|
Elput_Touch *touch;
|
|
|
|
Ecore_Event_Mouse_Move *ev;
|
|
|
|
|
|
|
|
touch = _evdev_touch_get(dev->seat);
|
|
|
|
if (!touch) return;
|
|
|
|
|
|
|
|
ev = calloc(1, sizeof(Ecore_Event_Mouse_Move));
|
|
|
|
if (!ev) return;
|
|
|
|
|
|
|
|
ev->window = dev->seat->manager->window;
|
|
|
|
ev->event_window = dev->seat->manager->window;
|
|
|
|
ev->root_window = dev->seat->manager->window;
|
|
|
|
ev->timestamp = touch->timestamp;
|
|
|
|
ev->same_screen = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->dev = dev->evas_device;
|
2017-01-12 08:09:47 -08:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->x = lround(touch->x);
|
|
|
|
ev->y = lround(touch->y);
|
|
|
|
ev->root.x = ev->x;
|
|
|
|
ev->root.y = ev->y;
|
2017-01-12 08:09:47 -08:00
|
|
|
|
|
|
|
ev->modifiers = dev->seat->modifiers;
|
|
|
|
|
|
|
|
ev->multi.device = touch->slot;
|
|
|
|
ev->multi.radius = 1;
|
|
|
|
ev->multi.radius_x = 1;
|
|
|
|
ev->multi.radius_y = 1;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->multi.pressure = touch->pressure;
|
2017-01-12 08:09:47 -08:00
|
|
|
ev->multi.angle = 0.0;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->multi.x = touch->x;
|
|
|
|
ev->multi.y = touch->y;
|
|
|
|
ev->multi.root.x = touch->x;
|
|
|
|
ev->multi.root.y = touch->y;
|
2017-01-12 08:09:47 -08:00
|
|
|
|
|
|
|
ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
static void
|
|
|
|
_touch_down(struct libinput_device *idevice, struct libinput_event_touch *event)
|
|
|
|
{
|
|
|
|
Elput_Device *dev;
|
|
|
|
Elput_Touch *touch;
|
|
|
|
|
|
|
|
dev = libinput_device_get_user_data(idevice);
|
|
|
|
if (!dev) return;
|
|
|
|
|
|
|
|
touch = _evdev_touch_get(dev->seat);
|
|
|
|
if (!touch) return;
|
|
|
|
|
2017-01-12 07:24:18 -08:00
|
|
|
touch->slot = libinput_event_touch_get_seat_slot(event);
|
|
|
|
touch->timestamp = libinput_event_touch_get_time(event);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
touch->x = libinput_event_touch_get_x_transformed(event, dev->ow);
|
|
|
|
touch->y = libinput_event_touch_get_y_transformed(event, dev->oh);
|
|
|
|
|
|
|
|
/* TODO: these needs to run a matrix transform based on output */
|
|
|
|
/* _ecore_drm2_output_coordinate_transform(dev->output, */
|
|
|
|
/* touch->x, touch->y, */
|
|
|
|
/* &touch->x, &touch->y); */
|
|
|
|
|
2017-01-12 07:24:18 -08:00
|
|
|
if (touch->slot == touch->grab.id)
|
2016-04-06 08:32:42 -07:00
|
|
|
{
|
|
|
|
touch->grab.x = touch->x;
|
|
|
|
touch->grab.y = touch->y;
|
|
|
|
}
|
|
|
|
|
|
|
|
touch->points++;
|
|
|
|
|
2017-01-12 08:09:47 -08:00
|
|
|
_touch_motion_send(dev);
|
2017-01-12 07:24:18 -08:00
|
|
|
_touch_event_send(dev, ECORE_EVENT_MOUSE_BUTTON_DOWN);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
|
|
|
if (touch->points == 1)
|
|
|
|
{
|
2017-01-12 07:24:18 -08:00
|
|
|
touch->grab.id = touch->slot;
|
2016-04-06 08:32:42 -07:00
|
|
|
touch->grab.x = touch->x;
|
|
|
|
touch->grab.y = touch->y;
|
2017-01-12 07:24:18 -08:00
|
|
|
touch->grab.timestamp = touch->timestamp;
|
2016-04-06 08:32:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_touch_up(struct libinput_device *idevice, struct libinput_event_touch *event)
|
|
|
|
{
|
|
|
|
Elput_Device *dev;
|
|
|
|
Elput_Touch *touch;
|
|
|
|
|
|
|
|
dev = libinput_device_get_user_data(idevice);
|
|
|
|
if (!dev) return;
|
|
|
|
|
|
|
|
touch = _evdev_touch_get(dev->seat);
|
|
|
|
if (!touch) return;
|
|
|
|
|
|
|
|
touch->points--;
|
|
|
|
touch->slot = libinput_event_touch_get_seat_slot(event);
|
2017-01-12 07:24:18 -08:00
|
|
|
touch->timestamp = libinput_event_touch_get_time(event);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2017-01-12 08:09:47 -08:00
|
|
|
_touch_motion_send(dev);
|
2017-01-12 07:24:18 -08:00
|
|
|
_touch_event_send(dev, ECORE_EVENT_MOUSE_BUTTON_UP);
|
2016-04-06 08:32:42 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_touch_motion(struct libinput_device *idevice, struct libinput_event_touch *event)
|
|
|
|
{
|
|
|
|
Elput_Device *dev;
|
|
|
|
Elput_Touch *touch;
|
|
|
|
|
|
|
|
dev = libinput_device_get_user_data(idevice);
|
|
|
|
if (!dev) return;
|
|
|
|
|
|
|
|
touch = _evdev_touch_get(dev->seat);
|
|
|
|
if (!touch) return;
|
|
|
|
|
|
|
|
touch->x = libinput_event_touch_get_x_transformed(event, dev->ow);
|
|
|
|
touch->y = libinput_event_touch_get_y_transformed(event, dev->oh);
|
|
|
|
|
|
|
|
/* TODO: these needs to run a matrix transform based on output */
|
|
|
|
/* _ecore_drm2_output_coordinate_transform(dev->output, */
|
|
|
|
/* touch->x, touch->y, */
|
|
|
|
/* &touch->x, &touch->y); */
|
|
|
|
|
|
|
|
touch->slot = libinput_event_touch_get_seat_slot(event);
|
2017-01-12 07:24:18 -08:00
|
|
|
touch->timestamp = libinput_event_touch_get_time(event);
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2017-01-12 07:24:18 -08:00
|
|
|
_touch_motion_send(dev);
|
2016-04-06 08:32:42 -07:00
|
|
|
}
|
|
|
|
|
2016-05-26 07:45:47 -07:00
|
|
|
void
|
2016-04-07 06:10:48 -07:00
|
|
|
_evdev_device_calibrate(Elput_Device *dev)
|
|
|
|
{
|
|
|
|
float cal[6];
|
|
|
|
const char *vals;
|
|
|
|
const char *sysname;
|
|
|
|
const char *device;
|
|
|
|
Eina_List *devices;
|
|
|
|
int w = 0, h = 0;
|
|
|
|
enum libinput_config_status status;
|
|
|
|
|
|
|
|
w = dev->ow;
|
|
|
|
h = dev->oh;
|
|
|
|
if ((w == 0) || (h == 0)) return;
|
|
|
|
|
|
|
|
if ((!libinput_device_config_calibration_has_matrix(dev->device)) ||
|
2016-05-20 08:28:48 -07:00
|
|
|
(libinput_device_config_calibration_get_default_matrix(dev->device, cal) != 0))
|
2016-04-07 06:10:48 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
sysname = libinput_device_get_sysname(dev->device);
|
|
|
|
|
|
|
|
devices = eeze_udev_find_by_subsystem_sysname("input", sysname);
|
|
|
|
EINA_LIST_FREE(devices, device)
|
|
|
|
{
|
|
|
|
vals = eeze_udev_syspath_get_property(device, "WL_CALIBRATION");
|
|
|
|
if ((!vals) ||
|
|
|
|
(sscanf(vals, "%f %f %f %f %f %f",
|
|
|
|
&cal[0], &cal[1], &cal[2], &cal[3], &cal[4], &cal[5]) != 6))
|
|
|
|
goto cont;
|
|
|
|
|
|
|
|
cal[2] /= w;
|
|
|
|
cal[5] /= h;
|
|
|
|
|
|
|
|
status =
|
|
|
|
libinput_device_config_calibration_set_matrix(dev->device, cal);
|
|
|
|
if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
|
|
|
|
WRN("Failed to apply device calibration");
|
|
|
|
|
|
|
|
cont:
|
|
|
|
eina_stringshare_del(device);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
static void
|
|
|
|
_axis_event_free(void *d EINA_UNUSED, void *event)
|
|
|
|
{
|
|
|
|
Ecore_Event_Axis_Update *ev = event;
|
|
|
|
|
|
|
|
free(ev->axis);
|
|
|
|
free(ev);
|
|
|
|
}
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
static void
|
|
|
|
_tablet_tool_axis(struct libinput_device *idev, struct libinput_event_tablet_tool *event)
|
|
|
|
{
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
struct libinput_tablet_tool *tool;
|
|
|
|
Elput_Device *dev = libinput_device_get_user_data(idev);
|
2017-05-26 13:34:10 -07:00
|
|
|
Ecore_Event_Axis_Update *ev;
|
|
|
|
Ecore_Axis ax[8] = {0}, *axis = NULL;
|
|
|
|
int i, num = 0;
|
2017-05-26 13:34:10 -07:00
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(dev->seat);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(ptr);
|
|
|
|
tool = libinput_event_tablet_tool_get_tool(event);
|
|
|
|
|
|
|
|
ptr->x = libinput_event_tablet_tool_get_x_transformed(event, dev->ow);
|
|
|
|
ptr->y = libinput_event_tablet_tool_get_y_transformed(event, dev->oh);
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (libinput_event_tablet_tool_x_has_changed(event))
|
|
|
|
{
|
|
|
|
ax[num].label = ECORE_AXIS_LABEL_X;
|
|
|
|
ax[num].value = ptr->x;
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
if (libinput_event_tablet_tool_y_has_changed(event))
|
|
|
|
{
|
|
|
|
ax[num].label = ECORE_AXIS_LABEL_Y;
|
|
|
|
ax[num].value = ptr->y;
|
|
|
|
num++;
|
|
|
|
}
|
2017-05-26 13:34:10 -07:00
|
|
|
if (libinput_tablet_tool_has_pressure(tool))
|
2017-05-26 13:34:10 -07:00
|
|
|
{
|
|
|
|
if (libinput_event_tablet_tool_pressure_has_changed(event))
|
|
|
|
{
|
|
|
|
ax[num].label = ECORE_AXIS_LABEL_PRESSURE;
|
|
|
|
ax[num].value = ptr->pressure = libinput_event_tablet_tool_get_pressure(event);
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (libinput_tablet_tool_has_distance(tool))
|
|
|
|
{
|
|
|
|
if (libinput_event_tablet_tool_distance_has_changed(event))
|
|
|
|
{
|
|
|
|
ax[num].label = ECORE_AXIS_LABEL_DISTANCE;
|
|
|
|
ax[num].value = libinput_event_tablet_tool_get_distance(event);
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (libinput_tablet_tool_has_tilt(tool))
|
|
|
|
{
|
|
|
|
if (libinput_event_tablet_tool_tilt_x_has_changed(event) ||
|
|
|
|
libinput_event_tablet_tool_tilt_y_has_changed(event))
|
|
|
|
{
|
|
|
|
double x = sin(libinput_event_tablet_tool_get_tilt_x(event));
|
|
|
|
double y = sin(-libinput_event_tablet_tool_get_tilt_y(event));
|
|
|
|
|
|
|
|
ax[num].label = ECORE_AXIS_LABEL_TILT;
|
|
|
|
ax[num].value = asin(sqrt((x * x) + (y * y)));
|
|
|
|
num++;
|
|
|
|
|
|
|
|
/* note: the value of atan2(0,0) is implementation-defined */
|
|
|
|
ax[num].label = ECORE_AXIS_LABEL_AZIMUTH;
|
|
|
|
ax[num].value = atan2(y, x);
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (libinput_tablet_tool_has_rotation(tool))
|
|
|
|
{
|
|
|
|
if (libinput_event_tablet_tool_rotation_has_changed(event))
|
|
|
|
{
|
|
|
|
ax[num].label = ECORE_AXIS_LABEL_TWIST;
|
|
|
|
ax[num].value = libinput_event_tablet_tool_get_rotation(event);
|
|
|
|
ax[num].value *= M_PI / 180;
|
|
|
|
num++;
|
|
|
|
}
|
|
|
|
}
|
2017-05-26 13:34:10 -07:00
|
|
|
|
|
|
|
ptr->timestamp = libinput_event_tablet_tool_get_time(event);
|
2017-05-26 13:34:10 -07:00
|
|
|
/* FIXME: other properties which efl event structs don't support:
|
|
|
|
* slider_position
|
|
|
|
* wheel_delta
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
if (libinput_event_tablet_tool_x_has_changed(event) ||
|
|
|
|
libinput_event_tablet_tool_y_has_changed(event))
|
|
|
|
_pointer_motion_send(dev);
|
|
|
|
|
|
|
|
if (!num) return;
|
|
|
|
ev = calloc(1, sizeof(Ecore_Event_Axis_Update));
|
|
|
|
|
|
|
|
ev->window = dev->seat->manager->window;
|
|
|
|
ev->event_window = dev->seat->manager->window;
|
|
|
|
ev->root_window = dev->seat->manager->window;
|
|
|
|
ev->timestamp = ptr->timestamp;
|
|
|
|
ev->naxis = num;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->dev = dev->evas_device;
|
2017-05-26 13:34:10 -07:00
|
|
|
ev->axis = axis = calloc(num, sizeof(Ecore_Axis));
|
|
|
|
for (i = 0; i < num; i++)
|
|
|
|
{
|
|
|
|
axis[i].label = ax[i].label;
|
|
|
|
axis[i].value = ax[i].value;
|
|
|
|
}
|
|
|
|
ecore_event_add(ECORE_EVENT_AXIS_UPDATE, ev, _axis_event_free, NULL);
|
2017-05-26 13:34:10 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_tablet_tool_tip(struct libinput_device *idev, struct libinput_event_tablet_tool *event)
|
|
|
|
{
|
|
|
|
Elput_Pointer *ptr;
|
|
|
|
Elput_Device *dev = libinput_device_get_user_data(idev);
|
|
|
|
int state;
|
|
|
|
int press[] =
|
|
|
|
{
|
|
|
|
[LIBINPUT_TABLET_TOOL_TIP_DOWN] = LIBINPUT_BUTTON_STATE_PRESSED,
|
|
|
|
[LIBINPUT_TABLET_TOOL_TIP_UP] = LIBINPUT_BUTTON_STATE_RELEASED,
|
|
|
|
};
|
|
|
|
|
|
|
|
ptr = _evdev_pointer_get(dev->seat);
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(ptr);
|
|
|
|
|
|
|
|
state = libinput_event_tablet_tool_get_tip_state(event);
|
|
|
|
ptr->buttons = 1;
|
|
|
|
ptr->timestamp = libinput_event_tablet_tool_get_time(event);
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (press[state]) _pointer_click_update(ptr, 1);
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
_pointer_button_send(dev, press[state]);
|
|
|
|
}
|
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
int
|
|
|
|
_evdev_event_process(struct libinput_event *event)
|
|
|
|
{
|
|
|
|
struct libinput_device *idev;
|
|
|
|
int ret = 1;
|
|
|
|
Eina_Bool frame = EINA_FALSE;
|
|
|
|
|
|
|
|
idev = libinput_event_get_device(event);
|
|
|
|
switch (libinput_event_get_type(event))
|
|
|
|
{
|
|
|
|
case LIBINPUT_EVENT_KEYBOARD_KEY:
|
2016-04-06 08:32:42 -07:00
|
|
|
_keyboard_key(idev, libinput_event_get_keyboard_event(event));
|
2016-04-06 05:46:29 -07:00
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_POINTER_MOTION:
|
2016-04-06 08:32:42 -07:00
|
|
|
frame =
|
|
|
|
_pointer_motion(idev, libinput_event_get_pointer_event(event));
|
2016-04-06 05:46:29 -07:00
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
|
2016-04-06 08:32:42 -07:00
|
|
|
frame =
|
|
|
|
_pointer_motion_abs(idev, libinput_event_get_pointer_event(event));
|
2016-04-06 05:46:29 -07:00
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_POINTER_BUTTON:
|
2016-04-06 08:32:42 -07:00
|
|
|
frame =
|
|
|
|
_pointer_button(idev, libinput_event_get_pointer_event(event));
|
2016-04-06 05:46:29 -07:00
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_POINTER_AXIS:
|
2016-04-06 08:32:42 -07:00
|
|
|
frame =
|
|
|
|
_pointer_axis(idev, libinput_event_get_pointer_event(event));
|
2016-04-06 05:46:29 -07:00
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_TOUCH_DOWN:
|
2016-04-06 08:32:42 -07:00
|
|
|
_touch_down(idev, libinput_event_get_touch_event(event));
|
2016-04-06 05:46:29 -07:00
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_TOUCH_MOTION:
|
2016-04-06 08:32:42 -07:00
|
|
|
_touch_motion(idev, libinput_event_get_touch_event(event));
|
2016-04-06 05:46:29 -07:00
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_TOUCH_UP:
|
2016-04-06 08:32:42 -07:00
|
|
|
_touch_up(idev, libinput_event_get_touch_event(event));
|
2016-04-06 05:46:29 -07:00
|
|
|
break;
|
2017-05-26 13:34:10 -07:00
|
|
|
case LIBINPUT_EVENT_TOUCH_FRAME: break;
|
|
|
|
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
|
|
|
|
_tablet_tool_axis(idev, libinput_event_get_tablet_tool_event(event));
|
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY: /* is this useful? */
|
|
|
|
break;
|
|
|
|
case LIBINPUT_EVENT_TABLET_TOOL_TIP: /* is this useful? */
|
|
|
|
_tablet_tool_tip(idev, libinput_event_get_tablet_tool_event(event));
|
|
|
|
break;
|
2016-04-06 05:46:29 -07:00
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frame)
|
|
|
|
{
|
2016-04-06 07:26:46 -07:00
|
|
|
Elput_Device *edev;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
2016-04-06 07:26:46 -07:00
|
|
|
edev = libinput_device_get_user_data(idev);
|
2016-04-06 07:38:08 -07:00
|
|
|
if (edev) _seat_frame_send(edev->seat);
|
2016-04-06 05:46:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
Elput_Device *
|
|
|
|
_evdev_device_create(Elput_Seat *seat, struct libinput_device *device)
|
|
|
|
{
|
|
|
|
Elput_Device *edev;
|
2017-02-07 08:33:25 -08:00
|
|
|
const char *oname;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
|
|
|
edev = calloc(1, sizeof(Elput_Device));
|
|
|
|
if (!edev) return NULL;
|
|
|
|
|
2017-06-02 15:23:45 -07:00
|
|
|
edev->refs = 1;
|
2016-04-06 05:46:29 -07:00
|
|
|
edev->seat = seat;
|
|
|
|
edev->device = device;
|
2017-01-31 07:54:09 -08:00
|
|
|
edev->caps = 0;
|
2017-05-26 13:34:10 -07:00
|
|
|
edev->ow = seat->manager->output_w;
|
|
|
|
edev->oh = seat->manager->output_h;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
2017-02-07 08:33:25 -08:00
|
|
|
oname = libinput_device_get_output_name(device);
|
2017-05-26 13:34:10 -07:00
|
|
|
if (!oname)
|
|
|
|
oname = libinput_device_get_name(device);
|
2017-02-07 08:33:25 -08:00
|
|
|
eina_stringshare_replace(&edev->output_name, oname);
|
|
|
|
|
2016-12-08 11:30:41 -08:00
|
|
|
if ((libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD)) &&
|
|
|
|
(libinput_device_keyboard_has_key(device, KEY_ENTER)))
|
2016-04-06 05:46:29 -07:00
|
|
|
{
|
2016-05-27 06:12:53 -07:00
|
|
|
_keyboard_init(seat, seat->manager->cached.keymap);
|
2017-05-26 13:34:10 -07:00
|
|
|
edev->caps |= ELPUT_DEVICE_CAPS_KEYBOARD;
|
2016-04-06 05:46:29 -07:00
|
|
|
}
|
|
|
|
|
2016-12-08 11:30:41 -08:00
|
|
|
if ((libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER) &&
|
|
|
|
(libinput_device_pointer_has_button(device, BTN_LEFT))))
|
2017-05-26 13:34:10 -07:00
|
|
|
edev->caps |= ELPUT_DEVICE_CAPS_POINTER;
|
2017-05-26 13:34:10 -07:00
|
|
|
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL))
|
2017-05-26 13:34:10 -07:00
|
|
|
edev->caps |= ELPUT_DEVICE_CAPS_POINTER | ELPUT_DEVICE_CAPS_TABLET_TOOL;
|
2017-05-26 13:34:10 -07:00
|
|
|
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_PAD))
|
2017-05-26 13:34:10 -07:00
|
|
|
edev->caps |= ELPUT_DEVICE_CAPS_TABLET_PAD;
|
2017-05-26 13:34:10 -07:00
|
|
|
if (edev->caps & ELPUT_DEVICE_CAPS_POINTER)
|
2016-04-06 05:46:29 -07:00
|
|
|
{
|
|
|
|
_pointer_init(seat);
|
2017-05-26 13:34:10 -07:00
|
|
|
edev->caps |= ELPUT_DEVICE_CAPS_POINTER;
|
2016-04-06 05:46:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
|
2017-05-26 13:34:10 -07:00
|
|
|
edev->caps |= ELPUT_DEVICE_CAPS_TOUCH;
|
2017-05-26 13:34:10 -07:00
|
|
|
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_GESTURE))
|
2017-05-26 13:34:10 -07:00
|
|
|
edev->caps |= ELPUT_DEVICE_CAPS_TOUCH | ELPUT_DEVICE_CAPS_GESTURE;
|
|
|
|
if (edev->caps & ELPUT_DEVICE_CAPS_TOUCH)
|
2017-05-26 13:34:10 -07:00
|
|
|
_touch_init(seat);
|
2016-04-06 05:46:29 -07:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (!edev->caps) goto err;
|
2017-01-31 07:54:09 -08:00
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
libinput_device_set_user_data(device, edev);
|
|
|
|
libinput_device_ref(edev->device);
|
|
|
|
|
|
|
|
if (libinput_device_config_tap_get_finger_count(edev->device) > 0)
|
|
|
|
{
|
|
|
|
Eina_Bool enable = EINA_FALSE;
|
|
|
|
|
|
|
|
enable = libinput_device_config_tap_get_default_enabled(edev->device);
|
|
|
|
libinput_device_config_tap_set_enabled(edev->device, enable);
|
|
|
|
}
|
|
|
|
|
|
|
|
return edev;
|
2017-01-31 07:54:09 -08:00
|
|
|
|
|
|
|
err:
|
2017-02-07 09:00:15 -08:00
|
|
|
eina_stringshare_del(edev->output_name);
|
2017-01-31 07:54:09 -08:00
|
|
|
free(edev);
|
|
|
|
return NULL;
|
2016-04-06 05:46:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_evdev_device_destroy(Elput_Device *edev)
|
|
|
|
{
|
|
|
|
if (!edev) return;
|
2017-06-02 15:23:45 -07:00
|
|
|
edev->refs--;
|
|
|
|
if (edev->refs) return;
|
2016-04-06 05:46:29 -07:00
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (edev->caps & ELPUT_DEVICE_CAPS_POINTER)
|
2016-04-06 05:46:29 -07:00
|
|
|
_pointer_release(edev->seat);
|
2017-05-26 13:34:10 -07:00
|
|
|
if (edev->caps & ELPUT_DEVICE_CAPS_KEYBOARD)
|
2016-04-06 05:46:29 -07:00
|
|
|
_keyboard_release(edev->seat);
|
2017-05-26 13:34:10 -07:00
|
|
|
if (edev->caps & ELPUT_DEVICE_CAPS_TOUCH)
|
2016-04-06 05:46:29 -07:00
|
|
|
_touch_release(edev->seat);
|
|
|
|
|
|
|
|
libinput_device_unref(edev->device);
|
|
|
|
eina_stringshare_del(edev->output_name);
|
2016-05-26 09:36:51 -07:00
|
|
|
|
|
|
|
if (edev->key_remap_hash) eina_hash_free(edev->key_remap_hash);
|
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
free(edev);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_evdev_keyboard_destroy(Elput_Keyboard *kbd)
|
|
|
|
{
|
|
|
|
free((char *)kbd->names.rules);
|
|
|
|
free((char *)kbd->names.model);
|
|
|
|
free((char *)kbd->names.layout);
|
|
|
|
free((char *)kbd->names.variant);
|
|
|
|
free((char *)kbd->names.options);
|
|
|
|
|
2017-05-26 13:34:10 -07:00
|
|
|
if (kbd->compose_table) xkb_compose_table_unref(kbd->compose_table);
|
|
|
|
if (kbd->compose_state) xkb_compose_state_unref(kbd->compose_state);
|
|
|
|
|
2016-04-06 05:46:29 -07:00
|
|
|
if (kbd->state) xkb_state_unref(kbd->state);
|
2017-05-26 13:34:10 -07:00
|
|
|
if (kbd->maskless_state) xkb_state_unref(kbd->maskless_state);
|
2017-05-26 13:34:10 -07:00
|
|
|
if (kbd->info) _keyboard_info_destroy(kbd->info);
|
2016-04-06 05:46:29 -07:00
|
|
|
|
|
|
|
xkb_context_unref(kbd->context);
|
|
|
|
|
|
|
|
free(kbd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_evdev_pointer_destroy(Elput_Pointer *ptr)
|
|
|
|
{
|
|
|
|
/* FIXME: destroy any resources inside pointer structure */
|
|
|
|
free(ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_evdev_touch_destroy(Elput_Touch *touch)
|
|
|
|
{
|
|
|
|
/* FIXME: destroy any resources inside touch structure */
|
|
|
|
free(touch);
|
|
|
|
}
|
2016-04-06 08:32:42 -07:00
|
|
|
|
2016-05-04 07:43:36 -07:00
|
|
|
void
|
|
|
|
_evdev_pointer_motion_send(Elput_Device *edev)
|
|
|
|
{
|
|
|
|
_pointer_motion_send(edev);
|
|
|
|
}
|
|
|
|
|
2016-04-06 08:32:42 -07:00
|
|
|
Elput_Pointer *
|
|
|
|
_evdev_pointer_get(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
if (!seat) return NULL;
|
|
|
|
if (seat->count.ptr) return seat->ptr;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Elput_Keyboard *
|
|
|
|
_evdev_keyboard_get(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
if (!seat) return NULL;
|
|
|
|
if (seat->count.kbd) return seat->kbd;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Elput_Touch *
|
|
|
|
_evdev_touch_get(Elput_Seat *seat)
|
|
|
|
{
|
|
|
|
if (!seat) return NULL;
|
|
|
|
if (seat->count.touch) return seat->touch;
|
|
|
|
return NULL;
|
|
|
|
}
|