SDL icon indicating copy to clipboard operation
SDL copied to clipboard

x11: add support for precision/pixel scrolling

Open wooosh opened this issue 3 years ago • 13 comments

This patch adds support for pixel scrolling for the x11 backend for xinput2.

Description

This patch will automatically detect precision scroll devices using xinput2, allowing for SDL applications to detect scrolling changes smaller than one line, allowing for smooth scrolling on devices with touchpads, trackpoints, and trackballs.

There are a few things about this patch I'm not certain about:

  • Should there be a define to enable this? It requires xinput 2.1 (2011) to compile.
  • I've only been able to test this on my laptop at the moment, but I should be able to get some help with testing it on other hardware in the next few days.
  • Currently the state to track the xinput devices is allocated statically, with a maximum of 8 devices.
    • Should this automatically allocate for the number of devices present? I don't have a good feel for SDL2's stance on allocation.
    • Should this state be stored somewhere else? I couldn't find a better place to put it, as I'm not very familiar with the codebase, but maybe it would be better off in the private x11 data struct or the private mouse data (if there is any for mice, that is).

Existing Issue(s)

When precision scrolling was originally added to SDL, the X11 backend was left out:

https://github.com/libsdl-org/SDL/issues/1267 On 2016-06-01 16:12:29 +0000, Martijn Courteaux wrote:

Note that this doesn't fix it for X11. I'm a X11 noob, but I think that SDL doesn't use xinput2, since @r.kreis said that.

wooosh avatar Mar 06 '22 22:03 wooosh

I tested this with my trackball and it worked fine

BanchouBoo avatar Mar 06 '22 23:03 BanchouBoo

https://github.com/libsdl-org/SDL/runs/5441478306?check_suite_focus=true#step:6:190

/home/runner/work/SDL/SDL/src/video/x11/SDL_x11xinput2.c:170:22: warning: declaration of ‘i’ shadows a previous local [-Wshadow]
  170 |         int ndevices,i,j,k,dev_i=0;
      |                      ^
/home/runner/work/SDL/SDL/src/video/x11/SDL_x11xinput2.c:138:21: note: shadowed declaration is here
  138 |     int event, err, i;
      |                     ^
/home/runner/work/SDL/SDL/src/video/x11/SDL_x11xinput2.c: In function ‘X11_HandleXinput2Event’:
/home/runner/work/SDL/SDL/src/video/x11/SDL_x11xinput2.c:310:13: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
  310 |             int pointer_emulated = (xev->flags & XIPointerEmulated);
      |             ^~~
cc1: some warnings being treated as errors

sezero avatar Mar 06 '22 23:03 sezero

Apologies for the back and forth over the CI compiler warnings, specifically with C89/C90 compliance, for some reason I cannot get cmake to produce warnings or errors for shadowing or mixed code and declarations locally.

wooosh avatar Mar 07 '22 00:03 wooosh

Possibly needs autotools and cmake checks for XIScrollClassInfo

sezero avatar Mar 07 '22 00:03 sezero

Possibly needs autotools and cmake checks for XIScrollClassInfo

Or, since SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH already requires 2.1+, the new code probably can be guarded with that existing macro. Maintainers to decide.

sezero avatar Mar 07 '22 00:03 sezero

I added checks for both cmake and autotools, though I'm not sure if I set up the autotools check properly for this.

wooosh avatar Mar 07 '22 02:03 wooosh

@icculus or @slouken should review now

sezero avatar Mar 07 '22 08:03 sezero

During further testing, I found a bug in my PR where both precise and non-precise scrolling events will still get sent even if a precision scrolling device is detected.

wooosh avatar Mar 07 '22 23:03 wooosh

xinput2 valuators have many pitfalls I was not aware of when I started this pull request, so I’m going to leave this as a draft until I’m more confident that this is free of bugs.

