Mac and Linux SDL2 binary snapshots
Edward Rudd
2021-06-15 dec7875a6e23212021e4d9080330a42832dfe02a
source/src/video/uikit/SDL_uikitview.m
@@ -29,12 +29,18 @@
#include "../../events/SDL_touch_c.h"
#include "../../events/SDL_events_c.h"
#import "SDL_uikitappdelegate.h"
#import "SDL_uikitmodes.h"
#import "SDL_uikitwindow.h"
#include "SDL_uikitappdelegate.h"
#include "SDL_uikitevents.h"
#include "SDL_uikitmodes.h"
#include "SDL_uikitwindow.h"
/* The maximum number of mouse buttons we support */
#define MAX_MOUSE_BUTTONS    5
/* This is defined in SDL_sysjoystick.m */
#if !SDL_JOYSTICK_DISABLED
extern int SDL_AppleTVRemoteOpenedAsJoystick;
#endif
@implementation SDL_uikitview {
    SDL_Window *sdlwindow;
@@ -63,6 +69,16 @@
        UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)];
        swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
        [self addGestureRecognizer:swipeRight];
#elif defined(__IPHONE_13_4)
        if (@available(iOS 13.4, *)) {
            UIPanGestureRecognizer *mouseWheelRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(mouseWheelGesture:)];
            mouseWheelRecognizer.allowedScrollTypesMask = UIScrollTypeMaskDiscrete;
            mouseWheelRecognizer.allowedTouchTypes = @[ @(UITouchTypeIndirectPointer) ];
            mouseWheelRecognizer.cancelsTouchesInView = NO;
            mouseWheelRecognizer.delaysTouchesBegan = NO;
            mouseWheelRecognizer.delaysTouchesEnded = NO;
            [self addGestureRecognizer:mouseWheelRecognizer];
        }
#endif
        self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
@@ -74,6 +90,12 @@
#if !TARGET_OS_TV
        self.multipleTouchEnabled = YES;
        SDL_AddTouch(directTouchId, SDL_TOUCH_DEVICE_DIRECT, "");
#endif
#if !TARGET_OS_TV && defined(__IPHONE_13_4)
        if (@available(iOS 13.4, *)) {
            [self addInteraction:[[UIPointerInteraction alloc] initWithDelegate:self]];
        }
#endif
    }
