From e841b066fd76aa1eb7cf2be9a46cc82798ab3c33 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 8 Jul 2019 13:41:01 -0400 Subject: [PATCH] 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. --- src/events/SDL_mouse.c | 2 -- src/events/SDL_touch.c | 4 --- src/video/cocoa/SDL_cocoamouse.m | 22 -------------- src/video/cocoa/SDL_cocoawindow.m | 48 +++++++++---------------------- 4 files changed, 13 insertions(+), 63 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index d63f00cc80af9..c423c56e542ee 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 ff2d706182029..6cf576dc1dc84 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 f5c06be9c8b57..01ed6141bd152 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 @@ + (NSCursor *)invisibleCursor } 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 @@ + (NSCursor *)invisibleCursor } 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 fd56f5c363f8c..879af65fc8162 100644 --- a/src/video/cocoa/SDL_cocoawindow.m +++ b/src/video/cocoa/SDL_cocoawindow.m @@ -918,20 +918,10 @@ - (void)mouseDown:(NSEvent *)theEvent 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 @@ - (void)mouseUp:(NSEvent *)theEvent 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 @@ - (void)mouseMoved:(NSEvent *)theEvent 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 @@ - (void)scrollWheel:(NSEvent *)theEvent - (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 @@ - (void)touchesBeganWithEvent:(NSEvent *) theEvent } } 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 @@ - (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent { 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. */