blob: 69dcbf8306d59d7163b85de8965a2543f9d56903 [file] [log] [blame]
Jonas Ådahle0de3c22014-03-12 22:08:42 +01001/*
2 * Copyright © 2010 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
29#include <errno.h>
30#include <stdlib.h>
31#include <string.h>
32#include <linux/input.h>
33#include <unistd.h>
34#include <fcntl.h>
35#include <mtdev.h>
36#include <assert.h>
37#include <libinput.h>
38
39#include "compositor.h"
40#include "libinput-device.h"
Jon Cruz867d50e2015-06-15 15:37:10 -070041#include "shared/helpers.h"
Jonas Ådahle0de3c22014-03-12 22:08:42 +010042
Jonas Ådahle0de3c22014-03-12 22:08:42 +010043void
44evdev_led_update(struct evdev_device *device, enum weston_led weston_leds)
45{
46 enum libinput_led leds = 0;
47
48 if (weston_leds & LED_NUM_LOCK)
49 leds |= LIBINPUT_LED_NUM_LOCK;
50 if (weston_leds & LED_CAPS_LOCK)
51 leds |= LIBINPUT_LED_CAPS_LOCK;
52 if (weston_leds & LED_SCROLL_LOCK)
53 leds |= LIBINPUT_LED_SCROLL_LOCK;
54
55 libinput_device_led_update(device->device, leds);
56}
57
58static void
59handle_keyboard_key(struct libinput_device *libinput_device,
60 struct libinput_event_keyboard *keyboard_event)
61{
62 struct evdev_device *device =
63 libinput_device_get_user_data(libinput_device);
Jonas Ådahl90d1ac82015-01-30 12:23:00 +080064 int key_state =
65 libinput_event_keyboard_get_key_state(keyboard_event);
66 int seat_key_count =
67 libinput_event_keyboard_get_seat_key_count(keyboard_event);
68
69 /* Ignore key events that are not seat wide state changes. */
70 if ((key_state == LIBINPUT_KEY_STATE_PRESSED &&
71 seat_key_count != 1) ||
72 (key_state == LIBINPUT_KEY_STATE_RELEASED &&
73 seat_key_count != 0))
74 return;
Jonas Ådahle0de3c22014-03-12 22:08:42 +010075
76 notify_key(device->seat,
77 libinput_event_keyboard_get_time(keyboard_event),
78 libinput_event_keyboard_get_key(keyboard_event),
79 libinput_event_keyboard_get_key_state(keyboard_event),
80 STATE_UPDATE_AUTOMATIC);
81}
82
83static void
84handle_pointer_motion(struct libinput_device *libinput_device,
85 struct libinput_event_pointer *pointer_event)
86{
87 struct evdev_device *device =
88 libinput_device_get_user_data(libinput_device);
Jonas Ådahl26714b42014-06-02 23:15:48 +020089 wl_fixed_t dx, dy;
Jonas Ådahle0de3c22014-03-12 22:08:42 +010090
Jonas Ådahl26714b42014-06-02 23:15:48 +020091 dx = wl_fixed_from_double(libinput_event_pointer_get_dx(pointer_event));
92 dy = wl_fixed_from_double(libinput_event_pointer_get_dy(pointer_event));
Jonas Ådahle0de3c22014-03-12 22:08:42 +010093 notify_motion(device->seat,
94 libinput_event_pointer_get_time(pointer_event),
Jonas Ådahl26714b42014-06-02 23:15:48 +020095 dx,
96 dy);
Jonas Ådahle0de3c22014-03-12 22:08:42 +010097}
98
99static void
100handle_pointer_motion_absolute(
101 struct libinput_device *libinput_device,
102 struct libinput_event_pointer *pointer_event)
103{
104 struct evdev_device *device =
105 libinput_device_get_user_data(libinput_device);
106 struct weston_output *output = device->output;
107 uint32_t time;
108 wl_fixed_t x, y;
109 uint32_t width, height;
110
111 if (!output)
112 return;
113
114 time = libinput_event_pointer_get_time(pointer_event);
115 width = device->output->current_mode->width;
116 height = device->output->current_mode->height;
117
Jonas Ådahl26714b42014-06-02 23:15:48 +0200118 x = wl_fixed_from_double(
119 libinput_event_pointer_get_absolute_x_transformed(pointer_event,
120 width));
121 y = wl_fixed_from_double(
122 libinput_event_pointer_get_absolute_y_transformed(pointer_event,
123 height));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100124
125 weston_output_transform_coordinate(device->output, x, y, &x, &y);
126 notify_motion_absolute(device->seat, time, x, y);
127}
128
129static void
130handle_pointer_button(struct libinput_device *libinput_device,
131 struct libinput_event_pointer *pointer_event)
132{
133 struct evdev_device *device =
134 libinput_device_get_user_data(libinput_device);
Jonas Ådahle90b9e92015-01-30 12:22:59 +0800135 int button_state =
136 libinput_event_pointer_get_button_state(pointer_event);
137 int seat_button_count =
138 libinput_event_pointer_get_seat_button_count(pointer_event);
139
140 /* Ignore button events that are not seat wide state changes. */
141 if ((button_state == LIBINPUT_BUTTON_STATE_PRESSED &&
142 seat_button_count != 1) ||
143 (button_state == LIBINPUT_BUTTON_STATE_RELEASED &&
144 seat_button_count != 0))
145 return;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100146
147 notify_button(device->seat,
148 libinput_event_pointer_get_time(pointer_event),
149 libinput_event_pointer_get_button(pointer_event),
150 libinput_event_pointer_get_button_state(pointer_event));
151}
152
Peter Hutterer5dddd412015-01-15 13:14:43 +1000153static double
154normalize_scroll(struct libinput_event_pointer *pointer_event,
155 enum libinput_pointer_axis axis)
156{
157 static int warned;
158 enum libinput_pointer_axis_source source;
159 double value;
160
161 source = libinput_event_pointer_get_axis_source(pointer_event);
162 /* libinput < 0.8 sent wheel click events with value 10. Since 0.8
163 the value is the angle of the click in degrees. To keep
164 backwards-compat with existing clients, we just send multiples of
165 the click count.
166 */
167 switch (source) {
168 case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
169 value = 10 * libinput_event_pointer_get_axis_value_discrete(
170 pointer_event,
171 axis);
172 break;
173 case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
174 case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
175 value = libinput_event_pointer_get_axis_value(pointer_event,
176 axis);
177 break;
178 default:
179 value = 0;
180 if (warned < 5) {
181 weston_log("Unknown scroll source %d. Event discarded\n",
182 source);
183 warned++;
184 }
185 break;
186 }
187
188 return value;
189}
190
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100191static void
192handle_pointer_axis(struct libinput_device *libinput_device,
193 struct libinput_event_pointer *pointer_event)
194{
195 struct evdev_device *device =
196 libinput_device_get_user_data(libinput_device);
Jonas Ådahl26714b42014-06-02 23:15:48 +0200197 double value;
Peter Huttererc54f23d2015-01-13 11:55:37 +1000198 enum libinput_pointer_axis axis;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100199
Peter Huttererc54f23d2015-01-13 11:55:37 +1000200 axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
201 if (libinput_event_pointer_has_axis(pointer_event, axis)) {
Peter Hutterer5dddd412015-01-15 13:14:43 +1000202 value = normalize_scroll(pointer_event, axis);
Peter Huttererc54f23d2015-01-13 11:55:37 +1000203 notify_axis(device->seat,
204 libinput_event_pointer_get_time(pointer_event),
205 WL_POINTER_AXIS_VERTICAL_SCROLL,
206 wl_fixed_from_double(value));
207 }
208
209 axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
210 if (libinput_event_pointer_has_axis(pointer_event, axis)) {
Peter Hutterer5dddd412015-01-15 13:14:43 +1000211 value = normalize_scroll(pointer_event, axis);
Peter Huttererc54f23d2015-01-13 11:55:37 +1000212 notify_axis(device->seat,
213 libinput_event_pointer_get_time(pointer_event),
214 WL_POINTER_AXIS_HORIZONTAL_SCROLL,
215 wl_fixed_from_double(value));
216 }
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100217}
218
219static void
220handle_touch_with_coords(struct libinput_device *libinput_device,
221 struct libinput_event_touch *touch_event,
222 int touch_type)
223{
224 struct evdev_device *device =
225 libinput_device_get_user_data(libinput_device);
226 wl_fixed_t x;
227 wl_fixed_t y;
228 uint32_t width, height;
229 uint32_t time;
230 int32_t slot;
231
Ander Conselvan de Oliveiraf957dfb2014-04-24 15:11:14 +0300232 if (!device->output)
233 return;
234
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100235 time = libinput_event_touch_get_time(touch_event);
236 slot = libinput_event_touch_get_seat_slot(touch_event);
237
238 width = device->output->current_mode->width;
239 height = device->output->current_mode->height;
Jonas Ådahl26714b42014-06-02 23:15:48 +0200240 x = wl_fixed_from_double(
241 libinput_event_touch_get_x_transformed(touch_event, width));
242 y = wl_fixed_from_double(
243 libinput_event_touch_get_y_transformed(touch_event, height));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100244
245 weston_output_transform_coordinate(device->output,
246 x, y, &x, &y);
247
248 notify_touch(device->seat, time, slot, x, y, touch_type);
249}
250
251static void
252handle_touch_down(struct libinput_device *device,
253 struct libinput_event_touch *touch_event)
254{
255 handle_touch_with_coords(device, touch_event, WL_TOUCH_DOWN);
256}
257
258static void
259handle_touch_motion(struct libinput_device *device,
260 struct libinput_event_touch *touch_event)
261{
262 handle_touch_with_coords(device, touch_event, WL_TOUCH_MOTION);
263}
264
265static void
266handle_touch_up(struct libinput_device *libinput_device,
267 struct libinput_event_touch *touch_event)
268{
269 struct evdev_device *device =
270 libinput_device_get_user_data(libinput_device);
271 uint32_t time = libinput_event_touch_get_time(touch_event);
272 int32_t slot = libinput_event_touch_get_seat_slot(touch_event);
273
274 notify_touch(device->seat, time, slot, 0, 0, WL_TOUCH_UP);
275}
276
Jonas Ådahl1679f232014-04-12 09:39:51 +0200277static void
278handle_touch_frame(struct libinput_device *libinput_device,
279 struct libinput_event_touch *touch_event)
280{
281 struct evdev_device *device =
282 libinput_device_get_user_data(libinput_device);
283 struct weston_seat *seat = device->seat;
284
285 notify_touch_frame(seat);
286}
287
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100288int
289evdev_device_process_event(struct libinput_event *event)
290{
291 struct libinput_device *libinput_device =
292 libinput_event_get_device(event);
293 int handled = 1;
294
295 switch (libinput_event_get_type(event)) {
296 case LIBINPUT_EVENT_KEYBOARD_KEY:
297 handle_keyboard_key(libinput_device,
298 libinput_event_get_keyboard_event(event));
299 break;
300 case LIBINPUT_EVENT_POINTER_MOTION:
301 handle_pointer_motion(libinput_device,
302 libinput_event_get_pointer_event(event));
303 break;
304 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
305 handle_pointer_motion_absolute(
306 libinput_device,
307 libinput_event_get_pointer_event(event));
308 break;
309 case LIBINPUT_EVENT_POINTER_BUTTON:
310 handle_pointer_button(libinput_device,
311 libinput_event_get_pointer_event(event));
312 break;
313 case LIBINPUT_EVENT_POINTER_AXIS:
314 handle_pointer_axis(libinput_device,
315 libinput_event_get_pointer_event(event));
316 break;
317 case LIBINPUT_EVENT_TOUCH_DOWN:
318 handle_touch_down(libinput_device,
319 libinput_event_get_touch_event(event));
320 break;
321 case LIBINPUT_EVENT_TOUCH_MOTION:
322 handle_touch_motion(libinput_device,
323 libinput_event_get_touch_event(event));
324 break;
325 case LIBINPUT_EVENT_TOUCH_UP:
326 handle_touch_up(libinput_device,
327 libinput_event_get_touch_event(event));
U. Artie Eoffcd9e5452014-04-17 07:53:24 -0700328 break;
Jonas Ådahl1679f232014-04-12 09:39:51 +0200329 case LIBINPUT_EVENT_TOUCH_FRAME:
330 handle_touch_frame(libinput_device,
331 libinput_event_get_touch_event(event));
332 break;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100333 default:
334 handled = 0;
335 weston_log("unknown libinput event %d\n",
336 libinput_event_get_type(event));
337 }
338
339 return handled;
340}
341
342static void
343notify_output_destroy(struct wl_listener *listener, void *data)
344{
345 struct evdev_device *device =
346 container_of(listener,
347 struct evdev_device, output_destroy_listener);
348 struct weston_compositor *c = device->seat->compositor;
349 struct weston_output *output;
350
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300351 if (!device->output_name && !wl_list_empty(&c->output_list)) {
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100352 output = container_of(c->output_list.next,
353 struct weston_output, link);
354 evdev_device_set_output(device, output);
355 } else {
356 device->output = NULL;
357 }
358}
359
Peter Hutterer3fbba492014-09-09 13:02:25 +1000360/**
361 * The WL_CALIBRATION property requires a pixel-specific matrix to be
362 * applied after scaling device coordinates to screen coordinates. libinput
363 * can't do that, so we need to convert the calibration to the normalized
364 * format libinput expects.
365 */
366static void
367evdev_device_set_calibration(struct evdev_device *device)
368{
369 struct udev *udev;
370 struct udev_device *udev_device = NULL;
371 const char *sysname = libinput_device_get_sysname(device->device);
372 const char *calibration_values;
373 uint32_t width, height;
374 float calibration[6];
375 enum libinput_config_status status;
376
377 if (!device->output)
378 return;
379
380 width = device->output->width;
381 height = device->output->height;
382 if (width == 0 || height == 0)
383 return;
384
385 /* If libinput has a pre-set calibration matrix, don't override it */
386 if (!libinput_device_config_calibration_has_matrix(device->device) ||
387 libinput_device_config_calibration_get_default_matrix(
388 device->device,
389 calibration) != 0)
390 return;
391
392 udev = udev_new();
393 if (!udev)
394 return;
395
396 udev_device = udev_device_new_from_subsystem_sysname(udev,
397 "input",
398 sysname);
399 if (!udev_device)
400 goto out;
401
402 calibration_values =
403 udev_device_get_property_value(udev_device,
404 "WL_CALIBRATION");
405
406 if (!calibration_values || sscanf(calibration_values,
407 "%f %f %f %f %f %f",
408 &calibration[0],
409 &calibration[1],
410 &calibration[2],
411 &calibration[3],
412 &calibration[4],
413 &calibration[5]) != 6)
414 goto out;
415
416 weston_log("Applying calibration: %f %f %f %f %f %f "
417 "(normalized %f %f)\n",
418 calibration[0],
419 calibration[1],
420 calibration[2],
421 calibration[3],
422 calibration[4],
423 calibration[5],
424 calibration[2] / width,
425 calibration[5] / height);
426
427 /* normalize to a format libinput can use. There is a chance of
428 this being wrong if the width/height don't match the device
429 width/height but I'm not sure how to fix that */
430 calibration[2] /= width;
431 calibration[5] /= height;
432
433 status = libinput_device_config_calibration_set_matrix(device->device,
434 calibration);
435 if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
436 weston_log("Failed to apply calibration.\n");
437
438out:
439 if (udev_device)
440 udev_device_unref(udev_device);
441 udev_unref(udev);
442}
443
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100444void
445evdev_device_set_output(struct evdev_device *device,
446 struct weston_output *output)
447{
U. Artie Eoff161c6c52014-04-17 07:53:25 -0700448 if (device->output_destroy_listener.notify) {
449 wl_list_remove(&device->output_destroy_listener.link);
450 device->output_destroy_listener.notify = NULL;
451 }
452
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100453 device->output = output;
454 device->output_destroy_listener.notify = notify_output_destroy;
455 wl_signal_add(&output->destroy_signal,
456 &device->output_destroy_listener);
Peter Hutterer3fbba492014-09-09 13:02:25 +1000457 evdev_device_set_calibration(device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100458}
459
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200460static void
461configure_device(struct evdev_device *device)
462{
463 struct weston_compositor *compositor = device->seat->compositor;
464 struct weston_config_section *s;
465 int enable_tap;
466 int enable_tap_default;
467
468 s = weston_config_get_section(compositor->config,
469 "libinput", NULL, NULL);
470
471 if (libinput_device_config_tap_get_finger_count(device->device) > 0) {
472 enable_tap_default =
473 libinput_device_config_tap_get_default_enabled(
474 device->device);
475 weston_config_section_get_bool(s, "enable_tap",
476 &enable_tap,
477 enable_tap_default);
478 libinput_device_config_tap_set_enabled(device->device,
479 enable_tap);
480 }
Peter Hutterer3fbba492014-09-09 13:02:25 +1000481
482 evdev_device_set_calibration(device);
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200483}
484
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100485struct evdev_device *
486evdev_device_create(struct libinput_device *libinput_device,
487 struct weston_seat *seat)
488{
489 struct evdev_device *device;
490
491 device = zalloc(sizeof *device);
492 if (device == NULL)
493 return NULL;
494
495 device->seat = seat;
496 wl_list_init(&device->link);
497 device->device = libinput_device;
498
499 if (libinput_device_has_capability(libinput_device,
500 LIBINPUT_DEVICE_CAP_KEYBOARD)) {
501 weston_seat_init_keyboard(seat, NULL);
502 device->seat_caps |= EVDEV_SEAT_KEYBOARD;
503 }
504 if (libinput_device_has_capability(libinput_device,
505 LIBINPUT_DEVICE_CAP_POINTER)) {
506 weston_seat_init_pointer(seat);
507 device->seat_caps |= EVDEV_SEAT_POINTER;
508 }
509 if (libinput_device_has_capability(libinput_device,
510 LIBINPUT_DEVICE_CAP_TOUCH)) {
511 weston_seat_init_touch(seat);
512 device->seat_caps |= EVDEV_SEAT_TOUCH;
513 }
514
515 libinput_device_set_user_data(libinput_device, device);
516 libinput_device_ref(libinput_device);
517
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200518 configure_device(device);
519
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100520 return device;
521}
522
523void
524evdev_device_destroy(struct evdev_device *device)
525{
526 if (device->seat_caps & EVDEV_SEAT_POINTER)
527 weston_seat_release_pointer(device->seat);
528 if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
529 weston_seat_release_keyboard(device->seat);
530 if (device->seat_caps & EVDEV_SEAT_TOUCH)
531 weston_seat_release_touch(device->seat);
532
533 if (device->output)
534 wl_list_remove(&device->output_destroy_listener.link);
535 wl_list_remove(&device->link);
536 libinput_device_unref(device->device);
537 free(device->devnode);
538 free(device->output_name);
539 free(device);
540}
541
542void
543evdev_notify_keyboard_focus(struct weston_seat *seat,
544 struct wl_list *evdev_devices)
545{
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100546 struct wl_array keys;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100547
Derek Foremand621df22014-11-19 11:04:12 -0600548 if (seat->keyboard_device_count == 0)
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100549 return;
550
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100551 wl_array_init(&keys);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100552 notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100553 wl_array_release(&keys);
554}