From f59b9c8b13811129c620410c7541ec1afe164472 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 6 Feb 2018 15:03:38 -0800 Subject: [PATCH] Replaced SDL_HINT_APPLE_TV_REMOTE_SWIPES_AS_ARROW_KEYS with SDL_HINT_TV_REMOTE_AS_JOYSTICK which controls whether remotes on iOS and Android are interpreted as joysticks (the default) or as return/escape/arrow keys. --- include/SDL_hints.h | 27 ++++++++-------- src/joystick/android/SDL_sysjoystick.c | 41 ++++++++++++++++++++++--- src/joystick/iphoneos/SDL_sysjoystick.m | 34 ++++++++++---------- src/video/uikit/SDL_uikitview.m | 39 ++++++++++++----------- 4 files changed, 89 insertions(+), 52 deletions(-) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index 8c0d72204a7a2..08a00c96b8ad6 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -355,16 +355,6 @@ extern "C" { */ #define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION" -/** - * \brief A variable controlling whether the Apple TV remote swipes are - * translated into arrow key events - * - * This variable can be set to the following values: - * "0" - Swipes are not translated into arrow key events - * "1" - Swipes are translated into arrow key events (the default) - */ -#define SDL_HINT_APPLE_TV_REMOTE_SWIPES_AS_ARROW_KEYS "SDL_APPLE_TV_REMOTE_SWIPES_AS_ARROW_KEYS" - /** * \brief A variable controlling whether the home indicator bar on iPhone X * should be hidden. @@ -378,15 +368,24 @@ extern "C" { /** * \brief A variable controlling whether the Android / iOS built-in - * accelerometer should be listed as a joystick device, rather than listing - * actual joysticks only. + * accelerometer should be listed as a joystick device. * * This variable can be set to the following values: - * "0" - List only real joysticks and accept input from them - * "1" - List real joysticks along with the accelerometer as if it were a 3 axis joystick (the default). + * "0" - The accelerometer is not listed as a joystick + * "1" - The accelerometer is available as a 3 axis joystick (the default). */ #define SDL_HINT_ACCELEROMETER_AS_JOYSTICK "SDL_ACCELEROMETER_AS_JOYSTICK" +/** + * \brief A variable controlling whether the Android / iOS remotes + * should be listed as joystick devices, instead of sending keyboard events. + * + * This variable can be set to the following values: + * "0" - Remotes send enter/escape/arrow key events + * "1" - Remotes are available as 2 axis, 2 button joysticks (the default). + */ +#define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK" + /** * \brief A variable that lets you disable the detection and use of Xinput gamepad devices * diff --git a/src/joystick/android/SDL_sysjoystick.c b/src/joystick/android/SDL_sysjoystick.c index 33e5483bdc1f5..ee6014e134b8d 100644 --- a/src/joystick/android/SDL_sysjoystick.c +++ b/src/joystick/android/SDL_sysjoystick.c @@ -80,8 +80,7 @@ keycode_to_SDL(int keycode) { /* FIXME: If this function gets too unwieldy in the future, replace with a lookup table */ int button = 0; - switch(keycode) - { + switch (keycode) { /* Some gamepad buttons (API 9) */ case AKEYCODE_BUTTON_A: button = SDL_CONTROLLER_BUTTON_A; @@ -179,7 +178,30 @@ keycode_to_SDL(int keycode) */ SDL_assert(button < ANDROID_MAX_NBUTTONS); return button; - +} + +static SDL_Scancode +button_to_scancode(int button) +{ + switch (button) { + case SDL_CONTROLLER_BUTTON_A: + return SDL_SCANCODE_RETURN; + case SDL_CONTROLLER_BUTTON_B: + return SDL_SCANCODE_ESCAPE; + case SDL_CONTROLLER_BUTTON_BACK: + return SDL_SCANCODE_ESCAPE; + case SDL_CONTROLLER_BUTTON_DPAD_UP: + return SDL_SCANCODE_UP; + case SDL_CONTROLLER_BUTTON_DPAD_DOWN: + return SDL_SCANCODE_DOWN; + case SDL_CONTROLLER_BUTTON_DPAD_LEFT: + return SDL_SCANCODE_LEFT; + case SDL_CONTROLLER_BUTTON_DPAD_RIGHT: + return SDL_SCANCODE_RIGHT; + } + + /* Unsupported button */ + return SDL_SCANCODE_UNKNOWN; } int @@ -191,6 +213,8 @@ Android_OnPadDown(int device_id, int keycode) item = JoystickByDeviceId(device_id); if (item && item->joystick) { SDL_PrivateJoystickButton(item->joystick, button , SDL_PRESSED); + } else { + SDL_SendKeyboardKey(SDL_PRESSED, button_to_scancode(button)); } return 0; } @@ -207,6 +231,8 @@ Android_OnPadUp(int device_id, int keycode) item = JoystickByDeviceId(device_id); if (item && item->joystick) { SDL_PrivateJoystickButton(item->joystick, button, SDL_RELEASED); + } else { + SDL_SendKeyboardKey(SDL_RELEASED, button_to_scancode(button)); } return 0; } @@ -252,8 +278,15 @@ Android_AddJoystick(int device_id, const char *name, const char *desc, SDL_bool { SDL_JoystickGUID guid; SDL_joylist_item *item; + + if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { + /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */ + if (naxes < 2 && nhats < 1) { + return -1; + } + } - if(JoystickByDeviceId(device_id) != NULL || name == NULL) { + if (JoystickByDeviceId(device_id) != NULL || name == NULL) { return -1; } diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m index 2d20f92485e25..e1602e58d6e58 100644 --- a/src/joystick/iphoneos/SDL_sysjoystick.m +++ b/src/joystick/iphoneos/SDL_sysjoystick.m @@ -150,6 +150,15 @@ { SDL_JoystickDeviceItem *device = deviceList; +#if TARGET_OS_TV + if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { + /* Ignore devices that aren't actually controllers (e.g. remotes), they'll be handled as keyboard input */ + if (controller && !controller.extendedGamepad && !controller.gamepad && controller.microGamepad) { + return; + } + } +#endif + while (device != NULL) { if (device->controller == controller) { return; @@ -157,13 +166,11 @@ device = device->next; } - device = (SDL_JoystickDeviceItem *) SDL_malloc(sizeof(SDL_JoystickDeviceItem)); + device = (SDL_JoystickDeviceItem *) SDL_calloc(1, sizeof(SDL_JoystickDeviceItem)); if (device == NULL) { return; } - SDL_zerop(device); - device->accelerometer = accelerometer; device->instance_id = instancecounter++; @@ -277,11 +284,11 @@ static SDL_bool SteamControllerConnectedCallback(const char *name, SDL_JoystickG } *device_instance = device->instance_id = instancecounter++; - device->name = SDL_strdup(name); - device->guid = guid; - SDL_GetSteamControllerInputs(&device->nbuttons, - &device->naxes, - &device->nhats); + device->name = SDL_strdup(name); + device->guid = guid; + SDL_GetSteamControllerInputs(&device->nbuttons, + &device->naxes, + &device->nhats); device->m_bSteamController = SDL_TRUE; if (deviceList == NULL) { @@ -305,10 +312,10 @@ static void SteamControllerDisconnectedCallback(int device_instance) { SDL_JoystickDeviceItem *item; - for (item = deviceList; item; item = item->next) { + for (item = deviceList; item; item = item->next) { if (item->instance_id == device_instance) { - SDL_SYS_RemoveJoystickDevice(item); - break; + SDL_SYS_RemoveJoystickDevice(item); + break; } } } @@ -608,9 +615,6 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) SDL_PrivateJoystickAxis(joystick, i, axes[i]); } - /* Apparently the dpad values are not accurate enough to be useful. */ - /* hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad); */ - Uint8 buttons[] = { gamepad.buttonA.isPressed, gamepad.buttonX.isPressed, @@ -620,8 +624,6 @@ SDL_JoystickID SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) updateplayerindex |= (joystick->buttons[i] != buttons[i]); SDL_PrivateJoystickButton(joystick, i, buttons[i]); } - - /* TODO: Figure out what to do with reportsAbsoluteDpadValues */ } #endif /* TARGET_OS_TV */ diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index e5dc99a0ce18a..b4f0f33332acf 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -44,7 +44,7 @@ - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { #if TARGET_OS_TV - if (SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_SWIPES_AS_ARROW_KEYS, SDL_TRUE)) { + if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { /* Apple TV Remote touchpad swipe gestures. */ UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; swipeUp.direction = UISwipeGestureRecognizerDirectionUp; @@ -237,10 +237,10 @@ - (SDL_Scancode)scancodeFromPressType:(UIPressType)presstype return SDL_SCANCODE_RIGHT; case UIPressTypeSelect: /* HIG says: "primary button behavior" */ - return SDL_SCANCODE_SELECT; + return SDL_SCANCODE_RETURN; case UIPressTypeMenu: /* HIG says: "returns to previous screen" */ - return SDL_SCANCODE_MENU; + return SDL_SCANCODE_ESCAPE; case UIPressTypePlayPause: /* HIG says: "secondary button behavior" */ return SDL_SCANCODE_PAUSE; @@ -251,31 +251,34 @@ - (SDL_Scancode)scancodeFromPressType:(UIPressType)presstype - (void)pressesBegan:(NSSet *)presses withEvent:(UIPressesEvent *)event { - for (UIPress *press in presses) { - SDL_Scancode scancode = [self scancodeFromPressType:press.type]; - SDL_SendKeyboardKey(SDL_PRESSED, scancode); - } - + if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { + for (UIPress *press in presses) { + SDL_Scancode scancode = [self scancodeFromPressType:press.type]; + SDL_SendKeyboardKey(SDL_PRESSED, scancode); + } + } [super pressesBegan:presses withEvent:event]; } - (void)pressesEnded:(NSSet *)presses withEvent:(UIPressesEvent *)event { - for (UIPress *press in presses) { - SDL_Scancode scancode = [self scancodeFromPressType:press.type]; - SDL_SendKeyboardKey(SDL_RELEASED, scancode); - } - + if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { + for (UIPress *press in presses) { + SDL_Scancode scancode = [self scancodeFromPressType:press.type]; + SDL_SendKeyboardKey(SDL_RELEASED, scancode); + } + } [super pressesEnded:presses withEvent:event]; } - (void)pressesCancelled:(NSSet *)presses withEvent:(UIPressesEvent *)event { - for (UIPress *press in presses) { - SDL_Scancode scancode = [self scancodeFromPressType:press.type]; - SDL_SendKeyboardKey(SDL_RELEASED, scancode); - } - + if (!SDL_GetHintBoolean(SDL_HINT_TV_REMOTE_AS_JOYSTICK, SDL_TRUE)) { + for (UIPress *press in presses) { + SDL_Scancode scancode = [self scancodeFromPressType:press.type]; + SDL_SendKeyboardKey(SDL_RELEASED, scancode); + } + } [super pressesCancelled:presses withEvent:event]; }