e_input: fix not to do unnecessary udev-lookups and loops
[platform/upstream/enlightenment.git] / src / bin / e_input_device.c
1 #include "e.h"
2 #include "e_input_private.h"
3
4 /* e_input_device private variable */
5 static Eina_List *einput_devices;
6 static E_Input_Device *e_input_device_default = NULL;
7
8 static int
9 _device_open_no_pending(const char *device, int flags)
10 {
11    int fd = -1;
12    struct stat s;
13
14    fd = open(device, flags | O_CLOEXEC);
15
16    if (fd < 0) return fd;
17    if (fstat(fd, &s) == -1)
18      {
19         close(fd);
20         return -1;
21      }
22
23    return fd;
24 }
25
26 static void
27 _device_close(const char *device, int fd)
28 {
29    if (fd >= 0)
30      close(fd);
31 }
32
33 /* local functions */
34 static int
35 _e_input_device_cb_open_restricted(const char *path, int flags, void *data)
36 {
37    E_Input_Backend *input;
38    int fd = -1;
39
40    if (!(input = data)) return -1;
41
42    /* try to open the device */
43    fd = _device_open_no_pending(path, flags);
44
45    if (fd < 0)
46      {
47         ERR("Could not open device");
48         return -1;
49      }
50
51    if (input->dev->fd_hash)
52      eina_hash_add(input->dev->fd_hash, path, (void *)(intptr_t)fd);
53
54    return fd;
55 }
56
57 static void
58 _e_input_device_cb_close_restricted(int fd, void *data)
59 {
60    if (fd >= 0) close(fd);
61 }
62
63 const struct libinput_interface _input_interface =
64 {
65    _e_input_device_cb_open_restricted,
66    _e_input_device_cb_close_restricted,
67 };
68
69 static E_Input_Device *
70 _e_input_device_default_get(void)
71 {
72    return e_input_device_default;
73 }
74
75 struct xkb_context *
76 _e_input_device_cached_context_get(enum xkb_context_flags flags)
77 {
78    if (!cached_context)
79      return xkb_context_new(flags);
80    else
81      return xkb_context_ref(cached_context);
82 }
83
84 struct xkb_keymap *
85 _e_input_device_cached_keymap_get(struct xkb_context *ctx,
86                        const struct xkb_rule_names *names,
87                        enum xkb_keymap_compile_flags flags)
88 {
89    EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
90
91    if (!cached_keymap)
92      return xkb_map_new_from_names(ctx, names, flags);
93    else
94      return xkb_map_ref(cached_keymap);
95 }
96
97 void
98 _e_input_device_cached_context_update(struct xkb_context *ctx)
99 {
100    Eina_List *l;
101    E_Input_Device *dev;
102
103    EINA_LIST_FOREACH(einput_devices, l, dev)
104      {
105         xkb_context_unref(dev->xkb_ctx);
106         dev->xkb_ctx = xkb_context_ref(ctx);
107      }
108 }
109
110 void
111 _e_input_device_cached_keymap_update(struct xkb_keymap *map)
112 {
113    Eina_List *l, *l2, *l3;
114    E_Input_Device *dev;
115    E_Input_Seat *seat;
116    E_Input_Evdev *edev;
117
118    EINA_LIST_FOREACH(einput_devices, l, dev)
119      EINA_LIST_FOREACH(dev->seats, l2, seat)
120        EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l3, edev)
121          {
122             xkb_keymap_unref(edev->xkb.keymap);
123             edev->xkb.keymap = xkb_keymap_ref(map);
124             xkb_state_unref(edev->xkb.state);
125             edev->xkb.state = xkb_state_new(map);
126          }
127 }
128
129 EINTERN void
130 e_input_device_keyboard_cached_context_set(struct xkb_context *ctx)
131 {
132    EINA_SAFETY_ON_NULL_RETURN(ctx);
133
134    if (cached_context == ctx) return;
135
136    if (cached_context)
137      _e_input_device_cached_context_update(ctx);
138
139    cached_context = ctx;
140 }
141
142 EINTERN void
143 e_input_device_keyboard_cached_keymap_set(struct xkb_keymap *map)
144 {
145    EINA_SAFETY_ON_NULL_RETURN(map);
146
147    if (cached_keymap == map) return;
148
149    if (cached_keymap)
150       _e_input_device_cached_keymap_update(map);
151
152    cached_keymap = map;
153 }
154
155 static void
156 e_input_device_destroy(E_Input_Device *dev)
157 {
158    E_Input_Backend *input;
159    E_Input_Seat *seat;
160    E_Input_Evdev *edev;
161
162    EINA_SAFETY_ON_NULL_RETURN(dev);
163
164    EINA_LIST_FREE(dev->seats, seat)
165      {
166         EINA_LIST_FREE(seat->devices, edev)
167           {
168              if (edev->fd >= 0)
169                close(edev->fd);
170              _e_input_evdev_device_destroy(edev);
171           }
172
173         if (seat->name)
174           eina_stringshare_del(seat->name);
175         free(seat);
176      }
177
178    EINA_LIST_FREE(dev->inputs, input)
179      {
180         if (input->hdlr)
181           ecore_main_fd_handler_del(input->hdlr);
182         if (input->libinput)
183           libinput_unref(input->libinput);
184         free(input);
185      }
186
187    eina_stringshare_del(dev->seat);
188    xkb_context_unref(dev->xkb_ctx);
189    eina_hash_free(dev->fd_hash);
190    dev->fd_hash = NULL;
191
192    if (dev == e_input_device_default)
193      e_input_device_default = NULL;
194
195    free(dev);
196 }
197
198 static void
199 _e_input_device_add_list(E_Input_Device *dev)
200 {
201    Eina_List *l;
202    E_Input_Device *dev_data;
203
204    EINA_LIST_FOREACH(einput_devices, l, dev_data)
205      {
206         if (dev_data == dev) return;
207      }
208
209    einput_devices = eina_list_append(einput_devices, dev);
210 }
211
212 static void
213 _e_input_device_remove_list(E_Input_Device *dev)
214 {
215    Eina_List *l, *l_next;
216    E_Input_Device *dev_data;
217
218    EINA_LIST_FOREACH_SAFE(einput_devices, l, l_next, dev_data)
219      {
220         if (dev == dev_data)
221           einput_devices = eina_list_remove_list(einput_devices, l);
222      }
223 }
224
225 EINTERN E_Input_Device *
226 e_input_device_open(void)
227 {
228    E_Input_Device *dev = NULL;
229
230    dev = (E_Input_Device *)calloc(1, sizeof(E_Input_Device));
231
232    if (!dev)
233      {
234         EINA_LOG_ERR("Failed to alloc memory for E_Input_Device\n");
235         return NULL;
236      }
237
238    dev->seat = eina_stringshare_add("seat0");
239    dev->fd_hash = eina_hash_string_superfast_new(NULL);
240
241    /* try to create xkb context */
242    if (!(dev->xkb_ctx = _e_input_device_cached_context_get(0)))
243      {
244         ERR("Failed to create xkb context: %m");
245         goto err;
246      }
247
248    if (!e_input_device_default)
249      e_input_device_default = dev;
250
251    _e_input_device_add_list(dev);
252
253    return dev;
254
255 err:
256    if (dev)
257      {
258         eina_stringshare_del(dev->seat);
259         xkb_context_unref(dev->xkb_ctx);
260         free(dev);
261      }
262
263    return NULL;
264 }
265
266 EINTERN Eina_Bool
267 e_input_device_close(E_Input_Device *dev)
268 {
269    /* check for valid device */
270    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
271
272    _e_input_device_remove_list(dev);
273    e_input_device_destroy(dev);
274
275    return EINA_TRUE;
276 }
277
278 EINTERN void
279 e_input_device_window_set(E_Input_Device *dev, unsigned int window)
280 {
281    /* check for valid device */
282    EINA_SAFETY_ON_TRUE_RETURN(!dev);
283
284    /* TODO : Must update window of ecore/evas device when the given window */
285    /*        is not equal to the existing window. */
286
287    dev->window = window;
288 }
289
290 EINTERN void
291 e_input_device_pointer_xy_get(E_Input_Device *dev, int *x, int *y)
292 {
293    E_Input_Seat *seat;
294    E_Input_Evdev *edev;
295    Eina_List *l, *ll;
296
297    if (x) *x = 0;
298    if (y) *y = 0;
299
300    if (!dev)
301      dev = _e_input_device_default_get();
302
303    /* check for valid device */
304    EINA_SAFETY_ON_TRUE_RETURN(!dev);
305    EINA_LIST_FOREACH(dev->seats, l, seat)
306      {
307         EINA_LIST_FOREACH(seat->devices, ll, edev)
308           {
309              if (!libinput_device_has_capability(edev->device,
310                                                  LIBINPUT_DEVICE_CAP_POINTER))
311                continue;
312
313              if (x) *x = seat->ptr.dx;
314              if (y) *y = seat->ptr.dy;
315
316              return;
317           }
318      }
319 }
320
321 E_API void
322 e_input_device_pointer_warp(E_Input_Device *dev, int x, int y)
323 {
324    E_Input_Seat *seat;
325    E_Input_Evdev *edev;
326    Eina_List *l, *ll;
327
328    if (!dev)
329      dev = _e_input_device_default_get();
330
331    /* check for valid device */
332    EINA_SAFETY_ON_TRUE_RETURN(!dev);
333    EINA_LIST_FOREACH(dev->seats, l, seat)
334      {
335         EINA_LIST_FOREACH(seat->devices, ll, edev)
336           {
337              if (!libinput_device_has_capability(edev->device,
338                                                  LIBINPUT_DEVICE_CAP_POINTER))
339                continue;
340
341              seat->ptr.dx = seat->ptr.ix = x;
342              seat->ptr.dy = seat->ptr.iy = y;
343              _e_input_pointer_motion_post(edev);
344           }
345      }
346 }
347
348 EINTERN Eina_Bool
349 e_input_device_pointer_left_handed_set(E_Input_Device *dev, Eina_Bool left_handed)
350 {
351    E_Input_Seat *seat = NULL;
352    E_Input_Evdev *edev = NULL;
353    Eina_List *l = NULL, *l2 = NULL;
354
355    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
356    EINA_SAFETY_ON_NULL_RETURN_VAL(dev->seats, EINA_FALSE);
357
358    if (dev->left_handed == left_handed)
359      return EINA_TRUE;
360    dev->left_handed = left_handed;
361
362    EINA_LIST_FOREACH(dev->seats, l, seat)
363      {
364         EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l2, edev)
365           {
366              if (libinput_device_has_capability(edev->device,
367                                                 LIBINPUT_DEVICE_CAP_POINTER))
368                {
369                   if (libinput_device_config_left_handed_set(edev->device, (int)left_handed) !=
370                       LIBINPUT_CONFIG_STATUS_SUCCESS)
371                     {
372                        WRN("Failed to set left hand mode about device: %s\n",
373                            libinput_device_get_name(edev->device));
374                        continue;
375                     }
376                }
377           }
378      }
379    return EINA_TRUE;
380 }
381
382
383 EINTERN Eina_Bool
384 e_input_device_pointer_rotation_set(E_Input_Device *dev, int rotation)
385 {
386    E_Input_Seat *seat = NULL;
387    Eina_List *l = NULL;
388
389    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
390    EINA_SAFETY_ON_NULL_RETURN_VAL(dev->seats, EINA_FALSE);
391
392    if ((rotation % 90 != 0) || (rotation / 90 > 3) || (rotation < 0)) return EINA_FALSE;
393
394    EINA_LIST_FOREACH(dev->seats, l, seat)
395      {
396         switch (rotation)
397           {
398            case 90:
399               seat->ptr.swap = EINA_TRUE;
400               seat->ptr.invert_x = EINA_FALSE;
401               seat->ptr.invert_y = EINA_TRUE;
402               break;
403            case 180:
404               seat->ptr.swap = EINA_FALSE;
405               seat->ptr.invert_x = EINA_TRUE;
406               seat->ptr.invert_y = EINA_TRUE;
407               break;
408            case 270:
409               seat->ptr.swap = EINA_TRUE;
410               seat->ptr.invert_x = EINA_TRUE;
411               seat->ptr.invert_y = EINA_FALSE;
412                 break;
413            case 0:
414               seat->ptr.swap = EINA_FALSE;
415               seat->ptr.invert_x = EINA_FALSE;
416               seat->ptr.invert_y = EINA_FALSE;
417               break;
418            default:
419               break;
420           }
421      }
422    return EINA_TRUE;
423 }
424
425 EINTERN void
426 e_input_device_rotation_set(E_Input_Device *dev, unsigned int rotation)
427 {
428    E_Input_Seat *seat = NULL;
429    E_Input_Evdev *edev = NULL;
430    Eina_List *l = NULL, *l2 = NULL;
431    int temp;
432
433    EINA_SAFETY_ON_NULL_RETURN(dev);
434    EINA_SAFETY_ON_NULL_RETURN(dev->seats);
435
436    EINA_LIST_FOREACH(dev->seats, l, seat)
437      {
438         EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l2, edev)
439           {
440              if (libinput_device_has_capability(edev->device,
441                                       LIBINPUT_DEVICE_CAP_POINTER))
442                {
443                   edev->mouse.minx = edev->mouse.miny = 0;
444                   e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen),
445                                        &edev->mouse.maxw, &edev->mouse.maxh);
446
447                   if (rotation == 90 || rotation == 270)
448                     {
449                        temp = edev->mouse.minx;
450                        edev->mouse.minx = edev->mouse.miny;
451                        edev->mouse.miny = temp;
452
453                        temp = edev->mouse.maxw;
454                        edev->mouse.maxw = edev->mouse.maxh;
455                        edev->mouse.maxh = temp;
456                     }
457                }
458           }
459      }
460 }
461
462 static void
463 _e_input_device_touch_matrix_identify(float result[6])
464 {
465    result[0] = 1.0;
466    result[1] = 0.0;
467    result[2] = 0.0;
468    result[3] = 0.0;
469    result[4] = 1.0;
470    result[5] = 0.0;
471 }
472
473 static void
474 _e_input_device_touch_matrix_mulifly(float result[6], float m1[6], float m2[6])
475 {
476    result[0] = m1[0] * m2 [0] + m1[1] * m2[3];
477    result[1] = m1[0] * m2 [1] + m1[1] * m2[4];
478    result[2] = m1[0] * m2 [2] + m1[1] * m2[5] + m1[2];
479    result[3] = m1[3] * m2 [0] + m1[4] * m2[3];
480    result[4] = m1[3] * m2 [1] + m1[4] * m2[4];
481    result[5] = m1[3] * m2 [2] + m1[4] * m2[5] + m1[5];
482 }
483
484 static void
485 _e_input_device_touch_matrix_rotation_get(float result[6], int degree, float w, float h)
486 {
487    if (w == 0.0) w = 1.0;
488    if (h == 0.0) h = 1.0;
489
490    switch (degree)
491      {
492         case 90:
493           result[0] = 0.0;
494           result[1] = -h/w;
495           result[2] = h/w;
496           result[3] = w/h;
497           result[4] = 0.0;
498           result[5] = 0.0;
499           break;
500         case 180:
501           result[0] = -1.0;
502           result[1] = 0.0;
503           result[2] = 1.0;
504           result[3] = 0.0;
505           result[4] = -1.0;
506           result[5] = 1.0;
507           break;
508         case 270:
509           result[0] = 0.0;
510           result[1] = h/w;
511           result[2] = 0.0;
512           result[3] = -w/h;
513           result[4] = 0.0;
514           result[5] = w/h;
515           break;
516         case 0:
517           _e_input_device_touch_matrix_identify(result);
518           break;
519         default:
520           WRN("Please input valid angle(%d)\n", degree);
521      }
522 }
523
524 static void
525 _e_input_device_touch_matrix_translate_get(float result[6], float x, float y, float w, float h, float default_w, float default_h)
526 {
527    if (default_w == 0.0) default_w = 1.0;
528    if (default_h == 0.0) default_h = 1.0;
529
530    result[0] = w / default_w;
531    result[4] = h / default_h;
532    result[2] = x / default_w;
533    result[5] = y / default_h;
534 }
535
536 EINTERN Eina_Bool
537 e_input_device_touch_rotation_set(E_Input_Device *dev, unsigned int rotation)
538 {
539    E_Input_Seat *seat = NULL;
540    E_Input_Evdev *edev = NULL;
541    Eina_List *l = NULL, *l2 = NULL;
542    float mat_translate[6] = {0.0, }, mat_rotation[6] = {0.0, }, result[6] = {0.0, };
543    float default_w = 0.0, default_h = 0.0;
544    Eina_Bool res = EINA_TRUE;
545    int output_w = 0, output_h = 0;
546
547    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
548    EINA_SAFETY_ON_NULL_RETURN_VAL(dev->seats, EINA_FALSE);
549
550    e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen), &output_w, &output_h);
551    default_w = (float)output_w;
552    default_h = (float)output_h;
553
554    EINA_LIST_FOREACH(dev->seats, l, seat)
555      {
556         EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l2, edev)
557           {
558              if (edev->caps & E_INPUT_SEAT_TOUCH)
559                {
560                   _e_input_device_touch_matrix_identify(mat_translate);
561                   _e_input_device_touch_matrix_identify(mat_rotation);
562                   _e_input_device_touch_matrix_identify(result);
563
564                   if (edev->touch.transform.x || edev->touch.transform.y ||
565                       edev->touch.transform.w || edev->touch.transform.h)
566                     {
567                        _e_input_device_touch_matrix_translate_get(mat_translate,
568                                                                     (float)edev->touch.transform.x,
569                                                                     (float)edev->touch.transform.y,
570                                                                     (float)edev->touch.transform.w,
571                                                                     (float)edev->touch.transform.h,
572                                                                     default_w, default_h);
573
574                     }
575
576                   _e_input_device_touch_matrix_rotation_get(mat_rotation, rotation, default_w, default_h);
577
578                   _e_input_device_touch_matrix_mulifly(result, mat_translate, mat_rotation);
579
580                   if (!e_input_evdev_touch_calibration_set(edev, result))
581                     {
582                        res = EINA_FALSE;
583                        continue;
584                     }
585                   else
586                     {
587                        edev->touch.transform.rotation = rotation;
588                     }
589                }
590           }
591      }
592
593    return res;
594 }
595
596 EINTERN Eina_Bool
597 e_input_device_touch_transformation_set(E_Input_Device *dev, int offset_x, int offset_y, int w, int h)
598 {
599    E_Input_Seat *seat = NULL;
600    E_Input_Evdev *edev = NULL;
601    Eina_List *l = NULL, *l2 = NULL;
602    float mat_translate[6] = {0.0, }, mat_rotation[6] = {0.0 }, result[6] = {0.0, };
603    float default_w = 0.0, default_h = 0.0;
604    Eina_Bool res = EINA_TRUE;
605    int output_w = 0, output_h = 0;
606
607    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
608    EINA_SAFETY_ON_NULL_RETURN_VAL(dev->seats, EINA_FALSE);
609    EINA_SAFETY_ON_TRUE_RETURN_VAL((w == 0) || (h == 0), EINA_FALSE);
610
611    e_output_size_get(e_comp_screen_primary_output_get(e_comp->e_comp_screen), &output_w, &output_h);
612    default_w = (float)output_w;
613    default_h = (float)output_h;
614
615    EINA_LIST_FOREACH(dev->seats, l, seat)
616      {
617         EINA_LIST_FOREACH(e_input_seat_evdev_list_get(seat), l2, edev)
618           {
619              if (edev->caps & E_INPUT_SEAT_TOUCH)
620                {
621                   _e_input_device_touch_matrix_identify(mat_translate);
622                   _e_input_device_touch_matrix_identify(mat_rotation);
623                   _e_input_device_touch_matrix_identify(result);
624
625                   _e_input_device_touch_matrix_translate_get(mat_translate,
626                                                                (float)offset_x, (float)offset_y,
627                                                                (float)w, (float)h, default_w, default_h);
628
629                   if (edev->touch.transform.rotation)
630                     {
631                        _e_input_device_touch_matrix_rotation_get(mat_rotation,
632                                                                    edev->touch.transform.rotation,
633                                                                    default_w, default_h);
634                     }
635
636                   _e_input_device_touch_matrix_mulifly(result, mat_translate, mat_rotation);
637
638                   if (!e_input_evdev_touch_calibration_set(edev, result))
639                     {
640                        res = EINA_FALSE;
641                        continue;
642                     }
643                   else
644                     {
645                        edev->touch.transform.x = offset_x;
646                        edev->touch.transform.y = offset_y;
647                        edev->touch.transform.w = w;
648                        edev->touch.transform.h = h;
649                     }
650                }
651           }
652      }
653    return res;
654 }
655
656 static void
657 e_input_device_libinput_log_handler(struct libinput *libinput EINA_UNUSED,
658                                enum libinput_log_priority priority,
659                                const char *format, va_list args)
660 {
661    char buf[1024] = {0,};
662
663    vsnprintf(buf, 1024, format, args);
664    switch (priority)
665      {
666         case LIBINPUT_LOG_PRIORITY_DEBUG:
667            DBG("%s", buf);
668            break;
669         case LIBINPUT_LOG_PRIORITY_INFO:
670            INF("%s", buf);
671            break;
672         case LIBINPUT_LOG_PRIORITY_ERROR:
673            ERR("%s", buf);
674            break;
675         default:
676            break;
677      }
678 }
679
680 EINTERN Eina_Bool
681 e_input_device_input_backend_create(E_Input_Device *dev, E_Input_Libinput_Backend backend)
682 {
683    Eina_Bool res = EINA_FALSE;
684
685    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
686
687    if (backend == E_INPUT_LIBINPUT_BACKEND_UDEV)
688      {
689         TRACE_INPUT_BEGIN(e_input_device_input_create_libinput_udev);
690         res = e_input_device_input_create_libinput_udev(dev);
691         TRACE_INPUT_END();
692      }
693    else if (backend == E_INPUT_LIBINPUT_BACKEND_PATH)
694      {
695         TRACE_INPUT_BEGIN(e_input_device_input_create_libinput_path);
696         res = e_input_device_input_create_libinput_path(dev);
697         TRACE_INPUT_END();
698      }
699
700    return res;
701 }
702
703 /* public functions */
704 EINTERN Eina_Bool
705 e_input_device_input_create_libinput_udev(E_Input_Device *dev)
706 {
707    E_Input_Backend *input;
708    char *env;
709
710    /* check for valid device */
711    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
712
713    /* try to allocate space for new input structure */
714    if (!(input = calloc(1, sizeof(E_Input_Backend))))
715      {
716         return EINA_FALSE;
717      }
718
719    /* set reference for parent device */
720    input->dev = dev;
721
722    /* try to create libinput context */
723    input->libinput =
724      libinput_udev_create_context(&_input_interface, input, eeze_udev_get());
725    if (!input->libinput)
726      {
727         ERR("Could not create libinput context: %m");
728         goto err;
729      }
730
731    /* set libinput log priority */
732    if ((env = getenv(E_INPUT_ENV_LIBINPUT_LOG_DISABLE)) && (atoi(env) == 1))
733      libinput_log_set_handler(input->libinput, NULL);
734    else if ((env = getenv(E_INPUT_ENV_LIBINPUT_LOG_EINA_LOG)) && (atoi(env) == 1))
735      libinput_log_set_handler(input->libinput, e_input_device_libinput_log_handler);
736
737    libinput_log_set_priority(input->libinput, LIBINPUT_LOG_PRIORITY_INFO);
738
739    /* assign udev seat */
740    TRACE_INPUT_BEGIN(libinput_udev_assign_seat);
741    if (libinput_udev_assign_seat(input->libinput, dev->seat) != 0)
742      {
743         ERR("Failed to assign seat: %m");
744         TRACE_INPUT_END();
745         goto err;
746      }
747    TRACE_INPUT_END();
748
749    /* process pending events */
750    _input_events_process(input);
751
752    /* enable this input */
753    if (!e_input_enable_input(input))
754      {
755         ERR("Failed to enable input");
756         goto err;
757      }
758
759    /* append this input */
760    dev->inputs = eina_list_append(dev->inputs, input);
761
762    return EINA_TRUE;
763
764 err:
765    if (input->libinput) libinput_unref(input->libinput);
766    free(input);
767
768    return EINA_FALSE;
769 }
770
771 EINTERN Eina_Bool
772 e_input_device_input_create_libinput_path(E_Input_Device *dev)
773 {
774    E_Input_Backend *input;
775    struct libinput_device *device;
776    int devices_num = 0;
777    char *env;
778    Eina_Stringshare *path;
779
780    /* check for valid device */
781    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
782
783    if ((env = getenv("PATH_DEVICES_NUM")))
784      devices_num = atoi(env);
785    if (devices_num <= 0 || devices_num >= INT_MAX)
786      {
787         return EINA_TRUE;
788      }
789
790    INF("PATH_DEVICES_NUM : %d", devices_num);
791
792    /* try to allocate space for new input structure */
793    if (!(input = calloc(1, sizeof(E_Input_Backend))))
794      {
795         return EINA_FALSE;
796      }
797
798    /* set reference for parent device */
799    input->dev = dev;
800
801    /* try to create libinput context */
802    input->libinput =
803      libinput_path_create_context(&_input_interface, input);
804    if (!input->libinput)
805      {
806         ERR("Could not create libinput path context: %m");
807         goto err;
808      }
809
810    /* set libinput log priority */
811    if ((env = getenv(E_INPUT_ENV_LIBINPUT_LOG_DISABLE)) && (atoi(env) == 1))
812      libinput_log_set_handler(input->libinput, NULL);
813    else if ((env = getenv(E_INPUT_ENV_LIBINPUT_LOG_EINA_LOG)) && (atoi(env) == 1))
814      libinput_log_set_handler(input->libinput, e_input_device_libinput_log_handler);
815
816    libinput_log_set_priority(input->libinput, LIBINPUT_LOG_PRIORITY_INFO);
817
818    for (int i = 0; i < devices_num; i++)
819      {
820         char buf[1024] = "PATH_DEVICE_";
821         eina_convert_itoa(i + 1, buf + 12);
822         env = getenv(buf);
823         if (env)
824           {
825              path = eina_stringshare_add(env);
826              device = libinput_path_add_device(input->libinput, path);
827              if (!device)
828                ERR("Failed to initialized device %s", path);
829              else
830                INF("libinput_path created input device %s", path);
831           }
832      }
833
834    /* process pending events */
835    _input_events_process(input);
836
837    /* enable this input */
838    if (!e_input_enable_input(input))
839      {
840         ERR("Failed to enable input");
841         goto err;
842      }
843
844    /* append this input */
845    dev->inputs = eina_list_append(dev->inputs, input);
846
847    return EINA_TRUE;
848
849 err:
850    if (input->libinput) libinput_unref(input->libinput);
851    free(input);
852
853    return EINA_FALSE;
854 }
855
856
857 E_API const Eina_List *
858 e_input_devices_get(void)
859 {
860    return einput_devices;
861 }
862