~ubuntu-branches/ubuntu/maverick/pygame/maverick

« back to all changes in this revision

Viewing changes to src/sdlmain_osx.m

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-01-14 17:02:11 UTC
  • mfrom: (1.3.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100114170211-21eop2ja7mr9vdcr
Tags: 1.9.1release-0ubuntu1
* New upstream version (lp: #433304)
* debian/control:
  - build-depends on libportmidi-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    pygame - Python Game Library
 
3
    Copyright (C) 2009 Brian Fisher
 
4
 
 
5
    This library is free software; you can redistribute it and/or
 
6
    modify it under the terms of the GNU Library General Public
 
7
    License as published by the Free Software Foundation; either
 
8
    version 2 of the License, or (at your option) any later version.
 
9
 
 
10
    This library is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
    Library General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU Library General Public
 
16
    License along with this library; if not, write to the Free
 
17
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
*/
 
19
 
 
20
/* Mac OS X functions to accommodate the fact SDLMain.m is not included */
 
21
 
 
22
#include "pygame.h"
 
23
 
 
24
#include <Carbon/Carbon.h>
 
25
#include <Foundation/Foundation.h>
 
26
#include <AppKit/NSApplication.h>
 
27
#include <AppKit/NSMenuItem.h>
 
28
#include <AppKit/NSMenu.h>
 
29
#include <AppKit/NSEvent.h>
 
30
#include <Foundation/NSData.h>
 
31
#include <AppKit/NSImage.h>
 
32
 
 
33
#include "pgcompat.h"
 
34
 
 
35
struct CPSProcessSerNum
 
36
{
 
37
        UInt32 lo;
 
38
        UInt32 hi;
 
39
};
 
40
typedef struct CPSProcessSerNum CPSProcessSerNum;
 
41
 
 
42
extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
 
43
extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
 
44
extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
 
45
extern OSErr CPSSetProcessName ( CPSProcessSerNum *psn, const char *processname );
 
46
 
 
47
static bool HasInstalledApplication = 0;
 
48
 
 
49
static NSString *getApplicationName(void)
 
50
{
 
51
    const NSDictionary *dict;
 
52
    NSString *appName = 0;
 
53
 
 
54
    /* Determine the application name */
 
55
    dict = (const NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle());
 
56
    if (dict)
 
57
        appName = [dict objectForKey: @"CFBundleName"];
 
58
    
 
59
    if (![appName length])
 
60
        appName = [[NSProcessInfo processInfo] processName];
 
61
 
 
62
    return appName;
 
63
}
 
64
 
 
65
static PyObject*
 
66
_WMEnable(PyObject* self)
 
67
{
 
68
        CPSProcessSerNum psn;
 
69
    OSErr err;
 
70
    const char* nameString;
 
71
    NSString* nameNSString;
 
72
    
 
73
    err = CPSGetCurrentProcess(&psn);
 
74
    if (err == 0)
 
75
    {
 
76
        nameNSString = getApplicationName();
 
77
        nameString = [nameNSString UTF8String];
 
78
        CPSSetProcessName(&psn, nameString);
 
79
 
 
80
        err = CPSEnableForegroundOperation(&psn,0x03,0x3C,0x2C,0x1103);
 
81
        if (err == 0)
 
82
        {
 
83
                err = CPSSetFrontProcess(&psn);
 
84
                if (err != 0)
 
85
                {
 
86
                return RAISE (PyExc_SDLError, "CPSSetFrontProcess failed");                     
 
87
                }
 
88
        }
 
89
        else
 
90
        {
 
91
                return RAISE (PyExc_SDLError, "CPSEnableForegroundOperation failed");
 
92
        }
 
93
    }
 
94
    else
 
95
    {
 
96
        return RAISE (PyExc_SDLError, "CPSGetCurrentProcess failed");
 
97
    }
 
98
    
 
99
    Py_RETURN_TRUE;
 
100
}
 
101
 
 
102
static PyObject*
 
103
_RunningFromBundleWithNSApplication(PyObject* self)
 
104
{
 
105
        if (HasInstalledApplication)
 
106
        {
 
107
                Py_RETURN_TRUE;
 
108
        }
 
109
        CFBundleRef MainBundle = CFBundleGetMainBundle();
 
110
        if (MainBundle != NULL)
 
111
        {
 
112
                if (CFBundleGetDataPointerForName(MainBundle, CFSTR("NSApp")) != NULL)
 
113
                {
 
114
                        Py_RETURN_TRUE;
 
115
                }
 
116
        }
 
117
    Py_RETURN_FALSE;
 
118
}
 
119
 
 
120
//#############################################################################
 
121
// Defining the NSApplication class we will use
 
122
//#############################################################################
 
123
@interface SDLApplication : NSApplication
 
124
@end
 
125
 
 
126
/* For some reaon, Apple removed setAppleMenu from the headers in 10.4,
 
127
 but the method still is there and works. To avoid warnings, we declare
 
128
 it ourselves here. */
 
129
@interface NSApplication(SDL_Missing_Methods)
 
130
- (void)setAppleMenu:(NSMenu *)menu;
 
131
@end
 
132
 
 
133
@implementation SDLApplication
 
134
/* Invoked from the Quit menu item */
 
135
- (void)terminate:(id)sender
 
136
{
 
137
    SDL_Event event;
 
138
    event.type = SDL_QUIT;
 
139
    SDL_PushEvent(&event);
 
140
}
 
141
@end
 
142
 
 
143
static void setApplicationMenu(void)
 
144
{
 
145
    NSMenu *appleMenu;
 
146
    NSMenuItem *menuItem;
 
147
    NSString *title;
 
148
    NSString *appName;
 
149
    
 
150
    appName = getApplicationName();
 
151
    appleMenu = [[NSMenu alloc] initWithTitle:@""];
 
152
    
 
153
 
 
154
    title = [@"About " stringByAppendingString:appName];
 
155
    [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
 
156
 
 
157
    [appleMenu addItem:[NSMenuItem separatorItem]];
 
158
 
 
159
    title = [@"Hide " stringByAppendingString:appName];
 
160
    [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"];
 
161
 
 
162
    menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"];
 
163
    [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)];
 
164
 
 
165
    [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""];
 
166
 
 
167
    [appleMenu addItem:[NSMenuItem separatorItem]];
 
168
 
 
169
    title = [@"Quit " stringByAppendingString:appName];
 
170
    [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
 
171
 
 
172
    
 
173
    menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
 
174
    [menuItem setSubmenu:appleMenu];
 
175
    [[NSApp mainMenu] addItem:menuItem];
 
176
 
 
177
    [NSApp setAppleMenu:appleMenu];
 
178
 
 
179
    [appleMenu release];
 
180
    [menuItem release];
 
181
}
 
182
 
 
183
static void setupWindowMenu(void)
 
184
{
 
185
    NSMenu      *windowMenu;
 
186
    NSMenuItem  *windowMenuItem;
 
187
    NSMenuItem  *menuItem;
 
188
 
 
189
    windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
 
190
    
 
191
    menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
 
192
    [windowMenu addItem:menuItem];
 
193
    [menuItem release];
 
194
    
 
195
    windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
 
196
    [windowMenuItem setSubmenu:windowMenu];
 
197
    [[NSApp mainMenu] addItem:windowMenuItem];
 
198
    
 
199
    [NSApp setWindowsMenu:windowMenu];
 
200
 
 
201
    [windowMenu release];
 
202
    [windowMenuItem release];
 
203
}
 
204
 
 
205
static PyObject*
 
206
_InstallNSApplication(PyObject* self, PyObject* arg)
 
207
{
 
208
    char* icon_data = NULL;
 
209
    int data_len = 0;
 
210
 
 
211
    NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];
 
212
 
 
213
    [SDLApplication sharedApplication];
 
214
 
 
215
    if (PyArg_ParseTuple (arg, "|z#", &icon_data, &data_len))
 
216
    {
 
217
        NSData *image_data = [NSData dataWithBytes:icon_data length:data_len];
 
218
            NSImage *icon_img = [[NSImage alloc] initWithData:image_data];
 
219
            if (icon_img != NULL)
 
220
            {
 
221
                [NSApp setApplicationIconImage:icon_img];
 
222
            }
 
223
    }
 
224
 
 
225
    [NSApp setMainMenu:[[NSMenu alloc] init]];
 
226
    setApplicationMenu();
 
227
    setupWindowMenu();
 
228
 
 
229
    [NSApp finishLaunching];
 
230
    [NSApp updateWindows];
 
231
    [NSApp activateIgnoringOtherApps:true];
 
232
 
 
233
    HasInstalledApplication = 1;
 
234
    
 
235
        Py_RETURN_TRUE;
 
236
}
 
237
 
 
238
static PyMethodDef macosx_builtins[] =
 
239
{
 
240
    { "WMEnable", (PyCFunction) _WMEnable, METH_NOARGS, "Enables Foreground Operation when Window Manager is not available" },
 
241
    { "RunningFromBundleWithNSApplication", (PyCFunction) _RunningFromBundleWithNSApplication, METH_NOARGS, "Returns true if we are running from an AppBundle with a variable named NSApp" },
 
242
    { "InstallNSApplication", _InstallNSApplication, METH_VARARGS, "Creates an NSApplication with the right behaviors for SDL" },
 
243
    { NULL, NULL, 0, NULL}
 
244
};
 
245
 
 
246
 
 
247
 
 
248
MODINIT_DEFINE (sdlmain_osx)
 
249
{
 
250
    PyObject *module;
 
251
 
 
252
    /* create the module */
 
253
 
 
254
#if PY3
 
255
    static struct PyModuleDef _module = {
 
256
        PyModuleDef_HEAD_INIT,
 
257
        MODPREFIX "sdlmain_osx",
 
258
        NULL,
 
259
        -1,
 
260
        macosx_builtins,
 
261
        NULL, NULL, NULL, NULL
 
262
    };
 
263
#endif
 
264
 
 
265
 
 
266
#if PY3
 
267
    module = PyModule_Create (&_module);
 
268
#else
 
269
    module = Py_InitModule3 (MODPREFIX "sdlmain_osx", macosx_builtins, NULL);
 
270
#endif
 
271
 
 
272
 
 
273
    /*imported needed apis*/
 
274
    import_pygame_base ();
 
275
    if (PyErr_Occurred ()) {
 
276
        MODINIT_ERROR;
 
277
    }
 
278
 
 
279
 
 
280
    MODINIT_RETURN (module);
 
281
}