-- v2: winex11: Select XI_Touch* input and translate it to WM_POINTER*. winex11: Support XInput2 events on individual windows.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/desktop.c | 2 ++ dlls/winex11.drv/mouse.c | 56 ++++++++++++++++++++++++-------------- dlls/winex11.drv/window.c | 9 +++++- dlls/winex11.drv/x11drv.h | 2 ++ 4 files changed, 48 insertions(+), 21 deletions(-)
diff --git a/dlls/winex11.drv/desktop.c b/dlls/winex11.drv/desktop.c index d6fa078e8a9..cb119c9a7be 100644 --- a/dlls/winex11.drv/desktop.c +++ b/dlls/winex11.drv/desktop.c @@ -86,6 +86,8 @@ BOOL X11DRV_CreateDesktop( const WCHAR *name, UINT width, UINT height ) 0, 0, width, height, 0, default_visual.depth, InputOutput, default_visual.visual, CWEventMask | CWCursor | CWColormap, &win_attr ); if (!win) return FALSE; + + x11drv_xinput2_enable( display, win ); XFlush( display );
X11DRV_init_desktop( win, width, height ); diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 03c2152b76b..19a82d23ab0 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -253,11 +253,10 @@ static void update_relative_valuators( XIAnyClassInfo **classes, int num_classes
/*********************************************************************** - * enable_xinput2 + * x11drv_xinput2_enable */ -static void enable_xinput2(void) +void x11drv_xinput2_enable( Display *display, Window window ) { - struct x11drv_thread_data *data = x11drv_thread_data(); XIEventMask mask; unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)];
@@ -267,21 +266,23 @@ static void enable_xinput2(void) mask.mask_len = sizeof(mask_bits); mask.deviceid = XIAllMasterDevices; 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 ); + + if (window == DefaultRootWindow( display )) + { + XISetMask( mask_bits, XI_DeviceChanged ); + XISetMask( mask_bits, XI_RawMotion ); + XISetMask( mask_bits, XI_ButtonPress ); + } + + pXISelectEvents( display, window, &mask, 1 ); }
-#endif
/*********************************************************************** - * disable_xinput2 + * x11drv_xinput2_disable */ -static void disable_xinput2(void) +void x11drv_xinput2_disable( Display *display, Window window ) { -#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H - struct x11drv_thread_data *data = x11drv_thread_data(); unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)]; XIEventMask mask;
@@ -291,9 +292,11 @@ static void disable_xinput2(void) mask.mask_len = sizeof(mask_bits); mask.deviceid = XIAllMasterDevices; memset( mask_bits, 0, sizeof(mask_bits) ); - XISetMask( mask_bits, XI_DeviceChanged ); - pXISelectEvents( data->display, DefaultRootWindow( data->display ), &mask, 1 ); -#endif + + if (window == DefaultRootWindow( display )) + XISetMask( mask_bits, XI_DeviceChanged ); + + pXISelectEvents( display, window, &mask, 1 ); }
@@ -302,7 +305,6 @@ static void disable_xinput2(void) */ void x11drv_xinput2_init( struct x11drv_thread_data *data ) { -#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H unsigned char mask_bits[XIMaskLen(XI_LASTEVENT)]; int major = 2, minor = 2; XIEventMask mask; @@ -332,9 +334,23 @@ void x11drv_xinput2_init( struct x11drv_thread_data *data ) }
TRACE( "XInput2 %d.%d available\n", major, minor ); -#endif }
+#else /* HAVE_X11_EXTENSIONS_XINPUT2_H */ + +void x11drv_xinput2_enable( Display *display, Window window ) +{ +} + +void x11drv_xinput2_disable( Display *display, Window window ) +{ +} + +void x11drv_xinput2_init( struct x11drv_thread_data *data ) +{ +} + +#endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */
/*********************************************************************** * grab_clipping_window @@ -370,7 +386,7 @@ static BOOL grab_clipping_window( const RECT *clip ) }
/* enable XInput2 unless we are already clipping */ - if (!data->clipping_cursor) enable_xinput2(); + if (!data->clipping_cursor) x11drv_xinput2_enable( data->display, DefaultRootWindow( data->display ) );
TRACE( "clipping to %s win %lx\n", wine_dbgstr_rect(clip), clip_window );
@@ -403,7 +419,7 @@ static BOOL grab_clipping_window( const RECT *clip )
if (!clipping_cursor) { - disable_xinput2(); + x11drv_xinput2_disable( data->display, DefaultRootWindow( data->display ) ); return FALSE; } clip_rect = *clip; @@ -432,7 +448,7 @@ void ungrab_clipping_window(void) if (clipping_cursor) XUngrabPointer( data->display, CurrentTime ); clipping_cursor = FALSE; data->clipping_cursor = FALSE; - disable_xinput2(); + x11drv_xinput2_disable( data->display, DefaultRootWindow( data->display ) ); }
/*********************************************************************** diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 84878e95e37..afa13f01277 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -362,6 +362,7 @@ static void sync_window_style( struct x11drv_win_data *data ) int mask = get_window_attributes( data, &attr );
XChangeWindowAttributes( data->display, data->whole_window, mask, &attr ); + x11drv_xinput2_enable( data->display, data->whole_window ); } }
@@ -1700,6 +1701,7 @@ static void create_whole_window( struct x11drv_win_data *data ) data->vis.visual, mask, &attr ); if (!data->whole_window) goto done;
+ x11drv_xinput2_enable( data->display, data->whole_window ); set_initial_wm_hints( data->display, data->whole_window ); set_wm_hints( data );
@@ -1742,7 +1744,12 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des Window xwin = (Window)NtUserGetProp( data->hwnd, foreign_window_prop ); if (xwin) { - if (!already_destroyed) XSelectInput( data->display, xwin, 0 ); + if (!already_destroyed) + { + x11drv_xinput2_disable( data->display, xwin ); + XSelectInput( data->display, xwin, 0 ); + } + XDeleteContext( data->display, xwin, winContext ); NtUserRemoveProp( data->hwnd, foreign_window_prop ); } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9c1b8012466..2f46522f59f 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -573,6 +573,8 @@ extern BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *event ); extern int xinput2_opcode; extern void x11drv_xinput2_load(void); extern void x11drv_xinput2_init( struct x11drv_thread_data *data ); +extern void x11drv_xinput2_enable( Display *display, Window window ); +extern void x11drv_xinput2_disable( Display *display, Window window );
extern Bool (*pXGetEventData)( Display *display, XEvent /*XGenericEventCookie*/ *event ); extern void (*pXFreeEventData)( Display *display, XEvent /*XGenericEventCookie*/ *event );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/mouse.c | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+)
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 19a82d23ab0..7293480b635 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -273,6 +273,12 @@ void x11drv_xinput2_enable( Display *display, Window window ) XISetMask( mask_bits, XI_RawMotion ); XISetMask( mask_bits, XI_ButtonPress ); } + else + { + XISetMask( mask_bits, XI_TouchBegin ); + XISetMask( mask_bits, XI_TouchUpdate ); + XISetMask( mask_bits, XI_TouchEnd ); + }
pXISelectEvents( display, window, &mask, 1 ); } @@ -1742,6 +1748,44 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) return TRUE; }
+static BOOL X11DRV_TouchEvent( HWND hwnd, XGenericEventCookie *xev ) +{ + RECT virtual = NtUserGetVirtualScreenRect(); + INPUT input = {.type = INPUT_HARDWARE}; + XIDeviceEvent *event = xev->data; + int flags = 0; + POINT pos; + + input.mi.dx = event->event_x; + input.mi.dy = event->event_y; + map_event_coords( hwnd, event->event, event->root, event->root_x, event->root_y, &input ); + pos.x = input.mi.dx * 65535 / (virtual.right - virtual.left); + pos.y = input.mi.dy * 65535 / (virtual.bottom - virtual.top); + + switch (event->evtype) + { + case XI_TouchBegin: + input.hi.uMsg = WM_POINTERDOWN; + flags |= POINTER_MESSAGE_FLAG_NEW; + TRACE("XI_TouchBegin detail %u pos %dx%d, flags %#x\n", event->detail, (int)pos.x, (int)pos.y, flags); + break; + case XI_TouchEnd: + input.hi.uMsg = WM_POINTERUP; + TRACE("XI_TouchEnd detail %u pos %dx%d, flags %#x\n", event->detail, (int)pos.x, (int)pos.y, flags); + break; + case XI_TouchUpdate: + input.hi.uMsg = WM_POINTERUPDATE; + TRACE("XI_TouchUpdate detail %u pos %dx%d, flags %#x\n", event->detail, (int)pos.x, (int)pos.y, flags); + break; + } + + input.hi.wParamL = event->detail; + input.hi.wParamH = POINTER_MESSAGE_FLAG_INRANGE | POINTER_MESSAGE_FLAG_INCONTACT | flags; + NtUserSendHardwareInput( hwnd, 0, &input, MAKELPARAM( pos.x, pos.y ) ); + + return TRUE; +} + #endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */
@@ -1807,6 +1851,12 @@ BOOL X11DRV_GenericEvent( HWND hwnd, XEvent *xev ) ret = X11DRV_RawMotion( event ); break;
+ case XI_TouchBegin: + case XI_TouchUpdate: + case XI_TouchEnd: + ret = X11DRV_TouchEvent( hwnd, event ); + break; + default: TRACE( "Unhandled event %#x\n", event->evtype ); break;
v2: Fix compilation failure.