mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-12 15:00:19 +01:00
touchpad: add hysteresis smoothing for input coordinates
Same algorithm as in evdev-touchpad. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
37a04e0b0d
commit
e75a0430be
1 changed files with 63 additions and 0 deletions
|
|
@ -23,10 +23,12 @@
|
|||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "evdev.h"
|
||||
|
||||
#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
|
||||
#define TOUCHPAD_HISTORY_LENGTH 4
|
||||
|
||||
#define tp_for_each_touch(_tp, _t) \
|
||||
|
|
@ -56,6 +58,11 @@ struct tp_touch {
|
|||
unsigned int index;
|
||||
unsigned int count;
|
||||
} history;
|
||||
|
||||
struct {
|
||||
int32_t center_x;
|
||||
int32_t center_y;
|
||||
} hysteresis;
|
||||
};
|
||||
|
||||
struct tp_dispatch {
|
||||
|
|
@ -66,8 +73,27 @@ struct tp_dispatch {
|
|||
|
||||
unsigned int ntouches; /* number of slots */
|
||||
struct tp_touch *touches; /* len == ntouches */
|
||||
|
||||
struct {
|
||||
int32_t margin_x;
|
||||
int32_t margin_y;
|
||||
} hysteresis;
|
||||
};
|
||||
|
||||
static inline int
|
||||
tp_hysteresis(int in, int center, int margin)
|
||||
{
|
||||
int diff = in - center;
|
||||
if (abs(diff) <= margin)
|
||||
return center;
|
||||
|
||||
if (diff > margin)
|
||||
return center + diff - margin;
|
||||
else if (diff < -margin)
|
||||
return center + diff + margin;
|
||||
return center + diff;
|
||||
}
|
||||
|
||||
static inline struct tp_motion *
|
||||
tp_motion_history_offset(struct tp_touch *t, int offset)
|
||||
{
|
||||
|
|
@ -91,6 +117,30 @@ tp_motion_history_push(struct tp_touch *t)
|
|||
t->history.index = motion_index;
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_motion_hysteresis(struct tp_dispatch *tp,
|
||||
struct tp_touch *t)
|
||||
{
|
||||
int x = t->x,
|
||||
y = t->y;
|
||||
|
||||
if (t->history.count == 0) {
|
||||
t->hysteresis.center_x = t->x;
|
||||
t->hysteresis.center_y = t->y;
|
||||
} else {
|
||||
x = tp_hysteresis(x,
|
||||
t->hysteresis.center_x,
|
||||
tp->hysteresis.margin_x);
|
||||
y = tp_hysteresis(y,
|
||||
t->hysteresis.center_y,
|
||||
tp->hysteresis.margin_y);
|
||||
t->hysteresis.center_x = x;
|
||||
t->hysteresis.center_y = y;
|
||||
t->x = x;
|
||||
t->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
tp_motion_history_reset(struct tp_touch *t)
|
||||
{
|
||||
|
|
@ -210,6 +260,7 @@ tp_process_state(struct tp_dispatch *tp, uint32_t time)
|
|||
if (!t->dirty)
|
||||
continue;
|
||||
|
||||
tp_motion_hysteresis(tp, t);
|
||||
tp_motion_history_push(t);
|
||||
}
|
||||
}
|
||||
|
|
@ -311,12 +362,24 @@ static int
|
|||
tp_init(struct tp_dispatch *tp,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
int width, height;
|
||||
double diagonal;
|
||||
|
||||
tp->base.interface = &tp_interface;
|
||||
tp->device = device;
|
||||
|
||||
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);
|
||||
diagonal = sqrt(width*width + height*height);
|
||||
|
||||
tp->hysteresis.margin_x =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
tp->hysteresis.margin_y =
|
||||
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue