We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 4690

Summary: [REGRESSION] macOS trackpad mouse events now report SDL_TOUCH_MOUSEID
Product: SDL Reporter: Cameron Gutman <cameron.gutman>
Component: videoAssignee: Ryan C. Gordon <icculus>
Status: ASSIGNED --- QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: amaranth72, sezeroz, sylvain.becker, tesch1
Version: HG 2.0   
Hardware: x86_64   
OS: macOS 10.13   

Description Cameron Gutman 2019-06-23 06:13:26 UTC
With SDL 2.0.10 pre-release, I'm seeing a breaking behavior change where now SDL_MouseMotionEvent and SDL_MouseButtonEvent are coming in from SDL_TOUCH_MOUSEID rather than a traditional mouse instance ID.

I'm explicitly ignoring SDL_TOUCH_MOUSEID events because I handle SDL_TouchFingerEvent explicitly (just as the SDL_MouseMotionEvent doc suggests). However, my SDL_TouchFingerEvent code doesn't handle all the stuff that a trackpad can do (two finger scroll, right-click, etc), so the trackpad acts pretty wonky after updating to SDL 2.0.10.

I suspect that I'm not the only one ignoring SDL_TOUCH_MOUSEID, so I think this change will cause problems with unsuspecting apps that upgrade to 2.0.10, and it might not easily be found during testing.

I think Alex's comments about the possible breakage from 2016 still apply today:
https://bugzilla.libsdl.org/show_bug.cgi?id=3542#c1
https://bugzilla.libsdl.org/show_bug.cgi?id=3542#c3

If this behavior is desired for some use cases, I think it would be best to place it behind a hint that's off by default to preserve existing behavior. At the very least, this should have a mention in the release notes.
Comment 1 Sylvain 2019-06-23 14:26:53 UTC
So continuation of bug 4576.

When you said "wonky", you mean you lose the WheelEvents, the Right Clicks, because there appears in terms of fingers moves. I think this is problematic.

Maybe: 
- the macosx trackpad should provide genuine MouseEvents, and virtual TouchEvents.
  (same as Linux).
Comment 2 Alex Szpakowski 2019-06-23 20:03:33 UTC
Indeed, I called this out recently again too: https://bugzilla.libsdl.org/show_bug.cgi?id=4576#c23

