]> git.saurik.com Git - wxWidgets.git/blame - src/cocoa/app.mm
Fixed tabs (i.e. turning into spaces...)
[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 89 wxASSERT(wxMenuBarManager::GetInstance());
fb896a32 90 wxLogDebug("doIdle called");
b93d8cc4
DE
91#ifdef __WXDEBUG__
92 if(wxTheApp->IsInAssert())
fb896a32 93 {
b93d8cc4
DE
94 wxLogDebug("Idle events ignored durring assertion dialog");
95 }
96 else
97#endif
98 {
99 NSRunLoop *rl = [NSRunLoop currentRunLoop];
100 // runMode: beforeDate returns YES if something was done
101 while(wxTheApp->ProcessIdle()) // FIXME: AND NO EVENTS ARE PENDING
fb896a32 102 {
b93d8cc4
DE
103 wxLogDebug("Looping for idle events");
104 #if 1
105 if( [rl runMode:[rl currentMode] beforeDate:[NSDate distantPast]])
106 {
107 wxLogDebug("Found actual work to do");
108 break;
109 }
110 #endif
fb896a32 111 }
fb896a32
DE
112 }
113 wxLogDebug("Idle processing complete, requesting next idle event");
114 // Add ourself back into the run loop (on next event) if necessary
115 wxTheApp->CocoaRequestIdle();
116}
117
2990ec97
DE
118// NOTE: Terminate means that the event loop does NOT return and thus
119// cleanup code doesn't properly execute. Furthermore, wxWindows has its
120// own exit on frame delete mechanism.
fb896a32
DE
121- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
122{
2990ec97 123 return NO;
fb896a32
DE
124}
125
0187ddb4
DE
126- (void)applicationWillBecomeActive:(NSNotification *)notification
127{
128 wxTheApp->CocoaDelegate_applicationWillBecomeActive();
129}
130
131- (void)applicationDidBecomeActive:(NSNotification *)notification
132{
133 wxTheApp->CocoaDelegate_applicationDidBecomeActive();
134}
135
136- (void)applicationWillResignActive:(NSNotification *)notification
137{
138 wxTheApp->CocoaDelegate_applicationWillResignActive();
139}
140
141- (void)applicationDidResignActive:(NSNotification *)notification
142{
143 wxTheApp->CocoaDelegate_applicationDidResignActive();
144}
145
146@end // implementation wxNSApplicationDelegate : NSObject
e2478fde 147
70fb935a
DE
148// ========================================================================
149// wxApp
150// ========================================================================
fb896a32
DE
151
152// ----------------------------------------------------------------------------
153// wxApp Static member initialization
154// ----------------------------------------------------------------------------
fb896a32
DE
155IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
156BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
955a9197 157 EVT_IDLE(wxAppBase::OnIdle)
fb896a32
DE
158// EVT_END_SESSION(wxApp::OnEndSession)
159// EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
160END_EVENT_TABLE()
fb896a32
DE
161
162// ----------------------------------------------------------------------------
05e2b077 163// wxApp initialization/cleanup
fb896a32 164// ----------------------------------------------------------------------------
05e2b077 165bool wxApp::Initialize(int& argc, wxChar **argv)
fb896a32 166{
47f1ad6a 167 wxAutoNSAutoreleasePool pool;
14fc7eb4 168 m_cocoaMainThread = [NSThread currentThread];
05e2b077
VZ
169 // Mac OS X passes a process serial number command line argument when
170 // the application is launched from the Finder. This argument must be
171 // removed from the command line arguments before being handled by the
172 // application (otherwise applications would need to handle it)
173 if ( argc > 1 )
174 {
175 static const wxChar *ARG_PSN = _T("-psn_");
33f39af3 176 if ( wxStrncmp(argv[1], ARG_PSN, strlen(ARG_PSN)) == 0 )
05e2b077
VZ
177 {
178 // remove this argument
33f39af3
GD
179 --argc;
180 memmove(argv + 1, argv + 2, argc * sizeof(char *));
05e2b077
VZ
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{
39050120 264 wxTopLevelWindowCocoa::DeactivatePendingWindow();
0187ddb4
DE
265}
266
267void wxApp::CocoaDelegate_applicationDidResignActive()
268{
269}
270
fb896a32
DE
271bool wxApp::OnInitGui()
272{
47f1ad6a 273 wxAutoNSAutoreleasePool pool;
fb896a32
DE
274 if(!wxAppBase::OnInitGui())
275 return FALSE;
276
277 // Create the app using the sharedApplication method
278 m_cocoaApp = [NSApplication sharedApplication];
0187ddb4
DE
279 m_cocoaAppDelegate = [[wxNSApplicationDelegate alloc] init];
280 [m_cocoaApp setDelegate:m_cocoaAppDelegate];
af367f46
DE
281
282 wxMenuBarManager::CreateInstance();
283
891d0563 284 wxDC::CocoaInitializeTextSystem();
fb896a32
DE
285// [ m_cocoaApp setDelegate:m_cocoaApp ];
286 #if 0
287 wxLogDebug("Just for kicks");
ba808e24 288 [ m_cocoaAppDelegate performSelector:@selector(doIdle:) withObject:NULL ];
fb896a32
DE
289 wxLogDebug("okay.. done now");
290 #endif
291 return TRUE;
292}
293
47f1ad6a
DE
294bool wxApp::CallOnInit()
295{
bd3e8827 296// wxAutoNSAutoreleasePool pool;
47f1ad6a
DE
297 return OnInit();
298}
299
fb896a32
DE
300bool wxApp::OnInit()
301{
302 if(!wxAppBase::OnInit())
303 return FALSE;
304
305 return TRUE;
306}
307
70fb935a
DE
308void wxApp::Exit()
309{
310 wxApp::CleanUp();
311
312 wxAppConsole::Exit();
313}
314
fb896a32 315// Yield to other processes
fb896a32
DE
316bool wxApp::Yield(bool onlyIfNeeded)
317{
318 // MT-FIXME
319 static bool s_inYield = false;
320
321#if wxUSE_LOG
322 // disable log flushing from here because a call to wxYield() shouldn't
323 // normally result in message boxes popping up &c
324 wxLog::Suspend();
325#endif // wxUSE_LOG
326
327 if (s_inYield)
328 {
329 if ( !onlyIfNeeded )
330 {
331 wxFAIL_MSG( wxT("wxYield called recursively" ) );
332 }
333
334 return false;
335 }
336
337 s_inYield = true;
338
aaa5ab05
DE
339 // Run the event loop until it is out of events
340 while(NSEvent *event = [GetNSApplication()
341 nextEventMatchingMask:NSAnyEventMask
342 untilDate:[NSDate distantPast]
343 inMode:NSDefaultRunLoopMode
344 dequeue: YES])
345 {
346 [GetNSApplication() sendEvent: event];
347 }
fb896a32
DE
348
349#if wxUSE_LOG
350 // let the logs be flashed again
351 wxLog::Resume();
352#endif // wxUSE_LOG
353
354 s_inYield = false;
355
356 return true;
357}
358
b93d8cc4
DE
359#ifdef __WXDEBUG__
360void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg)
361{
362 m_isInAssert = TRUE;
363 wxAppBase::OnAssert(file, line, cond, msg);
364 m_isInAssert = FALSE;
365}
366#endif // __WXDEBUG__
367