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