evdev: introduce a touch arbitration enum

This enables us to change the types of touch arbitration, with the focus on
allowing location-based touch arbitration as well as the more generic "disable
everything".

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2018-09-19 12:02:51 +10:00
parent 794bff8af0
commit d3595908e5
6 changed files with 40 additions and 25 deletions

View file

@ -1196,20 +1196,16 @@ fallback_interface_sync_initial_state(struct evdev_device *device,
static void static void
fallback_interface_toggle_touch(struct evdev_dispatch *evdev_dispatch, fallback_interface_toggle_touch(struct evdev_dispatch *evdev_dispatch,
struct evdev_device *device, struct evdev_device *device,
bool enable, enum evdev_arbitration_state which,
uint64_t time) uint64_t time)
{ {
struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch); struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch);
bool ignore_events = !enable;
if (ignore_events == dispatch->arbitration.ignore_events) if (which == dispatch->arbitration.state)
return; return;
if (ignore_events) { switch (which) {
libinput_timer_cancel(&dispatch->arbitration.arbitration_timer); case ARBITRATION_NOT_ACTIVE:
fallback_return_to_neutral_state(dispatch, device);
dispatch->arbitration.in_arbitration = true;
} else {
/* if in-kernel arbitration is in use and there is a touch /* if in-kernel arbitration is in use and there is a touch
* and a pen in proximity, lifting the pen out of proximity * and a pen in proximity, lifting the pen out of proximity
* causes a touch begin for the touch. On a hand-lift the * causes a touch begin for the touch. On a hand-lift the
@ -1219,9 +1215,15 @@ fallback_interface_toggle_touch(struct evdev_dispatch *evdev_dispatch,
* event is caught as palm touch. */ * event is caught as palm touch. */
libinput_timer_set(&dispatch->arbitration.arbitration_timer, libinput_timer_set(&dispatch->arbitration.arbitration_timer,
time + ms2us(90)); time + ms2us(90));
break;
case ARBITRATION_IGNORE_ALL:
libinput_timer_cancel(&dispatch->arbitration.arbitration_timer);
fallback_return_to_neutral_state(dispatch, device);
dispatch->arbitration.in_arbitration = true;
break;
} }
dispatch->arbitration.ignore_events = ignore_events; dispatch->arbitration.state = which;
} }
static void static void

View file

@ -141,11 +141,11 @@ struct fallback_dispatch {
struct list paired_keyboard_list; struct list paired_keyboard_list;
} lid; } lid;
/* pen/touch arbitration has a delayed state, if ignore_events is /* pen/touch arbitration has a delayed state,
* true we want to ignore events, in_arbitration actually filters. * in_arbitration is what decides when to filter.
*/ */
struct { struct {
bool ignore_events; enum evdev_arbitration_state state;
bool in_arbitration; bool in_arbitration;
struct libinput_timer arbitration_timer; struct libinput_timer arbitration_timer;
} arbitration; } arbitration;

View file

