Abstract
When scroll events are sent without being a multiple of 120, the axis_discrete event (sent for wl_seat protocol version < 8) can behave poorly. In particular, it waits to accumulate to 120 before firing an axis_discrete event, so if an event is too small then no axis_discrete event is fired (similarly, if it is too big, then multiple axis_discrete events are fired). A particular case in which this is problematic is for Wine with the wayland backend (winewayland.drv, which uses wl_seat protocol version 5): this is often used for games, which may bind something to the scroll wheel, in which case the control may misbehave.
Reproduction
- Use niri.
- Set the mouse input scroll-factor to a value other than 1.
- Run a program that uses an old version of
wl_seat (tested on wev by explicitly setting the protocol version to 5); enabling WAYLAND_DEBUG=1 is also helpful here.
- Try scrolling one mouse wheel notch at a time, and note when
axis_discrete events fire.
Possible solution
I can see the merit in some applications or input methods to have it work like it currently does, so a broad approach that always fires axis_discrete events would be too heavy-handed. Therefore, I think that Smithay should always fire at least one axis_discrete event when the source is discrete (Wheel or WheelTilt) and otherwise continue as now. For what it's worth, I believe this is how KDE works currently.
Another interesting option is to allow the library consumer (e.g., niri) to control this behavior. The simplest interface I can imagine for this is adding a function AxisFrame::discrete(mut self, axis: Axis, value: Option<i32>). If this function is not called at all then the default Smithay behavior is used (either the current behavior or the one described above); if it is called with a Some value, then that is forwarded to WlPointer::axis_discrete; if it called with a None value, then no WlPointer::axis_discrete call is made at all. I'm not entirely fond of this (how should multiple calls to AxisFrame::discrete be combined?), but it shows the idea of what kind of control I think would be necessary.
Abstract
When scroll events are sent without being a multiple of 120, the
axis_discreteevent (sent forwl_seatprotocol version < 8) can behave poorly. In particular, it waits to accumulate to 120 before firing anaxis_discreteevent, so if an event is too small then noaxis_discreteevent is fired (similarly, if it is too big, then multipleaxis_discreteevents are fired). A particular case in which this is problematic is for Wine with the wayland backend (winewayland.drv, which useswl_seatprotocol version 5): this is often used for games, which may bind something to the scroll wheel, in which case the control may misbehave.Reproduction
wl_seat(tested on wev by explicitly setting the protocol version to 5); enablingWAYLAND_DEBUG=1is also helpful here.axis_discreteevents fire.Possible solution
I can see the merit in some applications or input methods to have it work like it currently does, so a broad approach that always fires
axis_discreteevents would be too heavy-handed. Therefore, I think that Smithay should always fire at least oneaxis_discreteevent when the source is discrete (WheelorWheelTilt) and otherwise continue as now. For what it's worth, I believe this is how KDE works currently.Another interesting option is to allow the library consumer (e.g., niri) to control this behavior. The simplest interface I can imagine for this is adding a function
AxisFrame::discrete(mut self, axis: Axis, value: Option<i32>). If this function is not called at all then the default Smithay behavior is used (either the current behavior or the one described above); if it is called with aSomevalue, then that is forwarded toWlPointer::axis_discrete; if it called with aNonevalue, then noWlPointer::axis_discretecall is made at all. I'm not entirely fond of this (how should multiple calls toAxisFrame::discretebe combined?), but it shows the idea of what kind of control I think would be necessary.