SDL_uikitmodes.m (7609B)
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2014 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 "SDL_assert.h" 26#include "SDL_uikitmodes.h" 27 28 29static int 30UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode, 31 UIScreenMode * uiscreenmode, CGFloat scale) 32{ 33 SDL_DisplayModeData *data = NULL; 34 35 if (uiscreenmode != nil) { 36 /* Allocate the display mode data */ 37 data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data)); 38 if (!data) { 39 return SDL_OutOfMemory(); 40 } 41 42 data->uiscreenmode = uiscreenmode; 43 [data->uiscreenmode retain]; 44 45 data->scale = scale; 46 } 47 48 mode->driverdata = data; 49 50 return 0; 51} 52 53static void 54UIKit_FreeDisplayModeData(SDL_DisplayMode * mode) 55{ 56 if (mode->driverdata != NULL) { 57 SDL_DisplayModeData *data = (SDL_DisplayModeData *)mode->driverdata; 58 [data->uiscreenmode release]; 59 SDL_free(data); 60 mode->driverdata = NULL; 61 } 62} 63 64static int 65UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h, 66 UIScreenMode * uiscreenmode, CGFloat scale) 67{ 68 SDL_DisplayMode mode; 69 SDL_zero(mode); 70 71 mode.format = SDL_PIXELFORMAT_ABGR8888; 72 mode.refresh_rate = 0; 73 if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) { 74 return -1; 75 } 76 77 mode.w = w; 78 mode.h = h; 79 if (SDL_AddDisplayMode(display, &mode)) { 80 return 0; 81 } else { 82 UIKit_FreeDisplayModeData(&mode); 83 return -1; 84 } 85} 86 87static int 88UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, CGFloat scale, 89 UIScreenMode * uiscreenmode, SDL_bool addRotation) 90{ 91 if (UIKit_AddSingleDisplayMode(display, w, h, uiscreenmode, scale) < 0) { 92 return -1; 93 } 94 95 if (addRotation) { 96 /* Add the rotated version */ 97 if (UIKit_AddSingleDisplayMode(display, h, w, uiscreenmode, scale) < 0) { 98 return -1; 99 } 100 } 101 102 return 0; 103} 104 105static int 106UIKit_AddDisplay(UIScreen *uiscreen) 107{ 108 CGSize size = [uiscreen bounds].size; 109 110 /* Make sure the width/height are oriented correctly */ 111 if (UIKit_IsDisplayLandscape(uiscreen) != (size.width > size.height)) { 112 CGFloat height = size.width; 113 size.width = size.height; 114 size.height = height; 115 } 116 117 /* When dealing with UIKit all coordinates are specified in terms of 118 * what Apple refers to as points. [UIScreen scale] indicates the 119 * relationship between points and pixels. Since SDL has no notion 120 * of points, we must compensate in all cases where dealing with such 121 * units. 122 */ 123 CGFloat scale = [uiscreen scale]; 124 125 SDL_VideoDisplay display; 126 SDL_DisplayMode mode; 127 SDL_zero(mode); 128 mode.format = SDL_PIXELFORMAT_ABGR8888; 129 mode.w = (int)(size.width * scale); 130 mode.h = (int)(size.height * scale); 131 132 UIScreenMode * uiscreenmode = [uiscreen currentMode]; 133 134 if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode, scale) < 0) { 135 return -1; 136 } 137 138 SDL_zero(display); 139 display.desktop_mode = mode; 140 display.current_mode = mode; 141 142 /* Allocate the display data */ 143 SDL_DisplayData *data = (SDL_DisplayData *) SDL_malloc(sizeof(*data)); 144 if (!data) { 145 UIKit_FreeDisplayModeData(&display.desktop_mode); 146 return SDL_OutOfMemory(); 147 } 148 149 [uiscreen retain]; 150 data->uiscreen = uiscreen; 151 data->scale = scale; 152 153 display.driverdata = data; 154 SDL_AddVideoDisplay(&display); 155 156 return 0; 157} 158 159SDL_bool 160UIKit_IsDisplayLandscape(UIScreen *uiscreen) 161{ 162 if (uiscreen == [UIScreen mainScreen]) { 163 return UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]); 164 } else { 165 CGSize size = [uiscreen bounds].size; 166 return (size.width > size.height); 167 } 168} 169 170int 171UIKit_InitModes(_THIS) 172{ 173 for (UIScreen *uiscreen in [UIScreen screens]) { 174 if (UIKit_AddDisplay(uiscreen) < 0) { 175 return -1; 176 } 177 } 178 179 return 0; 180} 181 182void 183UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display) 184{ 185 SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; 186 187 SDL_bool isLandscape = UIKit_IsDisplayLandscape(data->uiscreen); 188 SDL_bool addRotation = (data->uiscreen == [UIScreen mainScreen]); 189 190 for (UIScreenMode *uimode in [data->uiscreen availableModes]) { 191 CGSize size = [uimode size]; 192 int w = (int)size.width; 193 int h = (int)size.height; 194 195 /* Make sure the width/height are oriented correctly */ 196 if (isLandscape != (w > h)) { 197 int tmp = w; 198 w = h; 199 h = tmp; 200 } 201 202 /* Add the native screen resolution. */ 203 UIKit_AddDisplayMode(display, w, h, data->scale, uimode, addRotation); 204 205 if (data->scale != 1.0f) { 206 /* Add the native screen resolution divided by its scale. 207 * This is so devices capable of e.g. 640x960 also advertise 320x480. 208 */ 209 UIKit_AddDisplayMode(display, 210 (int)(size.width / data->scale), 211 (int)(size.height / data->scale), 212 1.0f, uimode, addRotation); 213 } 214 } 215} 216 217int 218UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) 219{ 220 SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; 221 SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)mode->driverdata; 222 223 [data->uiscreen setCurrentMode:modedata->uiscreenmode]; 224 225 if (data->uiscreen == [UIScreen mainScreen]) { 226 if (mode->w > mode->h) { 227 if (!UIKit_IsDisplayLandscape(data->uiscreen)) { 228 [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO]; 229 } 230 } else if (mode->w < mode->h) { 231 if (UIKit_IsDisplayLandscape(data->uiscreen)) { 232 [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; 233 } 234 } 235 } 236 237 return 0; 238} 239 240void 241UIKit_QuitModes(_THIS) 242{ 243 /* Release Objective-C objects, so higher level doesn't free() them. */ 244 int i, j; 245 for (i = 0; i < _this->num_displays; i++) { 246 SDL_VideoDisplay *display = &_this->displays[i]; 247 248 UIKit_FreeDisplayModeData(&display->desktop_mode); 249 for (j = 0; j < display->num_display_modes; j++) { 250 SDL_DisplayMode *mode = &display->display_modes[j]; 251 UIKit_FreeDisplayModeData(mode); 252 } 253 254 SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata; 255 [data->uiscreen release]; 256 SDL_free(data); 257 display->driverdata = NULL; 258 } 259} 260 261#endif /* SDL_VIDEO_DRIVER_UIKIT */ 262 263/* vi: set ts=4 sw=4 expandtab: */