X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/73bdd73aa22ef33f346937d05bfb69bc04a0e430..ba8a4f660ae54de211a5869d7ea2c86cfd47cfeb:/src/mac/carbon/app.cpp diff --git a/src/mac/carbon/app.cpp b/src/mac/carbon/app.cpp index 39086ddeb8..63898fed72 100644 --- a/src/mac/carbon/app.cpp +++ b/src/mac/carbon/app.cpp @@ -73,7 +73,6 @@ extern wxList *wxWinMacControlList; // statics for implementation static bool s_inYield = FALSE; -static bool s_inOnIdle = FALSE; #if TARGET_CARBON static bool s_inReceiveEvent = FALSE ; @@ -288,6 +287,9 @@ void wxApp::MacNewFile() { kEventClassCommand, kEventProcessCommand } , { kEventClassCommand, kEventCommandUpdateStatus } , + { kEventClassMenu, kEventMenuOpening }, + { kEventClassMenu, kEventMenuClosed }, + { kEventClassApplication , kEventAppActivated } , { kEventClassApplication , kEventAppDeactivated } , // handling the quit event is not recommended by apple @@ -299,9 +301,35 @@ void wxApp::MacNewFile() { 'WXMC' , 'WXMC' } } ; -static pascal OSStatus MenuEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) +static pascal OSStatus +MenuEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) { - return eventNotHandledErr ; + // FIXME: this doesn't work for multiple windows + wxWindow *win = wxTheApp->GetTopWindow(); + if ( win ) + { + // VZ: we could find the menu from its handle here by examining all + // the menus in the menu bar recursively but knowing that neither + // wxMSW nor wxGTK do it why bother... +#if 0 + MenuRef menuRef; + + GetEventParameter(event, + kEventParamDirectObject, + typeMenuRef, NULL, + sizeof(menuRef), NULL, + &menuRef); +#endif // 0 + + wxMenuEvent wxevent(GetEventKind(event) == kEventMenuOpening + ? wxEVT_MENU_OPEN + : wxEVT_MENU_CLOSE); + wxevent.SetEventObject(win); + + (void)win->GetEventHandler()->ProcessEvent(wxevent); + } + + return eventNotHandledErr; } // due to the rather low-level event API of wxWindows, we cannot use RunApplicationEventLoop @@ -447,7 +475,7 @@ DEFINE_ONE_SHOT_HANDLER_GETTER( wxAppEventHandler ) WXIMPORT char std::__throws_bad_alloc ; #endif -bool wxApp::Initialize() +bool wxApp::Initialize(int& argc, wxChar **argv) { int error = 0 ; @@ -535,37 +563,31 @@ bool wxApp::Initialize() s_macCursorRgn = ::NewRgn() ; - wxClassInfo::InitializeClasses(); - -#if wxUSE_RESOURCES -// wxGetResource(wxT("wxWindows"), wxT("OsVersion"), &wxOsVersion); -#endif - -#if wxUSE_THREADS - wxPendingEventsLocker = new wxCriticalSection; -#endif + // Mac OS X passes a process serial number command line argument when + // the application is launched from the Finder. This argument must be + // removed from the command line arguments before being handled by the + // application (otherwise applications would need to handle it) + if ( argc > 1 ) + { + static const wxChar *ARG_PSN = _T("-psn_"); + if ( wxStrncmp(argv[1], ARG_PSN, sizeof(ARG_PSN) - 1) == 0 ) + { + // remove this argument + memmove(argv, argv + 1, argc--); + } + } - wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING); - wxTheColourDatabase->Initialize(); + if ( !wxAppBase::Initialize(argc, argv) ) + return false; wxWinMacWindowList = new wxList(wxKEY_INTEGER); wxWinMacControlList = new wxList(wxKEY_INTEGER); - wxInitializeStockLists(); - wxInitializeStockObjects(); - - wxBitmap::InitStandardHandlers(); - - wxModule::RegisterModules(); - if (!wxModule::InitializeModules()) { - return FALSE; - } - wxMacCreateNotifierTable() ; UMAShowArrowCursor() ; - return TRUE; + return true; } bool wxApp::OnInitGui() @@ -615,51 +637,17 @@ bool wxApp::OnInitGui() void wxApp::CleanUp() { wxToolTip::RemoveToolTips() ; -#if wxUSE_LOG - // flush the logged messages if any and install a 'safer' log target: the - // default one (wxLogGui) can't be used after the resources are freed just - // below and the user suppliedo ne might be even more unsafe (using any - // wxWindows GUI function is unsafe starting from now) - wxLog::DontCreateOnDemand(); - - // this will flush the old messages if any - delete wxLog::SetActiveTarget(new wxLogStderr); -#endif // wxUSE_LOG // One last chance for pending objects to be cleaned up wxTheApp->DeletePendingObjects(); - wxModule::CleanUpModules(); - - wxDeleteStockObjects() ; - - // Destroy all GDI lists, etc. - wxDeleteStockLists(); - - delete wxTheColourDatabase; - wxTheColourDatabase = NULL; - - wxBitmap::CleanUpHandlers(); - wxMacDestroyNotifierTable() ; - if (wxWinMacWindowList) { - delete wxWinMacWindowList ; - } - if (wxWinMacControlList) { - delete wxWinMacControlList ; - } - delete wxPendingEvents; - wxPendingEvents = NULL; -#if wxUSE_THREADS - delete wxPendingEventsLocker; - // There is still more cleanup code that will try to use this if not NULL. - wxPendingEventsLocker = NULL; - // If we don't do the following, we get an apparent memory leak. - ((wxEvtHandler&) wxDefaultValidator).ClearEventLocker(); -#endif + delete wxWinMacWindowList ; + wxWinMacWindowList = NULL; - wxClassInfo::CleanUpClasses(); + delete wxWinMacControlList ; + wxWinMacControlList = NULL; #ifndef __DARWIN__ # if __option(profile) @@ -668,28 +656,6 @@ void wxApp::CleanUp() # endif #endif - delete wxTheApp; - wxTheApp = NULL; - -#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT - // At this point we want to check if there are any memory - // blocks that aren't part of the wxDebugContext itself, - // as a special case. Then when dumping we need to ignore - // wxDebugContext, too. - if (wxDebugContext::CountObjectsLeft(TRUE) > 0) - { - wxLogDebug(wxT("There were memory leaks.")); - wxDebugContext::Dump(); - wxDebugContext::PrintStatistics(); - } - // wxDebugContext::SetStream(NULL, NULL); -#endif - -#if wxUSE_LOG - // do it as the very last thing because everything else can log messages - delete wxLog::SetActiveTarget(NULL); -#endif // wxUSE_LOG - #if defined(WXMAKINGDLL) && defined(__DARWIN__) // close shared library resources from here since we don't have // __wxterminate in Mach-O shared libraries @@ -705,10 +671,12 @@ void wxApp::CleanUp() #if 0 TerminateAE() ; #endif + + wxAppBase::CleanUp(); } //---------------------------------------------------------------------- -// wxEntry +// misc initialization stuff //---------------------------------------------------------------------- // extern variable for shared library resource id @@ -887,126 +855,6 @@ pascal void __wxterminate(void) #endif /* WXMAKINGDLL && !__DARWIN__ */ -int WXDLLEXPORT wxEntryStart( int WXUNUSED(argc), char *WXUNUSED(argv)[] ) -{ - return wxApp::Initialize(); -} - -int WXDLLEXPORT wxEntryInitGui() -{ - return wxTheApp->OnInitGui(); -} - -void WXDLLEXPORT wxEntryCleanup() -{ - wxApp::CleanUp(); -} - -int wxEntry( int argc, char *argv[] , bool enterLoop ) -{ -#ifdef __MWERKS__ -#if (defined(__WXDEBUG__) && wxUSE_MEMORY_TRACING) || wxUSE_DEBUG_CONTEXT - // This seems to be necessary since there are 'rogue' - // objects present at this point (perhaps global objects?) - // Setting a checkpoint will ignore them as far as the - // memory checking facility is concerned. - // Of course you may argue that memory allocated in globals should be - // checked, but this is a reasonable compromise. - wxDebugContext::SetCheckpoint(); -#endif -#endif - if (!wxEntryStart(argc, argv)) { - return 0; - } - // create the application object or ensure that one already exists - if (!wxTheApp) - { - // The app may have declared a global application object, but we recommend - // the IMPLEMENT_APP macro is used instead, which sets an initializer - // function for delayed, dynamic app object construction. - wxCHECK_MSG( wxApp::GetInitializerFunction(), 0, - wxT("No initializer - use IMPLEMENT_APP macro.") ); - - wxTheApp = (wxApp*) (*wxApp::GetInitializerFunction()) (); - } - - wxCHECK_MSG( wxTheApp, 0, wxT("You have to define an instance of wxApp!") ); - -#ifdef __DARWIN__ - // Mac OS X passes a process serial number command line argument when - // the application is launched from the Finder. This argument must be - // removed from the command line arguments before being handled by the - // application (otherwise applications would need to handle it) - - if (argc > 1) { - if (strncmp(argv[1], "-psn_", 5) == 0) { - // assume the argument is always the only one and remove it - --argc; - } - } -#else - argc = 0 ; // currently we don't support files as parameters -#endif - // we could try to get the open apple events here to adjust argc and argv better - - wxTheApp->argc = argc; -#if wxUSE_UNICODE - wxTheApp->argv = new wxChar*[argc+1]; - int mb_argc ; - for ( mb_argc = 0; mb_argc < argc; mb_argc++ ) - { - wxTheApp->argv[mb_argc] = wxStrdup(wxConvLocal.cMB2WX(argv[mb_argc])); - } - wxTheApp->argv[mb_argc] = (wxChar *)NULL; -#else - wxTheApp->argv = argv; -#endif - - // GUI-specific initialization, such as creating an app context. - wxEntryInitGui(); - - // Here frames insert themselves automatically - // into wxTopLevelWindows by getting created - // in OnInit(). - - int retValue = 0; - - if ( wxTheApp->OnInit() ) - { - if ( enterLoop ) - { - retValue = wxTheApp->OnRun(); - } - else - // We want to initialize, but not run or exit immediately. - return 1; - } - //else: app initialization failed, so we skipped OnRun() - - wxWindow *topWindow = wxTheApp->GetTopWindow(); - if ( topWindow ) - { - // Forcibly delete the window. - if ( topWindow->IsKindOf(CLASSINFO(wxFrame)) || - topWindow->IsKindOf(CLASSINFO(wxDialog)) ) - { - topWindow->Close(TRUE); - wxTheApp->DeletePendingObjects(); - } - else - { - delete topWindow; - wxTheApp->SetTopWindow(NULL); - } - } - - wxTheApp->OnExit(); - - wxEntryCleanup(); - - return retValue; -} - #if TARGET_CARBON bool wxMacConvertEventToRecord( EventRef event , EventRecord *rec) @@ -1121,18 +969,11 @@ pascal OSStatus wxMacApplicationEventHandler( EventHandlerCallRef handler , Even wxApp::wxApp() { - m_topWindow = NULL; - wxTheApp = this; - -#if WXWIN_COMPATIBILITY_2_2 - m_wantDebugOutput = TRUE; -#endif - - argc = 0; - argv = NULL; - m_printMode = wxPRINT_WINDOWS; m_auto3D = TRUE; + + m_macCurrentEvent = NULL ; + m_macCurrentEventHandlerCallRef = NULL ; } bool wxApp::Initialized() @@ -1155,16 +996,6 @@ int wxApp::MainLoop() return 0; } -// Returns TRUE if more time is needed. -bool wxApp::ProcessIdle() -{ - wxIdleEvent event; - event.SetEventObject(this); - ProcessEvent(event); - - return event.MoreRequested(); -} - void wxApp::ExitMainLoop() { m_keepGoing = FALSE; @@ -1178,7 +1009,7 @@ bool wxApp::Pending() #else EventRecord event ; - return EventAvail( everyEvent , &event ) ; + return EventAvail( everyEvent , &event ) ; #endif } @@ -1190,33 +1021,13 @@ void wxApp::Dispatch() void wxApp::OnIdle(wxIdleEvent& event) { - // Avoid recursion (via ProcessEvent default case) - if ( s_inOnIdle ) - return; - - - s_inOnIdle = TRUE; - - // 'Garbage' collection of windows deleted with Close(). - DeletePendingObjects(); - - // flush the logged messages if any - wxLog *pLog = wxLog::GetActiveTarget(); - if ( pLog != NULL && pLog->HasPendingMessages() ) - pLog->Flush(); - - // Send OnIdle events to all windows - bool needMore = SendIdleEvents(); - - if (needMore) - event.RequestMore(TRUE); - + wxAppBase::OnIdle(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 wxMacProcessNotifierAndPendingEvents(); - s_inOnIdle = FALSE; if(!wxMenuBar::MacGetInstalledMenuBar() && wxMenuBar::MacGetCommonMenuBar()) wxMenuBar::MacGetCommonMenuBar()->MacInstallMenuBar(); } @@ -1226,64 +1037,6 @@ void wxApp::WakeUpIdle() wxMacWakeUp() ; } -// Send idle event to all top-level windows -bool wxApp::SendIdleEvents() -{ - bool needMore = FALSE; - wxWindowListNode* node = wxTopLevelWindows.GetFirst(); - while (node) - { - wxWindow* win = node->GetData(); - if (SendIdleEvents(win)) - needMore = TRUE; - - node = node->GetNext(); - } - return needMore; -} - -// Send idle event to window and all subwindows -bool wxApp::SendIdleEvents(wxWindow* win) -{ - bool needMore = FALSE; - - wxIdleEvent event; - event.SetEventObject(win); - win->ProcessEvent(event); - - if (event.MoreRequested()) - needMore = TRUE; - - wxWindowListNode* node = win->GetChildren().GetFirst(); - while (node) - { - wxWindow* win = node->GetData(); - if (SendIdleEvents(win)) - needMore = TRUE; - - node = node->GetNext(); - } - return needMore ; -} - -void wxApp::DeletePendingObjects() -{ - wxNode *node = wxPendingDelete.GetFirst(); - while (node) - { - wxObject *obj = (wxObject *)node->GetData(); - - delete obj; - - if (wxPendingDelete.Member(obj)) - delete node; - - // Deleting one object may have deleted other pending - // objects, so start from beginning of list again. - node = wxPendingDelete.GetFirst(); - } -} - void wxApp::Exit() { wxApp::CleanUp(); @@ -1607,6 +1360,12 @@ void wxApp::MacHandleModifierEvents( WXEVENTREF evr ) event.SetEventType( ( ev->modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; focus->GetEventHandler()->ProcessEvent( event ) ; } + if ( ev->modifiers ^ s_lastModifiers ) & cmdKey ) + { + event.m_keyCode = WXK_COMMAND ; + event.SetEventType( ( ev->modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; + focus->GetEventHandler()->ProcessEvent( event ) ; + } s_lastModifiers = ev->modifiers ; } } @@ -1941,6 +1700,8 @@ void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr ) if ( MacSendKeyDownEvent( focus , ev->message , ev->modifiers , ev->when , ev->where.h , ev->where.v ) == false ) { +#if 0 + // we must handle control keys the other way round, otherwise text content is updated too late // has not been handled -> perform default wxControl* control = wxDynamicCast( focus , wxControl ) ; if ( control && control->GetMacControl() != NULL ) @@ -1951,6 +1712,7 @@ void wxApp::MacHandleKeyDownEvent( WXEVENTREF evr ) keycode = short(ev->message & keyCodeMask) >> 8 ; ::HandleControlKey( (ControlHandle) control->GetMacControl() , keycode , keychar , ev->modifiers ) ; } +#endif } } }