<div dir="ltr">This version removes the whole g_x11_threads list as I realized not all of them receive events.  The new method of ensuring only one thread per process sending the events is much cleaner and should work 100% of the time.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jul 18, 2019 at 4:52 PM Derek Lesho <<a href="mailto:dereklesho52@gmail.com">dereklesho52@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Signed-off-by: Derek Lesho <dereklesho52@Gmail.com><br>
---<br>
 dlls/winex11.drv/mouse.c       | 89 +++++++++++++++++++++++++++-------<br>
 dlls/winex11.drv/x11drv.h      |  4 +-<br>
 dlls/winex11.drv/x11drv_main.c |  4 ++<br>
 3 files changed, 79 insertions(+), 18 deletions(-)<br>
<br>
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c<br>
index f737a306a5..a68844d328 100644<br>
--- a/dlls/winex11.drv/mouse.c<br>
+++ b/dlls/winex11.drv/mouse.c<br>
@@ -284,11 +284,26 @@ static void update_relative_valuators(XIAnyClassInfo **valuators, int n_valuator<br>
 }<br>
 #endif<br>
<br>
+/***********************************************************************<br>
+ *              inform_wineserver<br>
+ */<br>
+static void inform_wineserver(void)<br>
+{<br>
+    static int once = 0;<br>
+    if (!once)<br>
+    {<br>
+        RAWINPUT raw_input;<br>
+        raw_input.header.dwType = RIM_ENABLE_NATIVE_MOUSE_MOVE;<br>
+        __wine_send_raw_input(&raw_input);<br>
+        once = 1;<br>
+    }<br>
+}<br>
+<br>
<br>
 /***********************************************************************<br>
- *              enable_xinput2<br>
+ *              X11DRV_XInput2_Enable<br>
  */<br>
-static void enable_xinput2(void)<br>
+void X11DRV_XInput2_Enable(void)<br>
 {<br>
 #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H<br>
     struct x11drv_thread_data *data = x11drv_thread_data();<br>
@@ -318,7 +333,6 @@ static void enable_xinput2(void)<br>
     memset( mask_bits, 0, sizeof(mask_bits) );<br>
     XISetMask( mask_bits, XI_DeviceChanged );<br>
     XISetMask( mask_bits, XI_RawMotion );<br>
-    XISetMask( mask_bits, XI_ButtonPress );<br>
<br>
     pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 );<br>
<br>
@@ -337,19 +351,21 @@ static void enable_xinput2(void)<br>
     data->xi2_current_slave = 0;<br>
<br>
     data->xi2_state = xi_enabled;<br>
+<br>
+    inform_wineserver();<br>
 #endif<br>
 }<br>
<br>
 /***********************************************************************<br>
- *              disable_xinput2<br>
+ *              X11DRV_XInput2_Disable<br>
  */<br>
-static void disable_xinput2(void)<br>
+void X11DRV_XInput2_Disable(void)<br>
 {<br>
 #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H<br>
     struct x11drv_thread_data *data = x11drv_thread_data();<br>
     XIEventMask mask;<br>
<br>
-    if (data->xi2_state != xi_enabled) return;<br>
+    if (data->xi2_state < xi_enabled) return;<br>
<br>
     TRACE( "disabling\n" );<br>
     data->xi2_state = xi_disabled;<br>
@@ -368,6 +384,21 @@ static void disable_xinput2(void)<br>
 #endif<br>
 }<br>
<br>
+static void use_xinput2_path(void)<br>
+{<br>
+    struct x11drv_thread_data *thread_data = x11drv_thread_data();<br>
+<br>
+    if (thread_data->xi2_state == xi_enabled)<br>
+        thread_data->xi2_state = xi_extra;<br>
+}<br>
+<br>
+static void disable_xinput2_path(void)<br>
+{<br>
+    struct x11drv_thread_data *thread_data = x11drv_thread_data();<br>
+<br>
+    if (thread_data->xi2_state == xi_extra)<br>
+        thread_data->xi2_state = xi_enabled;<br>
+}<br>
<br>
 /***********************************************************************<br>
  *             grab_clipping_window<br>
@@ -393,9 +424,9 @@ static BOOL grab_clipping_window( const RECT *clip )<br>
         return TRUE;<br>
<br>
     /* enable XInput2 unless we are already clipping */<br>
