evdev-touchpad: Cleanup and refactoring

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
dev
Jonas Ådahl 12 years ago committed by Kristian Høgsberg
parent b2f957a9f1
commit c689493b1a
  1. 225
      src/evdev-touchpad.c

@ -42,11 +42,13 @@ enum touchpad_model {
TOUCHPAD_MODEL_ELANTECH TOUCHPAD_MODEL_ELANTECH
}; };
#define TOUCHPAD_EVENT_NONE 0 enum touchpad_event {
#define TOUCHPAD_EVENT_ABSOLUTE_ANY (1 << 0) TOUCHPAD_EVENT_NONE = 0,
#define TOUCHPAD_EVENT_ABSOLUTE_X (1 << 1) TOUCHPAD_EVENT_ABSOLUTE_ANY = (1 << 0),
#define TOUCHPAD_EVENT_ABSOLUTE_Y (1 << 2) TOUCHPAD_EVENT_ABSOLUTE_X = (1 << 1),
#define TOUCHPAD_EVENT_REPORT (1 << 3) TOUCHPAD_EVENT_ABSOLUTE_Y = (1 << 2),
TOUCHPAD_EVENT_REPORT = (1 << 3)
};
struct touchpad_model_spec { struct touchpad_model_spec {
short vendor; short vendor;
@ -64,8 +66,8 @@ static struct touchpad_model_spec touchpad_spec_table[] = {
enum touchpad_state { enum touchpad_state {
TOUCHPAD_STATE_NONE = 0, TOUCHPAD_STATE_NONE = 0,
TOUCHPAD_STATE_TOUCH, TOUCHPAD_STATE_TOUCH = (1 << 0),
TOUCHPAD_STATE_PRESS TOUCHPAD_STATE_MOVE = (1 << 1)
}; };
#define TOUCHPAD_HISTORY_LENGTH 4 #define TOUCHPAD_HISTORY_LENGTH 4
@ -86,7 +88,7 @@ struct touchpad_dispatch {
struct evdev_device *device; struct evdev_device *device;
enum touchpad_model model; enum touchpad_model model;
enum touchpad_state state; unsigned int state;
int finger_state; int finger_state;
int last_finger_state; int last_finger_state;
@ -108,7 +110,6 @@ struct touchpad_dispatch {
struct { struct {
int32_t touch_low; int32_t touch_low;
int32_t touch_high; int32_t touch_high;
int32_t press;
} pressure; } pressure;
struct { struct {
@ -122,7 +123,7 @@ struct touchpad_dispatch {
int motion_index; int motion_index;
unsigned int motion_count; unsigned int motion_count;
struct wl_list motion_filters; struct weston_motion_filter *filter;
}; };
static enum touchpad_model static enum touchpad_model
@ -163,8 +164,6 @@ configure_touchpad_pressure(struct touchpad_dispatch *touchpad,
touchpad->pressure.touch_high = touchpad->pressure.touch_high =
pressure_min + range * (30.0/256.0); pressure_min + range * (30.0/256.0);
} }
touchpad->pressure.press = pressure_min + range;
} }
static double static double
@ -188,65 +187,6 @@ touchpad_profile(struct weston_motion_filter *filter,
return accel_factor; return accel_factor;
} }
static void
configure_touchpad(struct touchpad_dispatch *touchpad,
struct evdev_device *device)
{
struct weston_motion_filter *accel;
struct input_absinfo absinfo;
unsigned long abs_bits[NBITS(ABS_MAX)];
double width;
double height;
double diagonal;
/* Detect model */
touchpad->model = get_touchpad_model(device);
/* Configure pressure */
ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
if (TEST_BIT(abs_bits, ABS_PRESSURE)) {
ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo);
configure_touchpad_pressure(touchpad,
absinfo.minimum,
absinfo.maximum);
}
/* Configure acceleration factor */
width = abs(device->abs.max_x - device->abs.min_x);
height = abs(device->abs.max_y - device->abs.min_y);
diagonal = sqrt(width*width + height*height);
touchpad->constant_accel_factor =
DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR;
touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR;
touchpad->hysteresis.margin_x =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
touchpad->hysteresis.margin_y =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
touchpad->hysteresis.center_x = 0;
touchpad->hysteresis.center_y = 0;
/* Configure acceleration profile */
accel = create_pointer_accelator_filter(touchpad_profile);
wl_list_insert(&touchpad->motion_filters, &accel->link);
/* Setup initial state */
touchpad->reset = 1;
memset(touchpad->motion_history, 0, sizeof touchpad->motion_history);
touchpad->motion_index = 0;
touchpad->motion_count = 0;
touchpad->state = TOUCHPAD_STATE_NONE;
touchpad->last_finger_state = 0;
touchpad->finger_state = 0;
}
static inline struct touchpad_motion * static inline struct touchpad_motion *
motion_history_offset(struct touchpad_dispatch *touchpad, int offset) motion_history_offset(struct touchpad_dispatch *touchpad, int offset)
{ {
@ -294,14 +234,12 @@ static void
filter_motion(struct touchpad_dispatch *touchpad, filter_motion(struct touchpad_dispatch *touchpad,
double *dx, double *dy, uint32_t time) double *dx, double *dy, uint32_t time)
{ {
struct weston_motion_filter *filter;
struct weston_motion_params motion; struct weston_motion_params motion;
motion.dx = *dx; motion.dx = *dx;
motion.dy = *dy; motion.dy = *dy;
wl_list_for_each(filter, &touchpad->motion_filters, link) weston_filter_dispatch(touchpad->filter, &motion, touchpad, time);
weston_filter_dispatch(filter, &motion, touchpad, time);
*dx = motion.dx; *dx = motion.dx;
*dy = motion.dy; *dy = motion.dy;
@ -312,7 +250,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
{ {
int motion_index; int motion_index;
int center_x, center_y; int center_x, center_y;
double dx, dy; double dx = 0.0, dy = 0.0;
if (touchpad->reset || if (touchpad->reset ||
touchpad->last_finger_state != touchpad->finger_state) { touchpad->last_finger_state != touchpad->finger_state) {
@ -349,8 +287,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
center_y = hysteresis(touchpad->hw_abs.y, center_y = hysteresis(touchpad->hw_abs.y,
touchpad->hysteresis.center_y, touchpad->hysteresis.center_y,
touchpad->hysteresis.margin_y); touchpad->hysteresis.margin_y);
} } else {
else {
center_x = touchpad->hw_abs.x; center_x = touchpad->hw_abs.x;
center_y = touchpad->hw_abs.y; center_y = touchpad->hw_abs.y;
} }
@ -376,6 +313,25 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
touchpad->device->rel.dy = wl_fixed_from_double(dy); touchpad->device->rel.dy = wl_fixed_from_double(dy);
touchpad->device->pending_events |= EVDEV_RELATIVE_MOTION; touchpad->device->pending_events |= EVDEV_RELATIVE_MOTION;
} }
if (!(touchpad->state & TOUCHPAD_STATE_MOVE) &&
((int)dx || (int)dy)) {
touchpad->state |= TOUCHPAD_STATE_MOVE;
}
}
static void
on_touch(struct touchpad_dispatch *touchpad)
{
touchpad->state |= TOUCHPAD_STATE_TOUCH;
}
static void
on_release(struct touchpad_dispatch *touchpad)
{
touchpad->reset = 1;
touchpad->state &= ~(TOUCHPAD_STATE_MOVE | TOUCHPAD_STATE_TOUCH);
} }
static inline void static inline void
@ -385,27 +341,23 @@ process_absolute(struct touchpad_dispatch *touchpad,
{ {
switch (e->code) { switch (e->code) {
case ABS_PRESSURE: case ABS_PRESSURE:
if (e->value > touchpad->pressure.press) if (e->value > touchpad->pressure.touch_high &&
touchpad->state = TOUCHPAD_STATE_PRESS; !(touchpad->state & TOUCHPAD_STATE_TOUCH))
else if (e->value > touchpad->pressure.touch_high) on_touch(touchpad);
touchpad->state = TOUCHPAD_STATE_TOUCH; else if (e->value < touchpad->pressure.touch_low &&
else if (e->value < touchpad->pressure.touch_low) { touchpad->state & TOUCHPAD_STATE_TOUCH)
if (touchpad->state > TOUCHPAD_STATE_NONE) on_release(touchpad);
touchpad->reset = 1;
touchpad->state = TOUCHPAD_STATE_NONE;
}
break; break;
case ABS_X: case ABS_X:
if (touchpad->state >= TOUCHPAD_STATE_TOUCH) { if (touchpad->state & TOUCHPAD_STATE_TOUCH) {
touchpad->hw_abs.x = e->value; touchpad->hw_abs.x = e->value;
touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY; touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_X; touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_X;
} }
break; break;
case ABS_Y: case ABS_Y:
if (touchpad->state >= TOUCHPAD_STATE_TOUCH) { if (touchpad->state & TOUCHPAD_STATE_TOUCH) {
touchpad->hw_abs.y = e->value; touchpad->hw_abs.y = e->value;
touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY; touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_Y; touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_Y;
@ -423,15 +375,10 @@ process_key(struct touchpad_dispatch *touchpad,
switch (e->code) { switch (e->code) {
case BTN_TOUCH: case BTN_TOUCH:
if (!touchpad->has_pressure) { if (!touchpad->has_pressure) {
if (!e->value) { if (e->value && !(touchpad->state & TOUCHPAD_STATE_TOUCH))
touchpad->state = TOUCHPAD_STATE_NONE; on_touch(touchpad);
touchpad->reset = 1; else if (!e->value)
} else { on_release(touchpad);
touchpad->state =
e->value ?
TOUCHPAD_STATE_TOUCH :
TOUCHPAD_STATE_NONE;
}
} }
break; break;
case BTN_LEFT: case BTN_LEFT:
@ -504,12 +451,8 @@ touchpad_destroy(struct evdev_dispatch *dispatch)
{ {
struct touchpad_dispatch *touchpad = struct touchpad_dispatch *touchpad =
(struct touchpad_dispatch *) dispatch; (struct touchpad_dispatch *) dispatch;
struct weston_motion_filter *filter;
struct weston_motion_filter *next;
wl_list_for_each_safe(filter, next, &touchpad->motion_filters, link)
filter->interface->destroy(filter);
touchpad->filter->interface->destroy(touchpad->filter);
free(dispatch); free(dispatch);
} }
@ -518,6 +461,72 @@ struct evdev_dispatch_interface touchpad_interface = {
touchpad_destroy touchpad_destroy
}; };
static int
touchpad_init(struct touchpad_dispatch *touchpad,
struct evdev_device *device)
{
struct weston_motion_filter *accel;
struct input_absinfo absinfo;
unsigned long abs_bits[NBITS(ABS_MAX)];
double width;
double height;
double diagonal;
touchpad->base.interface = &touchpad_interface;
touchpad->device = device;
/* Detect model */
touchpad->model = get_touchpad_model(device);
/* Configure pressure */
ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
if (TEST_BIT(abs_bits, ABS_PRESSURE)) {
ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo);
configure_touchpad_pressure(touchpad,
absinfo.minimum,
absinfo.maximum);
}
/* Configure acceleration factor */
width = abs(device->abs.max_x - device->abs.min_x);
height = abs(device->abs.max_y - device->abs.min_y);
diagonal = sqrt(width*width + height*height);
touchpad->constant_accel_factor =
DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR;
touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR;
touchpad->hysteresis.margin_x =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
touchpad->hysteresis.margin_y =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
touchpad->hysteresis.center_x = 0;
touchpad->hysteresis.center_y = 0;
/* Configure acceleration profile */
accel = create_pointer_accelator_filter(touchpad_profile);
if (accel == NULL)
return -1;
touchpad->filter = accel;
/* Setup initial state */
touchpad->reset = 1;
memset(touchpad->motion_history, 0, sizeof touchpad->motion_history);
touchpad->motion_index = 0;
touchpad->motion_count = 0;
touchpad->state = TOUCHPAD_STATE_NONE;
touchpad->last_finger_state = 0;
touchpad->finger_state = 0;
return 0;
}
struct evdev_dispatch * struct evdev_dispatch *
evdev_touchpad_create(struct evdev_device *device) evdev_touchpad_create(struct evdev_device *device)
{ {
@ -527,12 +536,10 @@ evdev_touchpad_create(struct evdev_device *device)
if (touchpad == NULL) if (touchpad == NULL)
return NULL; return NULL;
touchpad->base.interface = &touchpad_interface; if (touchpad_init(touchpad, device) != 0) {
free(touchpad);
touchpad->device = device; return NULL;
wl_list_init(&touchpad->motion_filters); }
configure_touchpad(touchpad, device);
return &touchpad->base; return &touchpad->base;
} }

Loading…
Cancel
Save