1 /*
2 * Copyright © 2013 Intel Corporation
3 * Copyright © 2013 Jonas Ådahl
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 "config.h"
28
29 #include <stdint.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <libinput.h>
35 #include <libudev.h>
36
37 #include <libweston/libweston.h>
38 #include "backend.h"
39 #include "libweston-internal.h"
40 // OHOS remove logger
41 //#include "weston-log-internal.h"
42 #include "launcher-util.h"
43 #include "libinput-seat.h"
44 #include "libinput-device.h"
45 #include "shared/helpers.h"
46 // for multi model input
47 #include "libinput-seat-export.h"
48
49 static libinput_event_listener g_libinput_event_listener = NULL;
set_libinput_event_listener(libinput_event_listener listener)50 void set_libinput_event_listener(libinput_event_listener listener)
51 {
52 g_libinput_event_listener = listener;
53 }
54
55 static void
56 process_events(struct udev_input *input);
57 static struct udev_seat *
58 udev_seat_create(struct udev_input *input, const char *seat_name);
59 static void
60 udev_seat_destroy(struct udev_seat *seat);
61
62 static struct udev_seat *
get_udev_seat(struct udev_input * input,struct libinput_device * device)63 get_udev_seat(struct udev_input *input, struct libinput_device *device)
64 {
65 struct libinput_seat *libinput_seat;
66 const char *seat_name;
67
68 libinput_seat = libinput_device_get_seat(device);
69 seat_name = libinput_seat_get_logical_name(libinput_seat);
70 return udev_seat_get_named(input, seat_name);
71 }
72
73 static struct weston_output *
output_find_by_head_name(struct weston_compositor * compositor,const char * head_name)74 output_find_by_head_name(struct weston_compositor *compositor,
75 const char *head_name)
76 {
77 struct weston_output *output;
78 struct weston_head *head;
79
80 if (!head_name)
81 return NULL;
82
83 /* Only enabled outputs with connected heads.
84 * This means force-enabled outputs but with disconnected heads
85 * will be ignored; if the touchscreen doesn't have a video signal,
86 * touching it is meaningless.
87 */
88 wl_list_for_each(output, &compositor->output_list, link) {
89 wl_list_for_each(head, &output->head_list, output_link) {
90 if (!weston_head_is_connected(head))
91 continue;
92
93 if (strcmp(head_name, head->name) == 0)
94 return output;
95 }
96 }
97
98 return NULL;
99 }
100
101 static void
device_added(struct udev_input * input,struct libinput_device * libinput_device)102 device_added(struct udev_input *input, struct libinput_device *libinput_device)
103 {
104 struct weston_compositor *c;
105 struct evdev_device *device;
106 struct weston_output *output;
107 const char *output_name;
108 struct weston_seat *seat;
109 struct udev_seat *udev_seat;
110 struct weston_pointer *pointer;
111
112 c = input->compositor;
113
114 udev_seat = get_udev_seat(input, libinput_device);
115 if (!udev_seat)
116 return;
117
118 seat = &udev_seat->base;
119 device = evdev_device_create_l(libinput_device, seat);
120 if (device == NULL)
121 return;
122
123 if (input->configure_device != NULL)
124 input->configure_device(c, device->device);
125 evdev_device_set_calibration_l(device);
126 udev_seat = (struct udev_seat *) seat;
127 wl_list_insert(udev_seat->devices_list.prev, &device->link);
128
129 pointer = weston_seat_get_pointer(seat);
130 if (seat->output && pointer)
131 weston_pointer_clamp(pointer,
132 &pointer->x,
133 &pointer->y);
134
135 output_name = libinput_device_get_output_name(libinput_device);
136 if (output_name) {
137 device->output_name = strdup(output_name);
138 output = output_find_by_head_name(c, output_name);
139 evdev_device_set_output_l(device, output);
140 } else if (!wl_list_empty(&c->output_list)) {
141 /* default assignment to an arbitrary output */
142 output = container_of(c->output_list.next,
143 struct weston_output, link);
144 evdev_device_set_output_l(device, output);
145 }
146
147 if (!input->suspended)
148 weston_seat_repick(seat);
149 }
150
151 static void
device_removed(struct udev_input * input,struct libinput_device * libinput_device)152 device_removed(struct udev_input *input, struct libinput_device *libinput_device)
153 {
154 struct evdev_device *device;
155
156 device = libinput_device_get_user_data(libinput_device);
157 evdev_device_destroy_l(device);
158 }
159
160 static void
udev_seat_remove_devices(struct udev_seat * seat)161 udev_seat_remove_devices(struct udev_seat *seat)
162 {
163 struct evdev_device *device, *next;
164
165 wl_list_for_each_safe(device, next, &seat->devices_list, link) {
166 evdev_device_destroy_l(device);
167 }
168 }
169
170 void
udev_input_disable(struct udev_input * input)171 udev_input_disable(struct udev_input *input)
172 {
173 if (input->suspended)
174 return;
175
176 wl_event_source_remove(input->libinput_source);
177 input->libinput_source = NULL;
178 libinput_suspend(input->libinput);
179 process_events(input);
180 input->suspended = 1;
181 }
182
183 static int
udev_input_process_event(struct libinput_event * event)184 udev_input_process_event(struct libinput_event *event)
185 {
186 struct libinput *libinput = libinput_event_get_context(event);
187 struct libinput_device *libinput_device =
188 libinput_event_get_device(event);
189 struct udev_input *input = libinput_get_user_data(libinput);
190 int handled = 1;
191
192 switch (libinput_event_get_type(event)) {
193 case LIBINPUT_EVENT_DEVICE_ADDED:
194 device_added(input, libinput_device);
195 break;
196 case LIBINPUT_EVENT_DEVICE_REMOVED:
197 device_removed(input, libinput_device);
198 break;
199 default:
200 handled = 0;
201 }
202
203 return handled;
204 }
205
206 static void
process_event(struct libinput_event * event)207 process_event(struct libinput_event *event)
208 {
209 if (udev_input_process_event(event))
210 return;
211 if (evdev_device_process_event_l(event))
212 return;
213 }
214
215 bool
process_multimodalinput_touch_event(struct libinput_event * event,struct evdev_device * device,void ** data)216 process_multimodalinput_touch_event(struct libinput_event *event, struct evdev_device *device, void **data)
217 {
218 if (!event) {
219 weston_log("process_multimodalinput_events: libinput_event is nullptr.\n");
220 return false;
221 }
222 if (!device) {
223 weston_log("process_multimodalinput_events: evdev_device is nullptr.\n");
224 return false;
225 }
226 struct weston_touch *touch = device->touch_device->aggregate;
227 if (!touch || !touch->focus) {
228 weston_log("process_multimodalinput_events: weston_touch_has_focus_resource return false.\n");
229 return false;
230 }
231
232 uint32_t width = device->output->current_mode->width;
233 uint32_t height = device->output->current_mode->height;
234 struct libinput_event_touch *touch_event = libinput_event_get_touch_event(event);
235 if (!touch_event) {
236 weston_log("process_multimodalinput_events: libinput_event_get_touch_event return false.\n");
237 return false;
238 }
239 double double_x = libinput_event_touch_get_x_transformed(touch_event, width);
240 double double_y = libinput_event_touch_get_y_transformed(touch_event, height);
241 weston_output_transform_coordinate(device->output, double_x, double_y, &double_x, &double_y);
242
243 wl_fixed_t x = wl_fixed_from_double(double_x);
244 wl_fixed_t y = wl_fixed_from_double(double_y);
245
246 wl_fixed_t sx, sy;
247 weston_view_from_global_fixed(touch->focus, x, y, &sx, &sy);
248 double dx = wl_fixed_to_double(sx);
249 double dy = wl_fixed_to_double(sy);
250
251 *data = malloc(sizeof(struct multimodal_input_pointer_data));
252 if (!(*data)) {
253 weston_log("process_multimodalinput_events: malloc multimodal_input_pointer_data return null.\n");
254 return false;
255 }
256 struct multimodal_input_pointer_data *pdata = (struct multimodal_input_pointer_data *)(*data);
257 pdata->x = double_x;
258 pdata->y = double_y;
259 pdata->sx = dx;
260 pdata->sy = dy;
261 return true;
262 }
263
264 bool
process_multimodalinput_pointer_event(struct evdev_device * device,void ** data)265 process_multimodalinput_pointer_event(struct evdev_device *device, void **data)
266 {
267 if (!device) {
268 weston_log("process_multimodalinput_events: evdev_device is nullptr.\n");
269 return false;
270 }
271 struct weston_pointer *pointer = weston_seat_get_pointer(device->seat);
272 if (!pointer) {
273 weston_log("process_multimodalinput_events: weston_seat_get_pointer return null.\n");
274 return false;
275 }
276 *data = malloc(sizeof(struct multimodal_input_pointer_data));
277 if (!(*data)) {
278 weston_log("process_multimodalinput_events: malloc multimodal_input_pointer_data return null.\n");
279 return false;
280 }
281 struct multimodal_input_pointer_data *pdata = (struct multimodal_input_pointer_data *)(*data);
282 pdata->x = wl_fixed_to_int(pointer->x);
283 pdata->y = wl_fixed_to_int(pointer->y);
284 pdata->sx = wl_fixed_to_int(pointer->sx);
285 pdata->sy = wl_fixed_to_int(pointer->sy);
286 return true;
287 }
288
289 void
process_multimodalinput_events(struct libinput_event * event)290 process_multimodalinput_events(struct libinput_event *event)
291 {
292 if (!event) {
293 weston_log("process_multimodalinput_events: libinput_event is nullptr.\n");
294 return;
295 }
296 if (!g_libinput_event_listener) {
297 weston_log("process_multimodalinput_events: libinput_event_listener is not set.\n");
298 return;
299 }
300 struct libinput_device *libinput_dev = libinput_event_get_device(event);
301 if (!libinput_dev) {
302 weston_log("process_multimodalinput_events: libinput_event_get_device is nullptr.\n");
303 return;
304 }
305 struct evdev_device *device = libinput_device_get_user_data(libinput_dev);
306 if (!device || !device->output) {
307 weston_log("process_multimodalinput_events: libinput_device_get_user_data evdev_device is nullptr.\n");
308 return;
309 }
310
311 struct multimodal_libinput_event muli_event = {};
312 muli_event.event = event;
313 int type = libinput_event_get_type(event);
314 if (LIBINPUT_EVENT_TOUCH_DOWN == type || LIBINPUT_EVENT_TOUCH_MOTION == type) {
315 if (!process_multimodalinput_touch_event(event, device, (void **)&muli_event.userdata)) {
316 weston_log("process_multimodalinput_events: process_multimodalinput_touch_event "
317 "return false.\n");
318 return;
319 }
320 } else if (LIBINPUT_EVENT_POINTER_MOTION == type || LIBINPUT_EVENT_POINTER_BUTTON == type) {
321 if (!process_multimodalinput_pointer_event(device, (void **)&muli_event.userdata)) {
322 weston_log("process_multimodalinput_events: process_multimodalinput_pointer_event "
323 "return false.\n");
324 return;
325 }
326 }
327 g_libinput_event_listener(&muli_event);
328 if (muli_event.userdata) {
329 free(muli_event.userdata);
330 muli_event.userdata = NULL;
331 }
332 }
333
334 static void
process_events(struct udev_input * input)335 process_events(struct udev_input *input)
336 {
337 struct libinput_event *event = NULL;
338 while ((event = libinput_get_event(input->libinput))) {
339 process_event(event);
340 process_multimodalinput_events(event);
341 libinput_event_destroy(event);
342 }
343 }
344
345 static int
udev_input_dispatch(struct udev_input * input)346 udev_input_dispatch(struct udev_input *input)
347 {
348 if (libinput_dispatch(input->libinput) != 0)
349 weston_log("libinput: Failed to dispatch libinput\n");
350
351 process_events(input);
352
353 return 0;
354 }
355
356 static int
libinput_source_dispatch(int fd,uint32_t mask,void * data)357 libinput_source_dispatch(int fd, uint32_t mask, void *data)
358 {
359 struct udev_input *input = data;
360
361 return udev_input_dispatch(input) != 0;
362 }
363
364 static int
open_restricted(const char * path,int flags,void * user_data)365 open_restricted(const char *path, int flags, void *user_data)
366 {
367 struct udev_input *input = user_data;
368 struct weston_launcher *launcher = input->compositor->launcher;
369
370 return weston_launcher_open(launcher, path, flags);
371 }
372
373 static void
close_restricted(int fd,void * user_data)374 close_restricted(int fd, void *user_data)
375 {
376 struct udev_input *input = user_data;
377 struct weston_launcher *launcher = input->compositor->launcher;
378
379 weston_launcher_close(launcher, fd);
380 }
381
382 const struct libinput_interface libinput_interface = {
383 open_restricted,
384 close_restricted,
385 };
386
387 int
udev_input_enable(struct udev_input * input)388 udev_input_enable(struct udev_input *input)
389 {
390 struct wl_event_loop *loop;
391 struct weston_compositor *c = input->compositor;
392 int fd;
393 struct udev_seat *seat;
394 int devices_found = 0;
395
396 loop = wl_display_get_event_loop(c->wl_display);
397 fd = libinput_get_fd(input->libinput);
398 input->libinput_source =
399 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
400 libinput_source_dispatch, input);
401 if (!input->libinput_source) {
402 return -1;
403 }
404
405 if (input->suspended) {
406 if (libinput_resume(input->libinput) != 0) {
407 wl_event_source_remove(input->libinput_source);
408 input->libinput_source = NULL;
409 return -1;
410 }
411 input->suspended = 0;
412 process_events(input);
413 }
414
415 wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
416 evdev_notify_keyboard_focus_l(&seat->base, &seat->devices_list);
417
418 if (!wl_list_empty(&seat->devices_list))
419 devices_found = 1;
420 }
421
422 if (devices_found == 0 && !c->require_input) {
423 weston_log("warning: no input devices found, but none required "
424 "as per configuration.\n");
425 return 0;
426 }
427
428 if (devices_found == 0) {
429 weston_log(
430 "warning: no input devices on entering Weston. "
431 "Possible causes:\n"
432 "\t- no permissions to read /dev/input/event*\n"
433 "\t- seats misconfigured "
434 "(Weston backend option 'seat', "
435 "udev device property ID_SEAT)\n");
436 return -1;
437 }
438
439 return 0;
440 }
441
442 static void
libinput_log_func(struct libinput * libinput,enum libinput_log_priority priority,const char * format,va_list args)443 libinput_log_func(struct libinput *libinput,
444 enum libinput_log_priority priority,
445 const char *format, va_list args)
446 {
447 weston_vlog(format, args);
448 }
449
450 int
udev_input_init(struct udev_input * input,struct weston_compositor * c,struct udev * udev,const char * seat_id,udev_configure_device_t configure_device)451 udev_input_init(struct udev_input *input, struct weston_compositor *c,
452 struct udev *udev, const char *seat_id,
453 udev_configure_device_t configure_device)
454 {
455 enum libinput_log_priority priority = LIBINPUT_LOG_PRIORITY_INFO;
456 const char *log_priority = NULL;
457
458 memset(input, 0, sizeof *input);
459
460 input->compositor = c;
461 input->configure_device = configure_device;
462
463 log_priority = getenv("WESTON_LIBINPUT_LOG_PRIORITY");
464
465 input->libinput = libinput_udev_create_context(&libinput_interface,
466 input, udev);
467 if (!input->libinput) {
468 return -1;
469 }
470
471 libinput_log_set_handler(input->libinput, &libinput_log_func);
472
473 if (log_priority) {
474 if (strcmp(log_priority, "debug") == 0) {
475 priority = LIBINPUT_LOG_PRIORITY_DEBUG;
476 } else if (strcmp(log_priority, "info") == 0) {
477 priority = LIBINPUT_LOG_PRIORITY_INFO;
478 } else if (strcmp(log_priority, "error") == 0) {
479 priority = LIBINPUT_LOG_PRIORITY_ERROR;
480 }
481 }
482
483 libinput_log_set_priority(input->libinput, priority);
484
485 if (libinput_udev_assign_seat(input->libinput, seat_id) != 0) {
486 libinput_unref(input->libinput);
487 return -1;
488 }
489
490 process_events(input);
491
492 return udev_input_enable(input);
493 }
494
495 void
udev_input_destroy(struct udev_input * input)496 udev_input_destroy(struct udev_input *input)
497 {
498 struct udev_seat *seat, *next;
499
500 if (input->libinput_source)
501 wl_event_source_remove(input->libinput_source);
502 wl_list_for_each_safe(seat, next, &input->compositor->seat_list, base.link)
503 udev_seat_destroy(seat);
504 libinput_unref(input->libinput);
505 }
506
507 static void
udev_seat_led_update(struct weston_seat * seat_base,enum weston_led leds)508 udev_seat_led_update(struct weston_seat *seat_base, enum weston_led leds)
509 {
510 struct udev_seat *seat = (struct udev_seat *) seat_base;
511 struct evdev_device *device;
512
513 wl_list_for_each(device, &seat->devices_list, link)
514 evdev_led_update_l(device, leds);
515 }
516
517 static void
udev_seat_output_changed(struct udev_seat * seat,struct weston_output * output)518 udev_seat_output_changed(struct udev_seat *seat, struct weston_output *output)
519 {
520 struct evdev_device *device;
521 struct weston_output *found;
522
523 wl_list_for_each(device, &seat->devices_list, link) {
524 /* If we find any input device without an associated output
525 * or an output name to associate with, just tie it with the
526 * output we got here - the default assignment.
527 */
528 if (!device->output_name) {
529 if (!device->output)
530 evdev_device_set_output_l(device, output);
531
532 continue;
533 }
534
535 /* Update all devices' output associations, may they gain or
536 * lose it.
537 */
538 found = output_find_by_head_name(output->compositor,
539 device->output_name);
540 evdev_device_set_output_l(device, found);
541 }
542 }
543
544 static void
notify_output_create(struct wl_listener * listener,void * data)545 notify_output_create(struct wl_listener *listener, void *data)
546 {
547 struct udev_seat *seat = container_of(listener, struct udev_seat,
548 output_create_listener);
549 struct weston_output *output = data;
550
551 udev_seat_output_changed(seat, output);
552 }
553
554 static void
notify_output_heads_changed(struct wl_listener * listener,void * data)555 notify_output_heads_changed(struct wl_listener *listener, void *data)
556 {
557 struct udev_seat *seat = container_of(listener, struct udev_seat,
558 output_heads_listener);
559 struct weston_output *output = data;
560
561 udev_seat_output_changed(seat, output);
562 }
563
564 static struct udev_seat *
udev_seat_create(struct udev_input * input,const char * seat_name)565 udev_seat_create(struct udev_input *input, const char *seat_name)
566 {
567 struct weston_compositor *c = input->compositor;
568 struct udev_seat *seat;
569
570 seat = zalloc(sizeof *seat);
571 if (!seat)
572 return NULL;
573
574 weston_seat_init(&seat->base, c, seat_name);
575 seat->base.led_update = udev_seat_led_update;
576
577 seat->output_create_listener.notify = notify_output_create;
578 wl_signal_add(&c->output_created_signal,
579 &seat->output_create_listener);
580
581 seat->output_heads_listener.notify = notify_output_heads_changed;
582 wl_signal_add(&c->output_heads_changed_signal,
583 &seat->output_heads_listener);
584
585 wl_list_init(&seat->devices_list);
586
587 return seat;
588 }
589
590 static void
udev_seat_destroy(struct udev_seat * seat)591 udev_seat_destroy(struct udev_seat *seat)
592 {
593 struct weston_keyboard *keyboard =
594 weston_seat_get_keyboard(&seat->base);
595
596 if (keyboard)
597 notify_keyboard_focus_out(&seat->base);
598
599 udev_seat_remove_devices(seat);
600 weston_seat_release(&seat->base);
601 wl_list_remove(&seat->output_create_listener.link);
602 wl_list_remove(&seat->output_heads_listener.link);
603 free(seat);
604 }
605
606 struct udev_seat *
udev_seat_get_named(struct udev_input * input,const char * seat_name)607 udev_seat_get_named(struct udev_input *input, const char *seat_name)
608 {
609 struct udev_seat *seat;
610
611 wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
612 if (strcmp(seat->base.seat_name, seat_name) == 0)
613 return seat;
614 }
615
616 return udev_seat_create(input, seat_name);
617 }
618