-    if (!data->clip_hwnd) enable_xinput2();<br>
+    if (!data->clip_hwnd) use_xinput2_path();<br>
<br>
-    if (data->xi2_state != xi_enabled)<br>
+    if (data->xi2_state < xi_extra)<br>
     {<br>
         WARN( "XInput2 not supported, refusing to clip to %s\n", wine_dbgstr_rect(clip) );<br>
         DestroyWindow( msg_hwnd );<br>
@@ -423,7 +454,7 @@ static BOOL grab_clipping_window( const RECT *clip )<br>
<br>
     if (!clipping_cursor)<br>
     {<br>
-        disable_xinput2();<br>
+        disable_xinput2_path();<br>
         DestroyWindow( msg_hwnd );<br>
         return FALSE;<br>
     }<br>
@@ -489,7 +520,7 @@ LRESULT clip_cursor_notify( HWND hwnd, HWND new_clip_hwnd )<br>
         TRACE( "clip hwnd reset from %p\n", hwnd );<br>
         data->clip_hwnd = 0;<br>
         data->clip_reset = GetTickCount();<br>
-        disable_xinput2();<br>
+        disable_xinput2_path();<br>
         DestroyWindow( hwnd );<br>
     }<br>
     else if (hwnd == GetForegroundWindow())  /* request to clip */<br>
