[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    Re: [PATCH v2 6/6] winex11.drv: Implement native mouse-movement raw-input using RawMotion.
From:       Derek Lesho <dereklesho52 () gmail ! com>
Date:       2019-06-30 2:57:21
Message-ID: CAHTquDJQjX0kyyqcwurYKJyaHuGJHiXApUj_n8wXszg=76nS+Q () mail ! gmail ! com
[Download RAW message or body]

[Attachment #2 (multipart/alternative)]


This patch had to be updated as multiple threads in a process were sending
identical rawinput messages and increasing sensitivity.

On Sat, Jun 29, 2019 at 10:26 PM Derek Lesho <dereklesho52@gmail.com> wrote:

> Signed-off-by: Derek Lesho <dereklesho52@Gmail.com>
> ---
>  dlls/winex11.drv/mouse.c       | 97 ++++++++++++++++++++++++++--------
>  dlls/winex11.drv/x11drv.h      |  6 ++-
>  dlls/winex11.drv/x11drv_main.c | 10 ++++
>  3 files changed, 90 insertions(+), 23 deletions(-)
>
> diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
> index f737a306a5..b5afbb04df 100644
> --- a/dlls/winex11.drv/mouse.c
> +++ b/dlls/winex11.drv/mouse.c
> @@ -284,11 +284,26 @@ static void update_relative_valuators(XIAnyClassInfo
> **valuators, int n_valuator
>  }
>  #endif
>
> +/***********************************************************************
> + *              inform_wineserver
> + */
> +static void inform_wineserver(void)
> +{
> +    static int once = 0;
> +    if (!once)
> +    {
> +        RAWINPUT raw_input;
> +        raw_input.header.dwType = RIM_ENABLE_NATIVE_MOUSE_MOVE;
> +        __wine_send_raw_input(&raw_input);
> +        once = 1;
> +    }
> +}
> +
>
>  /***********************************************************************
> - *              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();
> @@ -318,7 +333,6 @@ static void enable_xinput2(void)
>      memset( mask_bits, 0, sizeof(mask_bits) );
>      XISetMask( mask_bits, XI_DeviceChanged );
>      XISetMask( mask_bits, XI_RawMotion );
> -    XISetMask( mask_bits, XI_ButtonPress );
>
>      pXISelectEvents( data->display, DefaultRootWindow( data->display ),
> &mask, 1 );
>
> @@ -337,19 +351,21 @@ static void enable_xinput2(void)
>      data->xi2_current_slave = 0;
>
>      data->xi2_state = xi_enabled;
> +
> +    inform_wineserver();
>  #endif
>  }
>
>  /***********************************************************************
> - *              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;
> @@ -368,6 +384,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
> @@ -393,9 +424,9 @@ static BOOL grab_clipping_window( const RECT *clip )
>          return TRUE;
>
>      /* 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 );
> @@ -423,7 +454,7 @@ static BOOL grab_clipping_window( const RECT *clip )
>
>      if (!clipping_cursor)
>      {
> -        disable_xinput2();
> +        disable_xinput2_path();
>          DestroyWindow( msg_hwnd );
>          return FALSE;
>      }
> @@ -489,7 +520,7 @@ LRESULT clip_cursor_notify( HWND 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 */
> @@ -1724,16 +1755,18 @@ 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_dx = 0, raw_dy = 0, val, raw_val;
>      struct x11drv_thread_data *thread_data = x11drv_thread_data();
>      struct x11drv_valuator_data *x_rel, *y_rel;
>
>      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 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
> @@ -1758,25 +1791,21 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie
> *xev )
>      x_rel = &thread_data->x_rel_valuator;
>      y_rel = &thread_data->y_rel_valuator;
>
> -    input.u.mi.mouseData   = 0;
> -    input.u.mi.dwFlags     = MOUSEEVENTF_MOVE;
> -    input.u.mi.time        = EVENT_x11_time_to_win32_time( event->time );
> -    input.u.mi.dwExtraInfo = 0;
> -    input.u.mi.dx          = 0;
> -    input.u.mi.dy          = 0;
> -
>      virtual_rect = get_virtual_screen_rect();
>
>      for (i = 0; i <= max ( 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_dx = raw_val;
>          }
>          if (i == y_rel->number)
>          {
> @@ -1784,6 +1813,8 @@ 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_dy = raw_val;
>          }
>      }
>
> @@ -1793,10 +1824,32 @@ 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 );
> +    raw_input.data.mouse.lLastX = raw_dx;
> +    raw_input.data.mouse.lLastY = raw_dy;
> +    raw_input.data.mouse.u.usButtonFlags = 0;
> +    raw_input.data.mouse.u.usButtonData = 0;
> +    raw_input.data.mouse.ulExtraInformation = 0;
> +
> +    TRACE("raw event %f,%f\n",  raw_dx, raw_dy);
> +
> +    raw_input.header.dwType = RIM_TYPEMOUSE;
> +
> +    if ( LIST_ENTRY((&g_x11_threads)->next, struct x11drv_thread_data,
> entry) == thread_data )
> +        __wine_send_raw_input( &raw_input );
> +
> +    if (thread_data->xi2_state == xi_extra)
> +    {
> +        input.u.mi.mouseData   = 0;
> +        input.u.mi.dwFlags     = MOUSEEVENTF_MOVE;
> +        input.u.mi.time        = EVENT_x11_time_to_win32_time(
> event->time );
> +        input.u.mi.dwExtraInfo = 0;
> +
> +        TRACE( "pos %d,%d (event %f,%f)\n", input.u.mi.dx, input.u.mi.dy,
> dx, dy );
> +
> +        input.type = INPUT_MOUSE;
> +        __wine_send_input( 0, &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 a0308b0675..378c1d7508 100644
> --- a/dlls/winex11.drv/x11drv.h
> +++ b/dlls/winex11.drv/x11drv.h
> @@ -194,6 +194,8 @@ extern BOOL 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,
> @@ -335,14 +337,16 @@ 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;
>      int      xi2_core_pointer;     /* XInput2 core pointer id */
>      int      xi2_current_slave;    /* Current slave driving the Core
> pointer */
> +    struct   list entry;           /* Entry in global list of setup X11
> threads */
>  };
> +extern struct list g_x11_threads DECLSPEC_HIDDEN; /* Global list of setup
> X11 threads */
>
>  extern struct x11drv_thread_data *x11drv_init_thread_data(void)
> DECLSPEC_HIDDEN;
>  extern DWORD thread_data_tls_index DECLSPEC_HIDDEN;
> diff --git a/dlls/winex11.drv/x11drv_main.c
> b/dlls/winex11.drv/x11drv_main.c
> index e67a3c05a9..685b3dd0f4 100644
> --- a/dlls/winex11.drv/x11drv_main.c
> +++ b/dlls/winex11.drv/x11drv_main.c
> @@ -601,6 +601,9 @@ static BOOL process_attach(void)
>  }
>
>
> +struct list g_x11_threads = LIST_INIT( g_x11_threads );
> +
> +
>  /***********************************************************************
>   *           ThreadDetach (X11DRV.@)
>   */
> @@ -610,6 +613,9 @@ void CDECL X11DRV_ThreadDetach(void)
>
>      if (data)
>      {
> +        list_remove( &data->entry );
> +        X11DRV_XInput2_Disable();
> +
>          if (data->xim) XCloseIM( data->xim );
>          if (data->font_set) XFreeFontSet( data->display, data->font_set );
>          XCloseDisplay( data->display );
> @@ -680,6 +686,10 @@ struct x11drv_thread_data
> *x11drv_init_thread_data(void)
>
>      if (use_xim) X11DRV_SetupXIM();
>
> +    X11DRV_XInput2_Enable();
> +
> +    list_add_tail( &g_x11_threads, &data->entry );
> +
>      return data;
>  }
>
> --
> 2.21.0
>
>

[Attachment #5 (text/html)]

<div dir="ltr">This patch had to be updated as multiple threads in a process were \
sending identical rawinput messages and increasing sensitivity.</div><br><div \
class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sat, Jun 29, 2019 at 10:26 \
PM Derek Lesho &lt;<a \
href="mailto:dereklesho52@gmail.com">dereklesho52@gmail.com</a>&gt; \
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 &lt;dereklesho52@Gmail.com&gt;<br>
---<br>
  dlls/winex11.drv/mouse.c           | 97 ++++++++++++++++++++++++++--------<br>
  dlls/winex11.drv/x11drv.h         |   6 ++-<br>
  dlls/winex11.drv/x11drv_main.c | 10 ++++<br>
  3 files changed, 90 insertions(+), 23 deletions(-)<br>
<br>
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c<br>
index f737a306a5..b5afbb04df 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(&amp;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-&gt;display, DefaultRootWindow( data-&gt;display ), \
&amp;mask, 1 );<br> <br>
@@ -337,19 +351,21 @@ static void enable_xinput2(void)<br>
        data-&gt;xi2_current_slave = 0;<br>
<br>
        data-&gt;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-&gt;xi2_state != xi_enabled) return;<br>
+      if (data-&gt;xi2_state &lt; xi_enabled) return;<br>
<br>
        TRACE( &quot;disabling\n&quot; );<br>
        data-&gt;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-&gt;xi2_state == xi_enabled)<br>
+            thread_data-&gt;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-&gt;xi2_state == xi_extra)<br>
+            thread_data-&gt;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-&gt;clip_hwnd) enable_xinput2();<br>
+      if (!data-&gt;clip_hwnd) use_xinput2_path();<br>
<br>
-      if (data-&gt;xi2_state != xi_enabled)<br>
+      if (data-&gt;xi2_state &lt; xi_extra)<br>
        {<br>
              WARN( &quot;XInput2 not supported, refusing to clip to %s\n&quot;, \
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( &quot;clip hwnd reset from %p\n&quot;, hwnd );<br>
              data-&gt;clip_hwnd = 0;<br>
              data-&gt;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,18 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
  {<br>
        XIRawEvent *event = xev-&gt;data;<br>
        const double *values = event-&gt;valuators.values;<br>
+      const double *raw_values = event-&gt;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>
<br>
        if (thread_data-&gt;x_rel_valuator.number &lt; 0 || \
thread_data-&gt;y_rel_valuator.number &lt; 0) return FALSE;<br>  if \
                (!event-&gt;valuators.mask_len) return FALSE;<br>
-      if (thread_data-&gt;xi2_state != xi_enabled) return FALSE;<br>
+      if (thread_data-&gt;xi2_state &lt; 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,25 +1791,21 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
        x_rel = &amp;thread_data-&gt;x_rel_valuator;<br>
        y_rel = &amp;thread_data-&gt;y_rel_valuator;<br>
<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-&gt;time \
                );<br>
-      input.u.mi.dwExtraInfo = 0;<br>
-      input.u.mi.dx               = 0;<br>
-      input.u.mi.dy               = 0;<br>
-<br>
        virtual_rect = get_virtual_screen_rect();<br>
<br>
        for (i = 0; i &lt;= max ( x_rel-&gt;number, y_rel-&gt;number ); i++)<br>
        {<br>
              if (!XIMaskIsSet( event-&gt;valuators.mask, i )) continue;<br>
              val = *values++;<br>
+            raw_val = *raw_values++;<br>
              if (i == x_rel-&gt;number)<br>
              {<br>
                    input.u.mi.dx = dx = val;<br>
                    if (x_rel-&gt;min &lt; x_rel-&gt;max)<br>
                          input.u.mi.dx = val * (virtual_rect.right - \
                virtual_rect.left)<br>
                                                        / (x_rel-&gt;max - \
x_rel-&gt;min);<br> +<br>
+                  raw_dx = raw_val;<br>
              }<br>
              if (i == y_rel-&gt;number)<br>
              {<br>
@@ -1784,6 +1813,8 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
                    if (y_rel-&gt;min &lt; y_rel-&gt;max)<br>
                          input.u.mi.dy = val * (virtual_rect.bottom - \
                virtual_rect.top)<br>
                                                        / (y_rel-&gt;max - \
y_rel-&gt;min);<br> +<br>
+                  raw_dy = raw_val;<br>
              }<br>
        }<br>
<br>
@@ -1793,10 +1824,32 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )<br>
              return FALSE;<br>
        }<br>
<br>
-      TRACE( &quot;pos %d,%d (event %f,%f)\n&quot;, input.u.mi.dx, input.u.mi.dy, \
dx, dy );<br> +      raw_input.data.mouse.lLastX = raw_dx;<br>
+      raw_input.data.mouse.lLastY = raw_dy;<br>
+      raw_input.data.mouse.u.usButtonFlags = 0;<br>
+      raw_input.data.mouse.u.usButtonData = 0;<br>
+      raw_input.data.mouse.ulExtraInformation = 0;<br>
+<br>
+      TRACE(&quot;raw event %f,%f\n&quot;,   raw_dx, raw_dy);<br>
+<br>
+      raw_input.header.dwType = RIM_TYPEMOUSE;<br>
+<br>
+      if ( LIST_ENTRY((&amp;g_x11_threads)-&gt;next, struct x11drv_thread_data, \
entry) == thread_data )<br> +            __wine_send_raw_input( &amp;raw_input );<br>
+<br>
+      if (thread_data-&gt;xi2_state == xi_extra)<br>
+      {<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-&gt;time );<br> +            input.u.mi.dwExtraInfo = 0;<br>
+<br>
+            TRACE( &quot;pos %d,%d (event %f,%f)\n&quot;, input.u.mi.dx, \
input.u.mi.dy, dx, dy );<br> +<br>
+            input.type = INPUT_MOUSE;<br>
+            __wine_send_input( 0, &amp;input );<br>
+      }<br>
<br>
-      input.type = INPUT_MOUSE;<br>
-      __wine_send_input( 0, &amp;input );<br>
        return TRUE;<br>
  }<br>
<br>
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h<br>
index a0308b0675..378c1d7508 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,14 +337,16 @@ 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>
        struct x11drv_valuator_data y_rel_valuator;<br>
        int         xi2_core_pointer;        /* XInput2 core pointer id */<br>
        int         xi2_current_slave;      /* Current slave driving the Core pointer \
*/<br> +      struct     list entry;                 /* Entry in global list of setup \
X11 threads */<br>  };<br>
+extern struct list g_x11_threads DECLSPEC_HIDDEN; /* Global list of setup X11 \
threads */<br> <br>
  extern struct x11drv_thread_data *x11drv_init_thread_data(void) \
DECLSPEC_HIDDEN;<br>  extern DWORD thread_data_tls_index DECLSPEC_HIDDEN;<br>
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c<br>
index e67a3c05a9..685b3dd0f4 100644<br>
--- a/dlls/winex11.drv/x11drv_main.c<br>
+++ b/dlls/winex11.drv/x11drv_main.c<br>
@@ -601,6 +601,9 @@ static BOOL process_attach(void)<br>
  }<br>
<br>
<br>
+struct list g_x11_threads = LIST_INIT( g_x11_threads );<br>
+<br>
+<br>
  /***********************************************************************<br>
   *                 ThreadDetach (X11DRV.@)<br>
   */<br>
@@ -610,6 +613,9 @@ void CDECL X11DRV_ThreadDetach(void)<br>
<br>
        if (data)<br>
        {<br>
+            list_remove( &amp;data-&gt;entry );<br>
+            X11DRV_XInput2_Disable();<br>
+<br>
              if (data-&gt;xim) XCloseIM( data-&gt;xim );<br>
              if (data-&gt;font_set) XFreeFontSet( data-&gt;display, \
data-&gt;font_set );<br>  XCloseDisplay( data-&gt;display );<br>
@@ -680,6 +686,10 @@ struct x11drv_thread_data *x11drv_init_thread_data(void)<br>
<br>
        if (use_xim) X11DRV_SetupXIM();<br>
<br>
+      X11DRV_XInput2_Enable();<br>
+<br>
+      list_add_tail( &amp;g_x11_threads, &amp;data-&gt;entry );<br>
+<br>
        return data;<br>
  }<br>
<br>
-- <br>
2.21.0<br>
<br>
</blockquote></div>


[Attachment #6 (text/plain)]




[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic