sdl

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

SDL_uikitvideo.m (10074B)


      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 #import <UIKit/UIKit.h>
     26 
     27 #include "SDL_video.h"
     28 #include "SDL_mouse.h"
     29 #include "SDL_hints.h"
     30 #include "../SDL_sysvideo.h"
     31 #include "../SDL_pixels_c.h"
     32 #include "../../events/SDL_events_c.h"
     33 
     34 #include "SDL_uikitvideo.h"
     35 #include "SDL_uikitevents.h"
     36 #include "SDL_uikitmodes.h"
     37 #include "SDL_uikitwindow.h"
     38 #include "SDL_uikitopengles.h"
     39 #include "SDL_uikitclipboard.h"
     40 #include "SDL_uikitvulkan.h"
     41 #include "SDL_uikitmetalview.h"
     42 
     43 #define UIKITVID_DRIVER_NAME "uikit"
     44 
     45 @implementation SDL_VideoData
     46 
     47 @end
     48 
     49 /* Initialization/Query functions */
     50 static int UIKit_VideoInit(_THIS);
     51 static void UIKit_VideoQuit(_THIS);
     52 
     53 /* DUMMY driver bootstrap functions */
     54 
     55 static void UIKit_DeleteDevice(SDL_VideoDevice * device)
     56 {
     57     @autoreleasepool {
     58         CFRelease(device->driverdata);
     59         SDL_free(device);
     60     }
     61 }
     62 
     63 static SDL_VideoDevice *
     64 UIKit_CreateDevice(int devindex)
     65 {
     66     @autoreleasepool {
     67         SDL_VideoDevice *device;
     68         SDL_VideoData *data;
     69 
     70         /* Initialize all variables that we clean on shutdown */
     71         device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
     72         if (device) {
     73             data = [SDL_VideoData new];
     74         } else {
     75             SDL_free(device);
     76             SDL_OutOfMemory();
     77             return (0);
     78         }
     79 
     80         device->driverdata = (void *) CFBridgingRetain(data);
     81 
     82         /* Set the function pointers */
     83         device->VideoInit = UIKit_VideoInit;
     84         device->VideoQuit = UIKit_VideoQuit;
     85         device->GetDisplayModes = UIKit_GetDisplayModes;
     86         device->SetDisplayMode = UIKit_SetDisplayMode;
     87         device->PumpEvents = UIKit_PumpEvents;
     88         device->SuspendScreenSaver = UIKit_SuspendScreenSaver;
     89         device->CreateSDLWindow = UIKit_CreateWindow;
     90         device->SetWindowTitle = UIKit_SetWindowTitle;
     91         device->ShowWindow = UIKit_ShowWindow;
     92         device->HideWindow = UIKit_HideWindow;
     93         device->RaiseWindow = UIKit_RaiseWindow;
     94         device->SetWindowBordered = UIKit_SetWindowBordered;
     95         device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
     96         device->DestroyWindow = UIKit_DestroyWindow;
     97         device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
     98         device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;
     99         device->GetDisplayDPI = UIKit_GetDisplayDPI;
    100 
    101 #if SDL_IPHONE_KEYBOARD
    102         device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
    103         device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
    104         device->HideScreenKeyboard = UIKit_HideScreenKeyboard;
    105         device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown;
    106         device->SetTextInputRect = UIKit_SetTextInputRect;
    107 #endif
    108 
    109         device->SetClipboardText = UIKit_SetClipboardText;
    110         device->GetClipboardText = UIKit_GetClipboardText;
    111         device->HasClipboardText = UIKit_HasClipboardText;
    112 
    113         /* OpenGL (ES) functions */
    114 #if SDL_VIDEO_OPENGL_ES || SDL_VIDEO_OPENGL_ES2
    115         device->GL_MakeCurrent      = UIKit_GL_MakeCurrent;
    116         device->GL_GetDrawableSize  = UIKit_GL_GetDrawableSize;
    117         device->GL_SwapWindow       = UIKit_GL_SwapWindow;
    118         device->GL_CreateContext    = UIKit_GL_CreateContext;
    119         device->GL_DeleteContext    = UIKit_GL_DeleteContext;
    120         device->GL_GetProcAddress   = UIKit_GL_GetProcAddress;
    121         device->GL_LoadLibrary      = UIKit_GL_LoadLibrary;
    122 #endif
    123         device->free = UIKit_DeleteDevice;
    124 
    125 #if SDL_VIDEO_VULKAN
    126         device->Vulkan_LoadLibrary = UIKit_Vulkan_LoadLibrary;
    127         device->Vulkan_UnloadLibrary = UIKit_Vulkan_UnloadLibrary;
    128         device->Vulkan_GetInstanceExtensions
    129                                      = UIKit_Vulkan_GetInstanceExtensions;
    130         device->Vulkan_CreateSurface = UIKit_Vulkan_CreateSurface;
    131         device->Vulkan_GetDrawableSize = UIKit_Vulkan_GetDrawableSize;
    132 #endif
    133 
    134 #if SDL_VIDEO_METAL
    135         device->Metal_CreateView = UIKit_Metal_CreateView;
    136         device->Metal_DestroyView = UIKit_Metal_DestroyView;
    137         device->Metal_GetLayer = UIKit_Metal_GetLayer;
    138         device->Metal_GetDrawableSize = UIKit_Metal_GetDrawableSize;
    139 #endif
    140 
    141         device->gl_config.accelerated = 1;
    142 
    143         return device;
    144     }
    145 }
    146 
    147 VideoBootStrap UIKIT_bootstrap = {
    148     UIKITVID_DRIVER_NAME, "SDL UIKit video driver",
    149     UIKit_CreateDevice
    150 };
    151 
    152 
    153 int
    154 UIKit_VideoInit(_THIS)
    155 {
    156     _this->gl_config.driver_loaded = 1;
    157 
    158     if (UIKit_InitModes(_this) < 0) {
    159         return -1;
    160     }
    161 
    162 	SDL_InitGCKeyboard();
    163 	SDL_InitGCMouse();
    164 
    165     return 0;
    166 }
    167 
    168 void
    169 UIKit_VideoQuit(_THIS)
    170 {
    171 	SDL_QuitGCKeyboard();
    172 	SDL_QuitGCMouse();
    173 
    174     UIKit_QuitModes(_this);
    175 }
    176 
    177 void
    178 UIKit_SuspendScreenSaver(_THIS)
    179 {
    180     @autoreleasepool {
    181         /* Ignore ScreenSaver API calls if the idle timer hint has been set. */
    182         /* FIXME: The idle timer hint should be deprecated for SDL 2.1. */
    183         if (!SDL_GetHintBoolean(SDL_HINT_IDLE_TIMER_DISABLED, SDL_FALSE)) {
    184             UIApplication *app = [UIApplication sharedApplication];
    185 
    186             /* Prevent the display from dimming and going to sleep. */
    187             app.idleTimerDisabled = (_this->suspend_screensaver != SDL_FALSE);
    188         }
    189     }
    190 }
    191 
    192 SDL_bool
    193 UIKit_IsSystemVersionAtLeast(double version)
    194 {
    195     return [[UIDevice currentDevice].systemVersion doubleValue] >= version;
    196 }
    197 
    198 CGRect
    199 UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen)
    200 {
    201     SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
    202     CGRect frame = screen.bounds;
    203 
    204     /* Use the UIWindow bounds instead of the UIScreen bounds, when possible.
    205      * The uiwindow bounds may be smaller than the screen bounds when Split View
    206      * is used on an iPad. */
    207     if (data != nil && data.uiwindow != nil) {
    208         frame = data.uiwindow.bounds;
    209     }
    210 
    211 #if !TARGET_OS_TV && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0)
    212     BOOL hasiOS7 = UIKit_IsSystemVersionAtLeast(7.0);
    213 
    214     /* The view should always show behind the status bar in iOS 7+. */
    215     if (!hasiOS7 && !(window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN))) {
    216         frame = screen.applicationFrame;
    217     }
    218 #endif
    219 
    220 #if !TARGET_OS_TV
    221     /* iOS 10 seems to have a bug where, in certain conditions, putting the
    222      * device to sleep with the a landscape-only app open, re-orienting the
    223      * device to portrait, and turning it back on will result in the screen
    224      * bounds returning portrait orientation despite the app being in landscape.
    225      * This is a workaround until a better solution can be found.
    226      * https://bugzilla.libsdl.org/show_bug.cgi?id=3505
    227      * https://bugzilla.libsdl.org/show_bug.cgi?id=3465
    228      * https://forums.developer.apple.com/thread/65337 */
    229     if (UIKit_IsSystemVersionAtLeast(8.0)) {
    230         UIInterfaceOrientation orient = [UIApplication sharedApplication].statusBarOrientation;
    231         BOOL landscape = UIInterfaceOrientationIsLandscape(orient);
    232         BOOL fullscreen = CGRectEqualToRect(screen.bounds, frame);
    233 
    234         /* The orientation flip doesn't make sense when the window is smaller
    235          * than the screen (iPad Split View, for example). */
    236         if (fullscreen && (landscape != (frame.size.width > frame.size.height))) {
    237             float height = frame.size.width;
    238             frame.size.width = frame.size.height;
    239             frame.size.height = height;
    240         }
    241     }
    242 #endif
    243 
    244     return frame;
    245 }
    246 
    247 void
    248 UIKit_ForceUpdateHomeIndicator()
    249 {
    250 #if !TARGET_OS_TV
    251     /* Force the main SDL window to re-evaluate home indicator state */
    252     SDL_Window *focus = SDL_GetFocusWindow();
    253     if (focus) {
    254         SDL_WindowData *data = (__bridge SDL_WindowData *) focus->driverdata;
    255         if (data != nil) {
    256 #pragma clang diagnostic push
    257 #pragma clang diagnostic ignored "-Wunguarded-availability-new"
    258             if ([data.viewcontroller respondsToSelector:@selector(setNeedsUpdateOfHomeIndicatorAutoHidden)]) {
    259                 [data.viewcontroller performSelectorOnMainThread:@selector(setNeedsUpdateOfHomeIndicatorAutoHidden) withObject:nil waitUntilDone:NO];
    260                 [data.viewcontroller performSelectorOnMainThread:@selector(setNeedsUpdateOfScreenEdgesDeferringSystemGestures) withObject:nil waitUntilDone:NO];
    261             }
    262 #pragma clang diagnostic pop
    263         }
    264     }
    265 #endif /* !TARGET_OS_TV */
    266 }
    267 
    268 /*
    269  * iOS log support.
    270  *
    271  * This doesn't really have aything to do with the interfaces of the SDL video
    272  *  subsystem, but we need to stuff this into an Objective-C source code file.
    273  *
    274  * NOTE: This is copypasted from src/video/cocoa/SDL_cocoavideo.m! Thus, if
    275  *  Cocoa is supported, we use that one instead. Be sure both versions remain
    276  *  identical!
    277  */
    278 
    279 #if !defined(SDL_VIDEO_DRIVER_COCOA)
    280 void SDL_NSLog(const char *text)
    281 {
    282     NSLog(@"%s", text);
    283 }
    284 #endif /* SDL_VIDEO_DRIVER_COCOA */
    285 
    286 /*
    287  * iOS Tablet detection
    288  *
    289  * This doesn't really have aything to do with the interfaces of the SDL video
    290  * subsystem, but we need to stuff this into an Objective-C source code file.
    291  */
    292 SDL_bool SDL_IsIPad(void)
    293 {
    294     return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad);
    295 }
    296 
    297 #endif /* SDL_VIDEO_DRIVER_UIKIT */
    298 
    299 /* vi: set ts=4 sw=4 expandtab: */