SDL icon indicating copy to clipboard operation
SDL copied to clipboard

Impossible to know how many and which fingers are still down on SDL_EVENT_FINGER_UP

Open MarkCallow opened this issue 4 months ago • 7 comments

I have observed on both macOS and Windows that when multiple fingers are touched down and raised it is possible for the app to receive either one or multiple SDL_EVENT_FINGER_{DOWN,UP} events. For SDL_EVENT_FINGER_DOWN this is not a problem as SDL_GetTouchFingers called on the last event gives the total number of fingers down.

Handling this dichotomy for SDL_EVENT_FINGER_UP is impossible. On the first event received, regardless if it will be the only one or is the first of several, SDL_GetTouchFingers reports the total number of fingers that were down before the event and the returned SDL_TouchFingers list includes all the fingers. Therefore it is impossible to know how many fingers may still be down. The SDL_TouchFingers returned in the list do not provide any help. I thought maybe pressure might be zero for the up fingers but all pressures are 1. It is possible that the fingerID in the SDL_EVENT_FINGER_UP may be the finger that was raised - there is no documentation to that effect - but that is helpful only if just 1 finger was raised.

If you are only interested in the number of fingers then you can fudge it by recording the number in SDL_EVENT_FINGER_DOWN handling then decrementing that number on each SDL_EVENT_FINGER_UP by the number of fingers reported by SDL_GetTouchFingers clamping it to a minimum of 0.

But if, as part of gesture processing such as in SDL_gesture.h, you want to calculate the centroid of the remaining down fingers, there is no way to do that reliably especially if you are using more than 2 fingers in your gestures.

On macOS you can reproduce a single SDL_EVENT_FINGER_UP by pressing 2 fingers on the trackpad to emulate a right mouse button. On release, regardless of any delay between raising the fingers, a single event will be received when the press is released. You can reproduce multiple events by touching the trackpad with 2 fingers, then raising one followed by the other.

The list returned by SDL_GetTouchFingers should be either the fingers remaining down or the fingers that have been raised. The former contradicts with the semantic of "finger up" but is probably more useful than the latter which will require keeping the list of fingers between events and removing from it the fingers that have been raised.

This is with SDL3 but the symptoms which I tracked to this problem were present with SDL2 as well.

MarkCallow avatar Jul 27 '25 09:07 MarkCallow

On macOS you can reproduce a single SDL_EVENT_FINGER_UP by pressing 2 fingers on the trackpad to emulate a right mouse button. On release, regardless of any delay between raising the fingers, a single event will be received when the press is released. You can reproduce multiple events by touching the trackpad with 2 fingers, then raising one followed by the other.

This description is simplistic. 2 fingers down for a right button press has many nuances. If the window does not have focus, the following events are sent:

FINGER_DOWN
FINGER_DOWN
right BUTTON_DOWN
FINGER_UP for the finger in the second FINGER_DOWN event. `SDL_GetTouchFingers` reports 2 fingers.

then when the fingers are released

right BUTTON_UP

When you move the fingers, MOUSE_MOTION events are sent.

If the window has focus you get the events described above then when you move your fingers you also get FINGER_MOTION events for which SDL_GetTouchFingers reports one finger down. When releasing the fingers you get a FINGER_UP event for the other finger after the BUTTON_UP event.

This does not change the essence of the issue which is the difficulty of knowing how many fingers are actually down but it makes reproduction of the one finger up event for multiple fingers harder to reproduce.

MarkCallow avatar Aug 07 '25 06:08 MarkCallow

Also found strange behavior on Android with swipe insets gesture from left or right edge of screen. First I touch screen on the left or right edge and get SDL_EVENT_FINGER_DOWN event, then make swipe and receive SDL_EVENT_FINGER_MOTION, then SDL_EVENT_FINGER_CANCELED, but when I take up my finger I DO NOT receive SDL_EVENT_FINGER_UP - is it correct?

akk0rd87 avatar Oct 30 '25 19:10 akk0rd87

Also found strange behavior on Android with swipe insets gesture from left or right edge of screen. First I touch screen on the left or right edge and get SDL_EVENT_FINGER_DOWN event, then make swipe and receive SDL_EVENT_FINGER_MOTION, then SDL_EVENT_FINGER_CANCELED, but when I take up my finger I DO NOT receive SDL_EVENT_FINGER_UP - is it correct?

Yes, a canceled event means that the touch is canceled and there will not be a following finger up event.

slouken avatar Oct 30 '25 20:10 slouken

Also https://github.com/libsdl-org/SDL_gesture/blob/main/SDL_gesture.h doesn't handle SDL_EVENT_FINGER_CANCELED event to reset inTouch->numDownFingers.

akk0rd87 avatar Nov 04 '25 12:11 akk0rd87

Also https://github.com/libsdl-org/SDL_gesture/blob/main/SDL_gesture.h doesn't handle SDL_EVENT_FINGER_CANCELED event to reset inTouch->numDownFingers.

Fixed in https://github.com/libsdl-org/SDL_gesture/commit/2248f31c05bfdcffd906468f26cca96c2892654e, thanks!

slouken avatar Nov 04 '25 18:11 slouken

@slouken, thank you too!

akk0rd87 avatar Nov 05 '25 07:11 akk0rd87

You're welcome!

slouken avatar Nov 05 '25 15:11 slouken