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