src/video/uikit/SDL_uikitvideo.m
author Sam Lantinga
Mon, 19 Oct 2020 17:29:16 -0700
changeset 14174 71e97db0ba5d
parent 14156 b7f667be5260
permissions -rw-r--r--
Removed debug log message
     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: */