Currently I’m aware of the following issues, though I suspect I will find more:

  • [x] Because the scroll valuators are represented as an absolute position, scrolling in another window invalidates the previous values stored in SDL to calculate the relative movement
  • [x] Hotplugging scrollable devices does not function properly
  • [x] The absolute scroll coordinates will wrap around at a certain point

wooosh avatar Mar 08 '22 03:03 wooosh

This is still in progress, so I'm tentatively putting it in the 2.0.22 milestone, but we'll slide it to 2.0.24 if necessary.

icculus avatar Mar 08 '22 16:03 icculus

I've fixed all of the issues I am currently aware of, so I'm going to continue to test this over the next few days to try and find any remaining edge cases.

This should support multiple distinct logical pointers, but I'm not certain it works 100% properly as I was unable to set up multiple pointers under FVWM, XFCE, or herbstluftwm. However, given that SDL makes no attempts to support multiple logical cursors (at least as far as I can tell, based on the wiki excerpt below), and my assumption that it's used relatively rarely, I believe this should not be an issue in practice. I suspect any issues caused by multiple logical pointers would be limited to not detecting creation and removal of logical pointers, and jumpy scrolling when both provide scroll events at the same time.

Please note that this ONLY discusses "mice" with the notion of the desktop GUI. You (usually) have one system cursor, and the OS hides the hardware details from you. If you plug in 10 mice, all ten move that one cursor. For many applications and games this is perfect, and this API has served hundreds of SDL programs well since its birth.

Regardless, if it's something deemed worth further investigation, I'm willing to put more effort into attempting to test multiple logical cursors.

wooosh avatar Mar 08 '22 23:03 wooosh

It's worth noting that the first scroll event after any of the following will be discarded:

  • The pointer leaves and enters the window again
  • A device change event
    • Master device changes - physically plugging or unplugging a device
    • Slave device changes - the user scrolls on one device, and then starts using another (already plugged in) device

This is an known deficiency in XInput2, due to scrolling being represented as absolute coordinates, any event that prevents us from knowing the previous coordinate forces us to eat the next input event.

As far as I can tell, there is zero reliable ways around this, as Chrome, GTK, or QT all share this behavior.

wooosh avatar Mar 09 '22 21:03 wooosh

Is this ready for review and testing in 2.26.0?

slouken avatar Jul 25 '22 21:07 slouken

@wooosh, can you review this and update it for the latest main code?

slouken avatar Aug 19 '22 16:08 slouken

Yes, I will update this to the latest code in main and review it.

wooosh avatar Aug 19 '22 17:08 wooosh

@wooosh ping? I'd like to get this in for release if it's ready.

slouken avatar Oct 04 '22 00:10 slouken

I resolved the merge conflicts but have not tested this...at this point, I think we bump to 2.28.0 or SDL3 and merge right away, as it's probably good but way too late for 2.26.0.

icculus avatar Nov 16 '22 04:11 icculus

3.0 it is. :)

slouken avatar Nov 16 '22 05:11 slouken

@wooosh, can you update this PR? It would be great to get in for SDL 3.0. Thanks!

slouken avatar Mar 10 '24 17:03 slouken

tried compiling 55231f4688f5052c8b7e8d2feabf4af63d98da5a

/src/video/x11/SDL_x11xinput2.c: In function ‘X11_Xinput2Select’:
/src/video/x11/SDL_x11xinput2.c:577:14: error: ‘SDL_VideoData’ has no member named ‘xinput_scrolling’
  577 |     if (!data->xinput_scrolling && !X11_Xinput2IsMultitouchSupported()) {
      |              ^~
/src/video/x11/SDL_x11xinput2.c:585:13: error: ‘SDL_VideoData’ has no member named ‘xinput_scrolling’
  585 |     if (data->xinput_scrolling) {
      |             ^~

this field is only defined if macro SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO is true (src/video/x11/SDL_x11video.h:137)

it seems to work just fine for me when i forcibly compile with -DSDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_SCROLLINFO=1

zlago avatar Mar 19 '24 15:03 zlago