Under XInput2 protocol version < 2.1, RawEvents are not supposed to be sent if a pointer grab is active. However slave device events are still received regardless of this specification and Wine implemented a workaround to receive RawEvents during pointer grabs by listening to these slave device events.
However as soon as a mouse button is pressed, only the grabbing client will receive the raw motion events.
By advertising the support of XInput2 version >= 2.1, where rawevents are sent even during pointer grabs, we ensure to receive the RawMotion events from the desktop window thread, even if a mouse grab is active.
It is also possible to simplify the code by listening to master device events only and get rid of slave device id tracking.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winex11.drv/mouse.c | 49 ++++++++------------------------------- dlls/winex11.drv/x11drv.h | 3 --- 2 files changed, 10 insertions(+), 42 deletions(-)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index cedb488614d..2c68e68a992 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -304,12 +304,16 @@ 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; + int major = 2, minor = 1; + if (!pXIQueryVersion( data->display, &major, &minor ) && major == 2 && minor > 0) + { + TRACE( "XInput2 v%d.%d available\n", major, minor ); + data->xi2_state = xi_disabled; + } else { data->xi2_state = xi_unavailable; - WARN( "X Input 2 not available\n" ); + WARN( "XInput v2.1 not available\n" ); } } if (data->xi2_state == xi_unavailable) return; @@ -317,7 +321,7 @@ 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 ); @@ -329,16 +333,6 @@ static void enable_xinput2(void) update_relative_valuators( pointer_info->classes, pointer_info->num_classes ); pXIFreeDeviceInfo( pointer_info );
- /* This device info list is only used to find the initial current slave if - * no XI_DeviceChanged events happened. If any hierarchy change occurred that - * might be relevant here (eg. user switching mice after (un)plugging), a - * XI_DeviceChanged event will point us to the right slave. So this list is - * 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_current_slave = 0; - data->xi2_state = xi_enabled; #endif } @@ -359,15 +353,12 @@ static void disable_xinput2(void)
mask.mask = NULL; mask.mask_len = 0; - mask.deviceid = XIAllDevices; + mask.deviceid = XIAllMasterDevices;
pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 ); - pXIFreeDeviceInfo( data->xi2_devices ); data->x_rel_valuator.number = -1; data->y_rel_valuator.number = -1; - data->xi2_devices = NULL; data->xi2_core_pointer = 0; - data->xi2_current_slave = 0; #endif }
@@ -1763,7 +1754,6 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev ) if (event->reason != XISlaveSwitch) return FALSE;
update_relative_valuators( event->classes, event->num_classes ); - data->xi2_current_slave = event->sourceid; return TRUE; }
@@ -1784,26 +1774,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) if (thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) return FALSE; 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) - { - XIDeviceInfo *devices = thread_data->xi2_devices; - - for (i = 0; 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; + if (event->deviceid != thread_data->xi2_core_pointer) return FALSE;
x_rel = &thread_data->x_rel_valuator; y_rel = &thread_data->y_rel_valuator; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index d4e476facb2..7dd8c158617 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -336,12 +336,9 @@ struct x11drv_thread_data DWORD clip_reset; /* time when clipping was last reset */ HKL kbd_layout; /* active keyboard layout */ enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */ - void *xi2_devices; /* list of XInput2 devices (valid when state is enabled) */ - int xi2_device_count; struct x11drv_valuator_data x_rel_valuator; struct x11drv_valuator_data y_rel_valuator; int xi2_core_pointer; /* XInput2 core pointer id */ - int xi2_current_slave; /* Current slave driving the Core pointer */ };
extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN;