From 22846605056d89063ec4c78b353f48d76b39b41f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 25 Mar 2021 16:12:58 +0100 Subject: [PATCH] winex11.drv: Listen to RawMotion and RawButton* events in the desktop thread. We still need to send "normal" input from the clipping window thread to trigger low-level hooks callbacks when clipping cursor. This is for instance used in our dinput implementation. --- dlls/winex11.drv/event.c | 10 ++- dlls/winex11.drv/mouse.c | 107 ++++++++++++++++++++++++++++++--- dlls/winex11.drv/x11drv.h | 1 + dlls/winex11.drv/x11drv_main.c | 4 ++ 4 files changed, 111 insertions(+), 11 deletions(-) diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 217c1eca857..8685ce9536b 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -328,6 +328,10 @@ static enum event_merge_action merge_raw_motion_events( XIRawEvent *prev, XIRawE */ static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) { +#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H + struct x11drv_thread_data *thread_data = x11drv_thread_data(); +#endif + switch (prev->type) { case ConfigureNotify: @@ -359,19 +363,21 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) case GenericEvent: if (next->xcookie.extension != xinput2_opcode) break; if (next->xcookie.evtype != XI_RawMotion) break; - if (x11drv_thread_data()->warp_serial) break; + if (thread_data->xi2_rawinput_only) break; + if (thread_data->warp_serial) break; return MERGE_KEEP; } break; case GenericEvent: if (prev->xcookie.extension != xinput2_opcode) break; if (prev->xcookie.evtype != XI_RawMotion) break; + if (thread_data->xi2_rawinput_only) break; switch (next->type) { case GenericEvent: if (next->xcookie.extension != xinput2_opcode) break; if (next->xcookie.evtype != XI_RawMotion) break; - if (x11drv_thread_data()->warp_serial) break; + if (thread_data->warp_serial) break; return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data ); #endif } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 6b6512521f4..0558467a805 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -422,7 +422,18 @@ void x11drv_xinput_enable( Display *display, Window window, long event_mask ) memset( mask_bits, 0, sizeof(mask_bits) ); XISetMask( mask_bits, XI_DeviceChanged ); XISetMask( mask_bits, XI_RawMotion ); - XISetMask( mask_bits, XI_ButtonPress ); + + if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) + { + XISetMask( mask_bits, XI_RawButtonPress ); + XISetMask( mask_bits, XI_RawButtonRelease ); + data->xi2_rawinput_only = TRUE; + } + else + { + XISetMask( mask_bits, XI_ButtonPress ); + data->xi2_rawinput_only = FALSE; + } pXISelectEvents( display, DefaultRootWindow( display ), &mask, 1 ); @@ -748,7 +759,6 @@ static void map_event_coords( HWND hwnd, Window window, Window event_root, int x static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPUT *input ) { struct x11drv_win_data *data; - RAWINPUT rawinput; input->type = INPUT_MOUSE; @@ -765,7 +775,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU sync_window_cursor( window ); last_cursor_change = input->u.mi.time; } - __wine_send_input( hwnd, input, &rawinput ); + __wine_send_input( hwnd, input, NULL ); return; } @@ -805,7 +815,7 @@ static void send_mouse_input( HWND hwnd, Window window, unsigned int state, INPU SERVER_END_REQ; } - __wine_send_input( hwnd, input, &rawinput ); + __wine_send_input( hwnd, input, NULL ); } #ifdef SONAME_LIBXCURSOR @@ -1760,7 +1770,6 @@ void move_resize_window( HWND hwnd, int dir ) { MSG msg; INPUT input; - RAWINPUT rawinput; int x, y, rootX, rootY; if (!XQueryPointer( display, root_window, &root, &child, &rootX, &rootY, &x, &y, &xstate )) break; @@ -1776,7 +1785,7 @@ void move_resize_window( HWND hwnd, int dir ) input.u.mi.dwFlags = button_up_flags[button - 1] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE; input.u.mi.time = GetTickCount(); input.u.mi.dwExtraInfo = 0; - __wine_send_input( hwnd, &input, &rawinput ); + __wine_send_input( hwnd, &input, NULL ); } while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) @@ -1952,6 +1961,7 @@ 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 ); @@ -1987,10 +1997,85 @@ 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_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, NULL ); + } + else + { + TRACE( "raw 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, &rawinput ); + rawinput.header.dwType = RIM_TYPEMOUSE; + rawinput.header.dwSize = offsetof(RAWINPUT, data) + sizeof(RAWMOUSE); + rawinput.header.hDevice = ULongToHandle(1); /* WINE_MOUSE_HANDLE */ + rawinput.header.wParam = RIM_INPUT; + rawinput.data.mouse.ulRawButtons = input.u.mi.dwFlags; + rawinput.data.mouse.u.ulButtons = input.u.mi.mouseData; + rawinput.data.mouse.lLastX = input.u.mi.dx; + rawinput.data.mouse.lLastY = input.u.mi.dy; + rawinput.data.mouse.ulExtraInformation = 0; + + input.type = INPUT_HARDWARE; + input.u.hi.uMsg = WM_INPUT; + input.u.hi.wParamH = (WORD)(rawinput.header.dwSize >> 16); + input.u.hi.wParamL = (WORD)(rawinput.header.dwSize >> 0); + if (rawinput.data.mouse.lLastX || rawinput.data.mouse.lLastY) + __wine_send_input( 0, &input, &rawinput ); + } + return TRUE; +} + +/*********************************************************************** + * X11DRV_RawButtonEvent + */ +static BOOL X11DRV_RawButtonEvent( XGenericEventCookie *cookie ) +{ + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + XIRawEvent *event = cookie->data; + int button = event->detail - 1; + RAWINPUT rawinput; + INPUT input; + + if (!device_mapping || device_mapping->deviceid != event->sourceid) + update_device_mapping( event->display, event->sourceid ); + + if (button >= 0 && device_mapping) + button = device_mapping->buttons[button] - 1; + + if (button >= 0 && pointer_mapping) + button = pointer_mapping->buttons[button] - 1; + + if (button < 0 || button >= NB_BUTTONS) return FALSE; + if (thread_data->xi2_state != xi_enabled) return FALSE; + if (event->deviceid != thread_data->xi2_core_pointer) return FALSE; + + TRACE( "raw button %u (raw: %u) %s\n", button, event->detail, event->evtype == XI_RawButtonRelease ? "up" : "down" ); + + rawinput.header.dwType = RIM_TYPEMOUSE; + rawinput.header.dwSize = offsetof(RAWINPUT, data) + sizeof(RAWMOUSE); + rawinput.header.hDevice = ULongToHandle(1); /* WINE_MOUSE_HANDLE */ + rawinput.header.wParam = RIM_INPUT; + if (event->evtype == XI_RawButtonRelease) + { + rawinput.data.mouse.ulRawButtons = button_up_flags[button]; + rawinput.data.mouse.u.ulButtons = button_up_data[button]; + } + else + { + rawinput.data.mouse.ulRawButtons = button_down_flags[button]; + rawinput.data.mouse.u.ulButtons = button_down_data[button]; + } + rawinput.data.mouse.lLastX = 0; + rawinput.data.mouse.lLastY = 0; + rawinput.data.mouse.ulExtraInformation = 0; + + input.type = INPUT_HARDWARE; + input.u.hi.uMsg = WM_INPUT; + input.u.hi.wParamH = (WORD)(rawinput.header.dwSize >> 16); + input.u.hi.wParamL = (WORD)(rawinput.header.dwSize >> 0); + if (rawinput.data.mouse.ulRawButtons || rawinput.data.mouse.u.ulButtons) + __wine_send_input( 0, &input, &rawinput ); return TRUE; } @@ -2066,6 +2151,10 @@ BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *xev ) case XI_RawMotion: ret = X11DRV_RawMotion( event ); break; + case XI_RawButtonPress: + case XI_RawButtonRelease: + ret = X11DRV_RawButtonEvent( event ); + break; default: TRACE( "Unhandled event %#x\n", event->evtype ); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index afa990b7e68..910a6c6cc18 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -353,6 +353,7 @@ struct x11drv_thread_data struct x11drv_valuator_data x_rel_valuator; struct x11drv_valuator_data y_rel_valuator; int xi2_core_pointer; /* XInput2 core pointer id */ + int xi2_rawinput_only; }; extern struct x11drv_thread_data *x11drv_init_thread_data(void) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index d8576949aea..c16825751c8 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -633,6 +633,8 @@ void CDECL X11DRV_ThreadDetach(void) if (data) { + if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) + x11drv_xinput_disable( data->display, DefaultRootWindow( data->display ), PointerMotionMask ); if (data->xim) XCloseIM( data->xim ); if (data->font_set) XFreeFontSet( data->display, data->font_set ); XCloseDisplay( data->display ); @@ -704,6 +706,8 @@ struct x11drv_thread_data *x11drv_init_thread_data(void) if (use_xim) X11DRV_SetupXIM(); x11drv_xinput_init(); + if (GetWindowThreadProcessId( GetDesktopWindow(), NULL ) == GetCurrentThreadId()) + x11drv_xinput_enable( data->display, DefaultRootWindow( data->display ), PointerMotionMask ); return data; } -- 2.30.2