1 /* this file contains code copied from weston; the copyright notice is below */
2 /*
3  * Copyright © 2013 Intel Corporation
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial
15  * portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 #include "elput_private.h"
28 #include <libudev.h>
29 
30 static int
_cb_open_restricted(const char * path,int flags,void * data)31 _cb_open_restricted(const char *path, int flags, void *data)
32 {
33    Elput_Manager *em = data;
34    int ret = -1;
35    Elput_Async_Open *ao;
36    int p[2];
37 
38    if (!em->input.thread)
39      return em->interface->open(em, path, flags);
40    if (!em->interface->open_async) return ret;
41    if (ecore_thread_check(em->input.thread)) return ret;
42    ao = calloc(1, sizeof(Elput_Async_Open));
43    if (!ao) return ret;
44    if (pipe2(p, O_CLOEXEC) < 0)
45      {
46         free(ao);
47         return ret;
48      }
49    ao->manager = em;
50    ao->path = strdup(path);
51    ao->flags = flags;
52    em->input.pipe = p[1];
53    ecore_thread_feedback(em->input.thread, ao);
54    while (!ecore_thread_check(em->input.thread))
55      {
56         int avail, fd;
57         fd_set rfds, wfds, exfds;
58         struct timeval tv, *t;
59 
60         FD_ZERO(&rfds);
61         FD_ZERO(&wfds);
62         FD_ZERO(&exfds);
63         FD_SET(p[0], &rfds);
64         tv.tv_sec = 0;
65         tv.tv_usec = 300;
66         t = &tv;
67         avail = select(p[0] + 1, &rfds, &wfds, &exfds, t);
68         if (avail > 0)
69           {
70              if (read(p[0], &fd, sizeof(int)) < 1)
71                ret = -1;
72              else
73                ret = fd;
74              break;
75           }
76         if (avail < 0) break;
77      }
78    close(p[0]);
79    return ret;
80 }
81 
82 static void
_cb_close_restricted(int fd,void * data)83 _cb_close_restricted(int fd, void *data)
84 {
85    Elput_Manager *em;
86 
87    em = data;
88    elput_manager_close(em, fd);
89 }
90 
91 const struct libinput_interface _input_interface =
92 {
93    _cb_open_restricted,
94    _cb_close_restricted,
95 };
96 
97 static Elput_Seat *
_udev_seat_create(Elput_Manager * em,const char * name)98 _udev_seat_create(Elput_Manager *em, const char *name)
99 {
100    Elput_Seat *eseat;
101 
102    eseat = calloc(1, sizeof(Elput_Seat));
103    if (!eseat) return NULL;
104 
105    eseat->manager = em;
106    eseat->refs = 1;
107 
108    eseat->name = eina_stringshare_add(name);
109    em->input.seats = eina_list_append(em->input.seats, eseat);
110 
111    return eseat;
112 }
113 
114 void
_udev_seat_destroy(Elput_Seat * eseat)115 _udev_seat_destroy(Elput_Seat *eseat)
116 {
117    Elput_Device *edev;
118 
119    eseat->refs--;
120    if (eseat->refs) return;
121 
122    EINA_LIST_FREE(eseat->devices, edev)
123      _evdev_device_destroy(edev);
124 
125    if (eseat->kbd) _evdev_keyboard_destroy(eseat->kbd);
126    eseat->kbd = NULL;
127    if (eseat->ptr) _evdev_pointer_destroy(eseat->ptr);
128    eseat->ptr = NULL;
129    if (eseat->touch) _evdev_touch_destroy(eseat->touch);
130    eseat->touch = NULL;
131    if (eseat->manager->input.seats)
132      eseat->manager->input.seats = eina_list_remove(eseat->manager->input.seats, eseat);
133    if (eseat->refs) return;
134 
135    eina_stringshare_del(eseat->name);
136    free(eseat);
137 }
138 
139 static Elput_Seat *
_udev_seat_named_get(Elput_Manager * em,const char * name)140 _udev_seat_named_get(Elput_Manager *em, const char *name)
141 {
142    Elput_Seat *eseat;
143    Eina_List *l;
144 
145    if (!name) name = "seat0";
146 
147    EINA_LIST_FOREACH(em->input.seats, l, eseat)
148      if (!strcmp(eseat->name, name)) return eseat;
149 
150    eseat = _udev_seat_create(em, name);
151    if (!eseat) return NULL;
152 
153    return eseat;
154 }
155 
156 static Elput_Seat *
_udev_seat_get(Elput_Manager * em,struct libinput_device * device)157 _udev_seat_get(Elput_Manager *em, struct libinput_device *device)
158 {
159    struct libinput_seat *lseat;
160    const char *name;
161 
162    lseat = libinput_device_get_seat(device);
163    name = libinput_seat_get_physical_name(lseat);
164 
165    return _udev_seat_named_get(em, name);
166 }
167 
168 static void
_device_event_cb_free(void * data EINA_UNUSED,void * event)169 _device_event_cb_free(void *data EINA_UNUSED, void *event)
170 {
171    Elput_Event_Device_Change *ev;
172 
173    ev = event;
174 
175    ev->device->refs--;
176    if (ev->type == ELPUT_DEVICE_REMOVED)
177      {
178         Elput_Seat *seat;
179 
180         seat = ev->device->seat;
181         if (seat)
182           seat->devices = eina_list_remove(seat->devices, ev->device);
183 
184         _evdev_device_destroy(ev->device);
185      }
186 
187    free(ev);
188 }
189 
190 static void
_device_event_send(Elput_Device * edev,Elput_Device_Change_Type type)191 _device_event_send(Elput_Device *edev, Elput_Device_Change_Type type)
192 {
193    Elput_Event_Device_Change *ev;
194 
195    ev = calloc(1, sizeof(Elput_Event_Device_Change));
196    if (!ev) return;
197 
198    ev->device = edev;
199    ev->type = type;
200    edev->refs++;
201 
202    ecore_event_add(ELPUT_EVENT_DEVICE_CHANGE, ev, _device_event_cb_free, NULL);
203 }
204 
205 static void
_device_add(Elput_Manager * em,struct libinput_device * dev)206 _device_add(Elput_Manager *em, struct libinput_device *dev)
207 {
208    Elput_Seat *eseat;
209    Elput_Device *edev;
210 
211    eseat = _udev_seat_get(em, dev);
212    if (!eseat) return;
213 
214    edev = _evdev_device_create(eseat, dev);
215    if (!edev) return;
216 
217    eseat->devices = eina_list_append(eseat->devices, edev);
218 
219    DBG("Input Device Added: %s", libinput_device_get_name(dev));
220 
221    if (edev->caps & ELPUT_DEVICE_CAPS_KEYBOARD)
222      DBG("\tDevice added as Keyboard device");
223 
224    if (edev->caps & ELPUT_DEVICE_CAPS_POINTER)
225      {
226         DBG("\tDevice added as Pointer device");
227         switch (em->input.rotation)
228           {
229            case 0:
230              edev->swap = EINA_FALSE;
231              edev->invert_x = EINA_FALSE;
232              edev->invert_y = EINA_FALSE;
233              break;
234            case 90:
235              edev->swap = EINA_TRUE;
236              edev->invert_x = EINA_FALSE;
237              edev->invert_y = EINA_TRUE;
238              break;
239            case 180:
240              edev->swap = EINA_FALSE;
241              edev->invert_x = EINA_TRUE;
242              edev->invert_y = EINA_TRUE;
243              break;
244            case 270:
245              edev->swap = EINA_TRUE;
246              edev->invert_x = EINA_TRUE;
247              edev->invert_y = EINA_FALSE;
248              break;
249            default:
250              break;
251           }
252      }
253 
254    if (edev->caps & ELPUT_DEVICE_CAPS_TOUCH)
255      {
256         DBG("\tDevice added as Touch device");
257      }
258 
259    _device_event_send(edev, ELPUT_DEVICE_ADDED);
260 }
261 
262 static void
_device_remove(Elput_Manager * em EINA_UNUSED,struct libinput_device * device)263 _device_remove(Elput_Manager *em EINA_UNUSED, struct libinput_device *device)
264 {
265    Elput_Device *edev;
266 
267    edev = libinput_device_get_user_data(device);
268    if (!edev) return;
269 
270    DBG("Input Device Removed: %s", libinput_device_get_name(device));
271 
272    _device_event_send(edev, ELPUT_DEVICE_REMOVED);
273 }
274 
275 static int
_udev_process_event(struct libinput_event * event)276 _udev_process_event(struct libinput_event *event)
277 {
278    Elput_Manager *em;
279    struct libinput *lib;
280    struct libinput_device *dev;
281    int ret = 1;
282 
283    lib = libinput_event_get_context(event);
284    dev = libinput_event_get_device(event);
285    em = libinput_get_user_data(lib);
286 
287    switch (libinput_event_get_type(event))
288      {
289       case LIBINPUT_EVENT_DEVICE_ADDED:
290         _device_add(em, dev);
291         break;
292       case LIBINPUT_EVENT_DEVICE_REMOVED:
293         _device_remove(em, dev);
294         break;
295       default:
296         ret = 0;
297         break;
298      }
299 
300    return ret;
301 }
302 
303 static void
_process_event(struct libinput_event * event)304 _process_event(struct libinput_event *event)
305 {
306    if (_udev_process_event(event)) return;
307    if (_evdev_event_process(event)) return;
308 }
309 
310 static void
_process_events(Elput_Input * ei)311 _process_events(Elput_Input *ei)
312 {
313    struct libinput_event *event;
314 
315    while ((ei->lib) && (event = libinput_get_event(ei->lib)))
316      {
317         _process_event(event);
318         libinput_event_destroy(event);
319      }
320 }
321 
322 static Eina_Bool
_cb_input_dispatch(void * data,Ecore_Fd_Handler * hdlr EINA_UNUSED)323 _cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
324 {
325    Elput_Input *ei;
326 
327    ei = data;
328 
329    if ((ei->lib) && (libinput_dispatch(ei->lib) != 0))
330      WRN("libinput failed to dispatch events");
331 
332    _process_events(ei);
333 
334    return EINA_TRUE;
335 }
336 
337 static void
_elput_input_init_cancel(void * data,Ecore_Thread * eth EINA_UNUSED)338 _elput_input_init_cancel(void *data, Ecore_Thread *eth EINA_UNUSED)
339 {
340    Elput_Manager *manager = data;
341 
342    manager->input.thread = NULL;
343    if (manager->input.current_pending)
344      {
345         eldbus_pending_cancel(manager->input.current_pending);
346         if (manager->input.pipe >= 0)
347           close(manager->input.pipe);
348      }
349    if (manager->del)
350      elput_manager_disconnect(manager);
351 }
352 
353 static void
_elput_input_init_end(void * data,Ecore_Thread * eth EINA_UNUSED)354 _elput_input_init_end(void *data, Ecore_Thread *eth EINA_UNUSED)
355 {
356    Elput_Manager *manager = data;
357 
358    manager->input.thread = NULL;
359    if (!manager->input.lib) return;
360 
361    manager->input.hdlr =
362      ecore_main_fd_handler_add(libinput_get_fd(manager->input.lib),
363                                ECORE_FD_READ, _cb_input_dispatch,
364                                &manager->input, NULL, NULL);
365 
366    if (manager->input.hdlr)
367       _process_events(&manager->input);
368    else
369      {
370         ERR("Could not create input fd handler");
371         libinput_unref(manager->input.lib);
372         manager->input.lib = NULL;
373      }
374 
375    if ((manager->pending_ptr_x) || (manager->pending_ptr_y))
376      {
377         elput_input_pointer_xy_set(manager, NULL, manager->pending_ptr_x,
378                                    manager->pending_ptr_y);
379         manager->pending_ptr_x = 0;
380         manager->pending_ptr_y = 0;
381      }
382 }
383 
384 static void
_elput_input_init_notify(void * data EINA_UNUSED,Ecore_Thread * eth EINA_UNUSED,void * msg_data)385 _elput_input_init_notify(void *data EINA_UNUSED, Ecore_Thread *eth EINA_UNUSED, void *msg_data)
386 {
387    Elput_Async_Open *ao = msg_data;
388 
389    ao->manager->interface->open_async(ao->manager, ao->path, ao->flags);
390    free(ao->path);
391    free(ao);
392 }
393 
394 static void
_elput_input_init_thread(void * data,Ecore_Thread * eth EINA_UNUSED)395 _elput_input_init_thread(void *data, Ecore_Thread *eth EINA_UNUSED)
396 {
397    Elput_Manager *manager = data;
398    struct udev *udev;
399 
400    udev = udev_new();
401 
402    manager->input.lib =
403      libinput_udev_create_context(&_input_interface, manager, udev);
404    if (!manager->input.lib)
405      {
406         ERR("libinput could not create udev context");
407         return;
408      }
409    udev_unref(udev);
410 
411    if (libinput_udev_assign_seat(manager->input.lib, manager->seat))
412      {
413         ERR("libinput could not assign udev seat");
414         libinput_unref(manager->input.lib);
415         manager->input.lib = NULL;
416      }
417 }
418 
419 void
_elput_input_enable(Elput_Manager * manager)420 _elput_input_enable(Elput_Manager *manager)
421 {
422    if (!manager->input.hdlr)
423      {
424         manager->input.hdlr =
425           ecore_main_fd_handler_add(libinput_get_fd(manager->input.lib),
426                                     ECORE_FD_READ, _cb_input_dispatch,
427                                     &manager->input, NULL, NULL);
428      }
429 
430    if (manager->input.suspended)
431      {
432         if (libinput_resume(manager->input.lib) != 0) return;
433         manager->input.suspended = EINA_FALSE;
434         _process_events(&manager->input);
435      }
436 }
437 
438 void
_elput_input_disable(Elput_Manager * manager)439 _elput_input_disable(Elput_Manager *manager)
440 {
441    Elput_Seat *seat;
442    Eina_List *l;
443 
444    EINA_LIST_FOREACH(manager->input.seats, l, seat)
445      seat->pending_motion = 1;
446    if (manager->input.lib) libinput_suspend(manager->input.lib);
447    _process_events(&manager->input);
448    manager->input.suspended = EINA_TRUE;
449 }
450 
451 EAPI Eina_Bool
elput_input_init(Elput_Manager * manager)452 elput_input_init(Elput_Manager *manager)
453 {
454    EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE);
455    EINA_SAFETY_ON_TRUE_RETURN_VAL(!!manager->input.hdlr, EINA_TRUE);
456 
457    memset(&manager->input, 0, sizeof(Elput_Input));
458    manager->input.thread =
459      ecore_thread_feedback_run(_elput_input_init_thread,
460                                _elput_input_init_notify,
461                                _elput_input_init_end,
462                                _elput_input_init_cancel, manager, 1);
463    return !!manager->input.thread;
464 }
465 
466 EAPI void
elput_input_shutdown(Elput_Manager * manager)467 elput_input_shutdown(Elput_Manager *manager)
468 {
469    Elput_Seat *seat;
470    Eina_List *l, *ll;
471 
472    EINA_SAFETY_ON_NULL_RETURN(manager);
473 
474    ecore_main_fd_handler_del(manager->input.hdlr);
475 
476    EINA_LIST_FOREACH_SAFE(manager->input.seats, l, ll, seat)
477      _udev_seat_destroy(seat);
478 
479    if (manager->input.thread)
480      ecore_thread_cancel(manager->input.thread);
481    else
482      {
483         libinput_unref(manager->input.lib);
484         manager->input.lib = NULL;
485      }
486 }
487 
488 EAPI void
elput_input_pointer_xy_get(Elput_Manager * manager,const char * seat,int * x,int * y)489 elput_input_pointer_xy_get(Elput_Manager *manager, const char *seat, int *x, int *y)
490 {
491    Elput_Seat *eseat;
492    Eina_List *l;
493 
494    if (x) *x = 0;
495    if (y) *y = 0;
496 
497    EINA_SAFETY_ON_NULL_RETURN(manager);
498 
499    /* if no seat name is passed in, just use default seat name */
500    if (!seat) seat = "seat0";
501 
502    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
503      {
504         if (!eina_streq(eseat->name, seat)) continue;
505         if (x) *x = eseat->pointer.x;
506         if (y) *y = eseat->pointer.y;
507         return;
508      }
509 }
510 
511 EAPI void
elput_input_pointer_xy_set(Elput_Manager * manager,const char * seat,int x,int y)512 elput_input_pointer_xy_set(Elput_Manager *manager, const char *seat, int x, int y)
513 {
514    Elput_Seat *eseat;
515    Elput_Device *edev;
516    Eina_List *l, *ll;
517 
518    EINA_SAFETY_ON_NULL_RETURN(manager);
519 
520    /* if no seat name is passed in, just use default seat name */
521    if (!seat) seat = "seat0";
522 
523    if (eina_list_count(manager->input.seats) < 1)
524      {
525         manager->pending_ptr_x = x;
526         manager->pending_ptr_y = y;
527         return;
528      }
529 
530    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
531      {
532         if (!eseat->ptr) continue;
533         if ((eseat->name) && (strcmp(eseat->name, seat)))
534           continue;
535 
536         eseat->pointer.x = x;
537         eseat->pointer.y = y;
538         eseat->ptr->timestamp = ecore_loop_time_get();
539 
540         EINA_LIST_FOREACH(eseat->devices, ll, edev)
541           {
542              if (!libinput_device_has_capability(edev->device,
543                                                  LIBINPUT_DEVICE_CAP_POINTER))
544                continue;
545 
546              _evdev_pointer_motion_send(edev);
547              break;
548           }
549      }
550 }
551 
552 EAPI Eina_Bool
elput_input_pointer_left_handed_set(Elput_Manager * manager,const char * seat,Eina_Bool left)553 elput_input_pointer_left_handed_set(Elput_Manager *manager, const char *seat, Eina_Bool left)
554 {
555    Elput_Seat *eseat;
556    Elput_Device *edev;
557    Eina_List *l, *ll;
558 
559    EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE);
560 
561    /* if no seat name is passed in, just use default seat name */
562    if (!seat) seat = "seat0";
563 
564    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
565      {
566         if ((eseat->name) && (strcmp(eseat->name, seat)))
567           continue;
568 
569         EINA_LIST_FOREACH(eseat->devices, ll, edev)
570           {
571              if (!libinput_device_has_capability(edev->device,
572                                                  LIBINPUT_DEVICE_CAP_POINTER))
573                continue;
574 
575              if (edev->left_handed == left) continue;
576 
577              if (libinput_device_config_left_handed_set(edev->device,
578                                                         (int)left) !=
579                  LIBINPUT_CONFIG_STATUS_SUCCESS)
580                {
581                   WRN("Failed to set left handed mode for device: %s",
582                       libinput_device_get_name(edev->device));
583                   continue;
584                }
585              else
586                edev->left_handed = !!left;
587           }
588      }
589 
590    return EINA_TRUE;
591 }
592 
593 EAPI void
elput_input_pointer_max_set(Elput_Manager * manager,int maxw,int maxh)594 elput_input_pointer_max_set(Elput_Manager *manager, int maxw, int maxh)
595 {
596    EINA_SAFETY_ON_NULL_RETURN(manager);
597    manager->input.pointer_w = maxw;
598    manager->input.pointer_h = maxh;
599 }
600 
601 EAPI Eina_Bool
elput_input_pointer_rotation_set(Elput_Manager * manager,int rotation)602 elput_input_pointer_rotation_set(Elput_Manager *manager, int rotation)
603 {
604    Elput_Seat *eseat;
605    Elput_Device *edev;
606    Eina_List *l, *ll;
607 
608    EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE);
609 
610    if ((rotation % 90 != 0) || (rotation / 90 > 3) || (rotation < 0))
611      return EINA_FALSE;
612 
613    manager->input.rotation = rotation;
614 
615    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
616      {
617         EINA_LIST_FOREACH(eseat->devices, ll, edev)
618           {
619              if (!(edev->caps & ELPUT_DEVICE_CAPS_POINTER)) continue;
620 
621              switch (rotation)
622                {
623                 case 0:
624                   edev->swap = EINA_FALSE;
625                   edev->invert_x = EINA_FALSE;
626                   edev->invert_y = EINA_FALSE;
627                   break;
628                 case 90:
629                   edev->swap = EINA_TRUE;
630                   edev->invert_x = EINA_FALSE;
631                   edev->invert_y = EINA_TRUE;
632                   break;
633                 case 180:
634                   edev->swap = EINA_FALSE;
635                   edev->invert_x = EINA_TRUE;
636                   edev->invert_y = EINA_TRUE;
637                   break;
638                 case 270:
639                   edev->swap = EINA_TRUE;
640                   edev->invert_x = EINA_TRUE;
641                   edev->invert_y = EINA_FALSE;
642                   break;
643                 default:
644                   break;
645                }
646           }
647      }
648 
649    return EINA_TRUE;
650 }
651 
652 EAPI void
elput_input_devices_calibrate(Elput_Manager * manager,int w,int h)653 elput_input_devices_calibrate(Elput_Manager *manager, int w, int h)
654 {
655    Elput_Seat *eseat;
656    Elput_Device *edev;
657    Eina_List *l, *ll;
658 
659    EINA_SAFETY_ON_NULL_RETURN(manager);
660 
661    manager->output_w = w;
662    manager->output_h = h;
663 
664    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
665      {
666         EINA_LIST_FOREACH(eseat->devices, ll, edev)
667           {
668              edev->ow = w;
669              edev->oh = h;
670              _evdev_device_calibrate(edev);
671           }
672      }
673 }
674 
675 EAPI Eina_Bool
elput_input_key_remap_enable(Elput_Manager * manager,Eina_Bool enable)676 elput_input_key_remap_enable(Elput_Manager *manager, Eina_Bool enable)
677 {
678    Elput_Seat *eseat;
679    Elput_Device *edev;
680    Eina_List *l, *ll;
681 
682    EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE);
683 
684    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
685      {
686         EINA_LIST_FOREACH(eseat->devices, ll, edev)
687           {
688              if (!(edev->caps & ELPUT_DEVICE_CAPS_KEYBOARD)) continue;
689 
690              edev->key_remap = enable;
691              if ((!enable) && (edev->key_remap_hash))
692                {
693                   eina_hash_free(edev->key_remap_hash);
694                   edev->key_remap_hash = NULL;
695                }
696           }
697      }
698 
699    return EINA_TRUE;
700 }
701 
702 EAPI Eina_Bool
elput_input_key_remap_set(Elput_Manager * manager,int * from_keys,int * to_keys,int num)703 elput_input_key_remap_set(Elput_Manager *manager, int *from_keys, int *to_keys, int num)
704 {
705    Elput_Seat *eseat;
706    Elput_Device *edev;
707    Eina_List *l, *ll;
708    int i = 0;
709 
710    EINA_SAFETY_ON_NULL_RETURN_VAL(manager, EINA_FALSE);
711    EINA_SAFETY_ON_NULL_RETURN_VAL(from_keys, EINA_FALSE);
712    EINA_SAFETY_ON_NULL_RETURN_VAL(to_keys, EINA_FALSE);
713    EINA_SAFETY_ON_TRUE_RETURN_VAL((num <= 0), EINA_FALSE);
714 
715    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
716      {
717         EINA_LIST_FOREACH(eseat->devices, ll, edev)
718           {
719              if (!(edev->caps & ELPUT_DEVICE_CAPS_KEYBOARD)) continue;
720 
721              if (!edev->key_remap) continue;
722              if (!edev->key_remap_hash)
723                edev->key_remap_hash = eina_hash_int32_new(NULL);
724              if (!edev->key_remap_hash) continue;
725 
726              for (i = 0; i < num; i++)
727                {
728                   if ((!from_keys[i]) || (!to_keys[i]))
729                     continue;
730                }
731 
732              for (i = 0; i < num; i++)
733                eina_hash_add(edev->key_remap_hash, &from_keys[i],
734                              (void *)(intptr_t)to_keys[i]);
735           }
736      }
737 
738    return EINA_TRUE;
739 }
740 
741 EAPI void
elput_input_keyboard_info_set(Elput_Manager * manager,void * context,void * keymap,int group)742 elput_input_keyboard_info_set(Elput_Manager *manager, void *context, void *keymap, int group)
743 {
744    Eina_List *l;
745    Elput_Seat *seat;
746 
747    EINA_SAFETY_ON_NULL_RETURN(manager);
748    EINA_SAFETY_ON_FALSE_RETURN((!!context) == (!!keymap));
749 
750    if ((manager->cached.context == context) &&
751        (manager->cached.keymap == keymap))
752      return;
753    if (context) xkb_context_ref(context);
754    if (keymap) xkb_keymap_ref(keymap);
755    if (manager->cached.context) xkb_context_unref(manager->cached.context);
756    if (manager->cached.keymap) xkb_keymap_unref(manager->cached.keymap);
757    manager->cached.context = context;
758    manager->cached.keymap = keymap;
759    manager->cached.group = group;
760    EINA_LIST_FOREACH(manager->input.seats, l, seat)
761      _keyboard_keymap_update(seat);
762 }
763 
764 EAPI void
elput_input_keyboard_group_set(Elput_Manager * manager,int group)765 elput_input_keyboard_group_set(Elput_Manager *manager, int group)
766 {
767    Eina_List *l;
768    Elput_Seat *seat;
769    EINA_SAFETY_ON_NULL_RETURN(manager);
770 
771    if (manager->cached.group == group) return;
772    manager->cached.group = group;
773    EINA_LIST_FOREACH(manager->input.seats, l, seat)
774      _keyboard_group_update(seat);
775 }
776 
777 EAPI void
elput_input_pointer_accel_profile_set(Elput_Manager * manager,const char * seat,uint32_t profile)778 elput_input_pointer_accel_profile_set(Elput_Manager *manager, const char *seat, uint32_t profile)
779 {
780    Elput_Seat *eseat;
781    Elput_Device *edev;
782    Eina_List *l, *ll;
783 
784    EINA_SAFETY_ON_NULL_RETURN(manager);
785 
786    /* if no seat name is passed in, just use default seat name */
787    if (!seat) seat = "seat0";
788 
789    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
790      {
791         if ((eseat->name) && (strcmp(eseat->name, seat)))
792           continue;
793 
794         EINA_LIST_FOREACH(eseat->devices, ll, edev)
795           {
796              if (!libinput_device_has_capability(edev->device,
797                                                  LIBINPUT_DEVICE_CAP_POINTER))
798                continue;
799 
800              if (libinput_device_config_accel_set_profile(edev->device,
801                                                           profile) !=
802                  LIBINPUT_CONFIG_STATUS_SUCCESS)
803                {
804                   WRN("Failed to set acceleration profile for device: %s",
805                       libinput_device_get_name(edev->device));
806                   continue;
807                }
808           }
809      }
810 }
811 
812 EAPI void
elput_input_pointer_accel_speed_set(Elput_Manager * manager,const char * seat,double speed)813 elput_input_pointer_accel_speed_set(Elput_Manager *manager, const char *seat, double speed)
814 {
815    Elput_Seat *eseat;
816    Elput_Device *edev;
817    Eina_List *l, *ll;
818 
819    EINA_SAFETY_ON_NULL_RETURN(manager);
820 
821    /* if no seat name is passed in, just use default seat name */
822    if (!seat) seat = "seat0";
823 
824    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
825      {
826         if ((eseat->name) && (strcmp(eseat->name, seat)))
827           continue;
828 
829         EINA_LIST_FOREACH(eseat->devices, ll, edev)
830           {
831              if (!libinput_device_has_capability(edev->device,
832                                                  LIBINPUT_DEVICE_CAP_POINTER))
833                continue;
834 
835              if (!libinput_device_config_accel_is_available(edev->device))
836                continue;
837 
838              if (libinput_device_config_accel_set_speed(edev->device,
839                                                         speed) !=
840                  LIBINPUT_CONFIG_STATUS_SUCCESS)
841                {
842                   WRN("Failed to set acceleration speed for device: %s",
843                       libinput_device_get_name(edev->device));
844                   continue;
845                }
846           }
847      }
848 }
849 
850 EAPI void
elput_input_touch_tap_to_click_enabled_set(Elput_Manager * manager,const char * seat,Eina_Bool enabled)851 elput_input_touch_tap_to_click_enabled_set(Elput_Manager *manager, const char *seat, Eina_Bool enabled)
852 {
853    Elput_Seat *eseat;
854    Elput_Device *edev;
855    Eina_List *l, *ll;
856    enum libinput_config_tap_state state;
857 
858    EINA_SAFETY_ON_NULL_RETURN(manager);
859 
860    state = enabled ? LIBINPUT_CONFIG_TAP_ENABLED : LIBINPUT_CONFIG_TAP_DISABLED;
861 
862    /* if no seat name is passed in, just use default seat name */
863    if (!seat) seat = "seat0";
864 
865    EINA_LIST_FOREACH(manager->input.seats, l, eseat)
866      {
867         if ((eseat->name) && (strcmp(eseat->name, seat)))
868           continue;
869 
870         EINA_LIST_FOREACH(eseat->devices, ll, edev)
871           {
872              if (!libinput_device_has_capability(edev->device,
873                                                  LIBINPUT_DEVICE_CAP_POINTER))
874                continue;
875 
876              if (libinput_device_config_tap_set_enabled(edev->device, state)
877                  != LIBINPUT_CONFIG_STATUS_SUCCESS)
878                {
879                   WRN("Failed to %s tap-to-click on device: %s",
880                       enabled ? "enable" : "disable",
881                       libinput_device_get_name(edev->device));
882                   continue;
883                }
884           }
885      }
886 }
887 
888 EAPI Elput_Seat *
elput_device_seat_get(const Elput_Device * dev)889 elput_device_seat_get(const Elput_Device *dev)
890 {
891    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL);
892    return dev->seat;
893 }
894 
895 EAPI Elput_Device_Caps
elput_device_caps_get(const Elput_Device * dev)896 elput_device_caps_get(const Elput_Device *dev)
897 {
898    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, 0);
899    return dev->caps;
900 }
901 
902 EAPI Eina_Stringshare *
elput_device_output_name_get(Elput_Device * device)903 elput_device_output_name_get(Elput_Device *device)
904 {
905    EINA_SAFETY_ON_NULL_RETURN_VAL(device, NULL);
906 
907    return device->output_name;
908 }
909 
910 EAPI const Eina_List *
elput_seat_devices_get(const Elput_Seat * seat)911 elput_seat_devices_get(const Elput_Seat *seat)
912 {
913    EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
914    return seat->devices;
915 }
916 
917 EAPI Eina_Stringshare *
elput_seat_name_get(const Elput_Seat * seat)918 elput_seat_name_get(const Elput_Seat *seat)
919 {
920    EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
921    return seat->name;
922 }
923 
924 EAPI Elput_Manager *
elput_seat_manager_get(const Elput_Seat * seat)925 elput_seat_manager_get(const Elput_Seat *seat)
926 {
927    EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
928    return seat->manager;
929 }
930