SDL  2.0
SDL_uikitvideo.m
Go to the documentation of this file.
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);
60  }
61 }
62 
63 static SDL_VideoDevice *
64 UIKit_CreateDevice(int devindex)
65 {
66  @autoreleasepool {
69 
70  /* Initialize all variables that we clean on shutdown */
72  if (device) {
73  data = [SDL_VideoData new];
74  } else {
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 
148  UIKITVID_DRIVER_NAME, "SDL UIKit video driver",
149  UIKit_CreateDevice
150 };
151 
152 
153 int
154 UIKit_VideoInit(_THIS)
155 {
157 
158  if (UIKit_InitModes(_this) < 0) {
159  return -1;
160  }
161 
163  SDL_InitGCMouse();
164 
165  return 0;
166 }
167 
168 void
169 UIKit_VideoQuit(_THIS)
170 {
172  SDL_QuitGCMouse();
173 
175 }
176 
177 void
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. */
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
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: */
#define _THIS
#define SDL_free
#define SDL_GetHintBoolean
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define SDL_HINT_IDLE_TIMER_DISABLED
A variable controlling whether the idle timer is disabled on iOS.
Definition: SDL_hints.h:394
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
SDL_bool
Definition: SDL_stdinc.h:168
@ SDL_FALSE
Definition: SDL_stdinc.h:169
VideoBootStrap UIKIT_bootstrap
SDL_Window * SDL_GetFocusWindow(void)
Definition: SDL_video.c:2812
char * UIKit_GetClipboardText(_THIS)
SDL_bool UIKit_HasClipboardText(_THIS)
int UIKit_SetClipboardText(_THIS, const char *text)
void SDL_InitGCMouse(void)
void SDL_InitGCKeyboard(void)
void UIKit_PumpEvents(_THIS)
void SDL_QuitGCKeyboard(void)
void SDL_QuitGCMouse(void)
void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
void UIKit_QuitModes(_THIS)
int UIKit_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi, float *hdpi, float *vdpi)
int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
int UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
int UIKit_InitModes(_THIS)
void UIKit_ForceUpdateHomeIndicator(void)
void UIKit_SuspendScreenSaver(_THIS)
SDL_bool UIKit_IsSystemVersionAtLeast(double version)
void UIKit_ShowWindow(_THIS, SDL_Window *window)
void UIKit_RaiseWindow(_THIS, SDL_Window *window)
SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
void UIKit_SetWindowBordered(_THIS, SDL_Window *window, SDL_bool bordered)
void UIKit_SetWindowTitle(_THIS, SDL_Window *window)
void UIKit_DestroyWindow(_THIS, SDL_Window *window)
void UIKit_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
int UIKit_CreateWindow(_THIS, SDL_Window *window)
void UIKit_HideWindow(_THIS, SDL_Window *window)
static SDL_VideoDevice * _this
Definition: SDL_video.c:126
@ SDL_WINDOW_FULLSCREEN
Definition: SDL_video.h:99
@ SDL_WINDOW_BORDERLESS
Definition: SDL_video.h:103
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
static SDL_AudioDeviceID device
Definition: loopwave.c:37
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
BOOL(WINAPI *CloseTouchInputHandle)(HTOUCHINPUT)
struct SDL_VideoDevice::@440 gl_config
SDL_bool suspend_screensaver
Definition: SDL_sysvideo.h:324
The type used to identify a window.
Definition: SDL_sysvideo.h:75
void * driverdata
Definition: SDL_sysvideo.h:112
SDL_Renderer * screen
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:47
int frame
Definition: teststreaming.c:60