X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/732c0bfdff11ed80921416d549d4649dd5c02eeb..d1f024a8de8872ae314b30e0d1b8c8a1b8518c3d:/src/motif/app.cpp diff --git a/src/motif/app.cpp b/src/motif/app.cpp index 6dffbd1e12..17ef7bc614 100644 --- a/src/motif/app.cpp +++ b/src/motif/app.cpp @@ -9,9 +9,8 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ - #pragma implementation "app.h" -#endif +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" #ifdef __VMS #define XtParent XTPARENT @@ -26,7 +25,6 @@ #include "wx/intl.h" #include "wx/evtloop.h" #include "wx/hash.h" -#include "wx/hashmap.h" #if wxUSE_THREADS #include "wx/thread.h" @@ -51,14 +49,16 @@ struct wxPerDisplayData { wxPerDisplayData() - { m_visualInfo = NULL; m_topLevelWidget = NULL; } + { + m_visualInfo = NULL; + m_topLevelWidget = NULL; + m_topLevelRealizedWidget = NULL; + } wxXVisualInfo* m_visualInfo; - Widget m_topLevelWidget; + Widget m_topLevelWidget, m_topLevelRealizedWidget; }; -WX_DECLARE_VOIDPTR_HASH_MAP( wxPerDisplayData, wxPerDisplayDataMap ); - static void wxTLWidgetDestroyCallback(Widget w, XtPointer clientData, XtPointer ptr); static WXWidget wxCreateTopLevelWidget( WXDisplay* display ); @@ -66,214 +66,86 @@ static WXWidget wxCreateTopLevelWidget( WXDisplay* display ); extern wxList wxPendingDelete; extern bool wxAddIdleCallback(); -wxApp *wxTheApp = NULL; - wxHashTable *wxWidgetHashTable = NULL; IMPLEMENT_DYNAMIC_CLASS(wxApp, wxEvtHandler) BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) - EVT_IDLE(wxApp::OnIdle) + EVT_IDLE(wxAppBase::OnIdle) END_EVENT_TABLE() #ifdef __WXDEBUG__ +extern "C" +{ typedef int (*XErrorHandlerFunc)(Display *, XErrorEvent *); +} - XErrorHandlerFunc gs_pfnXErrorHandler = 0; - - static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent) - { - // just forward to the default handler for now - return gs_pfnXErrorHandler(dpy, xevent); - } -#endif // __WXDEBUG__ +XErrorHandlerFunc gs_pfnXErrorHandler = 0; -bool wxApp::Initialize() +extern "C" { - wxClassInfo::InitializeClasses(); - // GL: I'm annoyed ... I don't know where to put this and I don't want to - // create a module for that as it's part of the core. -#if wxUSE_THREADS - wxPendingEventsLocker = new wxCriticalSection(); -#endif +static int wxXErrorHandler(Display *dpy, XErrorEvent *xevent) +{ + // just forward to the default handler for now + return gs_pfnXErrorHandler(dpy, xevent); +} - wxTheColourDatabase = new wxColourDatabase(wxKEY_STRING); - wxTheColourDatabase->Initialize(); +} +#endif // __WXDEBUG__ - wxInitializeStockLists(); - wxInitializeStockObjects(); +bool wxApp::Initialize(int& argcOrig, wxChar **argvOrig) +{ + if ( !wxAppBase::Initialize(argcOrig, argvOrig) ) + return false; wxWidgetHashTable = new wxHashTable(wxKEY_INTEGER); - wxModule::RegisterModules(); - if (!wxModule::InitializeModules()) return FALSE; +#if wxUSE_INTL + wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding()); +#endif - return TRUE; + return true; } void wxApp::CleanUp() { - wxModule::CleanUpModules(); - - wxDeleteStockObjects() ; - - // Destroy all GDI lists, etc. - - wxDeleteStockLists(); - - delete wxTheColourDatabase; - wxTheColourDatabase = NULL; - - wxClassInfo::CleanUpClasses(); - - delete wxTheApp; - wxTheApp = NULL; + wxAppBase::CleanUp(); delete wxWidgetHashTable; wxWidgetHashTable = NULL; - // GL: I'm annoyed ... I don't know where to put this and I don't want to - // create a module for that as it's part of the core. -#if wxUSE_THREADS - delete wxPendingEvents; - wxPendingEvents = NULL; - delete wxPendingEventsLocker; - wxPendingEventsLocker = NULL; -#endif + delete m_mainLoop; -#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) + for( wxPerDisplayDataMap::iterator it = m_perDisplayData->begin(), + end = m_perDisplayData->end(); + it != end; ++it ) { - wxLogDebug("There were memory leaks.\n"); - wxDebugContext::Dump(); - wxDebugContext::PrintStatistics(); + delete it->second->m_visualInfo; + XtDestroyWidget( it->second->m_topLevelWidget ); + delete it->second; } -#endif - - // do it as the very last thing because everything else can log messages - wxLog::DontCreateOnDemand(); - // do it as the very last thing because everything else can log messages - delete wxLog::SetActiveTarget(NULL); -} - -// ============================================================================ -// wxEntry* -// ============================================================================ - -int wxEntryStart( int argc, char* argv[] ) -{ -#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 - - if (!wxApp::Initialize()) - return -1; - - return 0; -} - -int wxEntryInitGui() -{ - int retValue = 0; - - // GUI-specific initialization, such as creating an app context. - if (!wxTheApp->OnInitGui()) - retValue = -1; - return retValue; + delete m_perDisplayData; } -void wxEntryCleanup() +void wxApp::Exit() { - // So dialog boxes aren't used for further messages - delete wxLog::SetActiveTarget(new wxLogStderr); - - // flush the logged messages if any - wxLog *pLog = wxLog::GetActiveTarget(); - if ( pLog != NULL && pLog->HasPendingMessages() ) - pLog->Flush(); - wxApp::CleanUp(); -} - -int wxEntry( int argc, char *argv[] ) -{ - int retValue = 0; - - retValue = wxEntryStart( argc, argv ); - if (retValue) return retValue; - - if (!wxTheApp) - { - if (!wxApp::GetInitializerFunction()) - { - printf( "wxWindows error: No initializer - use IMPLEMENT_APP macro.\n" ); - return 0; - }; - - wxTheApp = (wxApp*) (* wxApp::GetInitializerFunction()) (); - }; - - if (!wxTheApp) - { - printf( "wxWindows error: wxTheApp == NULL\n" ); - return 0; - }; - - wxTheApp->SetClassName(wxFileNameFromPath(argv[0])); - wxTheApp->SetAppName(wxFileNameFromPath(argv[0])); - - wxTheApp->argc = argc; - wxTheApp->argv = argv; - - // GUI-specific initialization, such as creating an app context. - retValue = wxEntryInitGui(); - if (retValue) return retValue; - // Here frames insert themselves automatically into wxTopLevelWindows by - // getting created in OnInit(). - - if (wxTheApp->OnInit()) - { - if (wxTheApp->Initialized()) - wxTheApp->OnRun(); - } - - if (wxTheApp->GetTopWindow()) - { - delete wxTheApp->GetTopWindow(); - wxTheApp->SetTopWindow(NULL); - } - - wxTheApp->DeletePendingObjects(); - - retValue = wxTheApp->OnExit(); - - wxEntryCleanup(); - - return retValue; + wxAppConsole::Exit(); } -// Static member initialization -wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NULL; +// ============================================================================ +// wxApp +// ============================================================================ wxApp::wxApp() { argc = 0; argv = NULL; - m_eventLoop = new wxEventLoop; + m_mainLoop = new wxEventLoop; m_mainColormap = (WXColormap) NULL; m_appContext = (WXAppContext) NULL; m_initialDisplay = (WXDisplay*) 0; @@ -282,27 +154,7 @@ wxApp::wxApp() wxApp::~wxApp() { - delete m_eventLoop; - - for( wxPerDisplayDataMap::iterator it = m_perDisplayData->begin(), - end = m_perDisplayData->end(); - it != end; ++it ) - { - delete it->second.m_visualInfo; - XtDestroyWidget( it->second.m_topLevelWidget ); - } - - delete m_perDisplayData; - - wxTheApp = NULL; -} - -bool wxApp::Initialized() -{ - if (GetTopWindow()) - return TRUE; - else - return FALSE; + wxApp::SetInstance(NULL); } int wxApp::MainLoop() @@ -318,45 +170,11 @@ int wxApp::MainLoop() XDefaultRootWindow(XtDisplay((Widget) wxTheApp->GetTopLevelWidget())), PropertyChangeMask); - m_eventLoop->Run(); + m_mainLoop->Run(); return 0; } -// Processes an idle event. -// Returns TRUE if more time is needed. -bool wxApp::ProcessIdle() -{ - wxIdleEvent event; - - return ProcessEvent(event) && event.MoreRequested(); -} - -void wxApp::ExitMainLoop() -{ - if( m_eventLoop->IsRunning() ) - m_eventLoop->Exit(); -} - -// Is a message/event pending? -bool wxApp::Pending() -{ - return m_eventLoop->Pending(); -#if 0 - XFlush(XtDisplay( (Widget) wxTheApp->GetTopLevelWidget() )); - - // Fix by Doug from STI, to prevent a stall if non-X event - // is found. - return ((XtAppPending( (XtAppContext) GetAppContext() ) & XtIMXEvent) != 0) ; -#endif -} - -// Dispatch a message. -void wxApp::Dispatch() -{ - m_eventLoop->Dispatch(); -} - // This should be redefined in a derived class for // handling property change events for XAtom IPC. void wxApp::HandlePropertyChange(WXEvent *event) @@ -365,109 +183,20 @@ void wxApp::HandlePropertyChange(WXEvent *event) XtDispatchEvent((XEvent*) event); /* let Motif do the work */ } -void wxApp::OnIdle(wxIdleEvent& event) -{ - static bool inOnIdle = FALSE; - - // Avoid recursion (via ProcessEvent default case) - if (inOnIdle) - return; - - inOnIdle = TRUE; - - // If there are pending events, we must process them: pending events - // are either events to the threads other than main or events posted - // with wxPostEvent() functions - // GRG: I have moved this here so that all pending events are processed - // before starting to delete any objects. This behaves better (in - // particular, wrt wxPostEvent) and is coherent with wxGTK's current - // behaviour. Also removed the '#if wxUSE_THREADS' around it. - // Changed Mar/2000 before 2.1.14 - - // Flush pending events. - ProcessPendingEvents(); - - // '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); - - inOnIdle = FALSE; -} - -// Send idle event to all top-level windows -bool wxApp::SendIdleEvents() -{ - bool needMore = FALSE; - - wxWindowList::Node* 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->GetEventHandler()->ProcessEvent(event); - - if (event.MoreRequested()) - needMore = TRUE; - - wxWindowList::Node* node = win->GetChildren().GetFirst(); - while (node) - { - wxWindow* win = node->GetData(); - if (SendIdleEvents(win)) - needMore = TRUE; - - node = node->GetNext(); - } - return needMore ; -} - -void wxApp::DeletePendingObjects() -{ - wxList::Node *node = wxPendingDelete.GetFirst(); - while (node) - { - wxObject *obj = 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(); - } -} - static char *fallbackResources[] = { - "*menuBar.marginHeight: 0", - "*menuBar.shadowThickness: 1", - "*background: #c0c0c0", - "*foreground: black", + // better defaults for CDE under Irix + // + // TODO: do something similar for the other systems, the hardcoded defaults + // below are ugly +#ifdef __SGI__ + wxMOTIF_STR("*sgiMode: True"), + wxMOTIF_STR("*useSchemes: all"), +#else // !__SGI__ + wxMOTIF_STR("*menuBar.marginHeight: 0"), + wxMOTIF_STR("*menuBar.shadowThickness: 1"), + wxMOTIF_STR("*background: #c0c0c0"), + wxMOTIF_STR("*foreground: black"), +#endif // __SGI__/!__SGI__ NULL }; @@ -475,8 +204,9 @@ static char *fallbackResources[] = { bool wxApp::OnInitGui() { if( !wxAppBase::OnInitGui() ) - return FALSE; + return false; + XtSetLanguageProc(NULL, NULL, NULL); XtToolkitInitialize() ; wxTheApp->m_appContext = (WXAppContext) XtCreateApplicationContext(); XtAppSetFallbackResources((XtAppContext) wxTheApp->m_appContext, fallbackResources); @@ -494,7 +224,7 @@ bool wxApp::OnInitGui() // if you don't log to stderr, nothing will be shown... delete wxLog::SetActiveTarget(new wxLogStderr); wxString className(wxTheApp->GetClassName()); - wxLogError(_("wxWindows could not open display for '%s': exiting."), + wxLogError(_("wxWidgets could not open display for '%s': exiting."), className.c_str()); exit(-1); } @@ -507,7 +237,7 @@ bool wxApp::OnInitGui() // Add general resize proc XtActionsRec rec; - rec.string = "resize"; + rec.string = wxMOTIF_STR("resize"); rec.proc = (XtActionProc)wxWidgetResizeProc; XtAppAddActions((XtAppContext) wxTheApp->m_appContext, &rec, 1); @@ -515,7 +245,7 @@ bool wxApp::OnInitGui() wxAddIdleCallback(); - return TRUE; + return true; } WXColormap wxApp::GetMainColormap(WXDisplay* display) @@ -534,17 +264,30 @@ WXColormap wxApp::GetMainColormap(WXDisplay* display) return (WXColormap) c; } -wxXVisualInfo* wxApp::GetVisualInfo( WXDisplay* display ) +static inline wxPerDisplayData& GetOrCreatePerDisplayData + ( wxPerDisplayDataMap& m, WXDisplay* display ) { - wxPerDisplayDataMap::iterator it = m_perDisplayData->find( display ); + wxPerDisplayDataMap::iterator it = m.find( display ); + if( it != m.end() && it->second != NULL ) + return *(it->second); - if( it != m_perDisplayData->end() && it->second.m_visualInfo ) - return it->second.m_visualInfo; + wxPerDisplayData* nData = new wxPerDisplayData(); + m[display] = nData; + + return *nData; +} + +wxXVisualInfo* wxApp::GetVisualInfo( WXDisplay* display ) +{ + wxPerDisplayData& data = GetOrCreatePerDisplayData( *m_perDisplayData, + display ); + if( data.m_visualInfo ) + return data.m_visualInfo; wxXVisualInfo* vi = new wxXVisualInfo; wxFillXVisualInfo( vi, (Display*)display ); - (*m_perDisplayData)[display].m_visualInfo = vi; + data.m_visualInfo = vi; return vi; } @@ -553,8 +296,12 @@ static void wxTLWidgetDestroyCallback(Widget w, XtPointer clientData, XtPointer ptr) { if( wxTheApp ) + { wxTheApp->SetTopLevelWidget( (WXDisplay*)XtDisplay(w), (WXWidget)NULL ); + wxTheApp->SetTopLevelRealizedWidget( (WXDisplay*)XtDisplay(w), + (WXWidget)NULL ); + } } WXWidget wxCreateTopLevelWidget( WXDisplay* display ) @@ -564,8 +311,9 @@ WXWidget wxCreateTopLevelWidget( WXDisplay* display ) applicationShellWidgetClass, (Display*)display, NULL, 0 ); - XtSetMappedWhenManaged( tlw, False ); - XtRealizeWidget( tlw ); + XtVaSetValues( tlw, + XmNoverrideRedirect, True, + NULL ); XtAddCallback( tlw, XmNdestroyCallback, (XtCallbackProc)wxTLWidgetDestroyCallback, @@ -574,13 +322,24 @@ WXWidget wxCreateTopLevelWidget( WXDisplay* display ) return (WXWidget)tlw; } +WXWidget wxCreateTopLevelRealizedWidget( WXDisplay* display ) +{ + Widget rTlw = XtVaCreateWidget( "dummy_widget", topLevelShellWidgetClass, + (Widget)wxTheApp->GetTopLevelWidget(), + NULL, 0 ); + XtSetMappedWhenManaged( rTlw, False ); + XtRealizeWidget( rTlw ); + + return (WXWidget)rTlw; +} + WXWidget wxApp::GetTopLevelWidget() { WXDisplay* display = wxGetDisplay(); - wxPerDisplayDataMap::iterator it = m_perDisplayData->find( display ); - - if( it != m_perDisplayData->end() && it->second.m_topLevelWidget ) - return (WXWidget)it->second.m_topLevelWidget; + wxPerDisplayData& data = GetOrCreatePerDisplayData( *m_perDisplayData, + display ); + if( data.m_topLevelWidget ) + return (WXWidget)data.m_topLevelWidget; WXWidget tlw = wxCreateTopLevelWidget( display ); SetTopLevelWidget( display, tlw ); @@ -588,31 +347,37 @@ WXWidget wxApp::GetTopLevelWidget() return tlw; } -void wxApp::SetTopLevelWidget(WXDisplay* display, WXWidget widget) +WXWidget wxApp::GetTopLevelRealizedWidget() { - (*m_perDisplayData)[display].m_topLevelWidget = (Widget)widget; + WXDisplay* display = wxGetDisplay(); + wxPerDisplayDataMap::iterator it = m_perDisplayData->find( display ); + + if( it != m_perDisplayData->end() && it->second->m_topLevelRealizedWidget ) + return (WXWidget)it->second->m_topLevelRealizedWidget; + + WXWidget rTlw = wxCreateTopLevelRealizedWidget( display ); + SetTopLevelRealizedWidget( display, rTlw ); + + return rTlw; } -void wxExit() +void wxApp::SetTopLevelWidget(WXDisplay* display, WXWidget widget) { - int retValue = 0; - if (wxTheApp) - retValue = wxTheApp->OnExit(); + GetOrCreatePerDisplayData( *m_perDisplayData, display ) + .m_topLevelWidget = (Widget)widget; +} - wxApp::CleanUp(); - /* - * Exit in some platform-specific way. - * Not recommended that the app calls this: - * only for emergencies. - */ - exit(retValue); +void wxApp::SetTopLevelRealizedWidget(WXDisplay* display, WXWidget widget) +{ + GetOrCreatePerDisplayData( *m_perDisplayData, display ) + .m_topLevelRealizedWidget = (Widget)widget; } // Yield to other processes bool wxApp::Yield(bool onlyIfNeeded) { - bool s_inYield = FALSE; + static bool s_inYield = false; if ( s_inYield ) { @@ -621,17 +386,17 @@ bool wxApp::Yield(bool onlyIfNeeded) wxFAIL_MSG( wxT("wxYield called recursively" ) ); } - return FALSE; + return false; } - s_inYield = TRUE; + s_inYield = true; while (wxTheApp && wxTheApp->Pending()) wxTheApp->Dispatch(); - s_inYield = FALSE; + s_inYield = false; - return TRUE; + return true; } // ----------------------------------------------------------------------------