(In reply to Sylvain from comment #1)
> Maybe: 
> - the macosx trackpad should provide genuine MouseEvents, and virtual
> TouchEvents.
>   (same as Linux).
I don't think that's a good idea. Trackpad touch positions and the mouse position are not 1-to-1 correlated, trying to turn one into the other makes them much less useful than they'd be otherwise, and would make apps that use those events feel different from all other apps the user runs.
Comment 3 Alex Szpakowski 2019-06-23 20:04:46 UTC
(In reply to Cameron Gutman from comment #0)
> If this behavior is desired for some use cases, I think it would be best to
> place it behind a hint that's off by default to preserve existing behavior.

That sounds like a good idea to me. Ryan?
Comment 4 Sylvain 2019-06-23 20:29:08 UTC
> I don't think that's a good idea. Trackpad touch positions and the mouse
> position are not 1-to-1 correlated, trying to turn one into the other makes
> them much less useful than they'd be otherwise, and would make apps that use
> those events feel different from all other apps the user runs.

I may be wrong, but just suggesting:
- that's the way trackpads works it's on Linux. Not sure on window API.
  I mean, whatever the behaviour, shouldn't we try to be the more uniform as possible ?

- What is problematic for me, is for 1 user physical action (a click), you get both a MOUSEDOWN event and a FINGER-TOUCH-DOWN event. Without knowing one is the duplication of the other. So if your app use both API, it gets disturb with a second event.

You could say, you can use only one of API touch/mouse, but you need both, even for macosx, to handle mouse and trackpad.
Comment 5 Alex Szpakowski 2019-06-23 23:12:36 UTC
(In reply to Sylvain from comment #4)
> I may be wrong, but just suggesting:
> - that's the way trackpads works it's on Linux. Not sure on window API.
>   I mean, whatever the behaviour, shouldn't we try to be the more uniform as
> possible ?
I think SDL should be uniform except when it conflicts with user expectations of how an app should behave or feel like, especially if that conflict is a result of replacing OS-provided functionality with its own. I think the way key repeat is handled in SDL1 (overridden by SDL) vs SDL2 (OS/user-controlled to match other apps on the OS) is an example of that idea in action.


> - What is problematic for me, is for 1 user physical action (a click), you
> get both a MOUSEDOWN event and a FINGER-TOUCH-DOWN event. Without knowing
> one is the duplication of the other. So if your app use both API, it gets
> disturb with a second event.
I agree, that's an issue with SDL 2.0.9 and prior that'd still be an issue with SDL 2.0.10 with the proposed changes in this thread. I think there are a couple alternative solutions proposed in the other thread which might solve it, I'm not sure which one is best though.
Comment 6 Ryan C. Gordon 2019-07-02 16:34:19 UTC
I've turned off SDL_TOUCH_MOUSEID events in the Cocoa target for now. If it's input from a trackpad that the OS has made look like a mouse, then SDL will report it as if it's a real mouse and a real touch device moving at the same time.

https://hg.libsdl.org/SDL/rev/73091a9e72f7

This is as far as I expect this to go for 2.0.10. Unless this is obviously disastrous, we can revisit this after this release. I'm leaving this bug open for now and removing the target-2.0.10 tag.

--ryan.
Comment 7 Ozkan Sezer 2019-07-02 16:42:39 UTC
(In reply to Ryan C. Gordon from comment #6)
> https://hg.libsdl.org/SDL/rev/73091a9e72f7

Suggest moving   #define TRACKPAD_REPORTS_TOUCH_MOUSEID 0
to SDL_cocoamouse.h
Comment 8 Sam Lantinga 2019-07-02 19:06:16 UTC
Yes, this is still problematic.

I'm not sure where we should go from here, but it's a real problem for games to get the same input as both mouse and touch without being able to differentiate them (see bug 4704)

We do need to resolve this for 2.0.10.
Comment 9 Ryan C. Gordon 2019-07-02 19:35:53 UTC
> We do need to resolve this for 2.0.10.

So let's say on the Mac that the (not actual virtual) touches from the trackpad are SDL_MOUSE_TOUCHID, and say the (strictly speaking, virtual, but that's hidden by the OS) mouse events from the touchpad are reported as physical hardware events?

It's exactly backwards from reality, but probably matches what people expect from SDL events on the platform.

After 2.0.10, we can try to figure out if there's a way to ask "is this mouse event specifically from a MacBook trackpad?" instead of "is this mouse event from a touch device?" and special-case it...it might be that this is the only scenario on macOS where this happens, but it also wouldn't surprise me to see a MacBook with a touchable display at some point, so we'll want the distinction eventually if possible.

--ryan.
Comment 10 Cameron Gutman 2019-07-02 19:44:58 UTC
(In reply to Sam Lantinga from comment #8)
> Yes, this is still problematic.
> 
> I'm not sure where we should go from here, but it's a real problem for games
> to get the same input as both mouse and touch without being able to
> differentiate them (see bug 4704)
> 
> We do need to resolve this for 2.0.10.

SDL 2.0.9 also sent duplicate touch events for trackpad motion on macOS, so this change returns to SDL 2.0.9's behavior. However, the new SDL_GetTouchDeviceType() API now lets us distinguish between direct and indirect devices, so we don't have to ignore all touch events on macOS anymore.

There's still a missing piece here because there's no SDL_GetTouchDeviceType() equivalent for mouse events to tell whether a direct or indirect device generated those, so we could ignore those already handled by our touch event code. This seems like an API limitation though that could be addressed in SDL 2.0.11.
Comment 11 Sam Lantinga 2019-07-03 01:27:59 UTC
(In reply to Ryan C. Gordon from comment #9)
> > We do need to resolve this for 2.0.10.
> 
> So let's say on the Mac that the (not actual virtual) touches from the
> trackpad are SDL_MOUSE_TOUCHID, and say the (strictly speaking, virtual, but
> that's hidden by the OS) mouse events from the touchpad are reported as
> physical hardware events?
> 
> It's exactly backwards from reality, but probably matches what people expect
> from SDL events on the platform.

Yeah, let's do that for 2.0.10.
Comment 12 Ryan C. Gordon 2019-07-08 17:48:30 UTC
I took another shot at this with https://hg.libsdl.org/SDL/rev/d6c5eb7a0afb based on changes discussed here.

Now the trackpad on a MacBook reports real mouse events (even though the OS is synthesizing them for us), and synthesized touch events (even though they are technically real)...so again: backwards from reality but more closely aligned with what apps and users expect, since they generally think of the trackpad as a mouse device and not a touch device.

Real touch devices that aren't the trackpad should report separate, non-synthesized touch events as expected, but I don't have any hardware that can test that.

I also ripped out some #ifdefs that had collected in src/events from prior attempts.

Tested locally on a MacBook, seems good to me. Touching the trackpad produces touch events from SDL_MOUSE_TOUCHID (and multitouch still produces separate finger IDs with this "virtual" device, fwiw) and "real" mouse events to match.

Please let me know if this is acceptable; I'd like to ship 2.0.10 and never think about this bug again.  :)

--ryan.
Comment 13 Sam Lantinga 2019-07-08 18:07:31 UTC
This sounds good to me. Can you cross reference bug 4704 and make sure the behavior is sane on Windows?

Thanks!
Comment 14 Sam Lantinga 2019-07-08 18:07:54 UTC
Anyone else have any comments before we close this bug?
Comment 15 Sam Lantinga 2019-07-08 18:11:51 UTC
(In reply to Sam Lantinga from comment #13)
> This sounds good to me. Can you cross reference bug 4704 and make sure the
> behavior is sane on Windows?
> 
> Thanks!

Ryan, can you also check bug 4713?
Comment 16 Sylvain 2019-07-08 18:40:38 UTC
Yes, just wondering: 

since platform layers can generate synthetics events,
maybe we should add in SDL_mouse.c and SDL_touch.c the capability to drop them when the hints are not set.

SDL_mouse.c, SDL_PrivateSendMouse{Button,Motion} :

if (mouse->touch_mouse_events == 0) {
  if (mouseID == SDL_TOUCH_MOUSEID) {
    return 0;
  }
}

SDL_touch.c, SDL_SendTouch{,Motion} :
if (mouse->touch_mouse_events == 0) {

if (mouse->mouse_touch_events == 0) {
  if (id == SDL_MOUSE_TOUCHID) {
    return 0;
  }
}

(also maybe the define SYNTHESIZE_TOUCH_TO_MOUSE is not needed anymore or should be usre?)
Comment 17 Ryan C. Gordon 2019-07-08 18:56:19 UTC
(In reply to Sylvain from comment #16)
> since platform layers can generate synthetics events,
> maybe we should add in SDL_mouse.c and SDL_touch.c the capability to drop
> them when the hints are not set.

Unless you think this is super important to add right now, let's make this change after 2.0.10 ships.

--ryan.
Comment 18 Cameron Gutman 2019-07-08 19:25:05 UTC
I would suggest setting `touchId = (SDL_TouchID)(intptr_t)[touch device]` in the [touch type] == NSTouchTypeDirect` cases, since those are definitely touchscreens. Other than that, looks good to me.

I wasn't sure whether SDL_GetTouchDeviceType() would work on SDL_MOUSE_TOUCHID, but it does :)
Comment 19 Sylvain 2019-07-08 19:32:57 UTC
(In reply to Ryan C. Gordon from comment #17)
> (In reply to Sylvain from comment #16)
> > since platform layers can generate synthetics events,
> > maybe we should add in SDL_mouse.c and SDL_touch.c the capability to drop
> > them when the hints are not set.
> 
> Unless you think this is super important to add right now, let's make this
> change after 2.0.10 ships.
> 
> --ryan.

I don't mean this is a big deal, but if one physical click generates both a mouseEvent and a touchEvent. The button in my game, instead of being clicked once, it will be double-clicked - which sometimes changes the behavior.

As a solution, I can drop all synthetic event, but this is the purpose of the previous patch. I can commit it tomorrow (so that I have time to test it! to make sure I didn't mess-up with the mouse<->touch words)
Comment 20 Sylvain 2019-07-09 09:48:10 UTC
SDL_Mouse/Touch: discard synthetic events when hints are not set.
Those are generated/flagged by platform layer. 

https://hg.libsdl.org/SDL/rev/d03900e991a2
Comment 21 Sylvain 2019-07-10 08:15:35 UTC
On Linux, X11, with a TouchScreen, there are also some synthetics. (call Pointer emulation)
http://who-t.blogspot.com/2011/12/multitouch-in-x-pointer-emulation.html

You get the pointer emulation or not, regarding which event you register.
I have a touchscreen, and when I use it, I receive also duplicate MouseEvents.

Here, it seems we don't get the full pointer_emulation (maybe because we also register XI_RawMotion etc). 
But what happens is: when I press the touch screen I always receive before 1 MotionNotify (which is traduced as a SDL_MouseEvent).

seems to be: 

https://www.x.org/wiki/Development/Documentation/Multitouch/
"Pointer emulation for TouchBegin_
If a touch emulates pointers, a MotionNotify event is generated and sent before the TouchBegin is processed. In addition to touch event masks, grabs and windows are also checked for an applicable pointer event mask."


The patch is to register for xinput2/XI_Motion and discard emulated
https://hg.libsdl.org/SDL/rev/fe7caa031d3e



It seems there are also MouseMotion generated when using the TouchScreen, this is when
EnterNotify or LeaveNotify happens. Not sure if we should generate a motion event here ?
Comment 22 Sylvain 2019-07-10 11:34:12 UTC
Sending MouseMotion in EnterNotify or LeaveNotify was added in bug 1612 for x11.
Maybe this should also for wayland. Continuing in this ticket ...
Comment 23 Ryan C. Gordon 2019-07-30 17:49:34 UTC
(Sorry if you get several emails like this, we're marking a bunch of bugs.)

We're hoping to ship SDL 2.0.11 on a much shorter timeframe than we have historically done releases, so I'm starting to tag bugs we hope to have closed in this release cycle.

Note that this tag means we just intend to scrutinize this bug for the 2.0.11 release: we may fix it, reject it, or even push it back to a later release for now, but this helps give us both a goal and a wishlist for the next release.

If this bug has been quiet for a few months and you have new information (such as, "this is definitely still broken" or "this got fixed at some point"), please feel free to retest and/or add more notes to the bug.

--ryan.
Comment 24 Ryan C. Gordon 2019-07-30 17:52:21 UTC
Moving all the remaining target-2.0.10 bugs to target-2.0.11. If these still aren't resolved when 2.0.11 ships, we should probably remove the keyword altogether.

--ryan.
Comment 25 Ryan C. Gordon 2019-09-20 20:47:39 UTC
We're changing how we do SDL release versions; now releases will be even numbers (2.0.10, 2.0.12, etc), and as soon as we tag a release, we'll move the internal version number to an odd number (2.0.12 ships, we tag the latest in revision control as 2.0.13 immediately, which will become 2.0.14 on release, etc).

As such, I'm moving the bugs tagged with target-2.0.11 to target 2.0.12. Sorry if you get a lot of email from this change!

Thanks,
--ryan.
Comment 26 Ryan C. Gordon 2019-09-20 20:48:43 UTC
We're changing how we do SDL release versions; now releases will be even numbers (2.0.10, 2.0.12, etc), and as soon as we tag a release, we'll move the internal version number to an odd number (2.0.12 ships, we tag the latest in revision control as 2.0.13 immediately, which will become 2.0.14 on release, etc).

As such, I'm moving the bugs tagged with target-2.0.11 to target 2.0.12. Sorry if you get a lot of email from this change!

Thanks,
--ryan.