blob: e68b54d7b5e835bf80ab940349e27a452a2f4748 [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;
Peter Huttererc54f23d2015-01-13 11:55:37 +1000136 enum libinput_pointer_axis axis;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100137
Peter Huttererc54f23d2015-01-13 11:55:37 +1000138 axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
139 if (libinput_event_pointer_has_axis(pointer_event, axis)) {
140 value = libinput_event_pointer_get_axis_value(pointer_event,
141 axis);
142 notify_axis(device->seat,
143 libinput_event_pointer_get_time(pointer_event),
144 WL_POINTER_AXIS_VERTICAL_SCROLL,
145 wl_fixed_from_double(value));
146 }
147
148 axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
149 if (libinput_event_pointer_has_axis(pointer_event, axis)) {
150 value = libinput_event_pointer_get_axis_value(pointer_event,
151 axis);
152 notify_axis(device->seat,
153 libinput_event_pointer_get_time(pointer_event),
154 WL_POINTER_AXIS_HORIZONTAL_SCROLL,
155 wl_fixed_from_double(value));
156 }
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100157}
158
159static void
160handle_touch_with_coords(struct libinput_device *libinput_device,
161 struct libinput_event_touch *touch_event,
162 int touch_type)
163{
164 struct evdev_device *device =
165 libinput_device_get_user_data(libinput_device);
166 wl_fixed_t x;
167 wl_fixed_t y;
168 uint32_t width, height;
169 uint32_t time;
170 int32_t slot;
171
Ander Conselvan de Oliveiraf957dfb2014-04-24 15:11:14 +0300172 if (!device->output)
173 return;
174
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100175 time = libinput_event_touch_get_time(touch_event);
176 slot = libinput_event_touch_get_seat_slot(touch_event);
177
178 width = device->output->current_mode->width;
179 height = device->output->current_mode->height;
Jonas Ådahl26714b42014-06-02 23:15:48 +0200180 x = wl_fixed_from_double(
181 libinput_event_touch_get_x_transformed(touch_event, width));
182 y = wl_fixed_from_double(
183 libinput_event_touch_get_y_transformed(touch_event, height));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100184
185 weston_output_transform_coordinate(device->output,
186 x, y, &x, &y);
187
188 notify_touch(device->seat, time, slot, x, y, touch_type);
189}
190
191static void
192handle_touch_down(struct libinput_device *device,
193 struct libinput_event_touch *touch_event)
194{
195 handle_touch_with_coords(device, touch_event, WL_TOUCH_DOWN);
196}
197
198static void
199handle_touch_motion(struct libinput_device *device,
200 struct libinput_event_touch *touch_event)
201{
202 handle_touch_with_coords(device, touch_event, WL_TOUCH_MOTION);
203}
204
205static void
206handle_touch_up(struct libinput_device *libinput_device,
207 struct libinput_event_touch *touch_event)
208{
209 struct evdev_device *device =
210 libinput_device_get_user_data(libinput_device);
211 uint32_t time = libinput_event_touch_get_time(touch_event);
212 int32_t slot = libinput_event_touch_get_seat_slot(touch_event);
213
214 notify_touch(device->seat, time, slot, 0, 0, WL_TOUCH_UP);
215}
216
Jonas Ådahl1679f232014-04-12 09:39:51 +0200217static void
218handle_touch_frame(struct libinput_device *libinput_device,
219 struct libinput_event_touch *touch_event)
220{
221 struct evdev_device *device =
222 libinput_device_get_user_data(libinput_device);
223 struct weston_seat *seat = device->seat;
224
225 notify_touch_frame(seat);
226}
227
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100228int
229evdev_device_process_event(struct libinput_event *event)
230{
231 struct libinput_device *libinput_device =
232 libinput_event_get_device(event);
233 int handled = 1;
234
235 switch (libinput_event_get_type(event)) {
236 case LIBINPUT_EVENT_KEYBOARD_KEY:
237 handle_keyboard_key(libinput_device,
238 libinput_event_get_keyboard_event(event));
239 break;
240 case LIBINPUT_EVENT_POINTER_MOTION:
241 handle_pointer_motion(libinput_device,
242 libinput_event_get_pointer_event(event));
243 break;
244 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
245 handle_pointer_motion_absolute(
246 libinput_device,
247 libinput_event_get_pointer_event(event));
248 break;
249 case LIBINPUT_EVENT_POINTER_BUTTON:
250 handle_pointer_button(libinput_device,
251 libinput_event_get_pointer_event(event));
252 break;
253 case LIBINPUT_EVENT_POINTER_AXIS:
254 handle_pointer_axis(libinput_device,
255 libinput_event_get_pointer_event(event));
256 break;
257 case LIBINPUT_EVENT_TOUCH_DOWN:
258 handle_touch_down(libinput_device,
259 libinput_event_get_touch_event(event));
260 break;
261 case LIBINPUT_EVENT_TOUCH_MOTION:
262 handle_touch_motion(libinput_device,
263 libinput_event_get_touch_event(event));
264 break;
265 case LIBINPUT_EVENT_TOUCH_UP:
266 handle_touch_up(libinput_device,
267 libinput_event_get_touch_event(event));
U. Artie Eoffcd9e5452014-04-17 07:53:24 -0700268 break;
Jonas Ådahl1679f232014-04-12 09:39:51 +0200269 case LIBINPUT_EVENT_TOUCH_FRAME:
270 handle_touch_frame(libinput_device,
271 libinput_event_get_touch_event(event));
272 break;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100273 default:
274 handled = 0;
275 weston_log("unknown libinput event %d\n",
276 libinput_event_get_type(event));
277 }
278
279 return handled;
280}
281
282static void
283notify_output_destroy(struct wl_listener *listener, void *data)
284{
285 struct evdev_device *device =
286 container_of(listener,
287 struct evdev_device, output_destroy_listener);
288 struct weston_compositor *c = device->seat->compositor;
289 struct weston_output *output;
290
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300291 if (!device->output_name && !wl_list_empty(&c->output_list)) {
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100292 output = container_of(c->output_list.next,
293 struct weston_output, link);
294 evdev_device_set_output(device, output);
295 } else {
296 device->output = NULL;
297 }
298}
299
Peter Hutterer3fbba492014-09-09 13:02:25 +1000300/**
301 * The WL_CALIBRATION property requires a pixel-specific matrix to be
302 * applied after scaling device coordinates to screen coordinates. libinput
303 * can't do that, so we need to convert the calibration to the normalized
304 * format libinput expects.
305 */
306static void
307evdev_device_set_calibration(struct evdev_device *device)
308{
309 struct udev *udev;
310 struct udev_device *udev_device = NULL;
311 const char *sysname = libinput_device_get_sysname(device->device);
312 const char *calibration_values;
313 uint32_t width, height;
314 float calibration[6];
315 enum libinput_config_status status;
316
317 if (!device->output)
318 return;
319
320 width = device->output->width;
321 height = device->output->height;
322 if (width == 0 || height == 0)
323 return;
324
325 /* If libinput has a pre-set calibration matrix, don't override it */
326 if (!libinput_device_config_calibration_has_matrix(device->device) ||
327 libinput_device_config_calibration_get_default_matrix(
328 device->device,
329 calibration) != 0)
330 return;
331
332 udev = udev_new();
333 if (!udev)
334 return;
335
336 udev_device = udev_device_new_from_subsystem_sysname(udev,
337 "input",
338 sysname);
339 if (!udev_device)
340 goto out;
341
342 calibration_values =
343 udev_device_get_property_value(udev_device,
344 "WL_CALIBRATION");
345
346 if (!calibration_values || sscanf(calibration_values,
347 "%f %f %f %f %f %f",
348 &calibration[0],
349 &calibration[1],
350 &calibration[2],
351 &calibration[3],
352 &calibration[4],
353 &calibration[5]) != 6)
354 goto out;
355
356 weston_log("Applying calibration: %f %f %f %f %f %f "
357 "(normalized %f %f)\n",
358 calibration[0],
359 calibration[1],
360 calibration[2],
361 calibration[3],
362 calibration[4],
363 calibration[5],
364 calibration[2] / width,
365 calibration[5] / height);
366
367 /* normalize to a format libinput can use. There is a chance of
368 this being wrong if the width/height don't match the device
369 width/height but I'm not sure how to fix that */
370 calibration[2] /= width;
371 calibration[5] /= height;
372
373 status = libinput_device_config_calibration_set_matrix(device->device,
374 calibration);
375 if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
376 weston_log("Failed to apply calibration.\n");
377
378out:
379 if (udev_device)
380 udev_device_unref(udev_device);
381 udev_unref(udev);
382}
383
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100384void
385evdev_device_set_output(struct evdev_device *device,
386 struct weston_output *output)
387{
U. Artie Eoff161c6c52014-04-17 07:53:25 -0700388 if (device->output_destroy_listener.notify) {
389 wl_list_remove(&device->output_destroy_listener.link);
390 device->output_destroy_listener.notify = NULL;
391 }
392
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100393 device->output = output;
394 device->output_destroy_listener.notify = notify_output_destroy;
395 wl_signal_add(&output->destroy_signal,
396 &device->output_destroy_listener);
Peter Hutterer3fbba492014-09-09 13:02:25 +1000397 evdev_device_set_calibration(device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100398}
399
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200400static void
401configure_device(struct evdev_device *device)
402{
403 struct weston_compositor *compositor = device->seat->compositor;
404 struct weston_config_section *s;
405 int enable_tap;
406 int enable_tap_default;
407
408 s = weston_config_get_section(compositor->config,
409 "libinput", NULL, NULL);
410
411 if (libinput_device_config_tap_get_finger_count(device->device) > 0) {
412 enable_tap_default =
413 libinput_device_config_tap_get_default_enabled(
414 device->device);
415 weston_config_section_get_bool(s, "enable_tap",
416 &enable_tap,
417 enable_tap_default);
418 libinput_device_config_tap_set_enabled(device->device,
419 enable_tap);
420 }
Peter Hutterer3fbba492014-09-09 13:02:25 +1000421
422 evdev_device_set_calibration(device);
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200423}
424
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100425struct evdev_device *
426evdev_device_create(struct libinput_device *libinput_device,
427 struct weston_seat *seat)
428{
429 struct evdev_device *device;
430
431 device = zalloc(sizeof *device);
432 if (device == NULL)
433 return NULL;
434
435 device->seat = seat;
436 wl_list_init(&device->link);
437 device->device = libinput_device;
438
439 if (libinput_device_has_capability(libinput_device,
440 LIBINPUT_DEVICE_CAP_KEYBOARD)) {
441 weston_seat_init_keyboard(seat, NULL);
442 device->seat_caps |= EVDEV_SEAT_KEYBOARD;
443 }
444 if (libinput_device_has_capability(libinput_device,
445 LIBINPUT_DEVICE_CAP_POINTER)) {
446 weston_seat_init_pointer(seat);
447 device->seat_caps |= EVDEV_SEAT_POINTER;
448 }
449 if (libinput_device_has_capability(libinput_device,
450 LIBINPUT_DEVICE_CAP_TOUCH)) {
451 weston_seat_init_touch(seat);
452 device->seat_caps |= EVDEV_SEAT_TOUCH;
453 }
454
455 libinput_device_set_user_data(libinput_device, device);
456 libinput_device_ref(libinput_device);
457
Jonas Ådahl05e4a1f2014-07-22 22:49:41 +0200458 configure_device(device);
459
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100460 return device;
461}
462
463void
464evdev_device_destroy(struct evdev_device *device)
465{
466 if (device->seat_caps & EVDEV_SEAT_POINTER)
467 weston_seat_release_pointer(device->seat);
468 if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
469 weston_seat_release_keyboard(device->seat);
470 if (device->seat_caps & EVDEV_SEAT_TOUCH)
471 weston_seat_release_touch(device->seat);
472
473 if (device->output)
474 wl_list_remove(&device->output_destroy_listener.link);
475 wl_list_remove(&device->link);
476 libinput_device_unref(device->device);
477 free(device->devnode);
478 free(device->output_name);
479 free(device);
480}
481
482void
483evdev_notify_keyboard_focus(struct weston_seat *seat,
484 struct wl_list *evdev_devices)
485{
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100486 struct wl_array keys;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100487
Derek Foremand621df22014-11-19 11:04:12 -0600488 if (seat->keyboard_device_count == 0)
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100489 return;
490
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100491 wl_array_init(&keys);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100492 notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100493 wl_array_release(&keys);
494}