@@ -1724,16 +1755,19 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
 {<br>
     XIRawEvent *event = xev->data;<br>
     const double *values = event->valuators.values;<br>
+    const double *raw_values = event->raw_values;<br>
     RECT virtual_rect;<br>
     INPUT input;<br>
+    RAWINPUT raw_input;<br>
     int i;<br>
-    double dx = 0, dy = 0, val;<br>
+    double dx = 0, dy = 0, raw_dx = 0, raw_dy = 0, val, raw_val;<br>
     struct x11drv_thread_data *thread_data = x11drv_thread_data();<br>
     struct x11drv_valuator_data *x_rel, *y_rel;<br>
+    static unsigned int last_cookie = 0;<br>
<br>
     if (thread_data->x_rel_valuator.number < 0 || thread_data->y_rel_valuator.number < 0) return FALSE;<br>
     if (!event->valuators.mask_len) return FALSE;<br>
-    if (thread_data->xi2_state != xi_enabled) return FALSE;<br>
+    if (thread_data->xi2_state < xi_enabled) return FALSE;<br>
<br>
     /* If there is no slave currently detected, no previous motion nor device<br>
      * change events were received. Look it up now on the device list in this<br>
@@ -1758,12 +1792,20 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
     x_rel = &thread_data->x_rel_valuator;<br>
     y_rel = &thread_data->y_rel_valuator;<br>
<br>
+    input.type = INPUT_MOUSE;<br>
     input.u.mi.mouseData   = 0;<br>
     input.u.mi.dwFlags     = MOUSEEVENTF_MOVE;<br>
     input.u.mi.time        = EVENT_x11_time_to_win32_time( event->time );<br>
     input.u.mi.dwExtraInfo = 0;<br>
-    input.u.mi.dx          = 0;<br>
-    input.u.mi.dy          = 0;<br>
+    input.u.mi.dx = 0;<br>
+    input.u.mi.dy = 0;<br>
+<br>
+    raw_input.header.dwType = RIM_TYPEMOUSE;<br>
+    raw_input.data.mouse.u.usButtonFlags = 0;<br>
+    raw_input.data.mouse.u.usButtonData = 0;<br>
+    raw_input.data.mouse.ulExtraInformation = 0;<br>
+    raw_input.data.mouse.lLastX = 0;<br>
+    raw_input.data.mouse.lLastY = 0;<br>
<br>
     virtual_rect = get_virtual_screen_rect();<br>
<br>
@@ -1771,12 +1813,15 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
     {<br>
         if (!XIMaskIsSet( event->valuators.mask, i )) continue;<br>
         val = *values++;<br>
+        raw_val = *raw_values++;<br>
         if (i == x_rel->number)<br>
         {<br>
             input.u.mi.dx = dx = val;<br>
             if (x_rel->min < x_rel->max)<br>
                 input.u.mi.dx = val * (virtual_rect.right - virtual_rect.left)<br>
                                     / (x_rel->max - x_rel->min);<br>
+<br>
+            raw_input.data.mouse.lLastX = raw_dx = raw_val;<br>
         }<br>
         if (i == y_rel->number)<br>
         {<br>
@@ -1784,6 +1829,8 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
             if (y_rel->min < y_rel->max)<br>
                 input.u.mi.dy = val * (virtual_rect.bottom - virtual_rect.top)<br>
                                     / (y_rel->max - y_rel->min);<br>
+<br>
+            raw_input.data.mouse.lLastY = raw_dy = raw_val;<br>
         }<br>
     }<br>
<br>
@@ -1793,10 +1840,18 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
         return FALSE;<br>
     }<br>
<br>
-    TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );<br>
+    if (thread_data->xi2_state == xi_extra)<br>
+    {<br>
+        TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy, dx, dy );<br>
+        __wine_send_input( 0, &input );<br>
+    }<br>
+<br>
+    if (InterlockedExchange(&last_cookie, xev->cookie) != xev->cookie)<br>
+    {<br>
+        TRACE("raw event %f,%f\n",  raw_dx, raw_dy);<br>
+        __wine_send_raw_input( &raw_input );<br>
+    }<br>
<br>
-    input.type = INPUT_MOUSE;<br>
-    __wine_send_input( 0, &input );<br>
     return TRUE;<br>
 }<br>
<br>
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h<br>
index a0308b0675..a9138eef2a 100644<br>
--- a/dlls/winex11.drv/x11drv.h<br>
+++ b/dlls/winex11.drv/x11drv.h<br>
@@ -194,6 +194,8 @@ extern BOOL X11DRV_UnrealizePalette( HPALETTE hpal ) DECLSPEC_HIDDEN;<br>
<br>
 extern void X11DRV_Xcursor_Init(void) DECLSPEC_HIDDEN;<br>
 extern void X11DRV_XInput2_Init(void) DECLSPEC_HIDDEN;<br>
+extern void X11DRV_XInput2_Enable(void) DECLSPEC_HIDDEN;<br>
+extern void X11DRV_XInput2_Disable(void) DECLSPEC_HIDDEN;<br>
<br>
 extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image,<br>
                               const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits,<br>
@@ -335,7 +337,7 @@ struct x11drv_thread_data<br>
     HWND     clip_hwnd;            /* message window stored in desktop while clipping is active */<br>
     DWORD    clip_reset;           /* time when clipping was last reset */<br>
     HKL      kbd_layout;           /* active keyboard layout */<br>
-    enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled } xi2_state; /* XInput2 state */<br>
+    enum { xi_unavailable = -1, xi_unknown, xi_disabled, xi_enabled, xi_extra } xi2_state; /* XInput2 state */<br>
     void    *xi2_devices;          /* list of XInput2 devices (valid when state is enabled) */<br>
     int      xi2_device_count;<br>
     struct x11drv_valuator_data x_rel_valuator;<br>
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c<br>
index e67a3c05a9..351ab89781 100644<br>
--- a/dlls/winex11.drv/x11drv_main.c<br>
+++ b/dlls/winex11.drv/x11drv_main.c<br>
@@ -610,6 +610,8 @@ void CDECL X11DRV_ThreadDetach(void)<br>
<br>
     if (data)<br>
     {<br>
+        X11DRV_XInput2_Disable();<br>
+<br>
         if (data->xim) XCloseIM( data->xim );<br>
         if (data->font_set) XFreeFontSet( data->display, data->font_set );<br>
         XCloseDisplay( data->display );<br>
@@ -680,6 +682,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)<br>
<br>
     if (use_xim) X11DRV_SetupXIM();<br>
<br>
+    X11DRV_XInput2_Enable();<br>
+<br>
     return data;<br>
 }<br>
<br>
-- <br>
2.22.0<br>
<br>
</blockquote></div>