Add keyboard input, move input device creation to compositor.
[profile/ivi/wayland.git] / evdev.c
1 #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
11 struct 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
20 static const struct wl_method input_device_methods[] = {
21 };
22
23 static const struct wl_interface input_device_interface = {
24         "input_device", 1,
25         ARRAY_LENGTH(input_device_methods),
26         input_device_methods,
27 };
28
29 static 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                         }
62                         break;
63
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                         }
74                         break;
75
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;
107
108                         default:
109                                 wl_display_post_key_event(device->display,
110                                                           &device->base, e->code, value);
111                                 break;
112                         }
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
125 WL_EXPORT struct wl_object *
126 wl_input_device_create(struct wl_display *display, const char *path)
127 {
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
135         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 }