tablet: add evdev/libinput functions for tablet scroll

This commit is contained in:
Louis Goyard 2024-03-12 00:08:21 +09:00
parent e335f43971
commit 27a66310fc
6 changed files with 326 additions and 0 deletions

View file

@ -499,6 +499,27 @@ evdev_notify_axis_continous(struct evdev_device *device,
&delta);
}
void
evdev_notify_axis_tablet_tool_continous(struct evdev_device *device,
uint64_t time,
struct libinput_tablet_tool *tool,
uint32_t scroll_axes,
const struct normalized_coords *delta_in)
{
struct normalized_coords delta = *delta_in;
if (device->scroll.natural_scrolling_enabled) {
delta.x *= -1;
delta.y *= -1;
}
tablet_tool_notify_axis_continuous(&device->base,
time,
tool,
scroll_axes,
&delta);
}
static void
evdev_tag_external_mouse(struct evdev_device *device,
struct udev_device *udev_device)
@ -2932,6 +2953,114 @@ evdev_stop_scroll(struct evdev_device *device,
device->scroll.direction = 0;
}
void
evdev_post_tablet_tool_scroll(struct evdev_device *device,
uint64_t time,
struct libinput_tablet_tool *tool,
enum libinput_tablet_tool_axis_source source,
const struct normalized_coords *delta)
{
const struct normalized_coords *trigger;
struct normalized_coords event;
if (!evdev_is_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
device->scroll.buildup.y += delta->y;
if (!evdev_is_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
device->scroll.buildup.x += delta->x;
trigger = &device->scroll.buildup;
/* If we're not scrolling yet, use a distance trigger: moving
past a certain distance starts scrolling */
if (!evdev_is_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) &&
!evdev_is_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
if (fabs(trigger->y) >= device->scroll.threshold)
evdev_start_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
if (fabs(trigger->x) >= device->scroll.threshold)
evdev_start_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
/* We're already scrolling in one direction. Require some
trigger speed to start scrolling in the other direction */
} else if (!evdev_is_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
if (fabs(delta->y) >= device->scroll.direction_lock_threshold)
evdev_start_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
} else if (!evdev_is_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
if (fabs(delta->x) >= device->scroll.direction_lock_threshold)
evdev_start_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
}
event = *delta;
/* We use the trigger to enable, but the delta from this event for
* the actual scroll movement. Otherwise we get a jump once
* scrolling engages */
if (!evdev_is_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
event.y = 0.0;
if (!evdev_is_scrolling(device,
LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL))
event.x = 0.0;
if (!normalized_is_zero(event)) {
uint32_t scroll_axes = device->scroll.direction;
if (event.y == 0.0)
scroll_axes &= ~bit(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
if (event.x == 0.0)
scroll_axes &= ~bit(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
switch (source) {
case LIBINPUT_TABLET_TOOL_AXIS_SOURCE_CONTINUOUS:
evdev_notify_axis_tablet_tool_continous(device, time, tool, scroll_axes, &event);
break;
default:
evdev_log_bug_libinput(device,
"Posting invalid scroll source %d\n",
source);
break;
}
}
}
void
evdev_stop_tablet_tool_scroll(struct evdev_device *device,
uint64_t time,
enum libinput_tablet_tool_axis_source source)
{
const struct normalized_coords zero = { 0.0, 0.0 };
/* terminate scrolling with a zero scroll event */
if (device->scroll.direction != 0) {
switch (source) {
case LIBINPUT_TABLET_TOOL_AXIS_SOURCE_CONTINUOUS:
pointer_notify_axis_continuous(&device->base,
time,
device->scroll.direction,
&zero);
break;
default:
evdev_log_bug_libinput(device,
"Stopping invalid scroll source %d\n",
source);
break;
}
}
device->scroll.buildup.x = 0;
device->scroll.buildup.y = 0;
device->scroll.direction = 0;
}
void
evdev_notify_suspended_device(struct evdev_device *device)
{

View file

@ -568,6 +568,11 @@ evdev_pointer_notify_button(struct evdev_device *device,
unsigned int button,
enum libinput_button_state state);
void
evdev_tablet_tool_notify_button(struct evdev_device *device,
uint64_t time,
unsigned int button,
enum libinput_button_state state);
void
evdev_pointer_notify_physical_button(struct evdev_device *device,
uint64_t time,
int button,
@ -612,6 +617,13 @@ evdev_notify_axis_continous(struct evdev_device *device,
uint32_t axes,
const struct normalized_coords *delta_in);
void
evdev_notify_axis_tablet_tool_continous(struct evdev_device *device,
uint64_t time,
struct libinput_tablet_tool *tool,
uint32_t scroll_axes,
const struct normalized_coords *delta_in);
void
evdev_post_scroll(struct evdev_device *device,
uint64_t time,
@ -623,6 +635,18 @@ evdev_stop_scroll(struct evdev_device *device,
uint64_t time,
enum libinput_pointer_axis_source source);
void
evdev_post_tablet_tool_scroll(struct evdev_device *device,
uint64_t time,
struct libinput_tablet_tool *tool,
enum libinput_tablet_tool_axis_source source,
const struct normalized_coords *delta);
void
evdev_stop_tablet_tool_scroll(struct evdev_device *device,
uint64_t time,
enum libinput_tablet_tool_axis_source source);
void
evdev_device_remove(struct evdev_device *device);

View file

@ -672,6 +672,13 @@ pointer_notify_axis_continuous(struct libinput_device *device,
uint32_t axes,
const struct normalized_coords *delta);
void
tablet_tool_notify_axis_continuous(struct libinput_device *device,
uint64_t time,
struct libinput_tablet_tool *tool,
uint32_t scroll_axes,
const struct normalized_coords *delta);
void
pointer_notify_axis_legacy_wheel(struct libinput_device *device,
uint64_t time,
@ -782,6 +789,15 @@ tablet_notify_tip(struct libinput_device *device,
unsigned char *changed_axes,
const struct tablet_axes *axes);
void
tablet_tool_notify_button(struct libinput_device *device,
uint64_t time,
struct libinput_tablet_tool *tool,
enum libinput_tablet_tool_tip_state tip_state,
const struct tablet_axes *axes,
int32_t button,
enum libinput_button_state state);
void
tablet_notify_button(struct libinput_device *device,
uint64_t time,

View file

@ -58,6 +58,7 @@ ASSERT_INT_SIZE(enum libinput_pointer_axis);
ASSERT_INT_SIZE(enum libinput_pointer_axis_source);
ASSERT_INT_SIZE(enum libinput_tablet_pad_ring_axis_source);
ASSERT_INT_SIZE(enum libinput_tablet_pad_strip_axis_source);
ASSERT_INT_SIZE(enum libinput_tablet_tool_axis_source);
ASSERT_INT_SIZE(enum libinput_tablet_tool_type);
ASSERT_INT_SIZE(enum libinput_tablet_tool_proximity_state);
ASSERT_INT_SIZE(enum libinput_tablet_tool_tip_state);
@ -214,11 +215,15 @@ struct libinput_event_tablet_tool {
enum libinput_button_state state;
uint32_t seat_button_count;
uint64_t time;
struct normalized_coords delta;
struct tablet_axes axes;
unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)];
struct libinput_tablet_tool *tool;
enum libinput_tablet_tool_proximity_state proximity_state;
enum libinput_tablet_tool_tip_state tip_state;
enum libinput_tablet_tool_axis_source source;
uint32_t scroll_axes;
};
struct libinput_event_tablet_pad {
@ -728,6 +733,24 @@ libinput_event_pointer_has_axis(struct libinput_event_pointer *event,
return 0;
}
LIBINPUT_EXPORT int
libinput_event_tablet_tool_has_axis(struct libinput_event_tablet_tool *event,
enum libinput_pointer_axis axis)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
0,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
switch (axis) {
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
return !!(event->scroll_axes & bit(axis));
}
return 0;
}
LIBINPUT_EXPORT double
libinput_event_pointer_get_axis_value(struct libinput_event_pointer *event,
enum libinput_pointer_axis axis)
@ -812,6 +835,33 @@ libinput_event_pointer_get_scroll_value(struct libinput_event_pointer *event,
return value;
}
LIBINPUT_EXPORT double
libinput_event_tablet_tool_get_scroll_value(struct libinput_event_tablet_tool *event,
enum libinput_pointer_axis axis)
{
struct libinput *libinput = event->base.device->seat->libinput;
double value = 0;
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
0.0,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
if (!libinput_event_tablet_tool_has_axis(event, axis)) {
log_bug_client(libinput, "value requested for unset axis\n");
} else {
switch (axis) {
case LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL:
value = event->delta.x;
break;
case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL:
value = event->delta.y;
break;
}
}
return value;
}
LIBINPUT_EXPORT double
libinput_event_pointer_get_scroll_value_v120(struct libinput_event_pointer *event,
enum libinput_pointer_axis axis)
@ -2552,6 +2602,43 @@ pointer_notify_button(struct libinput_device *device,
&button_event->base);
}
void
tablet_tool_notify_button(struct libinput_device *device,
uint64_t time,
struct libinput_tablet_tool *tool,
enum libinput_tablet_tool_tip_state tip_state,
const struct tablet_axes *axes,
int32_t button,
enum libinput_button_state state)
{
struct libinput_event_tablet_tool *button_event;
int32_t seat_button_count;
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL))
return;
button_event = zalloc(sizeof *button_event);
seat_button_count = update_seat_button_count(device->seat,
button,
state);
*button_event = (struct libinput_event_tablet_tool) {
.time = time,
.tool = libinput_tablet_tool_ref(tool),
.button = button,
.state = state,
.seat_button_count = seat_button_count,
.proximity_state = LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN,
.tip_state = tip_state,
.axes = *axes,
};
post_device_event(device, time,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
&button_event->base);
}
void
pointer_notify_axis_finger(struct libinput_device *device,
uint64_t time,
@ -2620,6 +2707,33 @@ pointer_notify_axis_continuous(struct libinput_device *device,
&axis_event_legacy->base);
}
void
tablet_tool_notify_axis_continuous(struct libinput_device *device,
uint64_t time,
struct libinput_tablet_tool *tool,
uint32_t scroll_axes,
const struct normalized_coords *delta)
{
struct libinput_event_tablet_tool *axis_event;
if (!device_has_cap(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL))
return;
axis_event = zalloc(sizeof *axis_event);
*axis_event = (struct libinput_event_tablet_tool) {
.time = time,
.tool = libinput_tablet_tool_ref(tool),
.delta = *delta,
.source = LIBINPUT_TABLET_TOOL_AXIS_SOURCE_CONTINUOUS,
.scroll_axes = scroll_axes,
};
post_device_event(device, time,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS,
&axis_event->base);
}
void
pointer_notify_axis_legacy_wheel(struct libinput_device *device,
uint64_t time,
@ -3771,6 +3885,17 @@ libinput_event_tablet_pad_get_strip_source(struct libinput_event_tablet_pad *eve
return event->strip.source;
}
LIBINPUT_EXPORT enum libinput_tablet_tool_axis_source
libinput_event_tablet_tool_get_axis_source(struct libinput_event_tablet_tool *event)
{
require_event_type(libinput_event_get_context(&event->base),
event->base.type,
LIBINPUT_TABLET_TOOL_AXIS_SOURCE_CONTINUOUS,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->source;
}
LIBINPUT_EXPORT uint32_t
libinput_event_tablet_pad_get_button_number(struct libinput_event_tablet_pad *event)
{

View file

@ -321,6 +321,24 @@ enum libinput_tablet_pad_strip_axis_source {
LIBINPUT_TABLET_PAD_STRIP_SOURCE_FINGER,
};
/**
* @ingroup event_tablet_pad
*
* The source for a @ref LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS event.
* See libinput_event_tablet_tool_get_axis_source() for details.
*
* @since 1.3
*/
enum libinput_tablet_tool_axis_source {
LIBINPUT_TABLET_TOOL_AXIS_SOURCE_UNKNOWN = 1,
/**
* The event is caused by the movement of the tool
* while the scroll button is being held down
*/
LIBINPUT_TABLET_TOOL_AXIS_SOURCE_CONTINUOUS,
};
/**
* @ingroup device
*
@ -1542,6 +1560,10 @@ int
libinput_event_pointer_has_axis(struct libinput_event_pointer *event,
enum libinput_pointer_axis axis);
int
libinput_event_tablet_tool_has_axis(struct libinput_event_tablet_tool *event,
enum libinput_pointer_axis axis);
/**
* @ingroup event_pointer
*
@ -1700,6 +1722,10 @@ double
libinput_event_pointer_get_scroll_value(struct libinput_event_pointer *event,
enum libinput_pointer_axis axis);
double
libinput_event_tablet_tool_get_scroll_value(struct libinput_event_tablet_tool *event,
enum libinput_pointer_axis axis);
/**
* @ingroup event_pointer
*
@ -3269,6 +3295,9 @@ libinput_event_tablet_pad_get_strip_number(struct libinput_event_tablet_pad *eve
enum libinput_tablet_pad_strip_axis_source
libinput_event_tablet_pad_get_strip_source(struct libinput_event_tablet_pad *event);
enum libinput_tablet_tool_axis_source
libinput_event_tablet_tool_get_axis_source(struct libinput_event_tablet_tool *event);
/**
* @ingroup event_tablet_pad
*

View file

@ -346,4 +346,7 @@ LIBINPUT_1.26 {
libinput_tablet_tool_config_pressure_range_get_maximum;
libinput_tablet_tool_config_pressure_range_get_default_minimum;
libinput_tablet_tool_config_pressure_range_get_default_maximum;
libinput_event_tablet_tool_has_axis;
libinput_event_tablet_tool_get_scroll_value;
libinput_event_tablet_tool_get_axis_source;
} LIBINPUT_1.23;