X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/010afced511d74f4f1c10390da96c6ccf687d574..153ecbb81caab1febc1916f5ec76b29ba09d2632:/src/gtk1/app.cpp diff --git a/src/gtk1/app.cpp b/src/gtk1/app.cpp index 6e1c25de26..006a066446 100644 --- a/src/gtk1/app.cpp +++ b/src/gtk1/app.cpp @@ -13,6 +13,7 @@ #ifdef __VMS #include +#undef ConnectionNumber #endif #include "wx/app.h" @@ -24,11 +25,9 @@ #include "wx/font.h" #include "wx/settings.h" #include "wx/dialog.h" - -#if wxUSE_WX_RESOURCES - #include "wx/resource.h" -#endif - +#include "wx/msgdlg.h" +#include "wx/file.h" +#include "wx/filename.h" #include "wx/module.h" #include "wx/image.h" @@ -42,11 +41,32 @@ #endif #include -#ifdef __VMS -# include -#else -# include -#endif + +#ifdef HAVE_POLL + #if defined(__VMS) + #include + #else + // bug in the OpenBSD headers: at least in 3.1 there is no extern "C" + // in neither poll.h nor sys/poll.h which results in link errors later + #ifdef __OPENBSD__ + extern "C" + { + #endif + + #include + + #ifdef __OPENBSD__ + }; + #endif + #endif // platform +#else // !HAVE_POLL + // we implement poll() ourselves using select() which is supposed exist in + // all modern Unices + #include + #include + #include +#endif // HAVE_POLL/!HAVE_POLL + #include "wx/gtk/win_gtk.h" #include @@ -72,25 +92,18 @@ extern bool g_isIdle; void wxapp_install_idle_handler(); -//----------------------------------------------------------------------------- -// wxExit -//----------------------------------------------------------------------------- - -void wxExit() -{ - gtk_main_quit(); -} - //----------------------------------------------------------------------------- // wxYield //----------------------------------------------------------------------------- +// not static because used by textctrl.cpp +// +// MT-FIXME +bool wxIsInsideYield = FALSE; + bool wxApp::Yield(bool onlyIfNeeded) { - // MT-FIXME - static bool s_inYield = FALSE; - - if ( s_inYield ) + if ( wxIsInsideYield ) { if ( !onlyIfNeeded ) { @@ -108,7 +121,7 @@ bool wxApp::Yield(bool onlyIfNeeded) } #endif // wxUSE_THREADS - s_inYield = TRUE; + wxIsInsideYield = TRUE; if (!g_isIdle) { @@ -128,7 +141,7 @@ bool wxApp::Yield(bool onlyIfNeeded) // 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). But we + // OnUpdateUI() which is a nice (and desired) side effect). But we // call ProcessIdle() only once since this is not meant for longish // background jobs (controlled by wxIdleEvent::RequestMore() and the // return value of Processidle(). @@ -137,7 +150,7 @@ bool wxApp::Yield(bool onlyIfNeeded) // let the logs be flashed again wxLog::Resume(); - s_inYield = FALSE; + wxIsInsideYield = FALSE; return TRUE; } @@ -146,7 +159,7 @@ bool wxApp::Yield(bool onlyIfNeeded) // wxWakeUpIdle //----------------------------------------------------------------------------- -void wxWakeUpIdle() +void wxApp::WakeUpIdle() { #if wxUSE_THREADS if (!wxThread::IsMain()) @@ -208,6 +221,17 @@ static gint wxapp_idle_callback( gpointer WXUNUSED(data) ) // from some safely-looking functions if ( wxTheApp->IsInAssert() ) { + // But repaint the assertion message if necessary + if (wxTopLevelWindows.GetCount() > 0) + { + wxWindow* win = (wxWindow*) wxTopLevelWindows.GetLast()->GetData(); +#ifdef __WXGTK20__ + if (win->IsKindOf(CLASSINFO(wxMessageDialog))) +#else + if (win->IsKindOf(CLASSINFO(wxGenericMessageDialog))) +#endif + win->OnInternalIdle(); + } return TRUE; } #endif // __WXDEBUG__ @@ -237,15 +261,82 @@ static gint wxapp_idle_callback( gpointer WXUNUSED(data) ) #if wxUSE_THREADS +#ifdef HAVE_POLL + #define wxPoll poll + #define wxPollFd pollfd +#else // !HAVE_POLL + +typedef GPollFD wxPollFd; + +int wxPoll(wxPollFd *ufds, unsigned int nfds, int timeout) +{ + // convert timeout from ms to struct timeval (s/us) + timeval tv_timeout; + tv_timeout.tv_sec = timeout/1000; + tv_timeout.tv_usec = (timeout%1000)*1000; + + // remember the highest fd used here + int fdMax = -1; + + // and fill the sets for select() + fd_set readfds; + fd_set writefds; + fd_set exceptfds; + FD_ZERO(&readfds); + FD_ZERO(&writefds); + FD_ZERO(&exceptfds); + + unsigned int i; + for ( i = 0; i < nfds; i++ ) + { + wxASSERT_MSG( ufds[i].fd < FD_SETSIZE, _T("fd out of range") ); + + if ( ufds[i].events & G_IO_IN ) + FD_SET(ufds[i].fd, &readfds); + + if ( ufds[i].events & G_IO_PRI ) + FD_SET(ufds[i].fd, &exceptfds); + + if ( ufds[i].events & G_IO_OUT ) + FD_SET(ufds[i].fd, &writefds); + + if ( ufds[i].fd > fdMax ) + fdMax = ufds[i].fd; + } + + fdMax++; + int res = select(fdMax, &readfds, &writefds, &exceptfds, &tv_timeout); + + // translate the results back + for ( i = 0; i < nfds; i++ ) + { + ufds[i].revents = 0; + + if ( FD_ISSET(ufds[i].fd, &readfds ) ) + ufds[i].revents |= G_IO_IN; + + if ( FD_ISSET(ufds[i].fd, &exceptfds ) ) + ufds[i].revents |= G_IO_PRI; + + if ( FD_ISSET(ufds[i].fd, &writefds ) ) + ufds[i].revents |= G_IO_OUT; + } + + return res; +} + +#endif // HAVE_POLL/!HAVE_POLL + static gint wxapp_poll_func( GPollFD *ufds, guint nfds, gint timeout ) { - gint res; gdk_threads_enter(); wxMutexGuiLeave(); g_mainThreadLocked = TRUE; - res = poll( (struct pollfd*) ufds, nfds, timeout ); + // we rely on the fact that glib GPollFD struct is really just pollfd but + // I wonder how wise is this in the long term (VZ) + gint res = wxPoll( (wxPollFd *) ufds, nfds, timeout ); wxMutexGuiEnter(); g_mainThreadLocked = FALSE; @@ -261,6 +352,11 @@ static gint wxapp_poll_func( GPollFD *ufds, guint nfds, gint timeout ) void wxapp_install_idle_handler() { + // GD: this assert is raised when using the thread sample (which works) + // so the test is probably not so easy. Can widget callbacks be + // triggered from child threads and, if so, for which widgets? + // wxASSERT_MSG( wxThread::IsMain() || gs_WakeUpIdle, wxT("attempt to install idle handler from widget callback in child thread (should be exclusively from wxWakeUpIdle)") ); + wxASSERT_MSG( wxTheApp->m_idleTag == 0, wxT("attempt to install idle handler twice") ); g_isIdle = FALSE; @@ -315,7 +411,7 @@ wxApp::wxApp() #endif m_colorCube = (unsigned char*) NULL; - + // this is NULL for a "regular" wxApp, but is set (and freed) by a wxGLApp m_glVisualInfo = (void *) NULL; } @@ -342,7 +438,7 @@ bool wxApp::OnInitGui() // seems gtk_widget_set_default_visual no longer exists? GdkVisual* vis = gtk_widget_get_default_visual(); #else - GdkVisual* vis = gdkx_visual_get( + GdkVisual* vis = gdkx_visual_get( ((XVisualInfo *) m_glVisualInfo) ->visualid ); gtk_widget_set_default_visual( vis ); #endif @@ -352,7 +448,7 @@ bool wxApp::OnInitGui() visual = vis; } - + // On some machines, the default visual is just 256 colours, so // we make sure we get the best. This can sometimes be wasteful. @@ -430,19 +526,29 @@ bool wxApp::OnInitGui() GdkVisual *wxApp::GetGdkVisual() { GdkVisual *visual = NULL; - + if (m_glVisualInfo) visual = gdkx_visual_get( ((XVisualInfo *) m_glVisualInfo)->visualid ); else visual = gdk_window_get_visual( wxGetRootWindow()->window ); - + wxASSERT( visual ); - + return visual; } bool wxApp::ProcessIdle() { + wxWindowList::Node* node = wxTopLevelWindows.GetFirst(); + node = wxTopLevelWindows.GetFirst(); + while (node) + { + wxWindow* win = node->GetData(); + CallInternalIdle( win ); + + node = node->GetNext(); + } + wxIdleEvent event; event.SetEventObject( this ); ProcessEvent( event ); @@ -486,18 +592,10 @@ bool wxApp::SendIdleEvents() wxWindow* win = node->GetData(); if (SendIdleEvents(win)) needMore = TRUE; - - node = node->GetNext(); - } - node = wxTopLevelWindows.GetFirst(); - while (node) - { - wxWindow* win = node->GetData(); - CallInternalIdle( win ); - node = node->GetNext(); } + return needMore; } @@ -505,15 +603,15 @@ bool wxApp::CallInternalIdle( wxWindow* win ) { win->OnInternalIdle(); - wxNode* node = win->GetChildren().First(); + wxWindowList::Node *node = win->GetChildren().GetFirst(); while (node) { - wxWindow* win = (wxWindow*) node->Data(); - CallInternalIdle( win ); + wxWindow *win = node->GetData(); - node = node->Next(); + CallInternalIdle( win ); + node = node->GetNext(); } - + return TRUE; } @@ -529,16 +627,16 @@ bool wxApp::SendIdleEvents( wxWindow* win ) if (event.MoreRequested()) needMore = TRUE; - wxNode* node = win->GetChildren().First(); + wxWindowList::Node *node = win->GetChildren().GetFirst(); while (node) { - wxWindow* win = (wxWindow*) node->Data(); + wxWindow *win = node->GetData(); + if (SendIdleEvents(win)) needMore = TRUE; - - node = node->Next(); + node = node->GetNext(); } - + return needMore; } @@ -548,6 +646,13 @@ int wxApp::MainLoop() return 0; } +void wxApp::Exit() +{ + // VZ: no idea why is it different from ExitMainLoop() but this is what + // wxExit() used to do + gtk_main_quit(); +} + void wxApp::ExitMainLoop() { if (gtk_main_level() > 0) @@ -571,17 +676,17 @@ void wxApp::Dispatch() void wxApp::DeletePendingObjects() { - wxNode *node = wxPendingDelete.First(); + wxNode *node = wxPendingDelete.GetFirst(); while (node) { - wxObject *obj = (wxObject *)node->Data(); + wxObject *obj = (wxObject *)node->GetData(); delete obj; if (wxPendingDelete.Find(obj)) delete node; - node = wxPendingDelete.First(); + node = wxPendingDelete.GetFirst(); } } @@ -589,10 +694,6 @@ bool wxApp::Initialize() { wxClassInfo::InitializeClasses(); -#if wxUSE_INTL - wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding()); -#endif - // 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 @@ -606,12 +707,13 @@ bool wxApp::Initialize() wxInitializeStockLists(); wxInitializeStockObjects(); -#if wxUSE_WX_RESOURCES - wxInitializeResourceSystem(); -#endif - wxModule::RegisterModules(); - if (!wxModule::InitializeModules()) return FALSE; + if (!wxModule::InitializeModules()) + return FALSE; + +#if wxUSE_INTL + wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding()); +#endif return TRUE; } @@ -620,10 +722,6 @@ void wxApp::CleanUp() { wxModule::CleanUpModules(); -#if wxUSE_WX_RESOURCES - wxCleanUpResourceSystem(); -#endif - delete wxTheColourDatabase; wxTheColourDatabase = (wxColourDatabase*) NULL; @@ -638,7 +736,9 @@ void wxApp::CleanUp() #if wxUSE_THREADS delete wxPendingEvents; + wxPendingEvents = NULL; delete wxPendingEventsLocker; + wxPendingEventsLocker = NULL; #endif // check for memory leaks @@ -696,10 +796,11 @@ int wxEntryStart( int& argc, char *argv[] ) if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL; #endif - gdk_threads_enter(); - gtk_init( &argc, &argv ); + /* we can not enter threads before gtk_init is done */ + gdk_threads_enter(); + wxSetDetectableAutoRepeat( TRUE ); if (!wxApp::Initialize()) @@ -790,9 +891,11 @@ int wxEntry( int argc, char *argv[] ) wxTheApp->argv = argv; #endif - wxString name(wxFileNameFromPath(argv[0])); - wxStripExtension( name ); - wxTheApp->SetAppName( name ); + if (wxTheApp->argc > 0) + { + wxFileName fname( wxTheApp->argv[0] ); + wxTheApp->SetAppName( fname.GetName() ); + } int retValue; retValue = wxEntryInitGui(); @@ -807,33 +910,24 @@ int wxEntry( int argc, char *argv[] ) if ( retValue == 0 ) { - /* delete pending toplevel windows (typically a single - dialog) so that, if there isn't any left, we don't - call OnRun() */ + // Delete pending toplevel windows wxTheApp->DeletePendingObjects(); - wxTheApp->m_initialized = wxTopLevelWindows.GetCount() != 0; + // When is the app not initialized ? + wxTheApp->m_initialized = TRUE; if (wxTheApp->Initialized()) { wxTheApp->OnRun(); wxWindow *topWindow = wxTheApp->GetTopWindow(); + + // Delete all pending windows if any + wxTheApp->DeletePendingObjects(); + + // Reset top window 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( (wxWindow*) NULL ); - } - } + wxTheApp->SetTopWindow( (wxWindow*) NULL ); retValue = wxTheApp->OnExit(); } @@ -846,11 +940,11 @@ int wxEntry( int argc, char *argv[] ) #ifdef __WXDEBUG__ -void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg) +void wxApp::OnAssert(const wxChar *file, int line, const wxChar* cond, const wxChar *msg) { m_isInAssert = TRUE; - wxAppBase::OnAssert(file, line, msg); + wxAppBase::OnAssert(file, line, cond, msg); m_isInAssert = FALSE; }