Skip to content

Latest commit

 

History

History
380 lines (315 loc) · 11.2 KB

SDL_uikitmodes.m

File metadata and controls

380 lines (315 loc) · 11.2 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 3, 2018
Jan 3, 2018
3
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_UIKIT
#include "SDL_assert.h"
#include "SDL_uikitmodes.h"
Aug 23, 2018
Aug 23, 2018
28
29
#include "../../events/SDL_events_c.h"
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
@implementation SDL_DisplayData
@synthesize uiscreen;
@end
@implementation SDL_DisplayModeData
@synthesize uiscreenmode;
@end
static int
UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode,
UIScreenMode * uiscreenmode)
{
SDL_DisplayModeData *data = nil;
if (uiscreenmode != nil) {
/* Allocate the display mode data */
data = [[SDL_DisplayModeData alloc] init];
if (!data) {
return SDL_OutOfMemory();
}
data.uiscreenmode = uiscreenmode;
}
mode->driverdata = (void *) CFBridgingRetain(data);
return 0;
}
static void
UIKit_FreeDisplayModeData(SDL_DisplayMode * mode)
{
if (mode->driverdata != NULL) {
CFRelease(mode->driverdata);
mode->driverdata = NULL;
}
}
Jun 11, 2017
Jun 11, 2017
73
74
75
76
77
78
79
80
81
82
83
static NSUInteger
UIKit_GetDisplayModeRefreshRate(UIScreen *uiscreen)
{
#ifdef __IPHONE_10_3
if ([uiscreen respondsToSelector:@selector(maximumFramesPerSecond)]) {
return uiscreen.maximumFramesPerSecond;
}
#endif
return 0;
}
84
85
static int
UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
Jun 11, 2017
Jun 11, 2017
86
UIScreen * uiscreen, UIScreenMode * uiscreenmode)
87
88
89
90
91
92
93
94
{
SDL_DisplayMode mode;
SDL_zero(mode);
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
return -1;
}
Jun 11, 2017
Jun 11, 2017
95
96
mode.format = SDL_PIXELFORMAT_ABGR8888;
mode.refresh_rate = (int) UIKit_GetDisplayModeRefreshRate(uiscreen);
97
98
mode.w = w;
mode.h = h;
Jun 11, 2017
Jun 11, 2017
99
100
101
102
103
104
105
106
107
108
if (SDL_AddDisplayMode(display, &mode)) {
return 0;
} else {
UIKit_FreeDisplayModeData(&mode);
return -1;
}
}
static int
Jun 11, 2017
Jun 11, 2017
109
UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, UIScreen * uiscreen,
110
111
UIScreenMode * uiscreenmode, SDL_bool addRotation)
{
Jun 11, 2017
Jun 11, 2017
112
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreen, uiscreenmode) < 0) {
113
114
115
116
117
return -1;
}
if (addRotation) {
/* Add the rotated version */
Jun 11, 2017
Jun 11, 2017
118
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreen, uiscreenmode) < 0) {
119
120
121
122
123
124
125
126
127
128
return -1;
}
}
return 0;
}
static int
UIKit_AddDisplay(UIScreen *uiscreen)
{
Jun 11, 2017
Jun 11, 2017
129
UIScreenMode *uiscreenmode = uiscreen.currentMode;
130
CGSize size = uiscreen.bounds.size;
Jun 11, 2017
Jun 11, 2017
131
132
133
SDL_VideoDisplay display;
SDL_DisplayMode mode;
SDL_zero(mode);
134
135
136
137
138
139
140
141
142
/* Make sure the width/height are oriented correctly */
if (UIKit_IsDisplayLandscape(uiscreen) != (size.width > size.height)) {
CGFloat height = size.width;
size.width = size.height;
size.height = height;
}
mode.format = SDL_PIXELFORMAT_ABGR8888;
Jun 11, 2017
Jun 11, 2017
143
mode.refresh_rate = (int) UIKit_GetDisplayModeRefreshRate(uiscreen);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
mode.w = (int) size.width;
mode.h = (int) size.height;
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
return -1;
}
SDL_zero(display);
display.desktop_mode = mode;
display.current_mode = mode;
/* Allocate the display data */
SDL_DisplayData *data = [[SDL_DisplayData alloc] init];
if (!data) {
UIKit_FreeDisplayModeData(&display.desktop_mode);
return SDL_OutOfMemory();
}
data.uiscreen = uiscreen;
display.driverdata = (void *) CFBridgingRetain(data);
SDL_AddVideoDisplay(&display);
return 0;
}
SDL_bool
UIKit_IsDisplayLandscape(UIScreen *uiscreen)
{
Sep 14, 2016
Sep 14, 2016
173
#if !TARGET_OS_TV
174
175
if (uiscreen == [UIScreen mainScreen]) {
return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
Sep 14, 2016
Sep 14, 2016
176
177
178
} else
#endif /* !TARGET_OS_TV */
{
179
180
181
182
183
184
185
186
187
188
189
190
191
192
CGSize size = uiscreen.bounds.size;
return (size.width > size.height);
}
}
int
UIKit_InitModes(_THIS)
{
@autoreleasepool {
for (UIScreen *uiscreen in [UIScreen screens]) {
if (UIKit_AddDisplay(uiscreen) < 0) {
return -1;
}
}
Aug 23, 2018
Aug 23, 2018
193
#if !TARGET_OS_TV
Sep 24, 2018
Sep 24, 2018
194
SDL_OnApplicationDidChangeStatusBarOrientation();
Aug 23, 2018
Aug 23, 2018
195
#endif
196
197
198
199
200
201
202
203
204
205
206
207
208
209
}
return 0;
}
void
UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
{
@autoreleasepool {
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
SDL_bool isLandscape = UIKit_IsDisplayLandscape(data.uiscreen);
SDL_bool addRotation = (data.uiscreen == [UIScreen mainScreen]);
CGFloat scale = data.uiscreen.scale;
Sep 14, 2016
Sep 14, 2016
210
211
212
213
214
215
216
217
NSArray *availableModes = nil;
#if TARGET_OS_TV
addRotation = SDL_FALSE;
availableModes = @[data.uiscreen.currentMode];
#else
availableModes = data.uiscreen.availableModes;
#endif
Sep 21, 2017
Sep 21, 2017
219
#ifdef __IPHONE_8_0
220
221
222
223
224
/* The UIScreenMode of an iPhone 6 Plus should be 1080x1920 rather than
* 1242x2208 (414x736@3x), so we should use the native scale. */
if ([data.uiscreen respondsToSelector:@selector(nativeScale)]) {
scale = data.uiscreen.nativeScale;
}
Sep 21, 2017
Sep 21, 2017
225
#endif
Sep 14, 2016
Sep 14, 2016
227
for (UIScreenMode *uimode in availableModes) {
228
229
230
231
232
233
234
235
236
237
238
239
/* The size of a UIScreenMode is in pixels, but we deal exclusively
* in points (except in SDL_GL_GetDrawableSize.) */
int w = (int)(uimode.size.width / scale);
int h = (int)(uimode.size.height / scale);
/* Make sure the width/height are oriented correctly */
if (isLandscape != (w > h)) {
int tmp = w;
w = h;
h = tmp;
}
Jun 11, 2017
Jun 11, 2017
240
UIKit_AddDisplayMode(display, w, h, data.uiscreen, uimode, addRotation);
241
242
243
244
245
246
247
248
249
250
}
}
}
int
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
{
@autoreleasepool {
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
Sep 14, 2016
Sep 14, 2016
251
252
#if !TARGET_OS_TV
SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)mode->driverdata;
253
[data.uiscreen setCurrentMode:modedata.uiscreenmode];
Sep 14, 2016
Sep 14, 2016
254
#endif
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
if (data.uiscreen == [UIScreen mainScreen]) {
/* [UIApplication setStatusBarOrientation:] no longer works reliably
* in recent iOS versions, so we can't rotate the screen when setting
* the display mode. */
if (mode->w > mode->h) {
if (!UIKit_IsDisplayLandscape(data.uiscreen)) {
return SDL_SetError("Screen orientation does not match display mode size");
}
} else if (mode->w < mode->h) {
if (UIKit_IsDisplayLandscape(data.uiscreen)) {
return SDL_SetError("Screen orientation does not match display mode size");
}
}
}
}
return 0;
}
Jan 5, 2016
Jan 5, 2016
275
276
277
int
UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
{
Sep 14, 2016
Sep 14, 2016
278
279
280
@autoreleasepool {
int displayIndex = (int) (display - _this->displays);
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
Jul 15, 2017
Jul 15, 2017
281
CGRect frame = data.uiscreen.bounds;
Sep 14, 2016
Sep 14, 2016
282
283
284
285
286
287
288
/* the default function iterates displays to make a fake offset,
as if all the displays were side-by-side, which is fine for iOS. */
if (SDL_GetDisplayBounds(displayIndex, rect) < 0) {
return -1;
}
Jul 15, 2017
Jul 15, 2017
289
#if !TARGET_OS_TV && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
Sep 14, 2016
Sep 14, 2016
290
291
292
293
294
295
296
297
298
if (!UIKit_IsSystemVersionAtLeast(7.0)) {
frame = [data.uiscreen applicationFrame];
}
#endif
rect->x += frame.origin.x;
rect->y += frame.origin.y;
rect->w = frame.size.width;
rect->h = frame.size.height;
Jan 5, 2016
Jan 5, 2016
299
300
301
302
303
}
return 0;
}
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
void
UIKit_QuitModes(_THIS)
{
/* Release Objective-C objects, so higher level doesn't free() them. */
int i, j;
@autoreleasepool {
for (i = 0; i < _this->num_displays; i++) {
SDL_VideoDisplay *display = &_this->displays[i];
UIKit_FreeDisplayModeData(&display->desktop_mode);
for (j = 0; j < display->num_display_modes; j++) {
SDL_DisplayMode *mode = &display->display_modes[j];
UIKit_FreeDisplayModeData(mode);
}
if (display->driverdata != NULL) {
CFRelease(display->driverdata);
display->driverdata = NULL;
}
}
}
}
Sep 11, 2018
Sep 11, 2018
327
#if !TARGET_OS_TV
Aug 23, 2018
Aug 23, 2018
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
void SDL_OnApplicationDidChangeStatusBarOrientation()
{
BOOL isLandscape = UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
SDL_VideoDisplay *display = SDL_GetDisplay(0);
if (display) {
SDL_DisplayMode *desktopmode = &display->desktop_mode;
SDL_DisplayMode *currentmode = &display->current_mode;
SDL_DisplayOrientation orientation = SDL_ORIENTATION_UNKNOWN;
/* The desktop display mode should be kept in sync with the screen
* orientation so that updating a window's fullscreen state to
* SDL_WINDOW_FULLSCREEN_DESKTOP keeps the window dimensions in the
* correct orientation. */
if (isLandscape != (desktopmode->w > desktopmode->h)) {
int height = desktopmode->w;
desktopmode->w = desktopmode->h;
desktopmode->h = height;
}
/* Same deal with the current mode + SDL_GetCurrentDisplayMode. */
if (isLandscape != (currentmode->w > currentmode->h)) {
int height = currentmode->w;
currentmode->w = currentmode->h;
currentmode->h = height;
}
switch ([UIApplication sharedApplication].statusBarOrientation) {
case UIInterfaceOrientationPortrait:
orientation = SDL_ORIENTATION_PORTRAIT;
break;
case UIInterfaceOrientationPortraitUpsideDown:
orientation = SDL_ORIENTATION_PORTRAIT_FLIPPED;
break;
case UIInterfaceOrientationLandscapeLeft:
/* Bug: UIInterfaceOrientationLandscapeLeft/Right are reversed - http://openradar.appspot.com/7216046 */
orientation = SDL_ORIENTATION_LANDSCAPE_FLIPPED;
break;
case UIInterfaceOrientationLandscapeRight:
/* Bug: UIInterfaceOrientationLandscapeLeft/Right are reversed - http://openradar.appspot.com/7216046 */
orientation = SDL_ORIENTATION_LANDSCAPE;
break;
default:
break;
}
SDL_SendDisplayEvent(display, SDL_DISPLAYEVENT_ORIENTATION, orientation);
}
}
Sep 11, 2018
Sep 11, 2018
376
#endif /* !TARGET_OS_TV */
Aug 23, 2018
Aug 23, 2018
377
378
379
380
#endif /* SDL_VIDEO_DRIVER_UIKIT */
/* vi: set ts=4 sw=4 expandtab: */