cocoa: Added hint to treat MacBook trackpads as touch devices, not mice.

Fixes #5511.
This commit is contained in:
Ryan C. Gordon
2022-08-10 00:41:25 -04:00
parent 73d8d02629
commit bdc7f958fd
5 changed files with 54 additions and 30 deletions

View File

@@ -99,6 +99,7 @@ DECLARE_ALERT_STYLE(Critical);
@interface SDL_VideoData : NSObject
@property (nonatomic) int allow_spaces;
@property (nonatomic) int trackpad_is_touch_only;
@property (nonatomic) unsigned int modifierFlags;
@property (nonatomic) void *key_layout;
@property (nonatomic) SDLTranslatorResponder *fieldEdit;

View File

@@ -197,6 +197,7 @@ Cocoa_VideoInit(_THIS)
}
data.allow_spaces = SDL_GetHintBoolean(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_TRUE);
data.trackpad_is_touch_only = SDL_GetHintBoolean(SDL_HINT_TRACKPAD_IS_TOUCH_ONLY, SDL_FALSE);
data.swaplock = SDL_CreateMutex();
if (!data.swaplock) {

View File

@@ -56,6 +56,7 @@ typedef enum
BOOL isDragAreaRunning;
}
-(BOOL) isTouchFromTrackpad:(NSEvent *)theEvent;
-(void) listen:(SDL_WindowData *) data;
-(void) pauseVisibleObservation;
-(void) resumeVisibleObservation;

View File

@@ -1359,26 +1359,39 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
Cocoa_HandleMouseWheel(_data.window, theEvent);
}
- (BOOL)isTouchFromTrackpad:(NSEvent *)theEvent
{
SDL_Window *window = _data.window;
SDL_VideoData *videodata = ((__bridge SDL_WindowData *) window->driverdata).videodata;
/* if this a MacBook trackpad, we'll make input look like a synthesized
event. This is backwards from reality, but better matches user
expectations. You can make it look like a generic touch device instead
with the SDL_HINT_TRACKPAD_IS_TOUCH_ONLY hint. */
BOOL istrackpad = NO;
if (!videodata.trackpad_is_touch_only) {
@try {
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
}
@catch (NSException *e) {
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
* This still prints a message to terminal so catching it's not an ideal solution.
*
* *** Assertion failure in -[NSEvent subtype]
*/
}
}
return istrackpad;
}
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
{
NSSet *touches;
SDL_TouchID touchID;
int existingTouchCount;
/* probably a MacBook trackpad; make this look like a synthesized event.
This is backwards from reality, but better matches user expectations. */
BOOL istrackpad = NO;
@try {
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
}
@catch (NSException *e) {
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
* This still prints a message to terminal so catching it's not an ideal solution.
*
* *** Assertion failure in -[NSEvent subtype]
*/
}
const BOOL istrackpad = [self isTouchFromTrackpad:theEvent];
touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
@@ -1426,24 +1439,10 @@ Cocoa_SendMouseButtonClicks(SDL_Mouse * mouse, NSEvent *theEvent, SDL_Window * w
- (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent
{
NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
const BOOL istrackpad = [self isTouchFromTrackpad:theEvent];
SDL_FingerID fingerId;
float x, y;
/* probably a MacBook trackpad; make this look like a synthesized event.
This is backwards from reality, but better matches user expectations. */
BOOL istrackpad = NO;
@try {
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
}
@catch (NSException *e) {
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
* This still prints a message to terminal so catching it's not an ideal solution.
*
* *** Assertion failure in -[NSEvent subtype]
*/
}
for (NSTouch *touch in touches) {
const SDL_TouchID touchId = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[touch device];
SDL_TouchDeviceType devtype = SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE;