blob: 0e3f46de9ec89b7865ccf6bbec575e97b5ae4d8e [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);
122
123 notify_button(device->seat,
124 libinput_event_pointer_get_time(pointer_event),
125 libinput_event_pointer_get_button(pointer_event),
126 libinput_event_pointer_get_button_state(pointer_event));
127}
128
129static void
130handle_pointer_axis(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 Ådahl26714b42014-06-02 23:15:48 +0200135 double value;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100136
Jonas Ådahl26714b42014-06-02 23:15:48 +0200137 value = libinput_event_pointer_get_axis_value(pointer_event);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100138 notify_axis(device->seat,
139 libinput_event_pointer_get_time(pointer_event),
140 libinput_event_pointer_get_axis(pointer_event),
Jonas Ådahl26714b42014-06-02 23:15:48 +0200141 wl_fixed_from_double(value));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100142}
143
144static void
145handle_touch_with_coords(struct libinput_device *libinput_device,
146 struct libinput_event_touch *touch_event,
147 int touch_type)
148{
149 struct evdev_device *device =
150 libinput_device_get_user_data(libinput_device);
151 wl_fixed_t x;
152 wl_fixed_t y;
153 uint32_t width, height;
154 uint32_t time;
155 int32_t slot;
156
Ander Conselvan de Oliveiraf957dfb2014-04-24 15:11:14 +0300157 if (!device->output)
158 return;
159
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100160 time = libinput_event_touch_get_time(touch_event);
161 slot = libinput_event_touch_get_seat_slot(touch_event);
162
163 width = device->output->current_mode->width;
164 height = device->output->current_mode->height;
Jonas Ådahl26714b42014-06-02 23:15:48 +0200165 x = wl_fixed_from_double(
166 libinput_event_touch_get_x_transformed(touch_event, width));
167 y = wl_fixed_from_double(
168 libinput_event_touch_get_y_transformed(touch_event, height));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100169
170 weston_output_transform_coordinate(device->output,
171 x, y, &x, &y);
172
173 notify_touch(device->seat, time, slot, x, y, touch_type);
174}
175
176static void
177handle_touch_down(struct libinput_device *device,
178 struct libinput_event_touch *touch_event)
179{
180 handle_touch_with_coords(device, touch_event, WL_TOUCH_DOWN);
181}
182
183static void
184handle_touch_motion(struct libinput_device *device,
185 struct libinput_event_touch *touch_event)
186{
187 handle_touch_with_coords(device, touch_event, WL_TOUCH_MOTION);
188}
189
190static void
191handle_touch_up(struct libinput_device *libinput_device,
192 struct libinput_event_touch *touch_event)
193{
194 struct evdev_device *device =
195 libinput_device_get_user_data(libinput_device);
196 uint32_t time = libinput_event_touch_get_time(touch_event);
197 int32_t slot = libinput_event_touch_get_seat_slot(touch_event);
198
199 notify_touch(device->seat, time, slot, 0, 0, WL_TOUCH_UP);
200}
201
Jonas Ådahl1679f232014-04-12 09:39:51 +0200202static void
203handle_touch_frame(struct libinput_device *libinput_device,
204 struct libinput_event_touch *touch_event)
205{
206 struct evdev_device *device =
207 libinput_device_get_user_data(libinput_device);
208 struct weston_seat *seat = device->seat;
209
210 notify_touch_frame(seat);
211}
212
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100213int
214evdev_device_process_event(struct libinput_event *event)
215{
216 struct libinput_device *libinput_device =
217 libinput_event_get_device(event);
218 int handled = 1;
219
220 switch (libinput_event_get_type(event)) {
221 case LIBINPUT_EVENT_KEYBOARD_KEY:
222 handle_keyboard_key(libinput_device,
223 libinput_event_get_keyboard_event(event));
224 break;
225 case LIBINPUT_EVENT_POINTER_MOTION:
226 handle_pointer_motion(libinput_device,
227 libinput_event_get_pointer_event(event));
228 break;
229 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
230 handle_pointer_motion_absolute(
231 libinput_device,
232 libinput_event_get_pointer_event(event));
233 break;
234 case LIBINPUT_EVENT_POINTER_BUTTON:
235 handle_pointer_button(libinput_device,
236 libinput_event_get_pointer_event(event));
237 break;
238 case LIBINPUT_EVENT_POINTER_AXIS:
239 handle_pointer_axis(libinput_device,
240 libinput_event_get_pointer_event(event));
241 break;
242 case LIBINPUT_EVENT_TOUCH_DOWN:
243 handle_touch_down(libinput_device,
244 libinput_event_get_touch_event(event));
245 break;
246 case LIBINPUT_EVENT_TOUCH_MOTION:
247 handle_touch_motion(libinput_device,
248 libinput_event_get_touch_event(event));
249 break;
250 case LIBINPUT_EVENT_TOUCH_UP:
251 handle_touch_up(libinput_device,
252 libinput_event_get_touch_event(event));
U. Artie Eoffcd9e5452014-04-17 07:53:24 -0700253 break;
Jonas Ådahl1679f232014-04-12 09:39:51 +0200254 case LIBINPUT_EVENT_TOUCH_FRAME:
255 handle_touch_frame(libinput_device,
256 libinput_event_get_touch_event(event));
257 break;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100258 default:
259 handled = 0;
260 weston_log("unknown libinput event %d\n",
261 libinput_event_get_type(event));
262 }
263
264 return handled;
265}
266
267static void
268notify_output_destroy(struct wl_listener *listener, void *data)
269{
270 struct evdev_device *device =
271 container_of(listener,
272 struct evdev_device, output_destroy_listener);
273 struct weston_compositor *c = device->seat->compositor;
274 struct weston_output *output;
275
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300276 if (!device->output_name && !wl_list_empty(&c->output_list)) {
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100277 output = container_of(c->output_list.next,
278 struct weston_output, link);
279 evdev_device_set_output(device, output);
280 } else {
281 device->output = NULL;
282 }
283}
284
Peter Hutterer3fbba492014-09-09 13:02:25 +1000285/**
286 * The WL_CALIBRATION property requires a pixel-specific matrix to be
287 * applied after scaling device coordinates to screen coordinates. libinput
288 * can't do that, so we need to convert the calibration to the normalized
289 * format libinput expects.
290 */
291static void
292evdev_device_set_calibration(struct evdev_device *device)
293{
294 struct udev *udev;
295 struct udev_device *udev_device = NULL;
296 const char *sysname = libinput_device_get_sysname(device->device);
297 const char *calibration_values;
298 uint32_t width, height;
299 float calibration[6];
300 enum libinput_config_status status;
301
302 if (!device->output)
303 return;
304
305 width = device->output->width;
306 height = device->output->height;
307 if (width == 0 || height == 0)
308 return;
309
310 /* If libinput has a pre-set calibration matrix, don't override it */
311 if (!libinput_device_config_calibration_has_matrix(device->device) ||
312 libinput_device_config_calibration_get_default_matrix(
313 device->device,
314 calibration) != 0)
315 return;
316
317 udev = udev_new();
318 if (!udev)
319 return;
320
321 udev_device = udev_device_new_from_subsystem_sysname(udev,
322 "input",
323 sysname);
324 if (!udev_device)
325 goto out;
326
327 calibration_values =
328 udev_device_get_property_value(udev_device,
329 "WL_CALIBRATION");
330
331 if (!calibration_values || sscanf(calibration_values,
332 "%f %f %f %f %f %f",
333 &calibration[0],
334 &calibration[1],
335 &calibration[2],
336 &calibration[3],
337 &calibration[4],
338 &calibration[5]) != 6)
339 goto out;
340
341 weston_log("Applying calibration: %f %f %f %f %f %f "
342 "(normalized %f %f)\n",
343 calibration[0],
344 calibration[1],
345 calibration[2],
346 calibration[3],
347 calibration[4],
348 calibration[5],
349 calibration[2] / width,
350 calibration[5] / height);
351
352 /* normalize to a format libinput can use. There is a chance of
353 this being wrong if the width/height don't match the device
354 width/height but I'm not sure how to fix that */
355 calibration[2] /= width;
356 calibration[5] /= height;
357
358 status = libinput_device_config_calibration_set_matrix(device->device,
359 calibration);
360 if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
361 weston_log("Failed to apply calibration.\n");
362
363out:
364 if (udev_device)
365 udev_device_unref(udev_device);
366 udev_unref(udev);
367}
368
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100369void
370evdev_device_set_output(struct evdev_device *device,
371 struct weston_output *output)
372{
U. Artie Eoff161c6c52014-04-17 07:53:25 -0700373 if (device->output_destroy_listener.notify) {
374 wl_list_remove(&device->output_destroy_listener.link);
375 device->output_destroy_listener.notify = NULL;
376 }
377
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100378 device->output = output;
379 device->output_destroy_listener.notify = notify_output_destroy;
380 wl_signal_add(&output->destroy_signal,
381 &device->output_destroy_listener);
Peter Hutterer3fbba492014-09-09 13:02:25 +1000382 evdev_device_set_calibration(device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100383}
384
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200385static void
386configure_device(struct evdev_device *device)
387{
388 struct weston_compositor *compositor = device->seat->compositor;
389 struct weston_config_section *s;
390 int enable_tap;
391 int enable_tap_default;
392
393 s = weston_config_get_section(compositor->config,
394 "libinput", NULL, NULL);
395
396 if (libinput_device_config_tap_get_finger_count(device->device) > 0) {
397 enable_tap_default =
398 libinput_device_config_tap_get_default_enabled(
399 device->device);
400 weston_config_section_get_bool(s, "enable_tap",
401 &enable_tap,
402 enable_tap_default);
403 libinput_device_config_tap_set_enabled(device->device,
404 enable_tap);
405 }
Peter Hutterer3fbba492014-09-09 13:02:25 +1000406
407 evdev_device_set_calibration(device);
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200408}
409
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100410struct evdev_device *
411evdev_device_create(struct libinput_device *libinput_device,
412 struct weston_seat *seat)
413{
414 struct evdev_device *device;
415
416 device = zalloc(sizeof *device);
417 if (device == NULL)
418 return NULL;
419
420 device->seat = seat;
421 wl_list_init(&device->link);
422 device->device = libinput_device;
423
424 if (libinput_device_has_capability(libinput_device,
425 LIBINPUT_DEVICE_CAP_KEYBOARD)) {
426 weston_seat_init_keyboard(seat, NULL);
427 device->seat_caps |= EVDEV_SEAT_KEYBOARD;
428 }
429 if (libinput_device_has_capability(libinput_device,
430 LIBINPUT_DEVICE_CAP_POINTER)) {
431 weston_seat_init_pointer(seat);
432 device->seat_caps |= EVDEV_SEAT_POINTER;
433 }
434 if (libinput_device_has_capability(libinput_device,
435 LIBINPUT_DEVICE_CAP_TOUCH)) {
436 weston_seat_init_touch(seat);
437 device->seat_caps |= EVDEV_SEAT_TOUCH;
438 }
439
440 libinput_device_set_user_data(libinput_device, device);
441 libinput_device_ref(libinput_device);
442
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200443 configure_device(device);
444
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100445 return device;
446}
447
448void
449evdev_device_destroy(struct evdev_device *device)
450{
451 if (device->seat_caps & EVDEV_SEAT_POINTER)
452 weston_seat_release_pointer(device->seat);
453 if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
454 weston_seat_release_keyboard(device->seat);
455 if (device->seat_caps & EVDEV_SEAT_TOUCH)
456 weston_seat_release_touch(device->seat);
457
458 if (device->output)
459 wl_list_remove(&device->output_destroy_listener.link);
460 wl_list_remove(&device->link);
461 libinput_device_unref(device->device);
462 free(device->devnode);
463 free(device->output_name);
464 free(device);
465}
466
467void
468evdev_notify_keyboard_focus(struct weston_seat *seat,
469 struct wl_list *evdev_devices)
470{
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100471 struct wl_array keys;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100472
473 if (!seat->keyboard_device_count > 0)
474 return;
475
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100476 wl_array_init(&keys);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100477 notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100478 wl_array_release(&keys);
479}