diff --git a/include/libinput-properties.h b/include/libinput-properties.h index bf774d5..2034338 100644 --- a/include/libinput-properties.h +++ b/include/libinput-properties.h @@ -154,6 +154,12 @@ /* Scroll pixel distance: CARD32, 1 value, read-only */ #define LIBINPUT_PROP_SCROLL_PIXEL_DISTANCE_DEFAULT "libinput Scrolling Pixel Distance Default" +/* Scroll factor: FLOAT, 1 value, 32 bit */ +#define LIBINPUT_PROP_SCROLL_FACTOR "libinput Scrolling Factor" + +/* Scroll factor: FLOAT, 1 value, 32 bit, read-only */ +#define LIBINPUT_PROP_SCROLL_FACTOR_DEFAULT "libinput Scrolling Factor Default" + /* Click method: BOOL read-only, 2 values in order buttonareas, clickfinger shows available click methods */ #define LIBINPUT_PROP_CLICK_METHODS_AVAILABLE "libinput Click Methods Available" diff --git a/man/libinput.man b/man/libinput.man index 053bbf7..2c2a6af 100644 --- a/man/libinput.man +++ b/man/libinput.man @@ -206,6 +206,11 @@ If disabled (the default), the button is considered logically down while held down and up once physically released. .TP 7 +.BI "Option \*qScrollFactor\*q \*q" float \*q +Sets the scroll factor for scroll events. A higher value means faster scrolling. +Applications that don't support xi2 input will instead receive scroll button events +less or more frequently depending on the scroll factor value, instead of scrolling "smoother". +.TP 7 .BI "Option \*qScrollMethod\*q \*q" string \*q Enables a scroll method. Permitted values are .BR none , diff --git a/src/xf86libinput.c b/src/xf86libinput.c index b62173b..ad059be 100644 --- a/src/xf86libinput.c +++ b/src/xf86libinput.c @@ -52,6 +52,8 @@ #define TOUCH_MAX_SLOTS 15 #define XORG_KEYCODE_OFFSET 8 #define SCROLL_INCREMENT 15 +#define SCROLL_FACTOR_MIN 0.0001 +#define SCROLL_FACTOR_MAX 1000.0 #define TOUCHPAD_SCROLL_DIST_MIN 10 /* in libinput pixels */ #define TOUCHPAD_SCROLL_DIST_MAX 50 /* in libinput pixels */ @@ -175,6 +177,7 @@ struct xf86libinput { CARD32 scroll_button; /* xorg button number */ BOOL scroll_buttonlock; uint32_t scroll_pixel_distance; + float scroll_factor; float speed; float matrix[9]; enum libinput_config_scroll_method scroll_method; @@ -1913,6 +1916,7 @@ calculate_axis_value(struct xf86libinput *driver_data, value = value/dist * SCROLL_INCREMENT * 8; } + value *= driver_data->options.scroll_factor; *value_out = value; return true; @@ -3435,6 +3439,20 @@ xf86libinput_parse_scroll_pixel_distance_option(InputInfoPtr pInfo, return dist; } +static inline double +xf86libinput_parse_scroll_factor_option(InputInfoPtr pInfo, + struct libinput_device *device) +{ + const double scroll_factor_default = 1.0; + double scroll_factor = xf86SetRealOption(pInfo->options, "ScrollFactor", scroll_factor_default); + if (scroll_factor < SCROLL_FACTOR_MIN || scroll_factor > SCROLL_FACTOR_MAX) { + xf86IDrvMsg(pInfo, X_ERROR, "Invalid ScrollFactor %f, expected to be between %f and %f\n", + scroll_factor, SCROLL_FACTOR_MIN, SCROLL_FACTOR_MAX); + scroll_factor = scroll_factor_default; + } + return scroll_factor; +} + static inline unsigned int xf86libinput_parse_clickmethod_option(InputInfoPtr pInfo, struct libinput_device *device) @@ -3774,6 +3792,7 @@ xf86libinput_parse_options(InputInfoPtr pInfo, options->scroll_button = xf86libinput_parse_scrollbutton_option(pInfo, device); options->scroll_buttonlock = xf86libinput_parse_scrollbuttonlock_option(pInfo, device); options->scroll_pixel_distance = xf86libinput_parse_scroll_pixel_distance_option(pInfo, device); + options->scroll_factor = xf86libinput_parse_scroll_factor_option(pInfo, device); options->click_method = xf86libinput_parse_clickmethod_option(pInfo, device); #if HAVE_LIBINPUT_CLICKFINGER_BUTTON_MAP options->clickfinger_button_map = xf86libinput_parse_clickfinger_map_option(pInfo, device); @@ -4257,6 +4276,8 @@ static Atom prop_scroll_buttonlock; static Atom prop_scroll_buttonlock_default; static Atom prop_scroll_pixel_distance; static Atom prop_scroll_pixel_distance_default; +static Atom prop_scroll_factor; +static Atom prop_scroll_factor_default; static Atom prop_click_methods_available; static Atom prop_click_method_enabled; static Atom prop_click_method_default; @@ -5247,6 +5268,34 @@ LibinputSetPropertyScrollPixelDistance(DeviceIntPtr dev, return Success; } +static inline int +LibinputSetPropertyScrollFactor(DeviceIntPtr dev, + Atom atom, + XIPropertyValuePtr val, + BOOL checkonly) +{ + InputInfoPtr pInfo = dev->public.devicePrivate; + struct xf86libinput *driver_data = pInfo->private; + float *scroll_factor; + + if (val->format != 32 || val->size != 1 || val->type != prop_float) + return BadMatch; + + scroll_factor = (float*)val->data; + + if (checkonly) { + if (*scroll_factor < SCROLL_FACTOR_MIN || *scroll_factor > SCROLL_FACTOR_MAX) + return BadValue; + + if (!xf86libinput_check_device(dev, atom)) + return BadMatch; + } else { + driver_data->options.scroll_factor = *scroll_factor; + } + + return Success; +} + static inline int LibinputSetPropertyRotationAngle(DeviceIntPtr dev, Atom atom, @@ -5502,6 +5551,8 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, rc = LibinputSetPropertyHorizScroll(dev, atom, val, checkonly); else if (atom == prop_scroll_pixel_distance) rc = LibinputSetPropertyScrollPixelDistance(dev, atom, val, checkonly); + else if (atom == prop_scroll_factor) + rc = LibinputSetPropertyScrollFactor(dev, atom, val, checkonly); else if (atom == prop_mode_groups) { InputInfoPtr pInfo = dev->public.devicePrivate; struct xf86libinput *driver_data = pInfo->private; @@ -5543,6 +5594,7 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, atom == prop_scroll_method_default || atom == prop_scroll_methods_available || atom == prop_scroll_pixel_distance_default || + atom == prop_scroll_factor_default || atom == prop_sendevents_available || atom == prop_sendevents_default || atom == prop_serial || @@ -6155,6 +6207,32 @@ LibinputInitScrollPixelDistanceProperty(DeviceIntPtr dev, 1, &dist); } +static void +LibinputInitScrollFactorProperty(DeviceIntPtr dev, + struct xf86libinput *driver_data, + struct libinput_device *device) +{ + float scroll_factor = driver_data->options.scroll_factor; + + if (!subdevice_has_capabilities(dev, CAP_POINTER)) + return; + + prop_scroll_factor = LibinputMakeProperty(dev, + LIBINPUT_PROP_SCROLL_FACTOR, + prop_float, 32, + 1, &scroll_factor); + if (!prop_scroll_factor) + return; + + prop_scroll_factor_default = LibinputMakeProperty(dev, + LIBINPUT_PROP_SCROLL_FACTOR_DEFAULT, + prop_float, 32, + 1, &scroll_factor); + + if (!prop_scroll_factor_default) + return; +} + static void LibinputInitClickMethodsProperty(DeviceIntPtr dev, struct xf86libinput *driver_data, @@ -6700,6 +6778,7 @@ LibinputInitProperty(DeviceIntPtr dev) LibinputInitNaturalScrollProperty(dev, driver_data, device); LibinputInitDisableWhileTypingProperty(dev, driver_data, device); LibinputInitScrollMethodsProperty(dev, driver_data, device); + LibinputInitScrollFactorProperty(dev, driver_data, device); LibinputInitClickMethodsProperty(dev, driver_data, device); LibinputInitClickfingerButtonmapProperty(dev, driver_data, device); LibinputInitMiddleEmulationProperty(dev, driver_data, device);