Search code examples
c++mobilesdlsdl-2mobile-application

SDL2 events on mobile


I've fought for a couple of hours with a bug due to a behavior of SDL2 of which I didn't know anything.
In particular, I didn't know that, on mobile, whenever the user touches the screen, two events are sent:

  • The first one was quite obvious to me: a finger down event.
  • The second one was indeed less obvious: a mouse button down event.

The same applies for the finger up/mouse button up events.
Because of them, an internal command was thrown twice giving me an headache.

The target is to support both mobile and desktop environments for reasons that are beyond the purpose of the question.
Also, I can guess SDL2 works like that in order to support smooth migration of already existent codebase.

Anyway, is there a (let me say) SDL2-way to inhibit the mouse related events on mobile?

Honestly, they don't make much sense from my point of view and I would like to get rid of them, unless the software is executed on a desktop environment.
Also, I don't want neither to use compile time parameters nor to have dedicated parts of code the aim of which is to suppress those events on mobile.

The code is quite simple. Below a (maybe) meaningful, reduced example:

SDL_Event ev;
while(SDL_PollEvent(&ev)) {
    switch(event.type) {
    case SDL_FINGERDOWN:
        // read it and throw an internal event E
        break;
    case SDL_MOUSEBUTTONDOWN:
        // read it and throw an internal event E
        break;
    }
}

Unfortunately, both the events above are read when the user touches the screen, as explained.

* EDIT *

I didn't mention that I was testing my application on an Android device and I'm far to be sure that the same problem arises on iOS.
See the response below. It seems indeed that the issue (that so far I've understood it is not exactly an issue) is mainly due to the way SDL2 treats by default finger events on Android.


Solution

  • Even though I really like the idea of Christophe to add an event filter, I've found that SDL2 already gives support for this problem in terms of an hint on Android.

    In particular, there exists the hint SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH.
    One can set it by means of the function SDL_SetHint. See here for further details.

    It's as simple as:

    SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1");
    

    As from the documentation of the hint, by default it is set to 0 and that means that:

    mouse events will be handled as touch events and touch will raise fake mouse events

    That's true, it was my problem, but by setting it to 1 we can get what follows:

    mouse events will be handled separately from pure touch events

    So, no longer fake mouse events on Android devices.

    The reason behind the default value is not so clear to me, but this one sounds really like the right way to achieve it.

    EDIT (more details)

    This change seems to be recent.
    Here is a link to the libsdl forum where they were discussing the issues that arose as a consequence of the patch that introduced this behavior.
    Someone had the same problem I had and some others were trying also to explain why the patch had been accepted.

    EDIT: alternative solution

    The hint SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH is available since SDL v2.0.4, so it seems that the only viable solution for lower versions of SDL2 is to use an event filter.

    Anyway, I discourage to query the platform by using SDL_GetPlatform in order to decide if to set or not to set an event filter.
    Instead, as from the documentation of both SDL_MouseMotionEvent and SDL_MouseButtonEvent, there exists the which parameter that:

    [...] may be SDL_TOUCH_MOUSEID, for events that were generated by a touch input device, and not a real mouse. You might want to ignore such events, if your application already handles SDL_TouchFingerEvent.

    Because of that, I suggest to set an event filter no matter of what's the underlying platform, thus to queue the events or to filter them if needed.