Atlas - SDL_uikitview.m

Home / ext / SDL / src / video / uikit Lines: 1 | Size: 21411 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2025 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "SDL_internal.h" 22 23#ifdef SDL_VIDEO_DRIVER_UIKIT 24 25#include "SDL_uikitview.h" 26 27#include "../../events/SDL_mouse_c.h" 28#include "../../events/SDL_touch_c.h" 29#include "../../events/SDL_events_c.h" 30#include "../../joystick/SDL_joystick_c.h" 31 32#include "SDL_uikitappdelegate.h" 33#include "SDL_uikitevents.h" 34#include "SDL_uikitmodes.h" 35#include "SDL_uikitpen.h" 36#include "SDL_uikitwindow.h" 37 38// The maximum number of mouse buttons we support 39#define MAX_MOUSE_BUTTONS 5 40 41// This is defined in SDL_sysjoystick.m 42extern int SDL_AppleTVRemoteOpenedAsJoystick; 43 44@implementation SDL_uikitview 45{ 46 SDL_Window *sdlwindow; 47 48 SDL_TouchID directTouchId; 49 SDL_TouchID indirectTouchId; 50 float pinch_scale; 51 52#if !defined(SDL_PLATFORM_TVOS) 53 UIPointerInteraction *indirectPointerInteraction API_AVAILABLE(ios(13.4)); 54#endif 55} 56 57- (instancetype)initWithFrame:(CGRect)frame 58{ 59 if ((self = [super initWithFrame:frame])) { 60#ifdef SDL_PLATFORM_TVOS 61 // Apple TV Remote touchpad swipe gestures. 62 UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; 63 swipeUp.direction = UISwipeGestureRecognizerDirectionUp; 64 [self addGestureRecognizer:swipeUp]; 65 66 UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; 67 swipeDown.direction = UISwipeGestureRecognizerDirectionDown; 68 [self addGestureRecognizer:swipeDown]; 69 70 UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; 71 swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft; 72 [self addGestureRecognizer:swipeLeft]; 73 74 UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; 75 swipeRight.direction = UISwipeGestureRecognizerDirectionRight; 76 [self addGestureRecognizer:swipeRight]; 77#endif 78 79#if !defined(SDL_PLATFORM_TVOS) 80 /* Pinch gestures */ 81 UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(sdlPinchGesture:)]; 82 pinchGesture.cancelsTouchesInView = NO; 83 pinchGesture.delaysTouchesBegan = NO; 84 pinchGesture.delaysTouchesEnded = NO; 85 [self addGestureRecognizer:pinchGesture]; 86#endif 87 88 self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 89 self.autoresizesSubviews = YES; 90 91 directTouchId = 1; 92 indirectTouchId = 2; 93 94#ifndef SDL_PLATFORM_TVOS 95 self.multipleTouchEnabled = YES; 96 SDL_AddTouch(directTouchId, SDL_TOUCH_DEVICE_DIRECT, ""); 97 98 if (@available(iOS 13.0, *)) { 99 UIHoverGestureRecognizer *pencilRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(pencilHovering:)]; 100 pencilRecognizer.allowedTouchTypes = @[@(UITouchTypePencil)]; 101 [self addGestureRecognizer:pencilRecognizer]; 102 } 103 104 if (@available(iOS 13.4, *)) { 105 indirectPointerInteraction = [[UIPointerInteraction alloc] initWithDelegate:self]; 106 [self addInteraction:indirectPointerInteraction]; 107 108 UIHoverGestureRecognizer *indirectPointerRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(indirectPointerHovering:)]; 109 indirectPointerRecognizer.allowedTouchTypes = @[@(UITouchTypeIndirectPointer)]; 110 [self addGestureRecognizer:indirectPointerRecognizer]; 111 } 112#endif // !defined(SDL_PLATFORM_TVOS) 113 } 114 115 return self; 116} 117 118- (void)setSDLWindow:(SDL_Window *)window 119{ 120 SDL_UIKitWindowData *data = nil; 121 122 if (window == sdlwindow) { 123 return; 124 } 125 126 // Remove ourself from the old window. 127 if (sdlwindow) { 128 SDL_uikitview *view = nil; 129 data = (__bridge SDL_UIKitWindowData *)sdlwindow->internal; 130 131 [data.views removeObject:self]; 132 133 [self removeFromSuperview]; 134 135 // Restore the next-oldest view in the old window. 136 view = data.views.lastObject; 137 138 data.viewcontroller.view = view; 139 140 data.uiwindow.rootViewController = nil; 141 data.uiwindow.rootViewController = data.viewcontroller; 142 143 [data.uiwindow layoutIfNeeded]; 144 } 145 146 sdlwindow = window; 147 148 // Add ourself to the new window. 149 if (window) { 150 data = (__bridge SDL_UIKitWindowData *)window->internal; 151 152 // Make sure the SDL window has a strong reference to this view. 153 [data.views addObject:self]; 154 155 // Replace the view controller's old view with this one. 156 [data.viewcontroller.view removeFromSuperview]; 157 data.viewcontroller.view = self; 158 159 /* The root view controller handles rotation and the status bar. 160 * Assigning it also adds the controller's view to the window. We 161 * explicitly re-set it to make sure the view is properly attached to 162 * the window. Just adding the sub-view if the root view controller is 163 * already correct causes orientation issues on iOS 7 and below. */ 164 data.uiwindow.rootViewController = nil; 165 data.uiwindow.rootViewController = data.viewcontroller; 166 167 /* The view's bounds may not be correct until the next event cycle. That 168 * might happen after the current dimensions are queried, so we force a 169 * layout now to immediately update the bounds. */ 170 [data.uiwindow layoutIfNeeded]; 171 } 172} 173 174- (SDL_Window *)getSDLWindow 175{ 176 return sdlwindow; 177} 178 179#if !defined(SDL_PLATFORM_TVOS) 180 181- (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction regionForRequest:(UIPointerRegionRequest *)request defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)) 182{ 183 return [UIPointerRegion regionWithRect:self.bounds identifier:nil]; 184} 185 186- (UIPointerStyle *)pointerInteraction:(UIPointerInteraction *)interaction styleForRegion:(UIPointerRegion *)region API_AVAILABLE(ios(13.4)) 187{ 188 if (SDL_CursorVisible()) { 189 return nil; 190 } else { 191 return [UIPointerStyle hiddenPointerStyle]; 192 } 193} 194 195- (void)indirectPointerHovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.4)) 196{ 197 switch (recognizer.state) { 198 case UIGestureRecognizerStateBegan: 199 case UIGestureRecognizerStateChanged: 200 { 201 CGPoint point = [recognizer locationInView:self]; 202 SDL_SendMouseMotion(0, sdlwindow, SDL_GLOBAL_MOUSE_ID, false, point.x, point.y); 203 break; 204 } 205 206 default: 207 break; 208 } 209} 210 211- (void)indirectPointerMoving:(UITouch *)touch API_AVAILABLE(ios(13.4)) 212{ 213 CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; 214 SDL_SendMouseMotion(0, sdlwindow, SDL_GLOBAL_MOUSE_ID, false, locationInView.x, locationInView.y); 215} 216 217- (void)indirectPointerPressed:(UITouch *)touch fromEvent:(UIEvent *)event API_AVAILABLE(ios(13.4)) 218{ 219 if (!SDL_HasMouse()) { 220 int i; 221 222 for (i = 1; i <= MAX_MOUSE_BUTTONS; ++i) { 223 if (event.buttonMask & SDL_BUTTON_MASK(i)) { 224 Uint8 button; 225 226 switch (i) { 227 case 1: 228 button = SDL_BUTTON_LEFT; 229 break; 230 case 2: 231 button = SDL_BUTTON_RIGHT; 232 break; 233 case 3: 234 button = SDL_BUTTON_MIDDLE; 235 break; 236 default: 237 button = (Uint8)i; 238 break; 239 } 240 SDL_SendMouseButton(UIKit_GetEventTimestamp([touch timestamp]), sdlwindow, SDL_GLOBAL_MOUSE_ID, button, true); 241 } 242 } 243 } 244} 245 246- (void)indirectPointerReleased:(UITouch *)touch fromEvent:(UIEvent *)event API_AVAILABLE(ios(13.4)) 247{ 248 if (!SDL_HasMouse()) { 249 int i; 250 SDL_MouseButtonFlags buttons = SDL_GetMouseState(NULL, NULL); 251 252 for (i = 1; i <= MAX_MOUSE_BUTTONS; ++i) { 253 if (buttons & SDL_BUTTON_MASK(i)) { 254 SDL_SendMouseButton(UIKit_GetEventTimestamp([touch timestamp]), sdlwindow, SDL_GLOBAL_MOUSE_ID, (Uint8)i, false); 255 } 256 } 257 } 258} 259 260- (void)pencilHovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0)) 261{ 262 switch (recognizer.state) { 263 case UIGestureRecognizerStateBegan: 264 case UIGestureRecognizerStateChanged: 265 UIKit_HandlePenHover(self, recognizer); 266 break; 267 268 case UIGestureRecognizerStateEnded: 269 case UIGestureRecognizerStateCancelled: 270 // we track touches elsewhere, so if a hover "ends" we'll deal with that there. 271 break; 272 273 default: 274 break; 275 } 276} 277 278- (void)pencilMoving:(UITouch *)touch 279{ 280 UIKit_HandlePenMotion(self, touch); 281} 282 283- (void)pencilPressed:(UITouch *)touch 284{ 285 UIKit_HandlePenPress(self, touch); 286} 287 288- (void)pencilReleased:(UITouch *)touch 289{ 290 UIKit_HandlePenRelease(self, touch); 291} 292 293#endif // !defined(SDL_PLATFORM_TVOS) 294 295- (SDL_TouchDeviceType)touchTypeForTouch:(UITouch *)touch 296{ 297 if (touch.type == UITouchTypeIndirect) { 298 return SDL_TOUCH_DEVICE_INDIRECT_RELATIVE; 299 } 300 return SDL_TOUCH_DEVICE_DIRECT; 301} 302 303- (SDL_TouchID)touchIdForType:(SDL_TouchDeviceType)type 304{ 305 switch (type) { 306 case SDL_TOUCH_DEVICE_DIRECT: 307 default: 308 return directTouchId; 309 case SDL_TOUCH_DEVICE_INDIRECT_RELATIVE: 310 return indirectTouchId; 311 } 312} 313 314- (CGPoint)touchLocation:(UITouch *)touch shouldNormalize:(BOOL)normalize 315{ 316 CGPoint point = [touch locationInView:self]; 317 318 if (normalize) { 319 CGRect bounds = self.bounds; 320 point.x /= bounds.size.width; 321 point.y /= bounds.size.height; 322 } 323 324 return point; 325} 326 327- (float)pressureForTouch:(UITouch *)touch 328{ 329 return (float)touch.force; 330} 331 332- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 333{ 334 for (UITouch *touch in touches) { 335#if !defined(SDL_PLATFORM_TVOS) 336 if (@available(iOS 13.0, *)) { 337 if (touch.type == UITouchTypePencil) { 338 [self pencilPressed:touch]; 339 continue; 340 } 341 } 342 343 if (@available(iOS 13.4, *)) { 344 if (touch.type == UITouchTypeIndirectPointer) { 345 [self indirectPointerPressed:touch fromEvent:event]; 346 continue; 347 } 348 } 349#endif // !defined(SDL_PLATFORM_TVOS) 350 351 SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch]; 352 SDL_TouchID touchId = [self touchIdForType:touchType]; 353 float pressure = [self pressureForTouch:touch]; 354 355 if (SDL_AddTouch(touchId, touchType, "") < 0) { 356 continue; 357 } 358 359 // FIXME, need to send: int clicks = (int) touch.tapCount; ? 360 361 CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; 362 SDL_SendTouch(UIKit_GetEventTimestamp([event timestamp]), 363 touchId, (SDL_FingerID)(uintptr_t)touch, sdlwindow, 364 SDL_EVENT_FINGER_DOWN, locationInView.x, locationInView.y, pressure); 365 } 366} 367 368- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 369{ 370 for (UITouch *touch in touches) { 371#if !defined(SDL_PLATFORM_TVOS) 372 if (@available(iOS 13.0, *)) { 373 if (touch.type == UITouchTypePencil) { 374 [self pencilReleased:touch]; 375 continue; 376 } 377 } 378 379 if (@available(iOS 13.4, *)) { 380 if (touch.type == UITouchTypeIndirectPointer) { 381 [self indirectPointerReleased:touch fromEvent:event]; 382 continue; 383 } 384 } 385#endif // !defined(SDL_PLATFORM_TVOS) 386 387 SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch]; 388 SDL_TouchID touchId = [self touchIdForType:touchType]; 389 float pressure = [self pressureForTouch:touch]; 390 391 if (SDL_AddTouch(touchId, touchType, "") < 0) { 392 continue; 393 } 394 395 // FIXME, need to send: int clicks = (int) touch.tapCount; ? 396 397 CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; 398 SDL_SendTouch(UIKit_GetEventTimestamp([event timestamp]), 399 touchId, (SDL_FingerID)(uintptr_t)touch, sdlwindow, 400 SDL_EVENT_FINGER_UP, locationInView.x, locationInView.y, pressure); 401 } 402} 403 404- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 405{ 406 for (UITouch *touch in touches) { 407#if !defined(SDL_PLATFORM_TVOS) 408 if (@available(iOS 13.0, *)) { 409 if (touch.type == UITouchTypePencil) { 410 [self pencilReleased:touch]; 411 continue; 412 } 413 } 414 415 if (@available(iOS 13.4, *)) { 416 if (touch.type == UITouchTypeIndirectPointer) { 417 [self indirectPointerReleased:touch fromEvent:event]; 418 continue; 419 } 420 } 421#endif // !defined(SDL_PLATFORM_TVOS) 422 423 SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch]; 424 SDL_TouchID touchId = [self touchIdForType:touchType]; 425 float pressure = [self pressureForTouch:touch]; 426 427 if (SDL_AddTouch(touchId, touchType, "") < 0) { 428 continue; 429 } 430 431 CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; 432 SDL_SendTouch(UIKit_GetEventTimestamp([event timestamp]), 433 touchId, (SDL_FingerID)(uintptr_t)touch, sdlwindow, 434 SDL_EVENT_FINGER_CANCELED, locationInView.x, locationInView.y, pressure); 435 } 436} 437 438- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 439{ 440 for (UITouch *touch in touches) { 441#if !defined(SDL_PLATFORM_TVOS) 442 if (@available(iOS 13.0, *)) { 443 if (touch.type == UITouchTypePencil) { 444 [self pencilMoving:touch]; 445 continue; 446 } 447 } 448 449 if (@available(iOS 13.4, *)) { 450 if (touch.type == UITouchTypeIndirectPointer) { 451 [self indirectPointerMoving:touch]; 452 continue; 453 } 454 } 455#endif // !defined(SDL_PLATFORM_TVOS) 456 457 SDL_TouchDeviceType touchType = [self touchTypeForTouch:touch]; 458 SDL_TouchID touchId = [self touchIdForType:touchType]; 459 float pressure = [self pressureForTouch:touch]; 460 461 if (SDL_AddTouch(touchId, touchType, "") < 0) { 462 continue; 463 } 464 465 CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; 466 SDL_SendTouchMotion(UIKit_GetEventTimestamp([event timestamp]), 467 touchId, (SDL_FingerID)(uintptr_t)touch, sdlwindow, 468 locationInView.x, locationInView.y, pressure); 469 } 470} 471 472- (void)safeAreaInsetsDidChange 473{ 474 // Update the safe area insets 475 SDL_SetWindowSafeAreaInsets(sdlwindow, 476 (int)SDL_ceilf(self.safeAreaInsets.left), 477 (int)SDL_ceilf(self.safeAreaInsets.right), 478 (int)SDL_ceilf(self.safeAreaInsets.top), 479 (int)SDL_ceilf(self.safeAreaInsets.bottom)); 480} 481 482#if !defined(SDL_PLATFORM_TVOS) 483- (IBAction)sdlPinchGesture:(UIPinchGestureRecognizer *)sender 484{ 485 CGFloat scale = sender.scale; 486 UIGestureRecognizerState state = sender.state; 487 488 switch (state) { 489 490 case UIGestureRecognizerStateBegan: 491 pinch_scale = 1.0f; 492 SDL_SendPinch(SDL_EVENT_PINCH_BEGIN, 0, sdlwindow, 0); 493 break; 494 495 case UIGestureRecognizerStateChanged: 496 if (pinch_scale > 0.0f) { 497 SDL_SendPinch(SDL_EVENT_PINCH_UPDATE, 0, sdlwindow, scale / pinch_scale); 498 } 499 pinch_scale = scale; 500 break; 501 502 case UIGestureRecognizerStateFailed: 503 case UIGestureRecognizerStateEnded: 504 case UIGestureRecognizerStateCancelled: 505 SDL_SendPinch(SDL_EVENT_PINCH_END, 0, sdlwindow, 0); 506 break; 507 508 default: 509 break; 510 } 511 512} 513#endif 514 515- (SDL_Scancode)scancodeFromPress:(UIPress *)press 516{ 517 if (press.key != nil) { 518 return (SDL_Scancode)press.key.keyCode; 519 } 520 521 // Presses from Apple TV remote or game controller 522 bool controller_opened = false; 523#ifdef SDL_PLATFORM_TVOS 524 // tvOS doesn't send these for game controllers, but does for the Siri remote 525 controller_opened = (SDL_AppleTVRemoteOpenedAsJoystick > 0); 526#else 527 // iOS doesn't have a Siri remote, but does send these for game controllers as of iOS 26 528 // We don't currently have any way of telling what controller sent this, so assume if any 529 // controllers are opened, that the application is handling the controller as a gamepad 530 controller_opened = SDL_JoysticksOpened(); 531#endif 532 if (!controller_opened) { 533 switch (press.type) { 534 case UIPressTypeUpArrow: 535 return SDL_SCANCODE_UP; 536 case UIPressTypeDownArrow: 537 return SDL_SCANCODE_DOWN; 538 case UIPressTypeLeftArrow: 539 return SDL_SCANCODE_LEFT; 540 case UIPressTypeRightArrow: 541 return SDL_SCANCODE_RIGHT; 542 case UIPressTypeSelect: 543 // HIG says: "primary button behavior" 544 return SDL_SCANCODE_RETURN; 545 case UIPressTypeMenu: 546 // HIG says: "returns to previous screen" 547 return SDL_SCANCODE_ESCAPE; 548 case UIPressTypePlayPause: 549 // HIG says: "secondary button behavior" 550 return SDL_SCANCODE_PAUSE; 551 default: 552 break; 553 } 554 } 555 556 return SDL_SCANCODE_UNKNOWN; 557} 558 559- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event 560{ 561 if (!SDL_HasKeyboard()) { 562 for (UIPress *press in presses) { 563 SDL_Scancode scancode = [self scancodeFromPress:press]; 564 SDL_SendKeyboardKey(UIKit_GetEventTimestamp([event timestamp]), SDL_GLOBAL_KEYBOARD_ID, 0, scancode, true); 565 } 566 } 567 if (SDL_TextInputActive(sdlwindow)) { 568 [super pressesBegan:presses withEvent:event]; 569 } 570} 571 572- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event 573{ 574 if (!SDL_HasKeyboard()) { 575 for (UIPress *press in presses) { 576 SDL_Scancode scancode = [self scancodeFromPress:press]; 577 SDL_SendKeyboardKey(UIKit_GetEventTimestamp([event timestamp]), SDL_GLOBAL_KEYBOARD_ID, 0, scancode, false); 578 } 579 } 580 if (SDL_TextInputActive(sdlwindow)) { 581 [super pressesEnded:presses withEvent:event]; 582 } 583} 584 585- (void)pressesCancelled:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event 586{ 587 if (!SDL_HasKeyboard()) { 588 for (UIPress *press in presses) { 589 SDL_Scancode scancode = [self scancodeFromPress:press]; 590 SDL_SendKeyboardKey(UIKit_GetEventTimestamp([event timestamp]), SDL_GLOBAL_KEYBOARD_ID, 0, scancode, false); 591 } 592 } 593 if (SDL_TextInputActive(sdlwindow)) { 594 [super pressesCancelled:presses withEvent:event]; 595 } 596} 597 598- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event 599{ 600 // This is only called when the force of a press changes. 601 if (SDL_TextInputActive(sdlwindow)) { 602 [super pressesChanged:presses withEvent:event]; 603 } 604} 605 606#ifdef SDL_PLATFORM_TVOS 607- (void)swipeGesture:(UISwipeGestureRecognizer *)gesture 608{ 609 // Swipe gestures don't trigger begin states. 610 if (gesture.state == UIGestureRecognizerStateEnded) { 611 // tvOS doesn't send these for game controllers, but does for the Siri remote 612 bool controller_opened = (SDL_AppleTVRemoteOpenedAsJoystick > 0); 613 if (!controller_opened) { 614 /* Send arrow key presses for now, as we don't have an external API 615 * which better maps to swipe gestures. */ 616 switch (gesture.direction) { 617 case UISwipeGestureRecognizerDirectionUp: 618 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_UP); 619 break; 620 case UISwipeGestureRecognizerDirectionDown: 621 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_DOWN); 622 break; 623 case UISwipeGestureRecognizerDirectionLeft: 624 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_LEFT); 625 break; 626 case UISwipeGestureRecognizerDirectionRight: 627 SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_RIGHT); 628 break; 629 } 630 } 631 } 632} 633#endif // SDL_PLATFORM_TVOS 634 635@end 636 637#endif // SDL_VIDEO_DRIVER_UIKIT 638
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.