sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

SDL_uikitevents.m (11355B)


      1 /*
      2   Simple DirectMedia Layer
      3   Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
      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 #if SDL_VIDEO_DRIVER_UIKIT
     24 
     25 #include "../../events/SDL_events_c.h"
     26 
     27 #include "SDL_uikitvideo.h"
     28 #include "SDL_uikitevents.h"
     29 #include "SDL_uikitopengles.h"
     30 
     31 #import <Foundation/Foundation.h>
     32 
     33 #if (__IPHONE_OS_VERSION_MAX_ALLOWED >= 140000) || (__APPLETV_OS_VERSION_MAX_ALLOWED >= 140000) || (__MAC_OS_VERSION_MAX_ALLOWED > 1500000)
     34 #import <GameController/GameController.h>
     35 
     36 #define ENABLE_GCKEYBOARD
     37 #define ENABLE_GCMOUSE
     38 #endif
     39 
     40 static BOOL UIKit_EventPumpEnabled = YES;
     41 
     42 void
     43 SDL_iPhoneSetEventPump(SDL_bool enabled)
     44 {
     45     UIKit_EventPumpEnabled = enabled;
     46 }
     47 
     48 void
     49 UIKit_PumpEvents(_THIS)
     50 {
     51     if (!UIKit_EventPumpEnabled) {
     52         return;
     53     }
     54 
     55     /* Let the run loop run for a short amount of time: long enough for
     56        touch events to get processed (which is important to get certain
     57        elements of Game Center's GKLeaderboardViewController to respond
     58        to touch input), but not long enough to introduce a significant
     59        delay in the rest of the app.
     60     */
     61     const CFTimeInterval seconds = 0.000002;
     62 
     63     /* Pump most event types. */
     64     SInt32 result;
     65     do {
     66         result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, seconds, TRUE);
     67     } while (result == kCFRunLoopRunHandledSource);
     68 
     69     /* Make sure UIScrollView objects scroll properly. */
     70     do {
     71         result = CFRunLoopRunInMode((CFStringRef)UITrackingRunLoopMode, seconds, TRUE);
     72     } while(result == kCFRunLoopRunHandledSource);
     73 
     74     /* See the comment in the function definition. */
     75 #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
     76     UIKit_GL_RestoreCurrentContext();
     77 #endif
     78 }
     79 
     80 #ifdef ENABLE_GCKEYBOARD
     81 
     82 static SDL_bool keyboard_connected = SDL_FALSE;
     83 static id keyboard_connect_observer = nil;
     84 static id keyboard_disconnect_observer = nil;
     85 
     86 static void OnGCKeyboardConnected(GCKeyboard *keyboard) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
     87 {
     88     keyboard_connected = SDL_TRUE;
     89     keyboard.keyboardInput.keyChangedHandler = ^(GCKeyboardInput *keyboard, GCControllerButtonInput *key, GCKeyCode keyCode, BOOL pressed)
     90     {
     91         SDL_SendKeyboardKey(pressed ? SDL_PRESSED : SDL_RELEASED, (SDL_Scancode)keyCode);
     92     };
     93 
     94 	dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.keyboard", DISPATCH_QUEUE_SERIAL );
     95 	dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
     96 	keyboard.handlerQueue = queue;
     97 }
     98 
     99 static void OnGCKeyboardDisconnected(GCKeyboard *keyboard) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
    100 {
    101     keyboard.keyboardInput.keyChangedHandler = nil;
    102     keyboard_connected = SDL_FALSE;
    103 }
    104 
    105 void SDL_InitGCKeyboard(void)
    106 {
    107     @autoreleasepool {
    108         if (@available(iOS 14.0, tvOS 14.0, *)) {
    109             NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    110 
    111             keyboard_connect_observer = [center addObserverForName:GCKeyboardDidConnectNotification
    112                                                             object:nil
    113                                                              queue:nil
    114                                                         usingBlock:^(NSNotification *note) {
    115                                                             GCKeyboard *keyboard = note.object;
    116                                                             OnGCKeyboardConnected(keyboard);
    117                                                         }];
    118 
    119             keyboard_disconnect_observer = [center addObserverForName:GCKeyboardDidDisconnectNotification
    120                                                                object:nil
    121                                                                 queue:nil
    122                                                            usingBlock:^(NSNotification *note) {
    123                                                                 GCKeyboard *keyboard = note.object;
    124                                                                 OnGCKeyboardDisconnected(keyboard);
    125                                                            }];
    126 
    127             if (GCKeyboard.coalescedKeyboard != nil) {
    128                 OnGCKeyboardConnected(GCKeyboard.coalescedKeyboard);
    129             }
    130         }
    131     }
    132 }
    133 
    134 SDL_bool SDL_HasGCKeyboard(void)
    135 {
    136     return keyboard_connected;
    137 }
    138 
    139 void SDL_QuitGCKeyboard(void)
    140 {
    141     @autoreleasepool {
    142         if (@available(iOS 14.0, tvOS 14.0, *)) {
    143             NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    144 
    145             if (keyboard_connect_observer) {
    146                 [center removeObserver:keyboard_connect_observer name:GCKeyboardDidConnectNotification object:nil];
    147                 keyboard_connect_observer = nil;
    148             }
    149 
    150             if (keyboard_disconnect_observer) {
    151                 [center removeObserver:keyboard_disconnect_observer name:GCKeyboardDidDisconnectNotification object:nil];
    152                 keyboard_disconnect_observer = nil;
    153             }
    154 
    155             if (GCKeyboard.coalescedKeyboard != nil) {
    156                 OnGCKeyboardDisconnected(GCKeyboard.coalescedKeyboard);
    157             }
    158         }
    159     }
    160 }
    161 
    162 #else
    163 
    164 void SDL_InitGCKeyboard(void)
    165 {
    166 }
    167 
    168 SDL_bool SDL_HasGCKeyboard(void)
    169 {
    170     return SDL_FALSE;
    171 }
    172 
    173 void SDL_QuitGCKeyboard(void)
    174 {
    175 }
    176 
    177 #endif /* ENABLE_GCKEYBOARD */
    178 
    179 
    180 #ifdef ENABLE_GCMOUSE
    181 
    182 static int mice_connected = 0;
    183 static id mouse_connect_observer = nil;
    184 static id mouse_disconnect_observer = nil;
    185 
    186 static int SetGCMouseRelativeMode(SDL_bool enabled)
    187 {
    188     /* We'll always send relative motion and we can't warp, so nothing to do here */
    189     return 0;
    190 }
    191 
    192 static void OnGCMouseButtonChanged(SDL_MouseID mouseID, Uint8 button, BOOL pressed)
    193 {
    194     SDL_SendMouseButton(SDL_GetMouseFocus(), mouseID, pressed ? SDL_PRESSED : SDL_RELEASED, button);
    195 }
    196 
    197 static void OnGCMouseConnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
    198 {
    199     SDL_MouseID mouseID = mice_connected;
    200 
    201     mouse.mouseInput.leftButton.pressedChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed)
    202     {
    203         OnGCMouseButtonChanged(mouseID, SDL_BUTTON_LEFT, pressed);
    204     };
    205     mouse.mouseInput.middleButton.pressedChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed)
    206     {
    207         OnGCMouseButtonChanged(mouseID, SDL_BUTTON_MIDDLE, pressed);
    208     };
    209     mouse.mouseInput.rightButton.pressedChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed)
    210     {
    211         OnGCMouseButtonChanged(mouseID, SDL_BUTTON_RIGHT, pressed);
    212     };
    213 
    214     int auxiliary_button = SDL_BUTTON_X1;
    215     for (GCControllerButtonInput *button in mouse.mouseInput.auxiliaryButtons) {
    216         button.pressedChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed)
    217         {
    218             OnGCMouseButtonChanged(mouseID, auxiliary_button, pressed);
    219         };
    220         ++auxiliary_button;
    221     }
    222 
    223     mouse.mouseInput.mouseMovedHandler = ^(GCMouseInput *mouse, float deltaX, float deltaY)
    224     {
    225 		SDL_SendMouseMotion(SDL_GetMouseFocus(), mouseID, SDL_TRUE, (int)deltaX, -(int)deltaY);
    226     };
    227 
    228 	dispatch_queue_t queue = dispatch_queue_create( "org.libsdl.input.mouse", DISPATCH_QUEUE_SERIAL );
    229 	dispatch_set_target_queue( queue, dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_HIGH, 0 ) );
    230 	mouse.handlerQueue = queue;
    231 
    232     ++mice_connected;
    233 }
    234 
    235 static void OnGCMouseDisconnected(GCMouse *mouse) API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0))
    236 {
    237     --mice_connected;
    238 
    239     mouse.mouseInput.mouseMovedHandler = nil;
    240 
    241     mouse.mouseInput.leftButton.pressedChangedHandler = nil;
    242     mouse.mouseInput.middleButton.pressedChangedHandler = nil;
    243     mouse.mouseInput.rightButton.pressedChangedHandler = nil;
    244 
    245     for (GCControllerButtonInput *button in mouse.mouseInput.auxiliaryButtons) {
    246         button.pressedChangedHandler = nil;
    247     }
    248 }
    249 
    250 void SDL_InitGCMouse(void)
    251 {
    252 	@autoreleasepool {
    253 		/* There is a bug where mouse accumulates duplicate deltas over time in iOS 14.0 */
    254         if (@available(iOS 14.1, tvOS 14.1, *)) {
    255             NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    256 
    257             mouse_connect_observer = [center addObserverForName:GCMouseDidConnectNotification
    258                                                          object:nil
    259                                                           queue:nil
    260                                                      usingBlock:^(NSNotification *note) {
    261                                                          GCMouse *mouse = note.object;
    262                                                          OnGCMouseConnected(mouse);
    263                                                      }];
    264 
    265             mouse_disconnect_observer = [center addObserverForName:GCMouseDidDisconnectNotification
    266                                                             object:nil
    267                                                              queue:nil
    268                                                         usingBlock:^(NSNotification *note) {
    269                                                             GCMouse *mouse = note.object;
    270                                                             OnGCMouseDisconnected(mouse);
    271                                                        }];
    272 
    273             for (GCMouse *mouse in [GCMouse mice]) {
    274                 OnGCMouseConnected(mouse);
    275             }
    276 
    277             SDL_GetMouse()->SetRelativeMouseMode = SetGCMouseRelativeMode;
    278         }
    279     }
    280 }
    281 
    282 SDL_bool SDL_HasGCMouse(void)
    283 {
    284     return (mice_connected > 0);
    285 }
    286 
    287 void SDL_QuitGCMouse(void)
    288 {
    289     @autoreleasepool {
    290         if (@available(iOS 14.1, tvOS 14.1, *)) {
    291             NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    292 
    293             if (mouse_connect_observer) {
    294                 [center removeObserver:mouse_connect_observer name:GCMouseDidConnectNotification object:nil];
    295                 mouse_connect_observer = nil;
    296             }
    297 
    298             if (mouse_disconnect_observer) {
    299                 [center removeObserver:mouse_disconnect_observer name:GCMouseDidDisconnectNotification object:nil];
    300                 mouse_disconnect_observer = nil;
    301             }
    302 
    303             for (GCMouse *mouse in [GCMouse mice]) {
    304                 OnGCMouseDisconnected(mouse);
    305             }
    306 
    307             SDL_GetMouse()->SetRelativeMouseMode = NULL;
    308         }
    309     }
    310 }
    311 
    312 #else
    313 
    314 void SDL_InitGCMouse(void)
    315 {
    316 }
    317 
    318 SDL_bool SDL_HasGCMouse(void)
    319 {
    320     return SDL_FALSE;
    321 }
    322 
    323 void SDL_QuitGCMouse(void)
    324 {
    325 }
    326 
    327 #endif /* ENABLE_GCMOUSE */
    328 
    329 #endif /* SDL_VIDEO_DRIVER_UIKIT */
    330 
    331 /* vi: set ts=4 sw=4 expandtab: */