[PATCH v10 6/9] winex11.drv: Directly listen to master XInput2 devices if supported
Derek Lesho
dereklesho52 at gmail.com
Fri Aug 2 01:24:32 CDT 2019
From: RĂ©mi Bernon <rbernon at codeweavers.com>
Under XInput2 protocol version < 2.1, raw events should not be received
if pointer grab is active. However slave device events are still
received regardless of this specification and Wine implemented a
workaround to get raw events during pointer grabs by listening to these
slave device events.
By advertising to support XInput2 protocol version >= 2.1, where raw
events are sent even during pointer grabs, it is possible to simplify
the code by listening to master device events only.
Signed-off-by: Derek Lesho <dereklesho52 at Gmail.com>
---
v10/v2: I put the adding of DeviceChanged to the mask in the legacy path so we
don't get those on XI >= 2.1 where we don't have any use for the event.
---
dlls/winex11.drv/event.c | 42 +-----------------------------
dlls/winex11.drv/mouse.c | 56 +++++++++++++++++++++++++++++-----------
2 files changed, 42 insertions(+), 56 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 5c465aa033..1e64f0d2a3 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -271,46 +271,6 @@ enum event_merge_action
MERGE_IGNORE /* ignore the new event, keep the old one */
};
-/***********************************************************************
- * merge_raw_motion_events
- */
-#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
-static enum event_merge_action merge_raw_motion_events( XIRawEvent *prev, XIRawEvent *next )
-{
- int i, j, k;
- unsigned char mask;
-
- if (!prev->valuators.mask_len) return MERGE_HANDLE;
- if (!next->valuators.mask_len) return MERGE_HANDLE;
-
- mask = prev->valuators.mask[0] | next->valuators.mask[0];
- if (mask == next->valuators.mask[0]) /* keep next */
- {
- for (i = j = k = 0; i < 8; i++)
- {
- if (XIMaskIsSet( prev->valuators.mask, i ))
- next->valuators.values[j] += prev->valuators.values[k++];
- if (XIMaskIsSet( next->valuators.mask, i )) j++;
- }
- TRACE( "merging duplicate GenericEvent\n" );
- return MERGE_DISCARD;
- }
- if (mask == prev->valuators.mask[0]) /* keep prev */
- {
- for (i = j = k = 0; i < 8; i++)
- {
- if (XIMaskIsSet( next->valuators.mask, i ))
- prev->valuators.values[j] += next->valuators.values[k++];
- if (XIMaskIsSet( prev->valuators.mask, i )) j++;
- }
- TRACE( "merging duplicate GenericEvent\n" );
- return MERGE_IGNORE;
- }
- /* can't merge events with disjoint masks */
- return MERGE_HANDLE;
-}
-#endif
-
/***********************************************************************
* merge_events
*
@@ -362,7 +322,7 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
if (next->xcookie.extension != xinput2_opcode) break;
if (next->xcookie.evtype != XI_RawMotion) break;
if (x11drv_thread_data()->warp_serial) break;
- return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data );
+ return MERGE_HANDLE;
#endif
}
break;
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
index f737a306a5..578efa1931 100644
--- a/dlls/winex11.drv/mouse.c
+++ b/dlls/winex11.drv/mouse.c
@@ -130,6 +130,8 @@ static Cursor create_cursor( HANDLE handle );
#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
static BOOL xinput2_available;
+static int xinput2_version_major = 2;
+static int xinput2_version_minor = 1;
static BOOL broken_rawevents;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
MAKE_FUNCPTR(XIGetClientPointer);
@@ -301,8 +303,11 @@ static void enable_xinput2(void)
if (data->xi2_state == xi_unknown)
{
- int major = 2, minor = 0;
- if (!pXIQueryVersion( data->display, &major, &minor )) data->xi2_state = xi_disabled;
+ if (!pXIQueryVersion( data->display, &xinput2_version_major, &xinput2_version_minor ))
+ {
+ TRACE( "XInput2 v%d.%d available\n", xinput2_version_major, xinput2_version_minor );
+ data->xi2_state = xi_disabled;
+ }
else
{
data->xi2_state = xi_unavailable;
@@ -314,12 +319,20 @@ static void enable_xinput2(void)
mask.mask = mask_bits;
mask.mask_len = sizeof(mask_bits);
- mask.deviceid = XIAllDevices;
+ mask.deviceid = XIAllMasterDevices;
memset( mask_bits, 0, sizeof(mask_bits) );
- XISetMask( mask_bits, XI_DeviceChanged );
XISetMask( mask_bits, XI_RawMotion );
XISetMask( mask_bits, XI_ButtonPress );
+ /* XInput 2.0 has a problematic behavior where master pointer will
+ * not send raw events to the root window whenever a grab is active
+ */
+ if (xinput2_version_major == 2 && xinput2_version_minor == 0)
+ {
+ mask.deviceid = XIAllDevices;
+ XISetMask( mask_bits, XI_DeviceChanged );
+ }
+
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
pointer_info = pXIQueryDevice( data->display, data->xi2_core_pointer, &count );
@@ -333,7 +346,7 @@ static void enable_xinput2(void)
* safe to be obtained statically at enable_xinput2() time.
*/
if (data->xi2_devices) pXIFreeDeviceInfo( data->xi2_devices );
- data->xi2_devices = pXIQueryDevice( data->display, XIAllDevices, &data->xi2_device_count );
+ data->xi2_devices = pXIQueryDevice( data->display, mask.deviceid, &data->xi2_device_count );
data->xi2_current_slave = 0;
data->xi2_state = xi_enabled;
@@ -356,7 +369,13 @@ static void disable_xinput2(void)
mask.mask = NULL;
mask.mask_len = 0;
- mask.deviceid = XIAllDevices;
+ mask.deviceid = XIAllMasterDevices;
+
+ /* XInput 2.0 has a problematic behavior where master pointer will
+ * not send raw events to the root window whenever a grab is active
+ */
+ if (xinput2_version_major == 2 && xinput2_version_minor == 0)
+ mask.deviceid = XIAllDevices;
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );
pXIFreeDeviceInfo( data->xi2_devices );
@@ -1735,25 +1754,32 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
if (!event->valuators.mask_len) return FALSE;
if (thread_data->xi2_state != xi_enabled) return FALSE;
- /* If there is no slave currently detected, no previous motion nor device
- * change events were received. Look it up now on the device list in this
- * case.
- */
- if (!thread_data->xi2_current_slave)
+ if (xinput2_version_major == 2 && xinput2_version_minor == 0)
{
XIDeviceInfo *devices = thread_data->xi2_devices;
- for (i = 0; i < thread_data->xi2_device_count; i++)
+ /* If there is no slave currently detected, no previous motion nor device
+ * change events were received. Look it up now on the device list in this
+ * case.
+ */
+ for (i = 0; !thread_data->xi2_current_slave && i < thread_data->xi2_device_count; i++)
{
if (devices[i].use != XISlavePointer) continue;
if (devices[i].deviceid != event->deviceid) continue;
if (devices[i].attachment != thread_data->xi2_core_pointer) continue;
thread_data->xi2_current_slave = event->deviceid;
- break;
}
- }
- if (event->deviceid != thread_data->xi2_current_slave) return FALSE;
+ /* Only listen to slave device events on XInput == 2.0 */
+ if (event->deviceid != thread_data->xi2_current_slave)
+ return FALSE;
+ }
+ else
+ {
+ /* Only listen to master device events on XInput >= 2.1 */
+ if (event->deviceid != thread_data->xi2_core_pointer)
+ return FALSE;
+ }
x_rel = &thread_data->x_rel_valuator;
y_rel = &thread_data->y_rel_valuator;
--
2.22.0
More information about the wine-devel
mailing list