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