blob: 6ff7b69927be59aaa1de3b05f1caa93e3936051c [file] [log] [blame]
Kristian Høgsberg43db4012011-01-14 14:45:42 -05001/*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <linux/input.h>
27#include <unistd.h>
28#include <fcntl.h>
29
30#include "compositor.h"
31
32struct evdev_input {
33 struct wlsc_input_device base;
34};
35
36struct evdev_input_device {
37 struct evdev_input *master;
38 struct wl_event_source *source;
39 int tool, new_x, new_y;
40 int base_x, base_y;
41 int fd;
Kristian Høgsberg96c8be92011-01-14 14:49:46 -050042 int min_x, max_x, min_y, max_y;
Kristian Høgsberg43db4012011-01-14 14:45:42 -050043};
44
45static void evdev_input_device_data(int fd, uint32_t mask, void *data)
46{
47 struct wlsc_compositor *ec;
48 struct evdev_input_device *device = data;
49 struct input_event ev[8], *e, *end;
50 int len, value, dx, dy, absolute_event;
51 int x, y;
52 uint32_t time;
53
Kristian Høgsberg96c8be92011-01-14 14:49:46 -050054 /* FIXME: Obviously we need to not hardcode these here, but
55 * instead get the values from the output it's associated with. */
56 const int screen_width = 1024, screen_height = 600;
57
Kristian Høgsberg43db4012011-01-14 14:45:42 -050058 ec = (struct wlsc_compositor *)
59 device->master->base.input_device.compositor;
60 if (!ec->focus)
61 return;
62
63 dx = 0;
64 dy = 0;
65 absolute_event = 0;
66 x = device->master->base.input_device.x;
67 y = device->master->base.input_device.y;
68
69 len = read(fd, &ev, sizeof ev);
70 if (len < 0 || len % sizeof e[0] != 0) {
71 /* FIXME: handle error... reopen device? */;
72 return;
73 }
74
75 e = ev;
76 end = (void *) ev + len;
77 for (e = ev; e < end; e++) {
78 /* Get the signed value, earlier kernels had this as unsigned */
79 value = e->value;
80 time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
81
82 switch (e->type) {
83 case EV_REL:
84 switch (e->code) {
85 case REL_X:
86 dx += value;
87 break;
88
89 case REL_Y:
90 dy += value;
91 break;
92 }
93 break;
94
95 case EV_ABS:
Kristian Høgsberg43db4012011-01-14 14:45:42 -050096 switch (e->code) {
97 case ABS_X:
Kristian Høgsberg96c8be92011-01-14 14:49:46 -050098 absolute_event = device->tool;
99 x = (value - device->min_x) * screen_width /
100 (device->max_x - device->min_x);
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500101 break;
102 case ABS_Y:
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500103 absolute_event = device->tool;
104 y = (value - device->min_y) * screen_height /
105 (device->max_y - device->min_y);
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500106 break;
107 }
108 break;
109
110 case EV_KEY:
111 if (value == 2)
112 break;
113
114 switch (e->code) {
115 case BTN_TOUCH:
116 case BTN_TOOL_PEN:
117 case BTN_TOOL_RUBBER:
118 case BTN_TOOL_BRUSH:
119 case BTN_TOOL_PENCIL:
120 case BTN_TOOL_AIRBRUSH:
121 case BTN_TOOL_FINGER:
122 case BTN_TOOL_MOUSE:
123 case BTN_TOOL_LENS:
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500124 device->tool = value ? e->code : 0;
125 break;
126
127 case BTN_LEFT:
128 case BTN_RIGHT:
129 case BTN_MIDDLE:
130 case BTN_SIDE:
131 case BTN_EXTRA:
132 case BTN_FORWARD:
133 case BTN_BACK:
134 case BTN_TASK:
135 notify_button(&device->master->base.input_device,
136 time, e->code, value);
137 break;
138
139 default:
140 notify_key(&device->master->base.input_device,
141 time, e->code, value);
142 break;
143 }
144 }
145 }
146
147 if (dx != 0 || dy != 0)
148 notify_motion(&device->master->base.input_device,
149 time, x + dx, y + dy);
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500150 if (absolute_event)
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500151 notify_motion(&device->master->base.input_device, time, x, y);
152}
153
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500154#define TEST_BIT(b, i) (b[(i) / 32] & (1 << (i & 31)))
155
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500156static struct evdev_input_device *
157evdev_input_device_create(struct evdev_input *master,
158 struct wl_display *display, const char *path)
159{
160 struct evdev_input_device *device;
161 struct wl_event_loop *loop;
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500162 struct input_absinfo absinfo;
163 uint32_t ev_bits[EV_MAX];
164 uint32_t key_bits[KEY_MAX];
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500165
166 device = malloc(sizeof *device);
167 if (device == NULL)
168 return NULL;
169
170 device->tool = 1;
171 device->new_x = 1;
172 device->new_y = 1;
173 device->master = master;
174
175 device->fd = open(path, O_RDONLY);
176 if (device->fd < 0) {
177 free(device);
178 fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
179 return NULL;
180 }
181
Kristian Høgsberg96c8be92011-01-14 14:49:46 -0500182 ioctl(device->fd, EVIOCGBIT(0, EV_MAX), ev_bits);
183 if (TEST_BIT(ev_bits, EV_ABS)) {
184 ioctl(device->fd, EVIOCGBIT(EV_ABS, EV_MAX), key_bits);
185 if (TEST_BIT(key_bits, ABS_X)) {
186 ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo);
187 device->min_x = absinfo.minimum;
188 device->max_x = absinfo.maximum;
189 }
190 if (TEST_BIT(key_bits, ABS_Y)) {
191 ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo);
192 device->min_y = absinfo.minimum;
193 device->max_y = absinfo.maximum;
194 }
195 }
196
Kristian Høgsberg43db4012011-01-14 14:45:42 -0500197 loop = wl_display_get_event_loop(display);
198 device->source = wl_event_loop_add_fd(loop, device->fd,
199 WL_EVENT_READABLE,
200 evdev_input_device_data, device);
201 if (device->source == NULL) {
202 close(device->fd);
203 free(device);
204 return NULL;
205 }
206
207 return device;
208}
209
210void
211evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev)
212{
213 struct evdev_input *input;
214 struct udev_enumerate *e;
215 struct udev_list_entry *entry;
216 struct udev_device *device;
217 const char *path;
218
219 input = malloc(sizeof *input);
220 if (input == NULL)
221 return;
222
223 memset(input, 0, sizeof *input);
224 wlsc_input_device_init(&input->base, c);
225
226 e = udev_enumerate_new(udev);
227 udev_enumerate_add_match_subsystem(e, "input");
228 udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1");
229 udev_enumerate_scan_devices(e);
230 udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) {
231 path = udev_list_entry_get_name(entry);
232 device = udev_device_new_from_syspath(udev, path);
233 evdev_input_device_create(input, c->wl_display,
234 udev_device_get_devnode(device));
235 }
236 udev_enumerate_unref(e);
237
238 c->input_device = &input->base.input_device;
239}