Commit e841b066fd76aa1eb7cf2be9a46cc82798ab3c33

Ryan C. Gordon 2019-07-08T13:41:01

cocoa: Another attempt at mouse vs touch support. This time, we make anything we think is a MacBook trackpad report its touches as SDL_MOUSE_TOUCHID, even though they're not _actually_ synthesized events, and let all mouse input--even if the OS synthesized it from a multitouch trackpad on our behalf--look like physical input. This is backwards from reality, but produces the results most apps will expect. Note that if you have a real touch device that doesn't appear to be the trackpad, it'll produce real touch events with unique device ids, so it's not a total loss here, but also note that the way we decide if it was the trackpad is an imperfect heuristic; it happens to work out right now, but it's not impossible that a real touchscreen could come to the Mac at some point and (incorrectly?) call it a "mouse" input, etc. But for now, good enough. Fixes Bugzilla #4690.

diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index d63f00c..c423c56 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -383,13 +383,11 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
         mouse->has_position = SDL_TRUE;
     }
 
-#ifndef __MACOSX__  /* all your trackpad input would lack relative motion when not dragging in this case. */
     /* Ignore relative motion positioning the first touch */
     if (mouseID == SDL_TOUCH_MOUSEID && !mouse->buttonstate) {
         xrel = 0;
         yrel = 0;
     }
-#endif
 
     /* Update internal mouse coordinates */
     if (!mouse->relative_mode) {
diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c
index ff2d706..6cf576d 100644
--- a/src/events/SDL_touch.c
+++ b/src/events/SDL_touch.c
@@ -33,11 +33,7 @@ static SDL_Touch **SDL_touchDevices = NULL;
 
 /* for mapping touch events to mice */
 
-#ifndef __MACOSX__  /* don't generate mouse events from touch on macOS, the OS handles that. */
 #define SYNTHESIZE_TOUCH_TO_MOUSE 1
-#else
-#define SYNTHESIZE_TOUCH_TO_MOUSE 0
-#endif
 
 #if SYNTHESIZE_TOUCH_TO_MOUSE
 static SDL_bool finger_touching = SDL_FALSE;
diff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m
index f5c06be..01ed614 100644
--- a/src/video/cocoa/SDL_cocoamouse.m
+++ b/src/video/cocoa/SDL_cocoamouse.m
@@ -38,8 +38,6 @@
 #define DLog(...) do { } while (0)
 #endif
 
-#define TRACKPAD_REPORTS_TOUCH_MOUSEID 0
-
 @implementation NSCursor (InvisibleCursor)
 + (NSCursor *)invisibleCursor
 {
@@ -381,16 +379,6 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
     }
 
     SDL_MouseID mouseID = mouse ? mouse->mouseID : 0;
-    #if TRACKPAD_REPORTS_TOUCH_MOUSEID
-    if ([event subtype] == NSEventSubtypeTouch) {  /* this is a synthetic from the OS */
-        if (mouse->touch_mouse_events) {
-            mouseID = SDL_TOUCH_MOUSEID;   /* Hint is set */
-        } else {
-            return;  /* no hint set, drop this one. */
-        }
-    }
-    #endif
-
     const SDL_bool seenWarp = driverdata->seenWarp;
     driverdata->seenWarp = NO;
 
@@ -436,16 +424,6 @@ Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
     }
 
     SDL_MouseID mouseID = mouse->mouseID;
-    #if TRACKPAD_REPORTS_TOUCH_MOUSEID
-    if ([event subtype] == NSEventSubtypeTouch) {  /* this is a synthetic from the OS */
-        if (mouse->touch_mouse_events) {
-            mouseID = SDL_TOUCH_MOUSEID;   /* Hint is set */
-        } else {
-            return;  /* no hint set, drop this one. */
-        }
-    }
-    #endif
-
     CGFloat x = -[event deltaX];
     CGFloat y = [event deltaY];
     SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL;
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index fd56f5c..879af65 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -918,20 +918,10 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
         return;
     }
 
-    SDL_MouseID mouseID = mouse->mouseID;
+    const SDL_MouseID mouseID = mouse->mouseID;
     int button;
     int clicks;
 
-    #if TRACKPAD_REPORTS_TOUCH_MOUSEID
-    if ([theEvent subtype] == NSEventSubtypeTouch) {  /* this is a synthetic from the OS */
-        if (mouse->touch_mouse_events) {
-            mouseID = SDL_TOUCH_MOUSEID;   /* Hint is set */
-        } else {
-            return;  /* no hint set, drop this one. */
-        }
-    }
-    #endif
-
     /* Ignore events that aren't inside the client area (i.e. title bar.) */
     if ([theEvent window]) {
         NSRect windowRect = [[[theEvent window] contentView] frame];
@@ -989,20 +979,10 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
         return;
     }
 
-    SDL_MouseID mouseID = mouse->mouseID;
+    const SDL_MouseID mouseID = mouse->mouseID;
     int button;
     int clicks;
 
-    #if TRACKPAD_REPORTS_TOUCH_MOUSEID
-    if ([theEvent subtype] == NSEventSubtypeTouch) {  /* this is a synthetic from the OS */
-        if (mouse->touch_mouse_events) {
-            mouseID = SDL_TOUCH_MOUSEID;   /* Hint is set */
-        } else {
-            return;  /* no hint set, drop this one. */
-        }
-    }
-    #endif
-
     if ([self processHitTest:theEvent]) {
         SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
         return;  /* stopped dragging, drop event. */
@@ -1050,21 +1030,11 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
         return;
     }
 
-    SDL_MouseID mouseID = mouse->mouseID;
+    const SDL_MouseID mouseID = mouse->mouseID;
     SDL_Window *window = _data->window;
     NSPoint point;
     int x, y;
 
-    #if TRACKPAD_REPORTS_TOUCH_MOUSEID
-    if ([theEvent subtype] == NSEventSubtypeTouch) {  /* this is a synthetic from the OS */
-        if (mouse->touch_mouse_events) {
-            mouseID = SDL_TOUCH_MOUSEID;   /* Hint is set */
-        } else {
-            return;  /* no hint set, drop this one. */
-        }
-    }
-    #endif
-
     if ([self processHitTest:theEvent]) {
         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
         return;  /* dragging, drop event. */
@@ -1134,7 +1104,12 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
 
 - (void)touchesBeganWithEvent:(NSEvent *) theEvent
 {
+    /* probably a MacBook trackpad; make this look like a synthesized event.
+       This is backwards from reality, but better matches user expectations. */
+    const BOOL istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
+
     NSSet *touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
+    const SDL_TouchID touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
     int existingTouchCount = 0;
 
     for (NSTouch* touch in touches) {
@@ -1143,7 +1118,6 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
         }
     }
     if (existingTouchCount == 0) {
-        const SDL_TouchID touchID = (SDL_TouchID)(intptr_t)[[touches anyObject] device];
         int numFingers = SDL_GetNumTouchFingers(touchID);
         DLog("Reset Lost Fingers: %d", numFingers);
         for (--numFingers; numFingers >= 0; --numFingers) {
@@ -1175,8 +1149,12 @@ SetWindowStyle(SDL_Window * window, NSUInteger style)
 {
     NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
 
+    /* probably a MacBook trackpad; make this look like a synthesized event.
+       This is backwards from reality, but better matches user expectations. */
+    const BOOL istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
+
     for (NSTouch *touch in touches) {
-        const SDL_TouchID touchId = (SDL_TouchID)(intptr_t)[touch device];
+        const SDL_TouchID touchId = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[touch device];
         SDL_TouchDeviceType devtype = SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE;
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 101202 /* Added in the 10.12.2 SDK. */