blob: 76ba63e65cdc98ad86f5cc60555c519a756caff2 [file] [log] [blame]
Jonas Ådahle0de3c22014-03-12 22:08:42 +01001/*
2 * Copyright © 2013 Intel Corporation
3 * Copyright © 2013 Jonas Ådahl
4 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -07005 * 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:
Jonas Ådahle0de3c22014-03-12 22:08:42 +010012 *
Bryce Harringtona0bbfea2015-06-11 15:35:43 -070013 * 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.
Jonas Ådahle0de3c22014-03-12 22:08:42 +010025 */
26
27#include "config.h"
28
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030029#include <stdint.h>
Jonas Ådahle0de3c22014-03-12 22:08:42 +010030#include <stdlib.h>
31#include <string.h>
32#include <unistd.h>
33#include <fcntl.h>
34#include <libinput.h>
35#include <libudev.h>
36
Pekka Paalanen3d5d9472019-03-28 16:28:47 +020037#include <libweston/libweston.h>
Marius Vlad5d649b62019-07-16 23:44:21 +030038#include "backend.h"
Marius Vlad0bf3f5a2019-07-10 17:32:42 +030039#include "libweston-internal.h"
Jonas Ådahle0de3c22014-03-12 22:08:42 +010040#include "launcher-util.h"
41#include "libinput-seat.h"
42#include "libinput-device.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070043#include "shared/helpers.h"
Jonas Ådahle0de3c22014-03-12 22:08:42 +010044
Jonas Ådahle0de3c22014-03-12 22:08:42 +010045static void
46process_events(struct udev_input *input);
47static struct udev_seat *
48udev_seat_create(struct udev_input *input, const char *seat_name);
49static void
50udev_seat_destroy(struct udev_seat *seat);
51
Derek Foremana6714fa2015-05-05 15:01:51 -050052static struct udev_seat *
53get_udev_seat(struct udev_input *input, struct libinput_device *device)
54{
55 struct libinput_seat *libinput_seat;
56 const char *seat_name;
57
58 libinput_seat = libinput_device_get_seat(device);
59 seat_name = libinput_seat_get_logical_name(libinput_seat);
60 return udev_seat_get_named(input, seat_name);
61}
62
Pekka Paalanenfd02efb2018-03-19 14:55:41 +020063static struct weston_output *
64output_find_by_head_name(struct weston_compositor *compositor,
65 const char *head_name)
66{
67 struct weston_output *output;
68 struct weston_head *head;
69
70 if (!head_name)
71 return NULL;
72
Pekka Paalanen8dc6db82018-03-20 13:29:40 +020073 /* Only enabled outputs with connected heads.
74 * This means force-enabled outputs but with disconnected heads
75 * will be ignored; if the touchscreen doesn't have a video signal,
76 * touching it is meaningless.
77 */
Pekka Paalanenfd02efb2018-03-19 14:55:41 +020078 wl_list_for_each(output, &compositor->output_list, link) {
79 wl_list_for_each(head, &output->head_list, output_link) {
Pekka Paalanen8dc6db82018-03-20 13:29:40 +020080 if (!weston_head_is_connected(head))
81 continue;
82
Pekka Paalanenfd02efb2018-03-19 14:55:41 +020083 if (strcmp(head_name, head->name) == 0)
84 return output;
85 }
86 }
87
88 return NULL;
89}
90
Jonas Ådahle0de3c22014-03-12 22:08:42 +010091static void
92device_added(struct udev_input *input, struct libinput_device *libinput_device)
93{
94 struct weston_compositor *c;
95 struct evdev_device *device;
96 struct weston_output *output;
Jonas Ådahle0de3c22014-03-12 22:08:42 +010097 const char *output_name;
Jonas Ådahle0de3c22014-03-12 22:08:42 +010098 struct weston_seat *seat;
99 struct udev_seat *udev_seat;
Derek Foreman1281a362015-07-31 16:55:32 -0500100 struct weston_pointer *pointer;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100101
102 c = input->compositor;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100103
Derek Foremana6714fa2015-05-05 15:01:51 -0500104 udev_seat = get_udev_seat(input, libinput_device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100105 if (!udev_seat)
106 return;
107
108 seat = &udev_seat->base;
109 device = evdev_device_create(libinput_device, seat);
110 if (device == NULL)
111 return;
112
Giulio Camuffo8aedf7b2016-06-02 21:48:12 +0300113 if (input->configure_device != NULL)
114 input->configure_device(c, device->device);
115 evdev_device_set_calibration(device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100116 udev_seat = (struct udev_seat *) seat;
117 wl_list_insert(udev_seat->devices_list.prev, &device->link);
118
Derek Foreman1281a362015-07-31 16:55:32 -0500119 pointer = weston_seat_get_pointer(seat);
120 if (seat->output && pointer)
121 weston_pointer_clamp(pointer,
122 &pointer->x,
123 &pointer->y);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100124
125 output_name = libinput_device_get_output_name(libinput_device);
126 if (output_name) {
127 device->output_name = strdup(output_name);
Pekka Paalanenfd02efb2018-03-19 14:55:41 +0200128 output = output_find_by_head_name(c, output_name);
129 evdev_device_set_output(device, output);
130 } else if (!wl_list_empty(&c->output_list)) {
131 /* default assignment to an arbitrary output */
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100132 output = container_of(c->output_list.next,
133 struct weston_output, link);
134 evdev_device_set_output(device, output);
135 }
136
137 if (!input->suspended)
138 weston_seat_repick(seat);
139}
140
141static void
Derek Foreman6b557a72015-05-05 15:01:52 -0500142device_removed(struct udev_input *input, struct libinput_device *libinput_device)
143{
144 struct evdev_device *device;
Derek Foreman0b7da012015-09-30 13:34:57 -0500145
Derek Foreman6b557a72015-05-05 15:01:52 -0500146 device = libinput_device_get_user_data(libinput_device);
147 evdev_device_destroy(device);
148}
149
150static void
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100151udev_seat_remove_devices(struct udev_seat *seat)
152{
153 struct evdev_device *device, *next;
154
155 wl_list_for_each_safe(device, next, &seat->devices_list, link) {
156 evdev_device_destroy(device);
157 }
158}
159
160void
161udev_input_disable(struct udev_input *input)
162{
163 if (input->suspended)
164 return;
165
Derek Foreman0e4e5702017-07-25 16:39:20 -0500166 wl_event_source_remove(input->libinput_source);
167 input->libinput_source = NULL;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100168 libinput_suspend(input->libinput);
169 process_events(input);
170 input->suspended = 1;
171}
172
173static int
174udev_input_process_event(struct libinput_event *event)
175{
176 struct libinput *libinput = libinput_event_get_context(event);
177 struct libinput_device *libinput_device =
178 libinput_event_get_device(event);
179 struct udev_input *input = libinput_get_user_data(libinput);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100180 int handled = 1;
181
182 switch (libinput_event_get_type(event)) {
183 case LIBINPUT_EVENT_DEVICE_ADDED:
184 device_added(input, libinput_device);
185 break;
186 case LIBINPUT_EVENT_DEVICE_REMOVED:
Derek Foreman6b557a72015-05-05 15:01:52 -0500187 device_removed(input, libinput_device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100188 break;
189 default:
190 handled = 0;
191 }
192
193 return handled;
194}
195
196static void
197process_event(struct libinput_event *event)
198{
199 if (udev_input_process_event(event))
200 return;
201 if (evdev_device_process_event(event))
202 return;
203}
204
205static void
206process_events(struct udev_input *input)
207{
208 struct libinput_event *event;
209
210 while ((event = libinput_get_event(input->libinput))) {
211 process_event(event);
212 libinput_event_destroy(event);
213 }
214}
215
216static int
217udev_input_dispatch(struct udev_input *input)
218{
219 if (libinput_dispatch(input->libinput) != 0)
220 weston_log("libinput: Failed to dispatch libinput\n");
221
222 process_events(input);
223
224 return 0;
225}
226
227static int
228libinput_source_dispatch(int fd, uint32_t mask, void *data)
229{
230 struct udev_input *input = data;
231
232 return udev_input_dispatch(input) != 0;
233}
234
235static int
236open_restricted(const char *path, int flags, void *user_data)
237{
238 struct udev_input *input = user_data;
239 struct weston_launcher *launcher = input->compositor->launcher;
240
241 return weston_launcher_open(launcher, path, flags);
242}
243
244static void
245close_restricted(int fd, void *user_data)
246{
247 struct udev_input *input = user_data;
248 struct weston_launcher *launcher = input->compositor->launcher;
249
250 weston_launcher_close(launcher, fd);
251}
252
253const struct libinput_interface libinput_interface = {
254 open_restricted,
255 close_restricted,
256};
257
258int
259udev_input_enable(struct udev_input *input)
260{
261 struct wl_event_loop *loop;
262 struct weston_compositor *c = input->compositor;
263 int fd;
264 struct udev_seat *seat;
265 int devices_found = 0;
266
267 loop = wl_display_get_event_loop(c->wl_display);
268 fd = libinput_get_fd(input->libinput);
269 input->libinput_source =
270 wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
271 libinput_source_dispatch, input);
272 if (!input->libinput_source) {
273 return -1;
274 }
275
276 if (input->suspended) {
277 if (libinput_resume(input->libinput) != 0) {
278 wl_event_source_remove(input->libinput_source);
279 input->libinput_source = NULL;
280 return -1;
281 }
282 input->suspended = 0;
283 process_events(input);
284 }
285
286 wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
287 evdev_notify_keyboard_focus(&seat->base, &seat->devices_list);
288
289 if (!wl_list_empty(&seat->devices_list))
290 devices_found = 1;
291 }
292
Daniel Díaz75b71972016-10-21 14:03:13 -0500293 if (devices_found == 0 && !c->require_input) {
294 weston_log("warning: no input devices found, but none required "
295 "as per configuration.\n");
296 return 0;
297 }
298
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100299 if (devices_found == 0) {
300 weston_log(
301 "warning: no input devices on entering Weston. "
302 "Possible causes:\n"
303 "\t- no permissions to read /dev/input/event*\n"
304 "\t- seats misconfigured "
305 "(Weston backend option 'seat', "
306 "udev device property ID_SEAT)\n");
307 return -1;
308 }
309
310 return 0;
311}
312
U. Artie Eoff71db0fd2014-04-17 07:53:22 -0700313static void
Peter Hutterer3b843d32014-06-25 14:07:36 +1000314libinput_log_func(struct libinput *libinput,
315 enum libinput_log_priority priority,
316 const char *format, va_list args)
U. Artie Eoff71db0fd2014-04-17 07:53:22 -0700317{
318 weston_vlog(format, args);
319}
320
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100321int
Pekka Paalaneneb4fd352014-09-12 12:07:43 +0300322udev_input_init(struct udev_input *input, struct weston_compositor *c,
Giulio Camuffo8aedf7b2016-06-02 21:48:12 +0300323 struct udev *udev, const char *seat_id,
324 udev_configure_device_t configure_device)
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100325{
Pekka Paalaneneb4fd352014-09-12 12:07:43 +0300326 enum libinput_log_priority priority = LIBINPUT_LOG_PRIORITY_INFO;
U. Artie Eoffc81c4242014-04-17 07:53:23 -0700327 const char *log_priority = NULL;
328
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100329 memset(input, 0, sizeof *input);
330
331 input->compositor = c;
Giulio Camuffo8aedf7b2016-06-02 21:48:12 +0300332 input->configure_device = configure_device;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100333
U. Artie Eoffc81c4242014-04-17 07:53:23 -0700334 log_priority = getenv("WESTON_LIBINPUT_LOG_PRIORITY");
U. Artie Eoff24713f62014-05-09 11:24:40 -0700335
Peter Hutterer3b843d32014-06-25 14:07:36 +1000336 input->libinput = libinput_udev_create_context(&libinput_interface,
337 input, udev);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100338 if (!input->libinput) {
339 return -1;
340 }
Peter Hutterer3b843d32014-06-25 14:07:36 +1000341
342 libinput_log_set_handler(input->libinput, &libinput_log_func);
343
344 if (log_priority) {
345 if (strcmp(log_priority, "debug") == 0) {
Pekka Paalaneneb4fd352014-09-12 12:07:43 +0300346 priority = LIBINPUT_LOG_PRIORITY_DEBUG;
Peter Hutterer3b843d32014-06-25 14:07:36 +1000347 } else if (strcmp(log_priority, "info") == 0) {
Pekka Paalaneneb4fd352014-09-12 12:07:43 +0300348 priority = LIBINPUT_LOG_PRIORITY_INFO;
Peter Hutterer3b843d32014-06-25 14:07:36 +1000349 } else if (strcmp(log_priority, "error") == 0) {
Pekka Paalaneneb4fd352014-09-12 12:07:43 +0300350 priority = LIBINPUT_LOG_PRIORITY_ERROR;
Peter Hutterer3b843d32014-06-25 14:07:36 +1000351 }
352 }
353
Pekka Paalaneneb4fd352014-09-12 12:07:43 +0300354 libinput_log_set_priority(input->libinput, priority);
355
Peter Hutterer3b843d32014-06-25 14:07:36 +1000356 if (libinput_udev_assign_seat(input->libinput, seat_id) != 0) {
357 libinput_unref(input->libinput);
358 return -1;
359 }
360
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100361 process_events(input);
362
363 return udev_input_enable(input);
364}
365
366void
367udev_input_destroy(struct udev_input *input)
368{
369 struct udev_seat *seat, *next;
370
Derek Foreman0e4e5702017-07-25 16:39:20 -0500371 if (input->libinput_source)
372 wl_event_source_remove(input->libinput_source);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100373 wl_list_for_each_safe(seat, next, &input->compositor->seat_list, base.link)
374 udev_seat_destroy(seat);
Peter Hutterer3b843d32014-06-25 14:07:36 +1000375 libinput_unref(input->libinput);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100376}
377
378static void
379udev_seat_led_update(struct weston_seat *seat_base, enum weston_led leds)
380{
381 struct udev_seat *seat = (struct udev_seat *) seat_base;
382 struct evdev_device *device;
383
384 wl_list_for_each(device, &seat->devices_list, link)
385 evdev_led_update(device, leds);
386}
387
388static void
Pekka Paalanen8dc6db82018-03-20 13:29:40 +0200389udev_seat_output_changed(struct udev_seat *seat, struct weston_output *output)
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100390{
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100391 struct evdev_device *device;
Pekka Paalanenfd02efb2018-03-19 14:55:41 +0200392 struct weston_output *found;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100393
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300394 wl_list_for_each(device, &seat->devices_list, link) {
Pekka Paalanenfd02efb2018-03-19 14:55:41 +0200395 /* If we find any input device without an associated output
396 * or an output name to associate with, just tie it with the
Emmanuel Gil Peyrot426c2462019-02-20 16:33:32 +0100397 * output we got here - the default assignment.
Pekka Paalanenfd02efb2018-03-19 14:55:41 +0200398 */
399 if (!device->output_name) {
400 if (!device->output)
401 evdev_device_set_output(device, output);
402
403 continue;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100404 }
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300405
Pekka Paalanenfd02efb2018-03-19 14:55:41 +0200406 /* Update all devices' output associations, may they gain or
407 * lose it.
408 */
409 found = output_find_by_head_name(output->compositor,
410 device->output_name);
411 evdev_device_set_output(device, found);
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300412 }
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100413}
414
Pekka Paalanen8dc6db82018-03-20 13:29:40 +0200415static void
416notify_output_create(struct wl_listener *listener, void *data)
417{
418 struct udev_seat *seat = container_of(listener, struct udev_seat,
419 output_create_listener);
420 struct weston_output *output = data;
421
422 udev_seat_output_changed(seat, output);
423}
424
425static void
426notify_output_heads_changed(struct wl_listener *listener, void *data)
427{
428 struct udev_seat *seat = container_of(listener, struct udev_seat,
429 output_heads_listener);
430 struct weston_output *output = data;
431
432 udev_seat_output_changed(seat, output);
433}
434
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100435static struct udev_seat *
436udev_seat_create(struct udev_input *input, const char *seat_name)
437{
438 struct weston_compositor *c = input->compositor;
439 struct udev_seat *seat;
440
441 seat = zalloc(sizeof *seat);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100442 if (!seat)
443 return NULL;
Bryce W. Harringtonbfd74f42014-04-21 23:51:02 +0000444
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100445 weston_seat_init(&seat->base, c, seat_name);
446 seat->base.led_update = udev_seat_led_update;
447
448 seat->output_create_listener.notify = notify_output_create;
449 wl_signal_add(&c->output_created_signal,
450 &seat->output_create_listener);
451
Pekka Paalanen8dc6db82018-03-20 13:29:40 +0200452 seat->output_heads_listener.notify = notify_output_heads_changed;
453 wl_signal_add(&c->output_heads_changed_signal,
454 &seat->output_heads_listener);
455
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100456 wl_list_init(&seat->devices_list);
457
458 return seat;
459}
460
461static void
462udev_seat_destroy(struct udev_seat *seat)
463{
Derek Foreman1281a362015-07-31 16:55:32 -0500464 struct weston_keyboard *keyboard =
465 weston_seat_get_keyboard(&seat->base);
466
Derek Foreman1281a362015-07-31 16:55:32 -0500467 if (keyboard)
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100468 notify_keyboard_focus_out(&seat->base);
Derek Foreman87c862a2015-08-06 12:19:51 -0500469
470 udev_seat_remove_devices(seat);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100471 weston_seat_release(&seat->base);
472 wl_list_remove(&seat->output_create_listener.link);
Pekka Paalanen8dc6db82018-03-20 13:29:40 +0200473 wl_list_remove(&seat->output_heads_listener.link);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100474 free(seat);
475}
476
477struct udev_seat *
478udev_seat_get_named(struct udev_input *input, const char *seat_name)
479{
480 struct udev_seat *seat;
481
482 wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
483 if (strcmp(seat->base.seat_name, seat_name) == 0)
484 return seat;
485 }
486
487 return udev_seat_create(input, seat_name);
488}