overriding the cfrunloop accessor, during booting cocoa has to create a NSRunLoop...
[wxWidgets.git] / src / osx / cocoa / evtloop.mm
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name:        src/osx/cocoa/evtloop.mm
3 // Purpose:     implementation of wxEventLoop for OS X
4 // Author:      Vadim Zeitlin, Stefan Csomor
5 // Modified by:
6 // Created:     2006-01-12
7 // RCS-ID:      $Id: evtloop.cpp 54845 2008-07-30 14:52:41Z SC $
8 // Copyright:   (c) 2006 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence:     wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
22
23 #ifdef __BORLANDC__
24     #pragma hdrstop
25 #endif
26
27 #include "wx/evtloop.h"
28
29 #ifndef WX_PRECOMP
30     #include "wx/app.h"
31     #include "wx/nonownedwnd.h"
32 #endif // WX_PRECOMP
33
34 #include "wx/log.h"
35
36 #include "wx/osx/private.h"
37
38 // ============================================================================
39 // wxEventLoop implementation
40 // ============================================================================
41
42 /*
43 static int CalculateNSEventMaskFromEventCategory(wxEventCategory cat)
44 {
45         NSLeftMouseDownMask     |
46         NSLeftMouseUpMask |
47         NSRightMouseDownMask |
48         NSRightMouseUpMask              = 1 << NSRightMouseUp,
49         NSMouseMovedMask                = 1 << NSMouseMoved,
50         NSLeftMouseDraggedMask          = 1 << NSLeftMouseDragged,
51         NSRightMouseDraggedMask         = 1 << NSRightMouseDragged,
52         NSMouseEnteredMask              = 1 << NSMouseEntered,
53         NSMouseExitedMask               = 1 << NSMouseExited,
54         NSScrollWheelMask               = 1 << NSScrollWheel,
55 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
56         NSTabletPointMask               = 1 << NSTabletPoint,
57         NSTabletProximityMask           = 1 << NSTabletProximity,
58 #endif
59         NSOtherMouseDownMask            = 1 << NSOtherMouseDown,
60         NSOtherMouseUpMask              = 1 << NSOtherMouseUp,
61         NSOtherMouseDraggedMask         = 1 << NSOtherMouseDragged,
62
63
64
65         NSKeyDownMask                   = 1 << NSKeyDown,
66         NSKeyUpMask                     = 1 << NSKeyUp,
67         NSFlagsChangedMask              = 1 << NSFlagsChanged,
68
69         NSAppKitDefinedMask             = 1 << NSAppKitDefined,
70         NSSystemDefinedMask             = 1 << NSSystemDefined,
71         NSApplicationDefinedMask        = 1 << NSApplicationDefined,
72         NSPeriodicMask                  = 1 << NSPeriodic,
73         NSCursorUpdateMask              = 1 << NSCursorUpdate,
74
75         NSAnyEventMask                  = 0xffffffffU
76 }
77 */
78
79 wxGUIEventLoop::wxGUIEventLoop()
80 {
81 }
82
83 //-----------------------------------------------------------------------------
84 // events dispatch and loop handling
85 //-----------------------------------------------------------------------------
86
87 #if 0
88
89 bool wxGUIEventLoop::Pending() const
90 {
91 #if 0
92     // this code doesn't reliably detect pending events
93     // so better return true and have the dispatch deal with it
94     // as otherwise we end up in a tight loop when idle events are responded
95     // to by RequestMore(true)
96     wxMacAutoreleasePool autoreleasepool;
97   
98     return [[NSApplication sharedApplication]
99             nextEventMatchingMask: NSAnyEventMask
100             untilDate: nil
101             inMode: NSDefaultRunLoopMode
102             dequeue: NO] != nil;
103 #else
104     return true;
105 #endif
106 }
107
108 bool wxGUIEventLoop::Dispatch()
109 {
110     if ( !wxTheApp )
111         return false;
112
113     wxMacAutoreleasePool autoreleasepool;
114
115     if(NSEvent *event = [NSApp
116                 nextEventMatchingMask:NSAnyEventMask
117                 untilDate:[NSDate dateWithTimeIntervalSinceNow: m_sleepTime]
118                 inMode:NSDefaultRunLoopMode
119                 dequeue: YES])
120     {
121         if (wxTheApp)
122             wxTheApp->MacSetCurrentEvent(event, NULL);
123         m_sleepTime = 0.0;
124         [NSApp sendEvent: event];
125     }
126     else
127     {
128         if (wxTheApp)
129             wxTheApp->ProcessPendingEvents();
130         
131         if ( wxTheApp->ProcessIdle() )
132             m_sleepTime = 0.0 ;
133         else
134         {
135             m_sleepTime = 1.0;
136 #if wxUSE_THREADS
137             wxMutexGuiLeave();
138             wxMilliSleep(20);
139             wxMutexGuiEnter();
140 #endif
141         }
142     }
143
144     return true;
145 }
146
147 #endif
148
149 int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout)
150 {
151     wxMacAutoreleasePool autoreleasepool;
152
153     NSEvent *event = [NSApp
154                 nextEventMatchingMask:NSAnyEventMask
155                 untilDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000]
156                 inMode:NSDefaultRunLoopMode
157                 dequeue: YES];
158     
159     if ( event == nil )
160         return -1;
161
162     [NSApp sendEvent: event];
163
164     return 1;
165 }
166
167 void wxGUIEventLoop::DoRun()
168 {
169     wxMacAutoreleasePool autoreleasepool;
170     [NSApp run];
171 }
172
173 void wxGUIEventLoop::DoStop()
174 {
175     [NSApp stop:0];
176 }
177
178 CFRunLoopRef wxGUIEventLoop::CFGetCurrentRunLoop() const
179 {
180     NSRunLoop* nsloop = [NSRunLoop currentRunLoop];
181     return [nsloop getCFRunLoop];
182 }
183
184
185 // TODO move into a evtloop_osx.cpp
186
187 wxModalEventLoop::wxModalEventLoop(wxWindow *modalWindow)
188 {
189     m_modalWindow = dynamic_cast<wxNonOwnedWindow*> (modalWindow);
190     wxASSERT_MSG( m_modalWindow != NULL, "must pass in a toplevel window for modal event loop" );
191     m_modalNativeWindow = m_modalWindow->GetWXWindow();
192 }
193
194 wxModalEventLoop::wxModalEventLoop(WXWindow modalNativeWindow)
195 {
196     m_modalWindow = NULL;
197     wxASSERT_MSG( modalNativeWindow != NULL, "must pass in a toplevel window for modal event loop" );
198     m_modalNativeWindow = modalNativeWindow;
199 }
200
201 // END move into a evtloop_osx.cpp
202
203 void wxModalEventLoop::DoRun()
204 {
205     wxMacAutoreleasePool pool;
206
207     // If the app hasn't started, flush the event queue
208     // If we don't do this, the Dock doesn't get the message that
209     // the app has started so will refuse to activate it.
210     [NSApplication sharedApplication];
211     if (![NSApp isRunning])
212     {
213         while(NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES])
214         {
215             [NSApp sendEvent:event];
216         }
217     }
218     
219     [NSApp runModalForWindow:m_modalNativeWindow];
220 }
221
222 void wxModalEventLoop::DoStop()
223 {
224     [NSApp stopModal];
225 }
226