events management to simulate a mouse

Peter Hutterer peter.hutterer at who-t.net
Fri Dec 4 00:14:15 UTC 2020


On Fri, Dec 04, 2020 at 12:42:19AM +0100, input-tools at storiepvtride.it wrote:
> 
> Hi,
> 
> I have experimented a bit and got the basics on how to send blocks of
> events using libinput. I now have a simple python script that filter
> EV_KEY events and transform them into EV_REL.
> 
> Now I have two questions:
> 
> 1) I'd like to get a sufficiently smooth movement, I wonder how should I
> manage acceleration and precision (example: increase the amout of pixels
> when I receive an autorepeat event or add more events to a single
> block?). Clearly I don't expect to replace the smoothness of a mouse
> by sending key events.

simply said - you don't, it's the wrong level here. evdev is a hardware
abstraction so the events you can simulate are the ones as if they came from
the device itself. acceleration and pointer precision is handled by the next
layer (libinput or on older systems the X server). The best you can do is
send events at regular intervals (e.g. at 125Hz, 500Hz, whatever) and then
hope that the next stack interprets it correctly. If you just send the
occasional large movement, it's likely libinput gets the acceleration wrong
because, well, that's not what a mouse would do.
 
> 2) I'd like to set a modifier and use four keys for mouse
> movement (say: w,a,s,d). How do I manage a modifier pressed and at the same
> send other EV_KEY events without "blocking" the stream of events?

again, the wrong layer because what is a modifier is defined by the XKB
keyboard layout which you cannot know at the evdev level (just like your
keyboard doesn't know whether you're using qwerty or azerty). Doesn't matter
for a home-grown solution because you won't change layouts often but this
prevents generic solutions.

If you want to intercept *some* events, then you need to multiplex the
keyboard. You hook your script onto the real keyboard event node and
EVIOCGRAB it (meaning all events are only delivered to your process). Then
you create *two* uinput devices - one for the mouse, one that looks exactly
like your real keyboard.

Whenever you get a key event that you don't immediately make use of, you
route it through the kbd uinput node. That's the cleanest and simplest
approach.

> I wonder if what I'm trying to accomplish would be better managed at the
> compositor level (wlroots, in my case).

ftr in case you didn't know yet: XKB has the concept of PointerKeys
available as option keypad:pointerkeys which provides you with mouse
emulation on the numpad. Enabled by pressing Shift+NumLock. This works in X
but for Wayland compositors its implementation-dependent, not sure wlroots
supports it.

You could change this to any key by changing the key bindings, so
implementing this on WASD would be possible, see this post here
https://who-t.blogspot.com/2020/09/user-specific-xkb-configuration-putting.html
and the ones leading up to it.

Cheers,
   Peter


More information about the Input-tools mailing list