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)
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;
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
50typedef struct _Elput_Swipe_Gesture Elput_Swipe_Gesture;
51
50/* structure to represent event for seat capability changes */ 52/* structure to represent event for seat capability changes */
51typedef struct _Elput_Event_Seat_Caps 53typedef struct _Elput_Event_Seat_Caps
52{ 54{
@@ -202,6 +204,19 @@ EAPI int elput_shutdown(void);
202EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty); 204EAPI Elput_Manager *elput_manager_connect(const char *seat, unsigned int tty);
203 205
204/** 206/**
207 * Create an input manager on the specified seat. Only gesture events are emitted. Nothing else.
208 *
209 * @param seat
210 * @param tty
211 *
212 * @return A Elput_Manager on success, NULL on failure
213 *
214 * @ingroup Elput_Manager_Group
215 */
216EAPI Elput_Manager *elput_manager_connect_gestures(const char *seat, unsigned int tty);
217
218
219/**
205 * Disconnect an input manager 220 * Disconnect an input manager
206 * 221 *
207 * @param manager 222 * @param manager
@@ -726,6 +741,17 @@ EAPI Eina_Stringshare *elput_seat_name_get(const Elput_Seat *seat);
726 * @since 1.20 741 * @since 1.20
727 */ 742 */
728EAPI Elput_Manager *elput_seat_manager_get(const Elput_Seat *seat); 743EAPI Elput_Manager *elput_seat_manager_get(const Elput_Seat *seat);
744
745typedef void (*Elput_Swipe_Gesture_Callback)(void *data, Elput_Device *dev, Elput_Swipe_Gesture *gesture);
746
747EAPI double elput_swipe_dx_get(Elput_Swipe_Gesture *gesture);
748EAPI double elput_swipe_dy_get(Elput_Swipe_Gesture *gesture);
749EAPI int elput_swipe_finger_count_get(Elput_Swipe_Gesture *gesture);
750EAPI void elput_manager_swipe_gesture_listen(Elput_Manager *em,
751 Elput_Swipe_Gesture_Callback begin, void *begin_data,
752 Elput_Swipe_Gesture_Callback update, void *update_data,
753 Elput_Swipe_Gesture_Callback end, void *end_data);
754
729# endif 755# endif
730 756
731# undef EAPI 757# 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 @@
1#include <elput_private.h>
2
3
4EAPI double
5elput_swipe_dx_get(Elput_Swipe_Gesture *gesture)
6{
7 EINA_SAFETY_ON_NULL_RETURN_VAL(gesture, 0.0f);
8 return gesture->dx;
9}
10
11EAPI double
12elput_swipe_dy_get(Elput_Swipe_Gesture *gesture)
13{
14 EINA_SAFETY_ON_NULL_RETURN_VAL(gesture, 0.0f);
15 return gesture->dy;
16}
17
18EAPI int
19elput_swipe_finger_count_get(Elput_Swipe_Gesture *gesture)
20{
21 EINA_SAFETY_ON_NULL_RETURN_VAL(gesture, 0);
22 return gesture->finger_count;
23}
24
25EAPI void
26elput_manager_swipe_gesture_listen(Elput_Manager *em,
27 Elput_Swipe_Gesture_Callback begin, void *begin_data,
28 Elput_Swipe_Gesture_Callback update, void *update_data,
29 Elput_Swipe_Gesture_Callback end, void *end_data)
30{
31 EINA_SAFETY_ON_NULL_RETURN(em);
32 em->swipe_callback.begin.cb = begin;
33 em->swipe_callback.begin.data = begin_data;
34 em->swipe_callback.end.cb = end;
35 em->swipe_callback.end.data = end_data;
36 em->swipe_callback.update.cb = update;
37 em->swipe_callback.update.data = update_data;
38}
39
40EAPI Elput_Manager*
41elput_manager_connect_gestures(const char *seat, unsigned int tty)
42{
43 Elput_Manager *em = elput_manager_connect(seat, tty);
44
45 if (em)
46 {
47 em->only_gesture_events = EINA_TRUE;
48 }
49
50 return em;
51}
52
53static void
54_eval_callback(Elput_Gesture_Swipe_Callback *callback, struct libinput_device *device, struct libinput_event_gesture *gesture)
55{
56 Elput_Device *dev;
57 Elput_Swipe_Gesture elput_gesture = {
58 libinput_event_gesture_get_dx(gesture),
59 libinput_event_gesture_get_dy(gesture),
60 libinput_event_gesture_get_finger_count(gesture),
61 };
62
63 if (!callback->cb) return;
64
65 dev = libinput_device_get_user_data(device);
66
67 callback->cb(callback->data, dev, &elput_gesture);
68}
69
70int
71_gesture_event_process(struct libinput_event *event)
72{
73 Elput_Manager *em;
74 struct libinput *lib;
75 struct libinput_device *dev;
76 int ret = 1;
77
78 lib = libinput_event_get_context(event);
79 dev = libinput_event_get_device(event);
80 em = libinput_get_user_data(lib);
81
82 switch (libinput_event_get_type(event))
83 {
84 case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
85 _eval_callback(&em->swipe_callback.begin, dev, libinput_event_get_gesture_event(event));
86 break;
87 case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
88 _eval_callback(&em->swipe_callback.update, dev, libinput_event_get_gesture_event(event));
89 break;
90 case LIBINPUT_EVENT_GESTURE_SWIPE_END:
91 _eval_callback(&em->swipe_callback.end, dev, libinput_event_get_gesture_event(event));
92 break;
93 default:
94 ret = 0;
95 break;
96 }
97
98 return ret;
99}
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..a73eb7e7eb 100644
--- a/src/lib/elput/elput_private.h
+++ b/src/lib/elput/elput_private.h
@@ -246,6 +246,16 @@ struct _Elput_Device
246 Eina_Bool invert_y : 1; 246 Eina_Bool invert_y : 1;
247}; 247};
248 248
249typedef struct {
250 Elput_Swipe_Gesture_Callback cb;
251 void *data;
252} Elput_Gesture_Swipe_Callback;
253
254struct _Elput_Swipe_Gesture {
255 double dx, dy;
256 int finger_count;
257};
258
249struct _Elput_Manager 259struct _Elput_Manager
250{ 260{
251 Elput_Interface *interface; 261 Elput_Interface *interface;
@@ -257,6 +267,9 @@ struct _Elput_Manager
257 int vt_fd; 267 int vt_fd;
258 Ecore_Event_Handler *vt_hdlr; 268 Ecore_Event_Handler *vt_hdlr;
259 uint32_t window; 269 uint32_t window;
270 struct {
271 Elput_Gesture_Swipe_Callback begin, update, end;
272 } swipe_callback;
260 273
261 int pending_ptr_x; 274 int pending_ptr_x;
262 int pending_ptr_y; 275 int pending_ptr_y;
@@ -282,6 +295,7 @@ struct _Elput_Manager
282 295
283 Elput_Input input; 296 Elput_Input input;
284 Eina_Bool del : 1; 297 Eina_Bool del : 1;
298 Eina_Bool only_gesture_events : 1;
285}; 299};
286 300
287typedef struct _Elput_Async_Open 301typedef struct _Elput_Async_Open
@@ -295,6 +309,7 @@ void _elput_input_enable(Elput_Manager *manager);
295void _elput_input_disable(Elput_Manager *manager); 309void _elput_input_disable(Elput_Manager *manager);
296 310
297int _evdev_event_process(struct libinput_event *event); 311int _evdev_event_process(struct libinput_event *event);
312int _gesture_event_process(struct libinput_event *event);
298Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device); 313Elput_Device *_evdev_device_create(Elput_Seat *seat, struct libinput_device *device);
299void _evdev_device_destroy(Elput_Device *edev); 314void _evdev_device_destroy(Elput_Device *edev);
300void _evdev_keyboard_destroy(Elput_Keyboard *kbd); 315void _evdev_keyboard_destroy(Elput_Keyboard *kbd);
@@ -308,6 +323,7 @@ Elput_Keyboard *_evdev_keyboard_get(Elput_Seat *seat);
308Elput_Touch *_evdev_touch_get(Elput_Seat *seat); 323Elput_Touch *_evdev_touch_get(Elput_Seat *seat);
309 324
310extern Elput_Interface _logind_interface; 325extern Elput_Interface _logind_interface;
326extern Elput_Interface _root_interface;
311 327
312void _keyboard_keymap_update(Elput_Seat *seat); 328void _keyboard_keymap_update(Elput_Seat *seat);
313void _keyboard_group_update(Elput_Seat *seat); 329void _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])