From c8fde99ad9e8ec8f1f904a14c5612d926d71ee94 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 1 Mar 2017 15:42:10 +1000 Subject: tablet: drop unnecessary call to reset the changed axes The only code path that leads here would see the changed_axes array zeroed out in tablet_send_axis_proximity_tip_down_events(), zeroing again is unlikely to make it more zero. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index bde6f60..eb56322 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -1421,7 +1421,6 @@ tablet_flush(struct tablet_dispatch *tablet, } if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { - memset(tablet->changed_axes, 0, sizeof(tablet->changed_axes)); tablet_notify_proximity(&device->base, time, tool, -- cgit v1.2.3 From c39a84da9eacf7c57ef3158d6bc105f6beaeb380 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 2 Mar 2017 13:17:56 +1000 Subject: tablet: remove unnecessary out-of-proximity check This cannot trigger because we'd never get here if out-of-proximity is set, tablet_flush() will return early. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index eb56322..51f11dc 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -1278,14 +1278,7 @@ tablet_send_axis_proximity_tip_down_events(struct tablet_dispatch *tablet, { struct tablet_axes axes = {0}; - /* We need to make sure that we check that the tool is not out of - * proximity before we send any axis updates. This is because many - * tablets will send axis events with incorrect values if the tablet - * tool is close enough so that the tablet can partially detect that - * it's there, but can't properly receive any data from the tool. */ - if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) - goto out; - else if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { + if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { /* Tool is leaving proximity, we can't rely on the last axis * information (it'll be mostly 0), so we just get the * current state and skip over updating the axes. -- cgit v1.2.3 From cadefc12659ada0120a497c244c70993f8d5779a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 1 Mar 2017 15:22:49 +1000 Subject: tablet: reshuffle the event sending code The current code modifies a bit of state inside the proximity_tip_down function which makes for confusing reading. Clean this up by having a bunch of helper functions for the various events. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 229 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 142 insertions(+), 87 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 51f11dc..74b42e8 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -543,8 +543,10 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, const char tmp[sizeof(tablet->changed_axes)] = {0}; struct device_coords delta; - if (memcmp(tmp, tablet->changed_axes, sizeof(tmp)) == 0) + if (memcmp(tmp, tablet->changed_axes, sizeof(tmp)) == 0) { + *axes_out = tablet->axes; return false; + } tablet_handle_xy(tablet, device, &axes.point, &delta); axes.pressure = tablet_handle_pressure(tablet, device, tool); @@ -1270,84 +1272,172 @@ tablet_update_proximity_state(struct tablet_dispatch *tablet, tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); } -static void -tablet_send_axis_proximity_tip_down_events(struct tablet_dispatch *tablet, - struct evdev_device *device, - struct libinput_tablet_tool *tool, - uint64_t time) +static inline bool +tablet_send_proximity_in(struct tablet_dispatch *tablet, + struct libinput_tablet_tool *tool, + struct evdev_device *device, + const struct tablet_axes *axes, + uint64_t time) { - struct tablet_axes axes = {0}; + if (!tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY)) + return false; - if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { - /* Tool is leaving proximity, we can't rely on the last axis - * information (it'll be mostly 0), so we just get the - * current state and skip over updating the axes. - */ - axes = tablet->axes; + tablet_notify_proximity(&device->base, + time, + tool, + LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN, + tablet->changed_axes, + axes); + tablet_unset_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY); + tablet_unset_status(tablet, TABLET_AXES_UPDATED); - /* Dont' send an axis event, but we may have a tip event - * update */ - tablet_unset_status(tablet, TABLET_AXES_UPDATED); - } else if (!tablet_check_notify_axes(tablet, - device, - tool, - &axes, - time)) { - goto out; - } + return true; +} - if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY)) { - tablet_notify_proximity(&device->base, - time, - tool, - LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN, - tablet->changed_axes, - &axes); - tablet_unset_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY); - tablet_unset_status(tablet, TABLET_AXES_UPDATED); - } +static inline bool +tablet_send_proximity_out(struct tablet_dispatch *tablet, + struct libinput_tablet_tool *tool, + struct evdev_device *device, + const struct tablet_axes *axes, + uint64_t time) +{ + if (!tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) + return false; + tablet_notify_proximity(&device->base, + time, + tool, + LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT, + tablet->changed_axes, + axes); + + tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); + tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); + + return true; +} + +static inline bool +tablet_send_tip(struct tablet_dispatch *tablet, + struct libinput_tablet_tool *tool, + struct evdev_device *device, + const struct tablet_axes *axes, + uint64_t time) +{ if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_CONTACT)) { tablet_notify_tip(&device->base, time, tool, LIBINPUT_TABLET_TOOL_TIP_DOWN, tablet->changed_axes, - &tablet->axes); + axes); tablet_unset_status(tablet, TABLET_AXES_UPDATED); tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT); tablet_set_status(tablet, TABLET_TOOL_IN_CONTACT); - } else if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_CONTACT)) { + return true; + } + + if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_CONTACT)) { tablet_notify_tip(&device->base, time, tool, LIBINPUT_TABLET_TOOL_TIP_UP, tablet->changed_axes, - &tablet->axes); + axes); tablet_unset_status(tablet, TABLET_AXES_UPDATED); tablet_unset_status(tablet, TABLET_TOOL_LEAVING_CONTACT); tablet_unset_status(tablet, TABLET_TOOL_IN_CONTACT); - } else if (tablet_has_status(tablet, TABLET_AXES_UPDATED)) { - enum libinput_tablet_tool_tip_state tip_state; + return true; + } - if (tablet_has_status(tablet, - TABLET_TOOL_IN_CONTACT)) - tip_state = LIBINPUT_TABLET_TOOL_TIP_DOWN; - else - tip_state = LIBINPUT_TABLET_TOOL_TIP_UP; - - tablet_notify_axis(&device->base, - time, - tool, - tip_state, - tablet->changed_axes, - &axes); + return false; +} + +static inline void +tablet_send_axes(struct tablet_dispatch *tablet, + struct libinput_tablet_tool *tool, + struct evdev_device *device, + const struct tablet_axes *axes, + uint64_t time) +{ + enum libinput_tablet_tool_tip_state tip_state; + + if (!tablet_has_status(tablet, TABLET_AXES_UPDATED)) + return; + + if (tablet_has_status(tablet, + TABLET_TOOL_IN_CONTACT)) + tip_state = LIBINPUT_TABLET_TOOL_TIP_DOWN; + else + tip_state = LIBINPUT_TABLET_TOOL_TIP_UP; + + tablet_notify_axis(&device->base, + time, + tool, + tip_state, + tablet->changed_axes, + axes); + tablet_unset_status(tablet, TABLET_AXES_UPDATED); +} + +static inline void +tablet_send_buttons(struct tablet_dispatch *tablet, + struct libinput_tablet_tool *tool, + struct evdev_device *device, + uint64_t time) +{ + if (tablet_has_status(tablet, TABLET_BUTTONS_RELEASED)) { + tablet_notify_buttons(tablet, + device, + time, + tool, + LIBINPUT_BUTTON_STATE_RELEASED); + tablet_unset_status(tablet, TABLET_BUTTONS_RELEASED); + } + + if (tablet_has_status(tablet, TABLET_BUTTONS_PRESSED)) { + tablet_notify_buttons(tablet, + device, + time, + tool, + LIBINPUT_BUTTON_STATE_PRESSED); + tablet_unset_status(tablet, TABLET_BUTTONS_PRESSED); + } +} + +static void +tablet_send_events(struct tablet_dispatch *tablet, + struct libinput_tablet_tool *tool, + struct evdev_device *device, + uint64_t time) +{ + struct tablet_axes axes = {0}; + + if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { + /* Tool is leaving proximity, we can't rely on the last axis + * information (it'll be mostly 0), so we just get the + * current state and skip over updating the axes. + */ + axes = tablet->axes; + + /* Dont' send an axis event, but we may have a tip event + * update */ tablet_unset_status(tablet, TABLET_AXES_UPDATED); + } else { + tablet_check_notify_axes(tablet, device, tool, &axes, time); } -out: + tablet_send_proximity_in(tablet, tool, device, &axes, time); + if (!tablet_send_tip(tablet, tool, device, &axes, time)) + tablet_send_axes(tablet, tool, device, &axes, time); + memset(tablet->changed_axes, 0, sizeof(tablet->changed_axes)); tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT); + + tablet_send_buttons(tablet, tool, device, time); + + if (tablet_send_proximity_out(tablet, tool, device, &axes, time)) + tablet_change_to_left_handed(device); } static void @@ -1390,42 +1480,7 @@ tablet_flush(struct tablet_dispatch *tablet, sanitize_tablet_axes(tablet, tool); } - tablet_send_axis_proximity_tip_down_events(tablet, - device, - tool, - time); - - if (tablet_has_status(tablet, TABLET_BUTTONS_RELEASED)) { - tablet_notify_buttons(tablet, - device, - time, - tool, - LIBINPUT_BUTTON_STATE_RELEASED); - tablet_unset_status(tablet, TABLET_BUTTONS_RELEASED); - } - - if (tablet_has_status(tablet, TABLET_BUTTONS_PRESSED)) { - tablet_notify_buttons(tablet, - device, - time, - tool, - LIBINPUT_BUTTON_STATE_PRESSED); - tablet_unset_status(tablet, TABLET_BUTTONS_PRESSED); - } - - if (tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) { - tablet_notify_proximity(&device->base, - time, - tool, - LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT, - tablet->changed_axes, - &tablet->axes); - - tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); - tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); - - tablet_change_to_left_handed(device); - } + tablet_send_events(tablet, tool, device, time); } static inline void -- cgit v1.2.3 From f5d8552cc3b93c890ac97aa454e890c1b1fdaa0a Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 1 Mar 2017 15:59:44 +1000 Subject: tablet: move definition of tablet_axes down Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/libinput-private.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libinput-private.h b/src/libinput-private.h index 205dbf8..a1d5000 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -99,18 +99,6 @@ struct wheel_tilt_flags { bool vertical, horizontal; }; -struct tablet_axes { - struct device_coords point; - struct normalized_coords delta; - double distance; - double pressure; - struct tilt_degrees tilt; - double rotation; - double slider; - double wheel; - int wheel_discrete; -}; - struct libinput_interface_backend { int (*resume)(struct libinput *libinput); void (*suspend)(struct libinput *libinput); @@ -335,6 +323,18 @@ enum libinput_tablet_tool_axis { #define LIBINPUT_TABLET_TOOL_AXIS_MAX LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL +struct tablet_axes { + struct device_coords point; + struct normalized_coords delta; + double distance; + double pressure; + struct tilt_degrees tilt; + double rotation; + double slider; + double wheel; + int wheel_discrete; +}; + struct libinput_tablet_tool { struct list link; uint32_t serial; -- cgit v1.2.3 From 0d757a94f95216123432317a18c5f6707f51ec19 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 13:11:51 +1000 Subject: tablet: add a motion history Stores the processed axes values in a history 4 events deep. Currently unused but will be used to smoothen out axis values to avoid transducer-caused axis wobbles. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++----- src/evdev-tablet.h | 8 +++++++ 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 74b42e8..ec1c822 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -76,6 +76,50 @@ tablet_force_button_presses(struct tablet_dispatch *tablet) } } +static inline size_t +tablet_history_size(const struct tablet_dispatch *tablet) +{ + return ARRAY_LENGTH(tablet->history.samples); +} + +static inline void +tablet_history_reset(struct tablet_dispatch *tablet) +{ + tablet->history.count = 0; +} + +static inline void +tablet_history_push(struct tablet_dispatch *tablet, + const struct tablet_axes *axes) +{ + unsigned int index = (tablet->history.index + 1) % + tablet_history_size(tablet); + + tablet->history.samples[index] = *axes; + tablet->history.index = index; + tablet->history.count = min(tablet->history.count + 1, + tablet_history_size(tablet)); + + if (tablet->history.count < tablet_history_size(tablet)) + tablet_history_push(tablet, axes); +} + +/** + * Return a previous axis state, where index of 0 means "most recent", 1 is + * "one before most recent", etc. + */ +static inline const struct tablet_axes* +tablet_history_get(const struct tablet_dispatch *tablet, unsigned int index) +{ + size_t sz = tablet_history_size(tablet); + + assert(index < sz); + assert(index < tablet->history.count); + + index = (tablet->history.index + sz - index) % sz; + return &tablet->history.samples[index]; +} + static bool tablet_device_has_axis(struct tablet_dispatch *tablet, enum libinput_tablet_tool_axis axis) @@ -542,10 +586,11 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, struct tablet_axes axes = {0}; const char tmp[sizeof(tablet->changed_axes)] = {0}; struct device_coords delta; + bool rc = false; if (memcmp(tmp, tablet->changed_axes, sizeof(tmp)) == 0) { - *axes_out = tablet->axes; - return false; + axes = tablet->axes; + goto out; } tablet_handle_xy(tablet, device, &axes.point, &delta); @@ -577,9 +622,14 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, *axes_out = axes; - return true; -} + rc = true; + +out: + tablet_history_push(tablet, &tablet->axes); + return rc; +} +/**/ static void tablet_update_button(struct tablet_dispatch *tablet, uint32_t evcode, @@ -1436,8 +1486,10 @@ tablet_send_events(struct tablet_dispatch *tablet, tablet_send_buttons(tablet, tool, device, time); - if (tablet_send_proximity_out(tablet, tool, device, &axes, time)) + if (tablet_send_proximity_out(tablet, tool, device, &axes, time)) { tablet_change_to_left_handed(device); + tablet_history_reset(tablet); + } } static void diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index 2b2b1a7..344b441 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -30,6 +30,8 @@ #define LIBINPUT_TOOL_NONE 0 #define LIBINPUT_TABLET_TOOL_TYPE_MAX LIBINPUT_TABLET_TOOL_TYPE_LENS +#define TABLET_HISTORY_LENGTH 4 + enum tablet_status { TABLET_NONE = 0, TABLET_AXES_UPDATED = 1 << 0, @@ -54,6 +56,12 @@ struct tablet_dispatch { unsigned int status; unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)]; struct tablet_axes axes; + struct { + unsigned int index; + unsigned int count; + struct tablet_axes samples[TABLET_HISTORY_LENGTH]; + } history; + unsigned char axis_caps[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)]; int current_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1]; int prev_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1]; -- cgit v1.2.3 From f8aa49b619ae37ca28a819fd13c3f35030d4c020 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 13:17:43 +1000 Subject: tablet: move delta processing down No functional changes, this is just to group the calls that modify tablet axis state together and move the bits that rely on this state (but don't modify it) to the bottom. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index ec1c822..dc8bede 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -598,7 +598,6 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, axes.distance = tablet_handle_distance(tablet, device); axes.slider = tablet_handle_slider(tablet, device); axes.tilt = tablet_handle_tilt(tablet, device); - axes.delta = tool_process_delta(tool, device, &delta, time); /* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are * already normalized and set if we have the mouse/lens tool */ @@ -620,6 +619,8 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, axes.wheel = tablet_handle_wheel(tablet, device, &axes.wheel_discrete); + axes.delta = tool_process_delta(tool, device, &delta, time); + *axes_out = axes; rc = true; -- cgit v1.2.3 From 1e113f6283f6ea13b776adbe53d9effe00a0f204 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 13:20:32 +1000 Subject: tablet: move the axis transforms to the end No functional changes, part of the grouping of tablet axis manipulation vs. processing of that manipulated state. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index dc8bede..0b168ac 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -423,9 +423,6 @@ tablet_handle_xy(struct tablet_dispatch *tablet, } point.y = tablet->axes.point.y; - evdev_transform_absolute(device, &point); - evdev_transform_relative(device, &delta); - *delta_out = delta; *point_out = point; } @@ -619,6 +616,9 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, axes.wheel = tablet_handle_wheel(tablet, device, &axes.wheel_discrete); + evdev_transform_absolute(device, &axes.point); + evdev_transform_relative(device, &delta); + axes.delta = tool_process_delta(tool, device, &delta, time); *axes_out = axes; -- cgit v1.2.3 From 401bbf52d889eff7eed9c400656a911e0012c97c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 13:29:23 +1000 Subject: tablet: reshuffle device axis updates This is prep work for axis smoothing. Modify the various helper functions to just update the state in the tablet and then grab the state later for better grouping. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 77 ++++++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 0b168ac..ab06f0a 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -448,8 +448,8 @@ tool_process_delta(struct libinput_tablet_tool *tool, time); } -static inline double -tablet_handle_pressure(struct tablet_dispatch *tablet, +static inline void +tablet_update_pressure(struct tablet_dispatch *tablet, struct evdev_device *device, struct libinput_tablet_tool *tool) { @@ -460,12 +460,10 @@ tablet_handle_pressure(struct tablet_dispatch *tablet, absinfo = libevdev_get_abs_info(device->evdev, ABS_PRESSURE); tablet->axes.pressure = normalize_pressure(absinfo, tool); } - - return tablet->axes.pressure; } -static inline double -tablet_handle_distance(struct tablet_dispatch *tablet, +static inline void +tablet_update_distance(struct tablet_dispatch *tablet, struct evdev_device *device) { const struct input_absinfo *absinfo; @@ -475,12 +473,10 @@ tablet_handle_distance(struct tablet_dispatch *tablet, absinfo = libevdev_get_abs_info(device->evdev, ABS_DISTANCE); tablet->axes.distance = normalize_distance(absinfo); } - - return tablet->axes.distance; } -static inline double -tablet_handle_slider(struct tablet_dispatch *tablet, +static inline void +tablet_update_slider(struct tablet_dispatch *tablet, struct evdev_device *device) { const struct input_absinfo *absinfo; @@ -490,15 +486,12 @@ tablet_handle_slider(struct tablet_dispatch *tablet, absinfo = libevdev_get_abs_info(device->evdev, ABS_WHEEL); tablet->axes.slider = normalize_slider(absinfo); } - - return tablet->axes.slider; } -static inline struct tilt_degrees -tablet_handle_tilt(struct tablet_dispatch *tablet, +static inline void +tablet_update_tilt(struct tablet_dispatch *tablet, struct evdev_device *device) { - struct tilt_degrees tilt; const struct input_absinfo *absinfo; if (bit_is_set(tablet->changed_axes, @@ -508,7 +501,6 @@ tablet_handle_tilt(struct tablet_dispatch *tablet, if (device->left_handed.enabled) tablet->axes.tilt.x *= -1; } - tilt.x = tablet->axes.tilt.x; if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) { @@ -517,13 +509,10 @@ tablet_handle_tilt(struct tablet_dispatch *tablet, if (device->left_handed.enabled) tablet->axes.tilt.y *= -1; } - tilt.y = tablet->axes.tilt.y; - - return tilt; } -static inline double -tablet_handle_artpen_rotation(struct tablet_dispatch *tablet, +static inline void +tablet_update_artpen_rotation(struct tablet_dispatch *tablet, struct evdev_device *device) { const struct input_absinfo *absinfo; @@ -535,12 +524,10 @@ tablet_handle_artpen_rotation(struct tablet_dispatch *tablet, /* artpen has 0 with buttons pointing east */ tablet->axes.rotation = convert_to_degrees(absinfo, 90); } - - return tablet->axes.rotation; } -static inline double -tablet_handle_mouse_rotation(struct tablet_dispatch *tablet, +static inline void +tablet_update_mouse_rotation(struct tablet_dispatch *tablet, struct evdev_device *device) { if (bit_is_set(tablet->changed_axes, @@ -549,28 +536,23 @@ tablet_handle_mouse_rotation(struct tablet_dispatch *tablet, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) { convert_tilt_to_rotation(tablet); } - - return tablet->axes.rotation; } -static inline double -tablet_handle_wheel(struct tablet_dispatch *tablet, - struct evdev_device *device, - int *wheel_discrete) +static inline void +tablet_update_wheel(struct tablet_dispatch *tablet, + struct evdev_device *device) { int a; a = LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL; if (bit_is_set(tablet->changed_axes, a)) { - *wheel_discrete = tablet->axes.wheel_discrete; + /* tablet->axes.wheel_discrete is already set */ tablet->axes.wheel = normalize_wheel(tablet, tablet->axes.wheel_discrete); } else { tablet->axes.wheel = 0; - *wheel_discrete = 0; + tablet->axes.wheel_discrete = 0; } - - return tablet->axes.wheel; } static bool @@ -591,31 +573,40 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, } tablet_handle_xy(tablet, device, &axes.point, &delta); - axes.pressure = tablet_handle_pressure(tablet, device, tool); - axes.distance = tablet_handle_distance(tablet, device); - axes.slider = tablet_handle_slider(tablet, device); - axes.tilt = tablet_handle_tilt(tablet, device); + + tablet_update_pressure(tablet, device, tool); + tablet_update_distance(tablet, device); + tablet_update_slider(tablet, device); + tablet_update_tilt(tablet, device); + tablet_update_wheel(tablet, device); + + axes.pressure = tablet->axes.pressure; + axes.distance = tablet->axes.distance; + axes.slider = tablet->axes.slider; + axes.tilt = tablet->axes.tilt; + axes.wheel = tablet->axes.wheel; + axes.wheel_discrete = tablet->axes.wheel_discrete; /* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are * already normalized and set if we have the mouse/lens tool */ if (tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE || tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_LENS) { - axes.rotation = tablet_handle_mouse_rotation(tablet, device); + tablet_update_mouse_rotation(tablet, device); clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_X); clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y); axes.tilt.x = 0; axes.tilt.y = 0; + axes.rotation = tablet->axes.rotation; /* tilt is already converted to left-handed, so mouse * rotation is converted to left-handed automatically */ } else { - axes.rotation = tablet_handle_artpen_rotation(tablet, device); + tablet_update_artpen_rotation(tablet, device); + axes.rotation = tablet->axes.rotation; if (device->left_handed.enabled) axes.rotation = fmod(180 + axes.rotation, 360); } - axes.wheel = tablet_handle_wheel(tablet, device, &axes.wheel_discrete); - evdev_transform_absolute(device, &axes.point); evdev_transform_relative(device, &delta); -- cgit v1.2.3 From 230af3f9fcf406b6c854c9fe7b6ff2cb6497c9dd Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 14:02:53 +1000 Subject: table: move custom rotation handling into a helper function This is a bit hard to follow: - tilt is handled first and if either tilt axis is set we fetch *both* tilt axes into tablet->axes.tilt - rotation is handled second but it only triggers if either tilt axis is flagged. as we now guarantee to have both axes in tablet->axes.tilt, we can continue with the rotation conversion without needing some other state Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 69 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 27 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index ab06f0a..ff12ad5 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -494,20 +494,23 @@ tablet_update_tilt(struct tablet_dispatch *tablet, { const struct input_absinfo *absinfo; + /* mouse rotation resets tilt to 0 so always fetch both axes if + * either has changed */ if (bit_is_set(tablet->changed_axes, - LIBINPUT_TABLET_TOOL_AXIS_TILT_X)) { + LIBINPUT_TABLET_TOOL_AXIS_TILT_X) || + bit_is_set(tablet->changed_axes, + LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) { + absinfo = libevdev_get_abs_info(device->evdev, ABS_TILT_X); tablet->axes.tilt.x = adjust_tilt(absinfo); - if (device->left_handed.enabled) - tablet->axes.tilt.x *= -1; - } - if (bit_is_set(tablet->changed_axes, - LIBINPUT_TABLET_TOOL_AXIS_TILT_Y)) { absinfo = libevdev_get_abs_info(device->evdev, ABS_TILT_Y); tablet->axes.tilt.y = adjust_tilt(absinfo); - if (device->left_handed.enabled) + + if (device->left_handed.enabled) { + tablet->axes.tilt.x *= -1; tablet->axes.tilt.y *= -1; + } } } @@ -538,6 +541,34 @@ tablet_update_mouse_rotation(struct tablet_dispatch *tablet, } } +static inline void +tablet_update_rotation(struct tablet_dispatch *tablet, + struct evdev_device *device) +{ + /* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are + * already normalized and set if we have the mouse/lens tool */ + if (tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE || + tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_LENS) { + tablet_update_mouse_rotation(tablet, device); + clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_X); + clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y); + tablet->axes.tilt.x = 0; + tablet->axes.tilt.y = 0; + tablet->axes.rotation = tablet->axes.rotation; + + /* tilt is already converted to left-handed, so mouse + * rotation is converted to left-handed automatically */ + } else { + + tablet_update_artpen_rotation(tablet, device); + + if (device->left_handed.enabled) { + double r = tablet->axes.rotation; + tablet->axes.rotation = fmod(180 + r, 360); + } + } +} + static inline void tablet_update_wheel(struct tablet_dispatch *tablet, struct evdev_device *device) @@ -579,6 +610,9 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, tablet_update_slider(tablet, device); tablet_update_tilt(tablet, device); tablet_update_wheel(tablet, device); + /* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are + * already normalized and set if we have the mouse/lens tool */ + tablet_update_rotation(tablet, device); axes.pressure = tablet->axes.pressure; axes.distance = tablet->axes.distance; @@ -586,26 +620,7 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, axes.tilt = tablet->axes.tilt; axes.wheel = tablet->axes.wheel; axes.wheel_discrete = tablet->axes.wheel_discrete; - - /* We must check ROTATION_Z after TILT_X/Y so that the tilt axes are - * already normalized and set if we have the mouse/lens tool */ - if (tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE || - tablet->current_tool_type == LIBINPUT_TABLET_TOOL_TYPE_LENS) { - tablet_update_mouse_rotation(tablet, device); - clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_X); - clear_bit(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_TILT_Y); - axes.tilt.x = 0; - axes.tilt.y = 0; - axes.rotation = tablet->axes.rotation; - - /* tilt is already converted to left-handed, so mouse - * rotation is converted to left-handed automatically */ - } else { - tablet_update_artpen_rotation(tablet, device); - axes.rotation = tablet->axes.rotation; - if (device->left_handed.enabled) - axes.rotation = fmod(180 + axes.rotation, 360); - } + axes.rotation = tablet->axes.rotation; evdev_transform_absolute(device, &axes.point); evdev_transform_relative(device, &delta); -- cgit v1.2.3 From 88876e66fab67eae3c7aa75a4e19479df556b08f Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 15:32:59 +1000 Subject: tablet: split point vs delta handling up Handle the delta in the end once we've updated the device state for all axes. This requires us to use the device history rather than the current state delta, and it also requires us to update both x and y whenever an axis change comes in. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 61 +++++++++++++++++++++++++----------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index ff12ad5..1120598 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -383,17 +383,14 @@ normalize_wheel(struct tablet_dispatch *tablet, } static inline void -tablet_handle_xy(struct tablet_dispatch *tablet, - struct evdev_device *device, - struct device_coords *point_out, - struct device_coords *delta_out) +tablet_update_xy(struct tablet_dispatch *tablet, + struct evdev_device *device) { - struct device_coords point; - struct device_coords delta = { 0, 0 }; const struct input_absinfo *absinfo; int value; - if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X)) { + if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X) || + bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y)) { absinfo = libevdev_get_abs_info(device->evdev, ABS_X); if (device->left_handed.enabled) @@ -401,14 +398,8 @@ tablet_handle_xy(struct tablet_dispatch *tablet, else value = absinfo->value; - if (!tablet_has_status(tablet, - TABLET_TOOL_ENTERING_PROXIMITY)) - delta.x = value - tablet->axes.point.x; tablet->axes.point.x = value; - } - point.x = tablet->axes.point.x; - if (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y)) { absinfo = libevdev_get_abs_info(device->evdev, ABS_Y); if (device->left_handed.enabled) @@ -416,28 +407,36 @@ tablet_handle_xy(struct tablet_dispatch *tablet, else value = absinfo->value; - if (!tablet_has_status(tablet, - TABLET_TOOL_ENTERING_PROXIMITY)) - delta.y = value - tablet->axes.point.y; tablet->axes.point.y = value; - } - point.y = tablet->axes.point.y; - *delta_out = delta; - *point_out = point; + evdev_transform_absolute(device, &tablet->axes.point); + } } static inline struct normalized_coords -tool_process_delta(struct libinput_tablet_tool *tool, - const struct evdev_device *device, - const struct device_coords *delta, - uint64_t time) +tablet_tool_process_delta(struct tablet_dispatch *tablet, + struct libinput_tablet_tool *tool, + const struct evdev_device *device, + uint64_t time) { const struct normalized_coords zero = { 0.0, 0.0 }; + const struct tablet_axes *last, *current; + struct device_coords delta = { 0, 0 }; struct device_float_coords accel; - accel.x = 1.0 * delta->x; - accel.y = 1.0 * delta->y; + if (!tablet_has_status(tablet, + TABLET_TOOL_ENTERING_PROXIMITY) && + (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X) || + bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y))) { + current = &tablet->axes; + last = tablet_history_get(tablet, 0); + + delta.x = current->point.x - last->point.x; + delta.y = current->point.y - last->point.y; + } + + accel.x = 1.0 * delta.x; + accel.y = 1.0 * delta.y; if (device_float_is_zero(accel)) return zero; @@ -595,7 +594,6 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, { struct tablet_axes axes = {0}; const char tmp[sizeof(tablet->changed_axes)] = {0}; - struct device_coords delta; bool rc = false; if (memcmp(tmp, tablet->changed_axes, sizeof(tmp)) == 0) { @@ -603,8 +601,7 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, goto out; } - tablet_handle_xy(tablet, device, &axes.point, &delta); - + tablet_update_xy(tablet, device); tablet_update_pressure(tablet, device, tool); tablet_update_distance(tablet, device); tablet_update_slider(tablet, device); @@ -614,6 +611,7 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, * already normalized and set if we have the mouse/lens tool */ tablet_update_rotation(tablet, device); + axes.point = tablet->axes.point; axes.pressure = tablet->axes.pressure; axes.distance = tablet->axes.distance; axes.slider = tablet->axes.slider; @@ -622,10 +620,7 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, axes.wheel_discrete = tablet->axes.wheel_discrete; axes.rotation = tablet->axes.rotation; - evdev_transform_absolute(device, &axes.point); - evdev_transform_relative(device, &delta); - - axes.delta = tool_process_delta(tool, device, &delta, time); + axes.delta = tablet_tool_process_delta(tablet, tool, device, time); *axes_out = axes; -- cgit v1.2.3 From a19d18f9c68ebe962731964f177427a1c16b7ca8 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 16:37:55 +1000 Subject: tablet: add assert that deltas are always 0 The tablet axis struct has a delta field that's only useful for the events, not for our internal axis handling. Make sure we never set it to anything nonzero. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 1120598..413fb42 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -1479,6 +1479,9 @@ tablet_send_events(struct tablet_dispatch *tablet, tablet_check_notify_axes(tablet, device, tool, &axes, time); } + assert(tablet->axes.delta.x == 0); + assert(tablet->axes.delta.y == 0); + tablet_send_proximity_in(tablet, tool, device, &axes, time); if (!tablet_send_tip(tablet, tool, device, &axes, time)) tablet_send_axes(tablet, tool, device, &axes, time); -- cgit v1.2.3 From ae11eaa2650d5b70b7d03c542c7efe8d10fbb95d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 17:08:07 +1000 Subject: tablet: reset delta and changed axes as soon as we send them We don't have frame events for tablets so we must take care to send the axis change notifications only once and leave the others as-is. Most of the axes are absolute so it doesn't really matter, but we need to reset the delta to make sure clients don't receive the same delta twice. Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 413fb42..daef7ac 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -120,6 +120,12 @@ tablet_history_get(const struct tablet_dispatch *tablet, unsigned int index) return &tablet->history.samples[index]; } +static inline void +tablet_reset_changed_axes(struct tablet_dispatch *tablet) +{ + memset(tablet->changed_axes, 0, sizeof(tablet->changed_axes)); +} + static bool tablet_device_has_axis(struct tablet_dispatch *tablet, enum libinput_tablet_tool_axis axis) @@ -1328,7 +1334,7 @@ static inline bool tablet_send_proximity_in(struct tablet_dispatch *tablet, struct libinput_tablet_tool *tool, struct evdev_device *device, - const struct tablet_axes *axes, + struct tablet_axes *axes, uint64_t time) { if (!tablet_has_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY)) @@ -1343,6 +1349,10 @@ tablet_send_proximity_in(struct tablet_dispatch *tablet, tablet_unset_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY); tablet_unset_status(tablet, TABLET_AXES_UPDATED); + tablet_reset_changed_axes(tablet); + axes->delta.x = 0; + axes->delta.y = 0; + return true; } @@ -1350,7 +1360,7 @@ static inline bool tablet_send_proximity_out(struct tablet_dispatch *tablet, struct libinput_tablet_tool *tool, struct evdev_device *device, - const struct tablet_axes *axes, + struct tablet_axes *axes, uint64_t time) { if (!tablet_has_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY)) @@ -1366,6 +1376,10 @@ tablet_send_proximity_out(struct tablet_dispatch *tablet, tablet_set_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY); tablet_unset_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); + tablet_reset_changed_axes(tablet); + axes->delta.x = 0; + axes->delta.y = 0; + return true; } @@ -1373,7 +1387,7 @@ static inline bool tablet_send_tip(struct tablet_dispatch *tablet, struct libinput_tablet_tool *tool, struct evdev_device *device, - const struct tablet_axes *axes, + struct tablet_axes *axes, uint64_t time) { if (tablet_has_status(tablet, TABLET_TOOL_ENTERING_CONTACT)) { @@ -1386,6 +1400,11 @@ tablet_send_tip(struct tablet_dispatch *tablet, tablet_unset_status(tablet, TABLET_AXES_UPDATED); tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT); tablet_set_status(tablet, TABLET_TOOL_IN_CONTACT); + + tablet_reset_changed_axes(tablet); + axes->delta.x = 0; + axes->delta.y = 0; + return true; } @@ -1399,6 +1418,11 @@ tablet_send_tip(struct tablet_dispatch *tablet, tablet_unset_status(tablet, TABLET_AXES_UPDATED); tablet_unset_status(tablet, TABLET_TOOL_LEAVING_CONTACT); tablet_unset_status(tablet, TABLET_TOOL_IN_CONTACT); + + tablet_reset_changed_axes(tablet); + axes->delta.x = 0; + axes->delta.y = 0; + return true; } @@ -1409,7 +1433,7 @@ static inline void tablet_send_axes(struct tablet_dispatch *tablet, struct libinput_tablet_tool *tool, struct evdev_device *device, - const struct tablet_axes *axes, + struct tablet_axes *axes, uint64_t time) { enum libinput_tablet_tool_tip_state tip_state; @@ -1430,6 +1454,9 @@ tablet_send_axes(struct tablet_dispatch *tablet, tablet->changed_axes, axes); tablet_unset_status(tablet, TABLET_AXES_UPDATED); + tablet_reset_changed_axes(tablet); + axes->delta.x = 0; + axes->delta.y = 0; } static inline void @@ -1486,8 +1513,8 @@ tablet_send_events(struct tablet_dispatch *tablet, if (!tablet_send_tip(tablet, tool, device, &axes, time)) tablet_send_axes(tablet, tool, device, &axes, time); - memset(tablet->changed_axes, 0, sizeof(tablet->changed_axes)); tablet_unset_status(tablet, TABLET_TOOL_ENTERING_CONTACT); + tablet_reset_changed_axes(tablet); tablet_send_buttons(tablet, tool, device, time); -- cgit v1.2.3 From 411a3a4766144c93795c2bda9aa9f89a3602c896 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 7 Mar 2017 16:00:45 +1000 Subject: tablet: add axis smoothing Taking the tablet events as-is produces the occasional wobble in what should be a straight line. Bug 99961 has a jpg attachment to illustrate that. Emulate the wacom driver behavior and average x/y across the last 4 values to smoothen out these dents. https://bugs.freedesktop.org/show_bug.cgi?id=99961 Signed-off-by: Peter Hutterer Acked-by: Ping Cheng --- src/evdev-tablet.c | 48 +++++++++++++++++++++++++-------- src/evdev-tablet.h | 3 ++- test/test-tablet.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 110 insertions(+), 19 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index daef7ac..f87ccfe 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -423,10 +423,10 @@ static inline struct normalized_coords tablet_tool_process_delta(struct tablet_dispatch *tablet, struct libinput_tablet_tool *tool, const struct evdev_device *device, + struct tablet_axes *axes, uint64_t time) { const struct normalized_coords zero = { 0.0, 0.0 }; - const struct tablet_axes *last, *current; struct device_coords delta = { 0, 0 }; struct device_float_coords accel; @@ -434,13 +434,12 @@ tablet_tool_process_delta(struct tablet_dispatch *tablet, TABLET_TOOL_ENTERING_PROXIMITY) && (bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_X) || bit_is_set(tablet->changed_axes, LIBINPUT_TABLET_TOOL_AXIS_Y))) { - current = &tablet->axes; - last = tablet_history_get(tablet, 0); - - delta.x = current->point.x - last->point.x; - delta.y = current->point.y - last->point.y; + delta.x = axes->point.x - tablet->last_smooth_point.x; + delta.y = axes->point.y - tablet->last_smooth_point.y; } + tablet->last_smooth_point = axes->point; + accel.x = 1.0 * delta.x; accel.y = 1.0 * delta.y; @@ -591,6 +590,31 @@ tablet_update_wheel(struct tablet_dispatch *tablet, } } +static void +tablet_smoothen_axes(const struct tablet_dispatch *tablet, + struct tablet_axes *axes) +{ + size_t i; + size_t count = tablet_history_size(tablet); + struct tablet_axes smooth = { 0 }; + + for (i = 0; i < count; i++) { + const struct tablet_axes *a = tablet_history_get(tablet, i); + + smooth.point.x += a->point.x; + smooth.point.y += a->point.y; + + smooth.tilt.x += a->tilt.x; + smooth.tilt.y += a->tilt.y; + } + + axes->point.x = smooth.point.x/count; + axes->point.y = smooth.point.y/count; + + axes->tilt.x = smooth.tilt.x/count; + axes->tilt.y = smooth.tilt.y/count; +} + static bool tablet_check_notify_axes(struct tablet_dispatch *tablet, struct evdev_device *device, @@ -626,18 +650,20 @@ tablet_check_notify_axes(struct tablet_dispatch *tablet, axes.wheel_discrete = tablet->axes.wheel_discrete; axes.rotation = tablet->axes.rotation; - axes.delta = tablet_tool_process_delta(tablet, tool, device, time); - - *axes_out = axes; - rc = true; out: tablet_history_push(tablet, &tablet->axes); + tablet_smoothen_axes(tablet, &axes); + + /* The delta relies on the last *smooth* point, so we do it last */ + axes.delta = tablet_tool_process_delta(tablet, tool, device, &axes, time); + + *axes_out = axes; return rc; } -/**/ + static void tablet_update_button(struct tablet_dispatch *tablet, uint32_t evcode, diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index 344b441..43ed897 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -55,7 +55,8 @@ struct tablet_dispatch { struct evdev_device *device; unsigned int status; unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)]; - struct tablet_axes axes; + struct tablet_axes axes; /* for assembling the current state */ + struct device_coords last_smooth_point; struct { unsigned int index; unsigned int count; diff --git a/test/test-tablet.c b/test/test-tablet.c index 7e2545d..215a9f6 100644 --- a/test/test-tablet.c +++ b/test/test-tablet.c @@ -1013,6 +1013,13 @@ START_TEST(proximity_has_axes) litest_axis_set_value(axes, ABS_DISTANCE, 20); litest_axis_set_value(axes, ABS_TILT_X, 15); litest_axis_set_value(axes, ABS_TILT_Y, 25); + + /* work around axis smoothing */ + litest_tablet_motion(dev, 20, 30, axes); + litest_tablet_motion(dev, 20, 29, axes); + litest_tablet_motion(dev, 20, 31, axes); + litest_drain_events(li); + litest_tablet_motion(dev, 20, 30, axes); libinput_dispatch(li); event = libinput_get_event(li); @@ -1044,8 +1051,10 @@ START_TEST(proximity_has_axes) x = libinput_event_tablet_tool_get_x(tablet_event); y = libinput_event_tablet_tool_get_y(tablet_event); - litest_assert_double_eq(x, last_x); - litest_assert_double_eq(y, last_y); + litest_assert_double_ge(x, last_x - 1); + litest_assert_double_le(x, last_x + 1); + litest_assert_double_ge(y, last_y - 1); + litest_assert_double_le(y, last_y + 1); if (libinput_tablet_tool_has_distance(tool)) { ck_assert(!libinput_event_tablet_tool_distance_has_changed( @@ -1428,6 +1437,16 @@ START_TEST(left_handed) libinput_event_destroy(event); + /* work around smoothing */ + litest_axis_set_value(axes, ABS_DISTANCE, 9); + litest_tablet_motion(dev, 100, 0, axes); + litest_axis_set_value(axes, ABS_DISTANCE, 7); + litest_tablet_motion(dev, 100, 0, axes); + litest_axis_set_value(axes, ABS_DISTANCE, 10); + litest_tablet_motion(dev, 100, 0, axes); + litest_drain_events(li); + + litest_axis_set_value(axes, ABS_DISTANCE, 5); litest_tablet_motion(dev, 100, 0, axes); libinput_dispatch(li); @@ -1468,6 +1487,16 @@ START_TEST(left_handed) libinput_event_destroy(event); + /* work around smoothing */ + litest_axis_set_value(axes, ABS_DISTANCE, 9); + litest_tablet_motion(dev, 100, 0, axes); + litest_axis_set_value(axes, ABS_DISTANCE, 7); + litest_tablet_motion(dev, 100, 0, axes); + litest_axis_set_value(axes, ABS_DISTANCE, 10); + litest_tablet_motion(dev, 100, 0, axes); + litest_drain_events(li); + + litest_axis_set_value(axes, ABS_DISTANCE, 5); litest_tablet_motion(dev, 100, 0, axes); libinput_dispatch(li); @@ -1768,6 +1797,7 @@ START_TEST(motion_outside_bounds) struct libinput_event *event; struct libinput_event_tablet_tool *tablet_event; double val; + int i; struct axis_replacement axes[] = { { ABS_DISTANCE, 10 }, @@ -1778,6 +1808,15 @@ START_TEST(motion_outside_bounds) litest_tablet_proximity_in(dev, 50, 50, axes); litest_drain_events(li); + /* Work around smoothing */ + for (i = 5; i > 0; i--) { + litest_event(dev, EV_ABS, ABS_X, 0 + 5 * i); + litest_event(dev, EV_ABS, ABS_Y, 1000); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + } + litest_drain_events(li); + /* On the 24HD x/y of 0 is outside the limit */ litest_event(dev, EV_ABS, ABS_X, 0); litest_event(dev, EV_ABS, ABS_Y, 1000); @@ -1797,6 +1836,15 @@ START_TEST(motion_outside_bounds) libinput_event_destroy(event); + /* Work around smoothing */ + for (i = 5; i > 0; i--) { + litest_event(dev, EV_ABS, ABS_X, 1000); + litest_event(dev, EV_ABS, ABS_Y, 0 + 5 * i); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + } + litest_drain_events(li); + /* On the 24HD x/y of 0 is outside the limit */ litest_event(dev, EV_ABS, ABS_X, 1000); litest_event(dev, EV_ABS, ABS_Y, 0); @@ -3341,12 +3389,18 @@ START_TEST(tablet_pressure_min_max) litest_tablet_motion(dev, 5, 100, axes); litest_drain_events(li); + /* need to fill the motion history */ litest_axis_set_value(axes, ABS_PRESSURE, 100); + litest_tablet_motion(dev, 5, 100, axes); + litest_tablet_motion(dev, 6, 100, axes); + litest_tablet_motion(dev, 7, 100, axes); + litest_tablet_motion(dev, 8, 100, axes); + litest_drain_events(li); + litest_tablet_motion(dev, 5, 100, axes); libinput_dispatch(li); event = libinput_get_event(li); tev = litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS); - ck_assert(libinput_event_tablet_tool_pressure_has_changed(tev)); p = libinput_event_tablet_tool_get_pressure(tev); ck_assert_double_ge(p, 1.0); libinput_event_destroy(event); @@ -3630,7 +3684,12 @@ START_TEST(tilt_x) for (tilt = 0; tilt <= 100; tilt += 5) { litest_axis_set_value(axes, ABS_TILT_X, tilt); + /* work around smoothing */ + litest_tablet_motion(dev, 10, 10, axes); + litest_tablet_motion(dev, 10, 11, axes); litest_tablet_motion(dev, 10, 10, axes); + litest_drain_events(li); + litest_tablet_motion(dev, 10, 11, axes); libinput_dispatch(li); event = libinput_get_event(li); tev = litest_is_tablet_event(event, @@ -3699,6 +3758,11 @@ START_TEST(tilt_y) for (tilt = 0; tilt <= 100; tilt += 5) { litest_axis_set_value(axes, ABS_TILT_Y, tilt); + /* work around smoothing */ + litest_tablet_motion(dev, 10, 11, axes); + litest_tablet_motion(dev, 10, 10, axes); + litest_tablet_motion(dev, 10, 11, axes); + litest_drain_events(li); litest_tablet_motion(dev, 10, 10, axes); libinput_dispatch(li); event = libinput_get_event(li); @@ -3815,7 +3879,7 @@ START_TEST(relative_delta) ck_assert(dy == 0.0); libinput_event_destroy(event); - litest_tablet_motion(dev, 10, 10, axes); + litest_tablet_motion(dev, 5, 10, axes); libinput_dispatch(li); event = libinput_get_event(li); tev = litest_is_tablet_event(event, @@ -3837,7 +3901,7 @@ START_TEST(relative_delta) ck_assert(dy > 0.0); libinput_event_destroy(event); - litest_tablet_motion(dev, 10, 10, axes); + litest_tablet_motion(dev, 10, 5, axes); libinput_dispatch(li); event = libinput_get_event(li); tev = litest_is_tablet_event(event, @@ -3888,7 +3952,7 @@ START_TEST(relative_calibration) ck_assert(dy == 0.0); libinput_event_destroy(event); - litest_tablet_motion(dev, 10, 10, axes); + litest_tablet_motion(dev, 5, 10, axes); libinput_dispatch(li); event = libinput_get_event(li); tev = litest_is_tablet_event(event, @@ -3910,7 +3974,7 @@ START_TEST(relative_calibration) ck_assert(dy < 0.0); libinput_event_destroy(event); - litest_tablet_motion(dev, 10, 10, axes); + litest_tablet_motion(dev, 10, 5, axes); libinput_dispatch(li); event = libinput_get_event(li); tev = litest_is_tablet_event(event, -- cgit v1.2.3