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. _______________________________________________ xorg@lists.x.org: X.Org support Archives: http://lists.freedesktop.org/archives/xorg Info: https://lists.x.org/mailman/listinfo/xorg Your subscription address: %(user_address)s