Compare commits

...

1 Commits

Author SHA1 Message Date
Marcel Hollerbach 202bae05ec 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.
2021-03-24 20:58:13 +01:00
7 changed files with 307 additions and 12 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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 (_evdev_event_process(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;
}

View File

@ -5,6 +5,7 @@ static Elput_Interface *_ifaces[] =
#ifdef HAVE_SYSTEMD
&_logind_interface,
#endif
&_root_interface,
NULL,
};

View File

@ -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);

146
src/lib/elput/elput_root.c Normal file
View File

@ -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,
};

View File

@ -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'
])