eldbus >= $efl_version \
eio >= $efl_version \
eo >= $efl_version \
+ eeze >= $efl_version \
+ libinput \
libtbm \
libtdm >= "1.0.0" \
"
AM_CONDITIONAL([HAVE_SYSTEMD], [test "x${have_systemd}" = "xyes"])
+#libinput
+PKG_CHECK_MODULES([LIBINPUT], [libinput])
#capi-system-device
PKG_CHECK_MODULES([CAPI_SYSTEM_DEVICE],
eldbus >= ${efl_version} \
eio >= ${efl_version} \
eo >= ${efl_version} \
+eeze >= ${efl_version} \
"
e_libs="$E_LIBS $fnmatch_libs $execinfo_libs"
BuildRequires: pkgconfig(eina)
BuildRequires: pkgconfig(eio)
BuildRequires: pkgconfig(evas)
+BuildRequires: pkgconfig(eeze)
BuildRequires: pkgconfig(libtbm)
BuildRequires: pkgconfig(ttrace)
BuildRequires: pkgconfig(wayland-server)
BuildRequires: pkgconfig(libsmack)
BuildRequires: pkgconfig(pixman-1)
BuildRequires: systemd-devel
+BuildRequires: pkgconfig(libinput)
Requires: libwayland-extension-server
%if "%{LIBGOMP}" == "use"
Requires: libgomp
src/bin/e_privilege.h \
src/bin/e_security.h \
src/bin/e_keyrouter.h \
-src/bin/e_gesture.h
+src/bin/e_gesture.h \
+src/bin/e_input.h
enlightenment_src = \
src/bin/e_actions.c \
src/bin/e_privilege.c \
src/bin/e_security.c \
src/bin/e_keyrouter.c \
-src/bin/e_gesture.c
+src/bin/e_gesture.c \
+src/bin/e_input_private.h \
+src/bin/e_input.c \
+src/bin/e_input_inputs.c \
+src/bin/e_input_device.c \
+src/bin/e_input_evdev.c
src_bin_enlightenment_CPPFLAGS = $(E_CPPFLAGS) -DEFL_BETA_API_SUPPORT -DEFL_EO_API_SUPPORT -DE_LOGGING=1 @WAYLAND_CFLAGS@ $(TTRACE_CFLAGS) $(DLOG_CFLAGS) $(PIXMAN_CFLAGS) $(POLICY_CFLAGS) @TIZEN_REMOTE_SURFACE_CFLAGS@
if HAVE_LIBGOMP
if HAVE_SYSTEMD
src_bin_enlightenment_CPPFLAGS += @SYSTEMD_CFLAGS@
endif
+src_bin_enlightenment_CPPFLAGS += @LIBINPUT_CFLAGS@
src_bin_enlightenment_SOURCES = \
src/bin/e_main.c \
if HAVE_SYSTEMD
src_bin_enlightenment_LDFLAGS += @SYSTEMD_LIBS@
endif
+src_bin_enlightenment_LDFLAGS += @LIBINPUT_LIBS@
src_bin_enlightenment_info_SOURCES = \
src/bin/e.h \
#include "e_main.h"
#include "e_keyrouter.h"
#include "e_gesture.h"
+#include "e_input.h"
--- /dev/null
+#include "e.h"
+#include "e_input_private.h"
+#include <Ecore_Input_Evas.h>
+
+int _e_input_init_count;
+int _e_input_log_dom = -1;
+
+E_API int E_INPUT_EVENT_INPUT_DEVICE_ADD = -1;
+E_API int E_INPUT_EVENT_INPUT_DEVICE_DEL = -1;
+E_API int E_INPUT_EVENT_SEAT_ADD = -1;
+E_API int E_EVENT_INPUT_ENABLED = -1;
+E_API int E_EVENT_INPUT_DISABLED = -1;
+
+E_API E_Input *e_input = NULL;
+
+EINTERN int
+e_input_init(Ecore_Evas *ee)
+{
+ E_Input_Device *dev;
+
+ if (++_e_input_init_count != 1) return _e_input_init_count;
+
+ if (!eina_init()) goto eina_err;
+ if (!ecore_init()) goto ecore_err;
+ if (!ecore_event_init()) goto ecore_event_err;
+ if (!eeze_init()) goto eeze_err;
+ if (!ecore_event_evas_init()) goto ecore_event_evas_err;
+
+ _e_input_log_dom = eina_log_domain_register("e_input", EINA_COLOR_GREEN);
+ if (!_e_input_log_dom)
+ {
+ EINA_LOG_ERR("Could not create logging domain for E_Input");
+ goto log_err;
+ }
+
+ E_INPUT_EVENT_INPUT_DEVICE_ADD = ecore_event_type_new();
+ E_INPUT_EVENT_INPUT_DEVICE_DEL = ecore_event_type_new();
+ E_INPUT_EVENT_SEAT_ADD = ecore_event_type_new();
+ E_EVENT_INPUT_ENABLED = ecore_event_type_new();
+ E_EVENT_INPUT_DISABLED = ecore_event_type_new();
+
+ ecore_event_add(E_EVENT_INPUT_ENABLED, NULL, NULL, NULL);
+
+ ecore_evas_input_event_register_with_multi(ee);
+ ecore_evas_input_event_register_with_multi2(ee);
+
+ if (!e_input)
+ {
+ e_input = (E_Input *)calloc(1, sizeof(E_Input));
+ }
+
+ if (!e_input)
+ {
+ EINA_LOG_ERR("Failed to alloc memory for e_input\n");
+ goto log_err;
+ }
+
+ dev = e_input_device_open();
+
+ if (!dev)
+ {
+ EINA_LOG_ERR("Failed to open device\n");
+ goto log_err;
+ }
+
+ e_input->window = ecore_evas_window_get(ee);
+ e_input_device_window_set(dev, e_input->window);
+
+ if (!e_input_device_input_backend_create(dev, "libinput_udev"))
+ {
+ EINA_LOG_ERR("Failed to create device\n");
+ goto device_create_err;
+ }
+
+ e_input->dev = dev;
+
+ return _e_input_init_count;
+
+device_create_err:
+ e_input_device_close(dev);
+
+log_err:
+ ecore_event_evas_shutdown();
+
+ecore_event_evas_err:
+ eeze_shutdown();
+
+eeze_err:
+ ecore_event_shutdown();
+
+ecore_event_err:
+ ecore_shutdown();
+
+ecore_err:
+ eina_shutdown();
+
+eina_err:
+ return --_e_input_init_count;
+}
+
+EINTERN int
+e_input_shutdown(void)
+{
+ if (_e_input_init_count < 1) return 0;
+ if (--_e_input_init_count != 0) return _e_input_init_count;
+
+ ecore_event_add(E_EVENT_INPUT_DISABLED, NULL, NULL, NULL);
+
+ E_INPUT_EVENT_INPUT_DEVICE_ADD = -1;
+ E_INPUT_EVENT_INPUT_DEVICE_DEL = -1;
+ E_INPUT_EVENT_SEAT_ADD = -1;
+ E_EVENT_INPUT_ENABLED = -1;
+ E_EVENT_INPUT_DISABLED = -1;
+
+ e_input_device_close(e_input->dev);
+ free(e_input);
+
+ ecore_event_evas_shutdown();
+ eeze_shutdown();
+ ecore_event_shutdown();
+ ecore_shutdown();
+ eina_shutdown();
+
+ return _e_input_init_count;
+}
--- /dev/null
+#ifdef E_TYPEDEFS
+
+typedef struct _E_Input E_Input;
+
+E_API extern int E_INPUT_EVENT_INPUT_DEVICE_ADD;
+E_API extern int E_INPUT_EVENT_INPUT_DEVICE_DEL;
+E_API extern int E_INPUT_EVENT_SEAT_ADD;
+E_API extern int E_EVENT_INPUT_ENABLED;
+E_API extern int E_EVENT_INPUT_DISABLED;
+
+#else
+
+#ifndef E_INPUT_H
+#define E_INPUT_H
+
+#define E_INPUT_TYPE (int)0xE0b0beaf
+
+#include <xkbcommon/xkbcommon.h>
+
+typedef enum _E_Input_Seat_Capabilities
+{
+ E_INPUT_SEAT_POINTER = (1 << 0),
+ E_INPUT_SEAT_KEYBOARD = (1 << 1),
+ E_INPUT_SEAT_TOUCH = (1 << 2),
+} E_Input_Seat_Capabilities;
+
+struct _E_Input_Event_Input_Device_Add
+{
+ const char *name; /* descriptive device name */
+ const char *sysname; /* system name of the input device */
+ const char *seatname; /* logical name of the seat */
+ E_Input_Seat_Capabilities caps; /* capabilities on a device */
+};
+
+struct _E_Input_Event_Input_Device_Del
+{
+ const char *name; /* descriptive device name */
+ const char *sysname; /* system name of the input device */
+ const char *seatname; /* logical name of the seat */
+ E_Input_Seat_Capabilities caps; /* capabilities on a device */
+};
+
+typedef struct _E_Input_Device E_Input_Device;
+typedef struct _E_Input_Backend E_Input_Backend;
+typedef struct _E_Input_Evdev E_Input_Evdev;
+typedef struct _E_Input_Seat E_Input_Seat;
+
+typedef struct _E_Input_Event_Input_Device_Add E_Input_Event_Input_Device_Add;
+typedef struct _E_Input_Event_Input_Device_Del E_Input_Event_Input_Device_Del;
+
+struct _E_Input
+{
+ Ecore_Window window;
+ E_Input_Device *dev;
+};
+
+struct _E_Input_Device
+{
+ const char *seat;
+
+ Eina_List *seats;
+ Eina_List *inputs;
+ Eina_Hash *fd_hash;
+
+ struct xkb_context *xkb_ctx;
+ int window;
+ Eina_Bool left_handed : 1;
+};
+
+EINTERN int e_input_init(Ecore_Evas *ee);
+EINTERN int e_input_shutdown(void);
+
+EINTERN E_Input_Device *e_input_device_open(void);
+EINTERN Eina_Bool e_input_device_close(E_Input_Device *dev);
+EINTERN void e_input_device_keyboard_cached_context_set(struct xkb_context *ctx);
+EINTERN void e_input_device_keyboard_cached_keymap_set(struct xkb_keymap *map);
+EINTERN Eina_Bool e_input_device_input_backend_create(E_Input_Device *dev, const char *backend);
+EINTERN Eina_Bool e_input_device_input_create_libinput_udev(E_Input_Device *dev);
+EINTERN Eina_Bool e_input_device_input_create_libinput_path(E_Input_Device *dev);
+EINTERN void e_input_device_window_set(E_Input_Device *dev, unsigned int window);
+EINTERN void e_input_device_pointer_xy_get(E_Input_Device *dev, int *x, int *y);
+EINTERN Eina_Bool e_input_device_pointer_left_handed_set(E_Input_Device *dev, Eina_Bool left_handed);
+EINTERN Eina_Bool e_input_device_pointer_rotation_set(E_Input_Device *dev, int rotation);
+EINTERN Eina_Bool e_input_device_touch_rotation_set(E_Input_Device *dev, unsigned int rotation);
+EINTERN void e_input_device_rotation_set(E_Input_Device *dev, unsigned int rotation);
+EINTERN Eina_Bool e_input_device_touch_transformation_set(E_Input_Device *dev, int offset_x, int offset_y, int w, int h);
+
+EINTERN Eina_Bool e_input_enable_input(E_Input_Backend *input);
+EINTERN void e_input_disable_input(E_Input_Backend *input);
+
+EINTERN void e_input_evdev_axis_size_set(E_Input_Evdev *edev, int w, int h);
+EINTERN const char *e_input_evdev_sysname_get(E_Input_Evdev *evdev);
+EINTERN Eina_Bool e_input_evdev_key_remap_enable(E_Input_Evdev *edev, Eina_Bool enable);
+EINTERN Eina_Bool e_input_evdev_key_remap_set(E_Input_Evdev *edev, int *from_keys, int *to_keys, int num);
+EINTERN Eina_Bool e_input_evdev_touch_calibration_set(E_Input_Evdev *edev, float matrix[6]);
+
+E_API const Eina_List *e_input_devices_get(void);
+E_API void e_input_device_pointer_warp(E_Input_Device *dev, int x, int y);
+
+E_API const char *e_input_evdev_name_get(E_Input_Evdev *evdev);
+E_API Eina_List *e_input_seat_evdev_list_get(E_Input_Seat *seat);
+E_API int e_input_evdev_wheel_click_angle_get(E_Input_Evdev *dev);
+E_API Ecore_Device *e_input_evdev_get_ecore_device(const char *path, Ecore_Device_Class clas);
+
+#endif
+#endif
--- /dev/null
+#include "e.h"
+#include "e_input_private.h"
+
+/* e_input_device private variable */
+static Eina_List *einput_devices;
+static E_Input_Device *e_input_device_default = NULL;
+
+static int
+_device_open_no_pending(const char *device, int flags)
+{
+ int fd = -1;
+ struct stat s;
+
+ fd = open(device, flags | O_CLOEXEC);
+
+ if (fd < 0) return fd;
+ if (fstat(fd, &s) == -1)
+ {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static void
+_device_close(const char *device, int fd)
+{
+ if (fd >= 0)
+ close(fd);
+}
+
+/* local functions */
+static int
+_e_input_device_cb_open_restricted(const char *path, int flags, void *data)
+{
+ E_Input_Backend *input;
+ int fd = -1;
+
+ if (!(input = data)) return -1;
+
+ /* try to open the device */
+ fd = _device_open_no_pending(path, flags);
+
+ if (fd < 0)
+ {
+ ERR("Could not open device");
+ return -1;
+ }
+
+ if (input->dev->fd_hash)
+ eina_hash_add(input->dev->fd_hash, path, (void *)(intptr_t)fd);
+
+ return fd;
+}
+
+static void
+_e_input_device_cb_close_restricted(int fd, void *data)
+{
+ E_Input_Backend *input;
+ E_Input_Seat *seat;
+ E_Input_Evdev *edev;
+ Eina_List *l, *ll;
+
+ if (!(input = data)) return;
+
+ EINA_LIST_FOREACH(input->dev->seats, l, seat)
+ {
+ EINA_LIST_FOREACH(seat->devices, ll, edev)
+ {
+ if (edev->fd == fd)
+ {
+ _device_close(edev->path, fd);
+
+ /* re-initialize fd after closing */
+ edev->fd = -1;
+ return;
+ }
+ }
+ }
+
+ if (fd >= 0) close(fd);
+}
+
+const struct libinput_interface _input_interface =
+{
+ _e_input_device_cb_open_restricted,
+ _e_input_device_cb_close_restricted,
+};
+
+static E_Input_Device *
+_e_input_device_default_get(void)
+{
+ return e_input_device_default;
+}
+
+struct xkb_context *
+_e_input_device_cached_context_get(enum xkb_context_flags flags)
+{
+ if (!cached_context)
+ return xkb_context_new(flags);
+ else
+ return xkb_context_ref(cached_context);
+}
+
+struct xkb_keymap *
+_e_input_device_cached_keymap_get(struct xkb_context *ctx,
+ const struct xkb_rule_names *names,
+ enum xkb_keymap_compile_flags flags)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
+
+ if (!cached_keymap)
+ return xkb_map_new_from_names(ctx, names, flags);
+ else
+ return xkb_map_ref(cached_keymap);
+}
+
+void
+_e_input_device_cached_context_update(struct xkb_context *ctx)
+{
+ Eina_List *l;
+ E_Input_Device *dev;
+
+ EINA_LIST_FOREACH(einput_devices, l, dev)
+ {
+ xkb_context_unref(dev->xkb_ctx);
+ dev->xkb_ctx = xkb_context_ref(ctx);
+ }
+}
+
+void
+_e_input_device_cached_keymap_update(struct xkb_keymap *map)
+{
+ Eina_List *l, *l2, *l3;
+ E_Input_Device *dev;
+ E_Input_Seat *seat;
+ E_Input_Evdev *edev;
+
+ EINA_LIST_FOREACH(einput_devices, l, dev)
+ EINA_LIST_FOREACH(dev->seats, l2, seat)
+ EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l3, edev)
+ {
+ xkb_keymap_unref(edev->xkb.keymap);
+ edev->xkb.keymap = xkb_keymap_ref(map);
+ xkb_state_unref(edev->xkb.state);
+ edev->xkb.state = xkb_state_new(map);
+ }
+}
+
+EINTERN void
+e_input_device_keyboard_cached_context_set(struct xkb_context *ctx)
+{
+ EINA_SAFETY_ON_NULL_RETURN(ctx);
+
+ if (cached_context == ctx) return;
+
+ if (cached_context)
+ _e_input_device_cached_context_update(ctx);
+
+ cached_context = ctx;
+}
+
+EINTERN void
+e_input_device_keyboard_cached_keymap_set(struct xkb_keymap *map)
+{
+ EINA_SAFETY_ON_NULL_RETURN(map);
+
+ if (cached_keymap == map) return;
+
+ if (cached_keymap)
+ _e_input_device_cached_keymap_update(map);
+
+ cached_keymap = map;
+}
+
+static void
+e_input_device_destroy(E_Input_Device *dev)
+{
+ E_Input_Backend *input;
+ E_Input_Seat *seat;
+ E_Input_Evdev *edev;
+
+ EINA_SAFETY_ON_NULL_RETURN(dev);
+
+ EINA_LIST_FREE(dev->seats, seat)
+ {
+ EINA_LIST_FREE(seat->devices, edev)
+ {
+ if (edev->fd >= 0)
+ close(edev->fd);
+ _e_input_evdev_device_destroy(edev);
+ }
+
+ if (seat->name)
+ eina_stringshare_del(seat->name);
+ free(seat);
+ }
+
+ EINA_LIST_FREE(dev->inputs, input)
+ {
+ if (input->hdlr)
+ ecore_main_fd_handler_del(input->hdlr);
+ if (input->libinput)
+ libinput_unref(input->libinput);
+ free(input);
+ }
+
+ eina_stringshare_del(dev->seat);
+ xkb_context_unref(dev->xkb_ctx);
+ eina_hash_free(dev->fd_hash);
+ dev->fd_hash = NULL;
+
+ if (dev == e_input_device_default)
+ e_input_device_default = NULL;
+
+ free(dev);
+}
+
+static void
+_e_input_device_add_list(E_Input_Device *dev)
+{
+ Eina_List *l;
+ E_Input_Device *dev_data;
+
+ EINA_LIST_FOREACH(einput_devices, l, dev_data)
+ {
+ if (dev_data == dev) return;
+ }
+
+ einput_devices = eina_list_append(einput_devices, dev);
+}
+
+static void
+_e_input_device_remove_list(E_Input_Device *dev)
+{
+ Eina_List *l, *l_next;
+ E_Input_Device *dev_data;
+
+ EINA_LIST_FOREACH_SAFE(einput_devices, l, l_next, dev_data)
+ {
+ if (dev == dev_data)
+ einput_devices = eina_list_remove_list(einput_devices, l);
+ }
+}
+
+EINTERN E_Input_Device *
+e_input_device_open(void)
+{
+ E_Input_Device *dev = NULL;
+
+ dev = (E_Input_Device *)calloc(1, sizeof(E_Input_Device));
+
+ if (!dev)
+ {
+ EINA_LOG_ERR("Failed to alloc memory for E_Input_Device\n");
+ return NULL;
+ }
+
+ dev->seat = eina_stringshare_add("seat0");
+ dev->fd_hash = eina_hash_string_superfast_new(NULL);
+
+ /* try to create xkb context */
+ if (!(dev->xkb_ctx = _e_input_device_cached_context_get(0)))
+ {
+ ERR("Failed to create xkb context: %m");
+ goto err;
+ }
+
+ if (!e_input_device_default)
+ e_input_device_default = dev;
+
+ _e_input_device_add_list(dev);
+
+ return dev;
+
+err:
+ if (dev)
+ {
+ eina_stringshare_del(dev->seat);
+ xkb_context_unref(dev->xkb_ctx);
+ free(dev);
+ }
+
+ return NULL;
+}
+
+EINTERN Eina_Bool
+e_input_device_close(E_Input_Device *dev)
+{
+ /* check for valid device */
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+
+ _e_input_device_remove_list(dev);
+ e_input_device_destroy(dev);
+
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_input_device_window_set(E_Input_Device *dev, unsigned int window)
+{
+ /* check for valid device */
+ EINA_SAFETY_ON_TRUE_RETURN(!dev);
+
+ /* TODO : Must update window of ecore/evas device when the given window */
+ /* is not equal to the existing window. */
+
+ dev->window = window;
+}
+
+EINTERN void
+e_input_device_pointer_xy_get(E_Input_Device *dev, int *x, int *y)
+{
+ E_Input_Seat *seat;
+ E_Input_Evdev *edev;
+ Eina_List *l, *ll;
+
+ if (x) *x = 0;
+ if (y) *y = 0;
+
+ if (!dev)
+ dev = _e_input_device_default_get();
+
+ /* check for valid device */
+ EINA_SAFETY_ON_TRUE_RETURN(!dev);
+ EINA_LIST_FOREACH(dev->seats, l, seat)
+ {
+ EINA_LIST_FOREACH(seat->devices, ll, edev)
+ {
+ if (!libinput_device_has_capability(edev->device,
+ LIBINPUT_DEVICE_CAP_POINTER))
+ continue;
+
+ if (x) *x = seat->ptr.dx;
+ if (y) *y = seat->ptr.dy;
+
+ return;
+ }
+ }
+}
+
+E_API void
+e_input_device_pointer_warp(E_Input_Device *dev, int x, int y)
+{
+ E_Input_Seat *seat;
+ E_Input_Evdev *edev;
+ Eina_List *l, *ll;
+
+ if (!dev)
+ dev = _e_input_device_default_get();
+
+ /* check for valid device */
+ EINA_SAFETY_ON_TRUE_RETURN(!dev);
+ EINA_LIST_FOREACH(dev->seats, l, seat)
+ {
+ EINA_LIST_FOREACH(seat->devices, ll, edev)
+ {
+ if (!libinput_device_has_capability(edev->device,
+ LIBINPUT_DEVICE_CAP_POINTER))
+ continue;
+
+ seat->ptr.dx = seat->ptr.ix = x;
+ seat->ptr.dy = seat->ptr.iy = y;
+ _e_input_pointer_motion_post(edev);
+ }
+ }
+}
+
+EINTERN Eina_Bool
+e_input_device_pointer_left_handed_set(E_Input_Device *dev, Eina_Bool left_handed)
+{
+ E_Input_Seat *seat = NULL;
+ E_Input_Evdev *edev = NULL;
+ Eina_List *l = NULL, *l2 = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev->seats, EINA_FALSE);
+
+ if (dev->left_handed == left_handed)
+ return EINA_TRUE;
+ dev->left_handed = left_handed;
+
+ EINA_LIST_FOREACH(dev->seats, l, seat)
+ {
+ EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l2, edev)
+ {
+ if (libinput_device_has_capability(edev->device,
+ LIBINPUT_DEVICE_CAP_POINTER))
+ {
+ if (libinput_device_config_left_handed_set(edev->device, (int)left_handed) !=
+ LIBINPUT_CONFIG_STATUS_SUCCESS)
+ {
+ WRN("Failed to set left hand mode about device: %s\n",
+ libinput_device_get_name(edev->device));
+ continue;
+ }
+ }
+ }
+ }
+ return EINA_TRUE;
+}
+
+
+EINTERN Eina_Bool
+e_input_device_pointer_rotation_set(E_Input_Device *dev, int rotation)
+{
+ E_Input_Seat *seat = NULL;
+ Eina_List *l = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev->seats, EINA_FALSE);
+
+ if ((rotation % 90 != 0) || (rotation / 90 > 3) || (rotation < 0)) return EINA_FALSE;
+
+ EINA_LIST_FOREACH(dev->seats, l, seat)
+ {
+ switch (rotation)
+ {
+ case 90:
+ seat->ptr.swap = EINA_TRUE;
+ seat->ptr.invert_x = EINA_FALSE;
+ seat->ptr.invert_y = EINA_TRUE;
+ break;
+ case 180:
+ seat->ptr.swap = EINA_FALSE;
+ seat->ptr.invert_x = EINA_TRUE;
+ seat->ptr.invert_y = EINA_TRUE;
+ break;
+ case 270:
+ seat->ptr.swap = EINA_TRUE;
+ seat->ptr.invert_x = EINA_TRUE;
+ seat->ptr.invert_y = EINA_FALSE;
+ break;
+ case 0:
+ seat->ptr.swap = EINA_FALSE;
+ seat->ptr.invert_x = EINA_FALSE;
+ seat->ptr.invert_y = EINA_FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+ return EINA_TRUE;
+}
+
+EINTERN void
+e_input_device_rotation_set(E_Input_Device *dev, unsigned int rotation)
+{
+ E_Input_Seat *seat = NULL;
+ E_Input_Evdev *edev = NULL;
+ Eina_List *l = NULL, *l2 = NULL;
+ int temp;
+
+ EINA_SAFETY_ON_NULL_RETURN(dev);
+ EINA_SAFETY_ON_NULL_RETURN(dev->seats);
+
+ EINA_LIST_FOREACH(dev->seats, l, seat)
+ {
+ EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l2, edev)
+ {
+ if (libinput_device_has_capability(edev->device,
+ LIBINPUT_DEVICE_CAP_POINTER))
+ {
+ edev->mouse.minx = edev->mouse.miny = 0;
+ e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen),
+ &edev->mouse.maxw, &edev->mouse.maxh);
+
+ if (rotation == 90 || rotation == 270)
+ {
+ temp = edev->mouse.minx;
+ edev->mouse.minx = edev->mouse.miny;
+ edev->mouse.miny = temp;
+
+ temp = edev->mouse.maxw;
+ edev->mouse.maxw = edev->mouse.maxh;
+ edev->mouse.maxh = temp;
+ }
+ }
+ }
+ }
+}
+
+static void
+_e_input_device_touch_matrix_identify(float result[6])
+{
+ result[0] = 1.0;
+ result[1] = 0.0;
+ result[2] = 0.0;
+ result[3] = 0.0;
+ result[4] = 1.0;
+ result[5] = 0.0;
+}
+
+static void
+_e_input_device_touch_matrix_mulifly(float result[6], float m1[6], float m2[6])
+{
+ result[0] = m1[0] * m2 [0] + m1[1] * m2[3];
+ result[1] = m1[0] * m2 [1] + m1[1] * m2[4];
+ result[2] = m1[0] * m2 [2] + m1[1] * m2[5] + m1[2];
+ result[3] = m1[3] * m2 [0] + m1[4] * m2[3];
+ result[4] = m1[3] * m2 [1] + m1[4] * m2[4];
+ result[5] = m1[3] * m2 [2] + m1[4] * m2[5] + m1[5];
+}
+
+static void
+_e_input_device_touch_matrix_rotation_get(float result[6], int degree, float w, float h)
+{
+ if (w == 0.0) w = 1.0;
+ if (h == 0.0) h = 1.0;
+
+ switch (degree)
+ {
+ case 90:
+ result[0] = 0.0;
+ result[1] = -h/w;
+ result[2] = h/w;
+ result[3] = w/h;
+ result[4] = 0.0;
+ result[5] = 0.0;
+ break;
+ case 180:
+ result[0] = -1.0;
+ result[1] = 0.0;
+ result[2] = 1.0;
+ result[3] = 0.0;
+ result[4] = -1.0;
+ result[5] = 1.0;
+ break;
+ case 270:
+ result[0] = 0.0;
+ result[1] = h/w;
+ result[2] = 0.0;
+ result[3] = -w/h;
+ result[4] = 0.0;
+ result[5] = w/h;
+ break;
+ case 0:
+ _e_input_device_touch_matrix_identify(result);
+ break;
+ default:
+ WRN("Please input valid angle(%d)\n", degree);
+ }
+}
+
+static void
+_e_input_device_touch_matrix_translate_get(float result[6], float x, float y, float w, float h, float default_w, float default_h)
+{
+ if (default_w == 0.0) default_w = 1.0;
+ if (default_h == 0.0) default_h = 1.0;
+
+ result[0] = w / default_w;
+ result[4] = h / default_h;
+ result[2] = x / default_w;
+ result[5] = y / default_h;
+}
+
+EINTERN Eina_Bool
+e_input_device_touch_rotation_set(E_Input_Device *dev, unsigned int rotation)
+{
+ E_Input_Seat *seat = NULL;
+ E_Input_Evdev *edev = NULL;
+ Eina_List *l = NULL, *l2 = NULL;
+ float mat_translate[6] = {0.0, }, mat_rotation[6] = {0.0, }, result[6] = {0.0, };
+ float default_w = 0.0, default_h = 0.0;
+ Eina_Bool res = EINA_TRUE;
+ int output_w = 0, output_h = 0;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev->seats, EINA_FALSE);
+
+ e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen), &output_w, &output_h);
+ default_w = (float)output_w;
+ default_h = (float)output_h;
+
+ EINA_LIST_FOREACH(dev->seats, l, seat)
+ {
+ EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l2, edev)
+ {
+ if (edev->caps & E_INPUT_SEAT_TOUCH)
+ {
+ _e_input_device_touch_matrix_identify(mat_translate);
+ _e_input_device_touch_matrix_identify(mat_rotation);
+ _e_input_device_touch_matrix_identify(result);
+
+ if (edev->touch.transform.x || edev->touch.transform.y ||
+ edev->touch.transform.w || edev->touch.transform.h)
+ {
+ _e_input_device_touch_matrix_translate_get(mat_translate,
+ (float)edev->touch.transform.x,
+ (float)edev->touch.transform.y,
+ (float)edev->touch.transform.w,
+ (float)edev->touch.transform.h,
+ default_w, default_h);
+
+ }
+
+ _e_input_device_touch_matrix_rotation_get(mat_rotation, rotation, default_w, default_h);
+
+ _e_input_device_touch_matrix_mulifly(result, mat_translate, mat_rotation);
+
+ if (!e_input_evdev_touch_calibration_set(edev, result))
+ {
+ res = EINA_FALSE;
+ continue;
+ }
+ else
+ {
+ edev->touch.transform.rotation = rotation;
+ }
+ }
+ }
+ }
+
+ return res;
+}
+
+EINTERN Eina_Bool
+e_input_device_touch_transformation_set(E_Input_Device *dev, int offset_x, int offset_y, int w, int h)
+{
+ E_Input_Seat *seat = NULL;
+ E_Input_Evdev *edev = NULL;
+ Eina_List *l = NULL, *l2 = NULL;
+ float mat_translate[6] = {0.0, }, mat_rotation[6] = {0.0 }, result[6] = {0.0, };
+ float default_w = 0.0, default_h = 0.0;
+ Eina_Bool res = EINA_TRUE;
+ int output_w = 0, output_h = 0;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev->seats, EINA_FALSE);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL((w == 0) || (h == 0), EINA_FALSE);
+
+ e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen), &output_w, &output_h);
+ default_w = (float)output_w;
+ default_h = (float)output_h;
+
+ EINA_LIST_FOREACH(dev->seats, l, seat)
+ {
+ EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l2, edev)
+ {
+ if (edev->caps & E_INPUT_SEAT_TOUCH)
+ {
+ _e_input_device_touch_matrix_identify(mat_translate);
+ _e_input_device_touch_matrix_identify(mat_rotation);
+ _e_input_device_touch_matrix_identify(result);
+
+ _e_input_device_touch_matrix_translate_get(mat_translate,
+ (float)offset_x, (float)offset_y,
+ (float)w, (float)h, default_w, default_h);
+
+ if (edev->touch.transform.rotation)
+ {
+ _e_input_device_touch_matrix_rotation_get(mat_rotation,
+ edev->touch.transform.rotation,
+ default_w, default_h);
+ }
+
+ _e_input_device_touch_matrix_mulifly(result, mat_translate, mat_rotation);
+
+ if (!e_input_evdev_touch_calibration_set(edev, result))
+ {
+ res = EINA_FALSE;
+ continue;
+ }
+ else
+ {
+ edev->touch.transform.x = offset_x;
+ edev->touch.transform.y = offset_y;
+ edev->touch.transform.w = w;
+ edev->touch.transform.h = h;
+ }
+ }
+ }
+ }
+ return res;
+}
+
+static void
+e_input_device_libinput_log_handler(struct libinput *libinput EINA_UNUSED,
+ enum libinput_log_priority priority,
+ const char *format, va_list args)
+{
+ char buf[1024] = {0,};
+
+ vsnprintf(buf, 1024, format, args);
+ switch (priority)
+ {
+ case LIBINPUT_LOG_PRIORITY_DEBUG:
+ DBG("%s", buf);
+ break;
+ case LIBINPUT_LOG_PRIORITY_INFO:
+ INF("%s", buf);
+ break;
+ case LIBINPUT_LOG_PRIORITY_ERROR:
+ ERR("%s", buf);
+ break;
+ default:
+ break;
+ }
+}
+
+EINTERN Eina_Bool
+e_input_device_input_backend_create(E_Input_Device *dev, const char *backend)
+{
+ Eina_Bool res = EINA_FALSE;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(backend, EINA_FALSE);
+
+ if (!strncmp(backend, "libinput_udev", strlen("libinput_udev")))
+ res = e_input_device_input_create_libinput_udev(dev);
+ else if (!strncmp(backend, "libinput_path", strlen("libinput_path")))
+ res = e_input_device_input_create_libinput_path(dev);
+
+ return res;
+}
+
+/* public functions */
+EINTERN Eina_Bool
+e_input_device_input_create_libinput_udev(E_Input_Device *dev)
+{
+ E_Input_Backend *input;
+ char *env;
+
+ /* check for valid device */
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+
+ /* try to allocate space for new input structure */
+ if (!(input = calloc(1, sizeof(E_Input_Backend))))
+ {
+ return EINA_FALSE;
+ }
+
+ /* set reference for parent device */
+ input->dev = dev;
+
+ /* try to create libinput context */
+ input->libinput =
+ libinput_udev_create_context(&_input_interface, input, eeze_udev_get());
+ if (!input->libinput)
+ {
+ ERR("Could not create libinput context: %m");
+ goto err;
+ }
+
+ /* set libinput log priority */
+ if ((env = getenv(E_INPUT_ENV_LIBINPUT_LOG_DISABLE)) && (atoi(env) == 1))
+ libinput_log_set_handler(input->libinput, NULL);
+ else if ((env = getenv(E_INPUT_ENV_LIBINPUT_LOG_EINA_LOG)) && (atoi(env) == 1))
+ libinput_log_set_handler(input->libinput, e_input_device_libinput_log_handler);
+
+ libinput_log_set_priority(input->libinput, LIBINPUT_LOG_PRIORITY_INFO);
+
+ /* assign udev seat */
+ if (libinput_udev_assign_seat(input->libinput, dev->seat) != 0)
+ {
+ ERR("Failed to assign seat: %m");
+ goto err;
+ }
+
+ /* process pending events */
+ _input_events_process(input);
+
+ /* enable this input */
+ if (!e_input_enable_input(input))
+ {
+ ERR("Failed to enable input");
+ goto err;
+ }
+
+ /* append this input */
+ dev->inputs = eina_list_append(dev->inputs, input);
+
+ return EINA_TRUE;
+
+err:
+ if (input->libinput) libinput_unref(input->libinput);
+ free(input);
+
+ return EINA_FALSE;
+}
+
+EINTERN Eina_Bool
+e_input_device_input_create_libinput_path(E_Input_Device *dev)
+{
+ E_Input_Backend *input;
+ struct libinput_device *device;
+ int devices_num = 0;
+ char *env;
+ Eina_Stringshare *path;
+
+ /* check for valid device */
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+
+ if ((env = getenv("PATH_DEVICES_NUM")))
+ devices_num = atoi(env);
+ if (devices_num <= 0 || devices_num >= INT_MAX)
+ {
+ return EINA_TRUE;
+ }
+
+ INF("PATH_DEVICES_NUM : %d", devices_num);
+
+ /* try to allocate space for new input structure */
+ if (!(input = calloc(1, sizeof(E_Input_Backend))))
+ {
+ return EINA_FALSE;
+ }
+
+ /* set reference for parent device */
+ input->dev = dev;
+
+ /* try to create libinput context */
+ input->libinput =
+ libinput_path_create_context(&_input_interface, input);
+ if (!input->libinput)
+ {
+ ERR("Could not create libinput path context: %m");
+ goto err;
+ }
+
+ /* set libinput log priority */
+ if ((env = getenv(E_INPUT_ENV_LIBINPUT_LOG_DISABLE)) && (atoi(env) == 1))
+ libinput_log_set_handler(input->libinput, NULL);
+ else if ((env = getenv(E_INPUT_ENV_LIBINPUT_LOG_EINA_LOG)) && (atoi(env) == 1))
+ libinput_log_set_handler(input->libinput, e_input_device_libinput_log_handler);
+
+ libinput_log_set_priority(input->libinput, LIBINPUT_LOG_PRIORITY_INFO);
+
+ for (int i = 0; i < devices_num; i++)
+ {
+ char buf[1024] = "PATH_DEVICE_";
+ eina_convert_itoa(i + 1, buf + 12);
+ env = getenv(buf);
+ if (env)
+ {
+ path = eina_stringshare_add(env);
+ device = libinput_path_add_device(input->libinput, path);
+ if (!device)
+ ERR("Failed to initialized device %s", path);
+ else
+ INF("libinput_path created input device %s", path);
+ }
+ }
+
+ /* process pending events */
+ _input_events_process(input);
+
+ /* enable this input */
+ if (!e_input_enable_input(input))
+ {
+ ERR("Failed to enable input");
+ goto err;
+ }
+
+ /* append this input */
+ dev->inputs = eina_list_append(dev->inputs, input);
+
+ return EINA_TRUE;
+
+err:
+ if (input->libinput) libinput_unref(input->libinput);
+ free(input);
+
+ return EINA_FALSE;
+}
+
+
+E_API const Eina_List *
+e_input_devices_get(void)
+{
+ return einput_devices;
+}
+
--- /dev/null
+#include "e.h"
+#include "e_input_private.h"
+
+static void _device_modifiers_update(E_Input_Evdev *edev);
+
+static void
+_device_calibration_set(E_Input_Evdev *edev)
+{
+ const char *sysname;
+ float cal[6];
+ const char *device;
+ Eina_List *devices;
+ const char *vals;
+ enum libinput_config_status status;
+ E_Output *output;
+ int w = 0, h = 0;
+ int temp;
+
+ output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
+ e_output_size_get(output, &w, &h);
+
+ edev->mouse.minx = edev->mouse.miny = 0;
+ edev->mouse.maxw = w;
+ edev->mouse.maxh = h;
+
+ if (libinput_device_has_capability(edev->device, LIBINPUT_DEVICE_CAP_POINTER))
+ {
+ edev->seat->ptr.ix = edev->seat->ptr.dx = w / 2;
+ edev->seat->ptr.iy = edev->seat->ptr.dy = h / 2;
+ edev->mouse.dx = edev->seat->ptr.dx;
+ edev->mouse.dy = edev->seat->ptr.dy;
+
+ if (output->config.rotation == 90 || output->config.rotation == 270)
+ {
+ temp = edev->mouse.minx;
+ edev->mouse.minx = edev->mouse.miny;
+ edev->mouse.miny = temp;
+
+ temp = edev->mouse.maxw;
+ edev->mouse.maxw = edev->mouse.maxh;
+ edev->mouse.maxh = temp;
+ }
+ }
+
+ if ((!libinput_device_config_calibration_has_matrix(edev->device)) ||
+ (libinput_device_config_calibration_get_default_matrix(edev->device, cal) != 0))
+ return;
+
+ sysname = libinput_device_get_sysname(edev->device);
+
+ devices = eeze_udev_find_by_subsystem_sysname("input", sysname);
+ if (eina_list_count(devices) < 1) return;
+
+ 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(edev->device, cal);
+
+ if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
+ ERR("Failed to apply calibration");
+
+cont:
+ eina_stringshare_del(device);
+ continue;
+ }
+}
+
+static void
+_device_configure(E_Input_Evdev *edev)
+{
+ if (libinput_device_config_tap_get_finger_count(edev->device) > 0)
+ {
+ Eina_Bool tap = EINA_FALSE;
+
+ tap = libinput_device_config_tap_get_default_enabled(edev->device);
+ libinput_device_config_tap_set_enabled(edev->device, tap);
+ }
+
+ _device_calibration_set(edev);
+}
+
+static void
+_device_keyboard_setup(E_Input_Evdev *edev)
+{
+ E_Input_Backend *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 = _e_input_device_cached_keymap_get(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;
+ }
+
+ 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 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_modifiers_update_device(E_Input_Evdev *edev, E_Input_Evdev *from)
+{
+ xkb_mod_mask_t mask;
+
+ edev->xkb.depressed =
+ xkb_state_serialize_mods(from->xkb.state, XKB_STATE_DEPRESSED);
+ edev->xkb.latched =
+ xkb_state_serialize_mods(from->xkb.state, XKB_STATE_LATCHED);
+ edev->xkb.locked =
+ xkb_state_serialize_mods(from->xkb.state, XKB_STATE_LOCKED);
+ edev->xkb.group =
+ xkb_state_serialize_mods(from->xkb.state, XKB_STATE_EFFECTIVE);
+
+ mask = (edev->xkb.depressed | edev->xkb.latched);
+
+ if (mask & from->xkb.ctrl_mask)
+ edev->xkb.modifiers |= ECORE_EVENT_MODIFIER_CTRL;
+ if (mask & from->xkb.alt_mask)
+ edev->xkb.modifiers |= ECORE_EVENT_MODIFIER_ALT;
+ if (mask & from->xkb.shift_mask)
+ edev->xkb.modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
+ if (mask & from->xkb.win_mask)
+ edev->xkb.modifiers |= ECORE_EVENT_MODIFIER_WIN;
+ if (mask & from->xkb.scroll_mask)
+ edev->xkb.modifiers |= ECORE_EVENT_LOCK_SCROLL;
+ if (mask & from->xkb.num_mask)
+ edev->xkb.modifiers |= ECORE_EVENT_LOCK_NUM;
+ if (mask & from->xkb.caps_mask)
+ edev->xkb.modifiers |= ECORE_EVENT_LOCK_CAPS;
+ if (mask & from->xkb.altgr_mask)
+ edev->xkb.modifiers |= ECORE_EVENT_MODIFIER_ALTGR;
+}
+
+static void
+_device_modifiers_update(E_Input_Evdev *edev)
+{
+ edev->xkb.modifiers = 0;
+
+ if (edev->caps & E_INPUT_SEAT_KEYBOARD)
+ _device_modifiers_update_device(edev, edev);
+ else
+ {
+ Eina_List *l;
+ E_Input_Evdev *ed;
+
+ EINA_LIST_FOREACH(edev->seat->devices, l, ed)
+ {
+ if (!(ed->caps & E_INPUT_SEAT_KEYBOARD)) continue;
+ _device_modifiers_update_device(edev, ed);
+ }
+ }
+
+}
+
+static int
+_device_remapped_key_get(E_Input_Evdev *edev, int code)
+{
+ void *ret = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(edev, code);
+ if (!edev->key_remap_enabled) return code;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(edev->key_remap_hash, code);
+
+ ret = eina_hash_find(edev->key_remap_hash, &code);
+
+ if (ret) code = (int)(intptr_t)ret;
+
+ return code;
+}
+
+E_API Ecore_Device *
+e_input_evdev_get_ecore_device(const char *path, Ecore_Device_Class clas)
+{
+ const Eina_List *dev_list = NULL;
+ const Eina_List *l;
+ Ecore_Device *dev = NULL;
+ const char *identifier;
+
+ if (!path) return NULL;
+
+ dev_list = ecore_device_list();
+ if (!dev_list) return NULL;
+ EINA_LIST_FOREACH(dev_list, l, dev)
+ {
+ if (!dev) continue;
+ identifier = ecore_device_identifier_get(dev);
+ if (!identifier) continue;
+ if ((ecore_device_class_get(dev) == clas) && !(strcmp(identifier, path)))
+ return dev;
+ }
+ return NULL;
+}
+
+static void
+_device_handle_key(struct libinput_device *device, struct libinput_event_keyboard *event)
+{
+ E_Input_Evdev *edev;
+ E_Input_Backend *input;
+ uint32_t timestamp;
+ uint32_t code, nsyms;
+ const xkb_keysym_t *syms;
+ enum libinput_key_state state;
+ int key_count;
+ xkb_keysym_t sym = XKB_KEY_NoSymbol;
+ char key[256], keyname[256], compose_buffer[256];
+ Ecore_Event_Key *e;
+ char *tmp = NULL, *compose = NULL;
+
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+
+ if (!(input = edev->seat->input))
+ {
+ return;
+ }
+
+ timestamp = libinput_event_keyboard_get_time(event);
+ code = libinput_event_keyboard_get_key(event);
+ code = _device_remapped_key_get(edev, code) + 8;
+ state = libinput_event_keyboard_get_key_state(event);
+ key_count = libinput_event_keyboard_get_seat_key_count(event);
+
+ /* ignore key events that are not seat wide state changes */
+ if (((state == LIBINPUT_KEY_STATE_PRESSED) && (key_count != 1)) ||
+ ((state == LIBINPUT_KEY_STATE_RELEASED) && (key_count != 0)))
+ {
+ return;
+ }
+
+ xkb_state_update_key(edev->xkb.state, code,
+ (state ? XKB_KEY_DOWN : XKB_KEY_UP));
+
+ /* get the keysym for this code */
+ nsyms = xkb_key_get_syms(edev->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(edev->xkb.state,
+ xkb_map_mod_get_index(edev->xkb.keymap,
+ XKB_MOD_NAME_SHIFT),
+ XKB_STATE_MODS_EFFECTIVE))
+ {
+ if (keyname[0] != '\0')
+ keyname[0] = tolower(keyname[0]);
+ }
+
+ memset(compose_buffer, 0, sizeof(compose_buffer));
+ if (_device_keysym_translate(sym, edev->xkb.modifiers,
+ compose_buffer, sizeof(compose_buffer)))
+ {
+ compose = eina_str_convert("ISO8859-1", "UTF-8", compose_buffer);
+ if (!compose)
+ {
+ ERR("E Input cannot convert input key string '%s' to UTF-8. "
+ "Is Eina built with iconv support?", compose_buffer);
+ }
+ else
+ tmp = compose;
+ }
+
+ if (!compose) compose = compose_buffer;
+
+ e = calloc(1, 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;
+
+ strncpy((char *)e->keyname, keyname, strlen(keyname));
+ strncpy((char *)e->key, key, strlen(key));
+ if (strlen(compose)) strncpy((char *)e->compose, compose, strlen(compose));
+
+ e->window = (Ecore_Window)input->dev->window;
+ e->event_window = (Ecore_Window)input->dev->window;
+ e->root_window = (Ecore_Window)input->dev->window;
+ e->timestamp = timestamp;
+ e->same_screen = 1;
+ e->keycode = code;
+ e->data = NULL;
+
+ _device_modifiers_update(edev);
+
+ e->modifiers = edev->xkb.modifiers;
+ e->dev = e_input_evdev_get_ecore_device(edev->path, ECORE_DEVICE_CLASS_KEYBOARD);
+
+ if (state)
+ ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
+ else
+ ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
+
+ if (tmp) free(tmp);
+}
+
+static void
+_device_pointer_motion(E_Input_Evdev *edev, struct libinput_event_pointer *event)
+{
+ E_Input_Backend *input;
+ Ecore_Event_Mouse_Move *ev;
+
+ if (!(input = edev->seat->input)) return;
+
+ if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)))) return;
+
+ if (edev->seat->ptr.ix < edev->mouse.minx)
+ edev->seat->ptr.dx = edev->seat->ptr.ix = edev->mouse.minx;
+ else if (edev->seat->ptr.ix >= (edev->mouse.minx + edev->mouse.maxw))
+ edev->seat->ptr.dx = edev->seat->ptr.ix = (edev->mouse.minx + edev->mouse.maxw - 1);
+
+ if (edev->seat->ptr.iy < edev->mouse.miny)
+ edev->seat->ptr.dy = edev->seat->ptr.iy = edev->mouse.miny;
+ else if (edev->seat->ptr.iy >= (edev->mouse.miny + edev->mouse.maxh))
+ edev->seat->ptr.dy = edev->seat->ptr.iy = (edev->mouse.miny + edev->mouse.maxh - 1);
+
+ edev->mouse.dx = edev->seat->ptr.dx;
+ edev->mouse.dy = edev->seat->ptr.dy;
+
+ ev->window = (Ecore_Window)input->dev->window;
+ ev->event_window = (Ecore_Window)input->dev->window;
+ ev->root_window = (Ecore_Window)input->dev->window;
+ if (event) ev->timestamp = libinput_event_pointer_get_time(event);
+ ev->same_screen = 1;
+
+ _device_modifiers_update(edev);
+ ev->modifiers = edev->xkb.modifiers;
+
+ ev->x = edev->seat->ptr.ix;
+ ev->y = edev->seat->ptr.iy;
+ ev->root.x = ev->x;
+ ev->root.y = ev->y;
+
+ ev->multi.device = edev->mt_slot;
+ ev->multi.radius = 1;
+ ev->multi.radius_x = 1;
+ ev->multi.radius_y = 1;
+ ev->multi.pressure = 1.0;
+ 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;
+ ev->dev = e_input_evdev_get_ecore_device(edev->path, ECORE_DEVICE_CLASS_MOUSE);
+
+ ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
+}
+
+void
+_e_input_pointer_motion_post(E_Input_Evdev *edev)
+{
+ _device_pointer_motion(edev, NULL);
+}
+
+static void
+_device_handle_pointer_motion(struct libinput_device *device, struct libinput_event_pointer *event)
+{
+ E_Input_Evdev *edev;
+ double dx, dy, temp;
+
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+
+ dx = libinput_event_pointer_get_dx(event);
+ dy = libinput_event_pointer_get_dy(event);
+
+ if (edev->seat->ptr.swap)
+ {
+ temp = dx;
+ dx = dy;
+ dy = temp;
+ }
+ if (edev->seat->ptr.invert_x)
+ dx *= -1;
+ if (edev->seat->ptr.invert_y)
+ dy *= -1;
+
+ edev->seat->ptr.dx += dx;
+ edev->seat->ptr.dy += dy;
+
+ edev->mouse.dx = edev->seat->ptr.dx;
+ edev->mouse.dy = edev->seat->ptr.dy;
+
+ if (floor(edev->seat->ptr.dx) == edev->seat->ptr.ix &&
+ floor(edev->seat->ptr.dy) == edev->seat->ptr.iy)
+ {
+ return;
+ }
+
+ edev->seat->ptr.ix = edev->seat->ptr.dx;
+ edev->seat->ptr.iy = edev->seat->ptr.dy;
+
+ _device_pointer_motion(edev, event);
+}
+
+static void
+_device_handle_pointer_motion_absolute(struct libinput_device *device, struct libinput_event_pointer *event)
+{
+ E_Input_Evdev *edev;
+ int w = 0, h = 0;
+
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+
+ e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen), &w, &h);
+
+ edev->mouse.dx = edev->seat->ptr.dx =
+ libinput_event_pointer_get_absolute_x_transformed(event, w);
+ edev->mouse.dy = edev->seat->ptr.dy =
+ libinput_event_pointer_get_absolute_y_transformed(event, h);
+
+ if (floor(edev->seat->ptr.dx) == edev->seat->ptr.ix &&
+ floor(edev->seat->ptr.dy) == edev->seat->ptr.iy)
+ {
+ return;
+ }
+
+ edev->seat->ptr.ix = edev->seat->ptr.dx;
+ edev->seat->ptr.iy = edev->seat->ptr.dy;
+ _device_pointer_motion(edev, event);
+}
+
+static void
+_device_handle_button(struct libinput_device *device, struct libinput_event_pointer *event)
+{
+ E_Input_Evdev *edev;
+ E_Input_Backend *input;
+ Ecore_Event_Mouse_Button *ev;
+ enum libinput_button_state state;
+ uint32_t button, timestamp;
+
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+ if (!(input = edev->seat->input))
+ {
+ return;
+ }
+
+ if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Button))))
+ {
+ return;
+ }
+
+ state = libinput_event_pointer_get_button_state(event);
+ button = libinput_event_pointer_get_button(event);
+ timestamp = libinput_event_pointer_get_time(event);
+
+ button = ((button & 0x00F) + 1);
+ if (button == 3) button = 2;
+ else if (button == 2) button = 3;
+
+ ev->window = (Ecore_Window)input->dev->window;
+ ev->event_window = (Ecore_Window)input->dev->window;
+ ev->root_window = (Ecore_Window)input->dev->window;
+ ev->timestamp = timestamp;
+ ev->same_screen = 1;
+
+ _device_modifiers_update(edev);
+ ev->modifiers = edev->xkb.modifiers;
+
+ ev->x = edev->seat->ptr.ix;
+ ev->y = edev->seat->ptr.iy;
+ ev->root.x = ev->x;
+ ev->root.y = ev->y;
+
+ ev->multi.device = edev->mt_slot;
+ ev->multi.radius = 1;
+ ev->multi.radius_x = 1;
+ ev->multi.radius_y = 1;
+ ev->multi.pressure = 1.0;
+ 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;
+ ev->dev = e_input_evdev_get_ecore_device(edev->path, ECORE_DEVICE_CLASS_MOUSE);
+
+ if (state)
+ {
+ unsigned int current;
+
+ current = timestamp;
+ edev->mouse.did_double = EINA_FALSE;
+ edev->mouse.did_triple = EINA_FALSE;
+
+ if (((current - edev->mouse.prev) <= edev->mouse.threshold) &&
+ (button == edev->mouse.prev_button))
+ {
+ edev->mouse.did_double = EINA_TRUE;
+ if (((current - edev->mouse.last) <= (2 * edev->mouse.threshold)) &&
+ (button == edev->mouse.last_button))
+ {
+ edev->mouse.did_triple = EINA_TRUE;
+ edev->mouse.prev = 0;
+ edev->mouse.last = 0;
+ current = 0;
+ }
+ }
+
+ edev->mouse.last = edev->mouse.prev;
+ edev->mouse.prev = current;
+ edev->mouse.last_button = edev->mouse.prev_button;
+ edev->mouse.prev_button = button;
+ }
+
+ ev->buttons = button;
+
+ if (edev->mouse.did_double)
+ ev->double_click = 1;
+ if (edev->mouse.did_triple)
+ ev->triple_click = 1;
+
+ 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);
+}
+
+static void
+_device_handle_axis(struct libinput_device *device, struct libinput_event_pointer *event)
+{
+ E_Input_Evdev *edev;
+ E_Input_Backend *input;
+ Ecore_Event_Mouse_Wheel *ev;
+ uint32_t timestamp;
+ enum libinput_pointer_axis axis;
+
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+ if (!(input = edev->seat->input))
+ {
+ return;
+ }
+
+ if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Wheel))))
+ {
+ return;
+ }
+
+ timestamp = libinput_event_pointer_get_time(event);
+
+ ev->window = (Ecore_Window)input->dev->window;
+ ev->event_window = (Ecore_Window)input->dev->window;
+ ev->root_window = (Ecore_Window)input->dev->window;
+ ev->timestamp = timestamp;
+ ev->same_screen = 1;
+
+ _device_modifiers_update(edev);
+ ev->modifiers = edev->xkb.modifiers;
+
+ ev->x = edev->seat->ptr.ix;
+ ev->y = edev->seat->ptr.iy;
+ ev->root.x = ev->x;
+ ev->root.y = ev->y;
+ ev->dev = e_input_evdev_get_ecore_device(edev->path, ECORE_DEVICE_CLASS_MOUSE);
+
+ axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
+ if (libinput_event_pointer_has_axis(event, axis))
+ ev->z = libinput_event_pointer_get_axis_value(event, axis);
+
+ axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
+ if (libinput_event_pointer_has_axis(event, axis))
+ {
+ ev->direction = 1;
+ ev->z = libinput_event_pointer_get_axis_value(event, axis);
+ }
+
+ ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
+}
+
+static void
+_device_handle_touch_event_send(E_Input_Evdev *edev, struct libinput_event_touch *event, int state)
+{
+ E_Input_Backend *input;
+ Ecore_Event_Mouse_Button *ev;
+ uint32_t timestamp, button = 0;
+
+ if (!edev) return;
+ if (!(input = edev->seat->input)) return;
+
+ if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Button)))) return;
+
+ timestamp = libinput_event_touch_get_time(event);
+
+ ev->window = (Ecore_Window)input->dev->window;
+ ev->event_window = (Ecore_Window)input->dev->window;
+ ev->root_window = (Ecore_Window)input->dev->window;
+ ev->timestamp = timestamp;
+ ev->same_screen = 1;
+
+ _device_modifiers_update(edev);
+ ev->modifiers = edev->xkb.modifiers;
+
+ ev->x = edev->seat->ptr.ix;
+ ev->y = edev->seat->ptr.iy;
+ ev->root.x = ev->x;
+ ev->root.y = ev->y;
+
+ ev->multi.device = edev->mt_slot;
+ ev->multi.radius = 1;
+ ev->multi.radius_x = 1;
+ ev->multi.radius_y = 1;
+ ev->multi.pressure = 1.0;
+ ev->multi.angle = 0.0;
+#if LIBINPUT_SUPPORT_EXTRA_TOUCH_EVENT
+ if (libinput_event_get_type(libinput_event_touch_get_base_event(event))
+ == LIBINPUT_EVENT_TOUCH_DOWN)
+ {
+ if (libinput_event_touch_has_minor(event))
+ ev->multi.radius_x = libinput_event_touch_get_minor(event);
+ if (libinput_event_touch_has_major(event))
+ ev->multi.radius_y = libinput_event_touch_get_major(event);
+ if (libinput_event_touch_has_pressure(event))
+ ev->multi.pressure = libinput_event_touch_get_pressure(event);
+ if (libinput_event_touch_has_orientation(event))
+ ev->multi.angle = libinput_event_touch_get_orientation(event);
+ }
+#endif
+ ev->multi.x = ev->x;
+ ev->multi.y = ev->y;
+ ev->multi.root.x = ev->x;
+ ev->multi.root.y = ev->y;
+ ev->dev = e_input_evdev_get_ecore_device(edev->path, ECORE_DEVICE_CLASS_TOUCH);
+
+ if (state == ECORE_EVENT_MOUSE_BUTTON_DOWN)
+ {
+ unsigned int current;
+
+ current = timestamp;
+ edev->mouse.did_double = EINA_FALSE;
+ edev->mouse.did_triple = EINA_FALSE;
+
+ if (((current - edev->mouse.prev) <= edev->mouse.threshold) &&
+ (button == edev->mouse.prev_button))
+ {
+ edev->mouse.did_double = EINA_TRUE;
+ if (((current - edev->mouse.last) <= (2 * edev->mouse.threshold)) &&
+ (button == edev->mouse.last_button))
+ {
+ edev->mouse.did_triple = EINA_TRUE;
+ edev->mouse.prev = 0;
+ edev->mouse.last = 0;
+ current = 0;
+ }
+ }
+
+ edev->mouse.last = edev->mouse.prev;
+ edev->mouse.prev = current;
+ edev->mouse.last_button = edev->mouse.prev_button;
+ edev->mouse.prev_button = button;
+ }
+
+ ev->buttons = ((button & 0x00F) + 1);
+
+ if (edev->mouse.did_double)
+ ev->double_click = 1;
+ if (edev->mouse.did_triple)
+ ev->triple_click = 1;
+
+ ecore_event_add(state, ev, NULL, NULL);
+}
+
+static void
+_device_handle_touch_motion_send(E_Input_Evdev *edev, struct libinput_event_touch *event)
+{
+ E_Input_Backend *input;
+ Ecore_Event_Mouse_Move *ev;
+
+ if (!edev) return;
+ if (!(input = edev->seat->input)) return;
+
+ if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)))) return;
+
+ ev->window = (Ecore_Window)input->dev->window;
+ ev->event_window = (Ecore_Window)input->dev->window;
+ ev->root_window = (Ecore_Window)input->dev->window;
+ ev->timestamp = libinput_event_touch_get_time(event);
+ ev->same_screen = 1;
+
+ _device_modifiers_update(edev);
+ ev->modifiers = edev->xkb.modifiers;
+ ev->modifiers = 0;
+
+ ev->x = edev->seat->ptr.ix;
+ ev->y = edev->seat->ptr.iy;
+ ev->root.x = ev->x;
+ ev->root.y = ev->y;
+
+ ev->multi.device = edev->mt_slot;
+ ev->multi.radius = 1;
+ ev->multi.radius_x = 1;
+ ev->multi.radius_y = 1;
+ ev->multi.pressure = 1.0;
+ ev->multi.angle = 0.0;
+#if LIBINPUT_SUPPORT_EXTRA_TOUCH_EVENT
+ if (libinput_event_touch_has_minor(event))
+ ev->multi.radius_x = libinput_event_touch_get_minor(event);
+ if (libinput_event_touch_has_major(event))
+ ev->multi.radius_y = libinput_event_touch_get_major(event);
+ if (libinput_event_touch_has_pressure(event))
+ ev->multi.pressure = libinput_event_touch_get_pressure(event);
+ if (libinput_event_touch_has_orientation(event))
+ ev->multi.angle = libinput_event_touch_get_orientation(event);
+#endif
+ ev->multi.x = ev->x;
+ ev->multi.y = ev->y;
+ ev->multi.root.x = ev->x;
+ ev->multi.root.y = ev->y;
+ ev->dev = e_input_evdev_get_ecore_device(edev->path, ECORE_DEVICE_CLASS_TOUCH);
+
+ ecore_event_add(ECORE_EVENT_MOUSE_MOVE, ev, NULL, NULL);
+}
+
+static void
+_device_handle_touch_down(struct libinput_device *device, struct libinput_event_touch *event)
+{
+ E_Input_Evdev *edev;
+ int w = 0, h = 0;
+
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+
+ e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen), &w, &h);
+
+ edev->mouse.dx = edev->seat->ptr.ix = edev->seat->ptr.dx =
+ libinput_event_touch_get_x_transformed(event, w);
+ edev->mouse.dy = edev->seat->ptr.iy = edev->seat->ptr.dy =
+ libinput_event_touch_get_y_transformed(event, h);
+
+ edev->mt_slot = libinput_event_touch_get_slot(event);
+
+ _device_handle_touch_motion_send(edev, event);
+ _device_handle_touch_event_send(edev, event, ECORE_EVENT_MOUSE_BUTTON_DOWN);
+}
+
+static void
+_device_handle_touch_motion(struct libinput_device *device, struct libinput_event_touch *event)
+{
+ E_Input_Evdev *edev;
+ int w = 0, h = 0;
+
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+
+ e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen), &w, &h);
+
+ edev->mouse.dx = edev->seat->ptr.dx =
+ libinput_event_touch_get_x_transformed(event, w);
+ edev->mouse.dy = edev->seat->ptr.dy =
+ libinput_event_touch_get_y_transformed(event, h);
+
+ if (floor(edev->seat->ptr.dx) == edev->seat->ptr.ix &&
+ floor(edev->seat->ptr.dy) == edev->seat->ptr.iy)
+ {
+ return;
+ }
+
+ edev->seat->ptr.ix = edev->seat->ptr.dx;
+ edev->seat->ptr.iy = edev->seat->ptr.dy;
+
+ edev->mt_slot = libinput_event_touch_get_slot(event);
+
+ _device_handle_touch_motion_send(edev, event);
+}
+
+static void
+_device_handle_touch_up(struct libinput_device *device, struct libinput_event_touch *event)
+{
+ E_Input_Evdev *edev;
+
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+
+ edev->mt_slot = libinput_event_touch_get_slot(event);
+ _device_handle_touch_event_send(edev, event, ECORE_EVENT_MOUSE_BUTTON_UP);
+}
+
+static void
+_device_handle_touch_frame(struct libinput_device *device EINA_UNUSED, struct libinput_event_touch *event EINA_UNUSED)
+{
+ /* DBG("Unhandled Touch Frame Event"); */
+}
+
+static void
+_e_input_aux_data_event_free(void *user_data EINA_UNUSED, void *ev)
+{
+ Ecore_Event_Axis_Update *e = (Ecore_Event_Axis_Update *)ev;
+ if (e->axis)
+ free(e->axis);
+ free(e);
+}
+
+static void
+_device_handle_touch_aux_data(struct libinput_device *device, struct libinput_event_touch_aux_data *event)
+{
+ E_Input_Evdev *edev;
+ E_Input_Backend *input;
+ Ecore_Event_Axis_Update *ev;
+ Ecore_Axis *axis;
+
+ if (libinput_event_touch_aux_data_get_type(event) != LIBINPUT_TOUCH_AUX_DATA_TYPE_PALM &&
+ libinput_event_touch_aux_data_get_value(event) > 0)
+ goto end;
+
+ if (!(edev = libinput_device_get_user_data(device))) goto end;
+ if (!(input = edev->seat->input)) goto end;
+ if (!(ev = calloc(1, sizeof(Ecore_Event_Axis_Update))))goto end;
+
+ ev->window = (Ecore_Window)input->dev->window;
+ ev->event_window = (Ecore_Window)input->dev->window;
+ ev->root_window = (Ecore_Window)input->dev->window;
+ ev->timestamp = libinput_event_touch_aux_data_get_time(event);
+
+ axis = (Ecore_Axis *)calloc(1, sizeof(Ecore_Axis));
+ if (axis)
+ {
+ axis->label = ECORE_AXIS_LABEL_TOUCH_PALM;
+ axis->value = libinput_event_touch_aux_data_get_value(event);
+ ev->naxis = 1;
+ }
+ ev->axis = axis;
+
+ ecore_event_add(ECORE_EVENT_AXIS_UPDATE, ev, _e_input_aux_data_event_free, NULL);
+
+end:
+ ;
+}
+
+E_Input_Evdev *
+_e_input_evdev_device_create(E_Input_Seat *seat, struct libinput_device *device)
+{
+ E_Input_Evdev *edev;
+ Eina_List *devices;
+ E_Input_Backend *b_input;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
+
+ /* try to allocate space for new evdev */
+ if (!(edev = calloc(1, sizeof(E_Input_Evdev)))) return NULL;
+
+ edev->seat = seat;
+ edev->device = device;
+ edev->path = eina_stringshare_add(libinput_device_get_sysname(device));
+ edev->fd = -1;
+
+ if (edev->path)
+ {
+ devices = eeze_udev_find_by_filter("input", NULL, edev->path);
+ if (eina_list_count(devices) >= 1)
+ {
+ Eina_List *l;
+ const char *dev, *name;
+
+ EINA_LIST_FOREACH(devices, l, dev)
+ {
+ name = eeze_udev_syspath_get_devname(dev);
+ if (name && strstr(name, edev->path))
+ {
+ eina_stringshare_replace(&edev->path, eeze_udev_syspath_get_devpath(dev));
+ break;
+ }
+ }
+
+ EINA_LIST_FREE(devices, dev)
+ eina_stringshare_del(dev);
+ }
+ }
+
+ if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD))
+ {
+ edev->caps |= E_INPUT_SEAT_KEYBOARD;
+ _device_keyboard_setup(edev);
+ }
+
+ if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER))
+ {
+ edev->caps |= E_INPUT_SEAT_POINTER;
+
+ /* TODO: make this configurable */
+ edev->mouse.threshold = 250;
+
+ b_input = seat->input;
+ if (b_input->left_handed == EINA_TRUE)
+ {
+ if (libinput_device_config_left_handed_set(device, 1) !=
+ LIBINPUT_CONFIG_STATUS_SUCCESS)
+ {
+ WRN("Failed to set left hand mode about device: %s\n",
+ libinput_device_get_name(device));
+ }
+ }
+ }
+
+ if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
+ {
+ int palm_code;
+ edev->caps |= E_INPUT_SEAT_TOUCH;
+ palm_code = libinput_device_touch_aux_data_get_code(LIBINPUT_TOUCH_AUX_DATA_TYPE_PALM);
+ if (libinput_device_touch_has_aux_data(device, palm_code))
+ {
+ libinput_device_touch_set_aux_data(device, palm_code);
+ }
+ }
+
+ libinput_device_set_user_data(device, edev);
+ libinput_device_ref(device);
+
+ /* configure device */
+ _device_configure(edev);
+
+ return edev;
+}
+
+void
+_e_input_evdev_device_destroy(E_Input_Evdev *edev)
+{
+ EINA_SAFETY_ON_NULL_RETURN(edev);
+
+ if (edev->caps & E_INPUT_SEAT_KEYBOARD)
+ {
+ if (edev->xkb.state) xkb_state_unref(edev->xkb.state);
+ if (edev->xkb.keymap) xkb_map_unref(edev->xkb.keymap);
+ }
+
+ if (edev->path) eina_stringshare_del(edev->path);
+ if (edev->device) libinput_device_unref(edev->device);
+ if (edev->key_remap_hash) eina_hash_free(edev->key_remap_hash);
+
+ free(edev);
+}
+
+Eina_Bool
+_e_input_evdev_event_process(struct libinput_event *event)
+{
+ struct libinput_device *device;
+ Eina_Bool ret = EINA_TRUE;
+
+ device = libinput_event_get_device(event);
+ switch (libinput_event_get_type(event))
+ {
+ case LIBINPUT_EVENT_KEYBOARD_KEY:
+ _device_handle_key(device, libinput_event_get_keyboard_event(event));
+ break;
+ case LIBINPUT_EVENT_POINTER_MOTION:
+ _device_handle_pointer_motion(device,
+ libinput_event_get_pointer_event(event));
+ break;
+ case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
+ _device_handle_pointer_motion_absolute(device,
+ libinput_event_get_pointer_event(event));
+ break;
+ case LIBINPUT_EVENT_POINTER_BUTTON:
+ _device_handle_button(device, libinput_event_get_pointer_event(event));
+ break;
+ case LIBINPUT_EVENT_POINTER_AXIS:
+ _device_handle_axis(device, libinput_event_get_pointer_event(event));
+ break;
+ case LIBINPUT_EVENT_TOUCH_DOWN:
+ _device_handle_touch_down(device, libinput_event_get_touch_event(event));
+ break;
+ case LIBINPUT_EVENT_TOUCH_MOTION:
+ _device_handle_touch_motion(device,
+ libinput_event_get_touch_event(event));
+ break;
+ case LIBINPUT_EVENT_TOUCH_UP:
+ _device_handle_touch_up(device, libinput_event_get_touch_event(event));
+ break;
+ case LIBINPUT_EVENT_TOUCH_FRAME:
+ _device_handle_touch_frame(device, libinput_event_get_touch_event(event));
+ break;
+ case LIBINPUT_EVENT_TOUCH_AUX_DATA:
+ _device_handle_touch_aux_data(device, libinput_event_get_touch_aux_data(event));
+ break;
+ default:
+ ret = EINA_FALSE;
+ break;
+ }
+
+ return ret;
+}
+
+/**
+ * @brief Set the axis size of the given device.
+ *
+ * @param dev The device to set the axis size to.
+ * @param w The width of the axis.
+ * @param h The height of the axis.
+ *
+ * This function sets set the width @p w and height @p h of the axis
+ * of device @p dev. If @p dev is a relative input device, a width and
+ * height must set for it. If its absolute set the ioctl correctly, if
+ * not, unsupported device.
+ */
+EINTERN void
+e_input_evdev_axis_size_set(E_Input_Evdev *edev, int w, int h)
+{
+ const char *sysname;
+ float cal[6];
+ const char *device;
+ Eina_List *devices;
+ const char *vals;
+ enum libinput_config_status status;
+
+ EINA_SAFETY_ON_NULL_RETURN(edev);
+ EINA_SAFETY_ON_TRUE_RETURN((w == 0) || (h == 0));
+
+ if ((!libinput_device_config_calibration_has_matrix(edev->device)) ||
+ (libinput_device_config_calibration_get_default_matrix(edev->device, cal) != 0))
+ return;
+
+ sysname = libinput_device_get_sysname(edev->device);
+
+ devices = eeze_udev_find_by_subsystem_sysname("input", sysname);
+ if (eina_list_count(devices) < 1) return;
+
+ 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(edev->device, cal);
+
+ if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
+ ERR("Failed to apply calibration");
+
+cont:
+ eina_stringshare_del(device);
+ continue;
+ }
+}
+
+E_API const char *
+e_input_evdev_name_get(E_Input_Evdev *evdev)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(evdev, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(evdev->device, NULL);
+
+ return libinput_device_get_name(evdev->device);
+}
+
+EINTERN const char *
+e_input_evdev_sysname_get(E_Input_Evdev *evdev)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(evdev, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(evdev->device, NULL);
+
+ return libinput_device_get_sysname(evdev->device);
+}
+
+EINTERN Eina_Bool
+e_input_evdev_key_remap_enable(E_Input_Evdev *edev, Eina_Bool enable)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(edev, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(edev->device, EINA_FALSE);
+
+ edev->key_remap_enabled = enable;
+
+ if (enable == EINA_FALSE && edev->key_remap_hash)
+ {
+ eina_hash_free(edev->key_remap_hash);
+ edev->key_remap_hash = NULL;
+ }
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_input_evdev_key_remap_set(E_Input_Evdev *edev, int *from_keys, int *to_keys, int num)
+{
+ int i;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(edev, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(edev->device, 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_SAFETY_ON_TRUE_RETURN_VAL(!edev->key_remap_enabled, EINA_FALSE);
+
+ if (edev->key_remap_hash == NULL)
+ edev->key_remap_hash = eina_hash_int32_new(NULL);
+
+ if (edev->key_remap_hash == NULL)
+ {
+ ERR("Failed to set remap key information : creating a hash is failed.");
+ return EINA_FALSE;
+ }
+
+ for (i = 0; i < num ; i++)
+ {
+ if (!from_keys[i] || !to_keys[i])
+ {
+ ERR("Failed to set remap key information : given arguments are invalid.");
+ return EINA_FALSE;
+ }
+ }
+
+ 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;
+}
+
+E_API int
+e_input_evdev_wheel_click_angle_get(E_Input_Evdev *dev)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(dev, -1);
+ return libinput_device_config_scroll_get_wheel_click_angle(dev->device);
+}
+
+EINTERN Eina_Bool
+e_input_evdev_touch_calibration_set(E_Input_Evdev *edev, float matrix[6])
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(edev, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(edev->device, EINA_FALSE);
+
+ if (!libinput_device_config_calibration_has_matrix(edev->device) ||
+ !libinput_device_has_capability(edev->device, LIBINPUT_DEVICE_CAP_TOUCH))
+ return EINA_FALSE;
+
+ if (libinput_device_config_calibration_set_matrix(edev->device, matrix) !=
+ LIBINPUT_CONFIG_STATUS_SUCCESS)
+ {
+ WRN("Failed to set input transformation about device: %s\n",
+ libinput_device_get_name(edev->device));
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
--- /dev/null
+#include "e.h"
+#include "e_input_private.h"
+
+static void
+_device_close(const char *device, int fd)
+{
+ if (fd >= 0)
+ close(fd);
+}
+
+static E_Input_Seat *
+_seat_create(E_Input_Backend *input, const char *seat)
+{
+ E_Input_Seat *s;
+
+ /* try to allocate space for new seat */
+ if (!(s = calloc(1, sizeof(E_Input_Seat))))
+ return NULL;
+
+ s->input = input;
+ s->name = eina_stringshare_add(seat);
+
+ /* add this new seat to list */
+ input->dev->seats = eina_list_append(input->dev->seats, s);
+
+ ecore_event_add(E_INPUT_EVENT_SEAT_ADD, NULL, NULL, NULL);
+
+ return s;
+}
+
+static void
+_e_input_event_input_device_add_free(void *data EINA_UNUSED, void *ev)
+{
+ E_Input_Event_Input_Device_Add *e;
+
+ e = ev;
+ eina_stringshare_del(e->name);
+ eina_stringshare_del(e->sysname);
+ eina_stringshare_del(e->seatname);
+
+ free(e);
+}
+
+static void
+_e_input_event_input_device_del_free(void *data EINA_UNUSED, void *ev)
+{
+ E_Input_Event_Input_Device_Del *e;
+
+ e = ev;
+ eina_stringshare_del(e->name);
+ eina_stringshare_del(e->sysname);
+ eina_stringshare_del(e->seatname);
+
+ free(e);
+}
+
+static E_Input_Seat *
+_seat_get(E_Input_Backend *input, const char *seat)
+{
+ E_Input_Seat *s;
+ Eina_List *l;
+
+ /* search for this name in existing seats */
+ EINA_LIST_FOREACH(input->dev->seats, l, s)
+ if (!strcmp(s->name, seat))
+ return s;
+
+ return _seat_create(input, seat);
+}
+
+static void
+_ecore_event_device_info_free(void *data EINA_UNUSED, void *ev)
+{
+ Ecore_Event_Device_Info *e;
+
+ e = ev;
+ eina_stringshare_del(e->name);
+ eina_stringshare_del(e->identifier);
+ eina_stringshare_del(e->seatname);
+
+ free(e);
+}
+
+static Ecore_Device_Class
+_e_input_seat_cap_to_ecore_device_class(unsigned int cap)
+{
+ switch(cap)
+ {
+ case E_INPUT_SEAT_POINTER:
+ return ECORE_DEVICE_CLASS_MOUSE;
+ case E_INPUT_SEAT_KEYBOARD:
+ return ECORE_DEVICE_CLASS_KEYBOARD;
+ case E_INPUT_SEAT_TOUCH:
+ return ECORE_DEVICE_CLASS_TOUCH;
+ default:
+ return ECORE_DEVICE_CLASS_NONE;
+ }
+ return ECORE_DEVICE_CLASS_NONE;
+}
+
+void
+_e_input_send_device_info(unsigned int window, E_Input_Evdev *edev, Ecore_Device_Class clas, Ecore_Device_Subclass subclas, Eina_Bool flag)
+{
+ Ecore_Event_Device_Info *e;
+
+ if (!(e = calloc(1, sizeof(Ecore_Event_Device_Info)))) return;
+
+ e->name = eina_stringshare_add(libinput_device_get_name(edev->device));
+ e->identifier = eina_stringshare_add(edev->path);
+ e->seatname = eina_stringshare_add(edev->seat->name);
+ e->clas = clas;
+ e->subclas = subclas;
+ e->window = window;
+
+ if (flag)
+ ecore_event_add(ECORE_EVENT_DEVICE_ADD, e, _ecore_event_device_info_free, NULL);
+ else
+ ecore_event_add(ECORE_EVENT_DEVICE_DEL, e, _ecore_event_device_info_free, NULL);
+}
+
+static Eina_Bool
+_e_input_add_ecore_device(E_Input_Evdev *edev, Ecore_Device_Class clas)
+{
+ const Eina_List *dev_list = NULL;
+ const Eina_List *l;
+ Ecore_Device *dev = NULL;
+ const char *identifier;
+
+ if (!edev->path) return EINA_FALSE;
+
+ dev_list = ecore_device_list();
+ if (dev_list)
+ {
+ EINA_LIST_FOREACH(dev_list, l, dev)
+ {
+ if (!dev) continue;
+ identifier = ecore_device_identifier_get(dev);
+ if (!identifier) continue;
+ if ((ecore_device_class_get(dev) == clas) && (!strcmp(identifier, edev->path)))
+ return EINA_FALSE;
+ }
+ }
+
+ if(!(dev = ecore_device_add())) return EINA_FALSE;
+
+ ecore_device_name_set(dev, libinput_device_get_name(edev->device));
+ ecore_device_description_set(dev, libinput_device_get_name(edev->device));
+ ecore_device_identifier_set(dev, edev->path);
+ ecore_device_class_set(dev, clas);
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_input_remove_ecore_device(E_Input_Evdev *edev, Ecore_Device_Class clas)
+{
+ const Eina_List *dev_list = NULL;
+ const Eina_List *l;
+ Ecore_Device *dev = NULL;
+ const char *identifier;
+
+ if (!edev->path) return EINA_FALSE;
+
+ dev_list = ecore_device_list();
+ if (!dev_list) return EINA_FALSE;
+ EINA_LIST_FOREACH(dev_list, l, dev)
+ {
+ if (!dev) continue;
+ identifier = ecore_device_identifier_get(dev);
+ if (!identifier) continue;
+ if ((ecore_device_class_get(dev) == clas) && (!strcmp(identifier, edev->path)))
+ {
+ ecore_device_del(dev);
+ return EINA_TRUE;
+ }
+ }
+ return EINA_FALSE;
+}
+
+void
+_e_input_device_add(unsigned int window, E_Input_Evdev *edev)
+{
+ Eina_Bool ret = EINA_FALSE;
+ Ecore_Device_Class clas;
+
+ if (edev->caps & E_INPUT_SEAT_POINTER)
+ {
+ clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_POINTER);
+ ret = _e_input_add_ecore_device(edev, clas);
+ if (ret) _e_input_send_device_info(window, edev, clas, ECORE_DEVICE_SUBCLASS_NONE, 1);
+ }
+ if (edev->caps & E_INPUT_SEAT_KEYBOARD)
+ {
+ clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_KEYBOARD);
+ ret = _e_input_add_ecore_device(edev, clas);
+ if (ret) _e_input_send_device_info(window, edev, clas, ECORE_DEVICE_SUBCLASS_NONE, 1);
+ }
+ if (edev->caps & E_INPUT_SEAT_TOUCH)
+ {
+ clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_TOUCH);
+ ret = _e_input_add_ecore_device(edev, clas);
+ if (ret) _e_input_send_device_info(window, edev, clas, ECORE_DEVICE_SUBCLASS_NONE, 1);
+ }
+}
+
+void
+_e_input_device_remove(unsigned int window, E_Input_Evdev *edev)
+{
+ Eina_Bool ret = EINA_FALSE;
+ Ecore_Device_Class clas;
+
+ if (edev->caps & E_INPUT_SEAT_POINTER)
+ {
+ clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_POINTER);
+ ret = _e_input_remove_ecore_device(edev, clas);
+ if (ret) _e_input_send_device_info(window, edev, clas, ECORE_DEVICE_SUBCLASS_NONE, 0);
+ }
+ if (edev->caps & E_INPUT_SEAT_KEYBOARD)
+ {
+ clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_KEYBOARD);
+ ret = _e_input_remove_ecore_device(edev, clas);
+ if (ret) _e_input_send_device_info(window, edev, clas, ECORE_DEVICE_SUBCLASS_NONE, 0);
+ }
+ if (edev->caps & E_INPUT_SEAT_TOUCH)
+ {
+ clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_TOUCH);
+ ret = _e_input_remove_ecore_device(edev, clas);
+ if (ret) _e_input_send_device_info(window, edev, clas, ECORE_DEVICE_SUBCLASS_NONE, 0);
+ }
+}
+
+static void
+_device_added(E_Input_Backend *input, struct libinput_device *device)
+{
+ struct libinput_seat *libinput_seat;
+ const char *seat_name;
+ E_Input_Seat *seat;
+ E_Input_Evdev *edev;
+ E_Input_Event_Input_Device_Add *ev;
+
+ libinput_seat = libinput_device_get_seat(device);
+ seat_name = libinput_seat_get_logical_name(libinput_seat);
+
+ /* try to get a seat */
+ if (!(seat = _seat_get(input, seat_name)))
+ {
+ ERR("Could not get matching seat: %s", seat_name);
+ return;
+ }
+
+ /* try to create a new evdev device */
+ if (!(edev = _e_input_evdev_device_create(seat, device)))
+ {
+ ERR("Failed to create new evdev device");
+ return;
+ }
+
+ edev->fd = (int)(intptr_t)eina_hash_find(input->dev->fd_hash, edev->path);
+
+ /* append this device to the seat */
+ seat->devices = eina_list_append(seat->devices, edev);
+
+ ev = calloc(1, sizeof(E_Input_Event_Input_Device_Add));
+ if (!ev)
+ {
+ return;
+ }
+
+ ev->name = eina_stringshare_add(libinput_device_get_name(device));
+ ev->sysname = eina_stringshare_add(edev->path);
+ ev->seatname = eina_stringshare_add(edev->seat->name);
+ ev->caps = edev->caps;
+
+ ecore_event_add(E_INPUT_EVENT_INPUT_DEVICE_ADD,
+ ev,
+ _e_input_event_input_device_add_free,
+ NULL);
+
+ if (input->dev->window != -1)
+ _e_input_device_add(input->dev->window, edev);
+}
+
+static void
+_device_removed(E_Input_Backend *input, struct libinput_device *device)
+{
+ E_Input_Evdev *edev;
+ E_Input_Event_Input_Device_Del *ev;
+
+ /* try to get the evdev structure */
+ if (!(edev = libinput_device_get_user_data(device)))
+ {
+ return;
+ }
+
+ ev = calloc(1, sizeof(E_Input_Event_Input_Device_Del));
+ if (!ev)
+ {
+ return;
+ }
+
+ ev->name = eina_stringshare_add(libinput_device_get_name(device));
+ ev->sysname = eina_stringshare_add(edev->path);
+ ev->seatname = eina_stringshare_add(edev->seat->name);
+ ev->caps = edev->caps;
+
+ ecore_event_add(E_INPUT_EVENT_INPUT_DEVICE_DEL,
+ ev,
+ _e_input_event_input_device_del_free,
+ NULL);
+
+ if (input->dev->window != -1)
+ _e_input_device_remove(input->dev->window, edev);
+
+ /* remove this evdev from the seat's list of devices */
+ edev->seat->devices = eina_list_remove(edev->seat->devices, edev);
+
+ if (input->dev->fd_hash)
+ eina_hash_del_by_key(input->dev->fd_hash, edev->path);
+
+ /* tell launcher to release device */
+ if (edev->fd >= 0)
+ _device_close(edev->path, edev->fd);
+
+ /* destroy this evdev */
+ _e_input_evdev_device_destroy(edev);
+}
+
+static int
+_udev_event_process(struct libinput_event *event)
+{
+ struct libinput *libinput;
+ struct libinput_device *device;
+ E_Input_Backend *input;
+ Eina_Bool ret = EINA_TRUE;
+
+ libinput = libinput_event_get_context(event);
+ input = libinput_get_user_data(libinput);
+ device = libinput_event_get_device(event);
+
+ switch (libinput_event_get_type(event))
+ {
+ case LIBINPUT_EVENT_DEVICE_ADDED:
+ _device_added(input, device);
+ break;
+ case LIBINPUT_EVENT_DEVICE_REMOVED:
+ _device_removed(input, device);
+ break;
+ default:
+ ret = EINA_FALSE;
+ }
+
+ return ret;
+}
+
+static void
+_input_event_process(struct libinput_event *event)
+{
+ if (_udev_event_process(event)) return;
+ if (_e_input_evdev_event_process(event)) return;
+}
+
+void
+_input_events_process(E_Input_Backend *input)
+{
+ struct libinput_event *event;
+
+ while ((event = libinput_get_event(input->libinput)))
+ {
+ _input_event_process(event);
+ libinput_event_destroy(event);
+ }
+}
+
+static Eina_Bool
+_cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
+{
+ E_Input_Backend *input;
+
+ if (!(input = data)) return EINA_TRUE;
+
+ if (libinput_dispatch(input->libinput) != 0)
+ ERR("Failed to dispatch libinput events: %m");
+
+ /* process pending events */
+ _input_events_process(input);
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_input_enable_input(E_Input_Backend *input)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(input, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(input->libinput, EINA_FALSE);
+
+ input->fd = libinput_get_fd(input->libinput);
+
+ if (!input->hdlr)
+ {
+ input->hdlr =
+ ecore_main_fd_handler_add(input->fd, ECORE_FD_READ,
+ _cb_input_dispatch, input, NULL, NULL);
+ }
+
+ if (input->suspended)
+ {
+ if (libinput_resume(input->libinput) != 0)
+ goto err;
+
+ input->suspended = EINA_FALSE;
+
+ /* process pending events */
+ _input_events_process(input);
+ }
+
+ input->enabled = EINA_TRUE;
+ input->suspended = EINA_FALSE;
+
+ return EINA_TRUE;
+
+err:
+ input->enabled = EINA_FALSE;
+ if (input->hdlr)
+ ecore_main_fd_handler_del(input->hdlr);
+ input->hdlr = NULL;
+
+ return EINA_FALSE;
+}
+
+EINTERN void
+e_input_disable_input(E_Input_Backend *input)
+{
+ EINA_SAFETY_ON_NULL_RETURN(input);
+ EINA_SAFETY_ON_TRUE_RETURN(input->suspended);
+
+ /* suspend this input */
+ libinput_suspend(input->libinput);
+
+ /* process pending events */
+ _input_events_process(input);
+
+ input->suspended = EINA_TRUE;
+}
+
+E_API Eina_List *
+e_input_seat_evdev_list_get(E_Input_Seat *seat)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
+ return seat->devices;
+}
--- /dev/null
+#ifdef E_TYPEDEFS
+
+#else
+
+#ifndef E_INPUT_PRIVIATES_H
+#define E_INPUT_PRIVIATES_H
+
+#include "e.h"
+#include "e_input.h"
+#include <libinput.h>
+#include <Eeze.h>
+
+struct xkb_keymap *cached_keymap;
+struct xkb_context *cached_context;
+
+#define E_INPUT_ENV_LIBINPUT_LOG_DISABLE "E_INPUT_LIBINPUT_LOG_DISABLE"
+#define E_INPUT_ENV_LIBINPUT_LOG_EINA_LOG "E_INPUT_LIBINPUT_LOG_EINA_LOG"
+
+struct _E_Input_Seat
+{
+ const char *name;
+ E_Input_Backend *input;
+ Eina_List *devices;
+ struct libinput_seat *seat;
+
+ struct
+ {
+ int ix, iy;
+ double dx, dy;
+ Eina_Bool swap;
+ Eina_Bool invert_x;
+ Eina_Bool invert_y;
+ } ptr;
+};
+
+struct _E_Input_Backend
+{
+ int fd;
+ E_Input_Device *dev;
+ struct libinput *libinput;
+
+ Ecore_Fd_Handler *hdlr;
+
+ Eina_Bool enabled : 1;
+ Eina_Bool suspended : 1;
+ Eina_Bool left_handed : 1;
+};
+
+struct _E_Input_Evdev
+{
+ E_Input_Seat *seat;
+ struct libinput_device *device;
+
+ const char *path;
+ int fd;
+
+ int mt_slot;
+
+ struct
+ {
+ int minx, miny, maxw, maxh;
+ double dx, dy;
+ unsigned int last, prev;
+ uint32_t threshold;
+ Eina_Bool did_double : 1;
+ Eina_Bool did_triple : 1;
+ uint32_t prev_button, last_button;
+ } mouse;
+
+ struct
+ {
+ struct xkb_keymap *keymap;
+ struct xkb_state *state;
+ xkb_mod_mask_t ctrl_mask;
+ xkb_mod_mask_t alt_mask;
+ xkb_mod_mask_t shift_mask;
+ xkb_mod_mask_t win_mask;
+ xkb_mod_mask_t scroll_mask;
+ xkb_mod_mask_t num_mask;
+ xkb_mod_mask_t caps_mask;
+ xkb_mod_mask_t altgr_mask;
+ unsigned int modifiers;
+ unsigned int depressed, latched, locked, group;
+ } xkb;
+
+ Eina_Hash *key_remap_hash;
+ Eina_Bool key_remap_enabled;
+
+ E_Input_Seat_Capabilities caps;
+
+ struct
+ {
+ struct
+ {
+ int rotation;
+ int x, y;
+ int w, h;
+ } transform;
+ } touch;
+};
+
+void _input_events_process(E_Input_Backend *input);
+E_Input_Evdev *_e_input_evdev_device_create(E_Input_Seat *seat, struct libinput_device *device);
+Eina_Bool _e_input_evdev_event_process(struct libinput_event *event);
+
+struct xkb_context * _e_input_device_cached_context_get(enum xkb_context_flags flags);
+struct xkb_keymap *_e_input_device_cached_keymap_get(struct xkb_context *ctx, const struct xkb_rule_names *names, enum xkb_keymap_compile_flags flags);
+
+
+void _e_input_evdev_device_destroy(E_Input_Evdev *evdev);
+void _e_input_pointer_motion_post(E_Input_Evdev *edev);
+
+#endif
+#endif