X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b2680ced12cbbed16990007c5fa3ea7730700122..08670ea85abf4b4946a9ce64971b591d7b1ee30b:/src/osx/carbon/evtloop.cpp diff --git a/src/osx/carbon/evtloop.cpp b/src/osx/carbon/evtloop.cpp index deee02fdce..d263effec7 100644 --- a/src/osx/carbon/evtloop.cpp +++ b/src/osx/carbon/evtloop.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: src/mac/carbon/evtloop.cpp +// Name: src/osx/carbon/evtloop.cpp // Purpose: implementation of wxEventLoop for wxMac // Author: Vadim Zeitlin // Modified by: @@ -28,92 +28,145 @@ #ifndef WX_PRECOMP #include "wx/app.h" + #include "wx/log.h" #endif // WX_PRECOMP -#if wxOSX_USE_CARBON - #include -#else - #include +#if wxUSE_GUI +#include "wx/nonownedwnd.h" #endif + +#include "wx/osx/private.h" + // ============================================================================ // wxEventLoop implementation // ============================================================================ -// ---------------------------------------------------------------------------- -// high level functions for RunApplicationEventLoop() case -// ---------------------------------------------------------------------------- +wxGUIEventLoop::wxGUIEventLoop() +{ +} + +static void DispatchAndReleaseEvent(EventRef theEvent) +{ + if ( wxTheApp ) + wxTheApp->MacSetCurrentEvent( theEvent, NULL ); + OSStatus status = SendEventToEventTarget(theEvent, GetEventDispatcherTarget()); + if (status == eventNotHandledErr && wxTheApp) + wxTheApp->MacHandleUnhandledEvent(theEvent); + ReleaseEvent( theEvent ); +} -#if wxMAC_USE_RUN_APP_EVENT_LOOP +int wxGUIEventLoop::DoDispatchTimeout(unsigned long timeout) +{ + wxMacAutoreleasePool autoreleasepool; + + EventRef event; + OSStatus status = ReceiveNextEvent(0, NULL, timeout/1000, true, &event); + switch ( status ) + { + default: + wxFAIL_MSG( "unexpected ReceiveNextEvent() error" ); + // fall through + + case eventLoopTimedOutErr: + return -1; + + case eventLoopQuitErr: + // according to QA1061 this may also occur + // when a WakeUp Process is executed + return 0; + + case noErr: + DispatchAndReleaseEvent(event); + return 1; + } +} -int wxGUIEventLoop::Run() +void wxGUIEventLoop::WakeUp() { - wxEventLoopActivator activate(this); + OSStatus err = noErr; + wxMacCarbonEvent wakeupEvent; + wakeupEvent.Create( 'WXMC', 'WXMC', GetCurrentEventTime(), + kEventAttributeNone ); + err = PostEventToQueue(GetMainEventQueue(), wakeupEvent, + kEventPriorityHigh ); +} +void wxGUIEventLoop::DoRun() +{ + wxMacAutoreleasePool autoreleasepool; RunApplicationEventLoop(); - - return m_exitcode; } -void wxGUIEventLoop::Exit(int rc) +void wxGUIEventLoop::DoStop() { - m_exitcode = rc; - QuitApplicationEventLoop(); - - OnExit(); } -#else // manual event loop +CFRunLoopRef wxGUIEventLoop::CFGetCurrentRunLoop() const +{ + return wxCFEventLoop::CFGetCurrentRunLoop(); +} -// ---------------------------------------------------------------------------- -// functions only used by wxEventLoopManual-based implementation -// ---------------------------------------------------------------------------- +// TODO move into a evtloop_osx.cpp -void wxGUIEventLoop::WakeUp() +wxModalEventLoop::wxModalEventLoop(wxWindow *modalWindow) { - extern void wxMacWakeUp(); - - wxMacWakeUp(); + m_modalWindow = wxDynamicCast(modalWindow, wxNonOwnedWindow); + wxASSERT_MSG( m_modalWindow != NULL, "must pass in a toplevel window for modal event loop" ); + m_modalNativeWindow = m_modalWindow->GetWXWindow(); } -#endif // high/low-level event loop +wxModalEventLoop::wxModalEventLoop(WXWindow modalNativeWindow) +{ + m_modalWindow = NULL; + wxASSERT_MSG( modalNativeWindow != NULL, "must pass in a toplevel window for modal event loop" ); + m_modalNativeWindow = modalNativeWindow; +} -// ---------------------------------------------------------------------------- -// low level functions used in both cases -// ---------------------------------------------------------------------------- +// END move into a evtloop_osx.cpp -bool wxGUIEventLoop::Pending() const +void wxModalEventLoop::DoRun() { -#if wxOSX_USE_CARBON - EventRef theEvent; - - return ReceiveNextEvent - ( - 0, // we want any event at all so we don't specify neither - NULL, // the number of event types nor the types themselves - kEventDurationNoWait, - false, // don't remove the event from queue - &theEvent - ) == noErr; -#else - return true; // TODO -#endif + wxWindowDisabler disabler(m_modalWindow); + wxMacAutoreleasePool autoreleasepool; + + bool resetGroupParent = false; + + WindowGroupRef windowGroup = NULL; + WindowGroupRef formerParentGroup = NULL; + + // make sure modal dialogs are in the right layer so that they are not covered + if ( m_modalWindow != NULL ) + { + if ( m_modalWindow->GetParent() == NULL ) + { + windowGroup = GetWindowGroup(m_modalNativeWindow) ; + if ( windowGroup != GetWindowGroupOfClass( kMovableModalWindowClass ) ) + { + formerParentGroup = GetWindowGroupParent( windowGroup ); + SetWindowGroupParent( windowGroup, GetWindowGroupOfClass( kMovableModalWindowClass ) ); + resetGroupParent = true; + } + } + } + + m_modalWindow->SetFocus(); + + RunAppModalLoopForWindow(m_modalNativeWindow); + + if ( resetGroupParent ) + { + SetWindowGroupParent( windowGroup , formerParentGroup ); + } + } -bool wxGUIEventLoop::Dispatch() +void wxModalEventLoop::DoStop() { - if ( !wxTheApp ) - return false; - -#if wxOSX_USE_CARBON - // TODO: we probably should do the dispatching directly from here but for - // now it's easier to forward to wxApp which has all the code to do - // it - wxTheApp->MacDoOneEvent(); -#else - CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, 0); -#endif - return true; + wxMacAutoreleasePool autoreleasepool; + QuitAppModalLoopForWindow(m_modalNativeWindow); } + +