ecore-drm: Merge port to libinput
Merge branch 'devs/devilhorns/libinput' Summary: These commits port the current ecore_drm input code to use libinput for handling of devices, input events, etc @feature
This commit is contained in:
commit
b2aa9eff9c
|
@ -3078,6 +3078,7 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eo])
|
||||||
EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eina])
|
EFL_INTERNAL_DEPEND_PKG([ECORE_DRM], [eina])
|
||||||
|
|
||||||
EFL_DEPEND_PKG([ECORE_DRM], [DRM], [libdrm >= 2.4 xkbcommon >= 0.3.0 gbm])
|
EFL_DEPEND_PKG([ECORE_DRM], [DRM], [libdrm >= 2.4 xkbcommon >= 0.3.0 gbm])
|
||||||
|
EFL_DEPEND_PKG([ECORE_DRM], [LIBINPUT], [libinput >= 0.6.0])
|
||||||
|
|
||||||
EFL_EVAL_PKGS([ECORE_DRM])
|
EFL_EVAL_PKGS([ECORE_DRM])
|
||||||
|
|
||||||
|
|
|
@ -2,22 +2,70 @@
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* copied from udev/extras/input_id/input_id.c */
|
|
||||||
/* we must use this kernel-compatible implementation */
|
|
||||||
#define BITS_PER_LONG (sizeof(unsigned long) * 8)
|
|
||||||
#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
|
|
||||||
#define OFF(x) ((x)%BITS_PER_LONG)
|
|
||||||
#define BIT(x) (1UL<<OFF(x))
|
|
||||||
#define LONG(x) ((x)/BITS_PER_LONG)
|
|
||||||
#define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1)
|
|
||||||
/* end copied */
|
|
||||||
|
|
||||||
#include "ecore_drm_private.h"
|
#include "ecore_drm_private.h"
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <linux/input.h>
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
/* local functions */
|
static void
|
||||||
|
_device_calibration_set(Ecore_Drm_Evdev *edev)
|
||||||
|
{
|
||||||
|
const char *sysname;
|
||||||
|
int w = 0, h = 0;
|
||||||
|
float cal[6];
|
||||||
|
const char *device;
|
||||||
|
Eina_List *devices;
|
||||||
|
const char *vals;
|
||||||
|
enum libinput_config_status status;
|
||||||
|
|
||||||
|
ecore_drm_output_size_get(edev->seat->input->dev,
|
||||||
|
edev->seat->input->dev->window, &w, &h);
|
||||||
|
if ((w == 0) || (h == 0)) return;
|
||||||
|
|
||||||
|
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(Ecore_Drm_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
|
static void
|
||||||
_device_keyboard_setup(Ecore_Drm_Evdev *edev)
|
_device_keyboard_setup(Ecore_Drm_Evdev *edev)
|
||||||
{
|
{
|
||||||
|
@ -60,169 +108,6 @@ _device_keyboard_setup(Ecore_Drm_Evdev *edev)
|
||||||
1 << xkb_map_mod_get_index(edev->xkb.keymap, "ISO_Level3_Shift");
|
1 << xkb_map_mod_get_index(edev->xkb.keymap, "ISO_Level3_Shift");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
|
||||||
_device_configure(Ecore_Drm_Evdev *edev)
|
|
||||||
{
|
|
||||||
Eina_Bool ret = EINA_FALSE;
|
|
||||||
|
|
||||||
if (!edev) return EINA_FALSE;
|
|
||||||
|
|
||||||
if ((edev->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) &&
|
|
||||||
(edev->caps & EVDEV_BUTTON))
|
|
||||||
{
|
|
||||||
DBG("\tInput device %s is a pointer", edev->name);
|
|
||||||
edev->seat_caps |= EVDEV_SEAT_POINTER;
|
|
||||||
|
|
||||||
/* FIXME: make this configurable */
|
|
||||||
edev->mouse.threshold = 0.25;
|
|
||||||
|
|
||||||
ret = EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edev->caps & EVDEV_KEYBOARD)
|
|
||||||
{
|
|
||||||
DBG("\tInput device %s is a keyboard", edev->name);
|
|
||||||
edev->seat_caps |= EVDEV_SEAT_KEYBOARD;
|
|
||||||
_device_keyboard_setup(edev);
|
|
||||||
ret = EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (edev->caps & EVDEV_TOUCH)
|
|
||||||
{
|
|
||||||
DBG("\tInput device %s is a touchpad", edev->name);
|
|
||||||
edev->seat_caps |= EVDEV_SEAT_TOUCH;
|
|
||||||
ret = EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_device_axis_update(Ecore_Drm_Evdev *dev)
|
|
||||||
{
|
|
||||||
if (!dev) return;
|
|
||||||
|
|
||||||
if ((dev->abs.rel_w < 0) || (dev->abs.rel_h < 0))
|
|
||||||
{
|
|
||||||
int w = 0, h = 0;
|
|
||||||
|
|
||||||
ecore_drm_output_size_get(dev->seat->input->dev,
|
|
||||||
dev->seat->input->dev->window, &w, &h);
|
|
||||||
if ((w) && (h))
|
|
||||||
ecore_drm_inputs_device_axis_size_set(dev, w, h);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Eina_Bool
|
|
||||||
_device_handle(Ecore_Drm_Evdev *edev)
|
|
||||||
{
|
|
||||||
struct input_absinfo absinfo;
|
|
||||||
unsigned long dev_bits[NBITS(EV_MAX)];
|
|
||||||
unsigned long abs_bits[NBITS(ABS_MAX)];
|
|
||||||
unsigned long rel_bits[NBITS(REL_MAX)];
|
|
||||||
unsigned long key_bits[NBITS(KEY_MAX)];
|
|
||||||
/* Eina_Bool have_key = EINA_FALSE; */
|
|
||||||
Eina_Bool have_abs = EINA_FALSE;
|
|
||||||
|
|
||||||
if (!edev) return EINA_FALSE;
|
|
||||||
|
|
||||||
ioctl(edev->fd, EVIOCGBIT(0, sizeof(dev_bits)), dev_bits);
|
|
||||||
if (TEST_BIT(dev_bits, EV_ABS))
|
|
||||||
{
|
|
||||||
have_abs = EINA_TRUE;
|
|
||||||
|
|
||||||
ioctl(edev->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
|
|
||||||
|
|
||||||
if ((TEST_BIT(abs_bits, ABS_WHEEL)) ||
|
|
||||||
(TEST_BIT(abs_bits, ABS_GAS)) ||
|
|
||||||
(TEST_BIT(abs_bits, ABS_BRAKE)) ||
|
|
||||||
(TEST_BIT(abs_bits, ABS_HAT0X)))
|
|
||||||
{
|
|
||||||
/* ignore joystick */
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_BIT(abs_bits, ABS_X))
|
|
||||||
{
|
|
||||||
ioctl(edev->fd, EVIOCGABS(ABS_X), &absinfo);
|
|
||||||
edev->abs.min_x = absinfo.minimum;
|
|
||||||
edev->abs.max_x = absinfo.maximum;
|
|
||||||
edev->abs.rel_w = -1;
|
|
||||||
edev->mouse.x = -1;
|
|
||||||
edev->caps |= EVDEV_MOTION_ABS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_BIT(abs_bits, ABS_Y))
|
|
||||||
{
|
|
||||||
ioctl(edev->fd, EVIOCGABS(ABS_Y), &absinfo);
|
|
||||||
edev->abs.min_y = absinfo.minimum;
|
|
||||||
edev->abs.max_y = absinfo.maximum;
|
|
||||||
edev->abs.rel_h = -1;
|
|
||||||
edev->mouse.y = -1;
|
|
||||||
edev->caps |= EVDEV_MOTION_ABS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((TEST_BIT(abs_bits, ABS_MT_POSITION_X)) &&
|
|
||||||
(TEST_BIT(abs_bits, ABS_MT_POSITION_Y)))
|
|
||||||
{
|
|
||||||
DBG("Handle MultiTouch Device: %s", edev->path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_BIT(dev_bits, EV_REL))
|
|
||||||
{
|
|
||||||
ioctl(edev->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), rel_bits);
|
|
||||||
|
|
||||||
if ((TEST_BIT(rel_bits, REL_X)) || (TEST_BIT(rel_bits, REL_Y)))
|
|
||||||
edev->caps |= EVDEV_MOTION_REL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_BIT(dev_bits, EV_KEY))
|
|
||||||
{
|
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
/* have_key = EINA_TRUE; */
|
|
||||||
|
|
||||||
ioctl(edev->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits);
|
|
||||||
|
|
||||||
if (have_abs)
|
|
||||||
{
|
|
||||||
if ((TEST_BIT(key_bits, BTN_TOOL_FINGER)) &&
|
|
||||||
(!TEST_BIT(key_bits, BTN_TOOL_PEN)))
|
|
||||||
{
|
|
||||||
DBG("Device Is Touchpad: %s", edev->path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = KEY_ESC; i < KEY_MAX; i++)
|
|
||||||
{
|
|
||||||
if ((i >= BTN_MISC) && (i < KEY_OK)) continue;
|
|
||||||
if (TEST_BIT(key_bits, i))
|
|
||||||
{
|
|
||||||
edev->caps |= EVDEV_KEYBOARD;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_BIT(key_bits, BTN_TOUCH))
|
|
||||||
edev->caps |= EVDEV_TOUCH;
|
|
||||||
|
|
||||||
for (i = BTN_MISC; i < BTN_JOYSTICK; i++)
|
|
||||||
{
|
|
||||||
if (TEST_BIT(key_bits, i))
|
|
||||||
{
|
|
||||||
edev->caps |= EVDEV_BUTTON;
|
|
||||||
edev->caps &= ~EVDEV_TOUCH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TEST_BIT(dev_bits, EV_LED)) edev->caps |= EVDEV_KEYBOARD;
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_device_keysym_translate(xkb_keysym_t keysym, unsigned int modifiers, char *buffer, int bytes)
|
_device_keysym_translate(xkb_keysym_t keysym, unsigned int modifiers, char *buffer, int bytes)
|
||||||
{
|
{
|
||||||
|
@ -304,28 +189,32 @@ _device_modifiers_update(Ecore_Drm_Evdev *edev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_device_notify_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp)
|
_device_handle_key(struct libinput_device *device, struct libinput_event_keyboard *event)
|
||||||
{
|
{
|
||||||
unsigned int code, nsyms;
|
Ecore_Drm_Evdev *edev;
|
||||||
/* unsigned int *keycode; */
|
Ecore_Drm_Input *input;
|
||||||
|
uint32_t timestamp;
|
||||||
|
uint32_t code, nsyms;
|
||||||
const xkb_keysym_t *syms;
|
const xkb_keysym_t *syms;
|
||||||
|
enum libinput_key_state state;
|
||||||
xkb_keysym_t sym = XKB_KEY_NoSymbol;
|
xkb_keysym_t sym = XKB_KEY_NoSymbol;
|
||||||
char key[256], keyname[256], compose_buffer[256];
|
char key[256], keyname[256], compose_buffer[256];
|
||||||
Ecore_Event_Key *e;
|
Ecore_Event_Key *e;
|
||||||
Ecore_Drm_Input *input;
|
char *tmp = NULL, *compose = NULL;
|
||||||
char *tmp = NULL;
|
|
||||||
char *compose = NULL;
|
|
||||||
|
|
||||||
if (!(input = dev->seat->input)) return;
|
if (!(edev = libinput_device_get_user_data(device))) return;
|
||||||
|
|
||||||
/* xkb rules reflect X broken keycodes, so offset by 8 */
|
if (!(input = edev->seat->input)) return;
|
||||||
code = event->code + 8;
|
|
||||||
|
|
||||||
xkb_state_update_key(dev->xkb.state, code,
|
timestamp = libinput_event_keyboard_get_time(event);
|
||||||
(event->value ? XKB_KEY_DOWN : XKB_KEY_UP));
|
code = libinput_event_keyboard_get_key(event) + 8;
|
||||||
|
state = libinput_event_keyboard_get_key_state(event);
|
||||||
|
|
||||||
|
xkb_state_update_key(edev->xkb.state, code,
|
||||||
|
(state ? XKB_KEY_DOWN : XKB_KEY_UP));
|
||||||
|
|
||||||
/* get the keysym for this code */
|
/* get the keysym for this code */
|
||||||
nsyms = xkb_key_get_syms(dev->xkb.state, code, &syms);
|
nsyms = xkb_key_get_syms(edev->xkb.state, code, &syms);
|
||||||
if (nsyms == 1) sym = syms[0];
|
if (nsyms == 1) sym = syms[0];
|
||||||
|
|
||||||
/* get the keyname for this sym */
|
/* get the keyname for this sym */
|
||||||
|
@ -339,8 +228,8 @@ _device_notify_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int
|
||||||
snprintf(keyname, sizeof(keyname), "Keycode-%u", code);
|
snprintf(keyname, sizeof(keyname), "Keycode-%u", code);
|
||||||
|
|
||||||
/* if shift is active, we need to transform the key to lower */
|
/* if shift is active, we need to transform the key to lower */
|
||||||
if (xkb_state_mod_index_is_active(dev->xkb.state,
|
if (xkb_state_mod_index_is_active(edev->xkb.state,
|
||||||
xkb_map_mod_get_index(dev->xkb.keymap,
|
xkb_map_mod_get_index(edev->xkb.keymap,
|
||||||
XKB_MOD_NAME_SHIFT),
|
XKB_MOD_NAME_SHIFT),
|
||||||
XKB_STATE_MODS_EFFECTIVE))
|
XKB_STATE_MODS_EFFECTIVE))
|
||||||
{
|
{
|
||||||
|
@ -349,23 +238,20 @@ _device_notify_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(compose_buffer, 0, sizeof(compose_buffer));
|
memset(compose_buffer, 0, sizeof(compose_buffer));
|
||||||
if (_device_keysym_translate(sym, dev->xkb.modifiers, compose_buffer, 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 = eina_str_convert("ISO8859-1", "UTF-8", compose_buffer);
|
||||||
compose_buffer);
|
|
||||||
if (!compose)
|
if (!compose)
|
||||||
{
|
{
|
||||||
ERR("Ecore_DRM cannot convert input key string '%s' to UTF-8. "
|
ERR("Ecore_DRM cannot convert input key string '%s' to UTF-8. "
|
||||||
"Is Eina built with iconv support?", compose_buffer);
|
"Is Eina built with iconv support?", compose_buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
|
||||||
tmp = compose;
|
tmp = compose;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!compose)
|
if (!compose) compose = compose_buffer;
|
||||||
compose = compose_buffer;
|
|
||||||
|
|
||||||
e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) +
|
e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) +
|
||||||
((compose[0] != '\0') ? strlen(compose) : 0) + 3);
|
((compose[0] != '\0') ? strlen(compose) : 0) + 3);
|
||||||
|
@ -388,44 +274,45 @@ _device_notify_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int
|
||||||
e->keycode = code;
|
e->keycode = code;
|
||||||
e->data = NULL;
|
e->data = NULL;
|
||||||
|
|
||||||
_device_modifiers_update(dev);
|
_device_modifiers_update(edev);
|
||||||
e->modifiers = dev->xkb.modifiers;
|
|
||||||
|
|
||||||
if (event->value)
|
e->modifiers = edev->xkb.modifiers;
|
||||||
|
|
||||||
|
if (state)
|
||||||
ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
|
ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
|
||||||
else
|
else
|
||||||
ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
|
ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
|
||||||
|
|
||||||
if (tmp)
|
if (tmp) free(tmp);
|
||||||
free(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_device_notify_motion(Ecore_Drm_Evdev *dev, unsigned int timestamp)
|
_device_pointer_motion(Ecore_Drm_Evdev *edev, struct libinput_event_pointer *event)
|
||||||
{
|
{
|
||||||
Ecore_Drm_Input *input;
|
Ecore_Drm_Input *input;
|
||||||
Ecore_Event_Mouse_Move *ev;
|
Ecore_Event_Mouse_Move *ev;
|
||||||
|
|
||||||
if (!(input = dev->seat->input)) return;
|
if (!(input = edev->seat->input)) return;
|
||||||
|
|
||||||
if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)))) return;
|
if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Move)))) return;
|
||||||
|
|
||||||
ev->window = (Ecore_Window)input->dev->window;
|
ev->window = (Ecore_Window)input->dev->window;
|
||||||
ev->event_window = (Ecore_Window)input->dev->window;
|
ev->event_window = (Ecore_Window)input->dev->window;
|
||||||
ev->root_window = (Ecore_Window)input->dev->window;
|
ev->root_window = (Ecore_Window)input->dev->window;
|
||||||
ev->timestamp = timestamp;
|
ev->timestamp = libinput_event_pointer_get_time(event);
|
||||||
ev->same_screen = 1;
|
ev->same_screen = 1;
|
||||||
|
|
||||||
/* NB: Commented out. This borks mouse movement if no key has been
|
/* NB: Commented out. This borks mouse movement if no key has been
|
||||||
* pressed yet due to 'state' not being set */
|
* pressed yet due to 'state' not being set */
|
||||||
// _device_modifiers_update(dev);
|
// _device_modifiers_update(dev);
|
||||||
ev->modifiers = dev->xkb.modifiers;
|
ev->modifiers = edev->xkb.modifiers;
|
||||||
|
|
||||||
ev->x = dev->mouse.x;
|
ev->x = edev->mouse.x;
|
||||||
ev->y = dev->mouse.y;
|
ev->y = edev->mouse.y;
|
||||||
ev->root.x = ev->x;
|
ev->root.x = ev->x;
|
||||||
ev->root.y = ev->y;
|
ev->root.y = ev->y;
|
||||||
|
|
||||||
ev->multi.device = dev->mt_slot;
|
ev->multi.device = edev->mt_slot;
|
||||||
ev->multi.radius = 1;
|
ev->multi.radius = 1;
|
||||||
ev->multi.radius_x = 1;
|
ev->multi.radius_x = 1;
|
||||||
ev->multi.radius_y = 1;
|
ev->multi.radius_y = 1;
|
||||||
|
@ -440,45 +327,54 @@ _device_notify_motion(Ecore_Drm_Evdev *dev, unsigned int timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_device_notify_wheel(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp)
|
_device_handle_pointer_motion(struct libinput_device *device, struct libinput_event_pointer *event)
|
||||||
{
|
{
|
||||||
Ecore_Drm_Input *input;
|
Ecore_Drm_Evdev *edev;
|
||||||
Ecore_Event_Mouse_Wheel *ev;
|
|
||||||
|
|
||||||
if (!(input = dev->seat->input)) return;
|
if (!(edev = libinput_device_get_user_data(device))) return;
|
||||||
if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Wheel)))) return;
|
|
||||||
|
|
||||||
ev->window = (Ecore_Window)input->dev->window;
|
edev->mouse.x += libinput_event_pointer_get_dx(event);
|
||||||
ev->event_window = (Ecore_Window)input->dev->window;
|
edev->mouse.y += libinput_event_pointer_get_dy(event);
|
||||||
ev->root_window = (Ecore_Window)input->dev->window;
|
|
||||||
ev->timestamp = timestamp;
|
|
||||||
ev->same_screen = 1;
|
|
||||||
|
|
||||||
/* NB: Commented out. This borks mouse wheel if no key has been
|
_device_pointer_motion(edev, event);
|
||||||
* pressed yet due to 'state' not being set */
|
|
||||||
// _device_modifiers_update(dev);
|
|
||||||
ev->modifiers = dev->xkb.modifiers;
|
|
||||||
|
|
||||||
ev->x = dev->mouse.x;
|
|
||||||
ev->y = dev->mouse.y;
|
|
||||||
ev->root.x = ev->x;
|
|
||||||
ev->root.y = ev->y;
|
|
||||||
if (event->value == REL_HWHEEL) ev->direction = 1;
|
|
||||||
ev->z = -event->value;
|
|
||||||
|
|
||||||
ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_device_notify_button(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp)
|
_device_handle_pointer_motion_absolute(struct libinput_device *device, struct libinput_event_pointer *event)
|
||||||
{
|
{
|
||||||
|
Ecore_Drm_Evdev *edev;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
if (!(edev = libinput_device_get_user_data(device))) return;
|
||||||
|
|
||||||
|
edev->mouse.x = libinput_event_pointer_get_absolute_x(event);
|
||||||
|
edev->mouse.y = libinput_event_pointer_get_absolute_y(event);
|
||||||
|
|
||||||
|
_device_pointer_motion(edev, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_device_handle_button(struct libinput_device *device, struct libinput_event_pointer *event)
|
||||||
|
{
|
||||||
|
Ecore_Drm_Evdev *edev;
|
||||||
Ecore_Drm_Input *input;
|
Ecore_Drm_Input *input;
|
||||||
Ecore_Event_Mouse_Button *ev;
|
Ecore_Event_Mouse_Button *ev;
|
||||||
int button;
|
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 (!(input = dev->seat->input)) return;
|
|
||||||
if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Button)))) 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->window = (Ecore_Window)input->dev->window;
|
||||||
ev->event_window = (Ecore_Window)input->dev->window;
|
ev->event_window = (Ecore_Window)input->dev->window;
|
||||||
ev->root_window = (Ecore_Window)input->dev->window;
|
ev->root_window = (Ecore_Window)input->dev->window;
|
||||||
|
@ -488,14 +384,14 @@ _device_notify_button(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned
|
||||||
/* NB: Commented out. This borks mouse button if no key has been
|
/* NB: Commented out. This borks mouse button if no key has been
|
||||||
* pressed yet due to 'state' not being set */
|
* pressed yet due to 'state' not being set */
|
||||||
// _device_modifiers_update(dev);
|
// _device_modifiers_update(dev);
|
||||||
ev->modifiers = dev->xkb.modifiers;
|
ev->modifiers = edev->xkb.modifiers;
|
||||||
|
|
||||||
ev->x = dev->mouse.x;
|
ev->x = edev->mouse.x;
|
||||||
ev->y = dev->mouse.y;
|
ev->y = edev->mouse.y;
|
||||||
ev->root.x = ev->x;
|
ev->root.x = ev->x;
|
||||||
ev->root.y = ev->y;
|
ev->root.y = ev->y;
|
||||||
|
|
||||||
ev->multi.device = dev->mt_slot;
|
ev->multi.device = edev->mt_slot;
|
||||||
ev->multi.radius = 1;
|
ev->multi.radius = 1;
|
||||||
ev->multi.radius_x = 1;
|
ev->multi.radius_x = 1;
|
||||||
ev->multi.radius_y = 1;
|
ev->multi.radius_y = 1;
|
||||||
|
@ -506,323 +402,188 @@ _device_notify_button(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned
|
||||||
ev->multi.root.x = ev->x;
|
ev->multi.root.x = ev->x;
|
||||||
ev->multi.root.y = ev->y;
|
ev->multi.root.y = ev->y;
|
||||||
|
|
||||||
button = ((event->code & 0x00F) + 1);
|
if (state)
|
||||||
|
|
||||||
/* swap buttons 2 & 3 so behaviour is like X */
|
|
||||||
if (button == 3) button = 2;
|
|
||||||
else if (button == 2) button = 3;
|
|
||||||
|
|
||||||
if (event->value)
|
|
||||||
{
|
{
|
||||||
unsigned int current;
|
unsigned int current;
|
||||||
|
|
||||||
current = timestamp;
|
current = timestamp;
|
||||||
dev->mouse.did_double = EINA_FALSE;
|
edev->mouse.did_double = EINA_FALSE;
|
||||||
dev->mouse.did_triple = EINA_FALSE;
|
edev->mouse.did_triple = EINA_FALSE;
|
||||||
|
|
||||||
if (((current - dev->mouse.prev) <= dev->mouse.threshold) &&
|
if (((current - edev->mouse.prev) <= edev->mouse.threshold) &&
|
||||||
(button == dev->mouse.prev_button))
|
(button == edev->mouse.prev_button))
|
||||||
{
|
{
|
||||||
dev->mouse.did_double = EINA_TRUE;
|
edev->mouse.did_double = EINA_TRUE;
|
||||||
if (((current - dev->mouse.last) <= (2 * dev->mouse.threshold)) &&
|
if (((current - edev->mouse.last) <= (2 * edev->mouse.threshold)) &&
|
||||||
(button == dev->mouse.last_button))
|
(button == edev->mouse.last_button))
|
||||||
{
|
{
|
||||||
dev->mouse.did_triple = EINA_TRUE;
|
edev->mouse.did_triple = EINA_TRUE;
|
||||||
dev->mouse.prev = 0;
|
edev->mouse.prev = 0;
|
||||||
dev->mouse.last = 0;
|
edev->mouse.last = 0;
|
||||||
current = 0;
|
current = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->mouse.last = dev->mouse.prev;
|
edev->mouse.last = edev->mouse.prev;
|
||||||
dev->mouse.prev = current;
|
edev->mouse.prev = current;
|
||||||
dev->mouse.last_button = dev->mouse.prev_button;
|
edev->mouse.last_button = edev->mouse.prev_button;
|
||||||
dev->mouse.prev_button = button;
|
edev->mouse.prev_button = button;
|
||||||
}
|
}
|
||||||
|
|
||||||
ev->buttons = button;
|
ev->buttons = button;
|
||||||
if (dev->mouse.did_double)
|
|
||||||
|
if (edev->mouse.did_double)
|
||||||
ev->double_click = 1;
|
ev->double_click = 1;
|
||||||
if (dev->mouse.did_triple)
|
if (edev->mouse.did_triple)
|
||||||
ev->triple_click = 1;
|
ev->triple_click = 1;
|
||||||
|
|
||||||
if (event->value)
|
if (state)
|
||||||
ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
|
ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, ev, NULL, NULL);
|
||||||
else
|
else
|
||||||
ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
|
ecore_event_add(ECORE_EVENT_MOUSE_BUTTON_UP, ev, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_device_process_flush(Ecore_Drm_Evdev *dev, unsigned int timestamp)
|
_device_handle_axis(struct libinput_device *device, struct libinput_event_pointer *event)
|
||||||
{
|
|
||||||
switch (dev->pending_event)
|
|
||||||
{
|
|
||||||
case EVDEV_NONE:
|
|
||||||
return;
|
|
||||||
case EVDEV_RELATIVE_MOTION:
|
|
||||||
_device_notify_motion(dev, timestamp);
|
|
||||||
/* dev->mouse.x = 0; */
|
|
||||||
/* dev->mouse.y = 0; */
|
|
||||||
goto out;
|
|
||||||
break;
|
|
||||||
case EVDEV_ABSOLUTE_MT_DOWN:
|
|
||||||
goto out;
|
|
||||||
break;
|
|
||||||
case EVDEV_ABSOLUTE_MT_MOTION:
|
|
||||||
goto out;
|
|
||||||
break;
|
|
||||||
case EVDEV_ABSOLUTE_MT_UP:
|
|
||||||
goto out;
|
|
||||||
break;
|
|
||||||
case EVDEV_ABSOLUTE_TOUCH_DOWN:
|
|
||||||
case EVDEV_ABSOLUTE_TOUCH_UP:
|
|
||||||
{
|
|
||||||
struct input_event event;
|
|
||||||
|
|
||||||
event.code = 0;
|
|
||||||
event.value = dev->abs.pt[dev->mt_slot].down;
|
|
||||||
|
|
||||||
dev->mouse.x = dev->abs.pt[dev->mt_slot].x[0];
|
|
||||||
dev->mouse.y = dev->abs.pt[dev->mt_slot].y[0];
|
|
||||||
|
|
||||||
_device_notify_motion(dev, timestamp);
|
|
||||||
_device_notify_button(dev, &event, timestamp);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case EVDEV_ABSOLUTE_MOTION:
|
|
||||||
dev->mouse.x = dev->abs.pt[dev->mt_slot].x[0];
|
|
||||||
dev->mouse.y = dev->abs.pt[dev->mt_slot].y[0];
|
|
||||||
|
|
||||||
_device_notify_motion(dev, timestamp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
dev->pending_event = EVDEV_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_device_process_key(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp)
|
|
||||||
{
|
|
||||||
/* ignore key repeat */
|
|
||||||
if (event->value == 2) return;
|
|
||||||
|
|
||||||
_device_process_flush(dev, timestamp);
|
|
||||||
|
|
||||||
if ((event->code >= BTN_LEFT) && (event->code <= BTN_TASK))
|
|
||||||
_device_notify_button(dev, event, timestamp);
|
|
||||||
else if ((event->code >= KEY_ESC) && (event->code <= KEY_MICMUTE))
|
|
||||||
_device_notify_key(dev, event, timestamp);
|
|
||||||
else if ((event->code == BTN_TOUCH) && (dev->caps & EVDEV_MOTION_ABS))
|
|
||||||
dev->abs.pt[dev->mt_slot].down = event->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_device_process_absolute(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp EINA_UNUSED)
|
|
||||||
{
|
|
||||||
_device_axis_update(dev);
|
|
||||||
|
|
||||||
switch (event->code)
|
|
||||||
{
|
|
||||||
case ABS_X:
|
|
||||||
if (dev->abs.pt[dev->mt_slot].down == 0)
|
|
||||||
return;
|
|
||||||
case ABS_MT_POSITION_X:
|
|
||||||
dev->abs.pt[dev->mt_slot].x[0] =
|
|
||||||
(int)((double)(event->value - dev->abs.min_x) / dev->abs.rel_w);
|
|
||||||
|
|
||||||
if (dev->pending_event != EVDEV_ABSOLUTE_TOUCH_DOWN)
|
|
||||||
if (dev->pending_event != EVDEV_ABSOLUTE_TOUCH_UP)
|
|
||||||
dev->pending_event = EVDEV_ABSOLUTE_MOTION;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ABS_Y:
|
|
||||||
if (dev->abs.pt[dev->mt_slot].down == 0)
|
|
||||||
return;
|
|
||||||
case ABS_MT_POSITION_Y:
|
|
||||||
dev->abs.pt[dev->mt_slot].y[0] =
|
|
||||||
(int)((double)(event->value - dev->abs.min_y) / dev->abs.rel_h);
|
|
||||||
|
|
||||||
if (dev->pending_event != EVDEV_ABSOLUTE_TOUCH_DOWN)
|
|
||||||
if (dev->pending_event != EVDEV_ABSOLUTE_TOUCH_UP)
|
|
||||||
dev->pending_event = EVDEV_ABSOLUTE_MOTION;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ABS_MT_SLOT:
|
|
||||||
if ((event->value >= 0) && (event->value < EVDEV_MAX_SLOTS))
|
|
||||||
dev->mt_slot = event->value;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ABS_MT_TRACKING_ID:
|
|
||||||
if (event->value < 0)
|
|
||||||
{
|
|
||||||
dev->abs.pt[dev->mt_slot].down = 0;
|
|
||||||
dev->pending_event = EVDEV_ABSOLUTE_TOUCH_UP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dev->abs.pt[dev->mt_slot].down = 1;
|
|
||||||
dev->pending_event = EVDEV_ABSOLUTE_TOUCH_DOWN;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_device_process_relative(Ecore_Drm_Evdev *dev, struct input_event *event, unsigned int timestamp)
|
|
||||||
{
|
|
||||||
switch (event->code)
|
|
||||||
{
|
|
||||||
case REL_X:
|
|
||||||
if (dev->pending_event != EVDEV_RELATIVE_MOTION)
|
|
||||||
_device_process_flush(dev, timestamp);
|
|
||||||
dev->mouse.x += event->value;
|
|
||||||
dev->pending_event = EVDEV_RELATIVE_MOTION;
|
|
||||||
break;
|
|
||||||
case REL_Y:
|
|
||||||
if (dev->pending_event != EVDEV_RELATIVE_MOTION)
|
|
||||||
_device_process_flush(dev, timestamp);
|
|
||||||
dev->mouse.y += event->value;
|
|
||||||
dev->pending_event = EVDEV_RELATIVE_MOTION;
|
|
||||||
break;
|
|
||||||
case REL_WHEEL:
|
|
||||||
case REL_HWHEEL:
|
|
||||||
_device_process_flush(dev, timestamp);
|
|
||||||
_device_notify_wheel(dev, event, timestamp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
_device_process(Ecore_Drm_Evdev *dev, struct input_event *event, int count)
|
|
||||||
{
|
|
||||||
struct input_event *ev, *end;
|
|
||||||
unsigned int timestamp = 0;
|
|
||||||
|
|
||||||
ev = event;
|
|
||||||
end = ev + count;
|
|
||||||
for (ev = event; ev < end; ev++)
|
|
||||||
{
|
|
||||||
timestamp = (ev->time.tv_sec * 1000) + (ev->time.tv_usec / 1000);
|
|
||||||
|
|
||||||
switch (ev->type)
|
|
||||||
{
|
|
||||||
case EV_KEY:
|
|
||||||
_device_process_key(dev, ev, timestamp);
|
|
||||||
break;
|
|
||||||
case EV_REL:
|
|
||||||
_device_process_relative(dev, ev, timestamp);
|
|
||||||
break;
|
|
||||||
case EV_ABS:
|
|
||||||
_device_process_absolute(dev, ev, timestamp);
|
|
||||||
break;
|
|
||||||
case EV_SYN:
|
|
||||||
_device_process_flush(dev, timestamp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Eina_Bool
|
|
||||||
_cb_device_data(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
|
|
||||||
{
|
{
|
||||||
Ecore_Drm_Evdev *edev;
|
Ecore_Drm_Evdev *edev;
|
||||||
struct input_event ev[32];
|
Ecore_Drm_Input *input;
|
||||||
int len = 0;
|
Ecore_Event_Mouse_Wheel *ev;
|
||||||
|
uint32_t timestamp;
|
||||||
|
enum libinput_pointer_axis axis;
|
||||||
|
|
||||||
if (!(edev = data)) return EINA_TRUE;
|
if (!(edev = libinput_device_get_user_data(device))) return;
|
||||||
|
if (!(input = edev->seat->input)) return;
|
||||||
|
|
||||||
do
|
if (!(ev = calloc(1, sizeof(Ecore_Event_Mouse_Wheel)))) return;
|
||||||
{
|
|
||||||
len = read(edev->fd, &ev, sizeof(ev));
|
|
||||||
|
|
||||||
if ((len < 0) || ((len % sizeof(ev[0])) != 0))
|
axis = libinput_event_pointer_get_axis(event);
|
||||||
{
|
timestamp = libinput_event_pointer_get_time(event);
|
||||||
if ((len < 0) && (errno != EAGAIN) && (errno != EINTR))
|
|
||||||
{
|
|
||||||
ERR("Device Died");
|
|
||||||
}
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
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;
|
||||||
|
|
||||||
edev->event_process(edev, ev, (len / sizeof(ev[0])));
|
/* NB: Commented out. This borks mouse wheel if no key has been
|
||||||
|
* pressed yet due to 'state' not being set */
|
||||||
|
// _device_modifiers_update(dev);
|
||||||
|
ev->modifiers = edev->xkb.modifiers;
|
||||||
|
|
||||||
} while (len > 0);
|
ev->x = edev->mouse.x;
|
||||||
|
ev->y = edev->mouse.y;
|
||||||
|
ev->root.x = ev->x;
|
||||||
|
ev->root.y = ev->y;
|
||||||
|
|
||||||
return EINA_TRUE;
|
if (axis == LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) ev->direction = 1;
|
||||||
|
ev->z = -libinput_event_pointer_get_axis_value(event);
|
||||||
|
|
||||||
|
ecore_event_add(ECORE_EVENT_MOUSE_WHEEL, ev, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* external functions */
|
|
||||||
Ecore_Drm_Evdev *
|
Ecore_Drm_Evdev *
|
||||||
_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, const char *path, int fd)
|
_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, struct libinput_device *device)
|
||||||
{
|
{
|
||||||
Ecore_Drm_Evdev *edev;
|
Ecore_Drm_Evdev *edev;
|
||||||
char name[256] = "unknown";
|
|
||||||
|
|
||||||
if (!(edev = calloc(1, sizeof(Ecore_Drm_Evdev))))
|
EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
|
||||||
return NULL;
|
|
||||||
|
/* try to allocate space for new evdev */
|
||||||
|
if (!(edev = calloc(1, sizeof(Ecore_Drm_Evdev)))) return NULL;
|
||||||
|
|
||||||
edev->seat = seat;
|
edev->seat = seat;
|
||||||
edev->path = eina_stringshare_add(path);
|
edev->device = device;
|
||||||
edev->fd = fd;
|
edev->path = eina_stringshare_add(libinput_device_get_sysname(device));
|
||||||
edev->mt_slot = 0;
|
|
||||||
|
|
||||||
if (ioctl(edev->fd, EVIOCGNAME(sizeof(name)), name) < 0)
|
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_KEYBOARD))
|
||||||
ERR("Error getting device name: %m");
|
|
||||||
|
|
||||||
name[sizeof(name) - 1] = '\0';
|
|
||||||
edev->name = eina_stringshare_add(name);
|
|
||||||
|
|
||||||
if (!_device_handle(edev))
|
|
||||||
{
|
{
|
||||||
ERR("Unhandled Input Device: %s", name);
|
edev->seat_caps |= EVDEV_SEAT_KEYBOARD;
|
||||||
_ecore_drm_evdev_device_destroy(edev);
|
_device_keyboard_setup(edev);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_device_configure(edev))
|
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER))
|
||||||
{
|
{
|
||||||
ERR("\tCould not configure input device: %s", name);
|
edev->seat_caps |= EVDEV_SEAT_POINTER;
|
||||||
_ecore_drm_evdev_device_destroy(edev);
|
|
||||||
return NULL;
|
/* TODO: make this configurable */
|
||||||
|
edev->mouse.threshold = 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
edev->event_process = _device_process;
|
if (libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TOUCH))
|
||||||
|
|
||||||
edev->hdlr =
|
|
||||||
ecore_main_fd_handler_add(edev->fd, ECORE_FD_READ,
|
|
||||||
_cb_device_data, edev, NULL, NULL);
|
|
||||||
if (!edev->hdlr)
|
|
||||||
{
|
{
|
||||||
ERR("\tCould not create fd handler");
|
edev->seat_caps |= EVDEV_SEAT_TOUCH;
|
||||||
_ecore_drm_evdev_device_destroy(edev);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libinput_device_set_user_data(device, edev);
|
||||||
|
libinput_device_ref(device);
|
||||||
|
|
||||||
|
/* configure device */
|
||||||
|
_device_configure(edev);
|
||||||
|
|
||||||
return edev;
|
return edev;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *dev)
|
_ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *edev)
|
||||||
{
|
{
|
||||||
if (!dev) return;
|
EINA_SAFETY_ON_NULL_RETURN(edev);
|
||||||
|
|
||||||
if (dev->xkb.state) xkb_state_unref(dev->xkb.state);
|
if (edev->seat_caps & EVDEV_SEAT_KEYBOARD)
|
||||||
if (dev->xkb.keymap) xkb_map_unref(dev->xkb.keymap);
|
{
|
||||||
|
if (edev->xkb.state) xkb_state_unref(edev->xkb.state);
|
||||||
|
if (edev->xkb.keymap) xkb_map_unref(edev->xkb.keymap);
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->path) eina_stringshare_del(dev->path);
|
if (edev->path) eina_stringshare_del(edev->path);
|
||||||
if (dev->name) eina_stringshare_del(dev->name);
|
if (edev->device) libinput_device_unref(edev->device);
|
||||||
if (dev->hdlr) ecore_main_fd_handler_del(dev->hdlr);
|
|
||||||
|
|
||||||
close(dev->fd);
|
free(edev);
|
||||||
|
|
||||||
free(dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
_ecore_drm_evdev_event_process(struct libinput_event *event)
|
||||||
|
{
|
||||||
|
struct libinput_device *device;
|
||||||
|
Eina_Bool ret = EINA_TRUE;
|
||||||
|
|
||||||
|
/* TODO: Finish Touch Events */
|
||||||
|
|
||||||
|
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:
|
||||||
|
break;
|
||||||
|
case LIBINPUT_EVENT_TOUCH_MOTION:
|
||||||
|
break;
|
||||||
|
case LIBINPUT_EVENT_TOUCH_UP:
|
||||||
|
break;
|
||||||
|
case LIBINPUT_EVENT_TOUCH_FRAME:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = EINA_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set the axis size of the given device.
|
* @brief Set the axis size of the given device.
|
||||||
|
@ -837,30 +598,45 @@ _ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *dev)
|
||||||
* not, unsupported device.
|
* not, unsupported device.
|
||||||
*/
|
*/
|
||||||
EAPI void
|
EAPI void
|
||||||
ecore_drm_inputs_device_axis_size_set(Ecore_Drm_Evdev *dev, int w, int h)
|
ecore_drm_inputs_device_axis_size_set(Ecore_Drm_Evdev *edev, int w, int h)
|
||||||
{
|
{
|
||||||
if (!dev) return;
|
const char *sysname;
|
||||||
if ((w < 0) || (h < 0)) return;
|
float cal[6];
|
||||||
|
const char *device;
|
||||||
|
Eina_List *devices;
|
||||||
|
const char *vals;
|
||||||
|
enum libinput_config_status status;
|
||||||
|
|
||||||
if (dev->caps & EVDEV_MOTION_ABS)
|
if ((w == 0) || (h == 0)) return;
|
||||||
{
|
|
||||||
/* FIXME looks like some kernels dont include this struct */
|
|
||||||
struct input_absinfo abs_features;
|
|
||||||
|
|
||||||
ioctl(dev->fd, EVIOCGABS(ABS_X), &abs_features);
|
if ((!libinput_device_config_calibration_has_matrix(edev->device)) ||
|
||||||
dev->abs.rel_w =
|
(libinput_device_config_calibration_get_default_matrix(edev->device, cal) != 0))
|
||||||
(double)(abs_features.maximum - abs_features.minimum)/(double)(w);
|
|
||||||
dev->abs.min_x = abs_features.minimum;
|
|
||||||
|
|
||||||
ioctl(dev->fd, EVIOCGABS(ABS_Y), &abs_features);
|
|
||||||
dev->abs.rel_h =
|
|
||||||
(double)(abs_features.maximum - abs_features.minimum)/(double)(h);
|
|
||||||
dev->abs.min_y = abs_features.minimum;
|
|
||||||
}
|
|
||||||
else if (!(dev->caps & EVDEV_MOTION_REL))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* update the local values */
|
sysname = libinput_device_get_sysname(edev->device);
|
||||||
if (dev->mouse.x > w - 1) dev->mouse.x = w - 1;
|
|
||||||
if (dev->mouse.y > h - 1) dev->mouse.y = h - 1;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,95 +4,77 @@
|
||||||
|
|
||||||
#include "ecore_drm_private.h"
|
#include "ecore_drm_private.h"
|
||||||
|
|
||||||
typedef struct _Ecore_Drm_Device_Open_Data Ecore_Drm_Device_Open_Data;
|
|
||||||
struct _Ecore_Drm_Device_Open_Data
|
|
||||||
{
|
|
||||||
Ecore_Drm_Seat *seat;
|
|
||||||
const char *node;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* local functions */
|
/* local functions */
|
||||||
static int
|
static void
|
||||||
_device_flags_set(int fd)
|
_cb_libinput_log(struct libinput *libinput EINA_UNUSED, enum libinput_log_priority priority, const char *format, va_list args)
|
||||||
{
|
{
|
||||||
int ret, fl;
|
switch (priority)
|
||||||
/* char name[256] = "unknown"; */
|
|
||||||
|
|
||||||
if (fd < 0)
|
|
||||||
{
|
{
|
||||||
ERR("Failed to take device");
|
case LIBINPUT_LOG_PRIORITY_DEBUG:
|
||||||
return -1;
|
DBG(format, args);
|
||||||
|
break;
|
||||||
|
/* case LIBINPUT_LOG_PRIORITY_INFO: */
|
||||||
|
/* INF(format, args); */
|
||||||
|
/* break; */
|
||||||
|
case LIBINPUT_LOG_PRIORITY_ERROR:
|
||||||
|
ERR(format, args);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((fl = fcntl(fd, F_GETFD)) < 0)
|
static int
|
||||||
|
_cb_open_restricted(const char *path, int flags, void *data)
|
||||||
|
{
|
||||||
|
Ecore_Drm_Input *input;
|
||||||
|
Ecore_Drm_Seat *seat;
|
||||||
|
Ecore_Drm_Evdev *edev;
|
||||||
|
Eina_List *l, *ll;
|
||||||
|
int fd = -1;
|
||||||
|
|
||||||
|
if (!(input = data)) return -1;
|
||||||
|
|
||||||
|
/* try to open the device */
|
||||||
|
fd = _ecore_drm_launcher_device_open_no_pending(path, flags);
|
||||||
|
if (fd < 0) ERR("Could not open device");
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(input->dev->seats, l, seat)
|
||||||
{
|
{
|
||||||
ERR("Failed to get file fd: %m");
|
EINA_LIST_FOREACH(seat->devices, ll, edev)
|
||||||
goto flag_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
fl &= ~FD_CLOEXEC;
|
|
||||||
|
|
||||||
if ((ret = fcntl(fd, F_SETFD, fl)) < 0)
|
|
||||||
{
|
{
|
||||||
ERR("Failed to set file fds: %m");
|
if (strstr(path, edev->path))
|
||||||
goto flag_err;
|
{
|
||||||
|
edev->fd = fd;
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) */
|
|
||||||
/* { */
|
|
||||||
/* ERR("Could not get device name: %m"); */
|
|
||||||
/* goto flag_err; */
|
|
||||||
/* } */
|
|
||||||
/* else */
|
|
||||||
/* { */
|
|
||||||
/* name[sizeof(name) - 1] = '\0'; */
|
|
||||||
/* DBG("%s Opened", name); */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
flag_err:
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cb_device_opened(void *data, int fd, Eina_Bool paused EINA_UNUSED)
|
_cb_close_restricted(int fd, void *data)
|
||||||
{
|
{
|
||||||
Ecore_Drm_Device_Open_Data *d;
|
Ecore_Drm_Input *input;
|
||||||
|
Ecore_Drm_Seat *seat;
|
||||||
Ecore_Drm_Evdev *edev;
|
Ecore_Drm_Evdev *edev;
|
||||||
Eina_Bool b = EINA_FALSE;
|
Eina_List *l, *ll;
|
||||||
|
|
||||||
if (!(d = data)) return;
|
if (!(input = data)) return;
|
||||||
|
|
||||||
if (fd < 0)
|
EINA_LIST_FOREACH(input->dev->seats, l, seat)
|
||||||
{
|
{
|
||||||
ERR("\tCould not get UNIX_FD from eldbus message: %d %d", fd, b);
|
EINA_LIST_FOREACH(seat->devices, ll, edev)
|
||||||
ERR("\tFailed to open device: %s", d->node);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fd = _device_flags_set(fd)) < 0)
|
|
||||||
{
|
{
|
||||||
ERR("\tCould not set fd flags");
|
if (edev->fd == fd)
|
||||||
goto release;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(edev = _ecore_drm_evdev_device_create(d->seat, d->node, fd)))
|
|
||||||
{
|
{
|
||||||
ERR("\tCould not create evdev device: %s", d->node);
|
_ecore_drm_launcher_device_close(edev->path, fd);
|
||||||
goto release;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d->seat->devices = eina_list_append(d->seat->devices, edev);
|
|
||||||
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
release:
|
|
||||||
_ecore_drm_launcher_device_close(d->node, fd);
|
|
||||||
cleanup:
|
|
||||||
eina_stringshare_del(d->node);
|
|
||||||
free(d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Ecore_Drm_Seat *
|
static Ecore_Drm_Seat *
|
||||||
|
@ -101,262 +83,288 @@ _seat_get(Ecore_Drm_Input *input, const char *seat)
|
||||||
Ecore_Drm_Seat *s;
|
Ecore_Drm_Seat *s;
|
||||||
Eina_List *l;
|
Eina_List *l;
|
||||||
|
|
||||||
|
/* search for this name in existing seats */
|
||||||
EINA_LIST_FOREACH(input->dev->seats, l, s)
|
EINA_LIST_FOREACH(input->dev->seats, l, s)
|
||||||
{
|
|
||||||
if (!strcmp(s->name, seat)) return s;
|
if (!strcmp(s->name, seat)) return s;
|
||||||
}
|
|
||||||
|
|
||||||
|
/* try to allocate space for new seat */
|
||||||
if (!(s = calloc(1, sizeof(Ecore_Drm_Seat))))
|
if (!(s = calloc(1, sizeof(Ecore_Drm_Seat))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
s->input = input;
|
s->input = input;
|
||||||
s->name = eina_stringshare_add(seat);
|
s->name = eina_stringshare_add(seat);
|
||||||
|
|
||||||
|
/* add this new seat to list */
|
||||||
input->dev->seats = eina_list_append(input->dev->seats, s);
|
input->dev->seats = eina_list_append(input->dev->seats, s);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
|
||||||
_device_add(Ecore_Drm_Input *input, const char *device)
|
|
||||||
{
|
|
||||||
Ecore_Drm_Seat *seat;
|
|
||||||
Ecore_Drm_Device_Open_Data *data;
|
|
||||||
const char *devseat, *wlseat;
|
|
||||||
|
|
||||||
if (!input) return EINA_FALSE;
|
|
||||||
|
|
||||||
DBG("Add Input Device: %s", device);
|
|
||||||
|
|
||||||
if (!(devseat = eeze_udev_syspath_get_property(device, "ID_SEAT")))
|
|
||||||
devseat = eina_stringshare_add("seat0");
|
|
||||||
|
|
||||||
if (strcmp(devseat, input->seat)) goto seat_err;
|
|
||||||
|
|
||||||
if (!(wlseat = eeze_udev_syspath_get_property(device, "WL_SEAT")))
|
|
||||||
wlseat = eina_stringshare_add("seat0");
|
|
||||||
|
|
||||||
if (!(seat = _seat_get(input, wlseat)))
|
|
||||||
{
|
|
||||||
ERR("\tCould not get matching seat");
|
|
||||||
goto seat_get_err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(data = calloc(1, sizeof(Ecore_Drm_Device_Open_Data))))
|
|
||||||
goto seat_get_err;
|
|
||||||
|
|
||||||
data->seat = seat;
|
|
||||||
if (!(data->node = eeze_udev_syspath_get_devpath(device)))
|
|
||||||
goto dev_err;
|
|
||||||
|
|
||||||
DBG("\tDevice Path: %s", data->node);
|
|
||||||
|
|
||||||
if (!_ecore_drm_launcher_device_open(data->node, _cb_device_opened, data, O_RDWR | O_NONBLOCK))
|
|
||||||
goto dev_err;
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
|
||||||
|
|
||||||
dev_err:
|
|
||||||
free(data);
|
|
||||||
seat_get_err:
|
|
||||||
eina_stringshare_del(wlseat);
|
|
||||||
seat_err:
|
|
||||||
eina_stringshare_del(devseat);
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_device_remove(Ecore_Drm_Input *input, const char *device)
|
_device_added(Ecore_Drm_Input *input, struct libinput_device *device)
|
||||||
{
|
{
|
||||||
|
struct libinput_seat *libinput_seat;
|
||||||
|
const char *seat_name;
|
||||||
Ecore_Drm_Seat *seat;
|
Ecore_Drm_Seat *seat;
|
||||||
Eina_List *l;
|
|
||||||
|
|
||||||
if (!input) return;
|
|
||||||
|
|
||||||
EINA_LIST_FOREACH(input->dev->seats, l, seat)
|
|
||||||
{
|
|
||||||
Ecore_Drm_Evdev *edev;
|
Ecore_Drm_Evdev *edev;
|
||||||
Eina_List *ll;
|
|
||||||
|
|
||||||
EINA_LIST_FOREACH(seat->devices, ll, edev)
|
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)))
|
||||||
{
|
{
|
||||||
if (!strcmp(edev->path, device))
|
ERR("Could not get matching seat: %s", seat_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to create a new evdev device */
|
||||||
|
if (!(edev = _ecore_drm_evdev_device_create(seat, device)))
|
||||||
{
|
{
|
||||||
seat->devices = eina_list_remove(seat->devices, edev);
|
ERR("Failed to create new evdev device");
|
||||||
_ecore_drm_evdev_device_destroy(edev);
|
return;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* append this device to the seat */
|
||||||
|
seat->devices = eina_list_append(seat->devices, edev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cb_input_event(const char *device, Eeze_Udev_Event event, void *data, Eeze_Udev_Watch *watch EINA_UNUSED)
|
_device_removed(Ecore_Drm_Input *input EINA_UNUSED, struct libinput_device *device)
|
||||||
|
{
|
||||||
|
Ecore_Drm_Evdev *edev;
|
||||||
|
|
||||||
|
/* try to get the evdev structure */
|
||||||
|
if (!(edev = libinput_device_get_user_data(device)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* remove this evdev from the seat's list of devices */
|
||||||
|
edev->seat->devices = eina_list_remove(edev->seat->devices, edev);
|
||||||
|
|
||||||
|
/* destroy this evdev */
|
||||||
|
_ecore_drm_evdev_device_destroy(edev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_udev_event_process(struct libinput_event *event)
|
||||||
|
{
|
||||||
|
struct libinput *libinput;
|
||||||
|
struct libinput_device *device;
|
||||||
|
Ecore_Drm_Input *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 (_ecore_drm_evdev_event_process(event)) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_input_events_process(Ecore_Drm_Input *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)
|
||||||
{
|
{
|
||||||
Ecore_Drm_Input *input;
|
Ecore_Drm_Input *input;
|
||||||
|
|
||||||
if (!(input = data)) return;
|
if (!(input = data)) return EINA_TRUE;
|
||||||
|
|
||||||
switch (event)
|
if (libinput_dispatch(input->libinput) != 0)
|
||||||
{
|
ERR("Failed to dispatch libinput events: %m");
|
||||||
case EEZE_UDEV_EVENT_ADD:
|
|
||||||
_device_add(input, device);
|
|
||||||
break;
|
|
||||||
case EEZE_UDEV_EVENT_REMOVE:
|
|
||||||
{
|
|
||||||
const char *node;
|
|
||||||
|
|
||||||
if ((node = eeze_udev_syspath_get_devpath(device)))
|
/* process pending events */
|
||||||
{
|
_input_events_process(input);
|
||||||
_device_remove(input, node);
|
|
||||||
eina_stringshare_del(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static Eina_Bool
|
|
||||||
_devices_add(Ecore_Drm_Input *input)
|
|
||||||
{
|
|
||||||
Eina_List *devices;
|
|
||||||
Eina_Bool found = EINA_FALSE;
|
|
||||||
const char *device;
|
|
||||||
|
|
||||||
/* NB: This really sucks !! We cannot 'OR' diferent device types
|
|
||||||
* together for eeze_udev_find_by_type
|
|
||||||
*
|
|
||||||
* For now, just find by 'NONE" and we'll filter for input devices by
|
|
||||||
* running tests */
|
|
||||||
devices = eeze_udev_find_by_type(EEZE_UDEV_TYPE_NONE, NULL);
|
|
||||||
EINA_LIST_FREE(devices, device)
|
|
||||||
{
|
|
||||||
if ((eeze_udev_syspath_is_mouse(device)) ||
|
|
||||||
(eeze_udev_syspath_is_kbd(device)) ||
|
|
||||||
(eeze_udev_syspath_is_touchpad(device)) ||
|
|
||||||
(eeze_udev_syspath_is_joystick(device)))
|
|
||||||
{
|
|
||||||
if (!_device_add(input, device))
|
|
||||||
ERR("\tFailed to add device");
|
|
||||||
else
|
|
||||||
found = EINA_TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
eina_stringshare_del(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
{
|
|
||||||
ERR("No Input Devices Found");
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct libinput_interface _input_interface =
|
||||||
|
{
|
||||||
|
_cb_open_restricted,
|
||||||
|
_cb_close_restricted,
|
||||||
|
};
|
||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
ecore_drm_inputs_create(Ecore_Drm_Device *dev)
|
ecore_drm_inputs_create(Ecore_Drm_Device *dev)
|
||||||
{
|
{
|
||||||
Ecore_Drm_Input *input;
|
Ecore_Drm_Input *input;
|
||||||
|
int level, priority = LIBINPUT_LOG_PRIORITY_INFO;
|
||||||
|
|
||||||
/* check for valid device */
|
/* check for valid device */
|
||||||
if (!dev) return EINA_FALSE;
|
EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
|
||||||
|
|
||||||
/* try to allocate space for input structure */
|
/* try to allocate space for new input structure */
|
||||||
if (!(input = calloc(1, sizeof(Ecore_Drm_Input))))
|
if (!(input = calloc(1, sizeof(Ecore_Drm_Input))))
|
||||||
return EINA_FALSE;
|
return EINA_FALSE;
|
||||||
|
|
||||||
input->seat = eina_stringshare_add(dev->seat);
|
/* set reference for parent device */
|
||||||
input->dev = dev;
|
input->dev = dev;
|
||||||
|
|
||||||
/* try to enable this input */
|
/* try to create libinput context */
|
||||||
if (!ecore_drm_inputs_enable(input))
|
input->libinput =
|
||||||
|
libinput_udev_create_context(&_input_interface, input, eeze_udev_get());
|
||||||
|
if (!input->libinput)
|
||||||
{
|
{
|
||||||
ERR("Could not enable input");
|
ERR("Could not create libinput context: %m");
|
||||||
if (input->seat) eina_stringshare_del(input->seat);
|
goto err;
|
||||||
free(input);
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add this input to dev */
|
/* get the current eina_log level */
|
||||||
|
level = eina_log_domain_registered_level_get(_ecore_drm_log_dom);
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case EINA_LOG_LEVEL_DBG:
|
||||||
|
priority = LIBINPUT_LOG_PRIORITY_DEBUG;
|
||||||
|
break;
|
||||||
|
case EINA_LOG_LEVEL_INFO:
|
||||||
|
priority = LIBINPUT_LOG_PRIORITY_INFO;
|
||||||
|
break;
|
||||||
|
case EINA_LOG_LEVEL_CRITICAL:
|
||||||
|
case EINA_LOG_LEVEL_ERR:
|
||||||
|
case EINA_LOG_LEVEL_WARN:
|
||||||
|
priority = LIBINPUT_LOG_PRIORITY_ERROR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set callback for libinput logging */
|
||||||
|
libinput_log_set_handler(input->libinput, &_cb_libinput_log);
|
||||||
|
|
||||||
|
/* set libinput log priority */
|
||||||
|
libinput_log_set_priority(input->libinput, priority);
|
||||||
|
|
||||||
|
/* 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 (!ecore_drm_inputs_enable(input))
|
||||||
|
{
|
||||||
|
ERR("Failed to enable input");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* append this input */
|
||||||
dev->inputs = eina_list_append(dev->inputs, input);
|
dev->inputs = eina_list_append(dev->inputs, input);
|
||||||
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (input->libinput) libinput_unref(input->libinput);
|
||||||
|
free(input);
|
||||||
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
ecore_drm_inputs_destroy(Ecore_Drm_Device *dev)
|
ecore_drm_inputs_destroy(Ecore_Drm_Device *dev)
|
||||||
{
|
{
|
||||||
|
Ecore_Drm_Input *input;
|
||||||
Ecore_Drm_Seat *seat;
|
Ecore_Drm_Seat *seat;
|
||||||
Eina_List *l;
|
|
||||||
|
|
||||||
if (!dev) return;
|
|
||||||
|
|
||||||
EINA_LIST_FOREACH(dev->seats, l, seat)
|
|
||||||
{
|
|
||||||
Ecore_Drm_Evdev *edev;
|
Ecore_Drm_Evdev *edev;
|
||||||
|
|
||||||
EINA_LIST_FREE(seat->devices, edev)
|
EINA_LIST_FREE(dev->inputs, input)
|
||||||
{
|
{
|
||||||
_ecore_drm_launcher_device_close(edev->path, edev->fd);
|
if (input->hdlr) ecore_main_fd_handler_del(input->hdlr);
|
||||||
_ecore_drm_evdev_device_destroy(edev);
|
if (input->libinput) libinput_unref(input->libinput);
|
||||||
|
free(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EINA_LIST_FREE(dev->seats, seat)
|
||||||
|
{
|
||||||
|
EINA_LIST_FREE(seat->devices, edev)
|
||||||
|
_ecore_drm_evdev_device_destroy(edev);
|
||||||
|
|
||||||
|
if (seat->name) eina_stringshare_del(seat->name);
|
||||||
|
free(seat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
ecore_drm_inputs_enable(Ecore_Drm_Input *input)
|
ecore_drm_inputs_enable(Ecore_Drm_Input *input)
|
||||||
{
|
{
|
||||||
/* check for valid input */
|
EINA_SAFETY_ON_NULL_RETURN_VAL(input, EINA_FALSE);
|
||||||
if (!input) return EINA_FALSE;
|
EINA_SAFETY_ON_NULL_RETURN_VAL(input->libinput, EINA_FALSE);
|
||||||
|
|
||||||
if (!input->watch)
|
input->fd = libinput_get_fd(input->libinput);
|
||||||
{
|
|
||||||
int events = 0;
|
|
||||||
|
|
||||||
events = (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE);
|
if (!input->hdlr)
|
||||||
/* NB: This really sucks !! We cannot 'OR' diferent device types
|
|
||||||
* together for eeze_udev_watch_add :(
|
|
||||||
*
|
|
||||||
* For now, just put a 'watch' on mouse type as this (in effect) does
|
|
||||||
* what we need by internally by adding a subsystem match for 'input' */
|
|
||||||
if (!(input->watch =
|
|
||||||
eeze_udev_watch_add(EEZE_UDEV_TYPE_MOUSE, events,
|
|
||||||
_cb_input_event, input)))
|
|
||||||
{
|
{
|
||||||
ERR("Could not create Eeze_Udev_Watch for input");
|
input->hdlr =
|
||||||
return EINA_FALSE;
|
ecore_main_fd_handler_add(input->fd, ECORE_FD_READ,
|
||||||
}
|
_cb_input_dispatch, input, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try to add devices */
|
if (input->suspended)
|
||||||
if (!_devices_add(input))
|
|
||||||
{
|
{
|
||||||
ERR("Could not add input devices");
|
if (libinput_resume(input->libinput) != 0)
|
||||||
eeze_udev_watch_del(input->watch);
|
goto err;
|
||||||
input->watch = NULL;
|
|
||||||
return EINA_FALSE;
|
input->suspended = EINA_FALSE;
|
||||||
|
|
||||||
|
/* process pending events */
|
||||||
|
_input_events_process(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
input->enabled = EINA_TRUE;
|
input->enabled = EINA_TRUE;
|
||||||
input->suspended = EINA_FALSE;
|
input->suspended = EINA_FALSE;
|
||||||
|
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
|
|
||||||
|
err:
|
||||||
|
input->enabled = EINA_FALSE;
|
||||||
|
if (input->hdlr) ecore_main_fd_handler_del(input->hdlr);
|
||||||
|
input->hdlr = NULL;
|
||||||
|
return EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
ecore_drm_inputs_disable(Ecore_Drm_Input *input)
|
ecore_drm_inputs_disable(Ecore_Drm_Input *input)
|
||||||
{
|
{
|
||||||
if (!input) return;
|
EINA_SAFETY_ON_NULL_RETURN(input);
|
||||||
|
EINA_SAFETY_ON_TRUE_RETURN(input->suspended);
|
||||||
|
|
||||||
if (input->watch) eeze_udev_watch_del(input->watch);
|
/* suspend this input */
|
||||||
input->watch = NULL;
|
libinput_suspend(input->libinput);
|
||||||
|
|
||||||
|
/* process pending events */
|
||||||
|
_input_events_process(input);
|
||||||
|
|
||||||
input->enabled = EINA_FALSE;
|
|
||||||
input->suspended = EINA_TRUE;
|
input->suspended = EINA_TRUE;
|
||||||
|
|
||||||
ecore_drm_inputs_destroy(input->dev);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,7 +128,7 @@ _ecore_drm_launcher_device_open_no_pending(const char *device, int flags)
|
||||||
void
|
void
|
||||||
_ecore_drm_launcher_device_close(const char *device, int fd)
|
_ecore_drm_launcher_device_close(const char *device, int fd)
|
||||||
{
|
{
|
||||||
if (logind)
|
if ((logind) && (device))
|
||||||
return _ecore_drm_logind_device_close(device);
|
return _ecore_drm_logind_device_close(device);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
# include <sys/ioctl.h>
|
# include <sys/ioctl.h>
|
||||||
|
|
||||||
# include <linux/input.h>
|
# include <linux/input.h>
|
||||||
//# include <libinput.h>
|
# include <libinput.h>
|
||||||
# include <xkbcommon/xkbcommon.h>
|
# include <xkbcommon/xkbcommon.h>
|
||||||
|
|
||||||
# include <xf86drm.h>
|
# include <xf86drm.h>
|
||||||
|
@ -140,10 +140,10 @@ struct _Ecore_Drm_Seat
|
||||||
struct _Ecore_Drm_Input
|
struct _Ecore_Drm_Input
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
const char *seat;
|
|
||||||
Eeze_Udev_Watch *watch;
|
|
||||||
Ecore_Fd_Handler *hdlr;
|
|
||||||
Ecore_Drm_Device *dev;
|
Ecore_Drm_Device *dev;
|
||||||
|
struct libinput *libinput;
|
||||||
|
|
||||||
|
Ecore_Fd_Handler *hdlr;
|
||||||
|
|
||||||
Eina_Bool enabled : 1;
|
Eina_Bool enabled : 1;
|
||||||
Eina_Bool suspended : 1;
|
Eina_Bool suspended : 1;
|
||||||
|
@ -152,25 +152,25 @@ struct _Ecore_Drm_Input
|
||||||
struct _Ecore_Drm_Evdev
|
struct _Ecore_Drm_Evdev
|
||||||
{
|
{
|
||||||
Ecore_Drm_Seat *seat;
|
Ecore_Drm_Seat *seat;
|
||||||
/* struct libinput *linput; */
|
struct libinput_device *device;
|
||||||
/* struct libinput_device *dev; */
|
|
||||||
const char *name, *path;
|
const char *path;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
int mt_slot;
|
int mt_slot;
|
||||||
|
|
||||||
struct
|
/* struct */
|
||||||
{
|
/* { */
|
||||||
int min_x, min_y;
|
/* int min_x, min_y; */
|
||||||
int max_x, max_y;
|
/* int max_x, max_y; */
|
||||||
double rel_w, rel_h;
|
/* double rel_w, rel_h; */
|
||||||
struct
|
/* struct */
|
||||||
{
|
/* { */
|
||||||
int x[2];
|
/* int x[2]; */
|
||||||
int y[2];
|
/* int y[2]; */
|
||||||
Eina_Bool down : 1;
|
/* Eina_Bool down : 1; */
|
||||||
} pt[EVDEV_MAX_SLOTS];
|
/* } pt[EVDEV_MAX_SLOTS]; */
|
||||||
} abs;
|
/* } abs; */
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -179,7 +179,7 @@ struct _Ecore_Drm_Evdev
|
||||||
double threshold;
|
double threshold;
|
||||||
Eina_Bool did_double : 1;
|
Eina_Bool did_double : 1;
|
||||||
Eina_Bool did_triple : 1;
|
Eina_Bool did_triple : 1;
|
||||||
int prev_button, last_button;
|
uint32_t prev_button, last_button;
|
||||||
} mouse;
|
} mouse;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
@ -198,13 +198,8 @@ struct _Ecore_Drm_Evdev
|
||||||
unsigned int depressed, latched, locked, group;
|
unsigned int depressed, latched, locked, group;
|
||||||
} xkb;
|
} xkb;
|
||||||
|
|
||||||
Ecore_Drm_Evdev_Event_Type pending_event;
|
/* Ecore_Drm_Evdev_Capabilities caps; */
|
||||||
Ecore_Drm_Evdev_Capabilities caps;
|
|
||||||
Ecore_Drm_Seat_Capabilities seat_caps;
|
Ecore_Drm_Seat_Capabilities seat_caps;
|
||||||
|
|
||||||
void (*event_process)(Ecore_Drm_Evdev *dev, struct input_event *event, int count);
|
|
||||||
|
|
||||||
Ecore_Fd_Handler *hdlr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Ecore_Drm_Sprite
|
struct _Ecore_Drm_Sprite
|
||||||
|
@ -233,9 +228,9 @@ Eina_Bool _ecore_drm_launcher_device_open(const char *device, Ecore_Drm_Open_Cb
|
||||||
int _ecore_drm_launcher_device_open_no_pending(const char *device, int flags);
|
int _ecore_drm_launcher_device_open_no_pending(const char *device, int flags);
|
||||||
void _ecore_drm_launcher_device_close(const char *device, int fd);
|
void _ecore_drm_launcher_device_close(const char *device, int fd);
|
||||||
|
|
||||||
Ecore_Drm_Evdev *_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, const char *path, int fd);
|
Ecore_Drm_Evdev *_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, struct libinput_device *device);
|
||||||
void _ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *evdev);
|
void _ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *evdev);
|
||||||
/* int _ecore_drm_evdev_event_process(struct libinput_event *event); */
|
Eina_Bool _ecore_drm_evdev_event_process(struct libinput_event *event);
|
||||||
|
|
||||||
Ecore_Drm_Fb *_ecore_drm_fb_create(Ecore_Drm_Device *dev, int width, int height);
|
Ecore_Drm_Fb *_ecore_drm_fb_create(Ecore_Drm_Device *dev, int width, int height);
|
||||||
void _ecore_drm_fb_destroy(Ecore_Drm_Fb *fb);
|
void _ecore_drm_fb_destroy(Ecore_Drm_Fb *fb);
|
||||||
|
|
|
@ -412,6 +412,21 @@ EAPI Eina_List *eeze_udev_find_by_type(Eeze_Udev_Type type, const char *na
|
||||||
* Requires at least one filter.
|
* Requires at least one filter.
|
||||||
*/
|
*/
|
||||||
EAPI Eina_List *eeze_udev_find_by_filter(const char *subsystem, const char *type, const char *name);
|
EAPI Eina_List *eeze_udev_find_by_filter(const char *subsystem, const char *type, const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A more advanced find, allows finds using udev subsystem and sysname
|
||||||
|
*
|
||||||
|
* @param subsystem The udev subsystem to filter by, or @c NULL
|
||||||
|
* @param sysname A filter for the device name, or @c NULL
|
||||||
|
* @return A stringshared Eina_List* of matched devices or @c NULL on failure
|
||||||
|
*
|
||||||
|
* @return A stringshared list of the devices found
|
||||||
|
*
|
||||||
|
* @since 1.13
|
||||||
|
|
||||||
|
EAPI */
|
||||||
|
EAPI Eina_List *eeze_udev_find_by_subsystem_sysname(const char *subsystem, const char *sysname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -382,3 +382,31 @@ eeze_udev_find_by_sysattr(const char *sysattr,
|
||||||
udev_enumerate_unref(en);
|
udev_enumerate_unref(en);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EAPI Eina_List *
|
||||||
|
eeze_udev_find_by_subsystem_sysname(const char *subsystem, const char *sysname)
|
||||||
|
{
|
||||||
|
_udev_enumerate *en;
|
||||||
|
_udev_list_entry *devs, *cur;
|
||||||
|
_udev_device *device;
|
||||||
|
const char *devname;
|
||||||
|
Eina_List *ret = NULL;
|
||||||
|
|
||||||
|
if (!sysname) return NULL;
|
||||||
|
|
||||||
|
en = udev_enumerate_new(udev);
|
||||||
|
if (!en) return NULL;
|
||||||
|
|
||||||
|
udev_enumerate_scan_devices(en);
|
||||||
|
devs = udev_enumerate_get_list_entry(en);
|
||||||
|
udev_list_entry_foreach(cur, devs)
|
||||||
|
{
|
||||||
|
devname = udev_list_entry_get_name(cur);
|
||||||
|
device =
|
||||||
|
udev_device_new_from_subsystem_sysname(udev, subsystem, sysname);
|
||||||
|
ret = eina_list_append(ret, eina_stringshare_add(devname));
|
||||||
|
udev_device_unref(device);
|
||||||
|
}
|
||||||
|
udev_enumerate_unref(en);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue