mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-01-04 22:30:13 +01:00
evdev: add a rectangle to the touch arbitration
This enables us to specify the location that needs to be arbitrated, rather than just disabling the whole device altogether. This patch just adds the hooks, no implementation. This is internal API only, one backend can specify an area in mm which gets converted to device coordinates in the target device and arbitrated there. Right now, everything simply passes NULL. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
72560e031b
commit
f325ca921d
7 changed files with 126 additions and 21 deletions
|
|
@ -871,6 +871,21 @@ fallback_any_button_down(struct fallback_dispatch *dispatch,
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
fallback_arbitrate_touch(struct fallback_dispatch *dispatch,
|
||||
struct mt_slot *slot)
|
||||
{
|
||||
bool discard = false;
|
||||
|
||||
if (dispatch->arbitration.state == ARBITRATION_IGNORE_RECT &&
|
||||
point_in_rect(&slot->point, &dispatch->arbitration.rect)) {
|
||||
slot->palm_state = PALM_IS_PALM;
|
||||
discard = true;
|
||||
}
|
||||
|
||||
return discard;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
fallback_flush_mt_events(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
|
|
@ -900,10 +915,13 @@ fallback_flush_mt_events(struct fallback_dispatch *dispatch,
|
|||
} else if (slot->palm_state == PALM_NONE) {
|
||||
switch (slot->state) {
|
||||
case SLOT_STATE_BEGIN:
|
||||
sent = fallback_flush_mt_down(dispatch,
|
||||
device,
|
||||
i,
|
||||
time);
|
||||
if (!fallback_arbitrate_touch(dispatch,
|
||||
slot)) {
|
||||
sent = fallback_flush_mt_down(dispatch,
|
||||
device,
|
||||
i,
|
||||
time);
|
||||
}
|
||||
break;
|
||||
case SLOT_STATE_UPDATE:
|
||||
sent = fallback_flush_mt_motion(dispatch,
|
||||
|
|
@ -1044,12 +1062,16 @@ fallback_interface_process(struct evdev_dispatch *evdev_dispatch,
|
|||
static void
|
||||
cancel_touches(struct fallback_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
const struct device_coord_rect *rect,
|
||||
uint64_t time)
|
||||
{
|
||||
unsigned int idx;
|
||||
bool need_frame = false;
|
||||
|
||||
need_frame = fallback_flush_st_cancel(dispatch, device, time);
|
||||
if (!rect || point_in_rect(&dispatch->abs.point, rect))
|
||||
need_frame = fallback_flush_st_cancel(dispatch,
|
||||
device,
|
||||
time);
|
||||
|
||||
for (idx = 0; idx < dispatch->mt.slots_len; idx++) {
|
||||
struct mt_slot *slot = &dispatch->mt.slots[idx];
|
||||
|
|
@ -1057,7 +1079,8 @@ cancel_touches(struct fallback_dispatch *dispatch,
|
|||
if (slot->seat_slot == -1)
|
||||
continue;
|
||||
|
||||
if (fallback_flush_mt_cancel(dispatch, device, idx, time))
|
||||
if ((!rect || point_in_rect(&slot->point, rect)) &&
|
||||
fallback_flush_mt_cancel(dispatch, device, idx, time))
|
||||
need_frame = true;
|
||||
}
|
||||
|
||||
|
|
@ -1125,7 +1148,7 @@ fallback_return_to_neutral_state(struct fallback_dispatch *dispatch,
|
|||
if ((time = libinput_now(libinput)) == 0)
|
||||
return;
|
||||
|
||||
cancel_touches(dispatch, device, time);
|
||||
cancel_touches(dispatch, device, NULL, time);
|
||||
release_pressed_keys(dispatch, device, time);
|
||||
memset(dispatch->hw_key_mask, 0, sizeof(dispatch->hw_key_mask));
|
||||
memset(dispatch->hw_key_mask, 0, sizeof(dispatch->last_hw_key_mask));
|
||||
|
|
@ -1199,9 +1222,11 @@ static void
|
|||
fallback_interface_toggle_touch(struct evdev_dispatch *evdev_dispatch,
|
||||
struct evdev_device *device,
|
||||
enum evdev_arbitration_state which,
|
||||
const struct phys_rect *phys_rect,
|
||||
uint64_t time)
|
||||
{
|
||||
struct fallback_dispatch *dispatch = fallback_dispatch(evdev_dispatch);
|
||||
struct device_coord_rect rect = {0};
|
||||
|
||||
if (which == dispatch->arbitration.state)
|
||||
return;
|
||||
|
|
@ -1218,6 +1243,12 @@ fallback_interface_toggle_touch(struct evdev_dispatch *evdev_dispatch,
|
|||
libinput_timer_set(&dispatch->arbitration.arbitration_timer,
|
||||
time + ms2us(90));
|
||||
break;
|
||||
case ARBITRATION_IGNORE_RECT:
|
||||
assert(phys_rect);
|
||||
rect = evdev_phys_rect_to_units(device, phys_rect);
|
||||
cancel_touches(dispatch, device, &rect, time);
|
||||
dispatch->arbitration.rect = rect;
|
||||
break;
|
||||
case ARBITRATION_IGNORE_ALL:
|
||||
libinput_timer_cancel(&dispatch->arbitration.arbitration_timer);
|
||||
fallback_return_to_neutral_state(dispatch, device);
|
||||
|
|
@ -1421,7 +1452,8 @@ struct evdev_dispatch_interface fallback_interface = {
|
|||
.device_suspended = fallback_interface_device_removed, /* treat as remove */
|
||||
.device_resumed = fallback_interface_device_added, /* treat as add */
|
||||
.post_added = fallback_interface_sync_initial_state,
|
||||
.toggle_touch = fallback_interface_toggle_touch,
|
||||
.touch_arbitration_toggle = fallback_interface_toggle_touch,
|
||||
.touch_arbitration_update_rect = NULL,
|
||||
.get_switch_state = fallback_interface_get_switch_state,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@ struct fallback_dispatch {
|
|||
struct {
|
||||
enum evdev_arbitration_state state;
|
||||
bool in_arbitration;
|
||||
struct device_coord_rect rect;
|
||||
struct libinput_timer arbitration_timer;
|
||||
} arbitration;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2693,6 +2693,7 @@ static void
|
|||
tp_interface_toggle_touch(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
enum evdev_arbitration_state which,
|
||||
const struct phys_rect *rect,
|
||||
uint64_t time)
|
||||
{
|
||||
struct tp_dispatch *tp = tp_dispatch(dispatch);
|
||||
|
|
@ -2702,6 +2703,7 @@ tp_interface_toggle_touch(struct evdev_dispatch *dispatch,
|
|||
|
||||
switch (which) {
|
||||
case ARBITRATION_IGNORE_ALL:
|
||||
case ARBITRATION_IGNORE_RECT:
|
||||
libinput_timer_cancel(&tp->arbitration.arbitration_timer);
|
||||
tp_clear_state(tp);
|
||||
tp->arbitration.state = which;
|
||||
|
|
@ -2730,7 +2732,8 @@ static struct evdev_dispatch_interface tp_interface = {
|
|||
.device_suspended = tp_interface_device_removed, /* treat as remove */
|
||||
.device_resumed = tp_interface_device_added, /* treat as add */
|
||||
.post_added = NULL,
|
||||
.toggle_touch = tp_interface_toggle_touch,
|
||||
.touch_arbitration_toggle = tp_interface_toggle_touch,
|
||||
.touch_arbitration_update_rect = NULL,
|
||||
.get_switch_state = NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -518,7 +518,8 @@ static struct evdev_dispatch_interface pad_interface = {
|
|||
.device_suspended = NULL,
|
||||
.device_resumed = NULL,
|
||||
.post_added = NULL,
|
||||
.toggle_touch = NULL,
|
||||
.touch_arbitration_toggle = NULL,
|
||||
.touch_arbitration_update_rect = NULL,
|
||||
.get_switch_state = NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1634,11 +1634,12 @@ tablet_set_touch_device_enabled(struct evdev_device *touch_device,
|
|||
which = ARBITRATION_IGNORE_ALL;
|
||||
|
||||
dispatch = touch_device->dispatch;
|
||||
if (dispatch->interface->toggle_touch)
|
||||
dispatch->interface->toggle_touch(dispatch,
|
||||
touch_device,
|
||||
which,
|
||||
time);
|
||||
if (dispatch->interface->touch_arbitration_toggle)
|
||||
dispatch->interface->touch_arbitration_toggle(dispatch,
|
||||
touch_device,
|
||||
which,
|
||||
NULL,
|
||||
time);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -1941,7 +1942,8 @@ static struct evdev_dispatch_interface tablet_interface = {
|
|||
.device_suspended = NULL,
|
||||
.device_resumed = NULL,
|
||||
.post_added = tablet_check_initial_proximity,
|
||||
.toggle_touch = NULL,
|
||||
.touch_arbitration_toggle = NULL,
|
||||
.touch_arbitration_update_rect = NULL,
|
||||
.get_switch_state = NULL,
|
||||
};
|
||||
|
||||
|
|
|
|||
49
src/evdev.h
49
src/evdev.h
|
|
@ -147,6 +147,7 @@ enum evdev_debounce_state {
|
|||
enum evdev_arbitration_state {
|
||||
ARBITRATION_NOT_ACTIVE,
|
||||
ARBITRATION_IGNORE_ALL,
|
||||
ARBITRATION_IGNORE_RECT,
|
||||
};
|
||||
|
||||
struct evdev_device {
|
||||
|
|
@ -303,11 +304,22 @@ struct evdev_dispatch_interface {
|
|||
struct evdev_dispatch *dispatch);
|
||||
|
||||
/* For touch arbitration, called on the device that should
|
||||
* enable/disable touch capabilities */
|
||||
void (*toggle_touch)(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
enum evdev_arbitration_state which,
|
||||
uint64_t now);
|
||||
* enable/disable touch capabilities.
|
||||
*/
|
||||
void (*touch_arbitration_toggle)(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
enum evdev_arbitration_state which,
|
||||
const struct phys_rect *rect, /* may be NULL */
|
||||
uint64_t now);
|
||||
|
||||
/* Called when touch arbitration is on, updates the area where touch
|
||||
* arbitration should apply.
|
||||
*/
|
||||
void (*touch_arbitration_update_rect)(struct evdev_dispatch *dispatch,
|
||||
struct evdev_device *device,
|
||||
const struct phys_rect *rect,
|
||||
uint64_t now);
|
||||
|
||||
|
||||
/* Return the state of the given switch */
|
||||
enum libinput_switch_state
|
||||
|
|
@ -880,6 +892,33 @@ evdev_device_mm_to_units(const struct evdev_device *device,
|
|||
return units;
|
||||
}
|
||||
|
||||
static inline struct device_coord_rect
|
||||
evdev_phys_rect_to_units(const struct evdev_device *device,
|
||||
const struct phys_rect *mm)
|
||||
{
|
||||
struct device_coord_rect units = {0};
|
||||
const struct input_absinfo *absx, *absy;
|
||||
|
||||
if (device->abs.absinfo_x == NULL ||
|
||||
device->abs.absinfo_y == NULL) {
|
||||
log_bug_libinput(evdev_libinput_context(device),
|
||||
"%s: is not an abs device\n",
|
||||
device->devname);
|
||||
return units;
|
||||
}
|
||||
|
||||
absx = device->abs.absinfo_x;
|
||||
absy = device->abs.absinfo_y;
|
||||
|
||||
units.x = mm->x * absx->resolution + absx->minimum;
|
||||
units.y = mm->y * absy->resolution + absy->minimum;
|
||||
units.w = mm->w * absx->resolution;
|
||||
units.h = mm->h * absy->resolution;
|
||||
|
||||
return units;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
evdev_device_init_abs_range_warnings(struct evdev_device *device)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -95,6 +95,18 @@ struct phys_coords {
|
|||
double y;
|
||||
};
|
||||
|
||||
/* A rectangle in mm, x/y is the top-left corner */
|
||||
struct phys_rect {
|
||||
double x, y;
|
||||
double w, h;
|
||||
};
|
||||
|
||||
/* A rectangle in device coordinates, x/y is the top-left corner */
|
||||
struct device_coord_rect {
|
||||
int x, y;
|
||||
int w, h;
|
||||
};
|
||||
|
||||
/* A pair of tilt flags */
|
||||
struct wheel_tilt_flags {
|
||||
bool vertical, horizontal;
|
||||
|
|
@ -810,4 +822,19 @@ device_float_get_direction(const struct device_float_coords coords)
|
|||
{
|
||||
return xy_get_direction(coords.x, coords.y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the point is within the given rectangle, including the
|
||||
* left edge but excluding the right edge.
|
||||
*/
|
||||
static inline bool
|
||||
point_in_rect(const struct device_coords *point,
|
||||
const struct device_coord_rect *rect)
|
||||
{
|
||||
return (point->x >= rect->x &&
|
||||
point->x < rect->x + rect->w &&
|
||||
point->y >= rect->y &&
|
||||
point->y < rect->y + rect->h);
|
||||
}
|
||||
|
||||
#endif /* LIBINPUT_PRIVATE_H */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue