X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b2680ced12cbbed16990007c5fa3ea7730700122..488addd58a902c3c5b713c6f81721e39c5779693:/src/osx/carbon/app.cpp?ds=inline diff --git a/src/osx/carbon/app.cpp b/src/osx/carbon/app.cpp index b2559ecd71..e1df3f151a 100644 --- a/src/osx/carbon/app.cpp +++ b/src/osx/carbon/app.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: src/mac/carbon/app.cpp +// Name: src/osx/carbon/app.cpp // Purpose: wxApp // Author: Stefan Csomor // Modified by: @@ -40,6 +40,7 @@ #include "wx/filename.h" #include "wx/link.h" #include "wx/thread.h" +#include "wx/evtloop.h" #include @@ -57,13 +58,6 @@ // Keep linker from discarding wxStockGDIMac wxFORCE_LINK_MODULE(gdiobj) -// statics for implementation -static bool s_inYield = false; -static bool s_inReceiveEvent = false ; -#if wxOSX_USE_COCOA_OR_CARBON -static EventTime sleepTime = kEventDurationNoWait ; -#endif - IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) EVT_IDLE(wxApp::OnIdle) @@ -85,7 +79,7 @@ wxString wxApp::s_macHelpMenuTitleName = wxT("&Help") ; bool wxApp::sm_isEmbedded = false; // Normally we're not a plugin -#if wxOSX_USE_COCOA_OR_CARBON +#if wxOSX_USE_CARBON //---------------------------------------------------------------------- // Core Apple Event Support @@ -190,7 +184,7 @@ short wxApp::MacHandleAEGURL(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply)) if (err != noErr) return err; - url[actualSize] = '\0'; // Terminate the C string + url[actualSize] = '\0'; // Terminate the C string ProcessSerialNumber PSN ; PSN.highLongOfPSN = 0 ; @@ -363,9 +357,9 @@ void wxApp::MacReopenApp() // make sure we don't show 'virtual toplevel windows' like wxTaskBarIconWindow if ( firstHidden == NULL && ( wxDynamicCast( win, wxFrame ) || wxDynamicCast( win, wxDialog ) ) ) firstHidden = win ; - } + } else if ( win->IsIconized() ) - { + { if ( firstIconized == NULL ) firstIconized = win ; } @@ -505,7 +499,7 @@ wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item ) // is it part of the application or the Help menu, then look for the id directly if ( ( GetMenuHandle( kwxMacAppleMenuId ) != NULL && command.menu.menuRef == GetMenuHandle( kwxMacAppleMenuId ) ) || - ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) || + ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) || wxMenuBar::MacGetWindowMenuHMenu() != NULL && command.menu.menuRef == wxMenuBar::MacGetWindowMenuHMenu() ) { wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ; @@ -514,12 +508,12 @@ wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item ) } else { - URefCon refCon ; + URefCon refCon = NULL ; GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , &refCon ) ; itemMenu = wxFindMenuFromMacMenu( command.menu.menuRef ) ; - if ( itemMenu != NULL ) - item = (wxMenuItem*) refCon ; + if ( itemMenu != NULL && refCon != 0) + item = ((wxMenuItemImpl*) refCon)->GetWXPeer() ; } } #endif @@ -569,22 +563,31 @@ wxMacAppMenuEventHandler( EventHandlerCallRef WXUNUSED(handler), if ( menu ) { - wxEventType type=0; - MenuCommand cmd=0; switch (GetEventKind(event)) { case kEventMenuOpening: - type = wxEVT_MENU_OPEN; + menu->HandleMenuOpened(); break; case kEventMenuClosed: - type = wxEVT_MENU_CLOSE; + menu->HandleMenuClosed(); break; case kEventMenuTargetItem: - cmd = cEvent.GetParameter(kEventParamMenuCommand,typeMenuCommand) ; - if (cmd != 0) - type = wxEVT_MENU_HIGHLIGHT; + { + HICommand command ; + + command.menu.menuRef = menuRef; + command.menu.menuItemIndex = cEvent.GetParameter(kEventParamMenuItemIndex,typeMenuItemIndex) ; + command.commandID = cEvent.GetParameter(kEventParamMenuCommand,typeMenuCommand) ; + if (command.commandID != 0) + { + wxMenuItem* item = NULL ; + wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ; + if ( itemMenu && item ) + itemMenu->HandleMenuItemHighlighted( item ); + } + } break; default: @@ -592,23 +595,6 @@ wxMacAppMenuEventHandler( EventHandlerCallRef WXUNUSED(handler), break; } - if ( type ) - { - wxMenuEvent wxevent(type, cmd, menu); - wxevent.SetEventObject(menu); - - wxEvtHandler* handler = menu->GetEventHandler(); - if (handler && handler->ProcessEvent(wxevent)) - { - // handled - } - else - { - wxWindow *win = menu->GetInvokingWindow(); - if (win) - win->HandleWindowEvent(wxevent); - } - } } #endif return eventNotHandledErr; @@ -628,7 +614,6 @@ wxMacAppCommandEventHandler( EventHandlerCallRef WXUNUSED(handler) , wxMenuItem* item = NULL ; wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ; - int id = wxMacCommandToId( command.commandID ) ; if ( item ) { @@ -637,11 +622,13 @@ wxMacAppCommandEventHandler( EventHandlerCallRef WXUNUSED(handler) , switch ( cEvent.GetKind() ) { case kEventProcessCommand : - result = itemMenu->MacHandleCommandProcess( item, id ); + if ( itemMenu->HandleCommandProcess( item ) ) + result = noErr; break ; case kEventCommandUpdateStatus: - result = itemMenu->MacHandleCommandUpdateStatus( item, id ); + if ( itemMenu->HandleCommandUpdateStatus( item ) ) + result = noErr; break ; default : @@ -843,21 +830,43 @@ bool wxApp::Initialize(int& argc, wxChar **argv) /* connect posted events to common-mode run loop so that wxPostEvent events are handled even while we're in the menu or on a scrollbar */ + /* CFRunLoopSourceContext event_posted_context = {0}; event_posted_context.perform = macPostedEventCallback; m_macEventPosted = CFRunLoopSourceCreate(NULL,0,&event_posted_context); CFRunLoopAddSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes); // run loop takes ownership CFRelease(m_macEventPosted); - + */ return true; } +bool wxApp::CallOnInit() +{ + wxMacAutoreleasePool autoreleasepool; + return OnInit(); +} + bool wxApp::OnInitGui() { if ( !wxAppBase::OnInitGui() ) return false ; + + if ( !DoInitGui() ) + return false; + + return true ; +} + +bool wxApp::ProcessIdle() +{ + wxMacAutoreleasePool autoreleasepool; + return wxAppBase::ProcessIdle(); +} + #if wxOSX_USE_CARBON +bool wxApp::DoInitGui() +{ InstallStandardEventHandler( GetApplicationEventTarget() ) ; if (!sm_isEmbedded) { @@ -865,9 +874,7 @@ bool wxApp::OnInitGui() GetwxMacAppEventHandlerUPP(), GetEventTypeCount(eventList), eventList, wxTheApp, (EventHandlerRef *)&(wxTheApp->m_macEventHandler)); } -#endif -#if wxOSX_USE_COCOA_OR_CARBON if (!sm_isEmbedded) { sODocHandler = NewAEEventHandlerUPP(AEHandleODoc) ; @@ -890,32 +897,15 @@ bool wxApp::OnInitGui() AEInstallEventHandler( kCoreEventClass , kAEQuitApplication , sQuitHandler , 0 , FALSE ) ; } -#endif -#if wxOSX_USE_CARBON + if ( !wxMacInitCocoa() ) return false; -#endif - return true ; + return true; } -void wxApp::CleanUp() +void wxApp::DoCleanUp() { -#if wxUSE_TOOLTIPS - wxToolTip::RemoveToolTips() ; -#endif - - if (m_macEventPosted) - { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes); - m_macEventPosted = NULL; - } - - // One last chance for pending objects to be cleaned up - wxTheApp->DeletePendingObjects(); - -#if wxOSX_USE_COCOA_OR_CARBON - if (!sm_isEmbedded) RemoveEventHandler( (EventHandlerRef)(wxTheApp->m_macEventHandler) ); @@ -941,9 +931,24 @@ void wxApp::CleanUp() DisposeAEEventHandlerUPP( sRAppHandler ) ; DisposeAEEventHandlerUPP( sQuitHandler ) ; } +} + +#endif +void wxApp::CleanUp() +{ +#if wxUSE_TOOLTIPS + wxToolTip::RemoveToolTips() ; #endif + if (m_macEventPosted) + { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes); + m_macEventPosted = NULL; + } + + DoCleanUp(); + wxAppBase::CleanUp(); } @@ -951,7 +956,7 @@ void wxApp::CleanUp() // misc initialization stuff //---------------------------------------------------------------------- -#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +#if wxOSX_USE_CARBON && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 bool wxMacConvertEventToRecord( EventRef event , EventRecord *rec) { OSStatus err = noErr ; @@ -1052,15 +1057,31 @@ wxApp::wxApp() m_macEventPosted = NULL ; } +CFMutableArrayRef GetAutoReleaseArray() +{ + static CFMutableArrayRef array = 0; + if ( array == 0) + array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks); + return array; +} + +void wxApp::MacAddToAutorelease( void* cfrefobj ) +{ + CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj ); +} + void wxApp::OnIdle(wxIdleEvent& WXUNUSED(event)) { // If they are pending events, we must process them: pending events are // either events to the threads other than main or events posted with // wxPostEvent() functions #ifndef __WXUNIVERSAL__ +#if wxUSE_MENUS if (!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar()) wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar(); #endif +#endif + CFArrayRemoveAllValues( GetAutoReleaseArray() ); } void wxApp::WakeUpIdle() @@ -1100,16 +1121,6 @@ void wxCYield() bool wxApp::Yield(bool onlyIfNeeded) { - if (s_inYield) - { - if ( !onlyIfNeeded ) - { - wxFAIL_MSG( wxT("wxYield called recursively" ) ); - } - - return false; - } - #if wxUSE_THREADS // Yielding from a non-gui thread needs to bail out, otherwise we end up // possibly sending events in the thread too. @@ -1119,82 +1130,44 @@ bool wxApp::Yield(bool onlyIfNeeded) } #endif // wxUSE_THREADS - s_inYield = true; - - // by definition yield should handle all non-processed events - -#if wxOSX_USE_COCOA_OR_CARBON - - EventRef theEvent; - - OSStatus status = noErr ; - - while ( status == noErr ) + if (m_isInsideYield) { - s_inReceiveEvent = true ; - status = ReceiveNextEvent(0, NULL,kEventDurationNoWait,true,&theEvent) ; - s_inReceiveEvent = false ; - - if ( status == eventLoopTimedOutErr ) - { - // make sure next time the event loop will trigger idle events - sleepTime = kEventDurationNoWait ; - } - else if ( status == eventLoopQuitErr ) - { - // according to QA1061 this may also occur when a WakeUp Process - // is executed - } - else + if ( !onlyIfNeeded ) { - MacHandleOneEvent( theEvent ) ; - ReleaseEvent(theEvent); + wxFAIL_MSG( wxT("wxYield called recursively" ) ); } - } - -#else - -#endif - - s_inYield = false; - return true; -} + return false; + } -void wxApp::MacDoOneEvent() -{ -#if wxOSX_USE_COCOA_OR_CARBON - wxMacAutoreleasePool autoreleasepool; - EventRef theEvent; + m_isInsideYield = true; - s_inReceiveEvent = true ; - OSStatus status = ReceiveNextEvent(0, NULL, sleepTime, true, &theEvent) ; - s_inReceiveEvent = false ; +#if wxUSE_LOG + // disable log flushing from here because a call to wxYield() shouldn't + // normally result in message boxes popping up &c + wxLog::Suspend(); +#endif // wxUSE_LOG - switch (status) + wxEventLoop * const + loop = static_cast(wxEventLoop::GetActive()); + if ( loop ) { - case eventLoopTimedOutErr : - if ( wxTheApp->ProcessIdle() ) - sleepTime = kEventDurationNoWait ; - else - sleepTime = kEventDurationSecond; - break; + // process all pending events: + while ( loop->Pending() ) + loop->Dispatch(); + } - case eventLoopQuitErr : - // according to QA1061 this may also occur - // when a WakeUp Process is executed - break; + // it's necessary to call ProcessIdle() to update the frames sizes which + // might have been changed (it also will update other things set from + // OnUpdateUI() which is a nice (and desired) side effect) + while ( ProcessIdle() ) {} - default: - MacHandleOneEvent( theEvent ) ; - ReleaseEvent( theEvent ); - sleepTime = kEventDurationNoWait ; - break; - } - // repeaters -#else -#endif - DeletePendingObjects() ; +#if wxUSE_LOG + wxLog::Resume(); +#endif // wxUSE_LOG + m_isInsideYield = false; + + return true; } // virtual @@ -1203,52 +1176,7 @@ void wxApp::MacHandleUnhandledEvent( WXEVENTREF WXUNUSED(evr) ) // Override to process unhandled events as you please } -CFMutableArrayRef GetAutoReleaseArray() -{ - static CFMutableArrayRef array = 0; - if ( array == 0) - array= CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks); - return array; -} - -// -// -// - - -// -// -// - -void wxApp::MacHandleOneEvent( WXEVENTREF evr ) -{ -#if wxOSX_USE_COCOA_OR_CARBON - EventTargetRef theTarget; - theTarget = GetEventDispatcherTarget(); - m_macCurrentEvent = evr ; - - OSStatus status = SendEventToEventTarget((EventRef) evr , theTarget); - if (status == eventNotHandledErr) - MacHandleUnhandledEvent(evr); - -#if wxUSE_THREADS - wxMutexGuiLeaveOrEnter(); -#endif // wxUSE_THREADS - -#else - // TODO Threads -#endif - - - CFArrayRemoveAllValues( GetAutoReleaseArray() ); -} - -void wxApp::MacAddToAutorelease( void* cfrefobj ) -{ - CFArrayAppendValue( GetAutoReleaseArray(), cfrefobj ); -} - -#if wxOSX_USE_COCOA_OR_CARBON +#if wxOSX_USE_CARBON long wxMacTranslateKey(unsigned char key, unsigned char code) { @@ -1420,12 +1348,12 @@ int wxMacKeyCodeToModifier(wxKeyCode key) wxMouseState wxGetMouseState() { wxMouseState ms; -#if wxOSX_USE_COCOA_OR_CARBON wxPoint pt = wxGetMousePosition(); ms.SetX(pt.x); ms.SetY(pt.y); +#if wxOSX_USE_CARBON UInt32 buttons = GetCurrentButtonState(); ms.SetLeftDown( (buttons & 0x01) != 0 ); ms.SetMiddleDown( (buttons & 0x04) != 0 ); @@ -1436,7 +1364,8 @@ wxMouseState wxGetMouseState() ms.SetShiftDown(modifiers & shiftKey); ms.SetAltDown(modifiers & optionKey); ms.SetMetaDown(modifiers & cmdKey); - +#else + // TODO #endif return ms; } @@ -1596,7 +1525,7 @@ bool wxApp::MacSendCharEvent( wxWindow* focus , long keymessage , long modifiers // This method handles common code for SendKeyDown, SendKeyUp, and SendChar events. void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , short wherex , short wherey , wxChar uniChar ) { -#if wxOSX_USE_COCOA_OR_CARBON +#if wxOSX_USE_CARBON short keycode, keychar ; keychar = short(keymessage & charCodeMask); @@ -1627,34 +1556,34 @@ void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymess { keyval = (keyval - '0') + WXK_NUMPAD0; } - else if (keycode >= 65 && keycode <= 81) + else if (keycode >= 65 && keycode <= 81) { switch (keycode) { case 76 : keyval = WXK_NUMPAD_ENTER; break; - + case 81: keyval = WXK_NUMPAD_EQUAL; break; - + case 67: keyval = WXK_NUMPAD_MULTIPLY; break; - + case 75: keyval = WXK_NUMPAD_DIVIDE; break; - + case 78: keyval = WXK_NUMPAD_SUBTRACT; break; - + case 69: keyval = WXK_NUMPAD_ADD; break; - + case 65: keyval = WXK_NUMPAD_DECIMAL; break; @@ -1663,7 +1592,7 @@ void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymess } } } - + event.m_shiftDown = modifiers & shiftKey; event.m_controlDown = modifiers & controlKey; event.m_altDown = modifiers & optionKey; @@ -1690,7 +1619,7 @@ void wxApp::MacHideApp() HICommand command; memset( &command, 0 , sizeof(command) ); command.commandID = kHICommandHide ; - event.SetParameter(kEventParamDirectObject, command ); + event.SetParameter(kEventParamDirectObject, command ); SendEventToApplication( event ); #endif }