From e53124abe8f6eaeebdb8ccb75cd884543f63a996 Mon Sep 17 00:00:00 2001 From: Jordan Galby Date: Tue, 16 Jul 2019 00:34:38 -0400 Subject: [PATCH 3/3] winex11.drv: Accumulate mouse movement to avoid rounding losses. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42631 From: Jordan Galby --- dlls/winex11.drv/mouse.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index a2310297ff9..e1273571fe2 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -367,6 +367,9 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator thread_data->x_pos_valuator.min = thread_data->x_pos_valuator.max = 0; if (thread_data->y_pos_valuator.min >= thread_data->y_pos_valuator.max) thread_data->y_pos_valuator.min = thread_data->y_pos_valuator.max = 0; + + thread_data->x_pos_valuator.value = 0; + thread_data->y_pos_valuator.value = 0; } #endif @@ -1906,6 +1909,7 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) double dx = 0, dy = 0, val; double raw_dx = 0, raw_dy = 0, raw_val; double x_scale = 1, y_scale = 1; + double x_accum = 0, y_accum = 0; struct x11drv_thread_data *thread_data = x11drv_thread_data(); XIValuatorClassInfo *x_pos, *y_pos; @@ -1917,6 +1921,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) x_pos = &thread_data->x_pos_valuator; y_pos = &thread_data->y_pos_valuator; + x_accum = x_pos->value; + y_accum = y_pos->value; + input.type = INPUT_MOUSE; input.u.mi.mouseData = 0; input.u.mi.dwFlags = MOUSEEVENTF_MOVE; @@ -1944,9 +1951,9 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) raw_dx = raw_val; input.u.mi.dwFlags |= (x_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0); if (x_pos->mode == XIModeAbsolute) - input.u.mi.dx = (dx - x_pos->min) * x_scale; + x_accum = (dx - x_pos->min) * x_scale; else - input.u.mi.dx = dx * x_scale; + x_accum += dx * x_scale; } if (i == y_pos->number) { @@ -1954,18 +1961,30 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) raw_dy = raw_val; input.u.mi.dwFlags |= (y_pos->mode == XIModeAbsolute ? MOUSEEVENTF_ABSOLUTE : 0); if (y_pos->mode == XIModeAbsolute) - input.u.mi.dy = (dy - y_pos->min) * y_scale; + y_accum = (dy - y_pos->min) * y_scale; else - input.u.mi.dy = dy * y_scale; + y_accum += dy * y_scale; } } + /* Accumulate the fractional parts so they aren't lost after casting + * successive motion values to integral fields. + * + * Note: It looks like raw_dx, raw_dy are already + * integral values but that may be wrong. + */ + input.u.mi.dx = (LONG)x_accum; + input.u.mi.dy = (LONG)y_accum; + if (broken_rawevents && is_old_motion_event( xev->serial )) { TRACE( "pos %d,%d old serial %lu, ignoring\n", input.u.mi.dx, input.u.mi.dy, xev->serial ); return FALSE; } + x_pos->value = x_accum - input.u.mi.dx; + y_pos->value = y_accum - input.u.mi.dy; + if (x_pos->mode == XIModeAbsolute) { TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); @@ -1973,14 +1992,21 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) } else if (!thread_data->xi2_rawinput_only) { - TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); - __wine_send_input( 0, &input, SEND_HWMSG_WINDOW ); + if ((dy || dy) && !(input.u.mi.dx || input.u.mi.dy)) + { + TRACE( "accumulating raw motion (event %f,%f accum %f,%f)\n", dx, dy, x_pos->value, y_pos->value ); + } + else + { + TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); + __wine_send_input( 0, &input, SEND_HWMSG_WINDOW ); + } } else { input.u.mi.dx = raw_dx; input.u.mi.dy = raw_dy; - TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy ); + TRACE( "raw pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, raw_dx, raw_dy ); __wine_send_input( 0, &input, SEND_HWMSG_RAWINPUT ); } return TRUE; -- 2.24.1