]> git.saurik.com Git - wxWidgets.git/blame - src/cocoa/app.mm
free the DIB for raw bitmaps even if they don't use alpha channel
[wxWidgets.git] / src / cocoa / app.mm
CommitLineData
fb896a32
DE
1/////////////////////////////////////////////////////////////////////////////
2// Name: cocoa/app.mm
3// Purpose: wxApp
4// Author: David Elliott
5// Modified by:
6// Created: 2002/11/27
d89d4059 7// RCS-ID: $Id$
fb896a32 8// Copyright: (c) David Elliott
d89d4059 9// Licence: wxWindows licence
fb896a32
DE
10/////////////////////////////////////////////////////////////////////////////
11
fb896a32
DE
12#include "wx/wxprec.h"
13#ifndef WX_PRECOMP
14 #include "wx/defs.h"
15 #include "wx/app.h"
16 #include "wx/frame.h"
17 #include "wx/dialog.h"
891d0563 18 #include "wx/dc.h"
fb896a32
DE
19 #include "wx/intl.h"
20 #include "wx/log.h"
fb896a32
DE
21#endif
22
11c08416
DE
23#include "wx/module.h"
24
fb45bb1f 25#include "wx/cocoa/ObjcPose.h"
493902ac 26#include "wx/cocoa/autorelease.h"
af367f46 27#include "wx/cocoa/mbarman.h"
fb45bb1f 28
fb896a32
DE
29#if wxUSE_WX_RESOURCES
30# include "wx/resource.h"
31#endif
32
33#import <AppKit/NSApplication.h>
34#import <Foundation/NSRunLoop.h>
35#import <Foundation/NSArray.h>
47f1ad6a 36#import <Foundation/NSAutoreleasePool.h>
14fc7eb4 37#import <Foundation/NSThread.h>
aaa5ab05 38#import <AppKit/NSEvent.h>
fb896a32 39
70fb935a
DE
40// ========================================================================
41// wxPoseAsInitializer
42// ========================================================================
fb896a32
DE
43wxPoseAsInitializer *wxPoseAsInitializer::sm_first = NULL;
44
70fb935a
DE
45// ========================================================================
46// wxPoserNSApplication
47// ========================================================================
fb896a32
DE
48@interface wxPoserNSApplication : NSApplication
49{
50}
51
fb896a32 52- (void)sendEvent: (NSEvent*)anEvent;
fb896a32
DE
53@end // wxPoserNSApplication
54
70fb935a
DE
55WX_IMPLEMENT_POSER(wxPoserNSApplication);
56
fb896a32
DE
57@implementation wxPoserNSApplication : NSApplication
58
ba808e24
DE
59- (void)sendEvent: (NSEvent*)anEvent
60{
61 wxLogDebug("SendEvent");
62 wxTheApp->CocoaInstallRequestedIdleHandler();
63 [super sendEvent: anEvent];
64}
65
66@end // wxPoserNSApplication
67
68// ========================================================================
69// wxNSApplicationDelegate
70// ========================================================================
71@interface wxNSApplicationDelegate : NSObject
72{
73}
74
75- (void)doIdle: (id)data;
76// Delegate methods
77- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication;
78- (void)applicationWillBecomeActive:(NSNotification *)notification;
79- (void)applicationDidBecomeActive:(NSNotification *)notification;
80- (void)applicationWillResignActive:(NSNotification *)notification;
81- (void)applicationDidResignActive:(NSNotification *)notification;
82@end // interface wxNSApplicationDelegate : NSObject
83
84@implementation wxNSApplicationDelegate : NSObject
85
fb896a32
DE
86- (void)doIdle: (id)data
87{
88 wxASSERT(wxTheApp);
af367f46
DE
89 wxASSERT(wxMenuBarManager::GetInstance());
90 wxMenuBarManager::GetInstance()->CocoaInternalIdle();
fb896a32 91 wxLogDebug("doIdle called");
b93d8cc4
DE
92#ifdef __WXDEBUG__
93 if(wxTheApp->IsInAssert())
fb896a32 94 {
b93d8cc4
DE
95 wxLogDebug("Idle events ignored durring assertion dialog");
96 }
97 else
98#endif
99 {
100 NSRunLoop *rl = [NSRunLoop currentRunLoop];
101 // runMode: beforeDate returns YES if something was done
102 while(wxTheApp->ProcessIdle()) // FIXME: AND NO EVENTS ARE PENDING
fb896a32 103 {
b93d8cc4
DE
104 wxLogDebug("Looping for idle events");
105 #if 1
106 if( [rl runMode:[rl currentMode] beforeDate:[NSDate distantPast]])
107 {
108 wxLogDebug("Found actual work to do");
109 break;
110 }
111 #endif
fb896a32 112 }
fb896a32
DE
113 }
114 wxLogDebug("Idle processing complete, requesting next idle event");
115 // Add ourself back into the run loop (on next event) if necessary
116 wxTheApp->CocoaRequestIdle();
117}
118
2990ec97
DE
119// NOTE: Terminate means that the event loop does NOT return and thus
120// cleanup code doesn't properly execute. Furthermore, wxWindows has its
121// own exit on frame delete mechanism.
fb896a32
DE
122- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
123{
2990ec97 124 return NO;
fb896a32
DE
125}
126
0187ddb4
DE
127- (void)applicationWillBecomeActive:(NSNotification *)notification
128{
129 wxTheApp->CocoaDelegate_applicationWillBecomeActive();
130}
131
132- (void)applicationDidBecomeActive:(NSNotification *)notification
133{
134 wxTheApp->CocoaDelegate_applicationDidBecomeActive();
135}
136
137- (void)applicationWillResignActive:(NSNotification *)notification
138{
139 wxTheApp->CocoaDelegate_applicationWillResignActive();
140}
141
142- (void)applicationDidResignActive:(NSNotification *)notification
143{
144 wxTheApp->CocoaDelegate_applicationDidResignActive();
145}
146
147@end // implementation wxNSApplicationDelegate : NSObject
e2478fde 148
70fb935a
DE
149// ========================================================================
150// wxApp
151// ========================================================================
fb896a32
DE
152
153// ----------------------------------------------------------------------------
154// wxApp Static member initialization
155// ----------------------------------------------------------------------------
fb896a32
DE
156IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
157BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
955a9197 158 EVT_IDLE(wxAppBase::OnIdle)
fb896a32
DE
159// EVT_END_SESSION(wxApp::OnEndSession)
160// EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
161END_EVENT_TABLE()
fb896a32
DE
162
163// ----------------------------------------------------------------------------
05e2b077 164// wxApp initialization/cleanup
fb896a32 165// ----------------------------------------------------------------------------
05e2b077 166bool wxApp::Initialize(int& argc, wxChar **argv)
fb896a32 167{
47f1ad6a 168 wxAutoNSAutoreleasePool pool;
14fc7eb4 169 m_cocoaMainThread = [NSThread currentThread];
05e2b077
VZ
170 // Mac OS X passes a process serial number command line argument when
171 // the application is launched from the Finder. This argument must be
172 // removed from the command line arguments before being handled by the
173 // application (otherwise applications would need to handle it)
174 if ( argc > 1 )
175 {
176 static const wxChar *ARG_PSN = _T("-psn_");
177 if ( wxStrncmp(argv[1], ARG_PSN, sizeof(ARG_PSN) - 1) == 0 )
178 {
179 // remove this argument
180 memmove(argv, argv + 1, argc--);
181 }
182 }
183
28ce3086
DE
184 // Posing must be completed before any instances of the Objective-C
185 // classes being posed as are created.
fb896a32 186 wxPoseAsInitializer::InitializePosers();
fb896a32 187
94826170 188 return wxAppBase::Initialize(argc, argv);
fb896a32
DE
189}
190
94826170 191void wxApp::CleanUp()
fb896a32 192{
0187ddb4
DE
193 wxAutoNSAutoreleasePool pool;
194
891d0563 195 wxDC::CocoaShutdownTextSystem();
af367f46 196 wxMenuBarManager::DestroyInstance();
94826170 197
0187ddb4
DE
198 [m_cocoaApp setDelegate:nil];
199 [m_cocoaAppDelegate release];
200 m_cocoaAppDelegate = NULL;
201
94826170 202 wxAppBase::CleanUp();
fb896a32
DE
203}
204
205// ----------------------------------------------------------------------------
206// wxApp creation
207// ----------------------------------------------------------------------------
fb896a32
DE
208wxApp::wxApp()
209{
210 m_topWindow = NULL;
fb896a32
DE
211
212 m_isIdle = true;
213#if WXWIN_COMPATIBILITY_2_2
214 m_wantDebugOutput = TRUE;
215#endif
b93d8cc4
DE
216#ifdef __WXDEBUG__
217 m_isInAssert = FALSE;
218#endif // __WXDEBUG__
219
fb896a32
DE
220 argc = 0;
221 argv = NULL;
222 m_cocoaApp = NULL;
0187ddb4 223 m_cocoaAppDelegate = NULL;
fb896a32
DE
224}
225
226void wxApp::CocoaInstallIdleHandler()
227{
14fc7eb4
DE
228 // If we're not the main thread, don't install the idle handler
229 if(m_cocoaMainThread != [NSThread currentThread])
230 {
231 wxLogDebug("Attempt to install idle handler from secondary thread");
232 return;
233 }
bc34fa26
DE
234 // If we're supposed to be stopping, don't add more idle events
235 if(![m_cocoaApp isRunning])
236 return;
fb896a32
DE
237 wxLogDebug("wxApp::CocoaInstallIdleHandler");
238 m_isIdle = false;
239 // Call doIdle for EVERYTHING dammit
240// We'd need Foundation/NSConnection.h for this next constant, do we need it?
ba808e24 241 [[ NSRunLoop currentRunLoop ] performSelector:@selector(doIdle:) target:m_cocoaAppDelegate argument:NULL order:0 modes:[NSArray arrayWithObjects:NSDefaultRunLoopMode, /* NSConnectionReplyRunLoopMode,*/ NSModalPanelRunLoopMode, /**/NSEventTrackingRunLoopMode,/**/ nil] ];
59d6b6a9
DE
242 /* Notes:
243 In the Mac OS X implementation of Cocoa, the above method schedules
244 doIdle: to be called from *within* [NSApplication
245 -nextEventMatchingMask:untilDate:inMode:dequeue:]. That is, no
246 NSEvent object is generated and control does not return from that
247 method. In fact, control will only return from that method for the
248 usual reasons (e.g. a real event is received or the untilDate is reached).
249 This has implications when trying to stop the event loop and return to
250 its caller. See wxEventLoop::Exit
251 */
fb896a32
DE
252}
253
0187ddb4
DE
254void wxApp::CocoaDelegate_applicationWillBecomeActive()
255{
256}
257
258void wxApp::CocoaDelegate_applicationDidBecomeActive()
259{
260}
261
262void wxApp::CocoaDelegate_applicationWillResignActive()
263{
264}
265
266void wxApp::CocoaDelegate_applicationDidResignActive()
267{
268}
269
fb896a32
DE
270bool wxApp::OnInitGui()
271{
47f1ad6a 272 wxAutoNSAutoreleasePool pool;
fb896a32
DE
273 if(!wxAppBase::OnInitGui())
274 return FALSE;
275
276 // Create the app using the sharedApplication method
277 m_cocoaApp = [NSApplication sharedApplication];
0187ddb4
DE
278 m_cocoaAppDelegate = [[wxNSApplicationDelegate alloc] init];
279 [m_cocoaApp setDelegate:m_cocoaAppDelegate];
af367f46
DE
280
281 wxMenuBarManager::CreateInstance();
282
891d0563 283 wxDC::CocoaInitializeTextSystem();
fb896a32
DE
284// [ m_cocoaApp setDelegate:m_cocoaApp ];
285 #if 0
286 wxLogDebug("Just for kicks");
ba808e24 287 [ m_cocoaAppDelegate performSelector:@selector(doIdle:) withObject:NULL ];
fb896a32
DE
288 wxLogDebug("okay.. done now");
289 #endif
290 return TRUE;
291}
292
47f1ad6a
DE
293bool wxApp::CallOnInit()
294{
bd3e8827 295// wxAutoNSAutoreleasePool pool;
47f1ad6a
DE
296 return OnInit();
297}
298
fb896a32
DE
299bool wxApp::OnInit()
300{
301 if(!wxAppBase::OnInit())
302 return FALSE;
303
304 return TRUE;
305}
306
70fb935a
DE
307void wxApp::Exit()
308{
309 wxApp::CleanUp();
310
311 wxAppConsole::Exit();
312}
313
fb896a32 314// Yield to other processes
fb896a32
DE
315bool wxApp::Yield(bool onlyIfNeeded)
316{
317 // MT-FIXME
318 static bool s_inYield = false;
319
320#if wxUSE_LOG
321 // disable log flushing from here because a call to wxYield() shouldn't
322 // normally result in message boxes popping up &c
323 wxLog::Suspend();
324#endif // wxUSE_LOG
325
326 if (s_inYield)
327 {
328 if ( !onlyIfNeeded )
329 {
330 wxFAIL_MSG( wxT("wxYield called recursively" ) );
331 }
332
333 return false;
334 }
335
336 s_inYield = true;
337
aaa5ab05
DE
338 // Run the event loop until it is out of events
339 while(NSEvent *event = [GetNSApplication()
340 nextEventMatchingMask:NSAnyEventMask
341 untilDate:[NSDate distantPast]
342 inMode:NSDefaultRunLoopMode
343 dequeue: YES])
344 {
345 [GetNSApplication() sendEvent: event];
346 }
fb896a32
DE
347
348#if wxUSE_LOG
349 // let the logs be flashed again
350 wxLog::Resume();
351#endif // wxUSE_LOG
352
353 s_inYield = false;
354
355 return true;
356}
357
b93d8cc4
DE
358#ifdef __WXDEBUG__
359void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg)
360{
361 m_isInAssert = TRUE;
362 wxAppBase::OnAssert(file, line, cond, msg);
363 m_isInAssert = FALSE;
364}
365#endif // __WXDEBUG__
366