Merge branch 'tablet-tool-scroll' into 'main'

Draft: Tablet tool scroll

Closes #729

See merge request libinput/libinput!981
This commit is contained in:
Louis Goyard 2024-10-31 20:31:38 +00:00
commit a4b1878cf3
12 changed files with 688 additions and 49 deletions

View file

@ -1310,6 +1310,171 @@ tablet_get_tool(struct tablet_dispatch *tablet,
return tool;
}
static struct libinput_tablet_tool *
tablet_get_current_tool(struct tablet_dispatch *tablet)
{
if (tablet->current_tool.type == LIBINPUT_TOOL_NONE)
return NULL;
return tablet_get_tool(tablet,
tablet->current_tool.type,
tablet->current_tool.id,
tablet->current_tool.serial);
}
static void
evdev_tablet_stop_scroll(struct evdev_device *device,
struct libinput_tablet_tool* tool,
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:
evdev_notify_axis_tablet_tool_continous(device,
time,
tool,
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;
}
#define DEFAULT_BUTTON_SCROLL_TIMEOUT ms2us(200)
static inline void
tablet_notify_button_scroll(struct evdev_device *device,
struct tablet_dispatch *tablet,
uint64_t time,
bool is_press)
{
if (is_press) {
device->scroll.button_scroll_state = BUTTONSCROLL_BUTTON_DOWN;
enum timer_flags flags = TIMER_FLAG_NONE;
libinput_timer_set_flags(&device->scroll.timer,
time + DEFAULT_BUTTON_SCROLL_TIMEOUT,
flags);
device->scroll.button_down_time = time;
evdev_log_debug(device, "btnscroll: down\n");
} else {
struct libinput_tablet_tool *tool;
tool = tablet_get_current_tool(tablet);
if (!tool)
return; /* OOM */
libinput_timer_cancel(&device->scroll.timer);
switch(device->scroll.button_scroll_state) {
case BUTTONSCROLL_IDLE:
evdev_log_bug_libinput(device,
"invalid state IDLE for button up\n");
break;
case BUTTONSCROLL_BUTTON_DOWN:
case BUTTONSCROLL_READY:
evdev_log_debug(device, "btnscroll: cancel\n");
enum libinput_tablet_tool_tip_state tip_state;
if (tablet_has_status(tablet, TABLET_TOOL_IN_CONTACT))
tip_state = LIBINPUT_TABLET_TOOL_TIP_DOWN;
else
tip_state = LIBINPUT_TABLET_TOOL_TIP_UP;
/* If the button is released quickly enough or
* without scroll events, emit the
* button press/release events. */
tablet_notify_button(&device->base,
device->scroll.button_down_time,
tool,
tip_state,
&tablet->axes,
device->scroll.button,
LIBINPUT_BUTTON_STATE_PRESSED);
tablet_notify_button(&device->base,
time,
tool,
tip_state,
&tablet->axes,
device->scroll.button,
LIBINPUT_BUTTON_STATE_RELEASED);
break;
case BUTTONSCROLL_SCROLLING:
evdev_log_debug(device, "btnscroll: up\n");
evdev_tablet_stop_scroll(device, tool, time,
LIBINPUT_TABLET_TOOL_AXIS_SOURCE_CONTINUOUS);
break;
}
device->scroll.button_scroll_state = BUTTONSCROLL_IDLE;
}
}
#undef DEFAULT_BUTTON_SCROLL_TIMEOUT
#define __SIGN(x) ((x > 0) - (x < 0))
#define TABLET_TOOL_SCROLL_MINIMUM 2
#define TABLET_TOOL_SCROLL_REDUCER 8
static inline bool
post_button_scroll(struct evdev_device *device,
struct tablet_dispatch *tablet,
uint64_t time)
{
if (device->scroll.method != LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN)
return false;
switch(device->scroll.button_scroll_state) {
case BUTTONSCROLL_IDLE:
return false;
case BUTTONSCROLL_BUTTON_DOWN:
/* if the button is down but scroll is not active, we're within the
timeout where we swallow motion events but don't post
scroll buttons */
evdev_log_debug(device, "btnscroll: discarding\n");
return true;
case BUTTONSCROLL_READY:
device->scroll.button_scroll_state = BUTTONSCROLL_SCROLLING;
_fallthrough_;
case BUTTONSCROLL_SCROLLING:
{
struct normalized_coords normalized = { tablet->current_value[1] - tablet->prev_value[1] , tablet->current_value[2] - tablet->prev_value[2] };
normalized.x = normalized.x / TABLET_TOOL_SCROLL_REDUCER;
normalized.y = normalized.y / TABLET_TOOL_SCROLL_REDUCER;
if (fabs(normalized.x) < TABLET_TOOL_SCROLL_MINIMUM)
normalized.x = 0;
else
normalized.x -= __SIGN(normalized.x)*(TABLET_TOOL_SCROLL_MINIMUM-1);
if (fabs(normalized.y) < TABLET_TOOL_SCROLL_MINIMUM)
normalized.y = 0;
else
normalized.y -= __SIGN(normalized.y)*(TABLET_TOOL_SCROLL_MINIMUM-1);
evdev_post_tablet_tool_scroll(device, time,
tablet_get_current_tool(tablet),
LIBINPUT_TABLET_TOOL_AXIS_SOURCE_CONTINUOUS,
&normalized);
}
return true;
}
assert(!"invalid scroll button state");
}
#undef TABLET_TOOL_SCROLL_REDUCER
#undef TABLET_TOOL_SCROLL_MINIMUM
#undef __SIGN
static void
tablet_notify_button_mask(struct tablet_dispatch *tablet,
struct evdev_device *device,
@ -1332,6 +1497,11 @@ tablet_notify_button_mask(struct tablet_dispatch *tablet,
if (!bit_is_set(buttons->bits, i))
continue;
if (device->scroll.method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN && i == device->scroll.button){
tablet_notify_button_scroll(device, tablet, time, state == LIBINPUT_BUTTON_STATE_PRESSED);
continue;
}
tablet_notify_button(base,
time,
tool,
@ -2059,18 +2229,6 @@ tablet_update_tool_state(struct tablet_dispatch *tablet,
return false;
}
static struct libinput_tablet_tool *
tablet_get_current_tool(struct tablet_dispatch *tablet)
{
if (tablet->current_tool.type == LIBINPUT_TOOL_NONE)
return NULL;
return tablet_get_tool(tablet,
tablet->current_tool.type,
tablet->current_tool.id,
tablet->current_tool.serial);
}
static void
tablet_flush(struct tablet_dispatch *tablet,
struct evdev_device *device,
@ -2115,6 +2273,8 @@ reprocess:
sanitize_tablet_axes(tablet, tool);
}
post_button_scroll(device, tablet, time);
tablet_send_events(tablet, tool, device, time);
if (process_tool_twice)
@ -2730,6 +2890,27 @@ tablet_fix_tilt(struct tablet_dispatch *tablet,
}
}
static void
tablet_change_scroll_method(struct evdev_device *device)
{
// FIXME
//struct tablet_dispatch *dispatch = tablet_dispatch(device->dispatch);
if (device->scroll.want_method == device->scroll.method &&
device->scroll.want_button == device->scroll.button &&
device->scroll.want_lock_enabled == device->scroll.lock_enabled)
return;
// FIXME
//if (tablet_any_button_down(dispatch, device))
// return;
device->scroll.method = device->scroll.want_method;
device->scroll.button = device->scroll.want_button;
device->scroll.lock_enabled = device->scroll.want_lock_enabled;
evdev_set_button_scroll_lock_enabled(device, device->scroll.lock_enabled);
}
static int
tablet_init(struct tablet_dispatch *tablet,
struct evdev_device *device)
@ -2769,6 +2950,9 @@ tablet_init(struct tablet_dispatch *tablet,
tablet->device = device;
tablet->status = TABLET_NONE;
tablet->current_tool.type = LIBINPUT_TOOL_NONE;
evdev_init_button_scroll(device, tablet_change_scroll_method);
list_init(&tablet->tool_list);
if (tablet_reject_device(device))

View file

@ -51,6 +51,7 @@ enum tablet_status {
TABLET_TOOL_ENTERING_CONTACT = bit(9),
TABLET_TOOL_LEAVING_CONTACT = bit(10),
TABLET_TOOL_OUT_OF_RANGE = bit(11),
TABLET_IN_SCROLL = bit(12),
};
struct button_state {

View file

@ -501,6 +501,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)
@ -2938,6 +2959,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

@ -676,6 +676,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,
@ -786,6 +793,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);
@ -101,6 +102,7 @@ event_type_to_str(enum libinput_event_type type)
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_TIP);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_BUTTON);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_RING);
CASE_RETURN_STRING(LIBINPUT_EVENT_TABLET_PAD_STRIP);
@ -214,11 +216,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 {
@ -437,7 +443,8 @@ libinput_event_get_tablet_tool_event(struct libinput_event *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return (struct libinput_event_tablet_tool *) event;
}
@ -727,6 +734,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)
@ -811,6 +836,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)
@ -1134,7 +1186,8 @@ libinput_event_tablet_tool_x_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_X);
@ -1150,7 +1203,8 @@ libinput_event_tablet_tool_y_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_Y);
@ -1166,7 +1220,8 @@ libinput_event_tablet_tool_pressure_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_PRESSURE);
@ -1182,7 +1237,8 @@ libinput_event_tablet_tool_distance_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_DISTANCE);
@ -1198,7 +1254,8 @@ libinput_event_tablet_tool_tilt_x_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_TILT_X);
@ -1214,7 +1271,8 @@ libinput_event_tablet_tool_tilt_y_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_TILT_Y);
@ -1230,7 +1288,8 @@ libinput_event_tablet_tool_rotation_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_ROTATION_Z);
@ -1246,7 +1305,8 @@ libinput_event_tablet_tool_slider_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_SLIDER);
@ -1262,7 +1322,8 @@ libinput_event_tablet_tool_size_major_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_SIZE_MAJOR);
@ -1278,7 +1339,8 @@ libinput_event_tablet_tool_size_minor_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_SIZE_MINOR);
@ -1294,7 +1356,8 @@ libinput_event_tablet_tool_wheel_has_changed(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return bit_is_set(event->changed_axes,
LIBINPUT_TABLET_TOOL_AXIS_REL_WHEEL);
@ -1311,7 +1374,8 @@ libinput_event_tablet_tool_get_x(struct libinput_event_tablet_tool *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return evdev_convert_to_mm(device->abs.absinfo_x,
event->axes.point.x);
@ -1328,7 +1392,8 @@ libinput_event_tablet_tool_get_y(struct libinput_event_tablet_tool *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return evdev_convert_to_mm(device->abs.absinfo_y,
event->axes.point.y);
@ -1343,7 +1408,8 @@ libinput_event_tablet_tool_get_dx(struct libinput_event_tablet_tool *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.delta.x;
}
@ -1357,7 +1423,8 @@ libinput_event_tablet_tool_get_dy(struct libinput_event_tablet_tool *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.delta.y;
}
@ -1371,7 +1438,8 @@ libinput_event_tablet_tool_get_pressure(struct libinput_event_tablet_tool *event
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.pressure;
}
@ -1385,7 +1453,8 @@ libinput_event_tablet_tool_get_distance(struct libinput_event_tablet_tool *event
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.distance;
}
@ -1399,7 +1468,8 @@ libinput_event_tablet_tool_get_tilt_x(struct libinput_event_tablet_tool *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.tilt.x;
}
@ -1413,7 +1483,8 @@ libinput_event_tablet_tool_get_tilt_y(struct libinput_event_tablet_tool *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.tilt.y;
}
@ -1427,7 +1498,8 @@ libinput_event_tablet_tool_get_rotation(struct libinput_event_tablet_tool *event
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.rotation;
}
@ -1441,7 +1513,8 @@ libinput_event_tablet_tool_get_slider_position(struct libinput_event_tablet_tool
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.slider;
}
@ -1455,7 +1528,8 @@ libinput_event_tablet_tool_get_size_major(struct libinput_event_tablet_tool *eve
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.size.major;
}
@ -1469,7 +1543,8 @@ libinput_event_tablet_tool_get_size_minor(struct libinput_event_tablet_tool *eve
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.size.minor;
}
@ -1483,7 +1558,8 @@ libinput_event_tablet_tool_get_wheel_delta(struct libinput_event_tablet_tool *ev
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.wheel;
}
@ -1498,7 +1574,8 @@ libinput_event_tablet_tool_get_wheel_delta_discrete(
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->axes.wheel_discrete;
}
@ -1515,7 +1592,8 @@ libinput_event_tablet_tool_get_x_transformed(struct libinput_event_tablet_tool *
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return evdev_device_transform_x(device,
event->axes.point.x,
@ -1534,7 +1612,8 @@ libinput_event_tablet_tool_get_y_transformed(struct libinput_event_tablet_tool *
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return evdev_device_transform_y(device,
event->axes.point.y,
@ -1550,7 +1629,8 @@ libinput_event_tablet_tool_get_tool(struct libinput_event_tablet_tool *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->tool;
}
@ -1564,7 +1644,8 @@ libinput_event_tablet_tool_get_proximity_state(struct libinput_event_tablet_tool
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->proximity_state;
}
@ -1578,7 +1659,8 @@ libinput_event_tablet_tool_get_tip_state(struct libinput_event_tablet_tool *even
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->tip_state;
}
@ -1592,7 +1674,8 @@ libinput_event_tablet_tool_get_time(struct libinput_event_tablet_tool *event)
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return us2ms(event->time);
}
@ -1606,7 +1689,8 @@ libinput_event_tablet_tool_get_time_usec(struct libinput_event_tablet_tool *even
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY);
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return event->time;
}
@ -2027,6 +2111,7 @@ libinput_event_destroy(struct libinput_event *event)
case LIBINPUT_EVENT_TABLET_TOOL_AXIS:
case LIBINPUT_EVENT_TABLET_TOOL_TIP:
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
case LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS:
libinput_event_tablet_tool_destroy(
libinput_event_get_tablet_tool_event(event));
break;
@ -2518,6 +2603,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,
@ -2586,6 +2708,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,
@ -3643,7 +3792,8 @@ libinput_event_tablet_tool_get_base_event(struct libinput_event_tablet_tool *eve
LIBINPUT_EVENT_TABLET_TOOL_AXIS,
LIBINPUT_EVENT_TABLET_TOOL_TIP,
LIBINPUT_EVENT_TABLET_TOOL_PROXIMITY,
LIBINPUT_EVENT_TABLET_TOOL_BUTTON);
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS);
return &event->base;
}
@ -3736,6 +3886,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

@ -323,6 +323,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
*
@ -943,6 +961,13 @@ enum libinput_event_type {
*/
LIBINPUT_EVENT_TABLET_TOOL_BUTTON,
/**
* A scroll event caused by the movement of tablet tool while scroll button is holded
*
* @since FIXME
*/
LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS,
/**
* A button pressed on a device with the @ref
* LIBINPUT_DEVICE_CAP_TABLET_PAD capability.
@ -1537,6 +1562,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
*
@ -1695,6 +1724,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
*
@ -3264,6 +3297,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

@ -349,4 +349,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;

View file

@ -3034,6 +3034,9 @@ litest_event_type_str(enum libinput_event_type type)
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
str = "TABLET TOOL BUTTON";
break;
case LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS:
str = "TABLET TOOL SCROLL CONTINOUS";
break;
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
str = "TABLET PAD BUTTON";
break;

View file

@ -3770,8 +3770,8 @@ TEST_COLLECTION(pointer)
litest_add(pointer_scroll_wheel_inhibit_dir_change, LITEST_WHEEL, LITEST_TABLET);
litest_add_for_device(pointer_scroll_wheel_lenovo_scrollpoint, LITEST_LENOVO_SCROLLPOINT);
litest_add(pointer_scroll_button, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
litest_add(pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE);
litest_add(pointer_scroll_button_noscroll, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON);
litest_add(pointer_scroll_button_noscroll, LITEST_ABSOLUTE|LITEST_BUTTON, LITEST_RELATIVE|LITEST_TABLET);
litest_add(pointer_scroll_button_noscroll, LITEST_ANY, LITEST_RELATIVE|LITEST_BUTTON|LITEST_TABLET);
litest_add(pointer_scroll_button_no_event_before_timeout, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
litest_add(pointer_scroll_button_middle_emulation, LITEST_RELATIVE|LITEST_BUTTON, LITEST_ANY);
litest_add_no_device(pointer_scroll_button_device_remove_while_down);

View file

@ -144,6 +144,9 @@ event_type_to_str(enum libinput_event_type evtype)
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
type = "TABLET_TOOL_BUTTON";
break;
case LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS:
type = "TABLET_TOOL_SCROLL_CONTINOUS";
break;
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
type = "TABLET_PAD_BUTTON";
break;
@ -506,6 +509,44 @@ print_tablet_button_event(struct libinput_event *ev)
libinput_event_tablet_tool_get_seat_button_count(p));
}
static void
print_tablet_tool_scroll_event(struct libinput_event *ev)
{
struct libinput_event_tablet_tool *t = libinput_event_get_tablet_tool_event(ev);
double v = 0, h = 0;
const char *have_vert = "",
*have_horiz = "";
const char *source = NULL;
enum libinput_pointer_axis axis;
enum libinput_event_type type;
type = libinput_event_get_type(ev);
switch (type) {
case LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS:
source = "continuous";
break;
default:
abort();
break;
}
axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
if (libinput_event_tablet_tool_has_axis(t, axis)) {
v = libinput_event_tablet_tool_get_scroll_value(t, axis);
have_vert = "*";
}
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
if (libinput_event_tablet_tool_has_axis(t, axis)) {
h = libinput_event_tablet_tool_get_scroll_value(t, axis);
have_horiz = "*";
}
printq("vert %.2f%s horiz %.2f%s (%s)\n",
v, have_vert,
h, have_horiz, source);
}
static void
print_pointer_axis_event(struct libinput_event *ev)
{
@ -1010,6 +1051,9 @@ handle_and_print_events(struct libinput *li)
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
print_tablet_button_event(ev);
break;
case LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS:
print_tablet_tool_scroll_event(ev);
break;
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
print_tablet_pad_button_event(ev);
break;

View file

@ -1477,7 +1477,7 @@ handle_event_touch(struct libinput_event *ev, struct window *w)
}
static void
handle_event_axis(struct libinput_event *ev, struct window *w)
handle_event_pointer_axis(struct libinput_event *ev, struct window *w)
{
struct libinput_event_pointer *p = libinput_event_get_pointer_event(ev);
double value;
@ -1511,6 +1511,43 @@ handle_event_axis(struct libinput_event *ev, struct window *w)
}
}
static void
handle_event_tablet_tool_axis(struct libinput_event *ev, struct window *w)
{
struct libinput_event_tablet_tool *p = libinput_event_get_tablet_tool_event(ev);
double value;
enum libinput_pointer_axis axis;
assert(p != NULL);
axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
if (libinput_event_tablet_tool_has_axis(p, axis)) {
value = libinput_event_tablet_tool_get_scroll_value(p, axis);
w->scroll.vy += value;
w->scroll.vy = clip(w->scroll.vy, 0, w->height);
}
axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
if (libinput_event_tablet_tool_has_axis(p, axis)) {
value = libinput_event_tablet_tool_get_scroll_value(p, axis);
w->scroll.hx += value;
w->scroll.hx = clip(w->scroll.hx, 0, w->width);
}
}
static void
handle_event_axis(struct libinput_event *ev, struct window *w)
{
switch (libinput_event_get_type(ev)){
case LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS:
handle_event_tablet_tool_axis(ev, w);
break;
default:
handle_event_pointer_axis(ev, w);
break;
}
}
static int
handle_event_keyboard(struct libinput_event *ev, struct window *w)
{
@ -1819,6 +1856,7 @@ handle_event_libinput(GIOChannel *source, GIOCondition condition, gpointer data)
case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
case LIBINPUT_EVENT_TABLET_TOOL_SCROLL_CONTINUOUS:
handle_event_axis(ev, w);
break;
case LIBINPUT_EVENT_POINTER_BUTTON: