X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fevdev.c;h=63eaa4dfaa32a0500af21a7815b5b31f009bec43;hb=967911791f9988be63b8a2c1ffb608eb2871889b;hp=34c6798f3e06ee9c1f57d4ffd4a8196e1b6f9ec5;hpb=6ef6968631939bdeca359a3354164907fd1a09e0;p=platform%2Fupstream%2Flibinput.git diff --git a/src/evdev.c b/src/evdev.c index 34c6798..63eaa4d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -26,18 +26,20 @@ #include #include #include -#include +#include "linux/input.h" #include #include #include #include #include +#include #include "libinput.h" #include "evdev.h" +#include "filter.h" #include "libinput-private.h" -#define DEFAULT_AXIS_STEP_DISTANCE li_fixed_from_int(10) +#define DEFAULT_AXIS_STEP_DISTANCE 10 void evdev_device_led_update(struct evdev_device *device, enum libinput_led leds) @@ -87,29 +89,35 @@ transform_absolute(struct evdev_device *device, int32_t *x, int32_t *y) } } -li_fixed_t +static inline double +scale_axis(const struct input_absinfo *absinfo, double val, double to_range) +{ + return (val - absinfo->minimum) * to_range / + (absinfo->maximum - absinfo->minimum + 1); +} + +double evdev_device_transform_x(struct evdev_device *device, - li_fixed_t x, + double x, uint32_t width) { - return ((uint64_t)x - li_fixed_from_int(device->abs.min_x)) * width / - (device->abs.max_x - device->abs.min_x + 1); + return scale_axis(device->abs.absinfo_x, x, width); } -li_fixed_t +double evdev_device_transform_y(struct evdev_device *device, - li_fixed_t y, + double y, uint32_t height) { - return ((uint64_t)y - li_fixed_from_int(device->abs.min_y)) * height / - (device->abs.max_y - device->abs.min_y + 1); + return scale_axis(device->abs.absinfo_y, y, height); } static void -evdev_flush_pending_event(struct evdev_device *device, uint32_t time) +evdev_flush_pending_event(struct evdev_device *device, uint64_t time) { + struct motion_params motion; int32_t cx, cy; - li_fixed_t x, y; + double x, y; int slot; int seat_slot; struct libinput_device *base = &device->base; @@ -121,17 +129,29 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) case EVDEV_NONE: return; case EVDEV_RELATIVE_MOTION: - pointer_notify_motion(base, - time, - device->rel.dx, - device->rel.dy); + motion.dx = device->rel.dx; + motion.dy = device->rel.dy; device->rel.dx = 0; device->rel.dy = 0; + + /* Apply pointer acceleration. */ + filter_dispatch(device->pointer.filter, &motion, device, time); + + if (motion.dx == 0.0 && motion.dy == 0.0) + break; + + pointer_notify_motion(base, time, motion.dx, motion.dy); break; case EVDEV_ABSOLUTE_MT_DOWN: if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) break; + if (device->mt.slots[slot].seat_slot != -1) { + log_bug_kernel("%s: Driver sent multiple touch down for the " + "same slot", device->devnode); + break; + } + seat_slot = ffs(~seat->slot_map) - 1; device->mt.slots[slot].seat_slot = seat_slot; @@ -139,8 +159,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) break; seat->slot_map |= 1 << seat_slot; - x = li_fixed_from_int(device->mt.slots[slot].x); - y = li_fixed_from_int(device->mt.slots[slot].y); + x = device->mt.slots[slot].x; + y = device->mt.slots[slot].y; touch_notify_touch_down(base, time, slot, seat_slot, x, y); break; @@ -149,8 +169,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) break; seat_slot = device->mt.slots[slot].seat_slot; - x = li_fixed_from_int(device->mt.slots[slot].x); - y = li_fixed_from_int(device->mt.slots[slot].y); + x = device->mt.slots[slot].x; + y = device->mt.slots[slot].y; if (seat_slot == -1) break; @@ -162,6 +182,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) break; seat_slot = device->mt.slots[slot].seat_slot; + device->mt.slots[slot].seat_slot = -1; if (seat_slot == -1) break; @@ -174,6 +195,12 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) if (!(device->seat_caps & EVDEV_DEVICE_TOUCH)) break; + if (device->abs.seat_slot != -1) { + log_bug_kernel("%s: Driver sent multiple touch down for the " + "same slot", device->devnode); + break; + } + seat_slot = ffs(~seat->slot_map) - 1; device->abs.seat_slot = seat_slot; @@ -183,15 +210,13 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) seat->slot_map |= 1 << seat_slot; transform_absolute(device, &cx, &cy); - x = li_fixed_from_int(cx); - y = li_fixed_from_int(cy); - touch_notify_touch_down(base, time, -1, seat_slot, x, y); + touch_notify_touch_down(base, time, -1, seat_slot, cx, cy); break; case EVDEV_ABSOLUTE_MOTION: transform_absolute(device, &cx, &cy); - x = li_fixed_from_int(cx); - y = li_fixed_from_int(cy); + x = cx; + y = cy; if (device->seat_caps & EVDEV_DEVICE_TOUCH) { seat_slot = device->abs.seat_slot; @@ -209,6 +234,7 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) break; seat_slot = device->abs.seat_slot; + device->abs.seat_slot = -1; if (seat_slot == -1) break; @@ -226,7 +252,8 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) } static void -evdev_process_touch_button(struct evdev_device *device, int time, int value) +evdev_process_touch_button(struct evdev_device *device, + uint64_t time, int value) { if (device->pending_event != EVDEV_NONE && device->pending_event != EVDEV_ABSOLUTE_MOTION) @@ -238,12 +265,16 @@ evdev_process_touch_button(struct evdev_device *device, int time, int value) } static inline void -evdev_process_key(struct evdev_device *device, struct input_event *e, int time) +evdev_process_key(struct evdev_device *device, + struct input_event *e, uint64_t time) { /* ignore kernel key repeat */ if (e->value == 2) return; + if (e->code > KEY_MAX) + return; + if (e->code == BTN_TOUCH) { if (!device->is_mt) evdev_process_touch_button(device, time, e->value); @@ -265,17 +296,22 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) &device->base, time, e->code, - e->value ? LIBINPUT_POINTER_BUTTON_STATE_PRESSED : - LIBINPUT_POINTER_BUTTON_STATE_RELEASED); + e->value ? LIBINPUT_BUTTON_STATE_PRESSED : + LIBINPUT_BUTTON_STATE_RELEASED); break; default: + /* Only let KEY_* codes pass through. */ + if (!(e->code <= KEY_MICMUTE || + (e->code >= KEY_OK && e->code <= KEY_LIGHTS_TOGGLE))) + break; + keyboard_notify_key( &device->base, time, e->code, - e->value ? LIBINPUT_KEYBOARD_KEY_STATE_PRESSED : - LIBINPUT_KEYBOARD_KEY_STATE_RELEASED); + e->value ? LIBINPUT_KEY_STATE_PRESSED : + LIBINPUT_KEY_STATE_RELEASED); break; } } @@ -283,7 +319,7 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) static void evdev_process_touch(struct evdev_device *device, struct input_event *e, - uint32_t time) + uint64_t time) { switch (e->code) { case ABS_MT_SLOT: @@ -332,7 +368,7 @@ evdev_process_absolute_motion(struct evdev_device *device, static inline void evdev_process_relative(struct evdev_device *device, - struct input_event *e, uint32_t time) + struct input_event *e, uint64_t time) { struct libinput_device *base = &device->base; @@ -340,13 +376,13 @@ evdev_process_relative(struct evdev_device *device, case REL_X: if (device->pending_event != EVDEV_RELATIVE_MOTION) evdev_flush_pending_event(device, time); - device->rel.dx += li_fixed_from_int(e->value); + device->rel.dx += e->value; device->pending_event = EVDEV_RELATIVE_MOTION; break; case REL_Y: if (device->pending_event != EVDEV_RELATIVE_MOTION) evdev_flush_pending_event(device, time); - device->rel.dy += li_fixed_from_int(e->value); + device->rel.dy += e->value; device->pending_event = EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: @@ -354,7 +390,7 @@ evdev_process_relative(struct evdev_device *device, pointer_notify_axis( base, time, - LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL, + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE); break; case REL_HWHEEL: @@ -367,7 +403,7 @@ evdev_process_relative(struct evdev_device *device, pointer_notify_axis( base, time, - LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL, + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, e->value * DEFAULT_AXIS_STEP_DISTANCE); break; default: @@ -380,7 +416,7 @@ evdev_process_relative(struct evdev_device *device, static inline void evdev_process_absolute(struct evdev_device *device, struct input_event *e, - uint32_t time) + uint64_t time) { if (device->is_mt) { evdev_process_touch(device, e, time); @@ -415,7 +451,7 @@ static void fallback_process(struct evdev_dispatch *dispatch, struct evdev_device *device, struct input_event *event, - uint32_t time) + uint64_t time) { int need_frame = 0; @@ -465,7 +501,7 @@ static inline void evdev_process_event(struct evdev_device *device, struct input_event *e) { struct evdev_dispatch *dispatch = device->dispatch; - uint32_t time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; + uint64_t time = e->time.tv_sec * 1000ULL + e->time.tv_usec / 1000; dispatch->interface->process(dispatch, device, e, time); } @@ -541,12 +577,29 @@ evdev_device_dispatch(void *data) } static int +configure_pointer_acceleration(struct evdev_device *device) +{ + device->pointer.filter = + create_pointer_accelator_filter( + pointer_accel_profile_smooth_simple); + if (!device->pointer.filter) + return -1; + + return 0; +} + +static int evdev_configure_device(struct evdev_device *device) { struct libevdev *evdev = device->evdev; const struct input_absinfo *absinfo; + struct input_absinfo fixed; int has_abs, has_rel, has_mt; int has_button, has_keyboard, has_touch; + struct mt_slot *slots; + int num_slots; + int active_slot; + int slot; unsigned int i; has_rel = 0; @@ -559,13 +612,21 @@ evdev_configure_device(struct evdev_device *device) if (libevdev_has_event_type(evdev, EV_ABS)) { if ((absinfo = libevdev_get_abs_info(evdev, ABS_X))) { - device->abs.min_x = absinfo->minimum; - device->abs.max_x = absinfo->maximum; + if (absinfo->resolution == 0) { + fixed = *absinfo; + fixed.resolution = 1; + libevdev_set_abs_info(evdev, ABS_X, &fixed); + } + device->abs.absinfo_x = absinfo; has_abs = 1; } if ((absinfo = libevdev_get_abs_info(evdev, ABS_Y))) { - device->abs.min_y = absinfo->minimum; - device->abs.max_y = absinfo->maximum; + if (absinfo->resolution == 0) { + fixed = *absinfo; + fixed.resolution = 1; + libevdev_set_abs_info(evdev, ABS_Y, &fixed); + } + device->abs.absinfo_y = absinfo; has_abs = 1; } /* We only handle the slotted Protocol B in weston. @@ -574,11 +635,23 @@ evdev_configure_device(struct evdev_device *device) if (libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_X) && libevdev_has_event_code(evdev, EV_ABS, ABS_MT_POSITION_Y)) { absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_X); - device->abs.min_x = absinfo->minimum; - device->abs.max_x = absinfo->maximum; + if (absinfo->resolution == 0) { + fixed = *absinfo; + fixed.resolution = 1; + libevdev_set_abs_info(evdev, + ABS_MT_POSITION_X, + &fixed); + } + device->abs.absinfo_x = absinfo; absinfo = libevdev_get_abs_info(evdev, ABS_MT_POSITION_Y); - device->abs.min_y = absinfo->minimum; - device->abs.max_y = absinfo->maximum; + if (absinfo->resolution == 0) { + fixed = *absinfo; + fixed.resolution = 1; + libevdev_set_abs_info(evdev, + ABS_MT_POSITION_Y, + &fixed); + } + device->abs.absinfo_y = absinfo; device->is_mt = 1; has_touch = 1; has_mt = 1; @@ -588,18 +661,38 @@ evdev_configure_device(struct evdev_device *device) device->mtdev = mtdev_new_open(device->fd); if (!device->mtdev) return -1; - device->mt.slot = device->mtdev->caps.slot.value; + + num_slots = device->mtdev->caps.slot.maximum; + if (device->mtdev->caps.slot.minimum < 0 || + num_slots <= 0) + return -1; + active_slot = device->mtdev->caps.slot.value; } else { - device->mt.slot = libevdev_get_current_slot(device->evdev); + num_slots = libevdev_get_num_slots(device->evdev); + active_slot = libevdev_get_current_slot(evdev); + } + + slots = calloc(num_slots, sizeof(struct mt_slot)); + if (!slots) + return -1; + + for (slot = 0; slot < num_slots; ++slot) { + slots[slot].seat_slot = -1; + slots[slot].x = 0; + slots[slot].y = 0; } + device->mt.slots = slots; + device->mt.slots_len = num_slots; + device->mt.slot = active_slot; } } if (libevdev_has_event_code(evdev, EV_REL, REL_X) || libevdev_has_event_code(evdev, EV_REL, REL_Y)) - has_rel = 1; + has_rel = 1; if (libevdev_has_event_type(evdev, EV_KEY)) { - if (libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_FINGER) && + if (!libevdev_has_property(evdev, INPUT_PROP_DIRECT) && + libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_FINGER) && !libevdev_has_event_code(evdev, EV_KEY, BTN_TOOL_PEN) && (has_abs || has_mt)) { device->dispatch = evdev_mt_touchpad_create(device); @@ -627,7 +720,11 @@ evdev_configure_device(struct evdev_device *device) has_keyboard = 1; if ((has_abs || has_rel) && has_button) { + if (configure_pointer_acceleration(device) == -1) + return -1; + device->seat_caps |= EVDEV_DEVICE_POINTER; + log_info("input device '%s', %s is a pointer caps =%s%s%s\n", device->devname, device->devnode, has_abs ? " absolute-motion" : "", @@ -686,9 +783,9 @@ evdev_device_create(struct libinput_seat *seat, device->mtdev = NULL; device->devnode = strdup(devnode); device->sysname = strdup(sysname); - device->mt.slot = -1; device->rel.dx = 0; device->rel.dy = 0; + device->abs.seat_slot = -1; device->dispatch = NULL; device->fd = fd; device->pending_event = EVDEV_NONE; @@ -774,6 +871,25 @@ evdev_device_has_capability(struct evdev_device *device, } } +int +evdev_device_get_size(struct evdev_device *device, + double *width, + double *height) +{ + const struct input_absinfo *x, *y; + + x = libevdev_get_abs_info(device->evdev, ABS_X); + y = libevdev_get_abs_info(device->evdev, ABS_Y); + + if (!x || !y || !x->resolution || !y->resolution) + return -1; + + *width = evdev_convert_to_mm(x, x->maximum); + *height = evdev_convert_to_mm(y, y->maximum); + + return 0; +} + void evdev_device_remove(struct evdev_device *device) { @@ -800,8 +916,10 @@ evdev_device_destroy(struct evdev_device *device) if (dispatch) dispatch->interface->destroy(dispatch); + motion_filter_destroy(device->pointer.filter); libinput_seat_unref(device->base.seat); libevdev_free(device->evdev); + free(device->mt.slots); free(device->devnode); free(device->sysname); free(device);