summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2021-03-24 16:07:27 +0100
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2021-03-24 20:58:13 +0100
commit202bae05ec3af12a3979e21fe967cb4a4c66f587 (patch)
treee2af87bf21e09c5cdd23e4d2a1786359bd5c3fe4
parent49ac4121cf8fe52316faf2829d348c51d7ac7a5e (diff)
downloadefl-devs/bu5hm4n/elput_with_swipe.tar.gz
WIP: elput: introduce gesture passingdevs/bu5hm4n/elput_with_swipe
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.
-rw-r--r--src/lib/elput/Elput.h26
-rw-r--r--src/lib/elput/elput_gestures.c99
-rw-r--r--src/lib/elput/elput_input.c29
-rw-r--r--src/lib/elput/elput_manager.c1
-rw-r--r--src/lib/elput/elput_private.h16
-rw-r--r--src/lib/elput/elput_root.c146
-rw-r--r--src/lib/elput/meson.build2
7 files changed, 307 insertions, 12 deletions
diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h
index 7a05f8e795..01f649ea46 100644
--- a/src/lib/elput/Elput.h
+++ b/src/lib/elput/Elput.h
@@ -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
{
@@ -202,6 +204,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
*
* @param 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
diff --git a/src/lib/elput/elput_gestures.c b/src/lib/elput/elput_gestures.c
new file mode 100644
index 0000000000..9aed338960
--- /dev/null
+++ b/src/lib/elput/elput_gestures.c
@@ -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;
+}
diff --git a/src/lib/elput/elput_input.c b/src/lib/elput/elput_input.c
index 392b157b1b..1ec339fb4e 100644
--- a/src/lib/elput/elput_input.c
+++ b/src/lib/elput/elput_input.c
@@ -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;
}
diff --git a/src/lib/elput/elput_manager.c b/src/lib/elput/elput_manager.c
index 93f39ea261..82335cd0a8 100644
--- a/src/lib/elput/elput_manager.c
+++ b/src/lib/elput/elput_manager.c
@@ -5,6 +5,7 @@ static Elput_Interface *_ifaces[] =
#ifdef HAVE_SYSTEMD
&_logind_interface,
#endif
+ &_root_interface,
NULL,
};
diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h
index fd7d843d2e..a73eb7e7eb 100644
--- a/src/lib/elput/elput_private.h
+++ b/src/lib/elput/elput_private.h
@@ -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);
diff --git a/src/lib/elput/elput_root.c b/src/lib/elput/elput_root.c
new file mode 100644
index 0000000000..f07d46d0b1
--- /dev/null
+++ b/src/lib/elput/elput_root.c
@@ -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,
+};
diff --git a/src/lib/elput/meson.build b/src/lib/elput/meson.build
index 639840e424..0caf56f06d 100644
--- a/src/lib/elput/meson.build
+++ b/src/lib/elput/meson.build
@@ -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'
])