| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
- 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_syswm.h"
- #include "SDL_video.h"
- #include "SDL_mouse.h"
- #include "SDL_assert.h"
- #include "SDL_hints.h"
- #include "../SDL_sysvideo.h"
- #include "../SDL_pixels_c.h"
- #include "../../events/SDL_events_c.h"
- #include "SDL_uikitvideo.h"
- #include "SDL_uikitevents.h"
- #include "SDL_uikitmodes.h"
- #include "SDL_uikitwindow.h"
- #import "SDL_uikitappdelegate.h"
- #import "SDL_uikitopenglview.h"
- #include <Foundation/Foundation.h>
- static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bool created)
- {
- SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
- SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
- SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
- SDL_WindowData *data;
- /* Allocate the window data */
- data = (SDL_WindowData *)SDL_malloc(sizeof(*data));
- if (!data) {
- return SDL_OutOfMemory();
- }
- data->uiwindow = uiwindow;
- data->viewcontroller = nil;
- data->view = nil;
- /* Fill in the SDL window with the window data */
- {
- window->x = 0;
- window->y = 0;
- CGRect bounds;
- if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
- bounds = [displaydata->uiscreen bounds];
- } else {
- bounds = [displaydata->uiscreen applicationFrame];
- }
- /* Get frame dimensions in pixels */
- int width = (int)(bounds.size.width * displaymodedata->scale);
- int height = (int)(bounds.size.height * displaymodedata->scale);
- /* Make sure the width/height are oriented correctly */
- if (UIKit_IsDisplayLandscape(displaydata->uiscreen) != (width > height)) {
- int temp = width;
- width = height;
- height = temp;
- }
- window->w = width;
- window->h = height;
- }
- window->driverdata = data;
- /* only one window on iOS, always shown */
- window->flags &= ~SDL_WINDOW_HIDDEN;
- /* SDL_WINDOW_BORDERLESS controls whether status bar is hidden.
- * This is only set if the window is on the main screen. Other screens
- * just force the window to have the borderless flag.
- */
- if (displaydata->uiscreen == [UIScreen mainScreen]) {
- window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */
- /* This was setup earlier for our window, and in iOS 7 is controlled by the view, not the application
- if ([UIApplication sharedApplication].statusBarHidden) {
- window->flags |= SDL_WINDOW_BORDERLESS;
- } else {
- window->flags &= ~SDL_WINDOW_BORDERLESS;
- }
- */
- } else {
- window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizeable */
- window->flags &= ~SDL_WINDOW_INPUT_FOCUS; /* never has input focus */
- window->flags |= SDL_WINDOW_BORDERLESS; /* never has a status bar. */
- }
- /* The View Controller will handle rotating the view when the
- * device orientation changes. This will trigger resize events, if
- * appropriate.
- */
- SDL_uikitviewcontroller *controller;
- controller = [SDL_uikitviewcontroller alloc];
- data->viewcontroller = [controller initWithSDLWindow:window];
- [data->viewcontroller setTitle:@"SDL App"]; /* !!! FIXME: hook up SDL_SetWindowTitle() */
- return 0;
- }
- int
- UIKit_CreateWindow(_THIS, SDL_Window *window)
- {
- SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
- SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
- const BOOL external = ([UIScreen mainScreen] != data->uiscreen);
- /* SDL currently puts this window at the start of display's linked list. We rely on this. */
- SDL_assert(_this->windows == window);
- /* We currently only handle a single window per display on iOS */
- if (window->next != NULL) {
- return SDL_SetError("Only one window allowed per display.");
- }
- /* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
- * user, so it's in standby), try to force the display to a resolution
- * that most closely matches the desired window size.
- */
- if (SDL_UIKit_supports_multiple_displays) {
- const CGSize origsize = [[data->uiscreen currentMode] size];
- if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
- if (display->num_display_modes == 0) {
- _this->GetDisplayModes(_this, display);
- }
- int i;
- const SDL_DisplayMode *bestmode = NULL;
- for (i = display->num_display_modes; i >= 0; i--) {
- const SDL_DisplayMode *mode = &display->display_modes[i];
- if ((mode->w >= window->w) && (mode->h >= window->h))
- bestmode = mode;
- }
- if (bestmode) {
- SDL_DisplayModeData *modedata = (SDL_DisplayModeData *)bestmode->driverdata;
- [data->uiscreen setCurrentMode:modedata->uiscreenmode];
- /* desktop_mode doesn't change here (the higher level will
- * use it to set all the screens back to their defaults
- * upon window destruction, SDL_Quit(), etc.
- */
- display->current_mode = *bestmode;
- }
- }
- }
- if (data->uiscreen == [UIScreen mainScreen]) {
- if (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) {
- [UIApplication sharedApplication].statusBarHidden = YES;
- } else {
- [UIApplication sharedApplication].statusBarHidden = NO;
- }
- }
- if (!(window->flags & SDL_WINDOW_RESIZABLE)) {
- if (window->w > window->h) {
- if (!UIKit_IsDisplayLandscape(data->uiscreen)) {
- [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:NO];
- }
- } else if (window->w < window->h) {
- if (UIKit_IsDisplayLandscape(data->uiscreen)) {
- [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
- }
- }
- }
- /* ignore the size user requested, and make a fullscreen window */
- /* !!! FIXME: can we have a smaller view? */
- UIWindow *uiwindow = [UIWindow alloc];
- uiwindow = [uiwindow initWithFrame:[data->uiscreen bounds]];
- /* put the window on an external display if appropriate. This implicitly
- * does [uiwindow setframe:[uiscreen bounds]], so don't do it on the
- * main display, where we land by default, as that would eat the
- * status bar real estate.
- */
- if (external) {
- [uiwindow setScreen:data->uiscreen];
- }
- if (SetupWindowData(_this, window, uiwindow, SDL_TRUE) < 0) {
- [uiwindow release];
- return -1;
- }
- return 1;
- }
- void
- UIKit_ShowWindow(_THIS, SDL_Window * window)
- {
- UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
- [uiwindow makeKeyAndVisible];
- }
- void
- UIKit_HideWindow(_THIS, SDL_Window * window)
- {
- UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
- uiwindow.hidden = YES;
- }
- void
- UIKit_RaiseWindow(_THIS, SDL_Window * window)
- {
- /* We don't currently offer a concept of "raising" the SDL window, since
- * we only allow one per display, in the iOS fashion.
- * However, we use this entry point to rebind the context to the view
- * during OnWindowRestored processing.
- */
- _this->GL_MakeCurrent(_this, _this->current_glwin, _this->current_glctx);
- }
- void
- UIKit_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
- {
- SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
- SDL_DisplayModeData *displaymodedata = (SDL_DisplayModeData *) display->current_mode.driverdata;
- UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
- if (fullscreen) {
- [UIApplication sharedApplication].statusBarHidden = YES;
- } else {
- [UIApplication sharedApplication].statusBarHidden = NO;
- }
- CGRect bounds;
- if (fullscreen) {
- bounds = [displaydata->uiscreen bounds];
- } else {
- bounds = [displaydata->uiscreen applicationFrame];
- }
- /* Get frame dimensions in pixels */
- int width = (int)(bounds.size.width * displaymodedata->scale);
- int height = (int)(bounds.size.height * displaymodedata->scale);
- /* We can pick either width or height here and we'll rotate the
- screen to match, so we pick the closest to what we wanted.
- */
- if (window->w >= window->h) {
- if (width > height) {
- window->w = width;
- window->h = height;
- } else {
- window->w = height;
- window->h = width;
- }
- } else {
- if (width > height) {
- window->w = height;
- window->h = width;
- } else {
- window->w = width;
- window->h = height;
- }
- }
- }
- void
- UIKit_DestroyWindow(_THIS, SDL_Window * window)
- {
- SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
- if (data) {
- [data->viewcontroller release];
- [data->uiwindow release];
- SDL_free(data);
- window->driverdata = NULL;
- }
- }
- SDL_bool
- UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
- {
- UIWindow *uiwindow = ((SDL_WindowData *) window->driverdata)->uiwindow;
- if (info->version.major <= SDL_MAJOR_VERSION) {
- info->subsystem = SDL_SYSWM_UIKIT;
- info->info.uikit.window = uiwindow;
- return SDL_TRUE;
- } else {
- SDL_SetError("Application not compiled with SDL %d.%d\n",
- SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
- return SDL_FALSE;
- }
- }
- int
- SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam)
- {
- SDL_WindowData *data = window ? (SDL_WindowData *)window->driverdata : NULL;
- if (!data || !data->view) {
- return SDL_SetError("Invalid window or view not set");
- }
- [data->view setAnimationCallback:interval callback:callback callbackParam:callbackParam];
- return 0;
- }
- #endif /* SDL_VIDEO_DRIVER_UIKIT */
- /* vi: set ts=4 sw=4 expandtab: */
|