fine grained scrolling via uinput [SOLVED - mostly]

Antoine Martin antoine at
Mon Aug 7 11:25:05 UTC 2017


We've got a solution to the "smooth scrolling" query from last year:

I believe that this solution is actually easier than implementing a
trackstick-like device: we adjust MOUSE_WHEEL_CLICK_COUNT on a uinput
device to give us 1 degree resolution, then multiply at runtime if we
need the "regular" 15 degree events.

There are quite a few places that need configuring to make this work:

1) ensure that those devices won't be picked up by real Xorg servers:
cat > /etc/X11/xorg.conf.d/90-xpra-virtual.conf << EOF
# Ignore all xpra virtual devices by default,
# these will be enabled explicitly when needed.
Section "InputClass"
        Identifier "xpra-virtual-device"
        MatchProduct "Xpra"
        Option "Ignore" "true"

2) Tell udev to add our click count setting:
cat > /lib/udev/rules.d/71-xpra-mouse.rules << EOF
ACTION=="add|change", ATTRS{name}=="Xpra Virtual Pointer", \
udevadm control --reload-rules && udevadm trigger

3) to be able to use uinput devices, xpra's xorg.conf has to enable
"AutoEnableDevices" and "AutoAddDevices", and so we also have to tell it
to ignore all the devices except the ones we will assign to it:
Section "InputClass"
  Identifier "ignore-non-xpra-devices"
  NoMatchProduct "Xpra"
  Option "Ignore" "true"

4) When starting a dummy Xorg server, we create a uinput device with
REL_WHEEL and BTN_* (as root so we can access /dev/uinput), then figure
out what path it's available under using UI_GET_SYSNAME and add this
Section "InputClass"
    Identifier "xpra-virtual-pointer"
    MatchProduct "Xpra Virtual Pointer"
    MatchDevicePath "/dev/input/eventNNN"
    Option "Ignore" "False"
    MatchIsPointer "True"
    Driver "libinput"
    Option "AccelProfile" "flat"
(the Xorg server doesn't run as root, we can drop privileges after
dealing with uinput and chowning the new device)

5) To send scroll events, we send these events to the uinput device:


And it all seems to work pretty well so far. Applications like Firefox
can now scroll a few pixels at a time.

1) Anything wrong with this approach?

2) what is the valid range for MOUSE_WHEEL_CLICK_COUNT?
If I set MOUSE_WHEEL_CLICK_COUNT too high, I get:
(EE) event19 - (EE) Xpra Virtual Pointer: (EE) mouse wheel click count
is present but invalid, using 15 degrees for angle instead instead
(and this error is logged twice)

3) Despite setting a flat AccelProfile above, "libinput list-devices" shows:
Accel profiles:   flat *adaptive
What am I doing wrong here?

4) the first scroll event is always ignored - what can I do to fix that?

5) I tried using a udev hwdb.d rule for setting the click count, but
that didn't seem to have any effect:
cat > /lib/udev/hwdb.d/71-mouse-xpra.hwdb <<EOF
# allow xpra to use smooth scrolling
mouse:*:name:Xpra Virtual Pointer:
udevadm hwdb --update
Does it matter? Any reason to use this rather than the udev rule?

6) to get the same motion as with an XTest wheel click, I'm having to
send REL_WHEEL=+-30, I would have thought it should be 15 instead.
Where did I get my maths wrong?

7) when the uinput device is created, udev will chown it to root:input,
is there any way we can tell udev to just leave it alone?
We know the uid and gid we want to chown to, and currently we have to
wait for udev to do its thing then do what we really want, which is both
ugly and racy.


More information about the xorg-devel mailing list