emit "smooth scrolling/pixel perfect" events

Peter Hutterer peter.hutterer at who-t.net
Mon Jun 20 07:03:05 UTC 2016


On Thu, Jun 16, 2016 at 06:24:46PM +0700, Antoine Martin wrote:
> On 05/01/15 06:52, Peter Hutterer wrote:
> > On Mon, Dec 29, 2014 at 08:07:31PM +0100, dustin wrote:
> >> Hi,
> >>
> >> i recently started to play around with the input facilitys of X. My goal is
> >> to develop a remote control for my PC and for that purpose i want to control
> >> the mouse with an android tablet. (Maybe other embeded devices)
> >>
> >> I found a few ways to do this namely xtest and uinput/evdev (and untested
> >> xlib/xcb). Both working out of the box but i think i'll stick with
> >> uinput/evdev cuz i think this approach should work with libinput(wayland) as
> >> well? One problem arises that i can't circumvent and this is the scrolling.
> >> my first implementation works by simply emitting button 4/5 events like what
> >> ordinary mouse wheels do (looking at xev xinput tools) but what i am rally
> >> looking for is emitting "smooth scroll events"/"pixel perfect scrolling"
> >> (whatever this means). I came across some articles from Peter Hutterer
> >> talking about this and that Gnome implemented this. One can see this in live
> >> action via touchpad and the epiphany webbrowser. What i discovered was, that
> >> a client program has to catch XI2 events (XIDeviceEvent)and watch for
> >> XI_Motion and its valuators. But i really don't know how to emit these? with
> >> uinput/evdev even if i am emiting EV_REL, REL_WHEEL events and not button
> >> 4/5 events i got ordinary scrolling. what is the "right way" to emit these
> >> XIDeviceEvent/XI_Motion events (if these are really the ones i am looking
> >> for)
> >>
> >> what i was seeing from xinput --test-xi2 for ordinary mouse wheels was
> >>
> >> EVENT type 17 (RawMotion)
> >>    device: 2 (10)
> >>    detail: 0
> >>    valuators:
> >>    flags:
> >>          2: -1.00 (-1.00)
> >>
> >> EVENT type 15 (RawButtonPress)
> >>    device: 2 (10)
> >>    detail: 5
> >>    valuators:
> >>    flags: emulated
> >>
> >> EVENT type 16 (RawButtonRelease)
> >>    device: 2 (10)
> >>    detail: 5
> >>    valuators:
> >>    flags: emulated
> >>
> >> As i understand this right the first XI_RawMotion is the "now" the regular
> >> new event and the button presses are for compatibility and can be ignored
> >> cuz of the "emulated" flag
> >>
> >> the valuator 2 means
> >>
> >> Class originated from: 10. Type: XIValuatorClass
> >>    Detail for Valuator 2:
> >> 	Label: Rel Vert Wheel
> >> 	Range: -1.000000 - -1.000000
> >> 	Resolution: 1 units/m
> >> 	Mode: relative
> >>
> >> if i scroll with my touchpad i get
> >>
> >> EVENT type 17 (RawMotion)
> >>    device: 2 (13) > >>    detail: 0
> >>    valuators:
> >>    flags:
> >>          3: 4.00 (4.00)
> >>
> >> there i have a valuator 3 which i guess means Rel Vert Scroll regarding to
> >> this
> >>
> >> Class originated from: 13. Type: XIValuatorClass
> >>    Detail for Valuator 3:
> >> 	Label: Rel Vert Scroll
> >> 	Range: 0.000000 - -1.000000
> >> 	Resolution: 0 units/m
> >> 	Mode: relative
> >>
> >> So the difference must somehow be with the different valuators. If so i just
> >> don't know how i can influence this with uinput/evdev. Maybe its only doable
> >> with xlib/xcb/xtest etc. i don't know.
> >>
> >> all i want is to simulate the "pixel perfect smooth scrolling" i get from
> >> regular laptop touchpads so that apps who respond to this will do from my
> >> application.
> > 
> > the output of xinput should also include a XIScrollClass. That contains
> > information whether it's vertical/horizontal and refers to the valuator
> > number. If such a class is present, the valuator listed is a scrolling
> > valuator and should be interpreted as such.
> > 
> > You don't have to do anything special in uinput, just send REL_WHEEL and the
> > rest of the xorg stack will do the right thing. Though since REL_WHEEL is
> > discreet, you won't get as much use out of smooth scrolling as you would
> > from a touchpad.
> When I send REL_WHEEL via uinput, applications that normally do smooth
> scrolling (ie: a browser) will scroll a few lines of text at a time, as
> if I had used the wheel using my mouse. That's expected.
> 
> What I would like to be able to do is emulate the behaviour I get from
> my trackpad with two-finger scrolling.

right, so this would be a two-step solution then and that's where it gets
tricky. unlike REL_WHEEL which is a dedicated scroll axis the smooth
scrolling behaviour is something handled in userspace only.

so the two-steps you need are:
a) send the right axes
b) convince userspace that the axes you send are scroll axes

but because of b) you're highly driver-dependent, evdev will do something
different to synaptics and so does libinput.

one option is to emulate a trackstick-like device and send a middle button
mouse press before sending scroll events (and relative
events otherwise). In libinput this will scroll automatically, in evdev it's
a configuration script away (EmulateWheel and
EmulateWheelButton). And that scroll type is 'smooth' (at least in libinput,
for evdev see https://bugs.freedesktop.org/show_bug.cgi?id=51533)

The other option is to emulate a touchpad and forward the touches as-is.
Then you let userspace take care of converting 2 finger to scroll, etc.
That works for android devices with screen, but obviously not for others.

Cheers,
   Peter

> I was hoping that simply setting uinput's absmax would have an effect on
> the valuator that gets assigned but this makes no difference.
> I assume that I need to get uinput to emulate a more "complete" device,
> but all my attempts have failed so far.
> Any ideas?
> 
> Thanks
> Antoine


More information about the xorg mailing list