e_input: close input device's fd in close restricted function only
[platform/upstream/enlightenment.git] / src / bin / e_input_inputs.c
1 #include "e.h"
2 #include "e_input_private.h"
3
4 static char *
5 _e_input_ecore_device_class_to_string(Ecore_Device_Class clas)
6 {
7    switch (clas)
8      {
9         case ECORE_DEVICE_CLASS_NONE:
10           return "None";
11           break;
12         case ECORE_DEVICE_CLASS_SEAT:
13           return "Seat";
14           break;
15         case ECORE_DEVICE_CLASS_KEYBOARD:
16           return "Keyboard";
17           break;
18         case ECORE_DEVICE_CLASS_MOUSE:
19           return "Mouse";
20           break;
21         case ECORE_DEVICE_CLASS_TOUCH:
22           return "Touch";
23           break;
24         case ECORE_DEVICE_CLASS_PEN:
25           return "Pen";
26           break;
27         case ECORE_DEVICE_CLASS_WAND:
28           return "Wand";
29           break;
30         case ECORE_DEVICE_CLASS_GAMEPAD:
31           return "Gamepad";
32           break;
33         default:
34           return "Unknown";
35      }
36 }
37
38 static Ecore_Device_Class
39 _e_input_seat_cap_to_ecore_device_class(unsigned int cap)
40 {
41    switch(cap)
42      {
43       case E_INPUT_SEAT_POINTER:
44          return ECORE_DEVICE_CLASS_MOUSE;
45       case E_INPUT_SEAT_KEYBOARD:
46          return ECORE_DEVICE_CLASS_KEYBOARD;
47       case E_INPUT_SEAT_TOUCH:
48          return ECORE_DEVICE_CLASS_TOUCH;
49       default:
50          return ECORE_DEVICE_CLASS_NONE;
51      }
52    return ECORE_DEVICE_CLASS_NONE;
53 }
54
55 static void
56 _e_input_ecore_device_info_free(void *data EINA_UNUSED, void *ev)
57 {
58    Ecore_Event_Device_Info *e;
59
60    e = ev;
61    eina_stringshare_del(e->name);
62    eina_stringshare_del(e->identifier);
63    eina_stringshare_del(e->seatname);
64
65    free(e);
66 }
67
68 void
69 _e_input_ecore_device_event(Ecore_Device *dev, Eina_Bool flag)
70 {
71    Ecore_Event_Device_Info *e;
72    E_Input *e_input;
73
74    if (!(e = calloc(1, sizeof(Ecore_Event_Device_Info)))) return;
75
76    e_input = e_input_get();
77
78    e->window = e_input?e_input->window:(Ecore_Window)0;
79    e->name = eina_stringshare_add(ecore_device_name_get(dev));
80    e->identifier = eina_stringshare_add(ecore_device_identifier_get(dev));
81    e->seatname = eina_stringshare_add(ecore_device_name_get(dev));
82    e->clas = ecore_device_class_get(dev);
83    e->subclas = ecore_device_subclass_get(dev);
84
85    if (flag)
86      ecore_event_add(ECORE_EVENT_DEVICE_ADD, e, _e_input_ecore_device_info_free, NULL);
87    else
88      ecore_event_add(ECORE_EVENT_DEVICE_DEL, e, _e_input_ecore_device_info_free, NULL);
89 }
90
91 static E_Input_Seat *
92 _seat_create(E_Input_Backend *input, const char *seat)
93 {
94    E_Input_Seat *s;
95    Ecore_Device *ecore_dev = NULL;
96
97    /* create an evas device of a seat */
98    ecore_dev = ecore_device_add();
99    if (!ecore_dev)
100      {
101         ERR("Failed to create an ecore device for a seat !\n");
102                 return NULL;
103      }
104
105    ecore_device_name_set(ecore_dev, seat);
106    ecore_device_identifier_set(ecore_dev, "Enlightenment seat");
107    ecore_device_class_set(ecore_dev, ECORE_DEVICE_CLASS_SEAT);
108    ecore_device_subclass_set(ecore_dev, ECORE_DEVICE_SUBCLASS_NONE);
109
110    /* try to allocate space for new seat */
111    if (!(s = calloc(1, sizeof(E_Input_Seat))))
112      {
113         ecore_device_del(ecore_dev);
114         return NULL;
115      }
116
117    s->input = input;
118    s->name = eina_stringshare_add(seat);
119    s->ecore_dev = ecore_dev;
120
121    /* add this new seat to list */
122    input->dev->seats = eina_list_append(input->dev->seats, s);
123
124    ecore_event_add(E_INPUT_EVENT_SEAT_ADD, NULL, NULL, NULL);
125
126    _e_input_ecore_device_event(ecore_dev, EINA_TRUE);
127
128    return s;
129 }
130
131 static E_Input_Seat *
132 _seat_get(E_Input_Backend *input, const char *seat)
133 {
134    E_Input_Seat *s;
135    Eina_List *l;
136
137    /* search for this name in existing seats */
138    EINA_LIST_FOREACH(input->dev->seats, l, s)
139      if (!strcmp(s->name, seat))
140        return s;
141
142    return _seat_create(input, seat);
143 }
144
145 static Eina_Bool
146 _e_input_add_ecore_device(E_Input_Evdev *edev, Ecore_Device_Class clas)
147 {
148    const Eina_List *dev_list = NULL;
149    const Eina_List *l;
150    Ecore_Device *dev = NULL;
151    const char *identifier;
152
153    if (!edev || !edev->path) return EINA_FALSE;
154
155    dev_list = ecore_device_list();
156    if (dev_list)
157      {
158         EINA_LIST_FOREACH(dev_list, l, dev)
159           {
160              if (!dev) continue;
161              identifier = ecore_device_description_get(dev);
162              if (!identifier) continue;
163              if ((ecore_device_class_get(dev) == clas) && (!strcmp(identifier, edev->path)))
164                return EINA_FALSE;
165           }
166      }
167
168    dev = ecore_device_add();
169    if (!dev)
170      {
171         edev->ecore_dev = NULL;
172         return EINA_FALSE;
173      }
174
175    ecore_device_name_set(dev, libinput_device_get_name(edev->device));
176    ecore_device_identifier_set(dev, edev->path);
177    ecore_device_class_set(dev, clas);
178    ecore_device_subclass_set(dev, ECORE_DEVICE_SUBCLASS_NONE);
179
180    if (!edev->ecore_dev)
181      {
182         if (!edev->ecore_dev_list || (eina_list_count(edev->ecore_dev_list) == 0))
183           {
184              /* 1st Ecore_Device is added */
185              edev->ecore_dev = ecore_device_ref(dev);
186           }
187         else
188           {
189              /* 3rd or more Ecore_Device is added */
190              edev->ecore_dev_list = eina_list_append(edev->ecore_dev_list, ecore_device_ref(dev));
191           }
192      }
193    else
194      {
195         /* 2nd Ecore_Device is added */
196         edev->ecore_dev_list = eina_list_append(edev->ecore_dev_list, edev->ecore_dev);
197         edev->ecore_dev = NULL;
198
199         edev->ecore_dev_list = eina_list_append(edev->ecore_dev_list, ecore_device_ref(dev));
200      }
201
202    _e_input_ecore_device_event(dev, EINA_TRUE);
203
204    return EINA_TRUE;
205 }
206
207 static Eina_Bool
208 _e_input_remove_ecore_device(E_Input_Evdev *edev, Ecore_Device_Class clas)
209 {
210    const Eina_List *dev_list = NULL, *l;
211    Eina_List *ll, *ll_next;
212    Ecore_Device *dev = NULL, *data;
213    const char *identifier;
214
215    if (!edev->path) return EINA_FALSE;
216
217    dev_list = ecore_device_list();
218    if (!dev_list) return EINA_FALSE;
219    EINA_LIST_FOREACH(dev_list, l, dev)
220       {
221          if (!dev) continue;
222          identifier = ecore_device_description_get(dev);
223          if (!identifier) continue;
224          if ((ecore_device_class_get(dev) == clas) && (!strcmp(identifier, edev->path)))
225            {
226               if (edev->ecore_dev) edev->ecore_dev = NULL;
227               else if (edev->ecore_dev_list)
228                 {
229                    EINA_LIST_FOREACH_SAFE(edev->ecore_dev_list, ll, ll_next, data)
230                      {
231                         if (data == dev)
232                           {
233                              edev->ecore_dev_list = eina_list_remove_list(edev->ecore_dev_list, ll);
234                           }
235                      }
236                 }
237               ecore_device_del(dev);
238               _e_input_ecore_device_event(dev, EINA_FALSE);
239               return EINA_TRUE;
240            }
241       }
242    return EINA_FALSE;
243 }
244
245 Eina_Bool
246 _e_input_device_add(E_Input_Evdev *edev)
247 {
248    Eina_Bool ret = EINA_FALSE;
249    Ecore_Device_Class clas = ECORE_DEVICE_CLASS_NONE;
250
251    if (edev->caps & E_INPUT_SEAT_POINTER)
252      {
253         if (!e_devicemgr_detent_is_detent(libinput_device_get_name(edev->device)))
254           clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_POINTER);
255         ret = _e_input_add_ecore_device(edev, clas);
256      }
257    if (edev->caps & E_INPUT_SEAT_KEYBOARD)
258      {
259         clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_KEYBOARD);
260         ret = _e_input_add_ecore_device(edev, clas);
261      }
262    if (edev->caps & E_INPUT_SEAT_TOUCH)
263      {
264         clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_TOUCH);
265         ret = _e_input_add_ecore_device(edev, clas);
266      }
267
268    return ret;
269 }
270
271 void
272 _e_input_device_remove(E_Input_Evdev *edev)
273 {
274    Ecore_Device_Class clas = ECORE_DEVICE_CLASS_NONE;
275    Ecore_Device *data;
276
277    if (edev->caps & E_INPUT_SEAT_POINTER)
278      {
279         if (!e_devicemgr_detent_is_detent(libinput_device_get_name(edev->device)))
280           clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_POINTER);
281         _e_input_remove_ecore_device(edev, clas);
282      }
283    if (edev->caps & E_INPUT_SEAT_KEYBOARD)
284      {
285         clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_KEYBOARD);
286         _e_input_remove_ecore_device(edev, clas);
287      }
288    if (edev->caps & E_INPUT_SEAT_TOUCH)
289      {
290         clas = _e_input_seat_cap_to_ecore_device_class(E_INPUT_SEAT_TOUCH);
291         _e_input_remove_ecore_device(edev, clas);
292      }
293
294    if (edev->ecore_dev_list)
295      {
296         if (eina_list_count(edev->ecore_dev_list) > 0)
297           {
298              EINA_LIST_FREE(edev->ecore_dev_list, data)
299                {
300                   WRN("Invalid device is left. name: %s, identifier: %s, clas: %s\n",
301                       ecore_device_name_get(data), ecore_device_description_get(data),
302                       _e_input_ecore_device_class_to_string(ecore_device_class_get(data)));
303                   ecore_device_del(data);
304                }
305           }
306         edev->ecore_dev_list = NULL;
307      }
308 }
309
310 static void
311 _device_added(E_Input_Backend *input, struct libinput_device *device)
312 {
313    struct libinput_seat *libinput_seat;
314    const char *seat_name;
315    E_Input_Seat *seat;
316    E_Input_Evdev *edev;
317
318    libinput_seat = libinput_device_get_seat(device);
319    seat_name = libinput_seat_get_logical_name(libinput_seat);
320
321    /* try to get a seat */
322    if (!(seat = _seat_get(input, seat_name)))
323      {
324         ERR("Could not get matching seat: %s", seat_name);
325         return;
326      }
327
328    /* try to create a new evdev device */
329    if (!(edev = _e_input_evdev_device_create(seat, device)))
330      {
331         ERR("Failed to create new evdev device");
332         return;
333      }
334
335    /* append this device to the seat */
336    seat->devices = eina_list_append(seat->devices, edev);
337
338    if (EINA_FALSE == _e_input_device_add(edev))
339      {
340         ERR("Failed to create evas device !\n");
341         return;
342      }
343 }
344
345 static void
346 _device_removed(E_Input_Backend *input, struct libinput_device *device)
347 {
348    E_Input_Evdev *edev;
349
350    /* try to get the evdev structure */
351    if (!(edev = libinput_device_get_user_data(device)))
352      {
353         return;
354      }
355
356    _e_input_device_remove(edev);
357
358    /* remove this evdev from the seat's list of devices */
359    edev->seat->devices = eina_list_remove(edev->seat->devices, edev);
360
361    /* destroy this evdev */
362    _e_input_evdev_device_destroy(edev);
363 }
364
365 static int
366 _udev_event_process(struct libinput_event *event)
367 {
368    struct libinput *libinput;
369    struct libinput_device *device;
370    E_Input_Backend *input;
371    Eina_Bool ret = EINA_TRUE;
372
373    libinput = libinput_event_get_context(event);
374    input = libinput_get_user_data(libinput);
375    device = libinput_event_get_device(event);
376
377    switch (libinput_event_get_type(event))
378      {
379       case LIBINPUT_EVENT_DEVICE_ADDED:
380         _device_added(input, device);
381         break;
382       case LIBINPUT_EVENT_DEVICE_REMOVED:
383         _device_removed(input, device);
384         break;
385       default:
386         ret = EINA_FALSE;
387      }
388
389    return ret;
390 }
391
392 static void
393 _input_event_process(struct libinput_event *event)
394 {
395    if (_udev_event_process(event)) return;
396    if (_e_input_evdev_event_process(event)) return;
397 }
398
399 void
400 _input_events_process(E_Input_Backend *input)
401 {
402    struct libinput_event *event;
403
404    while ((event = libinput_get_event(input->libinput)))
405      {
406         _input_event_process(event);
407         libinput_event_destroy(event);
408      }
409 }
410
411 static Eina_Bool
412 _cb_input_dispatch(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
413 {
414    E_Input_Backend *input;
415
416    if (!(input = data)) return EINA_TRUE;
417
418    if (libinput_dispatch(input->libinput) != 0)
419      ERR("Failed to dispatch libinput events: %m");
420
421    /* process pending events */
422    _input_events_process(input);
423
424    return EINA_TRUE;
425 }
426
427 EINTERN Eina_Bool
428 e_input_enable_input(E_Input_Backend *input)
429 {
430    EINA_SAFETY_ON_NULL_RETURN_VAL(input, EINA_FALSE);
431    EINA_SAFETY_ON_NULL_RETURN_VAL(input->libinput, EINA_FALSE);
432
433    input->fd = libinput_get_fd(input->libinput);
434
435    if (!input->hdlr)
436      {
437         input->hdlr =
438           ecore_main_fd_handler_add(input->fd, ECORE_FD_READ,
439                                     _cb_input_dispatch, input, NULL, NULL);
440      }
441
442    if (input->suspended)
443      {
444         if (libinput_resume(input->libinput) != 0)
445           goto err;
446
447         input->suspended = EINA_FALSE;
448
449         /* process pending events */
450         _input_events_process(input);
451      }
452
453    input->enabled = EINA_TRUE;
454    input->suspended = EINA_FALSE;
455
456    return EINA_TRUE;
457
458 err:
459    input->enabled = EINA_FALSE;
460    if (input->hdlr)
461      ecore_main_fd_handler_del(input->hdlr);
462    input->hdlr = NULL;
463
464    return EINA_FALSE;
465 }
466
467 EINTERN void
468 e_input_disable_input(E_Input_Backend *input)
469 {
470    EINA_SAFETY_ON_NULL_RETURN(input);
471    EINA_SAFETY_ON_TRUE_RETURN(input->suspended);
472
473    /* suspend this input */
474    libinput_suspend(input->libinput);
475
476    /* process pending events */
477    _input_events_process(input);
478
479    input->suspended = EINA_TRUE;
480 }
481
482 E_API Eina_List *
483 e_input_seat_evdev_list_get(E_Input_Seat *seat)
484 {
485    EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
486    return seat->devices;
487 }