How does mouse event synthesis work on touchscreen?
Grósz Dániel
groszdanielpub at gmail.com
Thu Nov 19 04:11:36 UTC 2020
Hi,
I'm not sure if this is the right place to ask, or where to look this up.
Please give me a rundown (or links) on how mouse event emulation works on
touchscreens.
Motivation: I'd like to implement mouse event emulation for touchscreens, such
as
- long tap for right click
- two-finger tap for middle click
- two-finger drag for scrolling
- tap-and-drag for dragging
- perhaps some gesture for relative rather than absolute pointer movement
(like a touchpad) for when mode precise cursor movements are desired.
Preferably, this would entail disabling any default mouse event emulation (so
if, for instance, a two-finger touch generates a left click by default, then I
need to generate only a middle click, rather than both). Ideally, if an
application specifically handles a given touch event (rather than relying on
the default mouse click emulation), that should take
precedence.
Libinput's documentation says that (unlike on touchpads) it doesn't handle
tapping or gestures on touchscreens, as they are expected to be implemented in
the toolkit. This is reasonable: for instance, dragging on a touchscreen is
sometimes equivalent to a click-and-drag operation, but in other cases it is
conventionally used (for instance) to drag content where a mouse drag would
select text.
However, this doesn't work well when an application doesn't have adequate
support for touch input, which is why I'd like to have a gesture to emulate
scrolling. Conversely, when dragging is used for scrolling, I'd like to have
an alternative gesture that always emulates mouse drag.
Despite what libinput's docs say, there does seem to be some sort of mouse
event emulation (only for left clicks and drags), as evidenced by the fact
that even ancient applications such as xterm or Qt 3 apps that (I presume)
don't have any specific code to handle touch events do react to touch.
I could imagine several ways it could work:
- X.org always sends only touch events to applications, and it's up to the
widget toolkit (such as Qt) to synthesize mouse events if the application
doesn't explicitly handle touch. (This doesn't seem to be the case, as even
ancient apps react to touch input. However, on Qt 5, QMouseEvent::source()
returns Qt::MouseEventSynthesizedByQt on mouse events corresponding to
touchscreen touches.)
- X.org always sends both touch events and emulated mouse left button events.
It's up to the application or toolkit to figure out if these belong to the
same user action, and only handle one of them.
- X.org sends a touch event. The application responds whether it handles it.
If it doesn't, then X.org sends an emulated mouse event.
- An application tells X.org in advance whether it is touchscreen-aware or
not. If it is, then X.org only sends touch events, otherwise it only sends
mouse events.
- X.org synthesizes mouse events for some touchscreen inputs, and in that case
it only sends them as mouse events. When there is no corresponding mouse
event, it sends touch events. (This doesn't seem to be the case. Even
multiple-finger touches work as left clicks in applications that don't have
specific touchscreen support, while single taps and drags are not always
handled the same as mouse left-button drags.)
My questions:
- Which of these (if any) is correct?
- If mouse event emulation happens somewhere in X.org, where does it happen?
In the touchscreen driver?
- Is what I want feasible at all? I'm afraid that preventing conflicts with
synthesized left button events is only theoretically feasible (without
modifying the widget toolkits) if the synthesis always happens in X.org.
- What's the best way to go about it? Modify the touchscreen driver (such as
libinput or evdev)? Interpret touch events coming from the relevant device in
/dev/input, and create fake mouse events with uinput? Capture touch events
using an X client, and fake mouse events using XTEST?
Thank you for any pointers.
More information about the xorg
mailing list