From aca556b644c6644f12f9da62ef537ac229fa6c21 Mon Sep 17 00:00:00 2001 From: Sascha Reuter Date: Sun, 21 Jun 2026 15:03:42 +1000 Subject: [PATCH] tvOS: add SDL_HINT_APPLE_TV_REMOTE_SWIPE_GESTURES to control swipe recognizers On tvOS, SDL installs UISwipeGestureRecognizers on the view so Apple TV remote swipes generate arrow-key events. When one recognizes, it cancels the in-progress touches, because the recognizers don't set cancelsTouchesInView = NO. Apps that read the remote touchpad's raw touch events directly (for example, absolute or relative pointer control) get their touch sequence cut off mid-gesture. Add SDL_HINT_APPLE_TV_REMOTE_SWIPE_GESTURES to gate installation of those recognizers. Default is "1", which keeps the current behavior. Set "0" to skip them and receive uninterrupted touch events. --- include/SDL3/SDL_hints.h | 22 +++++++++++++++++++++ src/video/uikit/SDL_uikitview.m | 35 ++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index d01f36f8a9e2f..9619ed874e92c 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -212,6 +212,28 @@ extern "C" { */ #define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION" +/** + * A variable controlling whether the Apple TV remote's touchpad swipe gesture + * recognizers are installed. + * + * On tvOS SDL installs UISwipeGestureRecognizers so that swipes on the remote's + * touchpad generate arrow-key events, which is convenient for apps that do not + * process touch directly. These recognizers cancel the underlying touches when + * they fire, which interferes with apps that implement their own handling of the + * remote touchpad's touch events. + * + * The variable can be set to the following values: + * + * - "0": The swipe gesture recognizers are not installed; raw touch events are + * delivered without being cancelled. + * - "1": The swipe gesture recognizers are installed. (default) + * + * This hint should be set before a window is created. + * + * \since This hint is available since SDL 3.5.0. + */ +#define SDL_HINT_APPLE_TV_REMOTE_SWIPE_GESTURES "SDL_APPLE_TV_REMOTE_SWIPE_GESTURES" + /** * Specify the default ALSA audio device name. * diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index d05a14a1c3190..ebe9cfacae491 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -58,22 +58,25 @@ - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { #ifdef SDL_PLATFORM_TVOS - // Apple TV Remote touchpad swipe gestures. - UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; - swipeUp.direction = UISwipeGestureRecognizerDirectionUp; - [self addGestureRecognizer:swipeUp]; - - UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; - swipeDown.direction = UISwipeGestureRecognizerDirectionDown; - [self addGestureRecognizer:swipeDown]; - - UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; - swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft; - [self addGestureRecognizer:swipeLeft]; - - UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; - swipeRight.direction = UISwipeGestureRecognizerDirectionRight; - [self addGestureRecognizer:swipeRight]; + // Apple TV Remote touchpad swipe gestures. These cancel the touches they + // recognize, so let apps that handle touch directly turn them off. + if (SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_SWIPE_GESTURES, true)) { + UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; + swipeUp.direction = UISwipeGestureRecognizerDirectionUp; + [self addGestureRecognizer:swipeUp]; + + UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; + swipeDown.direction = UISwipeGestureRecognizerDirectionDown; + [self addGestureRecognizer:swipeDown]; + + UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; + swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft; + [self addGestureRecognizer:swipeLeft]; + + UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; + swipeRight.direction = UISwipeGestureRecognizerDirectionRight; + [self addGestureRecognizer:swipeRight]; + } #endif #if !defined(SDL_PLATFORM_TVOS)