dix: Add POINTER_RAWONLY flag

This add a new flag POINTER_RAWONLY for GetPointerEvents() which does
pretty much the opposite of POINTER_NORAW.

Basically, this tells GetPointerEvents() that we only want the
DeviceChanged events and any raw events for this motion but no actual
motion events.

This is preliminary work for Xwayland to be able to use relative motion
events for raw events. Xwayland would use absolute events for raw
events, but some X11 clients (wrongly) assume raw events to be always
relative.

To allow such clients to work with Xwayland, it needs to switch to
relative raw events (if those are available from the Wayland
compositor).

However, Xwayland cannot use relative motion events for actual pointer
location because that would cause a drift over time, the pointer being
actually controlled by the Wayland compositor.

So Xwayland needs to be able to send only relative raw events, hence
this API.

Bump the ABI_XINPUT_VERSION minor version to reflect that API addition.

v2: Actually avoid sending motion events (Peter)
v3: Keep sending raw emulated events with RAWONLY (Peter)

Suggested-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Related: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1130
(cherry picked from commit b5e1f13681)
This commit is contained in:
Olivier Fourdan 2021-02-11 09:48:12 +01:00
parent 1e72c3ce84
commit 0663a245ad
2 changed files with 32 additions and 26 deletions

View File

@ -1343,7 +1343,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
int buttons, CARD32 ms, int flags,
const ValuatorMask *mask_in)
{
int num_events = 1;
int num_events = 0;
DeviceEvent *event;
RawDeviceEvent *raw = NULL;
double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */
@ -1386,6 +1386,10 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
num_events++;
init_raw(pDev, raw, ms, type, buttons);
if (flags & POINTER_EMULATED)
raw->flags = XIPointerEmulated;
set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw);
}
@ -1454,36 +1458,37 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
master->last.valuators[1] = screeny;
}
event = &events->device_event;
init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL);
if ((flags & POINTER_RAWONLY) == 0) {
num_events++;
if (type == MotionNotify) {
event->type = ET_Motion;
event->detail.button = 0;
}
else {
if (type == ButtonPress) {
event->type = ET_ButtonPress;
set_button_down(pDev, buttons, BUTTON_POSTED);
event = &events->device_event;
init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL);
if (type == MotionNotify) {
event->type = ET_Motion;
event->detail.button = 0;
}
else if (type == ButtonRelease) {
event->type = ET_ButtonRelease;
set_button_up(pDev, buttons, BUTTON_POSTED);
else {
if (type == ButtonPress) {
event->type = ET_ButtonPress;
set_button_down(pDev, buttons, BUTTON_POSTED);
}
else if (type == ButtonRelease) {
event->type = ET_ButtonRelease;
set_button_up(pDev, buttons, BUTTON_POSTED);
}
event->detail.button = buttons;
}
event->detail.button = buttons;
/* root_x and root_y must be in per-screen coordinates */
event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
if (flags & POINTER_EMULATED)
event->flags = XIPointerEmulated;
set_valuators(pDev, event, &mask);
}
/* root_x and root_y must be in per-screen coordinates */
event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
if (flags & POINTER_EMULATED) {
if (raw)
raw->flags = XIPointerEmulated;
event->flags = XIPointerEmulated;
}
set_valuators(pDev, event, &mask);
return num_events;
}

View File

@ -94,6 +94,7 @@ SOFTWARE.
#define POINTER_NORAW (1 << 5) /* Don't generate RawEvents */
#define POINTER_EMULATED (1 << 6) /* Event was emulated from another event */
#define POINTER_DESKTOP (1 << 7) /* Data in desktop coordinates */
#define POINTER_RAWONLY (1 << 8) /* Only generate RawEvents */
/* GetTouchEvent flags */
#define TOUCH_ACCEPT (1 << 0)