blob: 2ba4ec375890451f4f75509c2de139ac9363b2bd [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
285void
286evdev_device_set_output(struct evdev_device *device,
287 struct weston_output *output)
288{
U. Artie Eoff161c6c52014-04-17 07:53:25 -0700289 if (device->output_destroy_listener.notify) {
290 wl_list_remove(&device->output_destroy_listener.link);
291 device->output_destroy_listener.notify = NULL;
292 }
293
Jonas Ådahle0de3c22014-03-12 22:08:42 +0100294 device->output = output;
295 device->output_destroy_listener.notify = notify_output_destroy;
296 wl_signal_add(&output->destroy_signal,
297 &device->output_destroy_listener);
298}
299
300struct evdev_device *
301evdev_device_create(struct libinput_device *libinput_device,
302 struct weston_seat *seat)
303{
304 struct evdev_device *device;
305
306 device = zalloc(sizeof *device);
307 if (device == NULL)
308 return NULL;
309
310 device->seat = seat;
311 wl_list_init(&device->link);
312 device->device = libinput_device;
313
314 if (libinput_device_has_capability(libinput_device,
315 LIBINPUT_DEVICE_CAP_KEYBOARD)) {
316 weston_seat_init_keyboard(seat, NULL);
317 device->seat_caps |= EVDEV_SEAT_KEYBOARD;
318 }
319 if (libinput_device_has_capability(libinput_device,
320 LIBINPUT_DEVICE_CAP_POINTER)) {
321 weston_seat_init_pointer(seat);
322 device->seat_caps |= EVDEV_SEAT_POINTER;
323 }
324 if (libinput_device_has_capability(libinput_device,
325 LIBINPUT_DEVICE_CAP_TOUCH)) {
326 weston_seat_init_touch(seat);
327 device->seat_caps |= EVDEV_SEAT_TOUCH;
328 }
329
330 libinput_device_set_user_data(libinput_device, device);
331 libinput_device_ref(libinput_device);
332
333 return device;
334}
335
336void
337evdev_device_destroy(struct evdev_device *device)
338{
339 if (device->seat_caps & EVDEV_SEAT_POINTER)
340 weston_seat_release_pointer(device->seat);
341 if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
342 weston_seat_release_keyboard(device->seat);
343 if (device->seat_caps & EVDEV_SEAT_TOUCH)
344 weston_seat_release_touch(device->seat);
345
346 if (device->output)
347 wl_list_remove(&device->output_destroy_listener.link);
348 wl_list_remove(&device->link);
349 libinput_device_unref(device->device);
350 free(device->devnode);
351 free(device->output_name);
352 free(device);
353}
354
355void
356evdev_notify_keyboard_focus(struct weston_seat *seat,
357 struct wl_list *evdev_devices)
358{
359 struct evdev_device *device;
360 struct wl_array keys;
361 unsigned int i, set;
362 char evdev_keys[(KEY_CNT + 7) / 8];
363 char all_keys[(KEY_CNT + 7) / 8];
364 uint32_t *k;
365 int ret;
366
367 if (!seat->keyboard_device_count > 0)
368 return;
369
370 memset(all_keys, 0, sizeof all_keys);
371 wl_list_for_each(device, evdev_devices, link) {
372 memset(evdev_keys, 0, sizeof evdev_keys);
373 ret = libinput_device_get_keys(device->device,
374 evdev_keys,
375 sizeof evdev_keys);
376 if (ret < 0) {
377 weston_log("failed to get keys for device %s\n",
378 device->devnode);
379 continue;
380 }
381 for (i = 0; i < ARRAY_LENGTH(evdev_keys); i++)
382 all_keys[i] |= evdev_keys[i];
383 }
384
385 wl_array_init(&keys);
386 for (i = 0; i < KEY_CNT; i++) {
387 set = all_keys[i >> 3] & (1 << (i & 7));
388 if (set) {
389 k = wl_array_add(&keys, sizeof *k);
390 *k = i;
391 }
392 }
393
394 notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC);
395
396 wl_array_release(&keys);
397}