]> git.saurik.com Git - wxWidgets.git/blame - src/cocoa/app.mm
reverted relative include path
[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>
eb537cfb 39#import <Foundation/NSString.h>
fb896a32 40
70fb935a
DE
41// ========================================================================
42// wxPoseAsInitializer
43// ========================================================================
fb896a32
DE
44wxPoseAsInitializer *wxPoseAsInitializer::sm_first = NULL;
45
eb537cfb
DE
46static bool sg_needIdle = true;
47
70fb935a
DE
48// ========================================================================
49// wxPoserNSApplication
50// ========================================================================
fb896a32
DE
51@interface wxPoserNSApplication : NSApplication
52{
53}
54
eb537cfb 55- (NSEvent *)nextEventMatchingMask:(unsigned int)mask untilDate:(NSDate *)expiration inMode:(NSString *)mode dequeue:(BOOL)flag;
fb896a32 56- (void)sendEvent: (NSEvent*)anEvent;
fb896a32
DE
57@end // wxPoserNSApplication
58
70fb935a
DE
59WX_IMPLEMENT_POSER(wxPoserNSApplication);
60
fb896a32
DE
61@implementation wxPoserNSApplication : NSApplication
62
eb537cfb
DE
63/* NOTE: The old method of idle event handling added the handler using the
64 [NSRunLoop -performSelector:target:argument:order:modes] which caused
65 the invocation to occur at the begining of [NSApplication
66 -nextEventMatchingMask:untilDate:expiration:inMode:dequeue:]. However,
67 the code would be scheduled for invocation with every iteration of
68 the event loop. This new method simply overrides the method. The
69 same caveats apply. In particular, by the time the event loop has
70 called this method, it usually expects to receive an event. If you
71 plan on stopping the event loop, it is wise to send an event through
72 the queue to ensure this method will return.
73 See wxEventLoop::Exit() for more information.
74*/
75
76- (NSEvent *)nextEventMatchingMask:(unsigned int)mask untilDate:(NSDate *)expiration inMode:(NSString *)mode dequeue:(BOOL)flag
77{
78 // Get the same events except don't block
79 NSEvent *event = [super nextEventMatchingMask:mask untilDate:nil/* equivalent to [NSDate distantPast] */ inMode:mode dequeue:flag];
80 // If we got one, simply return it
81 if(event)
82 return event;
83 // No events, try doing some idle stuff
84 if(sg_needIdle && !wxTheApp->IsInAssert() && ([NSDefaultRunLoopMode isEqualToString:mode] || [NSModalPanelRunLoopMode isEqualToString:mode]))
85 {
86 sg_needIdle = false;
87 wxLogDebug("Processing idle events");
88 while(wxTheApp->ProcessIdle())
89 {
90 // Get the same events except don't block
91 NSEvent *event = [super nextEventMatchingMask:mask untilDate:nil/* equivalent to [NSDate distantPast] */ inMode:mode dequeue:flag];
92 // If we got one, simply return it
93 if(event)
94 return event;
95 // we didn't get one, do some idle work
96 wxLogDebug("Looping idle events");
97 }
98 // No more idle work requested, block
99 wxLogDebug("Finished idle processing");
100 }
101 else
102 wxLogDebug("Avoiding idle processing sg_needIdle=%d",sg_needIdle);
103 return [super nextEventMatchingMask:mask untilDate:expiration inMode:mode dequeue:flag];
104}
105
ba808e24
DE
106- (void)sendEvent: (NSEvent*)anEvent
107{
108 wxLogDebug("SendEvent");
eb537cfb 109 sg_needIdle = true;
ba808e24
DE
110 [super sendEvent: anEvent];
111}
112
113@end // wxPoserNSApplication
114
115// ========================================================================
116// wxNSApplicationDelegate
117// ========================================================================
118@interface wxNSApplicationDelegate : NSObject
119{
120}
121
ba808e24
DE
122// Delegate methods
123- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication;
124- (void)applicationWillBecomeActive:(NSNotification *)notification;
125- (void)applicationDidBecomeActive:(NSNotification *)notification;
126- (void)applicationWillResignActive:(NSNotification *)notification;
127- (void)applicationDidResignActive:(NSNotification *)notification;
128@end // interface wxNSApplicationDelegate : NSObject
129
130@implementation wxNSApplicationDelegate : NSObject
131
2990ec97
DE
132// NOTE: Terminate means that the event loop does NOT return and thus
133// cleanup code doesn't properly execute. Furthermore, wxWindows has its
134// own exit on frame delete mechanism.
fb896a32
DE
135- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
136{
2990ec97 137 return NO;
fb896a32
DE
138}
139
0187ddb4
DE
140- (void)applicationWillBecomeActive:(NSNotification *)notification
141{
142 wxTheApp->CocoaDelegate_applicationWillBecomeActive();
143}
144
145- (void)applicationDidBecomeActive:(NSNotification *)notification
146{
147 wxTheApp->CocoaDelegate_applicationDidBecomeActive();
148}
149
150- (void)applicationWillResignActive:(NSNotification *)notification
151{
152 wxTheApp->CocoaDelegate_applicationWillResignActive();
153}
154
155- (void)applicationDidResignActive:(NSNotification *)notification
156{
157 wxTheApp->CocoaDelegate_applicationDidResignActive();
158}
159
160@end // implementation wxNSApplicationDelegate : NSObject
e2478fde 161
70fb935a
DE
162// ========================================================================
163// wxApp
164// ========================================================================
fb896a32
DE
165
166// ----------------------------------------------------------------------------
167// wxApp Static member initialization
168// ----------------------------------------------------------------------------
fb896a32
DE
169IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
170BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
955a9197 171 EVT_IDLE(wxAppBase::OnIdle)
fb896a32
DE
172// EVT_END_SESSION(wxApp::OnEndSession)
173// EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
174END_EVENT_TABLE()
fb896a32
DE
175
176// ----------------------------------------------------------------------------
05e2b077 177// wxApp initialization/cleanup
fb896a32 178// ----------------------------------------------------------------------------
05e2b077 179bool wxApp::Initialize(int& argc, wxChar **argv)
fb896a32 180{
47f1ad6a 181 wxAutoNSAutoreleasePool pool;
14fc7eb4 182 m_cocoaMainThread = [NSThread currentThread];
05e2b077
VZ
183 // Mac OS X passes a process serial number command line argument when
184 // the application is launched from the Finder. This argument must be
185 // removed from the command line arguments before being handled by the
186 // application (otherwise applications would need to handle it)
187 if ( argc > 1 )
188 {
189 static const wxChar *ARG_PSN = _T("-psn_");
33f39af3 190 if ( wxStrncmp(argv[1], ARG_PSN, strlen(ARG_PSN)) == 0 )
05e2b077
VZ
191 {
192 // remove this argument
33f39af3
GD
193 --argc;
194 memmove(argv + 1, argv + 2, argc * sizeof(char *));
05e2b077
VZ
195 }
196 }
197
28ce3086
DE
198 // Posing must be completed before any instances of the Objective-C
199 // classes being posed as are created.
fb896a32 200 wxPoseAsInitializer::InitializePosers();
fb896a32 201
94826170 202 return wxAppBase::Initialize(argc, argv);
fb896a32
DE
203}
204
94826170 205void wxApp::CleanUp()
fb896a32 206{
0187ddb4
DE
207 wxAutoNSAutoreleasePool pool;
208
891d0563 209 wxDC::CocoaShutdownTextSystem();
af367f46 210 wxMenuBarManager::DestroyInstance();
94826170 211
0187ddb4
DE
212 [m_cocoaApp setDelegate:nil];
213 [m_cocoaAppDelegate release];
214 m_cocoaAppDelegate = NULL;
215
94826170 216 wxAppBase::CleanUp();
fb896a32
DE
217}
218
219// ----------------------------------------------------------------------------
220// wxApp creation
221// ----------------------------------------------------------------------------
fb896a32
DE
222wxApp::wxApp()
223{
224 m_topWindow = NULL;
fb896a32 225
fb896a32
DE
226#if WXWIN_COMPATIBILITY_2_2
227 m_wantDebugOutput = TRUE;
228#endif
b93d8cc4
DE
229#ifdef __WXDEBUG__
230 m_isInAssert = FALSE;
231#endif // __WXDEBUG__
232
fb896a32
DE
233 argc = 0;
234 argv = NULL;
235 m_cocoaApp = NULL;
0187ddb4 236 m_cocoaAppDelegate = NULL;
fb896a32
DE
237}
238
0187ddb4
DE
239void wxApp::CocoaDelegate_applicationWillBecomeActive()
240{
241}
242
243void wxApp::CocoaDelegate_applicationDidBecomeActive()
244{
245}
246
247void wxApp::CocoaDelegate_applicationWillResignActive()
248{
39050120 249 wxTopLevelWindowCocoa::DeactivatePendingWindow();
0187ddb4
DE
250}
251
252void wxApp::CocoaDelegate_applicationDidResignActive()
253{
254}
255
fb896a32
DE
256bool wxApp::OnInitGui()
257{
47f1ad6a 258 wxAutoNSAutoreleasePool pool;
fb896a32
DE
259 if(!wxAppBase::OnInitGui())
260 return FALSE;
261
262 // Create the app using the sharedApplication method
263 m_cocoaApp = [NSApplication sharedApplication];
0187ddb4
DE
264 m_cocoaAppDelegate = [[wxNSApplicationDelegate alloc] init];
265 [m_cocoaApp setDelegate:m_cocoaAppDelegate];
af367f46
DE
266
267 wxMenuBarManager::CreateInstance();
268
891d0563 269 wxDC::CocoaInitializeTextSystem();
fb896a32 270// [ m_cocoaApp setDelegate:m_cocoaApp ];
fb896a32
DE
271 return TRUE;
272}
273
47f1ad6a
DE
274bool wxApp::CallOnInit()
275{
bd3e8827 276// wxAutoNSAutoreleasePool pool;
47f1ad6a
DE
277 return OnInit();
278}
279
fb896a32
DE
280bool wxApp::OnInit()
281{
282 if(!wxAppBase::OnInit())
283 return FALSE;
284
285 return TRUE;
286}
287
70fb935a
DE
288void wxApp::Exit()
289{
290 wxApp::CleanUp();
291
292 wxAppConsole::Exit();
293}
294
fb896a32 295// Yield to other processes
fb896a32
DE
296bool wxApp::Yield(bool onlyIfNeeded)
297{
298 // MT-FIXME
299 static bool s_inYield = false;
300
301#if wxUSE_LOG
302 // disable log flushing from here because a call to wxYield() shouldn't
303 // normally result in message boxes popping up &c
304 wxLog::Suspend();
305#endif // wxUSE_LOG
306
307 if (s_inYield)
308 {
309 if ( !onlyIfNeeded )
310 {
311 wxFAIL_MSG( wxT("wxYield called recursively" ) );
312 }
313
314 return false;
315 }
316
317 s_inYield = true;
318
aaa5ab05
DE
319 // Run the event loop until it is out of events
320 while(NSEvent *event = [GetNSApplication()
321 nextEventMatchingMask:NSAnyEventMask
322 untilDate:[NSDate distantPast]
323 inMode:NSDefaultRunLoopMode
324 dequeue: YES])
325 {
326 [GetNSApplication() sendEvent: event];
327 }
fb896a32
DE
328
329#if wxUSE_LOG
330 // let the logs be flashed again
331 wxLog::Resume();
332#endif // wxUSE_LOG
333
334 s_inYield = false;
335
336 return true;
337}
338
eb537cfb
DE
339void wxApp::WakeUpIdle()
340{
341 [m_cocoaApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
342 location:NSZeroPoint modifierFlags:NSAnyEventMask
343 timestamp:0 windowNumber:0 context:nil
344 subtype:0 data1:0 data2:0] atStart:NO];
345}
346
b93d8cc4
DE
347#ifdef __WXDEBUG__
348void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg)
349{
350 m_isInAssert = TRUE;
351 wxAppBase::OnAssert(file, line, cond, msg);
352 m_isInAssert = FALSE;
353}
354#endif // __WXDEBUG__
355