[PATCH v2 6/9] evdev: organize main event processing loop

Tiago Vignatti tiago.vignatti at intel.com
Wed Oct 26 05:55:26 PDT 2011


No functional changes on this commit, but the general idea was stolen from X
input evdev with the intents of copying pretty much the way done there which
will ease next when implementing a smarter method for computing valuators.

Signed-off-by: Tiago Vignatti <tiago.vignatti at intel.com>
---
changes since v1:
- added 'count' variable to compute the number elements
- fix size of main struct input_event as 8, without using a macro

 compositor/evdev.c |  123 ++++++++++++++++++++++++++++++++++------------------
 1 files changed, 81 insertions(+), 42 deletions(-)

diff --git a/compositor/evdev.c b/compositor/evdev.c
index 3661236..6b9c280 100644
--- a/compositor/evdev.c
+++ b/compositor/evdev.c
@@ -26,6 +26,7 @@
 #include <linux/input.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <errno.h>
 
 #include "compositor.h"
 
@@ -49,13 +50,18 @@ struct evdev_input_device {
 	int is_touchpad, old_x_value, old_y_value, reset_x_value, reset_y_value;
 	uint32_t time;
 
-	uint32_t abs_queued;
+	uint32_t abs_queued, rel_queued;
 };
 
 static inline void
-evdev_process_key(struct evdev_input_device *device,
-                        struct input_event *e, int value)
+evdev_process_key(struct evdev_input_device *device, struct input_event *e)
 {
+	/* Get the signed value, earlier kernels had this as unsigned */
+	int value = e->value;
+
+	if (value == 2)
+		return;
+
 	switch (e->code) {
 	case BTN_TOOL_PEN:
 	case BTN_TOOL_RUBBER:
@@ -98,8 +104,10 @@ evdev_process_key(struct evdev_input_device *device,
 
 static inline void
 evdev_process_absolute_motion(struct evdev_input_device *device,
-			struct input_event *e, int value)
+			struct input_event *e)
 {
+	/* Get the signed value, earlier kernels had this as unsigned */
+	int value = e->value;
 	const int screen_width = device->output->current->width;
 	const int screen_height = device->output->current->height;
 
@@ -119,8 +127,11 @@ evdev_process_absolute_motion(struct evdev_input_device *device,
 
 static inline void
 evdev_process_absolute_motion_touchpad(struct evdev_input_device *device,
-			struct input_event *e, int value)
+			struct input_event *e)
 {
+	/* Get the signed value, earlier kernels had this as unsigned */
+	int value = e->value;
+
 	/* FIXME: Make this configurable somehow. */
 	const int touchpad_speed = 700;
 
@@ -147,12 +158,18 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device,
 		device->old_y_value = value;
 		break;
 	}
+
+	/* we converted to relative motion so treat accordingly */
+	device->rel_queued = 1;
 }
 
 static inline void
 evdev_process_relative_motion(struct evdev_input_device *device,
-			      struct input_event *e, int value)
+			      struct input_event *e)
 {
+	/* Get the signed value, earlier kernels had this as unsigned */
+	int value = e->value;
+
 	switch (e->code) {
 	case REL_X:
 		device->dx += value;
@@ -161,6 +178,47 @@ evdev_process_relative_motion(struct evdev_input_device *device,
 		device->dy += value;
 		break;
 	}
+	device->rel_queued = 1;
+}
+
+static inline void
+evdev_notify(struct evdev_input_device *device, struct input_event *e)
+{
+	if (device->rel_queued)
+               notify_motion(&device->master->base.input_device,
+                             device->time, device->x + device->dx,
+                             device->y + device->dy);
+
+	if (device->abs_queued)
+		notify_motion(&device->master->base.input_device,
+			      device->time, device->x, device->y);
+
+
+	device->rel_queued = 0;
+	device->abs_queued = 0;
+}
+
+static void
+evdev_process_event(struct evdev_input_device *device, struct input_event *e)
+{
+	device->time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
+
+	switch (e->type) {
+	case EV_REL:
+		evdev_process_relative_motion(device, e);
+		break;
+	case EV_ABS:
+		if (device->is_touchpad)
+			evdev_process_absolute_motion_touchpad(device, e);
+		else
+			evdev_process_absolute_motion(device, e);
+		break;
+	case EV_KEY:
+		evdev_process_key(device, e);
+		break;
+	}
+
+	evdev_notify(device, e);
 }
 
 static int
@@ -168,8 +226,8 @@ 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;
+	struct input_event ev[8];
+	int i, count, len = sizeof(ev);
 
 	ec = (struct wlsc_compositor *)
 		device->master->base.input_device.compositor;
@@ -181,45 +239,26 @@ evdev_input_device_data(int fd, uint32_t mask, void *data)
 	device->x = device->master->base.input_device.x;
 	device->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 1;
-	}
-
-	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;
-		device->time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
-
-		switch (e->type) {
-		case EV_REL:
-			evdev_process_relative_motion(device, e, value);
+	while (len == sizeof(ev))
+	{
+		len = read(fd, &ev, sizeof(ev));
+		if (len <= 0) {
+			/* FIXME: handle error... reopen device? */
+			fprintf(stderr, "input read error %s", strerror(errno));
 			break;
-		case EV_ABS:
-			if (device->is_touchpad)
-				evdev_process_absolute_motion_touchpad(device,
-					e, value);
-			else
-				evdev_process_absolute_motion(device, e, value);
+		}
+		/* The kernel promises that we always only read a complete
+		 * event, so len != sizeof ev is an error. */
+		if (len % sizeof(ev[0])) {
+			fprintf(stderr, "input read error %s", strerror(errno));
 			break;
-		case EV_KEY:
-			if (value == 2)
-				break;
-			evdev_process_key(device, e, value);
 		}
-	}
 
-	if (device->dx != 0 || device->dy != 0)
-		notify_motion(&device->master->base.input_device,
-			      device->time, device->x + device->dx, device->y + device->dy);
-	if (device->abs_queued)
-		notify_motion(&device->master->base.input_device, device->time,
-		              device->x, device->y);
+		count = len / sizeof ev[0];
+		for (i = 0; i < count; i++)
+			evdev_process_event(device, &ev[i]);
+	}
 
-	device->abs_queued = 0;
 	return 1;
 }
 
-- 
1.7.5.4



More information about the wayland-devel mailing list