zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_uikitwindow.m
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 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_config.h"
22 
23 #if SDL_VIDEO_DRIVER_UIKIT
24 
25 #include "SDL_syswm.h"
26 #include "SDL_video.h"
27 #include "SDL_mouse.h"
28 #include "SDL_assert.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 #import "SDL_uikitappdelegate.h"
39 
40 #import "SDL_uikitopenglview.h"
41 
42 #include <Foundation/Foundation.h>
43 
44 
45 
46 
47 static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created)
48 {
50  SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
51  SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
53 
54  /* Allocate the window data */
55  data = (SDL_WindowData *)SDL_malloc(sizeof(*data));
56  if (!data) {
57  return SDL_OutOfMemory();
58  }
59  data->uiwindow = uiwindow;
60  data->viewcontroller = nil;
61  data->view = nil;
62 
63  /* Fill in the SDL window with the window data */
64  {
65  window->x = 0;
66  window->y = 0;
67 
68  CGRect bounds;
70  bounds = [displaydata->uiscreen bounds];
71  } else {
72  bounds = [displaydata->uiscreen applicationFrame];
73  }
74 
75  /* Get frame dimensions in pixels */
76  int width = (int)(bounds.size.width * displaymodedata->scale);
77  int height = (int)(bounds.size.height * displaymodedata->scale);
78 
79  /* Make sure the width/height are oriented correctly */
80  if (UIKit_IsDisplayLandscape(displaydata->uiscreen) != (width > height)) {
81  int temp = width;
82  width = height;
83  height = temp;
84  }
85 
86  window->w = width;
87  window->h = height;
88  }
89 
90  window->driverdata = data;
91 
92  /* only one window on iOS, always shown */
93  window->flags &= ~SDL_WINDOW_HIDDEN;
94 
95  /* SDL_WINDOW_BORDERLESS controls whether status bar is hidden.
96  * This is only set if the window is on the main screen. Other screens
97  * just force the window to have the borderless flag.
98  */
99  if (displaydata->uiscreen == [UIScreen mainScreen]) {
100  window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */
101 
102  if ([UIApplication sharedApplication].statusBarHidden) {
103  window->flags |= SDL_WINDOW_BORDERLESS;
104  } else {
105  window->flags &= ~SDL_WINDOW_BORDERLESS;
106  }
107  } else {
108  window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */
109  window->flags &= ~SDL_WINDOW_INPUT_FOCUS; /* never has input focus */
110  window->flags |= SDL_WINDOW_BORDERLESS; /* never has a status bar. */
111  }
112 
113  /* The View Controller will handle rotating the view when the
114  * device orientation changes. This will trigger resize events, if
115  * appropriate.
116  */
117  SDL_uikitviewcontroller *controller;
118  controller = [SDL_uikitviewcontroller alloc];
119  data->viewcontroller = [controller initWithSDLWindow:window];
120  [data->viewcontroller setTitle:@"SDL App"]; /* !!! FIXME: hook up SDL_SetWindowTitle() */
121 
122  return 0;
123 }
124 
125 int
127 {
128  SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
129  SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
130  const BOOL external = ([UIScreen mainScreen] != data->uiscreen);
131 
132  /* SDL currently puts this window at the start of display's linked list. We rely on this. */
133  SDL_assert(_this->windows == window);
134 
135  /* We currently only handle a single window per display on iOS */
136  if (window->next != NULL) {
137  return SDL_SetError("Only one window allowed per display.");
138  }
139 
140  /* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
141  * user, so it's in standby), try to force the display to a resolution
142  * that most closely matches the desired window size.
143  */
145  const CGSize origsize = [[data->uiscreen currentMode] size];
146  if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
147  if (display->num_display_modes == 0) {
148  _this->GetDisplayModes(_this, display);
149  }
150 
151  int i;
152  const SDL_DisplayMode *bestmode = NULL;
153  for (i = display->num_display_modes; i >= 0; i--) {
154  const SDL_DisplayMode *mode = &display->display_modes[i];
155  if ((mode->w >= window->w) && (mode->h >= window->h))
156  bestmode = mode;
157  }
158 
159  if (bestmode) {
160  SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata;
161  [data->uiscreen setCurrentMode:modedata->uiscreenmode];
162 
163  /* desktop_mode doesn't change here (the higher level will
164  * use it to set all the screens back to their defaults
165  * upon window destruction, SDL_Quit(), etc.
166  */
167  display->current_mode = *bestmode;
168  }
169  }
170  }
171 
172  if (data->uiscreen == [UIScreen mainScreen]) {
174  [UIApplication sharedApplication].statusBarHidden = YES;
175  } else {
176  [UIApplication sharedApplication].statusBarHidden = NO;
177  }
178  }
179 
180  if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
181  if (window->w > window->h) {
182  if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
183  [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
184  }
185  } else if (window->w < window->h) {
186  if (UIKit_IsDisplayLandscape(data->uiscreen)) {
187  [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
188  }
189  }
190  }
191 
192  /* ignore the size user requested, and make a fullscreen window */
193  /* !!! FIXME: can we have a smaller view? */
194  UIWindow *uiwindow = [UIWindow alloc];
195  uiwindow = [uiwindow initWithFrame:[data->uiscreen bounds]];
196 
197  /* put the window on an external display if appropriate. This implicitly
198  * does [uiwindow setframe:[uiscreen bounds]], so don't do it on the
199  * main display, where we land by default, as that would eat the
200  * status bar real estate.
201  */
202  if (external) {
203  [uiwindow setScreen:data->uiscreen];
204  }
205 
206  if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
207  [uiwindow release];
208  return -1;
209  }
210 
211  return 1;
212 
213 }
214 
215 void
217 {
218  UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
219 
220  [uiwindow makeKeyAndVisible];
221 }
222 
223 void
225 {
226  UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
227 
228  uiwindow.hidden = YES;
229 }
230 
231 void
233 {
234  /* We don't currently offer a concept of "raising" the SDL window, since
235  * we only allow one per display, in the iOS fashion.
236  * However, we use this entry point to rebind the context to the view
237  * during OnWindowRestored processing.
238  */
240 }
241 
242 void
243 UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
244 {
245  SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
246  SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
247  UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
248 
249  if (fullscreen) {
250  [UIApplication sharedApplication].statusBarHidden = YES;
251  } else {
252  [UIApplication sharedApplication].statusBarHidden = NO;
253  }
254 
255  CGRect bounds;
256  if (fullscreen) {
257  bounds = [displaydata->uiscreen bounds];
258  } else {
259  bounds = [displaydata->uiscreen applicationFrame];
260  }
261 
262  /* Get frame dimensions in pixels */
263  int width = (int)(bounds.size.width * displaymodedata->scale);
264  int height = (int)(bounds.size.height * displaymodedata->scale);
265 
266  /* We can pick either width or height here and we'll rotate the
267  screen to match, so we pick the closest to what we wanted.
268  */
269  if (window->w >= window->h) {
270  if (width > height) {
271  window->w = width;
272  window->h = height;
273  } else {
274  window->w = height;
275  window->h = width;
276  }
277  } else {
278  if (width > height) {
279  window->w = height;
280  window->h = width;
281  } else {
282  window->w = width;
283  window->h = height;
284  }
285  }
286 }
287 
288 void
290 {
291  SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
292  if (data) {
293  [data->viewcontroller release];
294  [data->uiwindow release];
295  SDL_free(data);
296  window->driverdata = NULL;
297  }
298 }
299 
300 SDL_bool
302 {
303  UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
304 
305  if (info->version.major <= SDL_MAJOR_VERSION) {
306  info->subsystem = SDL_SYSWM_UIKIT;
307  info->info.uikit.window = uiwindow;
308  return SDL_TRUE;
309  } else {
310  SDL_SetError("Application not compiled with SDL %d.%d\n",
312  return SDL_FALSE;
313  }
314 }
315 
316 int
317 SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam)
318 {
319  SDL_WindowData *data = window ? (SDL_WindowData *)window->driverdata : NULL;
320 
321  if (!data || !data->view) {
322  return SDL_SetError("Invalid window or view not set");
323  }
324 
325  [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
326  return 0;
327 }
328 
329 #endif /* SDL_VIDEO_DRIVER_UIKIT */
330 
331 /* vi: set ts=4 sw=4 expandtab: */
void(* GetDisplayModes)(_THIS, SDL_VideoDisplay *display)
Definition: SDL_sysvideo.h:169
SDL_Window * next
Definition: SDL_sysvideo.h:102
#define SDL_MINOR_VERSION
Definition: SDL_version.h:61
SDL_bool UIKit_GetWindowWMInfo(_THIS, SDL_Window *window, struct SDL_SysWMinfo *info)
int UIKit_CreateWindow(_THIS, SDL_Window *window)
void UIKit_DestroyWindow(_THIS, SDL_Window *window)
#define NULL
Definition: ftobjs.h:61
int(* GL_MakeCurrent)(_THIS, SDL_Window *window, SDL_GLContext context)
Definition: SDL_sysvideo.h:226
#define SDL_MAJOR_VERSION
Definition: SDL_version.h:60
SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen)
SDL_bool
Definition: SDL_stdinc.h:116
SDL_uikitviewcontroller * viewcontroller
DECLSPEC void SDLCALL SDL_free(void *mem)
The structure that defines a display mode.
Definition: SDL_video.h:53
SDL_version version
Definition: SDL_syswm.h:161
Uint8 major
Definition: SDL_version.h:53
EGLSurface EGLint EGLint EGLint EGLint height
Definition: eglext.h:293
void UIKit_RaiseWindow(_THIS, SDL_Window *window)
SDL_SYSWM_TYPE subsystem
Definition: SDL_syswm.h:162
id initWithSDLWindow:(SDL_Window *_window)
void UIKit_HideWindow(_THIS, SDL_Window *window)
char * display
Definition: visualinfo.c:85
if(!yyg->yy_init)
static SDL_VideoDevice * _this
Definition: SDL_video.c:92
UIScreen * uiscreen
SDL_GLContext current_glctx
Definition: SDL_sysvideo.h:308
int
Definition: SDL_systhread.c:37
void UIKit_SetWindowFullscreen(_THIS, SDL_Window *window, SDL_VideoDisplay *display, SDL_bool fullscreen)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl2ext.h:848
EGLSurface EGLint EGLint EGLint width
Definition: eglext.h:293
#define _THIS
void * driverdata
Definition: SDL_video.h:59
SDL_DisplayMode * display_modes
Definition: SDL_sysvideo.h:118
SDL_DisplayMode current_mode
Definition: SDL_sysvideo.h:120
DECLSPEC int SDLCALL SDL_SetError(const char *fmt,...)
Definition: SDL_error.c:53
DECLSPEC void *SDLCALL SDL_malloc(size_t size)
SDL_Window * windows
Definition: SDL_sysvideo.h:266
UIWindow * uiwindow
union SDL_SysWMinfo::@78 info
#define SDL_assert(condition)
Definition: SDL_assert.h:159
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
UIScreenMode * uiscreenmode
SDL_VideoDisplay * SDL_GetDisplayForWindow(SDL_Window *window)
Definition: SDL_video.c:996
BOOL SDL_UIKit_supports_multiple_displays
void * driverdata
Definition: SDL_sysvideo.h:99
int i
Definition: pngrutil.c:1377
void UIKit_ShowWindow(_THIS, SDL_Window *window)
Uint32 flags
Definition: SDL_sysvideo.h:81
SDL_Window * current_glwin
Definition: SDL_sysvideo.h:307
GLenum mode
Definition: glew.h:2394
SDL_uikitopenglview * view
typedef BOOL(WINAPI *PFNWGLSETSTEREOEMITTERSTATE3DLPROC)(HDC hDC