Split out evdev handling to its own file

dev
Kristian Høgsberg 14 years ago
parent ed64311b6c
commit 43db4015f9
  1. 1
      compositor/Makefile.am
  2. 195
      compositor/compositor-drm.c
  3. 3
      compositor/compositor.h
  4. 223
      compositor/evdev.c

@ -22,6 +22,7 @@ compositor_SOURCES = \
screenshooter.c \
screenshooter-protocol.c \
screenshooter-server-protocol.h \
evdev.c \
drm.c \
shm.c

@ -64,199 +64,6 @@ struct drm_output {
uint32_t current;
};
struct drm_input {
struct wlsc_input_device base;
};
struct evdev_input_device {
struct drm_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 drm_compositor *c;
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;
c = (struct drm_compositor *)
device->master->base.input_device.compositor;
if (!c->vt_active)
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 drm_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;
}
static void
drm_input_create(struct drm_compositor *c)
{
struct drm_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->base);
e = udev_enumerate_new(c->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(c->udev, path);
evdev_input_device_create(input, c->base.wl_display,
udev_device_get_devnode(device));
}
udev_enumerate_unref(e);
c->base.input_device = &input->base.input_device;
}
static void
drm_compositor_present(struct wlsc_compositor *ec)
{
@ -683,7 +490,7 @@ drm_compositor_create(struct wl_display *display, int connector)
return NULL;
}
drm_input_create(ec);
evdev_input_add_devices(&ec->base, ec->udev);
loop = wl_display_get_event_loop(ec->base.wl_display);
ec->drm_source =

@ -195,6 +195,9 @@ drm_compositor_create(struct wl_display *display, int connector);
struct wlsc_compositor *
wayland_compositor_create(struct wl_display *display, int width, int height);
void
evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev);
void
screenshooter_create(struct wlsc_compositor *ec);

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/input.h>
#include <unistd.h>
#include <fcntl.h>
#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;
}
Loading…
Cancel
Save