This PR adds some plumbing for pinch events coming from the SDL backend. Namely, a new SDL_EVENT_PINCH_UPDATE case is added to the switch statement in ImGui_ImplSDL3_ProcessEvent. The pinch event's parameters get forwarded to the new function AddPinchUpdateEvent, which converts them to equivalent parameters of a wheel event and then posts an ImGuiInputEvent with type ImGuiInputEventType_MouseWheel.
One aspect that possibly requires further thought is what should be passed to imgui's io.AddMouseSourceEvent(...). In this PR right now,ImGuiMouseSource_TouchScreen gets passed, but SDL actually generates pinch events for both touchscreens and touch/trackpads (e.g., one on a laptop). Unfortunately, SDL doesn't distinguish between these sources in the event info it provides. If it did, I guess the best thing to do instead would be to pass ImGuiMouseSource_TouchScreen or ImGuiMouseSource_Mouse for touchscreen and touch/trackpad gesture sources respectively.
Activity
8If this is being added to SDL3 right now, please ask them to add an identifier to distinguish touch screen from track pad. It’s important for Dear ImGui.
Actually if don’t emit a mouse teleport/reposition then touch screen vs track pad doesn’t make a difference. But it feels like we should reserve the possibility to emit one eg on the START event a AddMousePosEvent(). I don’t know what’s better but I suspect emitting a MousePos event will feel better in order to allow selecting a target window.
It seems also odd that it would emit a Wheeling event (= scrolling) when the more likely desirable feature is zooming. Can you clarify how/why you intend to use this?
Short term I reckon there is no point in formalizing this as an ImGui event it could better be done in the SDL3 event.
If this is being added to SDL3 right now, please ask them to add an identifier to distinguish touch screen from track pad.
I can open an SDL PR for that. There is a bit of a hackey way to do it now – SDL assigns several entries in the pinch event struct to -1 for touch/trackpad pinches. ImGui could easily check for this dummy value, but it would be nicer to just have a bool.
It seems also odd that it would emit a Wheeling event (= scrolling) when the more likely desirable feature is zooming.
I partly felt OK doing this b/c of your comment here, "Pinches are generally converted by OS or backends into mouse wheel events." In this context, this PR just does some standardization such that, no matter whether the backend represents the pinch as a pinch or a wheel event, ImGui emits a wheel event. Also, genuine wheel events are sometimes used for zoom control in desktop applications. This PR allows such applications written with ImGui to also function on mobile. Namely, a user can pinch the screen and it produces the same behavior as wheeling on a desktop. My need for this arises specifically for a part of an app that uses ImPlot.
I don’t know what’s better but I suspect emitting a MousePos event will feel better in order to allow selecting a target window.
OK yeah I've only been working with one window so haven't come across this but it does seem important for touchscreen applications. For touch/trackpad pinches, the currently active window should be assumed to be the target for the zoom.
On a related note, a probably objectionable aspect of this PR is the addition in ImGuiIO of a new position, PosOther. I'm using this to store the centroid of the two finger positions that comprise a touchscreen pinch gesture. With this info, I'm able to implement a touchscreen zoom that keeps this centroid stationary on the screen. This centroid position is only sent by SDL for touchscreen pinch events, not for those on a track/touchpad.
Maybe PosOther can be removed and the mouse position can instead be assigned this centroid position? That could help with the target window selection you mention. On the other hand, a user will sometimes (rarely) have a mouse plugged in to their mobile device and may not want the cursor to move at all when they pinch.
@m4sternoob Thanks! About those items:
-
span_(x|y) are currently set in SDL in /src/video/uikit/SDL_uikitview.m :
- (IBAction)sdlPinchGesture:(UIPinchGestureRecognizer *)senderfor iOS and /android-project/app/src/main/java/org/libsdl/app/SDLSurface.java :public boolean onScale(ScaleGestureDetector detector)for Android. From that iOS-related file:function, it looks likespan_(x|y)is never 0 on iOS as long as the two points that comprise a pinch gesture are distinct. From the Android-specific file:function, it looks like the answer depends on whether ScaleGestureDetector ever returns 0 for the spans, which is not obvious fromScaleGestureDetector's documentation. To be safe, I'll add a guard againstnorm=0. Fwiw, for trackpad pinches, SDL setsspan_(x|y)to a dummy value, -1, so the issue never arises. -
In my experience,
SDL_EVENT_PINCH_BEGINandSDL_EVENT_PINCH_ENDare not useful. -
It's a good point. I don't think there's a settled convention for whether a negative wheel value should zoom in or out. For applications that allow zooming via both genuine wheel events and pinch events (likely for desktop and mobile machines, respectively), this PR locks in the convention that you indicate. Doesn't seem like the end of the world, but is a downside. The only way around it I think would be to add a flag to ImGui's
MouseWheelevent indicating whether it is a genuine wheel event or derived from a pinch, which would allow the user to negateWheel_(X|Y)only for the latter case. -
Fixed now
Also, this PR should be compiled against the current SDL code on GitHub, not the most recent release