]> git.saurik.com Git - wxWidgets.git/blob - src/cocoa/evtloop.mm
* When hiding a wxWindow make sure that none of its subviews are the first
[wxWidgets.git] / src / cocoa / evtloop.mm
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: cocoa/evtloop.mm
3 // Purpose: implements wxEventLoop for Cocoa
4 // Author: David Elliott
5 // Modified by:
6 // Created: 2003/10/02
7 // RCS-ID: $Id$
8 // Copyright: (c) 2003 David Elliott <dfe@cox.net>
9 // License: wxWidgets licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13 #ifndef WX_PRECOMP
14 #include "wx/log.h"
15 #include "wx/app.h"
16 #endif //WX_PRECOMP
17
18 #include "wx/evtloop.h"
19
20 #import <AppKit/NSApplication.h>
21 #import <AppKit/NSEvent.h>
22 #import <Foundation/NSRunLoop.h>
23
24 // ========================================================================
25 // wxEventLoopImpl
26 // ========================================================================
27
28 class WXDLLEXPORT wxEventLoopImpl
29 {
30 public:
31 // ctor
32 wxEventLoopImpl() { SetExitCode(0); }
33
34 // set/get the exit code
35 void SetExitCode(int exitcode) { m_exitcode = exitcode; }
36 int GetExitCode() const { return m_exitcode; }
37
38 private:
39 // the exit code of the event loop
40 int m_exitcode;
41 };
42
43 // ========================================================================
44 // wxGUIEventLoop
45 // ========================================================================
46
47 // ----------------------------------------------------------------------------
48 // wxGUIEventLoop running and exiting
49 // ----------------------------------------------------------------------------
50
51 wxGUIEventLoop::~wxGUIEventLoop()
52 {
53 wxASSERT_MSG( !m_impl, _T("should have been deleted in Run()") );
54 }
55
56 int wxGUIEventLoop::Run()
57 {
58 // event loops are not recursive, you need to create another loop!
59 wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
60
61 wxEventLoopActivator activate(this);
62
63 m_impl = new wxEventLoopImpl;
64
65 [[NSApplication sharedApplication] run];
66
67 OnExit();
68
69 int exitcode = m_impl->GetExitCode();
70 delete m_impl;
71 m_impl = NULL;
72
73 return exitcode;
74 }
75
76 void wxGUIEventLoop::Exit(int rc)
77 {
78 wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") );
79
80 m_impl->SetExitCode(rc);
81
82 NSApplication *cocoaApp = [NSApplication sharedApplication];
83 wxLogTrace(wxTRACE_COCOA,wxT("wxEventLoop::Exit isRunning=%d"), (int)[cocoaApp isRunning]);
84 wxTheApp->WakeUpIdle();
85 /* Notes:
86 If we're being called from idle time (which occurs while checking the
87 queue for new events) there may or may not be any events in the queue.
88 In order to successfully stop the event loop, at least one event must
89 be processed. To ensure this always happens, WakeUpIdle is called.
90
91 If the application was active when closed then this is unnecessary
92 because it would receive a deactivate event anyway. However, if the
93 application was not active when closed, then no events would be
94 added to the queue by Cocoa and thus the application would wait
95 indefinitely for the next event.
96 */
97 [cocoaApp stop: cocoaApp];
98 }
99
100 // ----------------------------------------------------------------------------
101 // wxEventLoop message processing dispatching
102 // ----------------------------------------------------------------------------
103
104 bool wxGUIEventLoop::Pending() const
105 {
106 // a pointer to the event is returned if there is one, or nil if not
107 return [[NSApplication sharedApplication]
108 nextEventMatchingMask: NSAnyEventMask
109 untilDate: nil /* Equivalent to [NSDate distantPast] */
110 inMode: NSDefaultRunLoopMode
111 dequeue: NO];
112 }
113
114 bool wxGUIEventLoop::Dispatch()
115 {
116 // This check is required by wxGTK but probably not really for wxCocoa
117 // Keep it here to encourage developers to write cross-platform code
118 wxCHECK_MSG( IsRunning(), false, _T("can't call Dispatch() if not running") );
119 NSApplication *cocoaApp = [NSApplication sharedApplication];
120 // Block to retrieve an event then send it
121 if(NSEvent *event = [cocoaApp
122 nextEventMatchingMask:NSAnyEventMask
123 untilDate:[NSDate distantFuture]
124 inMode:NSDefaultRunLoopMode
125 dequeue: YES])
126 {
127 [cocoaApp sendEvent: event];
128 return true;
129 }
130 return false;
131 }
132