Skip to content

Commit bdc7f95

Browse files
committed
cocoa: Added hint to treat MacBook trackpads as touch devices, not mice.
Fixes #5511.
1 parent 73d8d02 commit bdc7f95

File tree

5 files changed

+54
-30
lines changed

5 files changed

+54
-30
lines changed

include/SDL_hints.h

+22
Original file line numberDiff line numberDiff line change
@@ -2207,6 +2207,28 @@ extern "C" {
22072207
#define SDL_HINT_KMSDRM_DEVICE_INDEX "SDL_KMSDRM_DEVICE_INDEX"
22082208

22092209

2210+
/**
2211+
* \brief A variable that treats trackpads as touch devices.
2212+
*
2213+
* On macOS (and possibly other platforms in the future), SDL will report
2214+
* touches on a trackpad as mouse input, which is generally what users
2215+
* expect from this device; however, these are often actually full
2216+
* multitouch-capable touch devices, so it might be preferable to some apps
2217+
* to treat them as such.
2218+
*
2219+
* Setting this hint to true will make the trackpad input report as a
2220+
* multitouch device instead of a mouse. The default is false.
2221+
*
2222+
* Note that most platforms don't support this hint. As of 2.24.0, it
2223+
* only supports MacBooks' trackpads on macOS. Others may follow later.
2224+
*
2225+
* This hint is checked during SDL_Init and can not be changed after.
2226+
*
2227+
* This hint is available since SDL 2.24.0.
2228+
*/
2229+
#define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY"
2230+
2231+
22102232
/**
22112233
* \brief An enumeration of hint priorities
22122234
*/

src/video/cocoa/SDL_cocoavideo.h

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ DECLARE_ALERT_STYLE(Critical);
9999

100100
@interface SDL_VideoData : NSObject
101101
@property (nonatomic) int allow_spaces;
102+
@property (nonatomic) int trackpad_is_touch_only;
102103
@property (nonatomic) unsigned int modifierFlags;
103104
@property (nonatomic) void *key_layout;
104105
@property (nonatomic) SDLTranslatorResponder *fieldEdit;

src/video/cocoa/SDL_cocoavideo.m

+1
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ @implementation SDL_VideoData
197197
}
198198

199199
data.allow_spaces = SDL_GetHintBoolean(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_TRUE);
200+
data.trackpad_is_touch_only = SDL_GetHintBoolean(SDL_HINT_TRACKPAD_IS_TOUCH_ONLY, SDL_FALSE);
200201

201202
data.swaplock = SDL_CreateMutex();
202203
if (!data.swaplock) {

src/video/cocoa/SDL_cocoawindow.h

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ typedef enum
5656
BOOL isDragAreaRunning;
5757
}
5858

59+
-(BOOL) isTouchFromTrackpad:(NSEvent *)theEvent;
5960
-(void) listen:(SDL_WindowData *) data;
6061
-(void) pauseVisibleObservation;
6162
-(void) resumeVisibleObservation;

src/video/cocoa/SDL_cocoawindow.m

+29-30
Original file line numberDiff line numberDiff line change
@@ -1359,26 +1359,39 @@ - (void)scrollWheel:(NSEvent *)theEvent
13591359
Cocoa_HandleMouseWheel(_data.window, theEvent);
13601360
}
13611361

1362+
1363+
- (BOOL)isTouchFromTrackpad:(NSEvent *)theEvent
1364+
{
1365+
SDL_Window *window = _data.window;
1366+
SDL_VideoData *videodata = ((__bridge SDL_WindowData *) window->driverdata).videodata;
1367+
1368+
/* if this a MacBook trackpad, we'll make input look like a synthesized
1369+
event. This is backwards from reality, but better matches user
1370+
expectations. You can make it look like a generic touch device instead
1371+
with the SDL_HINT_TRACKPAD_IS_TOUCH_ONLY hint. */
1372+
BOOL istrackpad = NO;
1373+
if (!videodata.trackpad_is_touch_only) {
1374+
@try {
1375+
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
1376+
}
1377+
@catch (NSException *e) {
1378+
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
1379+
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
1380+
* This still prints a message to terminal so catching it's not an ideal solution.
1381+
*
1382+
* *** Assertion failure in -[NSEvent subtype]
1383+
*/
1384+
}
1385+
}
1386+
return istrackpad;
1387+
}
1388+
13621389
- (void)touchesBeganWithEvent:(NSEvent *) theEvent
13631390
{
13641391
NSSet *touches;
13651392
SDL_TouchID touchID;
13661393
int existingTouchCount;
1367-
1368-
/* probably a MacBook trackpad; make this look like a synthesized event.
1369-
This is backwards from reality, but better matches user expectations. */
1370-
BOOL istrackpad = NO;
1371-
@try {
1372-
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
1373-
}
1374-
@catch (NSException *e) {
1375-
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
1376-
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
1377-
* This still prints a message to terminal so catching it's not an ideal solution.
1378-
*
1379-
* *** Assertion failure in -[NSEvent subtype]
1380-
*/
1381-
}
1394+
const BOOL istrackpad = [self isTouchFromTrackpad:theEvent];
13821395

13831396
touches = [theEvent touchesMatchingPhase:NSTouchPhaseAny inView:nil];
13841397
touchID = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[[touches anyObject] device];
@@ -1426,24 +1439,10 @@ - (void)touchesCancelledWithEvent:(NSEvent *) theEvent
14261439
- (void)handleTouches:(NSTouchPhase) phase withEvent:(NSEvent *) theEvent
14271440
{
14281441
NSSet *touches = [theEvent touchesMatchingPhase:phase inView:nil];
1442+
const BOOL istrackpad = [self isTouchFromTrackpad:theEvent];
14291443
SDL_FingerID fingerId;
14301444
float x, y;
14311445

1432-
/* probably a MacBook trackpad; make this look like a synthesized event.
1433-
This is backwards from reality, but better matches user expectations. */
1434-
BOOL istrackpad = NO;
1435-
@try {
1436-
istrackpad = ([theEvent subtype] == NSEventSubtypeMouseEvent);
1437-
}
1438-
@catch (NSException *e) {
1439-
/* if NSEvent type doesn't have subtype, such as NSEventTypeBeginGesture on
1440-
* macOS 10.5 to 10.10, then NSInternalInconsistencyException is thrown.
1441-
* This still prints a message to terminal so catching it's not an ideal solution.
1442-
*
1443-
* *** Assertion failure in -[NSEvent subtype]
1444-
*/
1445-
}
1446-
14471446
for (NSTouch *touch in touches) {
14481447
const SDL_TouchID touchId = istrackpad ? SDL_MOUSE_TOUCHID : (SDL_TouchID)(intptr_t)[touch device];
14491448
SDL_TouchDeviceType devtype = SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE;

0 commit comments

Comments
 (0)