From 80eee8378f6b6e8b9ecae46062c2b66ff4469f48 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Wed, 17 Mar 2010 07:14:03 +0000 Subject: [PATCH] streamlining OSX event support third step, using platform specific native run methods for event loops git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63697 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/evtloop.h | 4 +- include/wx/osx/carbon/evtloop.h | 3 ++ include/wx/osx/cocoa/evtloop.h | 3 ++ include/wx/osx/evtloop.h | 36 +++++++++++++---- include/wx/unix/evtloop.h | 7 +++- src/common/evtloopcmn.cpp | 2 +- src/osx/carbon/evtloop.cpp | 55 ++++++++++++++++++++++++++ src/osx/cocoa/evtloop.mm | 37 ++++++++++++++++++ src/osx/core/evtloop_cf.cpp | 69 ++++++++++++++++++++++++--------- src/osx/iphone/evtloop.mm | 51 ++++++++++++++++-------- 10 files changed, 221 insertions(+), 46 deletions(-) diff --git a/include/wx/evtloop.h b/include/wx/evtloop.h index 6da21416a5..642cc128f0 100644 --- a/include/wx/evtloop.h +++ b/include/wx/evtloop.h @@ -185,7 +185,7 @@ protected: wxDECLARE_NO_COPY_CLASS(wxEventLoopBase); }; -#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXDFB__) || defined(__UNIX__) +#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXDFB__) || (defined(__UNIX__) && !defined(__WXOSX__)) // this class can be used to implement a standard event loop logic using // Pending() and Dispatch() @@ -318,7 +318,7 @@ protected: inline bool wxEventLoopBase::IsRunning() const { return GetActive() == this; } -#if wxUSE_GUI +#if wxUSE_GUI && !defined(__WXOSX__) // ---------------------------------------------------------------------------- // wxModalEventLoop // ---------------------------------------------------------------------------- diff --git a/include/wx/osx/carbon/evtloop.h b/include/wx/osx/carbon/evtloop.h index 0824ca2636..3ebda2efa8 100644 --- a/include/wx/osx/carbon/evtloop.h +++ b/include/wx/osx/carbon/evtloop.h @@ -23,6 +23,9 @@ public: protected: virtual int DoDispatchTimeout(unsigned long timeout); + virtual void DoRun(); + + virtual void DoStop(); }; #endif // _WX_MAC_CARBON_EVTLOOP_H_ diff --git a/include/wx/osx/cocoa/evtloop.h b/include/wx/osx/cocoa/evtloop.h index be4e788bbb..79c25c2b00 100644 --- a/include/wx/osx/cocoa/evtloop.h +++ b/include/wx/osx/cocoa/evtloop.h @@ -19,6 +19,9 @@ public: protected: virtual int DoDispatchTimeout(unsigned long timeout); + virtual void DoRun(); + + virtual void DoStop(); }; #endif // _WX_OSX_COCOA_EVTLOOP_H_ diff --git a/include/wx/osx/evtloop.h b/include/wx/osx/evtloop.h index 100804ae2a..bc6b5fddfe 100644 --- a/include/wx/osx/evtloop.h +++ b/include/wx/osx/evtloop.h @@ -59,7 +59,11 @@ protected: virtual CFRunLoopRef CFGetCurrentRunLoop() const; virtual int DoDispatchTimeout(unsigned long timeout); + + virtual void DoRun(); + virtual void DoStop(); + // should we exit the loop? bool m_shouldExit; @@ -68,22 +72,40 @@ protected: // runloop observer CFRunLoopObserverRef m_runLoopObserver; - + private: // process all already pending events and dispatch a new one (blocking // until it appears in the event queue if necessary) // // returns the return value of DoDispatchTimeout() int DoProcessEvents(); - }; #if wxUSE_GUI - #ifdef __WXOSX_COCOA__ - #include "wx/osx/cocoa/evtloop.h" - #else - #include "wx/osx/carbon/evtloop.h" - #endif + +#ifdef __WXOSX_COCOA__ + #include "wx/osx/cocoa/evtloop.h" +#else + #include "wx/osx/carbon/evtloop.h" +#endif + +class WXDLLIMPEXP_FWD_CORE wxWindow; +class WXDLLIMPEXP_FWD_CORE wxNonOwnedWindow; + +class WXDLLIMPEXP_CORE wxModalEventLoop : public wxGUIEventLoop +{ +public: + wxModalEventLoop(wxWindow *winModal); + +protected: + virtual void DoRun(); + + virtual void DoStop(); + + // (in case) the modal window for this event loop + wxNonOwnedWindow* m_modalWindow; +}; + #endif // wxUSE_GUI #endif // _WX_OSX_EVTLOOP_H_ diff --git a/include/wx/unix/evtloop.h b/include/wx/unix/evtloop.h index 40d3007787..1c47c5cd55 100644 --- a/include/wx/unix/evtloop.h +++ b/include/wx/unix/evtloop.h @@ -25,7 +25,12 @@ namespace wxPrivate class PipeIOHandler; } -class WXDLLIMPEXP_BASE wxConsoleEventLoop : public wxEventLoopManual +class WXDLLIMPEXP_BASE wxConsoleEventLoop +#ifdef __WXOSX__ +: public wxEventLoopBase +#else +: public wxEventLoopManual +#endif { public: // initialize the event loop, use IsOk() to check if we were successful diff --git a/src/common/evtloopcmn.cpp b/src/common/evtloopcmn.cpp index 5f9894d125..300a1885d1 100644 --- a/src/common/evtloopcmn.cpp +++ b/src/common/evtloopcmn.cpp @@ -82,7 +82,7 @@ bool wxEventLoopBase::Yield(bool onlyIfNeeded) } // wxEventLoopManual is unused in the other ports -#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXDFB__) || (defined(__UNIX__) && wxUSE_BASE) +#if defined(__WXMSW__) || defined(__WXDFB__) || ( ( defined(__UNIX__) && !defined(__WXOSX__) ) && wxUSE_BASE) // ============================================================================ // wxEventLoopManual implementation diff --git a/src/osx/carbon/evtloop.cpp b/src/osx/carbon/evtloop.cpp index abaafd3181..218b945b41 100644 --- a/src/osx/carbon/evtloop.cpp +++ b/src/osx/carbon/evtloop.cpp @@ -55,6 +55,8 @@ static void DispatchAndReleaseEvent(EventRef theEvent) int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout) { + wxMacAutoreleasePool autoreleasepool; + EventRef event; OSStatus status = ReceiveNextEvent(0, NULL, timeout/1000, true, &event); switch ( status ) @@ -76,3 +78,56 @@ int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout) return 1; } } + +void wxGUIEventLoop::DoRun() +{ + wxMacAutoreleasePool autoreleasepool; + RunApplicationEventLoop(); +} + +void wxGUIEventLoop::DoStop() +{ + QuitApplicationEventLoop(); +} + +void wxModalEventLoop::DoRun() +{ + wxMacAutoreleasePool autoreleasepool; + WindowRef windowRef = m_modalWindow->GetWXWindow(); + + WindowGroupRef windowGroup = NULL; + WindowGroupRef formerParentGroup = NULL; + bool resetGroupParent = false; + + // make sure modal dialogs are in the right layer so that they are not covered + + if ( m_modalWindow->GetParent() == NULL ) + { + windowGroup = GetWindowGroup(windowRef) ; + if ( windowGroup != GetWindowGroupOfClass( kMovableModalWindowClass ) ) + { + formerParentGroup = GetWindowGroupParent( windowGroup ); + SetWindowGroupParent( windowGroup, GetWindowGroupOfClass( kMovableModalWindowClass ) ); + resetGroupParent = true; + } + } + + m_modalWindow->SetFocus(); + + RunAppModalLoopForWindow(windowRef); + + if ( resetGroupParent ) + { + SetWindowGroupParent( windowGroup , formerParentGroup ); + } + +} + +void wxModalEventLoop::DoStop() +{ + wxMacAutoreleasePool autoreleasepool; + WindowRef theWindow = m_modalWindow->GetWXWindow(); + QuitAppModalLoopForWindow(theWindow); +} + + diff --git a/src/osx/cocoa/evtloop.mm b/src/osx/cocoa/evtloop.mm index 69c550b6d0..97a3b76330 100644 --- a/src/osx/cocoa/evtloop.mm +++ b/src/osx/cocoa/evtloop.mm @@ -162,3 +162,40 @@ int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout) return 1; } + +void wxGUIEventLoop::DoRun() +{ + wxMacAutoreleasePool autoreleasepool; + [NSApp run]; +} + +void wxGUIEventLoop::DoStop() +{ + [NSApp stop:0]; +} + +void wxModalEventLoop::DoRun() +{ + wxMacAutoreleasePool pool; + + // If the app hasn't started, flush the event queue + // If we don't do this, the Dock doesn't get the message that + // the app has started so will refuse to activate it. + [NSApplication sharedApplication]; + if (![NSApp isRunning]) + { + while(NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]) + { + [NSApp sendEvent:event]; + } + } + + NSWindow* theWindow = m_modalWindow->GetWXWindow(); + [NSApp runModalForWindow:theWindow]; +} + +void wxModalEventLoop::DoStop() +{ + [NSApp stopModal]; +} + diff --git a/src/osx/core/evtloop_cf.cpp b/src/osx/core/evtloop_cf.cpp index d16ed3ea2e..429312ac88 100644 --- a/src/osx/core/evtloop_cf.cpp +++ b/src/osx/core/evtloop_cf.cpp @@ -185,6 +185,7 @@ void wxCFEventLoop::ObserverCallBack(CFRunLoopObserverRef observer, int activity wxCFEventLoop::wxCFEventLoop() { m_shouldExit = false; + CFRunLoopObserverContext ctxt; bzero( &ctxt, sizeof(ctxt) ); ctxt.info = this; @@ -272,8 +273,6 @@ int wxCFEventLoop::DispatchTimeout(unsigned long timeout) if ( !wxTheApp ) return 0; - wxMacAutoreleasePool autoreleasepool; - int status = DoDispatchTimeout(timeout); switch( status ) @@ -313,6 +312,32 @@ int wxCFEventLoop::DoDispatchTimeout(unsigned long timeout) return 1; } +void wxCFEventLoop::DoRun() +{ + for ( ;; ) + { + // generate and process idle events for as long as we don't + // have anything else to do + DoProcessEvents(); + + // if the "should exit" flag is set, the loop should terminate + // but not before processing any remaining messages so while + // Pending() returns true, do process them + if ( m_shouldExit ) + { + while ( DoProcessEvents() == 1 ) + ; + + break; + } + } +} + +void wxCFEventLoop::DoStop() +{ + CFRunLoopStop(CFGetCurrentRunLoop()); +} + // enters a loop calling OnNextIteration(), Pending() and Dispatch() and // terminating when Exit() is called int wxCFEventLoop::Run() @@ -336,23 +361,8 @@ int wxCFEventLoop::Run() try { #endif // wxUSE_EXCEPTIONS - for ( ;; ) - { - // generate and process idle events for as long as we don't - // have anything else to do - DoProcessEvents(); - // if the "should exit" flag is set, the loop should terminate - // but not before processing any remaining messages so while - // Pending() returns true, do process them - if ( m_shouldExit ) - { - while ( DoProcessEvents() == 1 ) - ; - - break; - } - } + DoRun(); #if wxUSE_EXCEPTIONS // exit the outer loop as well @@ -390,6 +400,29 @@ void wxCFEventLoop::Exit(int rc) { m_exitcode = rc; m_shouldExit = true; + DoStop(); +} + +#if wxUSE_GUI + +wxModalEventLoop::wxModalEventLoop(wxWindow *winModal) +{ + m_modalWindow = dynamic_cast (winModal); + wxASSERT_MSG( m_modalWindow != NULL, "must pass in a toplevel window for modal event loop" ); } +#ifdef __WXOSX_IPHONE__ +void wxModalEventLoop::DoRun() +{ + // presentModalViewController:animated: +} + +void wxModalEventLoop::DoStop() +{ + // (void)dismissModalViewControllerAnimated:(BOOL)animated +} + +#endif // wxUSE_GUI + +#endif diff --git a/src/osx/iphone/evtloop.mm b/src/osx/iphone/evtloop.mm index 67e4784965..ca463a6dcf 100644 --- a/src/osx/iphone/evtloop.mm +++ b/src/osx/iphone/evtloop.mm @@ -75,26 +75,43 @@ static int CalculateUIEventMaskFromEventCategory(wxEventCategory cat) } */ -wxGUIEventLoop::wxGUIEventLoop() -{ - m_sleepTime = 0.0; +@interface wxAppDelegate : NSObject { } -int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout) -{ - wxMacAutoreleasePool autoreleasepool; +@end -/* - UIEvent *event = [[UIApplication sharedApplication] - nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate dateWithTimeIntervalSinceNow: timeout/1000] - inMode:NSDefaultRunLoopMode - dequeue: YES]; +@implementation wxAppDelegate - if ( event == nil ) - return -1; +- (void)applicationDidFinishLaunching:(UIApplication *)application { + wxTheApp->OnInit(); +} - [NSApp sendEvent: event]; -*/ - return 1; +- (void)applicationWillTerminate:(UIApplication *)application { + wxCloseEvent event; + wxTheApp->OnEndSession(event); +} + +- (void)dealloc { + [super dealloc]; } + +@end + +wxGUIEventLoop::wxGUIEventLoop() +{ +} + +void wxGUIEventLoop::DoRun() +{ + if ( IsMain() ) + { + wxMacAutoreleasePool pool; + const char* appname = "app"; + UIApplicationMain( 1, (char**) &appname, nil, @"wxAppDelegate" ); + } + else + { + wxCFEventLoop::DoRun(); + } +} + -- 2.45.2