diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c index ce48ed0b..45d5d703 100644 --- a/src/evdev-mt-touchpad-buttons.c +++ b/src/evdev-mt-touchpad-buttons.c @@ -565,6 +565,7 @@ tp_init_buttons(struct tp_dispatch *tp, struct tp_touch *t; int width, height; double diagonal; + const struct input_absinfo *absinfo_x, *absinfo_y; tp->buttons.is_clickpad = libevdev_has_property(device->evdev, INPUT_PROP_BUTTONPAD); @@ -580,8 +581,11 @@ tp_init_buttons(struct tp_dispatch *tp, log_bug_kernel("non clickpad without right button?\n"); } - width = abs(device->abs.max_x - device->abs.min_x); - height = abs(device->abs.max_y - device->abs.min_y); + absinfo_x = device->abs.absinfo_x; + absinfo_y = device->abs.absinfo_y; + + width = abs(absinfo_x->maximum - absinfo_x->minimum); + height = abs(absinfo_y->maximum - absinfo_y->minimum); diagonal = sqrt(width*width + height*height); tp->buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD; @@ -590,13 +594,15 @@ tp_init_buttons(struct tp_dispatch *tp, tp->buttons.use_clickfinger = true; if (tp->buttons.is_clickpad && !tp->buttons.use_clickfinger) { - tp->buttons.bottom_area.top_edge = height * .8 + device->abs.min_y; - tp->buttons.bottom_area.rightbutton_left_edge = width/2 + device->abs.min_x; + int xoffset = absinfo_x->minimum, + yoffset = absinfo_y->minimum; + tp->buttons.bottom_area.top_edge = height * .8 + yoffset; + tp->buttons.bottom_area.rightbutton_left_edge = width/2 + xoffset; if (tp->buttons.has_topbuttons) { - tp->buttons.top_area.bottom_edge = height * .08 + device->abs.min_y; - tp->buttons.top_area.rightbutton_left_edge = width * .58 + device->abs.min_x; - tp->buttons.top_area.leftbutton_right_edge = width * .42 + device->abs.min_x; + tp->buttons.top_area.bottom_edge = height * .08 + yoffset; + tp->buttons.top_area.rightbutton_left_edge = width * .58 + xoffset; + tp->buttons.top_area.leftbutton_right_edge = width * .42 + xoffset; } else { tp->buttons.top_area.bottom_edge = INT_MIN; } diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 0294eb2b..787afa4c 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -139,7 +139,7 @@ tp_motion_history_reset(struct tp_touch *t) static inline struct tp_touch * tp_current_touch(struct tp_dispatch *tp) { - return &tp->touches[min(tp->slot, tp->ntouches)]; + return &tp->touches[min(tp->slot, tp->ntouches - 1)]; } static inline struct tp_touch * @@ -750,8 +750,10 @@ tp_init(struct tp_dispatch *tp, if (tp_init_slots(tp, device) != 0) return -1; - width = abs(device->abs.max_x - device->abs.min_x); - height = abs(device->abs.max_y - device->abs.min_y); + width = abs(device->abs.absinfo_x->maximum - + device->abs.absinfo_x->minimum); + height = abs(device->abs.absinfo_y->maximum - + device->abs.absinfo_y->minimum); diagonal = sqrt(width*width + height*height); tp->hysteresis.margin_x = diff --git a/src/evdev.c b/src/evdev.c index 597977c4..42fe2de1 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -89,13 +89,19 @@ transform_absolute(struct evdev_device *device, int32_t *x, int32_t *y) } } +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, double x, uint32_t width) { - return (x - device->abs.min_x) * width / - (device->abs.max_x - device->abs.min_x + 1); + return scale_axis(device->abs.absinfo_x, x, width); } double @@ -103,8 +109,7 @@ evdev_device_transform_y(struct evdev_device *device, double y, uint32_t height) { - return (y - 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 @@ -588,6 +593,7 @@ 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; @@ -606,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. @@ -621,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; @@ -855,6 +881,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) { diff --git a/src/evdev.h b/src/evdev.h index 1164b7c0..63624dd8 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -67,7 +67,7 @@ struct evdev_device { const char *devname; int fd; struct { - int min_x, max_x, min_y, max_y; + const struct input_absinfo *absinfo_x, *absinfo_y; int32_t x, y; int32_t seat_slot; @@ -152,6 +152,11 @@ int evdev_device_has_capability(struct evdev_device *device, enum libinput_device_capability capability); +int +evdev_device_get_size(struct evdev_device *device, + double *w, + double *h); + double evdev_device_transform_x(struct evdev_device *device, double x, @@ -168,4 +173,11 @@ evdev_device_remove(struct evdev_device *device); void evdev_device_destroy(struct evdev_device *device); +static inline double +evdev_convert_to_mm(const struct input_absinfo *absinfo, double v) +{ + double value = v - absinfo->minimum; + return value/absinfo->resolution; +} + #endif /* EVDEV_H */ diff --git a/src/libinput.c b/src/libinput.c index 1ac62a87..054d4fae 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -376,13 +376,19 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event) LIBINPUT_EXPORT double libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event) { - return event->x; + struct evdev_device *device = + (struct evdev_device *) event->base.device; + + return evdev_convert_to_mm(device->abs.absinfo_x, event->x); } LIBINPUT_EXPORT double libinput_event_pointer_get_absolute_y(struct libinput_event_pointer *event) { - return event->y; + struct evdev_device *device = + (struct evdev_device *) event->base.device; + + return evdev_convert_to_mm(device->abs.absinfo_y, event->y); } LIBINPUT_EXPORT double @@ -459,7 +465,10 @@ libinput_event_touch_get_seat_slot(struct libinput_event_touch *event) LIBINPUT_EXPORT double libinput_event_touch_get_x(struct libinput_event_touch *event) { - return event->x; + struct evdev_device *device = + (struct evdev_device *) event->base.device; + + return evdev_convert_to_mm(device->abs.absinfo_x, event->x); } LIBINPUT_EXPORT double @@ -485,7 +494,10 @@ libinput_event_touch_get_y_transformed(struct libinput_event_touch *event, LIBINPUT_EXPORT double libinput_event_touch_get_y(struct libinput_event_touch *event) { - return event->y; + struct evdev_device *device = + (struct evdev_device *) event->base.device; + + return evdev_convert_to_mm(device->abs.absinfo_y, event->y); } LIBINPUT_EXPORT int @@ -1429,6 +1441,16 @@ libinput_device_has_capability(struct libinput_device *device, capability); } +LIBINPUT_EXPORT int +libinput_device_get_size(struct libinput_device *device, + double *width, + double *height) +{ + return evdev_device_get_size((struct evdev_device *)device, + width, + height); +} + LIBINPUT_EXPORT struct libinput_event * libinput_event_device_notify_get_base_event(struct libinput_event_device_notify *event) { diff --git a/src/libinput.h b/src/libinput.h index ca00bdcd..04f40fa8 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -538,11 +538,9 @@ libinput_event_pointer_get_dy(struct libinput_event_pointer *event); /** * @ingroup event_pointer * - * Return the current absolute x coordinate of the pointer event. - * - * The coordinate is in a device specific coordinate space; to get the - * corresponding output screen coordinate, use - * libinput_event_pointer_get_x_transformed(). + * Return the current absolute x coordinate of the pointer event, in mm from + * the top left corner of the device. To get the corresponding output screen + * coordinate, use libinput_event_pointer_get_x_transformed(). * * For pointer events that are not of type * LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, this function returns 0. @@ -558,11 +556,9 @@ libinput_event_pointer_get_absolute_x(struct libinput_event_pointer *event); /** * @ingroup event_pointer * - * Return the current absolute y coordinate of the pointer event. - * - * The coordinate is in a device specific coordinate space; to get the - * corresponding output screen coordinate, use - * libinput_event_pointer_get_y_transformed(). + * Return the current absolute y coordinate of the pointer event, in mm from + * the top left corner of the device. To get the corresponding output screen + * coordinate, use libinput_event_pointer_get_x_transformed(). * * For pointer events that are not of type * LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, this function returns 0. @@ -763,11 +759,9 @@ libinput_event_touch_get_seat_slot(struct libinput_event_touch *event); /** * @ingroup event_touch * - * Return the current absolute x coordinate of the touch event. - * - * The coordinate is in a device specific coordinate space; to get the - * corresponding output screen coordinate, use - * libinput_event_touch_get_x_transformed(). + * Return the current absolute x coordinate of the touch event, in mm from + * the top left corner of the device. To get the corresponding output screen + * coordinate, use libinput_event_touch_get_x_transformed(). * * @note this function should only be called for LIBINPUT_EVENT_TOUCH_DOWN and * LIBINPUT_EVENT_TOUCH_MOTION. @@ -781,11 +775,9 @@ libinput_event_touch_get_x(struct libinput_event_touch *event); /** * @ingroup event_touch * - * Return the current absolute y coordinate of the touch event. - * - * The coordinate is in a device specific coordinate space; to get the - * corresponding output screen coordinate, use - * libinput_event_touch_get_y_transformed(). + * Return the current absolute y coordinate of the touch event, in mm from + * the top left corner of the device. To get the corresponding output screen + * coordinate, use libinput_event_touch_get_y_transformed(). * * For LIBINPUT_EVENT_TOUCH_UP 0 is returned. * @@ -1604,6 +1596,25 @@ int libinput_device_has_capability(struct libinput_device *device, enum libinput_device_capability capability); +/** + * @ingroup device + * + * Get the physical size of a device in mm, where meaningful. This function + * only succeeds on devices with the required data, i.e. tablets, touchpads + * and touchscreens. + * + * If this function returns nonzero, width and height are unmodified. + * + * @param device The device + * @param width Set to the width of the device + * @param height Set to the height of the device + * @return 0 on success, or nonzero otherwise + */ +int +libinput_device_get_size(struct libinput_device *device, + double *width, + double *height); + #ifdef __cplusplus } #endif diff --git a/tools/event-debug.c b/tools/event-debug.c index b8cbd292..a26500e4 100644 --- a/tools/event-debug.c +++ b/tools/event-debug.c @@ -243,10 +243,16 @@ print_device_notify(struct libinput_event *ev) { struct libinput_device *dev = libinput_event_get_device(ev); struct libinput_seat *seat = libinput_device_get_seat(dev); + double w, h; - printf("%s %s\n", + printf("%s %s", libinput_seat_get_physical_name(seat), libinput_seat_get_logical_name(seat)); + + if (libinput_device_get_size(dev, &w, &h) == 0) + printf("\tsize %.2f/%.2fmm", w, h); + + printf("\n"); } static void @@ -450,13 +456,16 @@ print_touch_event_with_coords(struct libinput_event *ev) struct libinput_event_touch *t = libinput_event_get_touch_event(ev); double x = libinput_event_touch_get_x_transformed(t, screen_width); double y = libinput_event_touch_get_y_transformed(t, screen_height); + double xmm = libinput_event_touch_get_x(t); + double ymm = libinput_event_touch_get_y(t); print_event_time(libinput_event_touch_get_time(t)); - printf("%d (%d) %5.2f/%5.2f\n", + printf("%d (%d) %5.2f/%5.2f (%5.2f/%5.2fmm)\n", libinput_event_touch_get_slot(t), libinput_event_touch_get_seat_slot(t), - x, y); + x, y, + xmm, ymm); } static int