]> git.saurik.com Git - wxWidgets.git/blame - src/cocoa/app.mm
removed extra semicolons added by last commit
[wxWidgets.git] / src / cocoa / app.mm
CommitLineData
fb896a32 1/////////////////////////////////////////////////////////////////////////////
8898456d 2// Name: src/cocoa/app.mm
fb896a32
DE
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
047c1182 9// Software 2000 Ltd.
bb27b372 10// Licence: wxWidgets licence
fb896a32
DE
11/////////////////////////////////////////////////////////////////////////////
12
fb896a32 13#include "wx/wxprec.h"
8898456d 14
da80ae71
WS
15#include "wx/app.h"
16
fb896a32 17#ifndef WX_PRECOMP
891d0563 18 #include "wx/dc.h"
fb896a32
DE
19 #include "wx/intl.h"
20 #include "wx/log.h"
02761f6c 21 #include "wx/module.h"
fb896a32
DE
22#endif
23
047c1182 24#include "wx/cocoa/ObjcRef.h"
493902ac 25#include "wx/cocoa/autorelease.h"
af367f46 26#include "wx/cocoa/mbarman.h"
bb27b372 27#include "wx/cocoa/NSApplication.h"
fb45bb1f 28
fb896a32
DE
29#import <AppKit/NSApplication.h>
30#import <Foundation/NSRunLoop.h>
14fc7eb4 31#import <Foundation/NSThread.h>
aaa5ab05 32#import <AppKit/NSEvent.h>
eb537cfb 33#import <Foundation/NSString.h>
bb27b372
RN
34#import <Foundation/NSNotification.h>
35#import <AppKit/NSCell.h>
fb896a32 36
047c1182
DE
37// wxNSApplicationObserver singleton.
38static wxObjcAutoRefFromAlloc<wxNSApplicationObserver*> sg_cocoaAppObserver = [[wxNSApplicationObserver alloc] init];
39
ba808e24
DE
40// ========================================================================
41// wxNSApplicationDelegate
42// ========================================================================
ba808e24
DE
43@implementation wxNSApplicationDelegate : NSObject
44
2990ec97 45// NOTE: Terminate means that the event loop does NOT return and thus
bb27b372 46// cleanup code doesn't properly execute. Furthermore, wxWidgets has its
2990ec97 47// own exit on frame delete mechanism.
fb896a32
DE
48- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
49{
2990ec97 50 return NO;
fb896a32
DE
51}
52
047c1182
DE
53@end // implementation wxNSApplicationDelegate : NSObject
54
55// ========================================================================
56// wxNSApplicationObserver
57// ========================================================================
58@implementation wxNSApplicationObserver : NSObject
59
0187ddb4
DE
60- (void)applicationWillBecomeActive:(NSNotification *)notification
61{
62 wxTheApp->CocoaDelegate_applicationWillBecomeActive();
63}
64
65- (void)applicationDidBecomeActive:(NSNotification *)notification
66{
67 wxTheApp->CocoaDelegate_applicationDidBecomeActive();
68}
69
70- (void)applicationWillResignActive:(NSNotification *)notification
71{
72 wxTheApp->CocoaDelegate_applicationWillResignActive();
73}
74
75- (void)applicationDidResignActive:(NSNotification *)notification
76{
77 wxTheApp->CocoaDelegate_applicationDidResignActive();
78}
79
047c1182
DE
80- (void)applicationWillUpdate:(NSNotification *)notification;
81{
82 wxTheApp->CocoaDelegate_applicationWillUpdate();
83}
84
bb27b372
RN
85- (void)controlTintChanged:(NSNotification *)notification
86{
422d306c 87 wxLogDebug(wxT("TODO: send EVT_SYS_COLOUR_CHANGED as appropriate"));
bb27b372
RN
88}
89
047c1182 90@end // implementation wxNSApplicationObserver : NSObject
e2478fde 91
70fb935a
DE
92// ========================================================================
93// wxApp
94// ========================================================================
fb896a32
DE
95
96// ----------------------------------------------------------------------------
97// wxApp Static member initialization
98// ----------------------------------------------------------------------------
fb896a32
DE
99IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler)
100BEGIN_EVENT_TABLE(wxApp, wxEvtHandler)
955a9197 101 EVT_IDLE(wxAppBase::OnIdle)
fb896a32
DE
102// EVT_END_SESSION(wxApp::OnEndSession)
103// EVT_QUERY_END_SESSION(wxApp::OnQueryEndSession)
104END_EVENT_TABLE()
fb896a32
DE
105
106// ----------------------------------------------------------------------------
05e2b077 107// wxApp initialization/cleanup
fb896a32 108// ----------------------------------------------------------------------------
05e2b077 109bool wxApp::Initialize(int& argc, wxChar **argv)
fb896a32 110{
47f1ad6a 111 wxAutoNSAutoreleasePool pool;
14fc7eb4 112 m_cocoaMainThread = [NSThread currentThread];
05e2b077
VZ
113 // Mac OS X passes a process serial number command line argument when
114 // the application is launched from the Finder. This argument must be
115 // removed from the command line arguments before being handled by the
116 // application (otherwise applications would need to handle it)
117 if ( argc > 1 )
118 {
119 static const wxChar *ARG_PSN = _T("-psn_");
b0c0a393 120 if ( wxStrncmp(argv[1], ARG_PSN, wxStrlen(ARG_PSN)) == 0 )
05e2b077
VZ
121 {
122 // remove this argument
33f39af3 123 --argc;
b0c0a393 124 memmove(argv + 1, argv + 2, argc * sizeof(wxChar *));
05e2b077
VZ
125 }
126 }
127
94826170 128 return wxAppBase::Initialize(argc, argv);
fb896a32
DE
129}
130
94826170 131void wxApp::CleanUp()
fb896a32 132{
0187ddb4
DE
133 wxAutoNSAutoreleasePool pool;
134
891d0563 135 wxDC::CocoaShutdownTextSystem();
af367f46 136 wxMenuBarManager::DestroyInstance();
94826170 137
0187ddb4 138 [m_cocoaApp setDelegate:nil];
047c1182 139 [[NSNotificationCenter defaultCenter] removeObserver:m_cocoaAppDelegate];
0187ddb4
DE
140 [m_cocoaAppDelegate release];
141 m_cocoaAppDelegate = NULL;
142
94826170 143 wxAppBase::CleanUp();
fb896a32
DE
144}
145
146// ----------------------------------------------------------------------------
147// wxApp creation
148// ----------------------------------------------------------------------------
fb896a32
DE
149wxApp::wxApp()
150{
151 m_topWindow = NULL;
fb896a32 152
b93d8cc4 153#ifdef __WXDEBUG__
8898456d 154 m_isInAssert = false;
b93d8cc4
DE
155#endif // __WXDEBUG__
156
fb896a32
DE
157 argc = 0;
158 argv = NULL;
159 m_cocoaApp = NULL;
0187ddb4 160 m_cocoaAppDelegate = NULL;
fb896a32
DE
161}
162
0187ddb4
DE
163void wxApp::CocoaDelegate_applicationWillBecomeActive()
164{
165}
166
167void wxApp::CocoaDelegate_applicationDidBecomeActive()
168{
169}
170
171void wxApp::CocoaDelegate_applicationWillResignActive()
172{
39050120 173 wxTopLevelWindowCocoa::DeactivatePendingWindow();
0187ddb4
DE
174}
175
176void wxApp::CocoaDelegate_applicationDidResignActive()
177{
178}
179
fb896a32
DE
180bool wxApp::OnInitGui()
181{
47f1ad6a 182 wxAutoNSAutoreleasePool pool;
fb896a32 183 if(!wxAppBase::OnInitGui())
8898456d 184 return false;
fb896a32
DE
185
186 // Create the app using the sharedApplication method
187 m_cocoaApp = [NSApplication sharedApplication];
047c1182
DE
188
189 // Enable response to application delegate messages
0187ddb4
DE
190 m_cocoaAppDelegate = [[wxNSApplicationDelegate alloc] init];
191 [m_cocoaApp setDelegate:m_cocoaAppDelegate];
047c1182
DE
192
193 // Enable response to "delegate" messages on the notification observer
194 [[NSNotificationCenter defaultCenter] addObserver:sg_cocoaAppObserver
195 selector:@selector(applicationWillBecomeActive:)
196 name:NSApplicationWillBecomeActiveNotification object:nil];
197
198 [[NSNotificationCenter defaultCenter] addObserver:sg_cocoaAppObserver
199 selector:@selector(applicationDidBecomeActive:)
200 name:NSApplicationDidBecomeActiveNotification object:nil];
201
202 [[NSNotificationCenter defaultCenter] addObserver:sg_cocoaAppObserver
203 selector:@selector(applicationWillResignActive:)
204 name:NSApplicationWillResignActiveNotification object:nil];
205
206 [[NSNotificationCenter defaultCenter] addObserver:sg_cocoaAppObserver
207 selector:@selector(applicationDidResignActive:)
208 name:NSApplicationDidResignActiveNotification object:nil];
209
210 [[NSNotificationCenter defaultCenter] addObserver:sg_cocoaAppObserver
211 selector:@selector(applicationWillUpdate:)
212 name:NSApplicationWillUpdateNotification object:nil];
213
214 // Enable response to system notifications
215 [[NSNotificationCenter defaultCenter] addObserver:sg_cocoaAppObserver
bb27b372
RN
216 selector:@selector(controlTintChanged:)
217 name:NSControlTintDidChangeNotification object:nil];
af367f46
DE
218
219 wxMenuBarManager::CreateInstance();
220
891d0563 221 wxDC::CocoaInitializeTextSystem();
8898456d 222 return true;
fb896a32
DE
223}
224
047c1182
DE
225wxApp::~wxApp()
226{
227 if(m_cfRunLoopIdleObserver != NULL)
228 {
229 // Invalidate the observer which also removes it from the run loop.
230 CFRunLoopObserverInvalidate(m_cfRunLoopIdleObserver);
231 // Release the ref as we don't need it anymore.
232 m_cfRunLoopIdleObserver.reset();
233 }
234}
235
47f1ad6a
DE
236bool wxApp::CallOnInit()
237{
bd3e8827 238// wxAutoNSAutoreleasePool pool;
47f1ad6a
DE
239 return OnInit();
240}
241
fb896a32
DE
242bool wxApp::OnInit()
243{
244 if(!wxAppBase::OnInit())
8898456d 245 return false;
fb896a32 246
8898456d 247 return true;
fb896a32
DE
248}
249
70fb935a
DE
250void wxApp::Exit()
251{
252 wxApp::CleanUp();
253
254 wxAppConsole::Exit();
255}
256
fb896a32 257// Yield to other processes
fb896a32
DE
258bool wxApp::Yield(bool onlyIfNeeded)
259{
260 // MT-FIXME
261 static bool s_inYield = false;
262
263#if wxUSE_LOG
264 // disable log flushing from here because a call to wxYield() shouldn't
265 // normally result in message boxes popping up &c
266 wxLog::Suspend();
267#endif // wxUSE_LOG
268
269 if (s_inYield)
270 {
271 if ( !onlyIfNeeded )
272 {
273 wxFAIL_MSG( wxT("wxYield called recursively" ) );
274 }
275
276 return false;
277 }
278
279 s_inYield = true;
280
aaa5ab05 281 // Run the event loop until it is out of events
bb27b372
RN
282 while(1)
283 {
284 wxAutoNSAutoreleasePool pool;
285 NSEvent *event = [GetNSApplication()
aaa5ab05 286 nextEventMatchingMask:NSAnyEventMask
422d306c 287 untilDate:[NSDate distantPast]
aaa5ab05 288 inMode:NSDefaultRunLoopMode
bb27b372
RN
289 dequeue: YES];
290 if(!event)
291 break;
aaa5ab05
DE
292 [GetNSApplication() sendEvent: event];
293 }
fb896a32
DE
294
295#if wxUSE_LOG
296 // let the logs be flashed again
297 wxLog::Resume();
298#endif // wxUSE_LOG
299
300 s_inYield = false;
301
302 return true;
303}
304
eb537cfb
DE
305void wxApp::WakeUpIdle()
306{
307 [m_cocoaApp postEvent:[NSEvent otherEventWithType:NSApplicationDefined
308 location:NSZeroPoint modifierFlags:NSAnyEventMask
309 timestamp:0 windowNumber:0 context:nil
310 subtype:0 data1:0 data2:0] atStart:NO];
311}
312
047c1182
DE
313extern "C" static void ObserveMainRunLoopBeforeWaiting(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info);
314extern "C" static void ObserveMainRunLoopBeforeWaiting(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
315{
316 static_cast<wxApp*>(info)->CF_ObserveMainRunLoopBeforeWaiting(observer, activity);
317}
318
319#if 0
320static int sg_cApplicationWillUpdate = 0;
321#endif
322
323void wxApp::CocoaDelegate_applicationWillUpdate()
324{
325 wxLogTrace(wxTRACE_COCOA,wxT("applicationWillUpdate"));
326
327// CFRunLoopRef cfRunLoop = [[NSRunLoop currentRunLoop] getCFRunLoop];
328 CFRunLoopRef cfRunLoop = CFRunLoopGetCurrent();
329 wxCFRef<CFStringRef> cfRunLoopMode(CFRunLoopCopyCurrentMode(cfRunLoop));
330
331 if(m_cfRunLoopIdleObserver != NULL && m_cfObservedRunLoopMode != cfRunLoopMode)
332 {
333 CFRunLoopObserverInvalidate(m_cfRunLoopIdleObserver);
334 m_cfRunLoopIdleObserver.reset();
335 }
336#if 0
337 ++sg_cApplicationWillUpdate;
338#endif
339 if(m_cfRunLoopIdleObserver == NULL)
340 {
341 // Enable idle event handling
342 CFRunLoopObserverContext observerContext =
343 { 0
344 , this
345 , NULL
346 , NULL
347 , NULL
348 };
349 m_cfRunLoopIdleObserver.reset(CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, /*repeats*/FALSE, /*priority*/0, ObserveMainRunLoopBeforeWaiting, &observerContext));
350 m_cfObservedRunLoopMode = cfRunLoopMode;
351 CFRunLoopAddObserver(cfRunLoop, m_cfRunLoopIdleObserver, m_cfObservedRunLoopMode);
352 }
353}
354
355static inline bool FakeNeedMoreIdle()
356{
357#if 0
358// Return true on every 10th call.
359 static int idleCount = 0;
360 return ++idleCount % 10;
361#else
362 return false;
363#endif
364}
365
366void wxApp::CF_ObserveMainRunLoopBeforeWaiting(CFRunLoopObserverRef observer, int activity)
367{
368 // Ensure that the app knows we've been invalidated
369 m_cfRunLoopIdleObserver.reset();
370#if 0
371 wxLogTrace(wxTRACE_COCOA,wxT("Idle BEGIN (%d)"), sg_cApplicationWillUpdate);
372 sg_cApplicationWillUpdate = 0;
373#else
374 wxLogTrace(wxTRACE_COCOA,wxT("Idle BEGIN"));
375#endif
376 if( ProcessIdle() || FakeNeedMoreIdle() )
377 {
378 wxLogTrace(wxTRACE_COCOA, wxT("Idle REQUEST MORE"));
379 [NSApp setWindowsNeedUpdate:YES];
380 }
381 else
382 {
383 wxLogTrace(wxTRACE_COCOA, wxT("Idle END"));
384 }
385}
386
b93d8cc4
DE
387#ifdef __WXDEBUG__
388void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg)
389{
8898456d 390 m_isInAssert = true;
b93d8cc4 391 wxAppBase::OnAssert(file, line, cond, msg);
8898456d 392 m_isInAssert = false;
b93d8cc4
DE
393}
394#endif // __WXDEBUG__