blob: beba634bf678da6004e2dbf77039e03189421031 [file] [log] [blame]
Kristian Høgsbergffd710e2008-12-02 15:15:01 -05001/*
2 * Copyright © 2008 Kristian Høgsberg
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050023#include <stdio.h>
24#include <stdlib.h>
25#include <linux/input.h>
26#include <fcntl.h>
27#include <unistd.h>
28
29#include <linux/input.h>
30
31#include "wayland.h"
32
33struct wl_input_device {
34 struct wl_object base;
35 struct wl_event_source *source;
36 struct wl_display *display;
37 int fd;
Kristian Høgsberg0ee84082008-11-25 23:16:31 -050038 int tool, new_x, new_y;
39 int32_t x, y, base_x, base_y;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050040};
41
42static const struct wl_method input_device_methods[] = {
43};
44
45static const struct wl_interface input_device_interface = {
46 "input_device", 1,
47 ARRAY_LENGTH(input_device_methods),
48 input_device_methods,
49};
50
51static void wl_input_device_data(int fd, uint32_t mask, void *data)
52{
53 struct wl_input_device *device = data;
54 struct input_event ev[8], *e, *end;
55 int len, value, dx, dy, absolute_event;
56
57 dx = 0;
58 dy = 0;
59 absolute_event = 0;
60
61 len = read(fd, &ev, sizeof ev);
62 if (len < 0 || len % sizeof e[0] != 0) {
63 /* FIXME: handle error... reopen device? */;
64 return;
65 }
66
67 e = ev;
68 end = (void *) ev + len;
69 for (e = ev; e < end; e++) {
70 /* Get the signed value, earlier kernels had this as unsigned */
71 value = e->value;
72
73 switch (e->type) {
74 case EV_REL:
75 switch (e->code) {
76 case REL_X:
77 dx += value;
78 break;
79
80 case REL_Y:
81 dy += value;
82 break;
83 }
Kristian Høgsbergec8ef722008-11-24 00:13:13 -050084 break;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050085
86 case EV_ABS:
87 absolute_event = 1;
88 switch (e->code) {
89 case ABS_X:
Kristian Høgsberg0ee84082008-11-25 23:16:31 -050090 if (device->new_x) {
91 device->base_x = device->x - value;
92 device->new_x = 0;
93 }
94 device->x = device->base_x + value;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050095 break;
96 case ABS_Y:
Kristian Høgsberg0ee84082008-11-25 23:16:31 -050097 if (device->new_y) {
98 device->base_y = device->y - value;
99 device->new_y = 0;
100 }
101 device->y = device->base_y + value;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500102 break;
103 }
Kristian Høgsbergec8ef722008-11-24 00:13:13 -0500104 break;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500105
106 case EV_KEY:
107 if (value == 2)
108 break;
109
110 switch (e->code) {
111 case BTN_TOUCH:
112 case BTN_TOOL_PEN:
113 case BTN_TOOL_RUBBER:
114 case BTN_TOOL_BRUSH:
115 case BTN_TOOL_PENCIL:
116 case BTN_TOOL_AIRBRUSH:
117 case BTN_TOOL_FINGER:
118 case BTN_TOOL_MOUSE:
119 case BTN_TOOL_LENS:
Kristian Høgsberg0ee84082008-11-25 23:16:31 -0500120 if (device->tool == 0 && value) {
121 device->new_x = 1;
122 device->new_y = 1;
123 }
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500124 device->tool = value ? e->code : 0;
125 break;
126
127 case BTN_LEFT:
128 wl_display_post_button_event(device->display,
129 &device->base, 0, value);
130 break;
131
132 case BTN_RIGHT:
133 wl_display_post_button_event(device->display,
134 &device->base, 2, value);
135 break;
136
137 case BTN_MIDDLE:
138 wl_display_post_button_event(device->display,
139 &device->base, 1, value);
140 break;
Kristian Høgsbergcddc0ad2008-11-24 00:31:49 -0500141
142 default:
143 wl_display_post_key_event(device->display,
144 &device->base, e->code, value);
145 break;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500146 }
147 }
148 }
149
150 if (dx != 0 || dy != 0)
151 wl_display_post_relative_event(device->display,
152 &device->base, dx, dy);
153 if (absolute_event && device->tool)
154 wl_display_post_absolute_event(device->display,
155 &device->base,
156 device->x, device->y);
157}
158
Kristian Høgsbergcddc0ad2008-11-24 00:31:49 -0500159WL_EXPORT struct wl_object *
160wl_input_device_create(struct wl_display *display, const char *path)
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500161{
162 struct wl_input_device *device;
163 struct wl_event_loop *loop;
164
165 device = malloc(sizeof *device);
166 if (device == NULL)
167 return NULL;
168
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500169 device->base.interface = &input_device_interface;
170 device->display = display;
171 device->tool = 1;
Kristian Høgsberg0ee84082008-11-25 23:16:31 -0500172 device->x = 100;
173 device->y = 100;
174 device->new_x = 1;
175 device->new_y = 1;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500176
177 device->fd = open(path, O_RDONLY);
178 if (device->fd < 0) {
179 free(device);
180 fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
181 return NULL;
182 }
183
184 loop = wl_display_get_event_loop(display);
185 device->source = wl_event_loop_add_fd(loop, device->fd,
186 WL_EVENT_READABLE,
187 wl_input_device_data, device);
188 if (device->source == NULL) {
189 close(device->fd);
190 free(device);
191 return NULL;
192 }
193
194 return &device->base;
195}