移动设备上的 SDL2 事件

SDL2 events on mobile

由于 SDL2 的行为,我已经与一个错误战斗了几个小时,而我对此一无所知。
特别是,我不知道,在移动设备上,每当用户触摸屏幕时,都会发送两个事件:

这同样适用于手指 up/mouse 按钮弹起事件。
因为他们,一个内部命令被扔了两次,让我很头疼。

出于超出问题目的的原因,目标是同时支持移动和桌面环境。
此外,我可以猜测 SDL2 的工作方式是为了支持已经存在的代码库的平滑迁移。

无论如何,有没有(让我说)SDL2-way 来抑制移动设备上的鼠标相关事件?

老实说,从我的角度来看,它们没有多大意义,我想摆脱它们,除非该软件是在桌面环境中执行的。
此外,我既不想使用编译时参数,也不想使用专门的代码部分来抑制移动设备上的这些事件。

代码很简单。下面是一个(可能)有意义的简化示例:

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;
    }
}

不幸的是,如前所述,当用户触摸屏幕时会读取上述两个事件。

* 编辑 *

我没有提到我正在 Android 设备上测试我的应用程序,而且我无法确定 iOS.
上也会出现同样的问题 请参阅下面的响应。 问题(到目前为止我明白这不是一个问题)似乎确实主要是由于 SDL2 默认处理 Android 上的手指事件的方式。

遗憾的是,没有此类特定于平台的停用参数。

因此,最简洁的方法是在初始化代码中使用 SDL_GetPlatform() 查询平台,如果是移动设备,则使用 SDL_SetEventFilter() 设置事件过滤器,以防止鼠标事件被排队。 这不完全是您期望的答案,但我看不到其他 sdl 替代方案。

如果您控制事件循环的代码,一种更简单的方法是设置一个标志而不是事件过滤器,如果设置了标志,则不对鼠标事件执行任何操作。然而,第二种方法并不那么干净,因为您必须在所有代码中处理特定于平台的行为,而在第一种方法中它更加孤立。

尽管我真的很喜欢 Christophe 添加事件过滤器的想法,但我发现 SDL2 已经在 Android 上 gives support for this problem in terms of an hint

特别是存在提示SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH.
可以通过函数 SDL_SetHint 来设置它。有关详细信息,请参阅 here

就这么简单:

SDL_SetHint(SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH, "1");

根据提示的文档,默认情况下它设置为 0,这意味着:

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

没错,是我的问题,但是设置为1可以得到如下结果:

mouse events will be handled separately from pure touch events

因此,不再在 Android 设备上伪造鼠标事件。

我不太清楚默认值背后的原因,但这听起来确实是实现它的正确方法。

编辑(更多细节)

这个变化似乎是最近的。
Here 是 libsdl 论坛的 link,他们在那里讨论由于引入此行为的补丁而出现的问题。
有人和我有同样的问题,其他一些人也在试图解释为什么补丁被接受了。

编辑:替代解决方案

提示 SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCHSDL v2.0.4 以来可用,因此似乎是唯一可行的解​​决方案SDL2 的版本是使用事件过滤器。

无论如何,我不鼓励使用SDL_GetPlatform查询平台来决定是否设置事件过滤器。
相反,根据 SDL_MouseMotionEvent and SDL_MouseButtonEvent 的文档,存在 which 参数:

[...] 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.

因此,我建议无论底层平台是什么,都设置一个事件过滤器,从而将事件排队或在需要时过滤它们。