blob: 5c5b9b90f5d83ca49a86eeac501b347b34894afa [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);
62
63 notify_key(device->seat,
64 libinput_event_keyboard_get_time(keyboard_event),
65 libinput_event_keyboard_get_key(keyboard_event),
66 libinput_event_keyboard_get_key_state(keyboard_event),
67 STATE_UPDATE_AUTOMATIC);
68}
69
70static void
71handle_pointer_motion(struct libinput_device *libinput_device,
72 struct libinput_event_pointer *pointer_event)
73{
74 struct evdev_device *device =
75 libinput_device_get_user_data(libinput_device);
Jonas Ådahl26714b42014-06-02 23:15:48 +020076 wl_fixed_t dx, dy;
Jonas Ådahle0de3c22014-03-12 22:08:42 +010077
Jonas Ådahl26714b42014-06-02 23:15:48 +020078 dx = wl_fixed_from_double(libinput_event_pointer_get_dx(pointer_event));
79 dy = wl_fixed_from_double(libinput_event_pointer_get_dy(pointer_event));
Jonas Ådahle0de3c22014-03-12 22:08:42 +010080 notify_motion(device->seat,
81 libinput_event_pointer_get_time(pointer_event),
Jonas Ådahl26714b42014-06-02 23:15:48 +020082 dx,
83 dy);
Jonas Ådahle0de3c22014-03-12 22:08:42 +010084}
85
86static void
87handle_pointer_motion_absolute(
88 struct libinput_device *libinput_device,
89 struct libinput_event_pointer *pointer_event)
90{
91 struct evdev_device *device =
92 libinput_device_get_user_data(libinput_device);
93 struct weston_output *output = device->output;
94 uint32_t time;
95 wl_fixed_t x, y;
96 uint32_t width, height;
97
98 if (!output)
99 return;
100
101 time = libinput_event_pointer_get_time(pointer_event);
102 width = device->output->current_mode->width;
103 height = device->output->current_mode->height;
104
Jonas Ådahl26714b42014-06-02 23:15:48 +0200105 x = wl_fixed_from_double(
106 libinput_event_pointer_get_absolute_x_transformed(pointer_event,
107 width));
108 y = wl_fixed_from_double(
109 libinput_event_pointer_get_absolute_y_transformed(pointer_event,
110 height));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100111
112 weston_output_transform_coordinate(device->output, x, y, &x, &y);
113 notify_motion_absolute(device->seat, time, x, y);
114}
115
116static void
117handle_pointer_button(struct libinput_device *libinput_device,
118 struct libinput_event_pointer *pointer_event)
119{
120 struct evdev_device *device =
121 libinput_device_get_user_data(libinput_device);
Jonas Ådahle90b9e92015-01-30 12:22:59 +0800122 int button_state =
123 libinput_event_pointer_get_button_state(pointer_event);
124 int seat_button_count =
125 libinput_event_pointer_get_seat_button_count(pointer_event);
126
127 /* Ignore button events that are not seat wide state changes. */
128 if ((button_state == LIBINPUT_BUTTON_STATE_PRESSED &&
129 seat_button_count != 1) ||
130 (button_state == LIBINPUT_BUTTON_STATE_RELEASED &&
131 seat_button_count != 0))
132 return;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100133
134 notify_button(device->seat,
135 libinput_event_pointer_get_time(pointer_event),
136 libinput_event_pointer_get_button(pointer_event),
137 libinput_event_pointer_get_button_state(pointer_event));
138}
139
Peter Hutterer5dddd412015-01-15 13:14:43 +1000140static double
141normalize_scroll(struct libinput_event_pointer *pointer_event,
142 enum libinput_pointer_axis axis)
143{
144 static int warned;
145 enum libinput_pointer_axis_source source;
146 double value;
147
148 source = libinput_event_pointer_get_axis_source(pointer_event);
149 /* libinput < 0.8 sent wheel click events with value 10. Since 0.8
150 the value is the angle of the click in degrees. To keep
151 backwards-compat with existing clients, we just send multiples of
152 the click count.
153 */
154 switch (source) {
155 case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
156 value = 10 * libinput_event_pointer_get_axis_value_discrete(
157 pointer_event,
158 axis);
159 break;
160 case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
161 case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
162 value = libinput_event_pointer_get_axis_value(pointer_event,
163 axis);
164 break;
165 default:
166 value = 0;
167 if (warned < 5) {
168 weston_log("Unknown scroll source %d. Event discarded\n",
169 source);
170 warned++;
171 }
172 break;
173 }
174
175 return value;
176}
177
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100178static void
179handle_pointer_axis(struct libinput_device *libinput_device,
180 struct libinput_event_pointer *pointer_event)
181{
182 struct evdev_device *device =
183 libinput_device_get_user_data(libinput_device);
Jonas Ådahl26714b42014-06-02 23:15:48 +0200184 double value;
Peter Huttererc54f23d2015-01-13 11:55:37 +1000185 enum libinput_pointer_axis axis;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100186
Peter Huttererc54f23d2015-01-13 11:55:37 +1000187 axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
188 if (libinput_event_pointer_has_axis(pointer_event, axis)) {
Peter Hutterer5dddd412015-01-15 13:14:43 +1000189 value = normalize_scroll(pointer_event, axis);
Peter Huttererc54f23d2015-01-13 11:55:37 +1000190 notify_axis(device->seat,
191 libinput_event_pointer_get_time(pointer_event),
192 WL_POINTER_AXIS_VERTICAL_SCROLL,
193 wl_fixed_from_double(value));
194 }
195
196 axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
197 if (libinput_event_pointer_has_axis(pointer_event, axis)) {
Peter Hutterer5dddd412015-01-15 13:14:43 +1000198 value = normalize_scroll(pointer_event, axis);
Peter Huttererc54f23d2015-01-13 11:55:37 +1000199 notify_axis(device->seat,
200 libinput_event_pointer_get_time(pointer_event),
201 WL_POINTER_AXIS_HORIZONTAL_SCROLL,
202 wl_fixed_from_double(value));
203 }
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100204}
205
206static void
207handle_touch_with_coords(struct libinput_device *libinput_device,
208 struct libinput_event_touch *touch_event,
209 int touch_type)
210{
211 struct evdev_device *device =
212 libinput_device_get_user_data(libinput_device);
213 wl_fixed_t x;
214 wl_fixed_t y;
215 uint32_t width, height;
216 uint32_t time;
217 int32_t slot;
218
Ander Conselvan de Oliveiraf957dfb2014-04-24 15:11:14 +0300219 if (!device->output)
220 return;
221
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100222 time = libinput_event_touch_get_time(touch_event);
223 slot = libinput_event_touch_get_seat_slot(touch_event);
224
225 width = device->output->current_mode->width;
226 height = device->output->current_mode->height;
Jonas Ådahl26714b42014-06-02 23:15:48 +0200227 x = wl_fixed_from_double(
228 libinput_event_touch_get_x_transformed(touch_event, width));
229 y = wl_fixed_from_double(
230 libinput_event_touch_get_y_transformed(touch_event, height));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100231
232 weston_output_transform_coordinate(device->output,
233 x, y, &x, &y);
234
235 notify_touch(device->seat, time, slot, x, y, touch_type);
236}
237
238static void
239handle_touch_down(struct libinput_device *device,
240 struct libinput_event_touch *touch_event)
241{
242 handle_touch_with_coords(device, touch_event, WL_TOUCH_DOWN);
243}
244
245static void
246handle_touch_motion(struct libinput_device *device,
247 struct libinput_event_touch *touch_event)
248{
249 handle_touch_with_coords(device, touch_event, WL_TOUCH_MOTION);
250}
251
252static void
253handle_touch_up(struct libinput_device *libinput_device,
254 struct libinput_event_touch *touch_event)
255{
256 struct evdev_device *device =
257 libinput_device_get_user_data(libinput_device);
258 uint32_t time = libinput_event_touch_get_time(touch_event);
259 int32_t slot = libinput_event_touch_get_seat_slot(touch_event);
260
261 notify_touch(device->seat, time, slot, 0, 0, WL_TOUCH_UP);
262}
263
Jonas Ådahl1679f232014-04-12 09:39:51 +0200264static void
265handle_touch_frame(struct libinput_device *libinput_device,
266 struct libinput_event_touch *touch_event)
267{
268 struct evdev_device *device =
269 libinput_device_get_user_data(libinput_device);
270 struct weston_seat *seat = device->seat;
271
272 notify_touch_frame(seat);
273}
274
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100275int
276evdev_device_process_event(struct libinput_event *event)
277{
278 struct libinput_device *libinput_device =
279 libinput_event_get_device(event);
280 int handled = 1;
281
282 switch (libinput_event_get_type(event)) {
283 case LIBINPUT_EVENT_KEYBOARD_KEY:
284 handle_keyboard_key(libinput_device,
285 libinput_event_get_keyboard_event(event));
286 break;
287 case LIBINPUT_EVENT_POINTER_MOTION:
288 handle_pointer_motion(libinput_device,
289 libinput_event_get_pointer_event(event));
290 break;
291 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
292 handle_pointer_motion_absolute(
293 libinput_device,
294 libinput_event_get_pointer_event(event));
295 break;
296 case LIBINPUT_EVENT_POINTER_BUTTON:
297 handle_pointer_button(libinput_device,
298 libinput_event_get_pointer_event(event));
299 break;
300 case LIBINPUT_EVENT_POINTER_AXIS:
301 handle_pointer_axis(libinput_device,
302 libinput_event_get_pointer_event(event));
303 break;
304 case LIBINPUT_EVENT_TOUCH_DOWN:
305 handle_touch_down(libinput_device,
306 libinput_event_get_touch_event(event));
307 break;
308 case LIBINPUT_EVENT_TOUCH_MOTION:
309 handle_touch_motion(libinput_device,
310 libinput_event_get_touch_event(event));
311 break;
312 case LIBINPUT_EVENT_TOUCH_UP:
313 handle_touch_up(libinput_device,
314 libinput_event_get_touch_event(event));
U. Artie Eoffcd9e5452014-04-17 07:53:24 -0700315 break;
Jonas Ådahl1679f232014-04-12 09:39:51 +0200316 case LIBINPUT_EVENT_TOUCH_FRAME:
317 handle_touch_frame(libinput_device,
318 libinput_event_get_touch_event(event));
319 break;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100320 default:
321 handled = 0;
322 weston_log("unknown libinput event %d\n",
323 libinput_event_get_type(event));
324 }
325
326 return handled;
327}
328
329static void
330notify_output_destroy(struct wl_listener *listener, void *data)
331{
332 struct evdev_device *device =
333 container_of(listener,
334 struct evdev_device, output_destroy_listener);
335 struct weston_compositor *c = device->seat->compositor;
336 struct weston_output *output;
337
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300338 if (!device->output_name && !wl_list_empty(&c->output_list)) {
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100339 output = container_of(c->output_list.next,
340 struct weston_output, link);
341 evdev_device_set_output(device, output);
342 } else {
343 device->output = NULL;
344 }
345}
346
Peter Hutterer3fbba492014-09-09 13:02:25 +1000347/**
348 * The WL_CALIBRATION property requires a pixel-specific matrix to be
349 * applied after scaling device coordinates to screen coordinates. libinput
350 * can't do that, so we need to convert the calibration to the normalized
351 * format libinput expects.
352 */
353static void
354evdev_device_set_calibration(struct evdev_device *device)
355{
356 struct udev *udev;
357 struct udev_device *udev_device = NULL;
358 const char *sysname = libinput_device_get_sysname(device->device);
359 const char *calibration_values;
360 uint32_t width, height;
361 float calibration[6];
362 enum libinput_config_status status;
363
364 if (!device->output)
365 return;
366
367 width = device->output->width;
368 height = device->output->height;
369 if (width == 0 || height == 0)
370 return;
371
372 /* If libinput has a pre-set calibration matrix, don't override it */
373 if (!libinput_device_config_calibration_has_matrix(device->device) ||
374 libinput_device_config_calibration_get_default_matrix(
375 device->device,
376 calibration) != 0)
377 return;
378
379 udev = udev_new();
380 if (!udev)
381 return;
382
383 udev_device = udev_device_new_from_subsystem_sysname(udev,
384 "input",
385 sysname);
386 if (!udev_device)
387 goto out;
388
389 calibration_values =
390 udev_device_get_property_value(udev_device,
391 "WL_CALIBRATION");
392
393 if (!calibration_values || sscanf(calibration_values,
394 "%f %f %f %f %f %f",
395 &calibration[0],
396 &calibration[1],
397 &calibration[2],
398 &calibration[3],
399 &calibration[4],
400 &calibration[5]) != 6)
401 goto out;
402
403 weston_log("Applying calibration: %f %f %f %f %f %f "
404 "(normalized %f %f)\n",
405 calibration[0],
406 calibration[1],
407 calibration[2],
408 calibration[3],
409 calibration[4],
410 calibration[5],
411 calibration[2] / width,
412 calibration[5] / height);
413
414 /* normalize to a format libinput can use. There is a chance of
415 this being wrong if the width/height don't match the device
416 width/height but I'm not sure how to fix that */
417 calibration[2] /= width;
418 calibration[5] /= height;
419
420 status = libinput_device_config_calibration_set_matrix(device->device,
421 calibration);
422 if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
423 weston_log("Failed to apply calibration.\n");
424
425out:
426 if (udev_device)
427 udev_device_unref(udev_device);
428 udev_unref(udev);
429}
430
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100431void
432evdev_device_set_output(struct evdev_device *device,
433 struct weston_output *output)
434{
U. Artie Eoff161c6c52014-04-17 07:53:25 -0700435 if (device->output_destroy_listener.notify) {
436 wl_list_remove(&device->output_destroy_listener.link);
437 device->output_destroy_listener.notify = NULL;
438 }
439
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100440 device->output = output;
441 device->output_destroy_listener.notify = notify_output_destroy;
442 wl_signal_add(&output->destroy_signal,
443 &device->output_destroy_listener);
Peter Hutterer3fbba492014-09-09 13:02:25 +1000444 evdev_device_set_calibration(device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100445}
446
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200447static void
448configure_device(struct evdev_device *device)
449{
450 struct weston_compositor *compositor = device->seat->compositor;
451 struct weston_config_section *s;
452 int enable_tap;
453 int enable_tap_default;
454
455 s = weston_config_get_section(compositor->config,
456 "libinput", NULL, NULL);
457
458 if (libinput_device_config_tap_get_finger_count(device->device) > 0) {
459 enable_tap_default =
460 libinput_device_config_tap_get_default_enabled(
461 device->device);
462 weston_config_section_get_bool(s, "enable_tap",
463 &enable_tap,
464 enable_tap_default);
465 libinput_device_config_tap_set_enabled(device->device,
466 enable_tap);
467 }
Peter Hutterer3fbba492014-09-09 13:02:25 +1000468
469 evdev_device_set_calibration(device);
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200470}
471
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100472struct evdev_device *
473evdev_device_create(struct libinput_device *libinput_device,
474 struct weston_seat *seat)
475{
476 struct evdev_device *device;
477
478 device = zalloc(sizeof *device);
479 if (device == NULL)
480 return NULL;
481
482 device->seat = seat;
483 wl_list_init(&device->link);
484 device->device = libinput_device;
485
486 if (libinput_device_has_capability(libinput_device,
487 LIBINPUT_DEVICE_CAP_KEYBOARD)) {
488 weston_seat_init_keyboard(seat, NULL);
489 device->seat_caps |= EVDEV_SEAT_KEYBOARD;
490 }
491 if (libinput_device_has_capability(libinput_device,
492 LIBINPUT_DEVICE_CAP_POINTER)) {
493 weston_seat_init_pointer(seat);
494 device->seat_caps |= EVDEV_SEAT_POINTER;
495 }
496 if (libinput_device_has_capability(libinput_device,
497 LIBINPUT_DEVICE_CAP_TOUCH)) {
498 weston_seat_init_touch(seat);
499 device->seat_caps |= EVDEV_SEAT_TOUCH;
500 }
501
502 libinput_device_set_user_data(libinput_device, device);
503 libinput_device_ref(libinput_device);
504
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200505 configure_device(device);
506
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100507 return device;
508}
509
510void
511evdev_device_destroy(struct evdev_device *device)
512{
513 if (device->seat_caps & EVDEV_SEAT_POINTER)
514 weston_seat_release_pointer(device->seat);
515 if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
516 weston_seat_release_keyboard(device->seat);
517 if (device->seat_caps & EVDEV_SEAT_TOUCH)
518 weston_seat_release_touch(device->seat);
519
520 if (device->output)
521 wl_list_remove(&device->output_destroy_listener.link);
522 wl_list_remove(&device->link);
523 libinput_device_unref(device->device);
524 free(device->devnode);
525 free(device->output_name);
526 free(device);
527}
528
529void
530evdev_notify_keyboard_focus(struct weston_seat *seat,
531 struct wl_list *evdev_devices)
532{
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100533 struct wl_array keys;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100534
Derek Foremand621df22014-11-19 11:04:12 -0600535 if (seat->keyboard_device_count == 0)
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100536 return;
537
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100538 wl_array_init(&keys);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100539 notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100540 wl_array_release(&keys);
541}