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