diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 5a458582..e9422129 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -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)) diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index e3490cd8..66cd495a 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -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 { diff --git a/src/evdev.c b/src/evdev.c index 15e338ac..8a51d26f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -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) { diff --git a/src/evdev.h b/src/evdev.h index 4971e4e9..ad2f0a03 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -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); diff --git a/src/libinput-private.h b/src/libinput-private.h index dd526cb0..b971b7ac 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -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, diff --git a/src/libinput.c b/src/libinput.c index 76e7235e..fd31b910 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -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) { diff --git a/src/libinput.h b/src/libinput.h index aa0f2be3..7afe198c 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -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 * diff --git a/src/libinput.sym b/src/libinput.sym index a598f77a..2b66a5ee 100644 --- a/src/libinput.sym +++ b/src/libinput.sym @@ -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; diff --git a/test/litest.c b/test/litest.c index d33339a7..54383d3d 100644 --- a/test/litest.c +++ b/test/litest.c @@ -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; diff --git a/test/test-pointer.c b/test/test-pointer.c index 13efedf5..28bac6a2 100644 --- a/test/test-pointer.c +++ b/test/test-pointer.c @@ -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); diff --git a/tools/libinput-debug-events.c b/tools/libinput-debug-events.c index 9a6e68c9..284536c1 100644 --- a/tools/libinput-debug-events.c +++ b/tools/libinput-debug-events.c @@ -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; diff --git a/tools/libinput-debug-gui.c b/tools/libinput-debug-gui.c index 83149b90..5cab1af6 100644 --- a/tools/libinput-debug-gui.c +++ b/tools/libinput-debug-gui.c @@ -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: