[PATCH v7 6/7] winex11.drv: Implement native mouse-movement raw-input using RawMotion.

Rémi Bernon rbernon at codeweavers.com
Tue Jul 23 04:32:35 CDT 2019


On Sat, 2019-07-20 at 16:09 -0400, Derek Lesho wrote:
> Signed-off-by: Derek Lesho <dereklesho52 at Gmail.com>
> ---
>  dlls/winex11.drv/mouse.c       | 89 +++++++++++++++++++++++++++-------
>  dlls/winex11.drv/x11drv.h      |  4 +-
>  dlls/winex11.drv/x11drv_main.c |  4 ++
>  3 files changed, 79 insertions(+), 18 deletions(-)
> 
> diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c
> index f737a306a5..db71a33a41 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,19 @@ 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;
> +    static unsigned long last_time = 0;
>  
>      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,12 +1792,20 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
>      x_rel = &thread_data->x_rel_valuator;
>      y_rel = &thread_data->y_rel_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 );
>      input.u.mi.dwExtraInfo = 0;
> -    input.u.mi.dx          = 0;
> -    input.u.mi.dy          = 0;
> +    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.lLastX = 0;
> +    raw_input.data.mouse.lLastY = 0;
>  
>      virtual_rect = get_virtual_screen_rect();
>  
> @@ -1771,12 +1813,15 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev )
>      {
>          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.lLastX = raw_dx = raw_val;
>          }
>          if (i == y_rel->number)
>          {
> @@ -1784,6 +1829,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_input.data.mouse.lLastY = raw_dy = raw_val;
>          }
>      }
>  
> @@ -1793,10 +1840,18 @@ 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 );
> +    }
> +
> +    if (InterlockedExchange( (LONG volatile*)&last_time, (LONG)event->time ) != event->time)
> +    {
> +        TRACE("raw event %f,%f\n",  raw_dx, raw_dy);
> +        __wine_send_raw_input( &raw_input );
> +    }
>  
> -    input.type = INPUT_MOUSE;
> -    __wine_send_input( 0, &input );
>      return TRUE;
>  }

I think it /should/ be safe to only call __wine_send_raw_input here,
although not 100% sure about it.

AFAICS MotionNotify events are sent as well - even with a 0x0 clip
rectangle - and they will get translated to the corresponding WM_MOUSE*
and WM_*BUTTON* events, and update the desktop cursor position if
necessary. I understand that the call was here only to trigger the raw
input emulation.
-- 
Rémi Bernon <rbernon at codeweavers.com>




More information about the wine-devel mailing list