@@ -50,6 +50,10 @@ static Atom xinput2_rel_y_atom;
5050static Atom xinput2_abs_x_atom ;
5151static Atom xinput2_abs_y_atom ;
5252
53+ // Pointer button remapping table
54+ static unsigned char * xinput2_pointer_button_map ;
55+ static int xinput2_pointer_button_map_size ;
56+
5357#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
5458typedef struct
5559{
@@ -328,6 +332,7 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
328332 X11_XISelectEvents (data -> display , DefaultRootWindow (data -> display ), & eventmask , 1 );
329333
330334 X11_Xinput2UpdateDevices (_this );
335+ X11_Xinput2UpdatePointerMapping (_this );
331336
332337 return true;
333338#else
@@ -337,6 +342,10 @@ bool X11_InitXinput2(SDL_VideoDevice *_this)
337342
338343void X11_QuitXinput2 (SDL_VideoDevice * _this )
339344{
345+ SDL_free (xinput2_pointer_button_map );
346+ xinput2_pointer_button_map = NULL ;
347+ xinput2_pointer_button_map_size = 0 ;
348+
340349#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO
341350 for (int i = 0 ; i < scrollable_device_count ; ++ i ) {
342351 SDL_free (scrollable_devices [i ].scroll_info );
@@ -347,6 +356,29 @@ void X11_QuitXinput2(SDL_VideoDevice *_this)
347356#endif
348357}
349358
359+ void X11_Xinput2UpdatePointerMapping (SDL_VideoDevice * _this )
360+ {
361+ #ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
362+ if (X11_Xinput2IsInitialized ()) {
363+ SDL_VideoData * vid = _this -> internal ;
364+
365+ SDL_free (xinput2_pointer_button_map );
366+ xinput2_pointer_button_map = NULL ;
367+ xinput2_pointer_button_map_size = 0 ;
368+
369+ xinput2_pointer_button_map_size = X11_XGetPointerMapping (vid -> display , NULL , 0 );
370+ if (xinput2_pointer_button_map_size ) {
371+ xinput2_pointer_button_map = SDL_calloc (xinput2_pointer_button_map_size , sizeof (unsigned char ));
372+ if (xinput2_pointer_button_map ) {
373+ xinput2_pointer_button_map_size = X11_XGetPointerMapping (vid -> display , xinput2_pointer_button_map , xinput2_pointer_button_map_size );
374+ } else {
375+ xinput2_pointer_button_map_size = 0 ;
376+ }
377+ }
378+ }
379+ #endif
380+ }
381+
350382#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
351383// xi2 device went away? take it out of the list.
352384static void xinput2_remove_device_info (SDL_VideoData * videodata , const int device_id )
@@ -562,7 +594,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
562594 {
563595 const XIDeviceEvent * xev = (const XIDeviceEvent * )cookie -> data ;
564596 X11_PenHandle * pen = X11_FindPenByDeviceID (xev -> sourceid );
565- const int button = xev -> detail ;
597+ int button = xev -> detail ;
566598 const bool down = (cookie -> evtype == XI_ButtonPress );
567599#if defined(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO ) || defined(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH )
568600 bool pointer_emulated = (xev -> flags & XIPointerEmulated ) != 0 ;
@@ -587,6 +619,13 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
587619 SDL_WindowData * windowdata = xinput2_get_sdlwindowdata (videodata , xev -> event );
588620 int x_ticks = 0 , y_ticks = 0 ;
589621
622+ // Slave pointer devices don't have button remapping applied automatically, so do it manually.
623+ if (xev -> deviceid != videodata -> xinput_master_pointer_device ) {
624+ if (button <= xinput2_pointer_button_map_size ) {
625+ button = xinput2_pointer_button_map [button - 1 ];
626+ }
627+ }
628+
590629 /* Discard wheel events from "Master" devices to avoid duplicates,
591630 * as coarse wheel events are stateless and can't be deduplicated.
592631 *
0 commit comments