diff --git a/include/libinput-properties.h b/include/libinput-properties.h index 8c6942d..67684fb 100644 --- a/include/libinput-properties.h +++ b/include/libinput-properties.h @@ -183,4 +183,8 @@ /* Device rotation: FLOAT, 1 value, 32 bit, read-only */ #define LIBINPUT_PROP_ROTATION_ANGLE_DEFAULT "libinput Rotation Angle Default" +/* Distance per scroll wheel click: FLOAT, 2 values in order, horizontal, + vertical, 32 bit */ +#define LIBINPUT_PROP_SCROLL_DISTANCE "libinput Scroll Distance" + #endif /* _LIBINPUT_PROPERTIES_H_ */ diff --git a/man/libinput.man b/man/libinput.man index 36775e6..3a0199b 100644 --- a/man/libinput.man +++ b/man/libinput.man @@ -151,6 +151,13 @@ Enables a scroll method. Permitted values are Not all devices support all options, if an option is unsupported, the default scroll option for this device is used. .TP 7 +.BI "Option \*qScrollDistance\*q \*q" "float float" \*q +Sets horizontal and vertical amount (respectively) of scroll wheel movement in +degrees that should result in one unit of scrolling. The horizontal value is +ignored unless the pointing device has a horizontal scroll wheel. See +.B SCROLL DISTANCE +for more information. +.TP 7 .BI "Option \*qSendEventsMode\*q \*q" (disabled|enabled|disabled-on-external-mouse) \*q Sets the send events mode to disabled, enabled, or "disable when an external mouse is connected". @@ -242,6 +249,14 @@ Indicates which scroll methods are available on this device. 3 boolean values (8 bit, 0 or 1), in order "two-finger", "edge", "button". Indicates which scroll method is currently enabled on this device. .TP 7 +.BI "libinput Scroll Distance" +2 32-bit float values, in order "horizontal", "vertical". +Sets horizontal and vertical amount (respectively) of scroll wheel movement in +degrees that should result in one unit of scrolling. The horizontal value is +ignored unless the pointing device has a horizontal scroll wheel. See +.B SCROLL DISTANCE +for more information. +.TP 7 .BI "libinput Send Events Modes Available" 2 boolean values (8 bit, 0 or 1), in order "disabled" and "disabled-on-external-mouse". Indicates which send-event modes are available @@ -313,6 +328,17 @@ and only the target button events are sent. .TP This feature is provided by this driver, not by libinput. +.SH SCROLL DISTANCE +The scroll distance options are used to convert the scroll distances reported by +.B libinput +to __xservername__ scroll units. One __xservername__ scroll unit is the +distance the screen scrolls when a traditional mouse wheel rotates one click. +The scroll distance options control the number of degrees of mouse wheel +rotation that coorespond to one __xservername__ scroll unit. For most mice, the +vertical scroll distance should be set to 15, because scroll wheels usually +move 15 degrees per click. Unless a mouse has a horizontal scroll wheel, the +horizontal scroll distance is ignored. + .SH AUTHORS Peter Hutterer .SH "SEE ALSO" diff --git a/src/xf86libinput.c b/src/xf86libinput.c index 747e84b..4a10695 100644 --- a/src/xf86libinput.c +++ b/src/xf86libinput.c @@ -84,6 +84,8 @@ #define CAP_TABLET_TOOL 0x10 #define CAP_TABLET_PAD 0x20 +#define DEFAULT_SCROLL_DISTANCE 15 + struct xf86libinput_driver { struct libinput *libinput; int device_enabled_count; @@ -162,6 +164,9 @@ struct xf86libinput { BOOL horiz_scrolling_enabled; float rotation_angle; + + float scroll_hdist; + float scroll_vdist; } options; struct draglock draglock; @@ -1347,12 +1352,8 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; if (libinput_event_pointer_has_axis(event, axis)) { - if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) { - value = libinput_event_pointer_get_axis_value_discrete(event, axis); - value *= driver_data->scroll.vdist; - } else { - value = libinput_event_pointer_get_axis_value(event, axis); - } + value = libinput_event_pointer_get_axis_value(event, axis); + value = (value / driver_data->options.scroll_vdist) * driver_data->scroll.vdist; valuator_mask_set_double(mask, 3, value); } @@ -1361,12 +1362,8 @@ xf86libinput_handle_axis(InputInfoPtr pInfo, struct libinput_event_pointer *even axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; if (libinput_event_pointer_has_axis(event, axis)) { - if (source == LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) { - value = libinput_event_pointer_get_axis_value_discrete(event, axis); - value *= driver_data->scroll.hdist; - } else { - value = libinput_event_pointer_get_axis_value(event, axis); - } + value = libinput_event_pointer_get_axis_value(event, axis); + value = (value / driver_data->options.scroll_hdist) * driver_data->scroll.hdist; valuator_mask_set_double(mask, 2, value); } @@ -2608,6 +2605,31 @@ xf86libinput_parse_rotation_angle_option(InputInfoPtr pInfo, return angle; } +static inline void +xf86libinput_parse_scroll_distance_option(InputInfoPtr pInfo, + float* scroll_hdist, float* scroll_vdist) +{ + char *str; + int num_distance; + + str = xf86CheckStrOption(pInfo->options, "ScrollDistance", NULL); + if (!str) { + *scroll_hdist = DEFAULT_SCROLL_DISTANCE; + *scroll_vdist = DEFAULT_SCROLL_DISTANCE; + return; + } + + num_distance = sscanf(str, "%f %f ", scroll_hdist, scroll_vdist); + if (num_distance != 2 || + *scroll_hdist == 0.0 || *scroll_vdist == 0.0) { + xf86IDrvMsg(pInfo, X_ERROR, + "Invalid scroll distance: %s, using default\n", str); + *scroll_hdist = DEFAULT_SCROLL_DISTANCE; + *scroll_vdist = DEFAULT_SCROLL_DISTANCE; + } + free(str); +} + static void xf86libinput_parse_options(InputInfoPtr pInfo, struct xf86libinput *driver_data, @@ -2641,6 +2663,8 @@ xf86libinput_parse_options(InputInfoPtr pInfo, xf86libinput_parse_draglock_option(pInfo, driver_data); options->horiz_scrolling_enabled = xf86libinput_parse_horiz_scroll_option(pInfo); } + + xf86libinput_parse_scroll_distance_option(pInfo, &options->scroll_hdist, &options->scroll_vdist); } static const char* @@ -2928,8 +2952,8 @@ xf86libinput_pre_init(InputDriverPtr drv, pInfo->private = driver_data; driver_data->pInfo = pInfo; - driver_data->scroll.vdist = 15; - driver_data->scroll.hdist = 15; + driver_data->scroll.vdist = 100; + driver_data->scroll.hdist = 100; driver_data->path = path; driver_data->shared_device = shared_device; xorg_list_append(&driver_data->shared_device_link, @@ -3093,6 +3117,7 @@ static Atom prop_rotation_angle_default; /* driver properties */ static Atom prop_draglock; static Atom prop_horiz_scroll; +static Atom prop_scroll_distance; /* general properties */ static Atom prop_float; @@ -3843,6 +3868,39 @@ LibinputSetPropertyRotationAngle(DeviceIntPtr dev, return Success; } +static inline int +LibinputSetPropertyScrollDistance(DeviceIntPtr dev, + Atom atom, + XIPropertyValuePtr val, + BOOL checkonly) +{ + InputInfoPtr pInfo = dev->public.devicePrivate; + struct xf86libinput *driver_data = pInfo->private; + float *scroll_distance; + float scroll_hdist; + float scroll_vdist; + + if (val->format != 32 || val->size != 2 || val->type != prop_float) + return BadMatch; + + if (!xf86libinput_check_device(dev, atom)) + return BadMatch; + + scroll_distance = (float*)val->data; + scroll_hdist = scroll_distance[0]; + scroll_vdist = scroll_distance[1]; + + if (scroll_hdist == 0.0 || scroll_vdist == 0.0) + return BadValue; + + if (!checkonly) { + driver_data->options.scroll_hdist = scroll_hdist; + driver_data->options.scroll_vdist = scroll_vdist; + } + + return Success; +} + static int LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly) @@ -3895,6 +3953,8 @@ LibinputSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, } else if (atom == prop_rotation_angle) rc = LibinputSetPropertyRotationAngle(dev, atom, val, checkonly); + else if (atom == prop_scroll_distance) + rc = LibinputSetPropertyScrollDistance(dev, atom, val, checkonly); else if (atom == prop_device || atom == prop_product_id || atom == prop_tap_default || atom == prop_tap_drag_default || @@ -4719,6 +4779,25 @@ LibinputInitRotationAngleProperty(DeviceIntPtr dev, } static void +LibinputInitScrollDistanceProperty(DeviceIntPtr dev, + struct xf86libinput *driver_data, + struct libinput_device *device) +{ + float scroll_distance[2]; + + if (!libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_POINTER)) + return; + + scroll_distance[0] = driver_data->options.scroll_hdist; + scroll_distance[1] = driver_data->options.scroll_vdist; + + prop_scroll_distance = LibinputMakeProperty(dev, + LIBINPUT_PROP_SCROLL_DISTANCE, + prop_float, 32, + 2, &scroll_distance); +} + +static void LibinputInitProperty(DeviceIntPtr dev) { InputInfoPtr pInfo = dev->public.devicePrivate; @@ -4774,4 +4853,5 @@ LibinputInitProperty(DeviceIntPtr dev) LibinputInitDragLockProperty(dev, driver_data); LibinputInitHorizScrollProperty(dev, driver_data); + LibinputInitScrollDistanceProperty(dev, driver_data, device); }