blob: 36823213811ca259d17fbfac5492b5c26775dd03 [file] [log] [blame]
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -05001#include <stdio.h>
2#include <stdlib.h>
3#include <linux/input.h>
4#include <fcntl.h>
5#include <unistd.h>
6
7#include <linux/input.h>
8
9#include "wayland.h"
10
11struct wl_input_device {
12 struct wl_object base;
13 struct wl_event_source *source;
14 struct wl_display *display;
15 int fd;
16 int tool;
17 int32_t x, y;
18};
19
20static const struct wl_method input_device_methods[] = {
21};
22
23static const struct wl_interface input_device_interface = {
24 "input_device", 1,
25 ARRAY_LENGTH(input_device_methods),
26 input_device_methods,
27};
28
29static void wl_input_device_data(int fd, uint32_t mask, void *data)
30{
31 struct wl_input_device *device = data;
32 struct input_event ev[8], *e, *end;
33 int len, value, dx, dy, absolute_event;
34
35 dx = 0;
36 dy = 0;
37 absolute_event = 0;
38
39 len = read(fd, &ev, sizeof ev);
40 if (len < 0 || len % sizeof e[0] != 0) {
41 /* FIXME: handle error... reopen device? */;
42 return;
43 }
44
45 e = ev;
46 end = (void *) ev + len;
47 for (e = ev; e < end; e++) {
48 /* Get the signed value, earlier kernels had this as unsigned */
49 value = e->value;
50
51 switch (e->type) {
52 case EV_REL:
53 switch (e->code) {
54 case REL_X:
55 dx += value;
56 break;
57
58 case REL_Y:
59 dy += value;
60 break;
61 }
Kristian Høgsbergec8ef722008-11-24 00:13:13 -050062 break;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050063
64 case EV_ABS:
65 absolute_event = 1;
66 switch (e->code) {
67 case ABS_X:
68 device->x = value;
69 break;
70 case ABS_Y:
71 device->y = value;
72 break;
73 }
Kristian Høgsbergec8ef722008-11-24 00:13:13 -050074 break;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -050075
76 case EV_KEY:
77 if (value == 2)
78 break;
79
80 switch (e->code) {
81 case BTN_TOUCH:
82 case BTN_TOOL_PEN:
83 case BTN_TOOL_RUBBER:
84 case BTN_TOOL_BRUSH:
85 case BTN_TOOL_PENCIL:
86 case BTN_TOOL_AIRBRUSH:
87 case BTN_TOOL_FINGER:
88 case BTN_TOOL_MOUSE:
89 case BTN_TOOL_LENS:
90 device->tool = value ? e->code : 0;
91 break;
92
93 case BTN_LEFT:
94 wl_display_post_button_event(device->display,
95 &device->base, 0, value);
96 break;
97
98 case BTN_RIGHT:
99 wl_display_post_button_event(device->display,
100 &device->base, 2, value);
101 break;
102
103 case BTN_MIDDLE:
104 wl_display_post_button_event(device->display,
105 &device->base, 1, value);
106 break;
Kristian Høgsbergcddc0ad2008-11-24 00:31:49 -0500107
108 default:
109 wl_display_post_key_event(device->display,
110 &device->base, e->code, value);
111 break;
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500112 }
113 }
114 }
115
116 if (dx != 0 || dy != 0)
117 wl_display_post_relative_event(device->display,
118 &device->base, dx, dy);
119 if (absolute_event && device->tool)
120 wl_display_post_absolute_event(device->display,
121 &device->base,
122 device->x, device->y);
123}
124
Kristian Høgsbergcddc0ad2008-11-24 00:31:49 -0500125WL_EXPORT struct wl_object *
126wl_input_device_create(struct wl_display *display, const char *path)
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500127{
128 struct wl_input_device *device;
129 struct wl_event_loop *loop;
130
131 device = malloc(sizeof *device);
132 if (device == NULL)
133 return NULL;
134
Kristian Høgsbergf9bc7952008-11-02 10:12:29 -0500135 device->base.interface = &input_device_interface;
136 device->display = display;
137 device->tool = 1;
138
139 device->fd = open(path, O_RDONLY);
140 if (device->fd < 0) {
141 free(device);
142 fprintf(stderr, "couldn't create pointer for %s: %m\n", path);
143 return NULL;
144 }
145
146 loop = wl_display_get_event_loop(display);
147 device->source = wl_event_loop_add_fd(loop, device->fd,
148 WL_EVENT_READABLE,
149 wl_input_device_data, device);
150 if (device->source == NULL) {
151 close(device->fd);
152 free(device);
153 return NULL;
154 }
155
156 return &device->base;
157}