blob: 567e5ea9ae8e33d29ab05c533f5c6e00863bee5b [file] [log] [blame]
Jonas Ådahle0de3c22014-03-12 22:08:42 +01001/*
2 * Copyright © 2010 Intel Corporation
3 * Copyright © 2013 Jonas Ådahl
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#include "config.h"
25
26#include <errno.h>
27#include <stdlib.h>
28#include <string.h>
29#include <linux/input.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <mtdev.h>
33#include <assert.h>
34#include <libinput.h>
35
36#include "compositor.h"
37#include "libinput-device.h"
38
39#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
40
41void
42evdev_led_update(struct evdev_device *device, enum weston_led weston_leds)
43{
44 enum libinput_led leds = 0;
45
46 if (weston_leds & LED_NUM_LOCK)
47 leds |= LIBINPUT_LED_NUM_LOCK;
48 if (weston_leds & LED_CAPS_LOCK)
49 leds |= LIBINPUT_LED_CAPS_LOCK;
50 if (weston_leds & LED_SCROLL_LOCK)
51 leds |= LIBINPUT_LED_SCROLL_LOCK;
52
53 libinput_device_led_update(device->device, leds);
54}
55
56static void
57handle_keyboard_key(struct libinput_device *libinput_device,
58 struct libinput_event_keyboard *keyboard_event)
59{
60 struct evdev_device *device =
61 libinput_device_get_user_data(libinput_device);
Jonas Ådahl90d1ac82015-01-30 12:23:00 +080062 int key_state =
63 libinput_event_keyboard_get_key_state(keyboard_event);
64 int seat_key_count =
65 libinput_event_keyboard_get_seat_key_count(keyboard_event);
66
67 /* Ignore key events that are not seat wide state changes. */
68 if ((key_state == LIBINPUT_KEY_STATE_PRESSED &&
69 seat_key_count != 1) ||
70 (key_state == LIBINPUT_KEY_STATE_RELEASED &&
71 seat_key_count != 0))
72 return;
Jonas Ådahle0de3c22014-03-12 22:08:42 +010073
74 notify_key(device->seat,
75 libinput_event_keyboard_get_time(keyboard_event),
76 libinput_event_keyboard_get_key(keyboard_event),
77 libinput_event_keyboard_get_key_state(keyboard_event),
78 STATE_UPDATE_AUTOMATIC);
79}
80
81static void
82handle_pointer_motion(struct libinput_device *libinput_device,
83 struct libinput_event_pointer *pointer_event)
84{
85 struct evdev_device *device =
86 libinput_device_get_user_data(libinput_device);
Jonas Ådahl26714b42014-06-02 23:15:48 +020087 wl_fixed_t dx, dy;
Jonas Ådahle0de3c22014-03-12 22:08:42 +010088
Jonas Ådahl26714b42014-06-02 23:15:48 +020089 dx = wl_fixed_from_double(libinput_event_pointer_get_dx(pointer_event));
90 dy = wl_fixed_from_double(libinput_event_pointer_get_dy(pointer_event));
Jonas Ådahle0de3c22014-03-12 22:08:42 +010091 notify_motion(device->seat,
92 libinput_event_pointer_get_time(pointer_event),
Jonas Ådahl26714b42014-06-02 23:15:48 +020093 dx,
94 dy);
Jonas Ådahle0de3c22014-03-12 22:08:42 +010095}
96
97static void
98handle_pointer_motion_absolute(
99 struct libinput_device *libinput_device,
100 struct libinput_event_pointer *pointer_event)
101{
102 struct evdev_device *device =
103 libinput_device_get_user_data(libinput_device);
104 struct weston_output *output = device->output;
105 uint32_t time;
106 wl_fixed_t x, y;
107 uint32_t width, height;
108
109 if (!output)
110 return;
111
112 time = libinput_event_pointer_get_time(pointer_event);
113 width = device->output->current_mode->width;
114 height = device->output->current_mode->height;
115
Jonas Ådahl26714b42014-06-02 23:15:48 +0200116 x = wl_fixed_from_double(
117 libinput_event_pointer_get_absolute_x_transformed(pointer_event,
118 width));
119 y = wl_fixed_from_double(
120 libinput_event_pointer_get_absolute_y_transformed(pointer_event,
121 height));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100122
123 weston_output_transform_coordinate(device->output, x, y, &x, &y);
124 notify_motion_absolute(device->seat, time, x, y);
125}
126
127static void
128handle_pointer_button(struct libinput_device *libinput_device,
129 struct libinput_event_pointer *pointer_event)
130{
131 struct evdev_device *device =
132 libinput_device_get_user_data(libinput_device);
Jonas Ådahle90b9e92015-01-30 12:22:59 +0800133 int button_state =
134 libinput_event_pointer_get_button_state(pointer_event);
135 int seat_button_count =
136 libinput_event_pointer_get_seat_button_count(pointer_event);
137
138 /* Ignore button events that are not seat wide state changes. */
139 if ((button_state == LIBINPUT_BUTTON_STATE_PRESSED &&
140 seat_button_count != 1) ||
141 (button_state == LIBINPUT_BUTTON_STATE_RELEASED &&
142 seat_button_count != 0))
143 return;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100144
145 notify_button(device->seat,
146 libinput_event_pointer_get_time(pointer_event),
147 libinput_event_pointer_get_button(pointer_event),
148 libinput_event_pointer_get_button_state(pointer_event));
149}
150
Peter Hutterer5dddd412015-01-15 13:14:43 +1000151static double
152normalize_scroll(struct libinput_event_pointer *pointer_event,
153 enum libinput_pointer_axis axis)
154{
155 static int warned;
156 enum libinput_pointer_axis_source source;
157 double value;
158
159 source = libinput_event_pointer_get_axis_source(pointer_event);
160 /* libinput < 0.8 sent wheel click events with value 10. Since 0.8
161 the value is the angle of the click in degrees. To keep
162 backwards-compat with existing clients, we just send multiples of
163 the click count.
164 */
165 switch (source) {
166 case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
167 value = 10 * libinput_event_pointer_get_axis_value_discrete(
168 pointer_event,
169 axis);
170 break;
171 case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
172 case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
173 value = libinput_event_pointer_get_axis_value(pointer_event,
174 axis);
175 break;
176 default:
177 value = 0;
178 if (warned < 5) {
179 weston_log("Unknown scroll source %d. Event discarded\n",
180 source);
181 warned++;
182 }
183 break;
184 }
185
186 return value;
187}
188
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100189static void
190handle_pointer_axis(struct libinput_device *libinput_device,
191 struct libinput_event_pointer *pointer_event)
192{
193 struct evdev_device *device =
194 libinput_device_get_user_data(libinput_device);
Jonas Ådahl26714b42014-06-02 23:15:48 +0200195 double value;
Peter Huttererc54f23d2015-01-13 11:55:37 +1000196 enum libinput_pointer_axis axis;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100197
Peter Huttererc54f23d2015-01-13 11:55:37 +1000198 axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
199 if (libinput_event_pointer_has_axis(pointer_event, axis)) {
Peter Hutterer5dddd412015-01-15 13:14:43 +1000200 value = normalize_scroll(pointer_event, axis);
Peter Huttererc54f23d2015-01-13 11:55:37 +1000201 notify_axis(device->seat,
202 libinput_event_pointer_get_time(pointer_event),
203 WL_POINTER_AXIS_VERTICAL_SCROLL,
204 wl_fixed_from_double(value));
205 }
206
207 axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
208 if (libinput_event_pointer_has_axis(pointer_event, axis)) {
Peter Hutterer5dddd412015-01-15 13:14:43 +1000209 value = normalize_scroll(pointer_event, axis);
Peter Huttererc54f23d2015-01-13 11:55:37 +1000210 notify_axis(device->seat,
211 libinput_event_pointer_get_time(pointer_event),
212 WL_POINTER_AXIS_HORIZONTAL_SCROLL,
213 wl_fixed_from_double(value));
214 }
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100215}
216
217static void
218handle_touch_with_coords(struct libinput_device *libinput_device,
219 struct libinput_event_touch *touch_event,
220 int touch_type)
221{
222 struct evdev_device *device =
223 libinput_device_get_user_data(libinput_device);
224 wl_fixed_t x;
225 wl_fixed_t y;
226 uint32_t width, height;
227 uint32_t time;
228 int32_t slot;
229
Ander Conselvan de Oliveiraf957dfb2014-04-24 15:11:14 +0300230 if (!device->output)
231 return;
232
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100233 time = libinput_event_touch_get_time(touch_event);
234 slot = libinput_event_touch_get_seat_slot(touch_event);
235
236 width = device->output->current_mode->width;
237 height = device->output->current_mode->height;
Jonas Ådahl26714b42014-06-02 23:15:48 +0200238 x = wl_fixed_from_double(
239 libinput_event_touch_get_x_transformed(touch_event, width));
240 y = wl_fixed_from_double(
241 libinput_event_touch_get_y_transformed(touch_event, height));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100242
243 weston_output_transform_coordinate(device->output,
244 x, y, &x, &y);
245
246 notify_touch(device->seat, time, slot, x, y, touch_type);
247}
248
249static void
250handle_touch_down(struct libinput_device *device,
251 struct libinput_event_touch *touch_event)
252{
253 handle_touch_with_coords(device, touch_event, WL_TOUCH_DOWN);
254}
255
256static void
257handle_touch_motion(struct libinput_device *device,
258 struct libinput_event_touch *touch_event)
259{
260 handle_touch_with_coords(device, touch_event, WL_TOUCH_MOTION);
261}
262
263static void
264handle_touch_up(struct libinput_device *libinput_device,
265 struct libinput_event_touch *touch_event)
266{
267 struct evdev_device *device =
268 libinput_device_get_user_data(libinput_device);
269 uint32_t time = libinput_event_touch_get_time(touch_event);
270 int32_t slot = libinput_event_touch_get_seat_slot(touch_event);
271
272 notify_touch(device->seat, time, slot, 0, 0, WL_TOUCH_UP);
273}
274
Jonas Ådahl1679f232014-04-12 09:39:51 +0200275static void
276handle_touch_frame(struct libinput_device *libinput_device,
277 struct libinput_event_touch *touch_event)
278{
279 struct evdev_device *device =
280 libinput_device_get_user_data(libinput_device);
281 struct weston_seat *seat = device->seat;
282
283 notify_touch_frame(seat);
284}
285
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100286int
287evdev_device_process_event(struct libinput_event *event)
288{
289 struct libinput_device *libinput_device =
290 libinput_event_get_device(event);
291 int handled = 1;
292
293 switch (libinput_event_get_type(event)) {
294 case LIBINPUT_EVENT_KEYBOARD_KEY:
295 handle_keyboard_key(libinput_device,
296 libinput_event_get_keyboard_event(event));
297 break;
298 case LIBINPUT_EVENT_POINTER_MOTION:
299 handle_pointer_motion(libinput_device,
300 libinput_event_get_pointer_event(event));
301 break;
302 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
303 handle_pointer_motion_absolute(
304 libinput_device,
305 libinput_event_get_pointer_event(event));
306 break;
307 case LIBINPUT_EVENT_POINTER_BUTTON:
308 handle_pointer_button(libinput_device,
309 libinput_event_get_pointer_event(event));
310 break;
311 case LIBINPUT_EVENT_POINTER_AXIS:
312 handle_pointer_axis(libinput_device,
313 libinput_event_get_pointer_event(event));
314 break;
315 case LIBINPUT_EVENT_TOUCH_DOWN:
316 handle_touch_down(libinput_device,
317 libinput_event_get_touch_event(event));
318 break;
319 case LIBINPUT_EVENT_TOUCH_MOTION:
320 handle_touch_motion(libinput_device,
321 libinput_event_get_touch_event(event));
322 break;
323 case LIBINPUT_EVENT_TOUCH_UP:
324 handle_touch_up(libinput_device,
325 libinput_event_get_touch_event(event));
U. Artie Eoffcd9e5452014-04-17 07:53:24 -0700326 break;
Jonas Ådahl1679f232014-04-12 09:39:51 +0200327 case LIBINPUT_EVENT_TOUCH_FRAME:
328 handle_touch_frame(libinput_device,
329 libinput_event_get_touch_event(event));
330 break;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100331 default:
332 handled = 0;
333 weston_log("unknown libinput event %d\n",
334 libinput_event_get_type(event));
335 }
336
337 return handled;
338}
339
340static void
341notify_output_destroy(struct wl_listener *listener, void *data)
342{
343 struct evdev_device *device =
344 container_of(listener,
345 struct evdev_device, output_destroy_listener);
346 struct weston_compositor *c = device->seat->compositor;
347 struct weston_output *output;
348
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300349 if (!device->output_name && !wl_list_empty(&c->output_list)) {
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100350 output = container_of(c->output_list.next,
351 struct weston_output, link);
352 evdev_device_set_output(device, output);
353 } else {
354 device->output = NULL;
355 }
356}
357
Peter Hutterer3fbba492014-09-09 13:02:25 +1000358/**
359 * The WL_CALIBRATION property requires a pixel-specific matrix to be
360 * applied after scaling device coordinates to screen coordinates. libinput
361 * can't do that, so we need to convert the calibration to the normalized
362 * format libinput expects.
363 */
364static void
365evdev_device_set_calibration(struct evdev_device *device)
366{
367 struct udev *udev;
368 struct udev_device *udev_device = NULL;
369 const char *sysname = libinput_device_get_sysname(device->device);
370 const char *calibration_values;
371 uint32_t width, height;
372 float calibration[6];
373 enum libinput_config_status status;
374
375 if (!device->output)
376 return;
377
378 width = device->output->width;
379 height = device->output->height;
380 if (width == 0 || height == 0)
381 return;
382
383 /* If libinput has a pre-set calibration matrix, don't override it */
384 if (!libinput_device_config_calibration_has_matrix(device->device) ||
385 libinput_device_config_calibration_get_default_matrix(
386 device->device,
387 calibration) != 0)
388 return;
389
390 udev = udev_new();
391 if (!udev)
392 return;
393
394 udev_device = udev_device_new_from_subsystem_sysname(udev,
395 "input",
396 sysname);
397 if (!udev_device)
398 goto out;
399
400 calibration_values =
401 udev_device_get_property_value(udev_device,
402 "WL_CALIBRATION");
403
404 if (!calibration_values || sscanf(calibration_values,
405 "%f %f %f %f %f %f",
406 &calibration[0],
407 &calibration[1],
408 &calibration[2],
409 &calibration[3],
410 &calibration[4],
411 &calibration[5]) != 6)
412 goto out;
413
414 weston_log("Applying calibration: %f %f %f %f %f %f "
415 "(normalized %f %f)\n",
416 calibration[0],
417 calibration[1],
418 calibration[2],
419 calibration[3],
420 calibration[4],
421 calibration[5],
422 calibration[2] / width,
423 calibration[5] / height);
424
425 /* normalize to a format libinput can use. There is a chance of
426 this being wrong if the width/height don't match the device
427 width/height but I'm not sure how to fix that */
428 calibration[2] /= width;
429 calibration[5] /= height;
430
431 status = libinput_device_config_calibration_set_matrix(device->device,
432 calibration);
433 if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
434 weston_log("Failed to apply calibration.\n");
435
436out:
437 if (udev_device)
438 udev_device_unref(udev_device);
439 udev_unref(udev);
440}
441
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100442void
443evdev_device_set_output(struct evdev_device *device,
444 struct weston_output *output)
445{
U. Artie Eoff161c6c52014-04-17 07:53:25 -0700446 if (device->output_destroy_listener.notify) {
447 wl_list_remove(&device->output_destroy_listener.link);
448 device->output_destroy_listener.notify = NULL;
449 }
450
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100451 device->output = output;
452 device->output_destroy_listener.notify = notify_output_destroy;
453 wl_signal_add(&output->destroy_signal,
454 &device->output_destroy_listener);
Peter Hutterer3fbba492014-09-09 13:02:25 +1000455 evdev_device_set_calibration(device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100456}
457
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200458static void
459configure_device(struct evdev_device *device)
460{
461 struct weston_compositor *compositor = device->seat->compositor;
462 struct weston_config_section *s;
463 int enable_tap;
464 int enable_tap_default;
465
466 s = weston_config_get_section(compositor->config,
467 "libinput", NULL, NULL);
468
469 if (libinput_device_config_tap_get_finger_count(device->device) > 0) {
470 enable_tap_default =
471 libinput_device_config_tap_get_default_enabled(
472 device->device);
473 weston_config_section_get_bool(s, "enable_tap",
474 &enable_tap,
475 enable_tap_default);
476 libinput_device_config_tap_set_enabled(device->device,
477 enable_tap);
478 }
Peter Hutterer3fbba492014-09-09 13:02:25 +1000479
480 evdev_device_set_calibration(device);
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200481}
482
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100483struct evdev_device *
484evdev_device_create(struct libinput_device *libinput_device,
485 struct weston_seat *seat)
486{
487 struct evdev_device *device;
488
489 device = zalloc(sizeof *device);
490 if (device == NULL)
491 return NULL;
492
493 device->seat = seat;
494 wl_list_init(&device->link);
495 device->device = libinput_device;
496
497 if (libinput_device_has_capability(libinput_device,
498 LIBINPUT_DEVICE_CAP_KEYBOARD)) {
499 weston_seat_init_keyboard(seat, NULL);
500 device->seat_caps |= EVDEV_SEAT_KEYBOARD;
501 }
502 if (libinput_device_has_capability(libinput_device,
503 LIBINPUT_DEVICE_CAP_POINTER)) {
504 weston_seat_init_pointer(seat);
505 device->seat_caps |= EVDEV_SEAT_POINTER;
506 }
507 if (libinput_device_has_capability(libinput_device,
508 LIBINPUT_DEVICE_CAP_TOUCH)) {
509 weston_seat_init_touch(seat);
510 device->seat_caps |= EVDEV_SEAT_TOUCH;
511 }
512
513 libinput_device_set_user_data(libinput_device, device);
514 libinput_device_ref(libinput_device);
515
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200516 configure_device(device);
517
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100518 return device;
519}
520
521void
522evdev_device_destroy(struct evdev_device *device)
523{
524 if (device->seat_caps & EVDEV_SEAT_POINTER)
525 weston_seat_release_pointer(device->seat);
526 if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
527 weston_seat_release_keyboard(device->seat);
528 if (device->seat_caps & EVDEV_SEAT_TOUCH)
529 weston_seat_release_touch(device->seat);
530
531 if (device->output)
532 wl_list_remove(&device->output_destroy_listener.link);
533 wl_list_remove(&device->link);
534 libinput_device_unref(device->device);
535 free(device->devnode);
536 free(device->output_name);
537 free(device);
538}
539
540void
541evdev_notify_keyboard_focus(struct weston_seat *seat,
542 struct wl_list *evdev_devices)
543{
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100544 struct wl_array keys;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100545
Derek Foremand621df22014-11-19 11:04:12 -0600546 if (seat->keyboard_device_count == 0)
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100547 return;
548
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100549 wl_array_init(&keys);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100550 notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100551 wl_array_release(&keys);
552}