From 5ce9048468f363c5f844a35327aecc40d8304c9b Mon Sep 17 00:00:00 2001 From: Derek Lesho Date: Tue, 25 Jun 2019 22:37:34 -0400 Subject: [PATCH] winex11.drv: Implement native mouse-movement raw-input using RawMotion. Signed-off-by: Derek Lesho --- dlls/winex11.drv/mouse.c | 102 +++++++++++++++++++++++++++------ dlls/winex11.drv/x11drv.h | 8 ++- dlls/winex11.drv/x11drv_main.c | 6 ++ 3 files changed, 97 insertions(+), 19 deletions(-) diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 23c7c6fb35b..212511fde84 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -262,6 +262,8 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator thread_data->x_rel_valuator.number = -1; thread_data->y_rel_valuator.number = -1; + thread_data->x_abs_valuator.number = -1; + thread_data->y_abs_valuator.number = -1; for (i = 0; i < n_valuators; i++) { @@ -279,6 +281,16 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator { valuator_data = &thread_data->y_rel_valuator; } + else if (class->label == x11drv_atom( Abs_X ) || + (!class->label && class->number == 0 && class->mode == XIModeAbsolute)) + { + valuator_data = &thread_data->x_abs_valuator; + } + else if (class->label == x11drv_atom( Abs_Y ) || + (!class->label && class->number == 1 && class->mode == XIModeAbsolute)) + { + valuator_data = &thread_data->y_abs_valuator; + } if (valuator_data) { valuator_data->number = class->number; @@ -291,9 +303,9 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator /*********************************************************************** - * enable_xinput2 + * X11DRV_XInput2_Enable */ -static void enable_xinput2(void) +void X11DRV_XInput2_Enable(void) { #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H struct x11drv_thread_data *data = x11drv_thread_data(); @@ -324,8 +336,8 @@ static void enable_xinput2(void) mask.mask_len = sizeof(mask_bits); 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 ); XISetMask( mask_bits, XI_DeviceChanged ); /* XInput 2.0 has a problematic behavior where master pointer will @@ -357,15 +369,15 @@ static void enable_xinput2(void) } /*********************************************************************** - * disable_xinput2 + * X11DRV_XInput2_Disable */ -static void disable_xinput2(void) +void X11DRV_XInput2_Disable(void) { #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H struct x11drv_thread_data *data = x11drv_thread_data(); XIEventMask mask; - if (data->xi2_state != xi_enabled) return; + if (data->xi2_state < xi_enabled) return; TRACE( "disabling\n" ); data->xi2_state = xi_disabled; @@ -390,6 +402,21 @@ static void disable_xinput2(void) #endif } +static void use_xinput2_path(void) +{ + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + + if (thread_data->xi2_state == xi_enabled) + thread_data->xi2_state = xi_extra; +} + +static void disable_xinput2_path(void) +{ + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + + if (thread_data->xi2_state == xi_extra) + thread_data->xi2_state = xi_enabled; +} /*********************************************************************** * grab_clipping_window @@ -428,9 +455,9 @@ static BOOL grab_clipping_window( const RECT *clip ) } /* enable XInput2 unless we are already clipping */ - if (!data->clip_hwnd) enable_xinput2(); + if (!data->clip_hwnd) use_xinput2_path(); - if (data->xi2_state != xi_enabled) + if (data->xi2_state < xi_extra) { WARN( "XInput2 not supported, refusing to clip to %s\n", wine_dbgstr_rect(clip) ); DestroyWindow( msg_hwnd ); @@ -458,7 +485,7 @@ static BOOL grab_clipping_window( const RECT *clip ) if (!clipping_cursor) { - disable_xinput2(); + disable_xinput2_path(); DestroyWindow( msg_hwnd ); return FALSE; } @@ -539,7 +566,7 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND prev_clip_hwnd, HWND new_clip_hwnd ) TRACE( "clip hwnd reset from %p\n", hwnd ); data->clip_hwnd = 0; data->clip_reset = GetTickCount(); - disable_xinput2(); + disable_xinput2_path(); DestroyWindow( hwnd ); } else if (hwnd == GetForegroundWindow()) /* request to clip */ @@ -1801,16 +1828,20 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) { XIRawEvent *event = xev->data; const double *values = event->valuators.values; + const double *raw_values = event->raw_values; RECT virtual_rect; INPUT input; + RAWINPUT raw_input; int i; - double dx = 0, dy = 0, val; + double dx = 0, dy = 0, raw_x = 0, raw_y = 0, val, raw_val; struct x11drv_thread_data *thread_data = x11drv_thread_data(); - struct x11drv_valuator_data *x_rel, *y_rel; + struct x11drv_valuator_data *x_rel, *y_rel, *x_abs, *y_abs; + + if ((thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) && + (thread_data->x_abs_valuator.number < 0 || thread_data->y_abs_valuator.number < 0) return FALSE; - 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 (thread_data->xi2_state < xi_enabled) return FALSE; if (xinput2_version_major == 2 && xinput2_version_minor == 0) { @@ -1841,7 +1872,10 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) x_rel = &thread_data->x_rel_valuator; y_rel = &thread_data->y_rel_valuator; + x_abs = &thread_data->x_abs_valuator; + y_abs = &thread_data->y_abs_valuator; + input.type = INPUT_MOUSE; input.u.mi.mouseData = 0; input.u.mi.dwFlags = MOUSEEVENTF_MOVE; input.u.mi.time = EVENT_x11_time_to_win32_time( event->time ); @@ -1849,18 +1883,31 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) input.u.mi.dx = 0; input.u.mi.dy = 0; + raw_input.header.dwType = RIM_TYPEMOUSE; + raw_input.data.mouse.u.usButtonFlags = 0; + raw_input.data.mouse.u.usButtonData = 0; + raw_input.data.mouse.ulExtraInformation = 0; + raw_input.data.mouse.ulRawButtons = 0; + raw_input.data.mouse.usFlags = 0; + raw_input.data.mouse.lLastX = 0; + raw_input.data.mouse.lLastY = 0; + virtual_rect = get_virtual_screen_rect(); - for (i = 0; i <= max ( x_rel->number, y_rel->number ); i++) + for (i = 0; i <= max(max(max( x_abs->number, y_abs->number), x_rel->number), y_rel->number); i++) { if (!XIMaskIsSet( event->valuators.mask, i )) continue; val = *values++; + raw_val = *raw_values++; if (i == x_rel->number) { input.u.mi.dx = dx = val; if (x_rel->min < x_rel->max) input.u.mi.dx = val * (virtual_rect.right - virtual_rect.left) / (x_rel->max - x_rel->min); + + raw_input.data.mouse.usFlags = MOUSE_MOVE_RELATIVE; + raw_input.data.mouse.lLastX = raw_x = raw_val; } if (i == y_rel->number) { @@ -1868,6 +1915,19 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) if (y_rel->min < y_rel->max) input.u.mi.dy = val * (virtual_rect.bottom - virtual_rect.top) / (y_rel->max - y_rel->min); + + raw_input.data.mouse.usFlags = MOUSE_MOVE_RELATIVE; + raw_input.data.mouse.lLastY = raw_y = raw_val; + } + if (i == x_abs->number) + { + raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP; + raw_input.data.mouse.lLastX = raw_x = raw_val * (65536 / (x_abs->max - x_abs->min)); + } + if (i == y_abs->number) + { + raw_input.data.mouse.usFlags = MOUSE_MOVE_ABSOLUTE | MOUSE_VIRTUAL_DESKTOP; + raw_input.data.mouse.lLastY = raw_y = raw_val * (65536 / (y_abs->max - y_abs->min)); } } @@ -1877,10 +1937,16 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) return FALSE; } - TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); + if (thread_data->xi2_state == xi_extra) + { + TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); + __wine_send_input( 0, &input ); + } + + TRACE("raw %s event %f,%f\n", + raw_input.data.mouse.usFlags ? "absolute" : "relative", raw_x, raw_y); + __wine_send_raw_input( &raw_input ); - input.type = INPUT_MOUSE; - __wine_send_input( 0, &input ); return TRUE; } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index b8cfda43410..d79c78ecbc9 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -194,6 +194,8 @@ extern BOOL CDECL X11DRV_UnrealizePalette( HPALETTE hpal ) DECLSPEC_HIDDEN; extern void X11DRV_Xcursor_Init(void) DECLSPEC_HIDDEN; extern void X11DRV_XInput2_Init(void) DECLSPEC_HIDDEN; +extern void X11DRV_XInput2_Enable(void) DECLSPEC_HIDDEN; +extern void X11DRV_XInput2_Disable(void) DECLSPEC_HIDDEN; extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits, @@ -336,11 +338,13 @@ struct x11drv_thread_data HWND clip_hwnd; /* message window stored in desktop while clipping is active */ 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 */ + enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled, xi_extra } 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; + struct x11drv_valuator_data x_abs_valuator; + struct x11drv_valuator_data y_abs_valuator; int xi2_core_pointer; /* XInput2 core pointer id */ int xi2_current_slave; /* Current slave driving the Core pointer */ }; @@ -427,6 +431,8 @@ enum x11drv_atoms XATOM_RAW_CAP_HEIGHT, XATOM_Rel_X, XATOM_Rel_Y, + XATOM_Abs_X, + XATOM_Abs_Y, XATOM_WM_PROTOCOLS, XATOM_WM_DELETE_WINDOW, XATOM_WM_STATE, diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 54de5d8a6b0..9f896bddd9a 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -120,6 +120,8 @@ static const char * const atom_names[NB_XATOMS - FIRST_XATOM] = "RAW_CAP_HEIGHT", "Rel X", "Rel Y", + "Abs X", + "Abs Y", "WM_PROTOCOLS", "WM_DELETE_WINDOW", "WM_STATE", @@ -611,6 +613,8 @@ void CDECL X11DRV_ThreadDetach(void) if (data) { + X11DRV_XInput2_Disable(); + if (data->xim) XCloseIM( data->xim ); if (data->font_set) XFreeFontSet( data->display, data->font_set ); XCloseDisplay( data->display ); @@ -684,6 +688,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) if (use_xim) X11DRV_SetupXIM(); + X11DRV_XInput2_Enable(); + return data; } -- 2.23.0