1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: cocoa/evtloop.mm
3 // Purpose: implements wxEventLoop for Cocoa
4 // Author: David Elliott
8 // Copyright: (c) 2003 David Elliott <dfe@cox.net>
9 // License: wxWidgets licence
10 ///////////////////////////////////////////////////////////////////////////////
12 #include "wx/wxprec.h"
18 #include "wx/evtloop.h"
20 #import <AppKit/NSApplication.h>
21 #import <AppKit/NSEvent.h>
22 #import <Foundation/NSRunLoop.h>
24 // ========================================================================
26 // ========================================================================
28 class WXDLLEXPORT wxEventLoopImpl
32 wxEventLoopImpl() { SetExitCode(0); }
34 // set/get the exit code
35 void SetExitCode(int exitcode) { m_exitcode = exitcode; }
36 int GetExitCode() const { return m_exitcode; }
39 // the exit code of the event loop
43 // ========================================================================
45 // ========================================================================
47 // ----------------------------------------------------------------------------
48 // wxEventLoop running and exiting
49 // ----------------------------------------------------------------------------
51 wxEventLoop *wxEventLoop::ms_activeLoop = NULL;
53 wxEventLoop::~wxEventLoop()
55 wxASSERT_MSG( !m_impl, _T("should have been deleted in Run()") );
58 bool wxEventLoop::IsRunning() const
63 int wxEventLoop::Run()
65 // event loops are not recursive, you need to create another loop!
66 wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
68 wxEventLoop *oldLoop = ms_activeLoop;
71 m_impl = new wxEventLoopImpl;
73 [[NSApplication sharedApplication] run];
75 int exitcode = m_impl->GetExitCode();
79 ms_activeLoop = oldLoop;
84 void wxEventLoop::Exit(int rc)
86 wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") );
88 m_impl->SetExitCode(rc);
90 NSApplication *cocoaApp = [NSApplication sharedApplication];
91 wxLogTrace(wxTRACE_COCOA,wxT("wxEventLoop::Exit isRunning=%d"), (int)[cocoaApp isRunning]);
92 wxTheApp->WakeUpIdle();
94 If we're being called from idle time (which occurs while checking the
95 queue for new events) there may or may not be any events in the queue.
96 In order to successfully stop the event loop, at least one event must
97 be processed. To ensure this always happens, WakeUpIdle is called.
99 If the application was active when closed then this is unnecessary
100 because it would receive a deactivate event anyway. However, if the
101 application was not active when closed, then no events would be
102 added to the queue by Cocoa and thus the application would wait
103 indefinitely for the next event.
105 [cocoaApp stop: cocoaApp];
108 // ----------------------------------------------------------------------------
109 // wxEventLoop message processing dispatching
110 // ----------------------------------------------------------------------------
112 bool wxEventLoop::Pending() const
114 // a pointer to the event is returned if there is one, or nil if not
115 return [[NSApplication sharedApplication]
116 nextEventMatchingMask: NSAnyEventMask
117 untilDate: nil /* Equivalent to [NSDate distantPast] */
118 inMode: NSDefaultRunLoopMode
122 bool wxEventLoop::Dispatch()
124 // This check is required by wxGTK but probably not really for wxCocoa
125 // Keep it here to encourage developers to write cross-platform code
126 wxCHECK_MSG( IsRunning(), false, _T("can't call Dispatch() if not running") );
127 NSApplication *cocoaApp = [NSApplication sharedApplication];
128 // Block to retrieve an event then send it
129 if(NSEvent *event = [cocoaApp
130 nextEventMatchingMask:NSAnyEventMask
131 untilDate:[NSDate distantFuture]
132 inMode:NSDefaultRunLoopMode
135 [cocoaApp sendEvent: event];