1/*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 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_COCOA
24
25#include "SDL.h"
26#include "SDL_endian.h"
27#include "SDL_cocoavideo.h"
28#include "SDL_cocoashape.h"
29#include "SDL_assert.h"
30
31/* Initialization/Query functions */
32static int Cocoa_VideoInit(_THIS);
33static void Cocoa_VideoQuit(_THIS);
34
35/* Cocoa driver bootstrap functions */
36
37static int
38Cocoa_Available(void)
39{
40    return (1);
41}
42
43static void
44Cocoa_DeleteDevice(SDL_VideoDevice * device)
45{
46    SDL_free(device->driverdata);
47    SDL_free(device);
48}
49
50static SDL_VideoDevice *
51Cocoa_CreateDevice(int devindex)
52{
53    SDL_VideoDevice *device;
54    SDL_VideoData *data;
55
56    Cocoa_RegisterApp();
57
58    /* Initialize all variables that we clean on shutdown */
59    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
60    if (device) {
61        data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
62    } else {
63        data = NULL;
64    }
65    if (!data) {
66        SDL_OutOfMemory();
67        SDL_free(device);
68        return NULL;
69    }
70    device->driverdata = data;
71
72    /* Set the function pointers */
73    device->VideoInit = Cocoa_VideoInit;
74    device->VideoQuit = Cocoa_VideoQuit;
75    device->GetDisplayBounds = Cocoa_GetDisplayBounds;
76    device->GetDisplayUsableBounds = Cocoa_GetDisplayUsableBounds;
77    device->GetDisplayDPI = Cocoa_GetDisplayDPI;
78    device->GetDisplayModes = Cocoa_GetDisplayModes;
79    device->SetDisplayMode = Cocoa_SetDisplayMode;
80    device->PumpEvents = Cocoa_PumpEvents;
81    device->SuspendScreenSaver = Cocoa_SuspendScreenSaver;
82
83    device->CreateWindow = Cocoa_CreateWindow;
84    device->CreateWindowFrom = Cocoa_CreateWindowFrom;
85    device->SetWindowTitle = Cocoa_SetWindowTitle;
86    device->SetWindowIcon = Cocoa_SetWindowIcon;
87    device->SetWindowPosition = Cocoa_SetWindowPosition;
88    device->SetWindowSize = Cocoa_SetWindowSize;
89    device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize;
90    device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize;
91    device->SetWindowOpacity = Cocoa_SetWindowOpacity;
92    device->ShowWindow = Cocoa_ShowWindow;
93    device->HideWindow = Cocoa_HideWindow;
94    device->RaiseWindow = Cocoa_RaiseWindow;
95    device->MaximizeWindow = Cocoa_MaximizeWindow;
96    device->MinimizeWindow = Cocoa_MinimizeWindow;
97    device->RestoreWindow = Cocoa_RestoreWindow;
98    device->SetWindowBordered = Cocoa_SetWindowBordered;
99    device->SetWindowResizable = Cocoa_SetWindowResizable;
100    device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
101    device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
102    device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
103    device->SetWindowGrab = Cocoa_SetWindowGrab;
104    device->DestroyWindow = Cocoa_DestroyWindow;
105    device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
106    device->SetWindowHitTest = Cocoa_SetWindowHitTest;
107
108    device->shape_driver.CreateShaper = Cocoa_CreateShaper;
109    device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
110    device->shape_driver.ResizeWindowShape = Cocoa_ResizeWindowShape;
111
112#if SDL_VIDEO_OPENGL_CGL
113    device->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
114    device->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
115    device->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
116    device->GL_CreateContext = Cocoa_GL_CreateContext;
117    device->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
118    device->GL_GetDrawableSize = Cocoa_GL_GetDrawableSize;
119    device->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
120    device->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
121    device->GL_SwapWindow = Cocoa_GL_SwapWindow;
122    device->GL_DeleteContext = Cocoa_GL_DeleteContext;
123#endif
124
125    device->StartTextInput = Cocoa_StartTextInput;
126    device->StopTextInput = Cocoa_StopTextInput;
127    device->SetTextInputRect = Cocoa_SetTextInputRect;
128
129    device->SetClipboardText = Cocoa_SetClipboardText;
130    device->GetClipboardText = Cocoa_GetClipboardText;
131    device->HasClipboardText = Cocoa_HasClipboardText;
132
133    device->free = Cocoa_DeleteDevice;
134
135    return device;
136}
137
138VideoBootStrap COCOA_bootstrap = {
139    "cocoa", "SDL Cocoa video driver",
140    Cocoa_Available, Cocoa_CreateDevice
141};
142
143
144int
145Cocoa_VideoInit(_THIS)
146{
147    SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
148
149    Cocoa_InitModes(_this);
150    Cocoa_InitKeyboard(_this);
151    Cocoa_InitMouse(_this);
152
153    data->allow_spaces = ((floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && SDL_GetHintBoolean(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_TRUE));
154
155    /* The IOPM assertion API can disable the screensaver as of 10.7. */
156    data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
157
158    return 0;
159}
160
161void
162Cocoa_VideoQuit(_THIS)
163{
164    Cocoa_QuitModes(_this);
165    Cocoa_QuitKeyboard(_this);
166    Cocoa_QuitMouse(_this);
167}
168
169/* This function assumes that it's called from within an autorelease pool */
170NSImage *
171Cocoa_CreateImage(SDL_Surface * surface)
172{
173    SDL_Surface *converted;
174    NSBitmapImageRep *imgrep;
175    Uint8 *pixels;
176    int i;
177    NSImage *img;
178
179    converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA32, 0);
180    if (!converted) {
181        return nil;
182    }
183
184    imgrep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
185                    pixelsWide: converted->w
186                    pixelsHigh: converted->h
187                    bitsPerSample: 8
188                    samplesPerPixel: 4
189                    hasAlpha: YES
190                    isPlanar: NO
191                    colorSpaceName: NSDeviceRGBColorSpace
192                    bytesPerRow: converted->pitch
193                    bitsPerPixel: converted->format->BitsPerPixel] autorelease];
194    if (imgrep == nil) {
195        SDL_FreeSurface(converted);
196        return nil;
197    }
198
199    /* Copy the pixels */
200    pixels = [imgrep bitmapData];
201    SDL_memcpy(pixels, converted->pixels, converted->h * converted->pitch);
202    SDL_FreeSurface(converted);
203
204    /* Premultiply the alpha channel */
205    for (i = (surface->h * surface->w); i--; ) {
206        Uint8 alpha = pixels[3];
207        pixels[0] = (Uint8)(((Uint16)pixels[0] * alpha) / 255);
208        pixels[1] = (Uint8)(((Uint16)pixels[1] * alpha) / 255);
209        pixels[2] = (Uint8)(((Uint16)pixels[2] * alpha) / 255);
210        pixels += 4;
211    }
212
213    img = [[[NSImage alloc] initWithSize: NSMakeSize(surface->w, surface->h)] autorelease];
214    if (img != nil) {
215        [img addRepresentation: imgrep];
216    }
217    return img;
218}
219
220/*
221 * Mac OS X log support.
222 *
223 * This doesn't really have aything to do with the interfaces of the SDL video
224 *  subsystem, but we need to stuff this into an Objective-C source code file.
225 */
226
227void SDL_NSLog(const char *text)
228{
229    NSLog(@"%s", text);
230}
231
232#endif /* SDL_VIDEO_DRIVER_COCOA */
233
234/* vim: set ts=4 sw=4 expandtab: */
235