X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a1abca322fd7a9a7abe6cc0b144987786faa0f05..89c33c4831a62c628ebdbba02c2c05ec6b9169c0:/src/gtk/app.cpp diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index 56b33401b8..18c05dda50 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -7,12 +7,6 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __VMS -// vms_jackets.h should for proper working be included before anything else -# include -#undef ConnectionNumber -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -32,8 +26,12 @@ #include #endif -#include "wx/gtk/win_gtk.h" #include "wx/gtk/private.h" +#include "wx/apptrait.h" + +#if wxUSE_LIBHILDON + #include +#endif // wxUSE_LIBHILDON #include @@ -46,72 +44,6 @@ wxFORCE_LINK_MODULE(gnome_vfs) #endif -//----------------------------------------------------------------------------- -// global data -//----------------------------------------------------------------------------- - -bool g_mainThreadLocked = false; - -static GtkWidget *gs_RootWindow = (GtkWidget*) NULL; - -//----------------------------------------------------------------------------- -// wxYield -//----------------------------------------------------------------------------- - -// not static because used by textctrl.cpp -// -// MT-FIXME -bool wxIsInsideYield = false; - -bool wxApp::Yield(bool onlyIfNeeded) -{ - if ( wxIsInsideYield ) - { - if ( !onlyIfNeeded ) - { - wxFAIL_MSG( wxT("wxYield called recursively" ) ); - } - - return false; - } - -#if wxUSE_THREADS - if ( !wxThread::IsMain() ) - { - // can't call gtk_main_iteration() from other threads like this - return true; - } -#endif // wxUSE_THREADS - - wxIsInsideYield = true; - -#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 - - while (EventsPending()) - gtk_main_iteration(); - - // 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 - // call ProcessIdle() only once since this is not meant for longish - // background jobs (controlled by wxIdleEvent::RequestMore() and the - // return value of Processidle(). - ProcessIdle(); - -#if wxUSE_LOG - // let the logs be flashed again - wxLog::Resume(); -#endif - - wxIsInsideYield = false; - - return true; -} - //----------------------------------------------------------------------------- // local functions //----------------------------------------------------------------------------- @@ -208,6 +140,11 @@ bool wxApp::DoIdle() g_source_remove(m_idleSourceId); m_idleSourceId = 0; } + + // Pending events can be added asynchronously, + // need to keep idle source if any have appeared + needMore = needMore || HasPendingEvents(); + // if more idle processing requested if (needMore) { @@ -220,43 +157,20 @@ bool wxApp::DoIdle() return false; } -#if wxUSE_THREADS - -static GPollFunc wxgs_poll_func; - -extern "C" { -static gint wxapp_poll_func( GPollFD *ufds, guint nfds, gint timeout ) -{ - gdk_threads_enter(); - - wxMutexGuiLeave(); - g_mainThreadLocked = true; - - gint res = (*wxgs_poll_func)(ufds, nfds, timeout); - - wxMutexGuiEnter(); - g_mainThreadLocked = false; - - gdk_threads_leave(); - - return res; -} -} - -#endif // wxUSE_THREADS - //----------------------------------------------------------------------------- // Access to the root window global //----------------------------------------------------------------------------- GtkWidget* wxGetRootWindow() { - if (gs_RootWindow == NULL) + static GtkWidget *s_RootWindow = NULL; + + if (s_RootWindow == NULL) { - gs_RootWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL ); - gtk_widget_realize( gs_RootWindow ); + s_RootWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL ); + gtk_widget_realize( s_RootWindow ); } - return gs_RootWindow; + return s_RootWindow; } //----------------------------------------------------------------------------- @@ -265,10 +179,6 @@ GtkWidget* wxGetRootWindow() IMPLEMENT_DYNAMIC_CLASS(wxApp,wxEvtHandler) -BEGIN_EVENT_TABLE(wxApp, wxEvtHandler) - EVT_IDLE(wxAppBase::OnIdle) -END_EVENT_TABLE() - wxApp::wxApp() { #ifdef __WXDEBUG__ @@ -284,6 +194,30 @@ wxApp::~wxApp() { } +bool wxApp::SetNativeTheme(const wxString& theme) +{ + wxString path; + path = gtk_rc_get_theme_dir(); + path += "/"; + path += theme.utf8_str(); + path += "/gtk-2.0/gtkrc"; + + if ( wxFileExists(path.utf8_str()) ) + gtk_rc_add_default_file(path.utf8_str()); + else if ( wxFileExists(theme.utf8_str()) ) + gtk_rc_add_default_file(theme.utf8_str()); + else + { + wxLogWarning("Theme \"%s\" not available.", theme); + + return false; + } + + gtk_rc_reparse_all_for_settings(gtk_settings_get_default(), TRUE); + + return true; +} + bool wxApp::OnInitGui() { if ( !wxAppBase::OnInitGui() ) @@ -327,6 +261,15 @@ bool wxApp::OnInitGui() } } +#if wxUSE_LIBHILDON + m_hildonProgram = hildon_program_get_instance(); + if ( !m_hildonProgram ) + { + wxLogError(_("Unable to initialize Hildon program")); + return false; + } +#endif // wxUSE_LIBHILDON + return true; } @@ -345,27 +288,22 @@ GdkVisual *wxApp::GetGdkVisual() return visual; } -bool wxApp::Initialize(int& argc, wxChar **argv) +// use unusual names for the parameters to avoid conflict with wxApp::arg[cv] +bool wxApp::Initialize(int& argc_, wxChar **argv_) { - if ( !wxAppBase::Initialize(argc, argv) ) + if ( !wxAppBase::Initialize(argc_, argv_) ) return false; #if wxUSE_THREADS if (!g_thread_supported()) + { g_thread_init(NULL); - - wxgs_poll_func = g_main_context_get_poll_func(NULL); - g_main_context_set_poll_func(NULL, wxapp_poll_func); + gdk_threads_init(); + } #endif // wxUSE_THREADS - // We should have the wxUSE_WCHAR_T test on the _outside_ -#if wxUSE_WCHAR_T // gtk+ 2.0 supports Unicode through UTF-8 strings wxConvCurrent = &wxConvUTF8; -#else // !wxUSE_WCHAR_T - if (!wxOKlibc()) - wxConvCurrent = (wxMBConv*) NULL; -#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T // decide which conversion to use for the file names @@ -402,19 +340,19 @@ bool wxApp::Initialize(int& argc, wxChar **argv) bool init_result; + int i; #if wxUSE_UNICODE // gtk_init() wants UTF-8, not wchar_t, so convert - int i; - char **argvGTK = new char *[argc + 1]; - for ( i = 0; i < argc; i++ ) + char **argvGTK = new char *[argc_ + 1]; + for ( i = 0; i < argc_; i++ ) { - argvGTK[i] = wxStrdupA(wxConvUTF8.cWX2MB(argv[i])); + argvGTK[i] = wxStrdupA(wxConvUTF8.cWX2MB(argv_[i])); } - argvGTK[argc] = NULL; + argvGTK[argc_] = NULL; - int argcGTK = argc; + int argcGTK = argc_; #ifdef __WXGPE__ init_result = true; // is there a _check() version of this? @@ -422,19 +360,21 @@ bool wxApp::Initialize(int& argc, wxChar **argv) #else init_result = gtk_init_check( &argcGTK, &argvGTK ); #endif + wxUpdateLocaleIsUtf8(); - if ( argcGTK != argc ) + if ( argcGTK != argc_ ) { // we have to drop the parameters which were consumed by GTK+ for ( i = 0; i < argcGTK; i++ ) { - while ( strcmp(wxConvUTF8.cWX2MB(argv[i]), argvGTK[i]) != 0 ) + while ( strcmp(wxConvUTF8.cWX2MB(argv_[i]), argvGTK[i]) != 0 ) { - memmove(argv + i, argv + i + 1, (argc - i)*sizeof(*argv)); + memmove(argv_ + i, argv_ + i + 1, (argc_ - i)*sizeof(*argv_)); } } - argc = argcGTK; + argc_ = argcGTK; + argv_[argc_] = NULL; } //else: gtk_init() didn't modify our parameters @@ -446,13 +386,50 @@ bool wxApp::Initialize(int& argc, wxChar **argv) delete [] argvGTK; #else // !wxUSE_UNICODE - // gtk_init() shouldn't actually change argv itself (just its contents) so + // gtk_init() shouldn't actually change argv_ itself (just its contents) so // it's ok to pass pointer to it - init_result = gtk_init_check( &argc, &argv ); + init_result = gtk_init_check( &argc_, &argv_ ); #endif // wxUSE_UNICODE/!wxUSE_UNICODE - if (!init_result) { - wxLogError(wxT("Unable to initialize gtk, is DISPLAY set properly?")); + // update internal arg[cv] as GTK+ may have removed processed options: + this->argc = argc_; + this->argv = argv_; + + if ( m_traits ) + { + // if there are still GTK+ standard options unparsed in the command + // line, it means that they were not syntactically correct and GTK+ + // already printed a warning on the command line and we should now + // exit: + wxArrayString opt, desc; + m_traits->GetStandardCmdLineOptions(opt, desc); + + for ( i = 0; i < argc_; i++ ) + { + // leave just the names of the options with values + const wxString str = wxString(argv_[i]).BeforeFirst('='); + + for ( size_t j = 0; j < opt.size(); j++ ) + { + // remove the leading spaces from the option string as it does + // have them + if ( opt[j].Trim(false).BeforeFirst('=') == str ) + { + // a GTK+ option can be left on the command line only if + // there was an error in (or before, in another standard + // options) it, so abort, just as we do if incorrect + // program option is given + wxLogError(_("Invalid GTK+ command line option, use \"%s --help\""), + argv_[0]); + return false; + } + } + } + } + + if ( !init_result ) + { + wxLogError(_("Unable to initialize GTK+, is DISPLAY set properly?")); return false; } @@ -479,16 +456,21 @@ void wxApp::CleanUp() { if (m_idleSourceId != 0) g_source_remove(m_idleSourceId); -#if wxUSE_THREADS - delete m_idleMutex; - m_idleMutex = NULL; -#endif + // release reference acquired by Initialize() g_type_class_unref(g_type_class_peek(GTK_TYPE_WIDGET)); gdk_threads_leave(); wxAppBase::CleanUp(); + + // delete this mutex as late as possible as it's used from WakeUpIdle(), in + // particular do it after calling the base class CleanUp() which can result + // in it being called +#if wxUSE_THREADS + delete m_idleMutex; + m_idleMutex = NULL; +#endif } void wxApp::WakeUpIdle() @@ -534,3 +516,15 @@ void wxApp::OnAssertFailure(const wxChar *file, } #endif // __WXDEBUG__ + +#if wxUSE_THREADS +void wxGUIAppTraits::MutexGuiEnter() +{ + gdk_threads_enter(); +} + +void wxGUIAppTraits::MutexGuiLeave() +{ + gdk_threads_leave(); +} +#endif // wxUSE_THREADS