From 1d38a722177d02eb836ff8f9aa9857d00e6a7ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= Date: Thu, 19 Dec 2019 22:34:44 +0100 Subject: [PATCH] winex11.drv: Keep track of pointer and device button mappings. We are going to receive raw button events and we will need to apply the correct button mappings ourselves. Original patch by Andrew Eikum . --- dlls/winex11.drv/keyboard.c | 23 ++++++--- dlls/winex11.drv/mouse.c | 89 +++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 1 + dlls/winex11.drv/x11drv_main.c | 1 + 4 files changed, 106 insertions(+), 8 deletions(-) diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index b240b228ff0..b54ca795954 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1809,13 +1809,24 @@ BOOL X11DRV_MappingNotify( HWND dummy, XEvent *event ) { HWND hwnd; - XRefreshKeyboardMapping(&event->xmapping); - X11DRV_InitKeyboard( event->xmapping.display ); + switch (event->xmapping.request) + { + case MappingModifier: + case MappingKeyboard: + XRefreshKeyboardMapping( &event->xmapping ); + X11DRV_InitKeyboard( event->xmapping.display ); + + hwnd = get_focus(); + if (!hwnd) hwnd = get_active_window(); + NtUserPostMessage( hwnd, WM_INPUTLANGCHANGEREQUEST, + 0 /*FIXME*/, (LPARAM)NtUserGetKeyboardLayout(0) ); + break; + + case MappingPointer: + X11DRV_InitMouse( event->xmapping.display ); + break; + } - hwnd = get_focus(); - if (!hwnd) hwnd = get_active_window(); - NtUserPostMessage( hwnd, WM_INPUTLANGCHANGEREQUEST, - 0 /*FIXME*/, (LPARAM)NtUserGetKeyboardLayout(0) ); return TRUE; } diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index ff91aecb67f..33f6ac24af8 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -30,6 +30,9 @@ #include #include #include +#ifdef HAVE_X11_EXTENSIONS_XINPUT_H +#include +#endif #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H #include #endif @@ -137,6 +140,14 @@ MAKE_FUNCPTR(XISelectEvents); #undef MAKE_FUNCPTR #endif +#ifdef HAVE_X11_EXTENSIONS_XINPUT_H +#define MAKE_FUNCPTR(f) static typeof(f) * p##f +MAKE_FUNCPTR(XOpenDevice); +MAKE_FUNCPTR(XCloseDevice); +MAKE_FUNCPTR(XGetDeviceButtonMapping); +#undef MAKE_FUNCPTR +#endif + /*********************************************************************** * X11DRV_Xcursor_Init * @@ -224,6 +235,70 @@ void set_window_cursor( Window window, HCURSOR handle ) XFlush( gdi_display ); } +struct mouse_button_mapping +{ + int deviceid; + unsigned int button_count; + unsigned char buttons[256]; +}; + +static struct mouse_button_mapping *pointer_mapping; +static struct mouse_button_mapping *device_mapping; + +static void update_pointer_mapping( Display *display ) +{ + struct mouse_button_mapping *tmp; + + if (!(tmp = malloc( sizeof(*tmp) ))) + { + WARN("Unable to allocate device mapping.\n"); + return; + } + + tmp->button_count = ARRAY_SIZE( tmp->buttons ); + tmp->button_count = XGetPointerMapping( display, tmp->buttons, tmp->button_count ); + + tmp = InterlockedExchangePointer( (void**)&pointer_mapping, tmp ); + + free( tmp ); +} + +static void update_device_mapping( Display *display, int deviceid ) +{ +#ifdef HAVE_X11_EXTENSIONS_XINPUT_H + struct mouse_button_mapping *tmp; + XDevice *device; + + if (!(device = pXOpenDevice( display, deviceid ))) + { + WARN( "Unable to open cursor device %d\n", deviceid ); + return; + } + + if (!(tmp = malloc( sizeof(*tmp) ))) + { + WARN( "Unable to allocate device mapping.\n" ); + pXCloseDevice( display, device ); + return; + } + + tmp->deviceid = deviceid; + tmp->button_count = ARRAY_SIZE( tmp->buttons ); + tmp->button_count = pXGetDeviceButtonMapping( display, device, tmp->buttons, tmp->button_count ); + + tmp = InterlockedExchangePointer( (void**)&device_mapping, tmp ); + + free( tmp ); + + pXCloseDevice( display, device ); +#endif +} + +void X11DRV_InitMouse( Display *display ) +{ + update_pointer_mapping( display ); +} + #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H /*********************************************************************** * update_relative_valuators @@ -1675,6 +1750,8 @@ static BOOL X11DRV_DeviceChanged( XGenericEventCookie *xev ) if (event->reason != XISlaveSwitch) return FALSE; update_relative_valuators( event->classes, event->num_classes ); + update_device_mapping( event->display, event->sourceid ); + return TRUE; } @@ -1762,13 +1839,12 @@ static BOOL X11DRV_RawMotion( XGenericEventCookie *xev ) #endif /* HAVE_X11_EXTENSIONS_XINPUT2_H */ - /*********************************************************************** * x11drv_xinput_load */ void x11drv_xinput_load(void) { -#if defined(SONAME_LIBXI) && defined(HAVE_X11_EXTENSIONS_XINPUT2_H) +#if defined(SONAME_LIBXI) int event, error; void *libxi_handle = dlopen( SONAME_LIBXI, RTLD_NOW ); @@ -1784,11 +1860,20 @@ void x11drv_xinput_load(void) return; \ } +#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H LOAD_FUNCPTR(XIGetClientPointer); LOAD_FUNCPTR(XIFreeDeviceInfo); LOAD_FUNCPTR(XIQueryDevice); LOAD_FUNCPTR(XIQueryVersion); LOAD_FUNCPTR(XISelectEvents); +#endif + +#ifdef HAVE_X11_EXTENSIONS_XINPUT_H + LOAD_FUNCPTR(XOpenDevice); + LOAD_FUNCPTR(XCloseDevice); + LOAD_FUNCPTR(XGetDeviceButtonMapping); +#endif + #undef LOAD_FUNCPTR xinput2_available = XQueryExtension( gdi_display, "XInputExtension", &xinput2_opcode, &event, &error ); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index fc3231ed40d..8bbac23f88e 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -691,6 +691,7 @@ extern void retry_grab_clipping_window(void) DECLSPEC_HIDDEN; extern void ungrab_clipping_window(void) DECLSPEC_HIDDEN; extern void move_resize_window( HWND hwnd, int dir ) DECLSPEC_HIDDEN; extern void X11DRV_InitKeyboard( Display *display ) DECLSPEC_HIDDEN; +extern void X11DRV_InitMouse( Display *display ) DECLSPEC_HIDDEN; extern BOOL X11DRV_ProcessEvents( DWORD mask ) DECLSPEC_HIDDEN; extern HWND *build_hwnd_list(void) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index fc341c32f77..b0e306e3ac8 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -704,6 +704,7 @@ static NTSTATUS x11drv_init( void *arg ) XkbUseExtension( gdi_display, NULL, NULL ); X11DRV_InitKeyboard( gdi_display ); + X11DRV_InitMouse( gdi_display ); if (use_xim) use_xim = xim_init( input_style ); init_user_driver(); -- 2.40.1