@@ -136,6 +158,29 @@
    sdlwindow = window;
}
#if !TARGET_OS_TV && defined(__IPHONE_13_4)
- (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)){
    if (request != nil && !SDL_HasGCMouse()) {
        CGPoint origin = self.bounds.origin;
        CGPoint point = request.location;
        point.x -= origin.x;
        point.y -= origin.y;
        SDL_SendMouseMotion(sdlwindow, 0, 0, (int)point.x, (int)point.y);
    }
    return [UIPointerRegion regionWithRect:self.bounds identifier:nil];
}
- (UIPointerStyle *)pointerInteraction:(UIPointerInteraction *)interaction styleForRegion:(UIPointerRegion *)region  API_AVAILABLE(ios(13.4)){
    if (SDL_ShowCursor(-1)) {
        return nil;
    } else {
        return [UIPointerStyle hiddenPointerStyle];
    }
}
#endif /* !TARGET_OS_TV && __IPHONE_13_4 */
- (SDL_TouchDeviceType)touchTypeForTouch:(UITouch *)touch
{
#ifdef __IPHONE_9_0
@@ -187,38 +232,110 @@
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches) {
        SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
        SDL_TouchID touchId = [self touchIdForType:touchType];
        float pressure = [self pressureForTouch:touch];
        BOOL handled = NO;
        if (SDL_AddTouch(touchId, touchType, "") < 0) {
            continue;
#if !TARGET_OS_TV && defined(__IPHONE_13_4)
        if (@available(iOS 13.4, *)) {
            if (touch.type == UITouchTypeIndirectPointer) {
                if (!SDL_HasGCMouse()) {
                    int i;
                    for (i = 1; i <= MAX_MOUSE_BUTTONS; ++i) {
                        if ((event.buttonMask & SDL_BUTTON(i)) != 0) {
                            Uint8 button;
                            switch (i) {
                            case 1:
                                button = SDL_BUTTON_LEFT;
                                break;
                            case 2:
                                button = SDL_BUTTON_RIGHT;
                                break;
                            case 3:
                                button = SDL_BUTTON_MIDDLE;
                                break;
                            default:
                                button = (Uint8)i;
                                break;
                            }
                            SDL_SendMouseButton(sdlwindow, 0, SDL_PRESSED, button);
                        }
                    }
                }
                handled = YES;
            }
        }
#endif
        if (!handled) {
            SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
            SDL_TouchID touchId = [self touchIdForType:touchType];
            float pressure = [self pressureForTouch:touch];
        /* FIXME, need to send: int clicks = (int) touch.tapCount; ? */
            if (SDL_AddTouch(touchId, touchType, "") < 0) {
                continue;
            }
        CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
        SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                      SDL_TRUE, locationInView.x, locationInView.y, pressure);
            /* FIXME, need to send: int clicks = (int) touch.tapCount; ? */
            CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
            SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                          SDL_TRUE, locationInView.x, locationInView.y, pressure);
        }
    }
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches) {
        SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
        SDL_TouchID touchId = [self touchIdForType:touchType];
        float pressure = [self pressureForTouch:touch];
        BOOL handled = NO;
        if (SDL_AddTouch(touchId, touchType, "") < 0) {
            continue;
#if !TARGET_OS_TV && defined(__IPHONE_13_4)
        if (@available(iOS 13.4, *)) {
            if (touch.type == UITouchTypeIndirectPointer) {
                if (!SDL_HasGCMouse()) {
                    int i;
                    for (i = 1; i <= MAX_MOUSE_BUTTONS; ++i) {
                        if ((event.buttonMask & SDL_BUTTON(i)) != 0) {
                            Uint8 button;
                            switch (i) {
                            case 1:
                                button = SDL_BUTTON_LEFT;
                                break;
                            case 2:
                                button = SDL_BUTTON_RIGHT;
                                break;
                            case 3:
                                button = SDL_BUTTON_MIDDLE;
                                break;
                            default:
                                button = (Uint8)i;
                                break;
                            }
                            SDL_SendMouseButton(sdlwindow, 0, SDL_RELEASED, button);
                        }
                    }
                }
                handled = YES;
            }
        }
#endif
        if (!handled) {
            SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
            SDL_TouchID touchId = [self touchIdForType:touchType];
            float pressure = [self pressureForTouch:touch];
        /* FIXME, need to send: int clicks = (int) touch.tapCount; ? */
            if (SDL_AddTouch(touchId, touchType, "") < 0) {
                continue;
            }
        CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
        SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                      SDL_FALSE, locationInView.x, locationInView.y, pressure);
            /* FIXME, need to send: int clicks = (int) touch.tapCount; ? */
            CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
            SDL_SendTouch(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                          SDL_FALSE, locationInView.x, locationInView.y, pressure);
        }
    }
}
@@ -230,51 +347,78 @@
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    for (UITouch *touch in touches) {
        SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
        SDL_TouchID touchId = [self touchIdForType:touchType];
        float pressure = [self pressureForTouch:touch];
        BOOL handled = NO;
        if (SDL_AddTouch(touchId, touchType, "") < 0) {
            continue;
#if !TARGET_OS_TV && defined(__IPHONE_13_4)
        if (@available(iOS 13.4, *)) {
            if (touch.type == UITouchTypeIndirectPointer) {
                /* Already handled in pointerInteraction callback */
                handled = YES;
            }
        }
#endif
        if (!handled) {
            SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch];
            SDL_TouchID touchId = [self touchIdForType:touchType];
            float pressure = [self pressureForTouch:touch];
        CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
        SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                            locationInView.x, locationInView.y, pressure);
            if (SDL_AddTouch(touchId, touchType, "") < 0) {
                continue;
            }
            CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES];
            SDL_SendTouchMotion(touchId, (SDL_FingerID)((size_t)touch), sdlwindow,
                                locationInView.x, locationInView.y, pressure);
        }
    }
}
#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;
#ifdef __IPHONE_13_4
    if ([press respondsToSelector:@selector((key))]) {
        if (press.key != nil) {
            return (SDL_Scancode)press.key.keyCode;
        }
    }
