Skip to content

Commit

Permalink
Added support for press/release hardware keyboard events in iOS 13.4
Browse files Browse the repository at this point in the history
  • Loading branch information
slouken committed Apr 9, 2020
1 parent e9c94ac commit d4f1b52
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 96 deletions.
8 changes: 6 additions & 2 deletions src/events/SDL_events.c
Expand Up @@ -35,9 +35,9 @@

#undef SDL_PRIs64
#ifdef __WIN32__
#define SDL_PRIs64 "I64d"
#define SDL_PRIs64 "I64d"
#else
#define SDL_PRIs64 "lld"
#define SDL_PRIs64 "lld"
#endif

/* An arbitrary limit so we don't have unbounded growth */
Expand Down Expand Up @@ -678,10 +678,14 @@ SDL_PumpEvents(void)
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();

/* Release any keys held down from last frame */
SDL_ReleaseAutoReleaseKeys();

/* Get events from the video subsystem */
if (_this) {
_this->PumpEvents(_this);
}

#if !SDL_JOYSTICK_DISABLED
/* Check for joystick state change */
if ((!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY))) {
Expand Down
80 changes: 70 additions & 10 deletions src/events/SDL_keyboard.c
Expand Up @@ -33,15 +33,20 @@

/* Global keyboard information */

#define KEYBOARD_HARDWARE 0x01
#define KEYBOARD_AUTORELEASE 0x02

typedef struct SDL_Keyboard SDL_Keyboard;

struct SDL_Keyboard
{
/* Data common to all keyboards */
SDL_Window *focus;
Uint16 modstate;
Uint8 keysource[SDL_NUM_SCANCODES];
Uint8 keystate[SDL_NUM_SCANCODES];
SDL_Keycode keymap[SDL_NUM_SCANCODES];
SDL_bool autorelease_pending;
};

static SDL_Keyboard SDL_keyboard;
Expand Down Expand Up @@ -675,19 +680,20 @@ SDL_SetKeyboardFocus(SDL_Window * window)
}
}

int
SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
static int
SDL_SendKeyboardKeyInternal(Uint8 source, Uint8 state, SDL_Scancode scancode)
{
SDL_Keyboard *keyboard = &SDL_keyboard;
int posted;
SDL_Keymod modifier;
SDL_Keycode keycode;
Uint32 type;
Uint8 repeat;
Uint8 repeat = SDL_FALSE;

if (!scancode) {
if (scancode == SDL_SCANCODE_UNKNOWN) {
return 0;
}

#ifdef DEBUG_KEYBOARD
printf("The '%s' key has been %s\n", SDL_GetScancodeName(scancode),
state == SDL_PRESSED ? "pressed" : "released");
Expand All @@ -707,19 +713,31 @@ SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
}

/* Drop events that don't change state */
repeat = (state && keyboard->keystate[scancode]);
if (keyboard->keystate[scancode] == state && !repeat) {
#if 0
printf("Keyboard event didn't change state - dropped!\n");
#endif
return 0;
if (state) {
if (keyboard->keystate[scancode]) {
if (!(keyboard->keysource[scancode] & source)) {
keyboard->keysource[scancode] |= source;
return 0;
}
repeat = SDL_TRUE;
}
keyboard->keysource[scancode] |= source;
} else {
if (!keyboard->keystate[scancode]) {
return 0;
}
keyboard->keysource[scancode] = 0;
}

/* Update internal keyboard state */
keyboard->keystate[scancode] = state;

keycode = keyboard->keymap[scancode];

if (source == KEYBOARD_AUTORELEASE) {
keyboard->autorelease_pending = SDL_TRUE;
}

/* Update modifiers state if applicable */
switch (keycode) {
case SDLK_LCTRL:
Expand Down Expand Up @@ -785,6 +803,48 @@ SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
return (posted);
}

int
SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode)
{
return SDL_SendKeyboardKeyInternal(KEYBOARD_HARDWARE, state, scancode);
}

int
SDL_SendKeyboardKeyAutoRelease(SDL_Scancode scancode)
{
return SDL_SendKeyboardKeyInternal(KEYBOARD_AUTORELEASE, SDL_PRESSED, scancode);
}

void
SDL_ReleaseAutoReleaseKeys(void)
{
SDL_Keyboard *keyboard = &SDL_keyboard;
SDL_Scancode scancode;

if (keyboard->autorelease_pending) {
for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) {
if (keyboard->keysource[scancode] == KEYBOARD_AUTORELEASE) {
SDL_SendKeyboardKeyInternal(KEYBOARD_AUTORELEASE, SDL_RELEASED, scancode);
}
}
keyboard->autorelease_pending = SDL_FALSE;
}
}

SDL_bool
SDL_HardwareKeyboardKeyPressed(void)
{
SDL_Keyboard *keyboard = &SDL_keyboard;
SDL_Scancode scancode;

for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) {
if ((keyboard->keysource[scancode] & KEYBOARD_HARDWARE) != 0) {
return SDL_TRUE;
}
}
return SDL_FALSE;
}

int
SDL_SendKeyboardText(const char *text)
{
Expand Down
7 changes: 7 additions & 0 deletions src/events/SDL_keyboard_c.h
Expand Up @@ -49,6 +49,13 @@ extern void SDL_SetKeyboardFocus(SDL_Window * window);

/* Send a keyboard key event */
extern int SDL_SendKeyboardKey(Uint8 state, SDL_Scancode scancode);
extern int SDL_SendKeyboardKeyAutoRelease(SDL_Scancode scancode);

/* Release all the autorelease keys */
extern void SDL_ReleaseAutoReleaseKeys(void);

/* Return true if any hardware key is pressed */
extern SDL_bool SDL_HardwareKeyboardKeyPressed(void);

/* Send keyboard text input */
extern int SDL_SendKeyboardText(const char *text);
Expand Down
93 changes: 46 additions & 47 deletions src/video/uikit/SDL_uikitview.m
Expand Up @@ -245,61 +245,64 @@ - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
}

#if TARGET_OS_TV || defined(__IPHONE_9_1)
- (SDL_Scancode)scancodeFromPressType:(UIPressType)presstype
- (SDL_Scancode)scancodeFromPress:(UIPress*)press
{
switch (presstype) {
case UIPressTypeUpArrow:
return SDL_SCANCODE_UP;
case UIPressTypeDownArrow:
return SDL_SCANCODE_DOWN;
case UIPressTypeLeftArrow:
return SDL_SCANCODE_LEFT;
case UIPressTypeRightArrow:
return SDL_SCANCODE_RIGHT;
case UIPressTypeSelect:
/* HIG says: "primary button behavior" */
return SDL_SCANCODE_RETURN;
case UIPressTypeMenu:
/* HIG says: "returns to previous screen" */
return SDL_SCANCODE_ESCAPE;
case UIPressTypePlayPause:
/* HIG says: "secondary button behavior" */
return SDL_SCANCODE_PAUSE;
default:
return SDL_SCANCODE_UNKNOWN;
if (press.key != nil) {
return (SDL_Scancode)press.key.keyCode;
}

/* Presses from Apple TV remote */
if (!SDL_AppleTVRemoteOpenedAsJoystick) {
switch (press.type) {
case UIPressTypeUpArrow:
return SDL_SCANCODE_UP;
case UIPressTypeDownArrow:
return SDL_SCANCODE_DOWN;
case UIPressTypeLeftArrow:
return SDL_SCANCODE_LEFT;
case UIPressTypeRightArrow:
return SDL_SCANCODE_RIGHT;
case UIPressTypeSelect:
/* HIG says: "primary button behavior" */
return SDL_SCANCODE_RETURN;
case UIPressTypeMenu:
/* HIG says: "returns to previous screen" */
return SDL_SCANCODE_ESCAPE;
case UIPressTypePlayPause:
/* HIG says: "secondary button behavior" */
return SDL_SCANCODE_PAUSE;
default:
break;
}
}

return SDL_SCANCODE_UNKNOWN;
}

- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (!SDL_AppleTVRemoteOpenedAsJoystick) {
for (UIPress *press in presses) {
SDL_Scancode scancode = [self scancodeFromPressType:press.type];
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
}
}
for (UIPress *press in presses) {
SDL_Scancode scancode = [self scancodeFromPress:press];
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
}
[super pressesBegan:presses withEvent:event];
}

- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (!SDL_AppleTVRemoteOpenedAsJoystick) {
for (UIPress *press in presses) {
SDL_Scancode scancode = [self scancodeFromPressType:press.type];
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
}
for (UIPress *press in presses) {
SDL_Scancode scancode = [self scancodeFromPress:press];
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
[super pressesEnded:presses withEvent:event];
}

- (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (!SDL_AppleTVRemoteOpenedAsJoystick) {
for (UIPress *press in presses) {
SDL_Scancode scancode = [self scancodeFromPressType:press.type];
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
}
for (UIPress *press in presses) {
SDL_Scancode scancode = [self scancodeFromPress:press];
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
[super pressesCancelled:presses withEvent:event];
}

Expand All @@ -320,20 +323,16 @@ -(void)swipeGesture:(UISwipeGestureRecognizer *)gesture
* which better maps to swipe gestures. */
switch (gesture.direction) {
case UISwipeGestureRecognizerDirectionUp:
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_UP);
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_UP);
SDL_SendKeyboardKeyAutoRelease(SDL_SCANCODE_UP);
break;
case UISwipeGestureRecognizerDirectionDown:
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_DOWN);
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_DOWN);
SDL_SendKeyboardKeyAutoRelease(SDL_SCANCODE_DOWN);
break;
case UISwipeGestureRecognizerDirectionLeft:
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_LEFT);
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LEFT);
SDL_SendKeyboardKeyAutoRelease(SDL_SCANCODE_LEFT);
break;
case UISwipeGestureRecognizerDirectionRight:
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_RIGHT);
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RIGHT);
SDL_SendKeyboardKeyAutoRelease(SDL_SCANCODE_RIGHT);
break;
}
}
Expand Down

0 comments on commit d4f1b52

Please sign in to comment.