Skip to content

Commit

Permalink
cocoa: Another attempt at mouse vs touch support.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
icculus committed Jul 8, 2019
1 parent 680e793 commit e841b06
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 63 deletions.
2 changes: 0 additions & 2 deletions src/events/SDL_mouse.c
Expand Up @@ -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) {
Expand Down
4 changes: 0 additions & 4 deletions src/events/SDL_touch.c
Expand Up @@ -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;
Expand Down
22 changes: 0 additions & 22 deletions src/video/cocoa/SDL_cocoamouse.m
Expand Up @@ -38,8 +38,6 @@
#define DLog(...) do { } while (0)
#endif

#define TRACKPAD_REPORTS_TOUCH_MOUSEID 0

@implementation NSCursor (InvisibleCursor)
+ (NSCursor *)invisibleCursor
{
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
48 changes: 13 additions & 35 deletions src/video/cocoa/SDL_cocoawindow.m
Expand Up @@ -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];
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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. */
Expand Down

0 comments on commit e841b06

Please sign in to comment.