mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-03-21 13:20:42 +01:00
fsm now per device instead of a global struct
This commit is contained in:
parent
07337e906b
commit
7c5cdadcda
4 changed files with 77 additions and 78 deletions
|
|
@ -38,27 +38,6 @@
|
|||
|
||||
#include "evdev-mt-touchpad.h"
|
||||
|
||||
void
|
||||
tp_edge_motion_init(struct tp_dispatch *tp);
|
||||
|
||||
enum edge_motion_state { STATE_IDLE, STATE_DRAG_ACTIVE, STATE_EDGE_MOTION };
|
||||
|
||||
struct edge_motion_fsm {
|
||||
enum edge_motion_state current_state;
|
||||
usec_t last_motion_time;
|
||||
uint32_t current_edge;
|
||||
double motion_dx;
|
||||
double motion_dy;
|
||||
uint32_t continuous_motion_count;
|
||||
struct tp_dispatch *tp;
|
||||
struct libinput_timer timer;
|
||||
};
|
||||
|
||||
static struct edge_motion_fsm fsm = {
|
||||
.current_state = STATE_IDLE,
|
||||
.tp = NULL,
|
||||
};
|
||||
|
||||
#define EDGE_MOTION_CONFIG_SPEED_MM_S 70.0
|
||||
#define EDGE_MOTION_CONFIG_MIN_INTERVAL_US 8000
|
||||
#define EDGE_MOTION_CONFIG_EDGE_THRESHOLD_MM 5.0
|
||||
|
|
@ -89,12 +68,12 @@ calculate_motion_vector(uint32_t edge, double *dx, double *dy)
|
|||
static void
|
||||
inject_accumulated_motion(struct tp_dispatch *tp, usec_t time)
|
||||
{
|
||||
if (usec_is_zero(fsm.last_motion_time)) {
|
||||
fsm.last_motion_time = time;
|
||||
if (usec_is_zero(tp->edge_motion.last_motion_time)) {
|
||||
tp->edge_motion.last_motion_time = time;
|
||||
return;
|
||||
}
|
||||
|
||||
usec_t time_since_last = usec_sub(time, fsm.last_motion_time);
|
||||
usec_t time_since_last = usec_sub(time, tp->edge_motion.last_motion_time);
|
||||
double dist_mm = EDGE_MOTION_CONFIG_SPEED_MM_S *
|
||||
((double)usec_as_uint64_t(time_since_last) / 1000000.0);
|
||||
|
||||
|
|
@ -102,8 +81,8 @@ inject_accumulated_motion(struct tp_dispatch *tp, usec_t time)
|
|||
return;
|
||||
|
||||
struct device_float_coords raw = {
|
||||
.x = fsm.motion_dx * dist_mm * tp->accel.x_scale_coeff,
|
||||
.y = fsm.motion_dy * dist_mm * tp->accel.y_scale_coeff
|
||||
.x = tp->edge_motion.motion_dx * dist_mm * tp->accel.x_scale_coeff,
|
||||
.y = tp->edge_motion.motion_dy * dist_mm * tp->accel.y_scale_coeff
|
||||
};
|
||||
|
||||
struct normalized_coords delta =
|
||||
|
|
@ -111,8 +90,8 @@ inject_accumulated_motion(struct tp_dispatch *tp, usec_t time)
|
|||
|
||||
pointer_notify_motion(&tp->device->base, time, &delta, &raw);
|
||||
|
||||
fsm.last_motion_time = time;
|
||||
fsm.continuous_motion_count++;
|
||||
tp->edge_motion.last_motion_time = time;
|
||||
tp->edge_motion.continuous_motion_count++;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
|
|
@ -138,50 +117,44 @@ detect_touch_edge(const struct tp_dispatch *tp, const struct tp_touch *t)
|
|||
static void
|
||||
tp_edge_motion_handle_timeout(usec_t now, void *data)
|
||||
{
|
||||
struct edge_motion_fsm *fsm_ptr = data;
|
||||
struct tp_dispatch *tp = data;
|
||||
|
||||
if (fsm_ptr->current_state != STATE_EDGE_MOTION)
|
||||
if (tp->edge_motion.state != EDGE_MOTION_STATE_EDGE_MOTION)
|
||||
return;
|
||||
|
||||
inject_accumulated_motion(fsm_ptr->tp, now);
|
||||
inject_accumulated_motion(tp, now);
|
||||
libinput_timer_set(
|
||||
&fsm_ptr->timer,
|
||||
&tp->edge_motion.timer,
|
||||
usec_add(now, usec_from_uint64_t(EDGE_MOTION_CONFIG_MIN_INTERVAL_US)));
|
||||
}
|
||||
|
||||
void
|
||||
tp_edge_motion_init(struct tp_dispatch *tp)
|
||||
tp_init_edge_motion(struct tp_dispatch *tp)
|
||||
{
|
||||
if (fsm.tp)
|
||||
return;
|
||||
tp->edge_motion.state = EDGE_MOTION_STATE_IDLE;
|
||||
tp->edge_motion.last_motion_time = usec_from_uint64_t(0);
|
||||
tp->edge_motion.current_edge = EDGE_NONE;
|
||||
tp->edge_motion.motion_dx = 0.0;
|
||||
tp->edge_motion.motion_dy = 0.0;
|
||||
tp->edge_motion.continuous_motion_count = 0;
|
||||
|
||||
memset(&fsm, 0, sizeof(fsm));
|
||||
fsm.current_state = STATE_IDLE;
|
||||
fsm.tp = tp;
|
||||
|
||||
libinput_timer_init(&fsm.timer,
|
||||
libinput_timer_init(&tp->edge_motion.timer,
|
||||
tp_libinput_context(tp),
|
||||
"edge drag motion",
|
||||
tp_edge_motion_handle_timeout,
|
||||
&fsm);
|
||||
tp);
|
||||
}
|
||||
|
||||
void
|
||||
tp_edge_motion_cleanup(void)
|
||||
tp_remove_edge_motion(struct tp_dispatch *tp)
|
||||
{
|
||||
if (fsm.tp)
|
||||
libinput_timer_destroy(&fsm.timer);
|
||||
|
||||
memset(&fsm, 0, sizeof(fsm));
|
||||
fsm.current_state = STATE_IDLE;
|
||||
libinput_timer_cancel(&tp->edge_motion.timer);
|
||||
libinput_timer_destroy(&tp->edge_motion.timer);
|
||||
}
|
||||
|
||||
int
|
||||
tp_edge_motion_handle_drag_state(struct tp_dispatch *tp, usec_t time)
|
||||
{
|
||||
if (!fsm.tp)
|
||||
tp_edge_motion_init(tp);
|
||||
|
||||
bool drag_active = false;
|
||||
|
||||
switch (tp->tap.state) {
|
||||
|
|
@ -209,40 +182,41 @@ tp_edge_motion_handle_drag_state(struct tp_dispatch *tp, usec_t time)
|
|||
}
|
||||
}
|
||||
|
||||
enum edge_motion_state next_state = STATE_IDLE;
|
||||
enum tp_edge_motion_state next_state = EDGE_MOTION_STATE_IDLE;
|
||||
if (drag_active) {
|
||||
next_state = (detected_edge != EDGE_NONE) ? STATE_EDGE_MOTION
|
||||
: STATE_DRAG_ACTIVE;
|
||||
next_state = (detected_edge != EDGE_NONE) ? EDGE_MOTION_STATE_EDGE_MOTION
|
||||
: EDGE_MOTION_STATE_DRAG_ACTIVE;
|
||||
}
|
||||
|
||||
if (next_state != fsm.current_state) {
|
||||
fsm.current_state = next_state;
|
||||
fsm.current_edge = detected_edge;
|
||||
if (next_state != tp->edge_motion.state) {
|
||||
tp->edge_motion.state = next_state;
|
||||
tp->edge_motion.current_edge = detected_edge;
|
||||
|
||||
if (fsm.current_state != STATE_EDGE_MOTION)
|
||||
fsm.continuous_motion_count = 0;
|
||||
if (tp->edge_motion.state != EDGE_MOTION_STATE_EDGE_MOTION)
|
||||
tp->edge_motion.continuous_motion_count = 0;
|
||||
|
||||
switch (fsm.current_state) {
|
||||
case STATE_IDLE:
|
||||
case STATE_DRAG_ACTIVE:
|
||||
libinput_timer_cancel(&fsm.timer);
|
||||
switch (tp->edge_motion.state) {
|
||||
case EDGE_MOTION_STATE_IDLE:
|
||||
case EDGE_MOTION_STATE_DRAG_ACTIVE:
|
||||
libinput_timer_cancel(&tp->edge_motion.timer);
|
||||
tp->edge_motion.current_edge = EDGE_NONE;
|
||||
break;
|
||||
|
||||
case STATE_EDGE_MOTION:
|
||||
calculate_motion_vector(fsm.current_edge,
|
||||
&fsm.motion_dx,
|
||||
&fsm.motion_dy);
|
||||
fsm.last_motion_time = time;
|
||||
tp_edge_motion_handle_timeout(time, &fsm);
|
||||
case EDGE_MOTION_STATE_EDGE_MOTION:
|
||||
calculate_motion_vector(tp->edge_motion.current_edge,
|
||||
&tp->edge_motion.motion_dx,
|
||||
&tp->edge_motion.motion_dy);
|
||||
tp->edge_motion.last_motion_time = time;
|
||||
tp_edge_motion_handle_timeout(time, tp);
|
||||
break;
|
||||
}
|
||||
} else if (fsm.current_state == STATE_EDGE_MOTION &&
|
||||
detected_edge != fsm.current_edge) {
|
||||
fsm.current_edge = detected_edge;
|
||||
calculate_motion_vector(fsm.current_edge,
|
||||
&fsm.motion_dx,
|
||||
&fsm.motion_dy);
|
||||
} else if (tp->edge_motion.state == EDGE_MOTION_STATE_EDGE_MOTION &&
|
||||
detected_edge != tp->edge_motion.current_edge) {
|
||||
tp->edge_motion.current_edge = detected_edge;
|
||||
calculate_motion_vector(tp->edge_motion.current_edge,
|
||||
&tp->edge_motion.motion_dx,
|
||||
&tp->edge_motion.motion_dy);
|
||||
}
|
||||
|
||||
return (fsm.current_state == STATE_EDGE_MOTION);
|
||||
return (tp->edge_motion.state == EDGE_MOTION_STATE_EDGE_MOTION);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1293,7 +1293,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, usec_t time)
|
|||
}
|
||||
|
||||
/* Log 1-finger drag state changes */
|
||||
filter_motion = tp_edge_motion_handle_drag_state(tp, time);
|
||||
filter_motion |= tp_edge_motion_handle_drag_state(tp, time);
|
||||
|
||||
/**
|
||||
* In any state where motion exceeding the move threshold would
|
||||
|
|
@ -1597,7 +1597,6 @@ void
|
|||
tp_remove_tap(struct tp_dispatch *tp)
|
||||
{
|
||||
libinput_timer_cancel(&tp->tap.timer);
|
||||
tp_edge_motion_cleanup();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1960,6 +1960,7 @@ tp_interface_remove(struct evdev_dispatch *dispatch)
|
|||
tp_remove_buttons(tp);
|
||||
tp_remove_sendevents(tp);
|
||||
tp_remove_edge_scroll(tp);
|
||||
tp_remove_edge_motion(tp);
|
||||
tp_remove_gesture(tp);
|
||||
}
|
||||
|
||||
|
|
@ -3783,6 +3784,7 @@ tp_init(struct tp_dispatch *tp, struct evdev_device *device)
|
|||
tp_init_palmdetect(tp, device);
|
||||
tp_init_sendevents(tp, device);
|
||||
tp_init_scroll(tp, device);
|
||||
tp_init_edge_motion(tp);
|
||||
tp_init_gesture(tp);
|
||||
tp_init_thumb(tp);
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,12 @@ enum tp_tap_touch_state {
|
|||
TAP_TOUCH_STATE_DEAD, /**< exceeded motion/timeout */
|
||||
};
|
||||
|
||||
enum tp_edge_motion_state {
|
||||
EDGE_MOTION_STATE_IDLE,
|
||||
EDGE_MOTION_STATE_DRAG_ACTIVE,
|
||||
EDGE_MOTION_STATE_EDGE_MOTION,
|
||||
};
|
||||
|
||||
/* For edge scrolling, so we only care about right and bottom. For edge motion, we
|
||||
* require all four edges */
|
||||
enum tp_edge {
|
||||
|
|
@ -565,6 +571,21 @@ struct tp_dispatch {
|
|||
struct evdev_device *tablet_device;
|
||||
bool tablet_left_handed_state;
|
||||
} left_handed;
|
||||
|
||||
struct {
|
||||
enum tp_edge_motion_state state;
|
||||
|
||||
usec_t last_motion_time;
|
||||
|
||||
uint32_t current_edge;
|
||||
|
||||
double motion_dx;
|
||||
double motion_dy;
|
||||
|
||||
uint32_t continuous_motion_count;
|
||||
|
||||
struct libinput_timer timer;
|
||||
} edge_motion;
|
||||
};
|
||||
|
||||
static inline struct tp_dispatch *
|
||||
|
|
@ -726,11 +747,14 @@ tp_edge_scroll_touch_active(const struct tp_dispatch *tp, const struct tp_touch
|
|||
uint32_t
|
||||
tp_touch_get_edge(const struct tp_dispatch *tp, const struct tp_touch *t);
|
||||
|
||||
void
|
||||
tp_init_edge_motion(struct tp_dispatch *tp);
|
||||
|
||||
int
|
||||
tp_edge_motion_handle_drag_state(struct tp_dispatch *tp, usec_t time);
|
||||
|
||||
void
|
||||
tp_edge_motion_cleanup(void);
|
||||
tp_remove_edge_motion(struct tp_dispatch *tp);
|
||||
|
||||
void
|
||||
tp_init_gesture(struct tp_dispatch *tp);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue