From: Kristian Høgsberg Date: Fri, 14 Jan 2011 19:45:42 +0000 (-0500) Subject: Split out evdev handling to its own file X-Git-Tag: 0.1.0~163^2~150 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3b3c0013815e0e3896f308d5973ccefce43c24a8;p=platform%2Fupstream%2Flibinput.git Split out evdev handling to its own file --- diff --git a/compositor/evdev.c b/compositor/evdev.c new file mode 100644 index 00000000..2b5ab6bf --- /dev/null +++ b/compositor/evdev.c @@ -0,0 +1,223 @@ +/* + * Copyright © 2010 Intel Corporation + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. The copyright holders make + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include "compositor.h" + +struct evdev_input { + struct wlsc_input_device base; +}; + +struct evdev_input_device { + struct evdev_input *master; + struct wl_event_source *source; + int tool, new_x, new_y; + int base_x, base_y; + int fd; +}; + +static void evdev_input_device_data(int fd, uint32_t mask, void *data) +{ + struct wlsc_compositor *ec; + struct evdev_input_device *device = data; + struct input_event ev[8], *e, *end; + int len, value, dx, dy, absolute_event; + int x, y; + uint32_t time; + + ec = (struct wlsc_compositor *) + device->master->base.input_device.compositor; + if (!ec->focus) + return; + + dx = 0; + dy = 0; + absolute_event = 0; + x = device->master->base.input_device.x; + y = device->master->base.input_device.y; + + len = read(fd, &ev, sizeof ev); + if (len < 0 || len % sizeof e[0] != 0) { + /* FIXME: handle error... reopen device? */; + return; + } + + e = ev; + end = (void *) ev + len; + for (e = ev; e < end; e++) { + /* Get the signed value, earlier kernels had this as unsigned */ + value = e->value; + time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; + + switch (e->type) { + case EV_REL: + switch (e->code) { + case REL_X: + dx += value; + break; + + case REL_Y: + dy += value; + break; + } + break; + + case EV_ABS: + absolute_event = 1; + switch (e->code) { + case ABS_X: + if (device->new_x) { + device->base_x = x - value; + device->new_x = 0; + } + x = device->base_x + value; + break; + case ABS_Y: + if (device->new_y) { + device->base_y = y - value; + device->new_y = 0; + } + y = device->base_y + value; + break; + } + break; + + case EV_KEY: + if (value == 2) + break; + + switch (e->code) { + case BTN_TOUCH: + case BTN_TOOL_PEN: + case BTN_TOOL_RUBBER: + case BTN_TOOL_BRUSH: + case BTN_TOOL_PENCIL: + case BTN_TOOL_AIRBRUSH: + case BTN_TOOL_FINGER: + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + if (device->tool == 0 && value) { + device->new_x = 1; + device->new_y = 1; + } + device->tool = value ? e->code : 0; + break; + + case BTN_LEFT: + case BTN_RIGHT: + case BTN_MIDDLE: + case BTN_SIDE: + case BTN_EXTRA: + case BTN_FORWARD: + case BTN_BACK: + case BTN_TASK: + notify_button(&device->master->base.input_device, + time, e->code, value); + break; + + default: + notify_key(&device->master->base.input_device, + time, e->code, value); + break; + } + } + } + + if (dx != 0 || dy != 0) + notify_motion(&device->master->base.input_device, + time, x + dx, y + dy); + if (absolute_event && device->tool) + notify_motion(&device->master->base.input_device, time, x, y); +} + +static struct evdev_input_device * +evdev_input_device_create(struct evdev_input *master, + struct wl_display *display, const char *path) +{ + struct evdev_input_device *device; + struct wl_event_loop *loop; + + device = malloc(sizeof *device); + if (device == NULL) + return NULL; + + device->tool = 1; + device->new_x = 1; + device->new_y = 1; + device->master = master; + + device->fd = open(path, O_RDONLY); + if (device->fd < 0) { + free(device); + fprintf(stderr, "couldn't create pointer for %s: %m\n", path); + return NULL; + } + + loop = wl_display_get_event_loop(display); + device->source = wl_event_loop_add_fd(loop, device->fd, + WL_EVENT_READABLE, + evdev_input_device_data, device); + if (device->source == NULL) { + close(device->fd); + free(device); + return NULL; + } + + return device; +} + +void +evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev) +{ + struct evdev_input *input; + struct udev_enumerate *e; + struct udev_list_entry *entry; + struct udev_device *device; + const char *path; + + input = malloc(sizeof *input); + if (input == NULL) + return; + + memset(input, 0, sizeof *input); + wlsc_input_device_init(&input->base, c); + + e = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(e, "input"); + udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1"); + udev_enumerate_scan_devices(e); + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { + path = udev_list_entry_get_name(entry); + device = udev_device_new_from_syspath(udev, path); + evdev_input_device_create(input, c->wl_display, + udev_device_get_devnode(device)); + } + udev_enumerate_unref(e); + + c->input_device = &input->base.input_device; +}