]> git.saurik.com Git - wxWidgets.git/blame - src/osx/cocoa/evtloop.mm
signed/unsigned warning fix
[wxWidgets.git] / src / osx / cocoa / evtloop.mm
CommitLineData
b503b036
SC
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
1e04d2bf 27#include "wx/evtloop.h"
b503b036
SC
28
29#ifndef WX_PRECOMP
30 #include "wx/app.h"
bf06fbce 31 #include "wx/nonownedwnd.h"
b503b036
SC
32#endif // WX_PRECOMP
33
f965a844
RR
34#include "wx/log.h"
35
b503b036
SC
36#include "wx/osx/private.h"
37
38// ============================================================================
39// wxEventLoop implementation
40// ============================================================================
41
e9e8b381
SC
42#if 0
43
44// in case we want to integrate this
11fed901 45
902ddbfd
SC
46static NSUInteger CalculateNSEventMaskFromEventCategory(wxEventCategory cat)
47{
48 // the masking system doesn't really help, as only the lowlevel UI events
49 // are split in a useful way, all others are way to broad
50
51 if ( (cat | wxEVT_CATEGORY_USER_INPUT) && (cat | (~wxEVT_CATEGORY_USER_INPUT) ) )
52 return NSAnyEventMask;
53
54 NSUInteger mask = 0;
11fed901 55
902ddbfd
SC
56 if ( cat | wxEVT_CATEGORY_USER_INPUT )
57 {
58 mask |=
59 NSLeftMouseDownMask |
60 NSLeftMouseUpMask |
61 NSRightMouseDownMask |
62 NSRightMouseUpMask |
63 NSMouseMovedMask |
64 NSLeftMouseDraggedMask |
65 NSRightMouseDraggedMask |
66 NSMouseEnteredMask |
67 NSMouseExitedMask |
68 NSScrollWheelMask |
69#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
70 NSTabletPointMask |
71 NSTabletProximityMask |
72#endif
73 NSOtherMouseDownMask |
74 NSOtherMouseUpMask |
75 NSOtherMouseDraggedMask |
76
77 NSKeyDownMask |
78 NSKeyUpMask |
79 NSFlagsChangedMask |
80#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
81 NSEventMaskGesture |
82 NSEventMaskMagnify |
83 NSEventMaskSwipe |
84 NSEventMaskRotate |
85 NSEventMaskBeginGesture |
86 NSEventMaskEndGesture |
87#endif
88 0;
89 }
90
91 if ( cat | (~wxEVT_CATEGORY_USER_INPUT) )
92 {
93 mask |=
94 NSAppKitDefinedMask |
95 NSSystemDefinedMask |
96 NSApplicationDefinedMask |
97 NSPeriodicMask |
98 NSCursorUpdateMask;
99 }
100
101 return mask;
102}
11fed901 103
e9e8b381 104#endif
11fed901 105
902ddbfd
SC
106wxGUIEventLoop::wxGUIEventLoop()
107{
108 m_modalSession = nil;
109 m_dummyWindow = nil;
11fed901 110}
11fed901 111
902ddbfd 112wxGUIEventLoop::~wxGUIEventLoop()
b503b036 113{
902ddbfd
SC
114 wxASSERT( m_modalSession == nil );
115 wxASSERT( m_dummyWindow == nil );
6b8ef0b3
VZ
116}
117
118//-----------------------------------------------------------------------------
119// events dispatch and loop handling
120//-----------------------------------------------------------------------------
121
0056673c
SC
122#if 0
123
b503b036
SC
124bool wxGUIEventLoop::Pending() const
125{
a765eef3
SC
126#if 0
127 // this code doesn't reliably detect pending events
128 // so better return true and have the dispatch deal with it
129 // as otherwise we end up in a tight loop when idle events are responded
130 // to by RequestMore(true)
dbeddfb9 131 wxMacAutoreleasePool autoreleasepool;
a765eef3 132
b503b036
SC
133 return [[NSApplication sharedApplication]
134 nextEventMatchingMask: NSAnyEventMask
135 untilDate: nil
136 inMode: NSDefaultRunLoopMode
a765eef3
SC
137 dequeue: NO] != nil;
138#else
139 return true;
140#endif
b503b036
SC
141}
142
143bool wxGUIEventLoop::Dispatch()
144{
145 if ( !wxTheApp )
146 return false;
147
148 wxMacAutoreleasePool autoreleasepool;
149
150 if(NSEvent *event = [NSApp
151 nextEventMatchingMask:NSAnyEventMask
152 untilDate:[NSDate dateWithTimeIntervalSinceNow: m_sleepTime]
153 inMode:NSDefaultRunLoopMode
154 dequeue: YES])
155 {
0b6f851f
SC
156 WXEVENTREF formerEvent = wxTheApp == NULL ? NULL : wxTheApp->MacGetCurrentEvent();
157 WXEVENTHANDLERCALLREF formerHandler = wxTheApp == NULL ? NULL : wxTheApp->MacGetCurrentEventHandlerCallRef();
158
7dab9892
KO
159 if (wxTheApp)
160 wxTheApp->MacSetCurrentEvent(event, NULL);
b503b036
SC
161 m_sleepTime = 0.0;
162 [NSApp sendEvent: event];
0b6f851f
SC
163
164 if (wxTheApp)
165 wxTheApp->MacSetCurrentEvent(formerEvent , formerHandler);
b503b036
SC
166 }
167 else
168 {
b0a9bfc8
SC
169 if (wxTheApp)
170 wxTheApp->ProcessPendingEvents();
171
b503b036
SC
172 if ( wxTheApp->ProcessIdle() )
173 m_sleepTime = 0.0 ;
174 else
175 {
176 m_sleepTime = 1.0;
177#if wxUSE_THREADS
178 wxMutexGuiLeave();
179 wxMilliSleep(20);
180 wxMutexGuiEnter();
181#endif
182 }
183 }
184
185 return true;
186}
91407318 187
0056673c 188#endif
f965a844 189
0056673c 190int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout)
91407318
VZ
191{
192 wxMacAutoreleasePool autoreleasepool;
193
902ddbfd
SC
194 if ( m_modalSession )
195 {
196 NSInteger response = [NSApp runModalSession:(NSModalSession)m_modalSession];
197
198 switch (response)
199 {
200 case NSRunContinuesResponse:
201 {
202 if ( [[NSApplication sharedApplication]
203 nextEventMatchingMask: NSAnyEventMask
204 untilDate: nil
205 inMode: NSDefaultRunLoopMode
206 dequeue: NO] != nil )
207 return 1;
208
209 return -1;
210 }
211
212 case NSRunStoppedResponse:
213 case NSRunAbortedResponse:
214 return -1;
215 default:
216 wxFAIL_MSG("unknown response code");
902ddbfd
SC
217 break;
218 }
a624c97f 219 return -1;
902ddbfd
SC
220 }
221 else
222 {
223 NSEvent *event = [NSApp
224 nextEventMatchingMask:NSAnyEventMask
225 untilDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000]
226 inMode:NSDefaultRunLoopMode
227 dequeue: YES];
228
229 if ( event == nil )
230 return -1;
91407318 231
902ddbfd 232 [NSApp sendEvent: event];
91407318 233
902ddbfd
SC
234 return 1;
235 }
91407318 236}
80eee837
SC
237
238void wxGUIEventLoop::DoRun()
239{
240 wxMacAutoreleasePool autoreleasepool;
241 [NSApp run];
242}
243
244void wxGUIEventLoop::DoStop()
245{
246 [NSApp stop:0];
2e5f9929
SC
247 // only calling stop: is not enough when called from a runloop-observer,
248 // therefore add a dummy event, to make sure the runloop gets another round
249 NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined
250 location:NSMakePoint(0.0, 0.0)
251 modifierFlags:0
252 timestamp:0
253 windowNumber:0
254 context:nil
255 subtype:0 data1:0 data2:0];
256 [NSApp postEvent:event atStart:FALSE];
80eee837
SC
257}
258
7934e447
SC
259CFRunLoopRef wxGUIEventLoop::CFGetCurrentRunLoop() const
260{
261 NSRunLoop* nsloop = [NSRunLoop currentRunLoop];
262 return [nsloop getCFRunLoop];
263}
264
265
cfb0ef70
SC
266// TODO move into a evtloop_osx.cpp
267
268wxModalEventLoop::wxModalEventLoop(wxWindow *modalWindow)
2439f1d9 269{
cfb0ef70 270 m_modalWindow = dynamic_cast<wxNonOwnedWindow*> (modalWindow);
2439f1d9 271 wxASSERT_MSG( m_modalWindow != NULL, "must pass in a toplevel window for modal event loop" );
cfb0ef70 272 m_modalNativeWindow = m_modalWindow->GetWXWindow();
2439f1d9
SC
273}
274
cfb0ef70
SC
275wxModalEventLoop::wxModalEventLoop(WXWindow modalNativeWindow)
276{
277 m_modalWindow = NULL;
278 wxASSERT_MSG( modalNativeWindow != NULL, "must pass in a toplevel window for modal event loop" );
279 m_modalNativeWindow = modalNativeWindow;
280}
281
282// END move into a evtloop_osx.cpp
283
80eee837
SC
284void wxModalEventLoop::DoRun()
285{
286 wxMacAutoreleasePool pool;
287
288 // If the app hasn't started, flush the event queue
289 // If we don't do this, the Dock doesn't get the message that
290 // the app has started so will refuse to activate it.
291 [NSApplication sharedApplication];
292 if (![NSApp isRunning])
293 {
294 while(NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES])
295 {
296 [NSApp sendEvent:event];
297 }
298 }
299
cfb0ef70 300 [NSApp runModalForWindow:m_modalNativeWindow];
80eee837
SC
301}
302
303void wxModalEventLoop::DoStop()
304{
305 [NSApp stopModal];
306}
307
902ddbfd
SC
308void wxGUIEventLoop::BeginModalSession( wxWindow* modalWindow )
309{
310 WXWindow nsnow = nil;
311
312 if ( modalWindow )
313 {
b64af07b
SC
314 // we must show now, otherwise beginModalSessionForWindow does it but it
315 // also would do a centering of the window before overriding all our position
316 if ( !modalWindow->IsShownOnScreen() )
317 modalWindow->Show();
318
902ddbfd
SC
319 wxNonOwnedWindow* now = dynamic_cast<wxNonOwnedWindow*> (modalWindow);
320 wxASSERT_MSG( now != NULL, "must pass in a toplevel window for modal event loop" );
321 nsnow = now ? now->GetWXWindow() : nil;
322 }
323 else
324 {
325 NSRect r = NSMakeRect(10, 10, 0, 0);
326 nsnow = [NSPanel alloc];
327 [nsnow initWithContentRect:r
328 styleMask:NSBorderlessWindowMask
329 backing:NSBackingStoreBuffered
330 defer:YES
331 ];
332 [nsnow orderOut:nil];
333 m_dummyWindow = nsnow;
334 }
335 m_modalSession = [NSApp beginModalSessionForWindow:nsnow];
336}
337
338void wxGUIEventLoop::EndModalSession()
339{
340 wxASSERT_MSG(m_modalSession != NULL, "no modal session active");
341 [NSApp endModalSession:(NSModalSession)m_modalSession];
342 m_modalSession = nil;
343 if ( m_dummyWindow )
344 {
345 [m_dummyWindow release];
346 m_dummyWindow = nil;
347 }
348}
349
350//
351//
352//
353
354wxWindowDisabler::wxWindowDisabler(bool disable)
355{
356 m_modalEventLoop = NULL;
357 m_disabled = disable;
358 if ( disable )
359 DoDisable();
360}
361
362wxWindowDisabler::wxWindowDisabler(wxWindow *winToSkip)
363{
364 m_disabled = true;
365 DoDisable(winToSkip);
366}
367
368void wxWindowDisabler::DoDisable(wxWindow *winToSkip)
369{
370 // remember the top level windows which were already disabled, so that we
371 // don't reenable them later
372 m_winDisabled = NULL;
373
374 wxWindowList::compatibility_iterator node;
375 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
376 {
377 wxWindow *winTop = node->GetData();
378 if ( winTop == winToSkip )
379 continue;
380
381 // we don't need to disable the hidden or already disabled windows
382 if ( winTop->IsEnabled() && winTop->IsShown() )
383 {
384 winTop->Disable();
385 }
386 else
387 {
388 if ( !m_winDisabled )
389 {
390 m_winDisabled = new wxWindowList;
391 }
392
393 m_winDisabled->Append(winTop);
394 }
395 }
396
397 m_modalEventLoop = (wxEventLoop*)wxEventLoopBase::GetActive();
398 m_modalEventLoop->BeginModalSession(winToSkip);
399}
400
401wxWindowDisabler::~wxWindowDisabler()
402{
403 if ( !m_disabled )
404 return;
405
406 m_modalEventLoop->EndModalSession();
407
408 wxWindowList::compatibility_iterator node;
409 for ( node = wxTopLevelWindows.GetFirst(); node; node = node->GetNext() )
410 {
411 wxWindow *winTop = node->GetData();
412 if ( !m_winDisabled || !m_winDisabled->Find(winTop) )
413 {
414 winTop->Enable();
415 }
416 //else: had been already disabled, don't reenable
417 }
418
419 delete m_winDisabled;
420}
421