summaryrefslogtreecommitdiff
path: root/src
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-04-01 15:05:51 +0200
commit8493a38876e02e5448b7eafe23725f8843d69185 (patch)
treea375cb7b0f7d784b2d7f87c458d7a2348b58632d /src
parent72f19cc9fafe38293b317e27a3377b30f7c12d56 (diff)
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 this only has swipe bindings, other gestures can follow.
Diffstat (limited to 'src')
-rw-r--r--src/lib/elput/Elput.h104
-rw-r--r--src/lib/elput/elput.c6
-rw-r--r--src/lib/elput/elput_gestures.c78
-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.h10
-rw-r--r--src/lib/elput/elput_root.c146
-rw-r--r--src/lib/elput/meson.build2
8 files changed, 364 insertions, 12 deletions
diff --git a/src/lib/elput/Elput.h b/src/lib/elput/Elput.h
index 7a05f8e795..03f186a8c8 100644
--- a/src/lib/elput/Elput.h
+++ b/src/lib/elput/Elput.h
@@ -47,6 +47,9 @@ typedef struct _Elput_Pointer Elput_Pointer;
47/* opaque structure to represent a touch device */ 47/* opaque structure to represent a touch device */
48typedef struct _Elput_Touch Elput_Touch; 48typedef struct _Elput_Touch Elput_Touch;
49 49
50/* opaque structure to represent swipe data */
51typedef struct _Elput_Swipe_Gesture Elput_Swipe_Gesture;
52
50/* structure to represent event for seat capability changes */ 53/* structure to represent event for seat capability changes */
51typedef struct _Elput_Event_Seat_Caps 54typedef struct _Elput_Event_Seat_Caps
52{ 55{
@@ -131,6 +134,7 @@ EAPI extern int ELPUT_EVENT_MODIFIERS_SEND;
131EAPI extern int ELPUT_EVENT_DEVICE_CHANGE; 134EAPI extern int ELPUT_EVENT_DEVICE_CHANGE;
132EAPI extern int ELPUT_EVENT_SESSION_ACTIVE; 135EAPI extern int ELPUT_EVENT_SESSION_ACTIVE;
133 136
137
134/** @since 1.19 */ 138/** @since 1.19 */
135EAPI extern int ELPUT_EVENT_POINTER_MOTION; 139EAPI extern int ELPUT_EVENT_POINTER_MOTION;
136 140
@@ -202,6 +206,19 @@ EAPI int elput_shutdown(void);
202EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty); 206EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty);
203 207
204/** 208/**
209 * Create an input manager on the specified seat. Only gesture events are emitted. Nothing else.
210 *
211 * @param seat
212 * @param tty
213 *
214 * @return A Elput_Manager on success, NULL on failure
215 *
216 * @ingroup Elput_Manager_Group
217 */
218EAPI Elput_Manager *elput_manager_connect_gestures(const char *seat, unsigned int tty);
219
220
221/**
205 * Disconnect an input manager 222 * Disconnect an input manager
206 * 223 *
207 * @param manager 224 * @param manager
@@ -726,6 +743,93 @@ EAPI Eina_Stringshare *elput_seat_name_get(const Elput_Seat *seat);
726 * @since 1.20 743 * @since 1.20
727 */ 744 */
728EAPI Elput_Manager *elput_seat_manager_get(const Elput_Seat *seat); 745EAPI Elput_Manager *elput_seat_manager_get(const Elput_Seat *seat);
746
747
748/**
749 * @defgroup Elput_Gestures Elput gesture accessors
750 *
751 * Functions for accessing details of gesture events.
752 * The structure pointers can only be accessed within the events that emit them.
753 */
754
755/**
756 * A swipe gesture has began.
757 * ELPUT_EVENT_SWIPE_UPDATE and finally a single ELPUT_EVENT_SWIPE_END event will be emitted.
758 *
759 * @ingroup Elput_Gestures
760 * @since 1.26
761 */
762EAPI extern int ELPUT_EVENT_SWIPE_BEGIN;
763
764/**
765 * There is a change to a ongoing swipe gesture.
766 *
767 * @ingroup Elput_Gestures
768 * @since 1.26
769 */
770EAPI extern int ELPUT_EVENT_SWIPE_UPDATE;
771
772/**
773 * A ongoing swipe gesture has ended.
774 * This ends the lifetime of this gesture.
775 *
776 * @ingroup Elput_Gestures
777 * @since 1.26
778 */
779EAPI extern int ELPUT_EVENT_SWIPE_END;
780
781/**
782 * Get the difference of x position from the last event to this event.
783 *
784 * @param gesture The event, if NULL 0 is returned
785 *
786 * @ingroup Elput_Gestures
787 * @since 1.26
788 */
789EAPI double elput_swipe_dx_get(Elput_Swipe_Gesture *gesture);
790
791/**
792 * Get the difference of y position from the last event to this event.
793 *
794 * @param gesture The event, if NULL 0 is returned
795 *
796 * @ingroup Elput_Gestures
797 * @since 1.26
798 */
799EAPI double elput_swipe_dy_get(Elput_Swipe_Gesture *gesture);
800
801/**
802 * Get the finger_count for this gesture
803 *
804 * @param gesture The event, if NULL 0 is returned
805 *
806 * @ingroup Elput_Gestures
807 * @since 1.26
808 */
809EAPI int elput_swipe_finger_count_get(Elput_Swipe_Gesture *gesture);
810
811/**
812 * Get the window in which this event is emitted.
813 *
814 * @param gesture The event, if NULL 0 is returned
815 *
816 * @ingroup Elput_Gestures
817 * @since 1.26
818 */
819EAPI int elput_swipe_window_get(Elput_Swipe_Gesture *gesture);
820
821/**
822 * Get the device from which the gesture event is coming.
823 *
824 * This value is the same for the lifetime of a gesture
825 *
826 * @param gesture The event, if NULL, NULL is returned
827 *
828 * @ingroup Elput_Gestures
829 * @since 1.26
830 */
831EAPI Elput_Device *elput_swipe_device_get(Elput_Swipe_Gesture *gesture);
832
729# endif 833# endif
730 834
731# undef EAPI 835# undef EAPI
diff --git a/src/lib/elput/elput.c b/src/lib/elput/elput.c
index 3c51bca1ff..6426e803e4 100644
--- a/src/lib/elput/elput.c
+++ b/src/lib/elput/elput.c
@@ -14,6 +14,9 @@ EAPI int ELPUT_EVENT_DEVICE_CHANGE = 0;
14EAPI int ELPUT_EVENT_SESSION_ACTIVE = 0; 14EAPI int ELPUT_EVENT_SESSION_ACTIVE = 0;
15EAPI int ELPUT_EVENT_POINTER_MOTION = 0; 15EAPI int ELPUT_EVENT_POINTER_MOTION = 0;
16EAPI int ELPUT_EVENT_SWITCH = 0; 16EAPI int ELPUT_EVENT_SWITCH = 0;
17EAPI int ELPUT_EVENT_SWIPE_BEGIN = 0;
18EAPI int ELPUT_EVENT_SWIPE_UPDATE = 0;
19EAPI int ELPUT_EVENT_SWIPE_END = 0;
17 20
18EAPI int 21EAPI int
19elput_init(void) 22elput_init(void)
@@ -40,6 +43,9 @@ elput_init(void)
40 ELPUT_EVENT_SESSION_ACTIVE = ecore_event_type_new(); 43 ELPUT_EVENT_SESSION_ACTIVE = ecore_event_type_new();
41 ELPUT_EVENT_POINTER_MOTION = ecore_event_type_new(); 44 ELPUT_EVENT_POINTER_MOTION = ecore_event_type_new();
42 ELPUT_EVENT_SWITCH = ecore_event_type_new(); 45 ELPUT_EVENT_SWITCH = ecore_event_type_new();
46 ELPUT_EVENT_SWIPE_BEGIN = ecore_event_type_new();
47 ELPUT_EVENT_SWIPE_UPDATE = ecore_event_type_new();
48 ELPUT_EVENT_SWIPE_END = ecore_event_type_new();
43 49
44 return _elput_init_count; 50 return _elput_init_count;
45 51
diff --git a/src/lib/elput/elput_gestures.c b/src/lib/elput/elput_gestures.c
new file mode 100644
index 0000000000..baa67e9519
--- /dev/null
+++ b/src/lib/elput/elput_gestures.c
@@ -0,0 +1,78 @@
1#include <elput_private.h>
2
3#define ACCESSOR(STRUCT_NAME, FIELD_NAME, TYPE, FALLBACK) \
4EAPI TYPE \
5elput_##STRUCT_NAME##_##FIELD_NAME##_get(Elput_Swipe_Gesture *gesture) \
6{ \
7 EINA_SAFETY_ON_NULL_RETURN_VAL(gesture, FALLBACK); \
8 return gesture->FIELD_NAME; \
9}
10
11ACCESSOR(swipe, dy, double, 0.0f)
12ACCESSOR(swipe, dx, double, 0.0f)
13ACCESSOR(swipe, finger_count, int, 0)
14ACCESSOR(swipe, window, int, 0)
15ACCESSOR(swipe, device, Elput_Device*, NULL)
16
17EAPI Elput_Manager*
18elput_manager_connect_gestures(const char *seat, unsigned int tty)
19{
20 Elput_Manager *em = elput_manager_connect(seat, tty);
21
22 if (em)
23 {
24 em->only_gesture_events = EINA_TRUE;
25 }
26
27 return em;
28}
29
30static void
31_free_and_unref_device(void *userdata EINA_UNUSED, void *data)
32{
33 Elput_Swipe_Gesture *gesture = data;
34 libinput_device_unref(gesture->device->device);
35 free(gesture);
36}
37
38static void
39_eval_callback(int event, struct libinput_device *device, struct libinput_event_gesture *gesture)
40{
41 Elput_Device *dev = libinput_device_get_user_data(device);
42 Elput_Swipe_Gesture *elput_gesture = calloc(1, sizeof(Elput_Swipe_Gesture));
43 elput_gesture->dx = libinput_event_gesture_get_dx(gesture);
44 elput_gesture->dy = libinput_event_gesture_get_dy(gesture);
45 elput_gesture->finger_count = libinput_event_gesture_get_finger_count(gesture);
46 elput_gesture->window = dev->seat->manager->window;
47 elput_gesture->device = dev;
48
49 libinput_device_ref(device);
50 ecore_event_add(event, elput_gesture, _free_and_unref_device, NULL);
51}
52
53int
54_gesture_event_process(struct libinput_event *event)
55{
56 struct libinput_device *dev;
57 int ret = 1;
58
59 dev = libinput_event_get_device(event);
60
61 switch (libinput_event_get_type(event))
62 {
63 case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
64 _eval_callback(ELPUT_EVENT_SWIPE_BEGIN, dev, libinput_event_get_gesture_event(event));
65 break;
66 case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
67 _eval_callback(ELPUT_EVENT_SWIPE_UPDATE, dev, libinput_event_get_gesture_event(event));
68 break;
69 case LIBINPUT_EVENT_GESTURE_SWIPE_END:
70 _eval_callback(ELPUT_EVENT_SWIPE_END, dev, libinput_event_get_gesture_event(event));
71 break;
72 default:
73 ret = 0;
74 break;
75 }
76
77 return ret;
78}
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)
301} 301}
302 302
303static void 303static void
304_process_event(struct libinput_event *event) 304_process_event(Elput_Manager *em, struct libinput_event *event)
305{ 305{
306 if (_udev_process_event(event)) return; 306 if (_udev_process_event(event)) return;
307 if (_evdev_event_process(event)) return; 307 if (!em->only_gesture_events)
308 {
309 if (_evdev_event_process(event)) return;
310 }
311 if (_gesture_event_process(event)) return;
308} 312}
309 313
310static void 314static void
311_process_events(Elput_Input *ei) 315_process_events(Elput_Manager *em)
312{ 316{
313 struct libinput_event *event; 317 struct libinput_event *event;
318 Elput_Input *ei = &em->input;
314 319
315 while ((ei->lib) && (event = libinput_get_event(ei->lib))) 320 while ((ei->lib) && (event = libinput_get_event(ei->lib)))
316 { 321 {
317 _process_event(event); 322 _process_event(em, event);
318 libinput_event_destroy(event); 323 libinput_event_destroy(event);
319 } 324 }
320} 325}
@@ -322,14 +327,14 @@ _process_events(Elput_Input *ei)
322static Eina_Bool 327static Eina_Bool
323_cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) 328_cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
324{ 329{
325 Elput_Input *ei; 330 Elput_Manager *em;
326 331
327 ei = data; 332 em = data;
328 333
329 if ((ei->lib) && (libinput_dispatch(ei->lib) != 0)) 334 if ((em->input.lib) && (libinput_dispatch(em->input.lib) != 0))
330 WRN("libinput failed to dispatch events"); 335 WRN("libinput failed to dispatch events");
331 336
332 _process_events(ei); 337 _process_events(em);
333 338
334 return EINA_TRUE; 339 return EINA_TRUE;
335} 340}
@@ -361,10 +366,10 @@ _elput_input_init_end(void *data, Ecore_Thread *eth EINA_UNUSED)
361 manager->input.hdlr = 366 manager->input.hdlr =
362 ecore_main_fd_handler_add(libinput_get_fd(manager->input.lib), 367 ecore_main_fd_handler_add(libinput_get_fd(manager->input.lib),
363 ECORE_FD_READ, _cb_input_dispatch, 368 ECORE_FD_READ, _cb_input_dispatch,
364 &manager->input, NULL, NULL); 369 manager, NULL, NULL);
365 370
366 if (manager->input.hdlr) 371 if (manager->input.hdlr)
367 _process_events(&manager->input); 372 _process_events(manager);
368 else 373 else
369 { 374 {
370 ERR("Could not create input fd handler"); 375 ERR("Could not create input fd handler");
@@ -431,7 +436,7 @@ _elput_input_enable(Elput_Manager *manager)
431 { 436 {
432 if (libinput_resume(manager->input.lib) != 0) return; 437 if (libinput_resume(manager->input.lib) != 0) return;
433 manager->input.suspended = EINA_FALSE; 438 manager->input.suspended = EINA_FALSE;
434 _process_events(&manager->input); 439 _process_events(manager);
435 } 440 }
436} 441}
437 442
@@ -444,7 +449,7 @@ _elput_input_disable(Elput_Manager *manager)
444 EINA_LIST_FOREACH(manager->input.seats, l, seat) 449 EINA_LIST_FOREACH(manager->input.seats, l, seat)
445 seat->pending_motion = 1; 450 seat->pending_motion = 1;
446 if (manager->input.lib) libinput_suspend(manager->input.lib); 451 if (manager->input.lib) libinput_suspend(manager->input.lib);
447 _process_events(&manager->input); 452 _process_events(manager);
448 manager->input.suspended = EINA_TRUE; 453 manager->input.suspended = EINA_TRUE;
449} 454}
450 455
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[] =
5#ifdef HAVE_SYSTEMD 5#ifdef HAVE_SYSTEMD
6 &_logind_interface, 6 &_logind_interface,
7#endif 7#endif
8 &_root_interface,
8 NULL, 9 NULL,
9}; 10};
10 11
diff --git a/src/lib/elput/elput_private.h b/src/lib/elput/elput_private.h
index fd7d843d2e..9c613d9d57 100644
--- a/src/lib/elput/elput_private.h
+++ b/src/lib/elput/elput_private.h
@@ -246,6 +246,13 @@ struct _Elput_Device
246 Eina_Bool invert_y : 1; 246 Eina_Bool invert_y : 1;
247}; 247};
248 248
249struct _Elput_Swipe_Gesture {
250 double dx, dy;
251 int finger_count;
252 int window;
253 Elput_Device *device;
254};
255
249struct _Elput_Manager 256struct _Elput_Manager
250{ 257{
251 Elput_Interface *interface; 258 Elput_Interface *interface;
@@ -282,6 +289,7 @@ struct _Elput_Manager
282 289
283 Elput_Input input; 290 Elput_Input input;
284 Eina_Bool del : 1; 291 Eina_Bool del : 1;
292 Eina_Bool only_gesture_events : 1;
285}; 293};
286 294
287typedef struct _Elput_Async_Open 295typedef struct _Elput_Async_Open
@@ -295,6 +303,7 @@ void _elput_input_enable(Elput_Manager *manager);
295void _elput_input_disable(Elput_Manager *manager); 303void _elput_input_disable(Elput_Manager *manager);
296 304
297int _evdev_event_process(struct libinput_event *event); 305int _evdev_event_process(struct libinput_event *event);
306int _gesture_event_process(struct libinput_event *event);
298Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device); 307Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device);
299void _evdev_device_destroy(Elput_Device *edev); 308void _evdev_device_destroy(Elput_Device *edev);
300void _evdev_keyboard_destroy(Elput_Keyboard *kbd); 309void _evdev_keyboard_destroy(Elput_Keyboard *kbd);
@@ -308,6 +317,7 @@ Elput_Keyboard *_evdev_keyboard_get(Elput_Seat *seat);
308Elput_Touch *_evdev_touch_get(Elput_Seat *seat); 317Elput_Touch *_evdev_touch_get(Elput_Seat *seat);
309 318
310extern Elput_Interface _logind_interface; 319extern Elput_Interface _logind_interface;
320extern Elput_Interface _root_interface;
311 321
312void _keyboard_keymap_update(Elput_Seat *seat); 322void _keyboard_keymap_update(Elput_Seat *seat);
313void _keyboard_group_update(Elput_Seat *seat); 323void _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 @@
1#include "elput_private.h"
2#include <grp.h>
3#include <sys/types.h>
4#include <pwd.h>
5
6# ifdef major
7# define MAJOR(x) major(x)
8# else
9# define MAJOR(x) ((((x) >> 8) & 0xfff) | (((x) >> 32) & ~0xfff))
10# endif
11
12static Eina_Bool
13_user_part_of_input(void)
14{
15 uid_t user = getuid();
16 struct passwd *user_pw = getpwuid(user);
17 gid_t *gids = NULL;
18 int number_of_groups = 0;
19 struct group *input_group = getgrnam("input");
20
21 EINA_SAFETY_ON_NULL_RETURN_VAL(user_pw, EINA_FALSE);
22 EINA_SAFETY_ON_NULL_RETURN_VAL(input_group, EINA_FALSE);
23
24 if (getgrouplist(user_pw->pw_name, getgid(), NULL, &number_of_groups) != -1)
25 {
26 ERR("Failed to enumerate groups of user");
27 return EINA_FALSE;
28 }
29 number_of_groups ++;
30 gids = alloca((number_of_groups) * sizeof(gid_t));
31 if (getgrouplist(user_pw->pw_name, getgid(), gids, &number_of_groups) == -1)
32 {
33 ERR("Failed to get groups of user");
34 return EINA_FALSE;
35 }
36
37 for (int i = 0; i < number_of_groups; ++i)
38 {
39 if (gids[i] == input_group->gr_gid)
40 return EINA_TRUE;
41 }
42 return EINA_FALSE;
43}
44
45static Eina_Bool
46_root_connect(Elput_Manager **manager EINA_UNUSED, const char *seat EINA_UNUSED, unsigned int tty EINA_UNUSED)
47{
48 Elput_Manager *em;
49
50 em = calloc(1, sizeof(Elput_Manager));
51 if (!em) return EINA_FALSE;
52
53 em->interface = &_root_interface;
54 em->seat = eina_stringshare_add(seat);
55
56 if (!_user_part_of_input())
57 {
58 free(em);
59 return EINA_FALSE;
60 }
61 *manager = em;
62 return EINA_TRUE;
63}
64
65static void
66_root_disconnect(Elput_Manager *em EINA_UNUSED)
67{
68 //Nothing to do here, there is no data to free
69}
70
71static int
72_root_open(Elput_Manager *em EINA_UNUSED, const char *path, int flags)
73{
74 struct stat st;
75 int ret, fd = -1;
76 int fl;
77
78 ret = stat(path, &st);
79 if (ret < 0) return -1;
80
81 if (!S_ISCHR(st.st_mode)) return -1;
82
83 fd = open(path, flags);
84 if (fd < 0) return fd;
85
86 if (MAJOR(st.st_rdev) == 226) //DRM_MAJOR
87 em->drm_opens++;
88
89 fl = fcntl(fd, F_GETFL);
90 if (fl < 0) goto err;
91
92 if (flags & O_NONBLOCK)
93 fl |= O_NONBLOCK;
94
95 ret = fcntl(fd, F_SETFL, fl);
96 if (ret < 0) goto err;
97
98 return fd;
99err:
100 close(fd);
101 return -1;
102}
103
104static void
105_root_open_async(Elput_Manager *em, const char *path, int flags)
106{
107 int fd = _root_open(em, path, flags);
108 int ret;
109
110 while (1)
111 {
112 ret = write(em->input.pipe, &fd, sizeof(int));
113 if (ret < 0)
114 {
115 if ((errno == EAGAIN) || (errno == EINTR))
116 continue;
117 WRN("Failed to write to input pipe");
118 }
119 break;
120 }
121 close(em->input.pipe);
122 em->input.pipe = -1;
123}
124
125static void
126_root_close(Elput_Manager *em EINA_UNUSED, int fd)
127{
128 close(fd);
129}
130
131static Eina_Bool
132_root_vt_set(Elput_Manager *em EINA_UNUSED, int vt EINA_UNUSED)
133{
134 //Nothing to do here
135 return EINA_TRUE;
136}
137
138Elput_Interface _root_interface =
139{
140 _root_connect,
141 _root_disconnect,
142 _root_open,
143 _root_open_async,
144 _root_close,
145 _root_vt_set,
146};
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([
11 'elput_evdev.c', 11 'elput_evdev.c',
12 'elput_input.c', 12 'elput_input.c',
13 'elput_logind.c', 13 'elput_logind.c',
14 'elput_root.c',
14 'elput_manager.c', 15 'elput_manager.c',
16 'elput_gestures.c',
15 'elput.c', 17 'elput.c',
16 'elput_private.h' 18 'elput_private.h'
17]) 19])