[1/2 v2] winex11: Always use the client pointer for raw events

Carlos Garnacho carlosg at gnome.org
Fri Nov 18 05:43:18 CST 2016


Detection of the master pointer Wine listens to for raw events
is busted. First, it's trying to do so based on the capabilities of
the master pointer (looking for rel x/y axes), whereas master devices
always get their capabilities updated to reflect those of the device
that was last interacted by the user. This means that if the user
interacts with a device not having relative axes (eg. a touchscreen)
right before Wine tries to enable XI2, the check will fail despite
the master pointer having attached HW devices with relative axes.

Second, in the unlikely case that Wine managed to detect a master
pointer other than the VCP (this requires user intervention, creating
a second pointer/keyboard pair and assigning HW devices to it) This
second pointer would be unaffected by the core X calls performed by
Wine (eg. grabs,cursor). This could eg. result in Wine grabbing/confining
one pointer, while listening to raw events from another, which is
otherwise unaffected by the grab.

Thus, use XI2's client pointer, it will be the master pointer affected
by X core calls, and even if it doesn't currently have relative X/Y
capabilities, it will gain those as soon as a slave device with such
capabilities is used.

The main purpose of this patch is fixing master device detection over
Xwayland, which is affected by the relative axes check. Xwayland will
most usually emit pointer events as coming from a device with absolute
axes, only switching to emitting relative motion when a very specific
set of conditions are met (thought out for gaming basically). But most
usually these conditions don't apply yet when XI2 is enabled, so the
VCP is skipped and it ends up with xi2_core_pointer=0, thus ignoring
the relative motion that is later sent.

But again, this is not Xwayland specific, it could happen as well with
the right conditions on traditional X servers.

Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
---

 Changes since v1: Use XIGetClientPointer instead of hardcoding the VCP

 dlls/winex11.drv/mouse.c | 25 +++----------------------
 1 file changed, 3 insertions(+), 22 deletions(-)

diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index a120fae..4d20882 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -132,6 +132,7 @@ static Cursor create_cursor( HANDLE handle );
 static BOOL xinput2_available;
 static BOOL broken_rawevents;
 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
+MAKE_FUNCPTR(XIGetClientPointer);
 MAKE_FUNCPTR(XIFreeDeviceInfo);
 MAKE_FUNCPTR(XIQueryDevice);
 MAKE_FUNCPTR(XIQueryVersion);
@@ -272,29 +273,8 @@ static void enable_xinput2(void)
     if (data->xi2_state == xi_unavailable) return;
 
     if (data->xi2_devices) pXIFreeDeviceInfo( data->xi2_devices );
+    if (!pXIGetClientPointer( data->display, None, &data->xi2_core_pointer )) return;
     data->xi2_devices = devices = pXIQueryDevice( data->display, XIAllDevices, &data->xi2_device_count );
-    for (i = 0; i < data->xi2_device_count; ++i)
-    {
-        if (devices[i].use != XIMasterPointer) continue;
-        for (j = count = 0; j < devices[i].num_classes; j++)
-        {
-            XIValuatorClassInfo *class = (XIValuatorClassInfo *)devices[i].classes[j];
-
-            if (devices[i].classes[j]->type != XIValuatorClass) continue;
-            TRACE( "Device %u (%s) num %u %f,%f res %u mode %u label %s\n",
-                   devices[i].deviceid, debugstr_a(devices[i].name),
-                   class->number, class->min, class->max, class->resolution, class->mode,
-                   XGetAtomName( data->display, class->label ));
-            if (class->label == x11drv_atom( Rel_X ) || class->label == x11drv_atom( Rel_Y )) count++;
-            /* workaround for drivers that don't provide labels */
-            if (!class->label && class->number <= 1 && class->mode == XIModeRelative) count++;
-        }
-        if (count < 2) continue;
-        TRACE( "Using %u (%s) as core pointer\n",
-               devices[i].deviceid, debugstr_a(devices[i].name) );
-        data->xi2_core_pointer = devices[i].deviceid;
-        break;
-    }
 
     mask.mask     = mask_bits;
     mask.mask_len = sizeof(mask_bits);
@@ -1729,6 +1709,7 @@ void X11DRV_XInput2_Init(void)
         return; \
     }
 
+    LOAD_FUNCPTR(XIGetClientPointer);
     LOAD_FUNCPTR(XIFreeDeviceInfo);
     LOAD_FUNCPTR(XIQueryDevice);
     LOAD_FUNCPTR(XIQueryVersion);
-- 
2.9.3




More information about the wine-patches mailing list