@ -1028,7 +1028,7 @@ tp_palm_detect_arbitration_triggered(struct tp_dispatch *tp,
struct tp_touch *t, struct tp_touch *t,
uint64_t time) uint64_t time)
{ {
if (!tp->arbitration.in_arbitration) if (tp->arbitration.state == ARBITRATION_NOT_ACTIVE)
return false; return false;
t->palm.state = PALM_ARBITRATION; t->palm.state = PALM_ARBITRATION;
@ -2685,27 +2685,28 @@ tp_arbitration_timeout(uint64_t now, void *data)
{ {
struct tp_dispatch *tp = data; struct tp_dispatch *tp = data;
if (tp->arbitration.in_arbitration) if (tp->arbitration.state != ARBITRATION_NOT_ACTIVE)
tp->arbitration.in_arbitration = false; tp->arbitration.state = ARBITRATION_NOT_ACTIVE;
} }
static void static void
tp_interface_toggle_touch(struct evdev_dispatch *dispatch, tp_interface_toggle_touch(struct evdev_dispatch *dispatch,
struct evdev_device *device, struct evdev_device *device,
bool enable, enum evdev_arbitration_state which,
uint64_t time) uint64_t time)
{ {
struct tp_dispatch *tp = tp_dispatch(dispatch); struct tp_dispatch *tp = tp_dispatch(dispatch);
bool arbitrate = !enable;
if (arbitrate == tp->arbitration.in_arbitration) if (which == tp->arbitration.state)
return; return;
if (arbitrate) { switch (which) {
case ARBITRATION_IGNORE_ALL:
libinput_timer_cancel(&tp->arbitration.arbitration_timer); libinput_timer_cancel(&tp->arbitration.arbitration_timer);
tp_clear_state(tp); tp_clear_state(tp);
tp->arbitration.in_arbitration = true; tp->arbitration.state = which;
} else { break;
case ARBITRATION_NOT_ACTIVE:
/* if in-kernel arbitration is in use and there is a touch /* if in-kernel arbitration is in use and there is a touch
* and a pen in proximity, lifting the pen out of proximity * and a pen in proximity, lifting the pen out of proximity
* causes a touch begin for the touch. On a hand-lift the * causes a touch begin for the touch. On a hand-lift the
@ -2715,6 +2716,7 @@ tp_interface_toggle_touch(struct evdev_dispatch *dispatch,
* event is caught as palm touch. */ * event is caught as palm touch. */
libinput_timer_set(&tp->arbitration.arbitration_timer, libinput_timer_set(&tp->arbitration.arbitration_timer,
time + ms2us(90)); time + ms2us(90));
break;
} }
} }
@ -3231,7 +3233,7 @@ tp_init_palmdetect_arbitration(struct tp_dispatch *tp,
tp_libinput_context(tp), tp_libinput_context(tp),
timer_name, timer_name,
tp_arbitration_timeout, tp); tp_arbitration_timeout, tp);
tp->arbitration.in_arbitration = false; tp->arbitration.state = ARBITRATION_NOT_ACTIVE;
} }
static void static void

View file

@ -270,7 +270,7 @@ struct tp_dispatch {
/* pen/touch arbitration */ /* pen/touch arbitration */
struct { struct {
bool in_arbitration; enum evdev_arbitration_state state;
struct libinput_timer arbitration_timer; struct libinput_timer arbitration_timer;
} arbitration; } arbitration;

View file

@ -1623,15 +1623,21 @@ tablet_set_touch_device_enabled(struct evdev_device *touch_device,
uint64_t time) uint64_t time)
{ {
struct evdev_dispatch *dispatch; struct evdev_dispatch *dispatch;
enum evdev_arbitration_state which;
if (touch_device == NULL) if (touch_device == NULL)
return; return;
if (enable)
which = ARBITRATION_NOT_ACTIVE;
else
which = ARBITRATION_IGNORE_ALL;
dispatch = touch_device->dispatch; dispatch = touch_device->dispatch;
if (dispatch->interface->toggle_touch) if (dispatch->interface->toggle_touch)
dispatch->interface->toggle_touch(dispatch, dispatch->interface->toggle_touch(dispatch,
touch_device, touch_device,
enable, which,
time); time);
} }

View file

@ -144,6 +144,11 @@ enum evdev_debounce_state {
DEBOUNCE_ACTIVE, DEBOUNCE_ACTIVE,
}; };
enum evdev_arbitration_state {
ARBITRATION_NOT_ACTIVE,
ARBITRATION_IGNORE_ALL,
};
struct evdev_device { struct evdev_device {
struct libinput_device base; struct libinput_device base;
@ -301,7 +306,7 @@ struct evdev_dispatch_interface {
* enable/disable touch capabilities */ * enable/disable touch capabilities */
void (*toggle_touch)(struct evdev_dispatch *dispatch, void (*toggle_touch)(struct evdev_dispatch *dispatch,
struct evdev_device *device, struct evdev_device *device,
bool enable, enum evdev_arbitration_state which,
uint64_t now); uint64_t now);
/* Return the state of the given switch */ /* Return the state of the given switch */