blob: 62f4cee838754b136702d2e5176ff10896f70173 [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>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030030#include <stdint.h>
Jonas Ådahle0de3c22014-03-12 22:08:42 +010031#include <stdlib.h>
32#include <string.h>
33#include <linux/input.h>
34#include <unistd.h>
35#include <fcntl.h>
Jonas Ådahle0de3c22014-03-12 22:08:42 +010036#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"
Alexandros Frantzis84b31f82017-11-24 18:01:46 +020042#include "shared/timespec-util.h"
Jonas Ådahle0de3c22014-03-12 22:08:42 +010043
Jonas Ådahle0de3c22014-03-12 22:08:42 +010044void
45evdev_led_update(struct evdev_device *device, enum weston_led weston_leds)
46{
47 enum libinput_led leds = 0;
48
49 if (weston_leds & LED_NUM_LOCK)
50 leds |= LIBINPUT_LED_NUM_LOCK;
51 if (weston_leds & LED_CAPS_LOCK)
52 leds |= LIBINPUT_LED_CAPS_LOCK;
53 if (weston_leds & LED_SCROLL_LOCK)
54 leds |= LIBINPUT_LED_SCROLL_LOCK;
55
56 libinput_device_led_update(device->device, leds);
57}
58
59static void
60handle_keyboard_key(struct libinput_device *libinput_device,
61 struct libinput_event_keyboard *keyboard_event)
62{
63 struct evdev_device *device =
64 libinput_device_get_user_data(libinput_device);
Jonas Ådahl90d1ac82015-01-30 12:23:00 +080065 int key_state =
66 libinput_event_keyboard_get_key_state(keyboard_event);
67 int seat_key_count =
68 libinput_event_keyboard_get_seat_key_count(keyboard_event);
Alexandros Frantzis47e79c82017-11-16 18:20:57 +020069 struct timespec time;
Jonas Ådahl90d1ac82015-01-30 12:23:00 +080070
71 /* Ignore key events that are not seat wide state changes. */
72 if ((key_state == LIBINPUT_KEY_STATE_PRESSED &&
73 seat_key_count != 1) ||
74 (key_state == LIBINPUT_KEY_STATE_RELEASED &&
75 seat_key_count != 0))
76 return;
Jonas Ådahle0de3c22014-03-12 22:08:42 +010077
Alexandros Frantzis47e79c82017-11-16 18:20:57 +020078 timespec_from_usec(&time,
79 libinput_event_keyboard_get_time_usec(keyboard_event));
80
81 notify_key(device->seat, &time,
Jonas Ådahle0de3c22014-03-12 22:08:42 +010082 libinput_event_keyboard_get_key(keyboard_event),
Chris Michael7e7f7932016-02-22 08:47:24 -050083 key_state, STATE_UPDATE_AUTOMATIC);
Jonas Ådahle0de3c22014-03-12 22:08:42 +010084}
85
Peter Hutterer87743e92016-01-18 16:38:22 +100086static bool
Jonas Ådahle0de3c22014-03-12 22:08:42 +010087handle_pointer_motion(struct libinput_device *libinput_device,
88 struct libinput_event_pointer *pointer_event)
89{
90 struct evdev_device *device =
91 libinput_device_get_user_data(libinput_device);
Jonas Ådahld2510102014-10-05 21:39:14 +020092 struct weston_pointer_motion_event event = { 0 };
Alexandros Frantzis84b31f82017-11-24 18:01:46 +020093 struct timespec time;
Jonas Ådahl3845b322014-10-21 23:51:29 +020094 double dx_unaccel, dy_unaccel;
95
Alexandros Frantzis84b31f82017-11-24 18:01:46 +020096 timespec_from_usec(&time,
97 libinput_event_pointer_get_time_usec(pointer_event));
Jonas Ådahl3845b322014-10-21 23:51:29 +020098 dx_unaccel = libinput_event_pointer_get_dx_unaccelerated(pointer_event);
99 dy_unaccel = libinput_event_pointer_get_dy_unaccelerated(pointer_event);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100100
Jonas Ådahld2510102014-10-05 21:39:14 +0200101 event = (struct weston_pointer_motion_event) {
Jonas Ådahl3845b322014-10-21 23:51:29 +0200102 .mask = WESTON_POINTER_MOTION_REL |
103 WESTON_POINTER_MOTION_REL_UNACCEL,
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200104 .time = time,
Jonas Ådahld2510102014-10-05 21:39:14 +0200105 .dx = libinput_event_pointer_get_dx(pointer_event),
106 .dy = libinput_event_pointer_get_dy(pointer_event),
Jonas Ådahl3845b322014-10-21 23:51:29 +0200107 .dx_unaccel = dx_unaccel,
108 .dy_unaccel = dy_unaccel,
Jonas Ådahld2510102014-10-05 21:39:14 +0200109 };
110
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200111 notify_motion(device->seat, &time, &event);
Peter Hutterer87743e92016-01-18 16:38:22 +1000112
113 return true;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100114}
115
Peter Hutterer87743e92016-01-18 16:38:22 +1000116static bool
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100117handle_pointer_motion_absolute(
118 struct libinput_device *libinput_device,
119 struct libinput_event_pointer *pointer_event)
120{
121 struct evdev_device *device =
122 libinput_device_get_user_data(libinput_device);
123 struct weston_output *output = device->output;
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200124 struct timespec time;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200125 double x, y;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100126 uint32_t width, height;
127
128 if (!output)
Peter Hutterer87743e92016-01-18 16:38:22 +1000129 return false;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100130
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200131 timespec_from_usec(&time,
132 libinput_event_pointer_get_time_usec(pointer_event));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100133 width = device->output->current_mode->width;
134 height = device->output->current_mode->height;
135
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200136 x = libinput_event_pointer_get_absolute_x_transformed(pointer_event,
137 width);
138 y = libinput_event_pointer_get_absolute_y_transformed(pointer_event,
139 height);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100140
141 weston_output_transform_coordinate(device->output, x, y, &x, &y);
Alexandros Frantzis84b31f82017-11-24 18:01:46 +0200142 notify_motion_absolute(device->seat, &time, x, y);
Peter Hutterer87743e92016-01-18 16:38:22 +1000143
144 return true;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100145}
146
Peter Hutterer87743e92016-01-18 16:38:22 +1000147static bool
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100148handle_pointer_button(struct libinput_device *libinput_device,
149 struct libinput_event_pointer *pointer_event)
150{
151 struct evdev_device *device =
152 libinput_device_get_user_data(libinput_device);
Jonas Ådahle90b9e92015-01-30 12:22:59 +0800153 int button_state =
154 libinput_event_pointer_get_button_state(pointer_event);
155 int seat_button_count =
156 libinput_event_pointer_get_seat_button_count(pointer_event);
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200157 struct timespec time;
Jonas Ådahle90b9e92015-01-30 12:22:59 +0800158
159 /* Ignore button events that are not seat wide state changes. */
160 if ((button_state == LIBINPUT_BUTTON_STATE_PRESSED &&
161 seat_button_count != 1) ||
162 (button_state == LIBINPUT_BUTTON_STATE_RELEASED &&
163 seat_button_count != 0))
Peter Hutterer87743e92016-01-18 16:38:22 +1000164 return false;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100165
Alexandros Frantzis215bedc2017-11-16 18:20:55 +0200166 timespec_from_usec(&time,
167 libinput_event_pointer_get_time_usec(pointer_event));
168
169 notify_button(device->seat, &time,
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100170 libinput_event_pointer_get_button(pointer_event),
Christopher Michaele1719c72016-02-19 11:07:00 -0500171 button_state);
172
Peter Hutterer87743e92016-01-18 16:38:22 +1000173 return true;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100174}
175
Peter Hutterer5dddd412015-01-15 13:14:43 +1000176static double
177normalize_scroll(struct libinput_event_pointer *pointer_event,
178 enum libinput_pointer_axis axis)
179{
Peter Hutterer5dddd412015-01-15 13:14:43 +1000180 enum libinput_pointer_axis_source source;
Peter Hutterer87743e92016-01-18 16:38:22 +1000181 double value = 0.0;
Peter Hutterer5dddd412015-01-15 13:14:43 +1000182
183 source = libinput_event_pointer_get_axis_source(pointer_event);
184 /* libinput < 0.8 sent wheel click events with value 10. Since 0.8
185 the value is the angle of the click in degrees. To keep
186 backwards-compat with existing clients, we just send multiples of
187 the click count.
188 */
189 switch (source) {
190 case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
191 value = 10 * libinput_event_pointer_get_axis_value_discrete(
192 pointer_event,
193 axis);
194 break;
195 case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
196 case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
197 value = libinput_event_pointer_get_axis_value(pointer_event,
198 axis);
199 break;
Daniel Stone4933ca52017-03-14 17:24:04 +0000200 default:
201 assert(!"unhandled event source in normalize_scroll");
Peter Hutterer5dddd412015-01-15 13:14:43 +1000202 }
203
204 return value;
205}
206
Peter Hutterer87743e92016-01-18 16:38:22 +1000207static int32_t
208get_axis_discrete(struct libinput_event_pointer *pointer_event,
209 enum libinput_pointer_axis axis)
210{
211 enum libinput_pointer_axis_source source;
212
213 source = libinput_event_pointer_get_axis_source(pointer_event);
214
215 if (source != LIBINPUT_POINTER_AXIS_SOURCE_WHEEL)
216 return 0;
217
218 return libinput_event_pointer_get_axis_value_discrete(pointer_event,
219 axis);
220}
221
222static bool
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100223handle_pointer_axis(struct libinput_device *libinput_device,
224 struct libinput_event_pointer *pointer_event)
225{
Peter Hutterer87743e92016-01-18 16:38:22 +1000226 static int warned;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100227 struct evdev_device *device =
228 libinput_device_get_user_data(libinput_device);
Peter Hutterer87743e92016-01-18 16:38:22 +1000229 double vert, horiz;
230 int32_t vert_discrete, horiz_discrete;
Peter Huttererc54f23d2015-01-13 11:55:37 +1000231 enum libinput_pointer_axis axis;
Peter Hutterer89b6a492016-01-18 15:58:17 +1000232 struct weston_pointer_axis_event weston_event;
Peter Hutterer87743e92016-01-18 16:38:22 +1000233 enum libinput_pointer_axis_source source;
234 uint32_t wl_axis_source;
235 bool has_vert, has_horiz;
Alexandros Frantzis80321942017-11-16 18:20:56 +0200236 struct timespec time;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100237
Peter Hutterer87743e92016-01-18 16:38:22 +1000238 has_vert = libinput_event_pointer_has_axis(pointer_event,
239 LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
240 has_horiz = libinput_event_pointer_has_axis(pointer_event,
241 LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
242
243 if (!has_vert && !has_horiz)
244 return false;
245
246 source = libinput_event_pointer_get_axis_source(pointer_event);
247 switch (source) {
248 case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
249 wl_axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
250 break;
251 case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
252 wl_axis_source = WL_POINTER_AXIS_SOURCE_FINGER;
253 break;
254 case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
255 wl_axis_source = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
256 break;
257 default:
258 if (warned < 5) {
259 weston_log("Unknown scroll source %d.\n", source);
260 warned++;
261 }
262 return false;
263 }
264
265 notify_axis_source(device->seat, wl_axis_source);
266
Alexandros Frantzis80321942017-11-16 18:20:56 +0200267 timespec_from_usec(&time,
268 libinput_event_pointer_get_time_usec(pointer_event));
269
Peter Hutterer87743e92016-01-18 16:38:22 +1000270 if (has_vert) {
271 axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
272 vert_discrete = get_axis_discrete(pointer_event, axis);
273 vert = normalize_scroll(pointer_event, axis);
274
Peter Hutterer89b6a492016-01-18 15:58:17 +1000275 weston_event.axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200276 weston_event.value = vert;
Peter Hutterer87743e92016-01-18 16:38:22 +1000277 weston_event.discrete = vert_discrete;
278 weston_event.has_discrete = (vert_discrete != 0);
279
Alexandros Frantzis80321942017-11-16 18:20:56 +0200280 notify_axis(device->seat, &time, &weston_event);
Peter Huttererc54f23d2015-01-13 11:55:37 +1000281 }
282
Peter Hutterer87743e92016-01-18 16:38:22 +1000283 if (has_horiz) {
284 axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
285 horiz_discrete = get_axis_discrete(pointer_event, axis);
286 horiz = normalize_scroll(pointer_event, axis);
287
Peter Hutterer89b6a492016-01-18 15:58:17 +1000288 weston_event.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200289 weston_event.value = horiz;
Peter Hutterer87743e92016-01-18 16:38:22 +1000290 weston_event.discrete = horiz_discrete;
291 weston_event.has_discrete = (horiz_discrete != 0);
292
Alexandros Frantzis80321942017-11-16 18:20:56 +0200293 notify_axis(device->seat, &time, &weston_event);
Peter Huttererc54f23d2015-01-13 11:55:37 +1000294 }
Peter Hutterer87743e92016-01-18 16:38:22 +1000295
296 return true;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100297}
298
299static void
300handle_touch_with_coords(struct libinput_device *libinput_device,
301 struct libinput_event_touch *touch_event,
302 int touch_type)
303{
304 struct evdev_device *device =
305 libinput_device_get_user_data(libinput_device);
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200306 double x;
307 double y;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100308 uint32_t width, height;
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200309 struct timespec time;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100310 int32_t slot;
311
Ander Conselvan de Oliveiraf957dfb2014-04-24 15:11:14 +0300312 if (!device->output)
313 return;
314
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200315 timespec_from_usec(&time,
316 libinput_event_touch_get_time_usec(touch_event));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100317 slot = libinput_event_touch_get_seat_slot(touch_event);
318
319 width = device->output->current_mode->width;
320 height = device->output->current_mode->height;
Giulio Camuffo90a6fc62016-03-22 17:44:54 +0200321 x = libinput_event_touch_get_x_transformed(touch_event, width);
322 y = libinput_event_touch_get_y_transformed(touch_event, height);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100323
324 weston_output_transform_coordinate(device->output,
325 x, y, &x, &y);
326
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200327 notify_touch(device->seat, &time, slot, x, y, touch_type);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100328}
329
330static void
331handle_touch_down(struct libinput_device *device,
332 struct libinput_event_touch *touch_event)
333{
334 handle_touch_with_coords(device, touch_event, WL_TOUCH_DOWN);
335}
336
337static void
338handle_touch_motion(struct libinput_device *device,
339 struct libinput_event_touch *touch_event)
340{
341 handle_touch_with_coords(device, touch_event, WL_TOUCH_MOTION);
342}
343
344static void
345handle_touch_up(struct libinput_device *libinput_device,
346 struct libinput_event_touch *touch_event)
347{
348 struct evdev_device *device =
349 libinput_device_get_user_data(libinput_device);
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200350 struct timespec time;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100351 int32_t slot = libinput_event_touch_get_seat_slot(touch_event);
352
Alexandros Frantzis9448deb2017-11-16 18:20:58 +0200353 timespec_from_usec(&time,
354 libinput_event_touch_get_time_usec(touch_event));
355
356 notify_touch(device->seat, &time, slot, 0, 0, WL_TOUCH_UP);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100357}
358
Jonas Ådahl1679f232014-04-12 09:39:51 +0200359static void
360handle_touch_frame(struct libinput_device *libinput_device,
361 struct libinput_event_touch *touch_event)
362{
363 struct evdev_device *device =
364 libinput_device_get_user_data(libinput_device);
365 struct weston_seat *seat = device->seat;
366
367 notify_touch_frame(seat);
368}
369
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100370int
371evdev_device_process_event(struct libinput_event *event)
372{
373 struct libinput_device *libinput_device =
374 libinput_event_get_device(event);
Peter Hutterer87743e92016-01-18 16:38:22 +1000375 struct evdev_device *device =
376 libinput_device_get_user_data(libinput_device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100377 int handled = 1;
Peter Hutterer87743e92016-01-18 16:38:22 +1000378 bool need_frame = false;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100379
380 switch (libinput_event_get_type(event)) {
381 case LIBINPUT_EVENT_KEYBOARD_KEY:
382 handle_keyboard_key(libinput_device,
383 libinput_event_get_keyboard_event(event));
384 break;
385 case LIBINPUT_EVENT_POINTER_MOTION:
Peter Hutterer87743e92016-01-18 16:38:22 +1000386 need_frame = handle_pointer_motion(libinput_device,
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100387 libinput_event_get_pointer_event(event));
388 break;
389 case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
Peter Hutterer87743e92016-01-18 16:38:22 +1000390 need_frame = handle_pointer_motion_absolute(
391 libinput_device,
392 libinput_event_get_pointer_event(event));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100393 break;
394 case LIBINPUT_EVENT_POINTER_BUTTON:
Peter Hutterer87743e92016-01-18 16:38:22 +1000395 need_frame = handle_pointer_button(libinput_device,
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100396 libinput_event_get_pointer_event(event));
397 break;
398 case LIBINPUT_EVENT_POINTER_AXIS:
Peter Hutterer87743e92016-01-18 16:38:22 +1000399 need_frame = handle_pointer_axis(
400 libinput_device,
401 libinput_event_get_pointer_event(event));
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100402 break;
403 case LIBINPUT_EVENT_TOUCH_DOWN:
404 handle_touch_down(libinput_device,
405 libinput_event_get_touch_event(event));
406 break;
407 case LIBINPUT_EVENT_TOUCH_MOTION:
408 handle_touch_motion(libinput_device,
409 libinput_event_get_touch_event(event));
410 break;
411 case LIBINPUT_EVENT_TOUCH_UP:
412 handle_touch_up(libinput_device,
413 libinput_event_get_touch_event(event));
U. Artie Eoffcd9e5452014-04-17 07:53:24 -0700414 break;
Jonas Ådahl1679f232014-04-12 09:39:51 +0200415 case LIBINPUT_EVENT_TOUCH_FRAME:
416 handle_touch_frame(libinput_device,
417 libinput_event_get_touch_event(event));
418 break;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100419 default:
420 handled = 0;
421 weston_log("unknown libinput event %d\n",
422 libinput_event_get_type(event));
423 }
424
Peter Hutterer87743e92016-01-18 16:38:22 +1000425 if (need_frame)
426 notify_pointer_frame(device->seat);
427
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100428 return handled;
429}
430
431static void
432notify_output_destroy(struct wl_listener *listener, void *data)
433{
434 struct evdev_device *device =
435 container_of(listener,
436 struct evdev_device, output_destroy_listener);
437 struct weston_compositor *c = device->seat->compositor;
438 struct weston_output *output;
439
Ander Conselvan de Oliveiraa7caef92014-04-24 15:11:17 +0300440 if (!device->output_name && !wl_list_empty(&c->output_list)) {
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100441 output = container_of(c->output_list.next,
442 struct weston_output, link);
443 evdev_device_set_output(device, output);
444 } else {
445 device->output = NULL;
446 }
447}
448
Peter Hutterer3fbba492014-09-09 13:02:25 +1000449/**
450 * The WL_CALIBRATION property requires a pixel-specific matrix to be
451 * applied after scaling device coordinates to screen coordinates. libinput
452 * can't do that, so we need to convert the calibration to the normalized
453 * format libinput expects.
454 */
Giulio Camuffo8aedf7b2016-06-02 21:48:12 +0300455void
Peter Hutterer3fbba492014-09-09 13:02:25 +1000456evdev_device_set_calibration(struct evdev_device *device)
457{
458 struct udev *udev;
459 struct udev_device *udev_device = NULL;
460 const char *sysname = libinput_device_get_sysname(device->device);
461 const char *calibration_values;
462 uint32_t width, height;
463 float calibration[6];
464 enum libinput_config_status status;
465
Pekka Paalanendfc9d3b2017-04-18 12:14:32 +0300466 if (!libinput_device_config_calibration_has_matrix(device->device))
Peter Hutterer3fbba492014-09-09 13:02:25 +1000467 return;
468
Pekka Paalanendfc9d3b2017-04-18 12:14:32 +0300469 /* If LIBINPUT_CALIBRATION_MATRIX was set to non-identity, we will not
470 * override it with WL_CALIBRATION. It also means we don't need an
471 * output to load a calibration. */
472 if (libinput_device_config_calibration_get_default_matrix(
473 device->device,
474 calibration) != 0)
475 return;
476
477 if (!device->output) {
478 weston_log("input device %s has no enabled output associated "
479 "(%s named), skipping calibration for now.\n",
480 sysname, device->output_name ?: "none");
481 return;
482 }
483
Peter Hutterer3fbba492014-09-09 13:02:25 +1000484 width = device->output->width;
485 height = device->output->height;
486 if (width == 0 || height == 0)
487 return;
488
Peter Hutterer3fbba492014-09-09 13:02:25 +1000489 udev = udev_new();
490 if (!udev)
491 return;
492
493 udev_device = udev_device_new_from_subsystem_sysname(udev,
494 "input",
495 sysname);
496 if (!udev_device)
497 goto out;
498
499 calibration_values =
500 udev_device_get_property_value(udev_device,
501 "WL_CALIBRATION");
502
Pekka Paalanened51b622018-03-21 14:30:04 +0200503 if (calibration_values) {
504 weston_log("Warning: input device %s has WL_CALIBRATION property set. "
505 "Support for it will be removed in the future. "
506 "Please use LIBINPUT_CALIBRATION_MATRIX instead.\n",
507 sysname);
508 }
509
Peter Hutterer3fbba492014-09-09 13:02:25 +1000510 if (!calibration_values || sscanf(calibration_values,
511 "%f %f %f %f %f %f",
512 &calibration[0],
513 &calibration[1],
514 &calibration[2],
515 &calibration[3],
516 &calibration[4],
517 &calibration[5]) != 6)
518 goto out;
519
520 weston_log("Applying calibration: %f %f %f %f %f %f "
521 "(normalized %f %f)\n",
522 calibration[0],
523 calibration[1],
524 calibration[2],
525 calibration[3],
526 calibration[4],
527 calibration[5],
528 calibration[2] / width,
529 calibration[5] / height);
530
531 /* normalize to a format libinput can use. There is a chance of
532 this being wrong if the width/height don't match the device
533 width/height but I'm not sure how to fix that */
534 calibration[2] /= width;
535 calibration[5] /= height;
536
537 status = libinput_device_config_calibration_set_matrix(device->device,
538 calibration);
539 if (status != LIBINPUT_CONFIG_STATUS_SUCCESS)
540 weston_log("Failed to apply calibration.\n");
541
542out:
543 if (udev_device)
544 udev_device_unref(udev_device);
545 udev_unref(udev);
546}
547
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100548void
549evdev_device_set_output(struct evdev_device *device,
550 struct weston_output *output)
551{
Pekka Paalanen018e6ad2017-04-18 12:22:12 +0300552 if (device->output == output)
553 return;
554
U. Artie Eoff161c6c52014-04-17 07:53:25 -0700555 if (device->output_destroy_listener.notify) {
556 wl_list_remove(&device->output_destroy_listener.link);
557 device->output_destroy_listener.notify = NULL;
558 }
559
Pekka Paalanen6632b6d2017-04-18 12:22:12 +0300560 weston_log("associating input device %s with output %s "
561 "(%s by udev)\n",
562 libinput_device_get_sysname(device->device),
563 output->name,
564 device->output_name ?: "none");
565
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100566 device->output = output;
567 device->output_destroy_listener.notify = notify_output_destroy;
568 wl_signal_add(&output->destroy_signal,
569 &device->output_destroy_listener);
Peter Hutterer3fbba492014-09-09 13:02:25 +1000570 evdev_device_set_calibration(device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100571}
572
573struct evdev_device *
574evdev_device_create(struct libinput_device *libinput_device,
575 struct weston_seat *seat)
576{
577 struct evdev_device *device;
578
579 device = zalloc(sizeof *device);
580 if (device == NULL)
581 return NULL;
582
583 device->seat = seat;
584 wl_list_init(&device->link);
585 device->device = libinput_device;
586
587 if (libinput_device_has_capability(libinput_device,
588 LIBINPUT_DEVICE_CAP_KEYBOARD)) {
589 weston_seat_init_keyboard(seat, NULL);
590 device->seat_caps |= EVDEV_SEAT_KEYBOARD;
591 }
592 if (libinput_device_has_capability(libinput_device,
593 LIBINPUT_DEVICE_CAP_POINTER)) {
594 weston_seat_init_pointer(seat);
595 device->seat_caps |= EVDEV_SEAT_POINTER;
596 }
597 if (libinput_device_has_capability(libinput_device,
598 LIBINPUT_DEVICE_CAP_TOUCH)) {
599 weston_seat_init_touch(seat);
600 device->seat_caps |= EVDEV_SEAT_TOUCH;
601 }
602
603 libinput_device_set_user_data(libinput_device, device);
604 libinput_device_ref(libinput_device);
605
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100606 return device;
607}
608
609void
610evdev_device_destroy(struct evdev_device *device)
611{
612 if (device->seat_caps & EVDEV_SEAT_POINTER)
613 weston_seat_release_pointer(device->seat);
614 if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
615 weston_seat_release_keyboard(device->seat);
616 if (device->seat_caps & EVDEV_SEAT_TOUCH)
617 weston_seat_release_touch(device->seat);
618
619 if (device->output)
620 wl_list_remove(&device->output_destroy_listener.link);
621 wl_list_remove(&device->link);
622 libinput_device_unref(device->device);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100623 free(device->output_name);
624 free(device);
625}
626
627void
628evdev_notify_keyboard_focus(struct weston_seat *seat,
629 struct wl_list *evdev_devices)
630{
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100631 struct wl_array keys;
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100632
Derek Foremand621df22014-11-19 11:04:12 -0600633 if (seat->keyboard_device_count == 0)
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100634 return;
635
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100636 wl_array_init(&keys);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100637 notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC);
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100638 wl_array_release(&keys);
639}