#endif
#if !SDL_JOYSTICK_DISABLED
    /* 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;
        }
    }
#endif /* !SDL_JOYSTICK_DISABLED */
    return SDL_SCANCODE_UNKNOWN;
}
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
    if (!SDL_AppleTVRemoteOpenedAsJoystick) {
    if (!SDL_HasGCKeyboard()) {
        for (UIPress *press in presses) {
            SDL_Scancode scancode = [self scancodeFromPressType:press.type];
            SDL_Scancode scancode = [self scancodeFromPress:press];
            SDL_SendKeyboardKey(SDL_PRESSED, scancode);
        }
    }
@@ -283,9 +427,9 @@
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
    if (!SDL_AppleTVRemoteOpenedAsJoystick) {
    if (!SDL_HasGCKeyboard()) {
        for (UIPress *press in presses) {
            SDL_Scancode scancode = [self scancodeFromPressType:press.type];
            SDL_Scancode scancode = [self scancodeFromPress:press];
            SDL_SendKeyboardKey(SDL_RELEASED, scancode);
        }
    }
@@ -294,9 +438,9 @@
- (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
    if (!SDL_AppleTVRemoteOpenedAsJoystick) {
    if (!SDL_HasGCKeyboard()) {
        for (UIPress *press in presses) {
            SDL_Scancode scancode = [self scancodeFromPressType:press.type];
            SDL_Scancode scancode = [self scancodeFromPress:press];
            SDL_SendKeyboardKey(SDL_RELEASED, scancode);
        }
    }
@@ -308,35 +452,57 @@
    /* This is only called when the force of a press changes. */
    [super pressesChanged:presses withEvent:event];
}
#endif /* TARGET_OS_TV || defined(__IPHONE_9_1) */
-(void)mouseWheelGesture:(UIPanGestureRecognizer *)gesture
{
    if (gesture.state == UIGestureRecognizerStateBegan ||
        gesture.state == UIGestureRecognizerStateChanged ||
        gesture.state == UIGestureRecognizerStateEnded) {
        CGPoint velocity = [gesture velocityInView:self];
        if (velocity.x > 0.0f) {
            velocity.x = -1.0;
        } else if (velocity.x < 0.0f) {
            velocity.x = 1.0f;
        }
        if (velocity.y > 0.0f) {
            velocity.y = -1.0;
        } else if (velocity.y < 0.0f) {
            velocity.y = 1.0f;
        }
        if (velocity.x != 0.0f || velocity.y != 0.0f) {
            SDL_SendMouseWheel(sdlwindow, 0, velocity.x, velocity.y, SDL_MOUSEWHEEL_NORMAL);
        }
    }
}
#if TARGET_OS_TV
-(void)swipeGesture:(UISwipeGestureRecognizer *)gesture
{
    /* Swipe gestures don't trigger begin states. */
    if (gesture.state == UIGestureRecognizerStateEnded) {
#if !SDL_JOYSTICK_DISABLED
        if (!SDL_AppleTVRemoteOpenedAsJoystick) {
            /* Send arrow key presses for now, as we don't have an external API
             * 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;
            }
        }
#endif /* !SDL_JOYSTICK_DISABLED */
    }
}
#endif /* TARGET_OS_TV */