X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c77eea28f955e9c5e59d952594ccc5e96de1597e..2e61f6814126617f286fad69f614cccd86db6412:/src/gtk/app.cpp diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index d78d893db2..fa47355e8f 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -26,50 +26,12 @@ #include "wx/font.h" #endif -#include "wx/file.h" -#include "wx/filename.h" #include "wx/thread.h" #ifdef __WXGPE__ #include #endif -#ifdef __WXUNIVERSAL__ - #include "wx/univ/theme.h" - #include "wx/univ/renderer.h" -#endif - -#include - -#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 - #ifdef HAVE_SYS_SELECT_H - #include - #endif -#endif // HAVE_POLL/!HAVE_POLL - -#include "wx/unix/private.h" #include "wx/gtk/win_gtk.h" #include "wx/gtk/private.h" @@ -79,9 +41,9 @@ // link GnomeVFS //----------------------------------------------------------------------------- -#if wxUSE_LIBGNOMEVFS -#include "wx/html/forcelnk.h" -FORCE_LINK(gnome_vfs) +#if wxUSE_MIMETYPE && wxUSE_LIBGNOMEVFS + #include "wx/link.h" + wxFORCE_LINK_MODULE(gnome_vfs) #endif //----------------------------------------------------------------------------- @@ -135,7 +97,7 @@ bool wxApp::Yield(bool onlyIfNeeded) // We need to remove idle callbacks or the loop will // never finish. - RemoveIdleSource(); + SuspendIdleCallback(); #if wxUSE_LOG // disable log flushing from here because a call to wxYield() shouldn't @@ -208,31 +170,57 @@ static inline void wxAddEmissionHook() static gint wxapp_idle_callback( gpointer WXUNUSED(data) ) { + // this does not look possible, but just in case... if (!wxTheApp) return false; + bool moreIdles = false; + #ifdef __WXDEBUG__ // don't generate the idle events while the assert modal dialog is shown, - // this completely confuses the apps which don't expect to be reentered - // from some safely-looking functions - if ( wxTheApp->IsInAssert() ) - return false; + // this matches the behavior of wxMSW + if (!wxTheApp->IsInAssert()) #endif // __WXDEBUG__ + { + guint idleID_save; + { + // Allow another idle source to be added while this one is busy. + // Needed if an idle event handler runs a new event loop, + // for example by showing a dialog. +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + idleID_save = wxTheApp->m_idleTag; + wxTheApp->m_idleTag = 0; + g_isIdle = true; + wxAddEmissionHook(); + } - // When getting called from GDK's time-out handler - // we are no longer within GDK's grab on the GUI - // thread so we must lock it here ourselves. - gdk_threads_enter(); + // When getting called from GDK's time-out handler + // we are no longer within GDK's grab on the GUI + // thread so we must lock it here ourselves. + gdk_threads_enter(); - bool moreIdles; + // Send idle event to all who request them as long as + // no events have popped up in the event queue. + do { + moreIdles = wxTheApp->ProcessIdle(); + } while (moreIdles && gtk_events_pending() == 0); - // Send idle event to all who request them as long as - // no events have popped up in the event queue. - while ( (moreIdles = wxTheApp->ProcessIdle()) && gtk_events_pending() == 0) - ; + // Release lock again + gdk_threads_leave(); - // Release lock again - gdk_threads_leave(); + { + // If another idle source was added, remove it +#if wxUSE_THREADS + wxMutexLocker lock(gs_idleTagsMutex); +#endif + if (wxTheApp->m_idleTag != 0) + g_source_remove(wxTheApp->m_idleTag); + wxTheApp->m_idleTag = idleID_save; + g_isIdle = false; + } + } if (!moreIdles) { @@ -250,75 +238,13 @@ static gint wxapp_idle_callback( gpointer WXUNUSED(data) ) // Return FALSE if no more idle events are to be sent return moreIdles; } +} // extern "C" #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; - wxFD_ZERO(&readfds); - wxFD_ZERO(&writefds); - wxFD_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 ) - wxFD_SET(ufds[i].fd, &readfds); - - if ( ufds[i].events & G_IO_PRI ) - wxFD_SET(ufds[i].fd, &exceptfds); - - if ( ufds[i].events & G_IO_OUT ) - wxFD_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 ( wxFD_ISSET(ufds[i].fd, &readfds ) ) - ufds[i].revents |= G_IO_IN; - - if ( wxFD_ISSET(ufds[i].fd, &exceptfds ) ) - ufds[i].revents |= G_IO_PRI; - - if ( wxFD_ISSET(ufds[i].fd, &writefds ) ) - ufds[i].revents |= G_IO_OUT; - } - - return res; -} - -#endif // HAVE_POLL/!HAVE_POLL +static GPollFunc wxgs_poll_func; +extern "C" { static gint wxapp_poll_func( GPollFD *ufds, guint nfds, gint timeout ) { gdk_threads_enter(); @@ -326,9 +252,7 @@ static gint wxapp_poll_func( GPollFD *ufds, guint nfds, gint timeout ) wxMutexGuiLeave(); g_mainThreadLocked = true; - // 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 ); + gint res = (*wxgs_poll_func)(ufds, nfds, timeout); wxMutexGuiEnter(); g_mainThreadLocked = false; @@ -337,11 +261,10 @@ static gint wxapp_poll_func( GPollFD *ufds, guint nfds, gint timeout ) return res; } +} #endif // wxUSE_THREADS -} // extern "C" - void wxapp_install_idle_handler() { if (wxTheApp == NULL) @@ -407,10 +330,6 @@ wxApp::wxApp() g_isIdle = true; wxapp_install_idle_handler(); -#if wxUSE_THREADS - g_main_context_set_poll_func( NULL, wxapp_poll_func ); -#endif - // this is NULL for a "regular" wxApp, but is set (and freed) by a wxGLApp m_glVisualInfo = (void *) NULL; m_glFBCInfo = (void *) NULL; @@ -484,14 +403,16 @@ GdkVisual *wxApp::GetGdkVisual() bool wxApp::Initialize(int& argc, wxChar **argv) { - bool init_result; + if ( !wxAppBase::Initialize(argc, argv) ) + return false; #if wxUSE_THREADS if (!g_thread_supported()) g_thread_init(NULL); -#endif // wxUSE_THREADS - gtk_set_locale(); + wxgs_poll_func = g_main_context_get_poll_func(NULL); + g_main_context_set_poll_func(NULL, wxapp_poll_func); +#endif // wxUSE_THREADS // We should have the wxUSE_WCHAR_T test on the _outside_ #if wxUSE_WCHAR_T @@ -508,7 +429,7 @@ bool wxApp::Initialize(int& argc, wxChar **argv) // of the filenames for GTK+ programs, so use it if it is set wxString encName(wxGetenv(_T("G_FILENAME_ENCODING"))); encName = encName.BeforeFirst(_T(',')); - if (encName == _T("@locale")) + if (encName.CmpNoCase(_T("@locale")) == 0) encName.clear(); encName.MakeUpper(); #if wxUSE_INTL @@ -525,10 +446,19 @@ bool wxApp::Initialize(int& argc, wxChar **argv) #else if (encName.empty()) encName = _T("UTF-8"); + + // if wxUSE_INTL==0 it probably indicates that only "C" locale is supported + // by the program anyhow so prevent GTK+ from calling setlocale(LC_ALL, "") + // from gtk_init_check() as it does by default + gtk_disable_setlocale(); + #endif // wxUSE_INTL static wxConvBrokenFileNames fileconv(encName); wxConvFileName = &fileconv; + + bool init_result; + #if wxUSE_UNICODE // gtk_init() wants UTF-8, not wchar_t, so convert int i; @@ -556,7 +486,7 @@ bool wxApp::Initialize(int& argc, wxChar **argv) { while ( strcmp(wxConvUTF8.cWX2MB(argv[i]), argvGTK[i]) != 0 ) { - memmove(argv + i, argv + i + 1, argc - i); + memmove(argv + i, argv + i + 1, (argc - i)*sizeof(*argv)); } } @@ -585,13 +515,6 @@ bool wxApp::Initialize(int& argc, wxChar **argv) // we can not enter threads before gtk_init is done gdk_threads_enter(); - if ( !wxAppBase::Initialize(argc, argv) ) - { - gdk_threads_leave(); - - return false; - } - wxSetDetectableAutoRepeat( true ); #if wxUSE_INTL @@ -616,6 +539,8 @@ void wxApp::OnAssertFailure(const wxChar *file, const wxChar* cond, const wxChar *msg) { + + // block wx idle events while assert dialog is showing m_isInAssert = true; wxAppBase::OnAssertFailure(file, line, func, cond, msg); @@ -625,7 +550,7 @@ void wxApp::OnAssertFailure(const wxChar *file, #endif // __WXDEBUG__ -void wxApp::RemoveIdleSource() +void wxApp::SuspendIdleCallback() { #if wxUSE_THREADS wxMutexLocker lock(gs_idleTagsMutex);