forked from enlightenment/efl
WIP: elput: introduce gesture passing
In order to have that working on Xorg, this requires the libinput group hack if you are not session leader. for now only swipe bindings.
This commit is contained in:
parent
49ac4121cf
commit
202bae05ec
|
@ -47,6 +47,8 @@ typedef struct _Elput_Pointer Elput_Pointer;
|
|||
/* opaque structure to represent a touch device */
|
||||
typedef struct _Elput_Touch Elput_Touch;
|
||||
|
||||
typedef struct _Elput_Swipe_Gesture Elput_Swipe_Gesture;
|
||||
|
||||
/* structure to represent event for seat capability changes */
|
||||
typedef struct _Elput_Event_Seat_Caps
|
||||
{
|
||||
|
@ -201,6 +203,19 @@ EAPI int elput_shutdown(void);
|
|||
*/
|
||||
EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty);
|
||||
|
||||
/**
|
||||
* Create an input manager on the specified seat. Only gesture events are emitted. Nothing else.
|
||||
*
|
||||
* @param seat
|
||||
* @param tty
|
||||
*
|
||||
* @return A Elput_Manager on success, NULL on failure
|
||||
*
|
||||
* @ingroup Elput_Manager_Group
|
||||
*/
|
||||
EAPI Elput_Manager *elput_manager_connect_gestures(const char *seat, unsigned int tty);
|
||||
|
||||
|
||||
/**
|
||||
* Disconnect an input manager
|
||||
*
|
||||
|
@ -726,6 +741,17 @@ EAPI Eina_Stringshare *elput_seat_name_get(const Elput_Seat *seat);
|
|||
* @since 1.20
|
||||
*/
|
||||
EAPI Elput_Manager *elput_seat_manager_get(const Elput_Seat *seat);
|
||||
|
||||
typedef void (*Elput_Swipe_Gesture_Callback)(void *data, Elput_Device *dev, Elput_Swipe_Gesture *gesture);
|
||||
|
||||
EAPI double elput_swipe_dx_get(Elput_Swipe_Gesture *gesture);
|
||||
EAPI double elput_swipe_dy_get(Elput_Swipe_Gesture *gesture);
|
||||
EAPI int elput_swipe_finger_count_get(Elput_Swipe_Gesture *gesture);
|
||||
EAPI void elput_manager_swipe_gesture_listen(Elput_Manager *em,
|
||||
Elput_Swipe_Gesture_Callback begin, void *begin_data,
|
||||
Elput_Swipe_Gesture_Callback update, void *update_data,
|
||||
Elput_Swipe_Gesture_Callback end, void *end_data);
|
||||
|
||||
# endif
|
||||
|
||||
# undef EAPI
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
#include <elput_private.h>
|
||||
|
||||
|
||||
EAPI double
|
||||
elput_swipe_dx_get(Elput_Swipe_Gesture *gesture)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(gesture, 0.0f);
|
||||
return gesture->dx;
|
||||
}
|
||||
|
||||
EAPI double
|
||||
elput_swipe_dy_get(Elput_Swipe_Gesture *gesture)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(gesture, 0.0f);
|
||||
return gesture->dy;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
elput_swipe_finger_count_get(Elput_Swipe_Gesture *gesture)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(gesture, 0);
|
||||
return gesture->finger_count;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
elput_manager_swipe_gesture_listen(Elput_Manager *em,
|
||||
Elput_Swipe_Gesture_Callback begin, void *begin_data,
|
||||
Elput_Swipe_Gesture_Callback update, void *update_data,
|
||||
Elput_Swipe_Gesture_Callback end, void *end_data)
|
||||
{
|
||||
EINA_SAFETY_ON_NULL_RETURN(em);
|
||||
em->swipe_callback.begin.cb = begin;
|
||||
em->swipe_callback.begin.data = begin_data;
|
||||
em->swipe_callback.end.cb = end;
|
||||
em->swipe_callback.end.data = end_data;
|
||||
em->swipe_callback.update.cb = update;
|
||||
em->swipe_callback.update.data = update_data;
|
||||
}
|
||||
|
||||
EAPI Elput_Manager*
|
||||
elput_manager_connect_gestures(const char *seat, unsigned int tty)
|
||||
{
|
||||
Elput_Manager *em = elput_manager_connect(seat, tty);
|
||||
|
||||
if (em)
|
||||
{
|
||||
em->only_gesture_events = EINA_TRUE;
|
||||
}
|
||||
|
||||
return em;
|
||||
}
|
||||
|
||||
static void
|
||||
_eval_callback(Elput_Gesture_Swipe_Callback *callback, struct libinput_device *device, struct libinput_event_gesture *gesture)
|
||||
{
|
||||
Elput_Device *dev;
|
||||
Elput_Swipe_Gesture elput_gesture = {
|
||||
libinput_event_gesture_get_dx(gesture),
|
||||
libinput_event_gesture_get_dy(gesture),
|
||||
libinput_event_gesture_get_finger_count(gesture),
|
||||
};
|
||||
|
||||
if (!callback->cb) return;
|
||||
|
||||
dev = libinput_device_get_user_data(device);
|
||||
|
||||
callback->cb(callback->data, dev, &elput_gesture);
|
||||
}
|
||||
|
||||
int
|
||||
_gesture_event_process(struct libinput_event *event)
|
||||
{
|
||||
Elput_Manager *em;
|
||||
struct libinput *lib;
|
||||
struct libinput_device *dev;
|
||||
int ret = 1;
|
||||
|
||||
lib = libinput_event_get_context(event);
|
||||
dev = libinput_event_get_device(event);
|
||||
em = libinput_get_user_data(lib);
|
||||
|
||||
switch (libinput_event_get_type(event))
|
||||
{
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
|
||||
_eval_callback(&em->swipe_callback.begin, dev, libinput_event_get_gesture_event(event));
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
|
||||
_eval_callback(&em->swipe_callback.update, dev, libinput_event_get_gesture_event(event));
|
||||
break;
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_END:
|
||||
_eval_callback(&em->swipe_callback.end, dev, libinput_event_get_gesture_event(event));
|
||||
break;
|
||||
default:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -301,20 +301,25 @@ _udev_process_event(struct libinput_event *event)
|
|||
}
|
||||
|
||||
static void
|
||||
_process_event(struct libinput_event *event)
|
||||
_process_event(Elput_Manager *em, struct libinput_event *event)
|
||||
{
|
||||
if (_udev_process_event(event)) return;
|
||||
if (!em->only_gesture_events)
|
||||
{
|
||||
if (_evdev_event_process(event)) return;
|
||||
}
|
||||
if (_gesture_event_process(event)) return;
|
||||
}
|
||||
|
||||
static void
|
||||
_process_events(Elput_Input *ei)
|
||||
_process_events(Elput_Manager *em)
|
||||
{
|
||||
struct libinput_event *event;
|
||||
Elput_Input *ei = &em->input;
|
||||
|
||||
while ((ei->lib) && (event = libinput_get_event(ei->lib)))
|
||||
{
|
||||
_process_event(event);
|
||||
_process_event(em, event);
|
||||
libinput_event_destroy(event);
|
||||
}
|
||||
}
|
||||
|
@ -322,14 +327,14 @@ _process_events(Elput_Input *ei)
|
|||
static Eina_Bool
|
||||
_cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
|
||||
{
|
||||
Elput_Input *ei;
|
||||
Elput_Manager *em;
|
||||
|
||||
ei = data;
|
||||
em = data;
|
||||
|
||||
if ((ei->lib) && (libinput_dispatch(ei->lib) != 0))
|
||||
if ((em->input.lib) && (libinput_dispatch(em->input.lib) != 0))
|
||||
WRN("libinput failed to dispatch events");
|
||||
|
||||
_process_events(ei);
|
||||
_process_events(em);
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
@ -361,10 +366,10 @@ _elput_input_init_end(void *data, Ecore_Thread *eth EINA_UNUSED)
|
|||
manager->input.hdlr =
|
||||
ecore_main_fd_handler_add(libinput_get_fd(manager->input.lib),
|
||||
ECORE_FD_READ, _cb_input_dispatch,
|
||||
&manager->input, NULL, NULL);
|
||||
manager, NULL, NULL);
|
||||
|
||||
if (manager->input.hdlr)
|
||||
_process_events(&manager->input);
|
||||
_process_events(manager);
|
||||
else
|
||||
{
|
||||
ERR("Could not create input fd handler");
|
||||
|
@ -431,7 +436,7 @@ _elput_input_enable(Elput_Manager *manager)
|
|||
{
|
||||
if (libinput_resume(manager->input.lib) != 0) return;
|
||||
manager->input.suspended = EINA_FALSE;
|
||||
_process_events(&manager->input);
|
||||
_process_events(manager);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,7 +449,7 @@ _elput_input_disable(Elput_Manager *manager)
|
|||
EINA_LIST_FOREACH(manager->input.seats, l, seat)
|
||||
seat->pending_motion = 1;
|
||||
if (manager->input.lib) libinput_suspend(manager->input.lib);
|
||||
_process_events(&manager->input);
|
||||
_process_events(manager);
|
||||
manager->input.suspended = EINA_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ static Elput_Interface *_ifaces[] =
|
|||
#ifdef HAVE_SYSTEMD
|
||||
&_logind_interface,
|
||||
#endif
|
||||
&_root_interface,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -246,6 +246,16 @@ struct _Elput_Device
|
|||
Eina_Bool invert_y : 1;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
Elput_Swipe_Gesture_Callback cb;
|
||||
void *data;
|
||||
} Elput_Gesture_Swipe_Callback;
|
||||
|
||||
struct _Elput_Swipe_Gesture {
|
||||
double dx, dy;
|
||||
int finger_count;
|
||||
};
|
||||
|
||||
struct _Elput_Manager
|
||||
{
|
||||
Elput_Interface *interface;
|
||||
|
@ -257,6 +267,9 @@ struct _Elput_Manager
|
|||
int vt_fd;
|
||||
Ecore_Event_Handler *vt_hdlr;
|
||||
uint32_t window;
|
||||
struct {
|
||||
Elput_Gesture_Swipe_Callback begin, update, end;
|
||||
} swipe_callback;
|
||||
|
||||
int pending_ptr_x;
|
||||
int pending_ptr_y;
|
||||
|
@ -282,6 +295,7 @@ struct _Elput_Manager
|
|||
|
||||
Elput_Input input;
|
||||
Eina_Bool del : 1;
|
||||
Eina_Bool only_gesture_events : 1;
|
||||
};
|
||||
|
||||
typedef struct _Elput_Async_Open
|
||||
|
@ -295,6 +309,7 @@ void _elput_input_enable(Elput_Manager *manager);
|
|||
void _elput_input_disable(Elput_Manager *manager);
|
||||
|
||||
int _evdev_event_process(struct libinput_event *event);
|
||||
int _gesture_event_process(struct libinput_event *event);
|
||||
Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device);
|
||||
void _evdev_device_destroy(Elput_Device *edev);
|
||||
void _evdev_keyboard_destroy(Elput_Keyboard *kbd);
|
||||
|
@ -308,6 +323,7 @@ Elput_Keyboard *_evdev_keyboard_get(Elput_Seat *seat);
|
|||
Elput_Touch *_evdev_touch_get(Elput_Seat *seat);
|
||||
|
||||
extern Elput_Interface _logind_interface;
|
||||
extern Elput_Interface _root_interface;
|
||||
|
||||
void _keyboard_keymap_update(Elput_Seat *seat);
|
||||
void _keyboard_group_update(Elput_Seat *seat);
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
#include "elput_private.h"
|
||||
#include <grp.h>
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
|
||||
# ifdef major
|
||||
# define MAJOR(x) major(x)
|
||||
# else
|
||||
# define MAJOR(x) ((((x) >> 8) & 0xfff) | (((x) >> 32) & ~0xfff))
|
||||
# endif
|
||||
|
||||
static Eina_Bool
|
||||
_user_part_of_input(void)
|
||||
{
|
||||
uid_t user = getuid();
|
||||
struct passwd *user_pw = getpwuid(user);
|
||||
gid_t *gids = NULL;
|
||||
int number_of_groups = 0;
|
||||
struct group *input_group = getgrnam("input");
|
||||
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(user_pw, EINA_FALSE);
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(input_group, EINA_FALSE);
|
||||
|
||||
if (getgrouplist(user_pw->pw_name, getgid(), NULL, &number_of_groups) != -1)
|
||||
{
|
||||
ERR("Failed to enumerate groups of user");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
number_of_groups ++;
|
||||
gids = alloca((number_of_groups) * sizeof(gid_t));
|
||||
if (getgrouplist(user_pw->pw_name, getgid(), gids, &number_of_groups) == -1)
|
||||
{
|
||||
ERR("Failed to get groups of user");
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < number_of_groups; ++i)
|
||||
{
|
||||
if (gids[i] == input_group->gr_gid)
|
||||
return EINA_TRUE;
|
||||
}
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_root_connect(Elput_Manager **manager EINA_UNUSED, const char *seat EINA_UNUSED, unsigned int tty EINA_UNUSED)
|
||||
{
|
||||
Elput_Manager *em;
|
||||
|
||||
em = calloc(1, sizeof(Elput_Manager));
|
||||
if (!em) return EINA_FALSE;
|
||||
|
||||
em->interface = &_root_interface;
|
||||
em->seat = eina_stringshare_add(seat);
|
||||
|
||||
if (!_user_part_of_input())
|
||||
{
|
||||
free(em);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
*manager = em;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_root_disconnect(Elput_Manager *em EINA_UNUSED)
|
||||
{
|
||||
//Nothing to do here, there is no data to free
|
||||
}
|
||||
|
||||
static int
|
||||
_root_open(Elput_Manager *em EINA_UNUSED, const char *path, int flags)
|
||||
{
|
||||
struct stat st;
|
||||
int ret, fd = -1;
|
||||
int fl;
|
||||
|
||||
ret = stat(path, &st);
|
||||
if (ret < 0) return -1;
|
||||
|
||||
if (!S_ISCHR(st.st_mode)) return -1;
|
||||
|
||||
fd = open(path, flags);
|
||||
if (fd < 0) return fd;
|
||||
|
||||
if (MAJOR(st.st_rdev) == 226) //DRM_MAJOR
|
||||
em->drm_opens++;
|
||||
|
||||
fl = fcntl(fd, F_GETFL);
|
||||
if (fl < 0) goto err;
|
||||
|
||||
if (flags & O_NONBLOCK)
|
||||
fl |= O_NONBLOCK;
|
||||
|
||||
ret = fcntl(fd, F_SETFL, fl);
|
||||
if (ret < 0) goto err;
|
||||
|
||||
return fd;
|
||||
err:
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
_root_open_async(Elput_Manager *em, const char *path, int flags)
|
||||
{
|
||||
int fd = _root_open(em, path, flags);
|
||||
int ret;
|
||||
|
||||
while (1)
|
||||
{
|
||||
ret = write(em->input.pipe, &fd, sizeof(int));
|
||||
if (ret < 0)
|
||||
{
|
||||
if ((errno == EAGAIN) || (errno == EINTR))
|
||||
continue;
|
||||
WRN("Failed to write to input pipe");
|
||||
}
|
||||
break;
|
||||
}
|
||||
close(em->input.pipe);
|
||||
em->input.pipe = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
_root_close(Elput_Manager *em EINA_UNUSED, int fd)
|
||||
{
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_root_vt_set(Elput_Manager *em EINA_UNUSED, int vt EINA_UNUSED)
|
||||
{
|
||||
//Nothing to do here
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
Elput_Interface _root_interface =
|
||||
{
|
||||
_root_connect,
|
||||
_root_disconnect,
|
||||
_root_open,
|
||||
_root_open_async,
|
||||
_root_close,
|
||||
_root_vt_set,
|
||||
};
|
|
@ -11,7 +11,9 @@ elput_src = files([
|
|||
'elput_evdev.c',
|
||||
'elput_input.c',
|
||||
'elput_logind.c',
|
||||
'elput_root.c',
|
||||
'elput_manager.c',
|
||||
'elput_gestures.c',
|
||||
'elput.c',
|
||||
'elput_private.h'
|
||||
])
|
||||
|
|
Loading…
Reference in New Issue