]>
git.saurik.com Git - wxWidgets.git/blob - src/gtk/app.cpp
   1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/app.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling, Julian Smart 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  19     #include "wx/memory.h" 
  23 #include "wx/thread.h" 
  29 #include "wx/gtk/private.h" 
  30 #include "wx/apptrait.h" 
  33     #include <hildon-widgets/hildon-program.h> 
  34 #endif // wxUSE_LIBHILDON 
  37     #include <hildon/hildon.h> 
  38 #endif // wxUSE_LIBHILDON2 
  42 //----------------------------------------------------------------------------- 
  44 //----------------------------------------------------------------------------- 
  46 #if wxUSE_MIMETYPE && wxUSE_LIBGNOMEVFS 
  48     wxFORCE_LINK_MODULE(gnome_vfs
) 
  51 //----------------------------------------------------------------------------- 
  53 //----------------------------------------------------------------------------- 
  55 // One-shot signal emission hook, to install idle handler. 
  58 wx_emission_hook(GSignalInvocationHint
*, guint
, const GValue
*, gpointer data
) 
  60     wxApp
* app 
= wxTheApp
; 
  63     bool* hook_installed 
= (bool*)data
; 
  64     // record that hook is not installed 
  65     *hook_installed 
= false; 
  71 // Add signal emission hooks, to re-install idle handler when needed. 
  72 static void wx_add_idle_hooks() 
  76         static bool hook_installed
; 
  81                 sig_id 
= g_signal_lookup("event", GTK_TYPE_WIDGET
); 
  82             hook_installed 
= true; 
  83             g_signal_add_emission_hook( 
  84                 sig_id
, 0, wx_emission_hook
, &hook_installed
, NULL
); 
  87     // "size_allocate" hook 
  88     // Needed to match the behavior of the old idle system, 
  89     // but probably not necessary. 
  91         static bool hook_installed
; 
  96                 sig_id 
= g_signal_lookup("size_allocate", GTK_TYPE_WIDGET
); 
  97             hook_installed 
= true; 
  98             g_signal_add_emission_hook( 
  99                 sig_id
, 0, wx_emission_hook
, &hook_installed
, NULL
); 
 105 static gboolean 
wxapp_idle_callback(gpointer
) 
 107     return wxTheApp
->DoIdle(); 
 115         // Allow another idle source to be added while this one is busy. 
 116         // Needed if an idle event handler runs a new event loop, 
 117         // for example by showing a dialog. 
 119         wxMutexLocker 
lock(m_idleMutex
); 
 121         id_save 
= m_idleSourceId
; 
 126         // don't generate the idle events while the assert modal dialog is shown, 
 127         // this matches the behavior of wxMSW 
 136         ProcessPendingEvents(); 
 138         needMore 
= ProcessIdle(); 
 139     } while (needMore 
&& gtk_events_pending() == 0); 
 143     wxMutexLocker 
lock(m_idleMutex
); 
 145     // if a new idle source was added during ProcessIdle 
 146     if (m_idleSourceId 
!= 0) 
 149         g_source_remove(m_idleSourceId
); 
 153     // Pending events can be added asynchronously, 
 154     // need to keep idle source if any have appeared 
 155     if (HasPendingEvents()) 
 158     // if more idle processing requested 
 161         // keep this source installed 
 162         m_idleSourceId 
= id_save
; 
 165     // add hooks and remove this source 
 170 //----------------------------------------------------------------------------- 
 171 // Access to the root window global 
 172 //----------------------------------------------------------------------------- 
 174 GtkWidget
* wxGetRootWindow() 
 176     static GtkWidget 
*s_RootWindow 
= NULL
; 
 178     if (s_RootWindow 
== NULL
) 
 180         s_RootWindow 
= gtk_window_new( GTK_WINDOW_TOPLEVEL 
); 
 181         gtk_widget_realize( s_RootWindow 
); 
 186 //----------------------------------------------------------------------------- 
 188 //----------------------------------------------------------------------------- 
 190 IMPLEMENT_DYNAMIC_CLASS(wxApp
,wxEvtHandler
) 
 194     m_isInAssert 
= false; 
 202 bool wxApp::SetNativeTheme(const wxString
& theme
) 
 205     path 
= gtk_rc_get_theme_dir(); 
 207     path 
+= theme
.utf8_str(); 
 208     path 
+= "/gtk-2.0/gtkrc"; 
 210     if ( wxFileExists(path
.utf8_str()) ) 
 211         gtk_rc_add_default_file(path
.utf8_str()); 
 212     else if ( wxFileExists(theme
.utf8_str()) ) 
 213         gtk_rc_add_default_file(theme
.utf8_str()); 
 216         wxLogWarning("Theme \"%s\" not available.", theme
); 
 221     gtk_rc_reparse_all_for_settings(gtk_settings_get_default(), TRUE
); 
 226 bool wxApp::OnInitGui() 
 228     if ( !wxAppBase::OnInitGui() ) 
 231     // if this is a wxGLApp (derived from wxApp), and we've already 
 232     // chosen a specific visual, then derive the GdkVisual from that 
 233     if ( GetXVisualInfo() ) 
 235         GdkVisual
* vis 
= gtk_widget_get_default_visual(); 
 237         GdkColormap 
*colormap 
= gdk_colormap_new( vis
, FALSE 
); 
 238         gtk_widget_set_default_colormap( colormap 
); 
 242         // On some machines, the default visual is just 256 colours, so 
 243         // we make sure we get the best. This can sometimes be wasteful. 
 246             if (m_forceTrueColour
) 
 248                 GdkVisual
* visual 
= gdk_visual_get_best_with_both( 24, GDK_VISUAL_TRUE_COLOR 
); 
 251                     wxLogError(wxT("Unable to initialize TrueColor visual.")); 
 254                 GdkColormap 
*colormap 
= gdk_colormap_new( visual
, FALSE 
); 
 255                 gtk_widget_set_default_colormap( colormap 
); 
 259                 if (gdk_visual_get_best() != gdk_visual_get_system()) 
 261                     GdkVisual
* visual 
= gdk_visual_get_best(); 
 262                     GdkColormap 
*colormap 
= gdk_colormap_new( visual
, FALSE 
); 
 263                     gtk_widget_set_default_colormap( colormap 
); 
 269 #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 
 270     if ( !GetHildonProgram() ) 
 272         wxLogError(_("Unable to initialize Hildon program")); 
 275 #endif // wxUSE_LIBHILDON || wxUSE_LIBHILDON2 
 280 // use unusual names for the parameters to avoid conflict with wxApp::arg[cv] 
 281 bool wxApp::Initialize(int& argc_
, wxChar 
**argv_
) 
 283     if ( !wxAppBase::Initialize(argc_
, argv_
) ) 
 287     if (!g_thread_supported()) 
 292 #endif // wxUSE_THREADS 
 294     // gtk+ 2.0 supports Unicode through UTF-8 strings 
 295     wxConvCurrent 
= &wxConvUTF8
; 
 297     // decide which conversion to use for the file names 
 299     // (1) this variable exists for the sole purpose of specifying the encoding 
 300     //     of the filenames for GTK+ programs, so use it if it is set 
 301     wxString 
encName(wxGetenv(wxT("G_FILENAME_ENCODING"))); 
 302     encName 
= encName
.BeforeFirst(wxT(',')); 
 303     if (encName
.CmpNoCase(wxT("@locale")) == 0) 
 309         // (2) if a non default locale is set, assume that the user wants his 
 310         //     filenames in this locale too 
 311         encName 
= wxLocale::GetSystemEncodingName().Upper(); 
 312         // (3) finally use UTF-8 by default 
 313         if (encName
.empty() || encName 
== wxT("US-ASCII")) 
 314             encName 
= wxT("UTF-8"); 
 315         wxSetEnv(wxT("G_FILENAME_ENCODING"), encName
); 
 319         encName 
= wxT("UTF-8"); 
 321     // if wxUSE_INTL==0 it probably indicates that only "C" locale is supported 
 322     // by the program anyhow so prevent GTK+ from calling setlocale(LC_ALL, "") 
 323     // from gtk_init_check() as it does by default 
 324     gtk_disable_setlocale(); 
 327     static wxConvBrokenFileNames 
fileconv(encName
); 
 328     wxConvFileName 
= &fileconv
; 
 335     // gtk_init() wants UTF-8, not wchar_t, so convert 
 336     char **argvGTK 
= new char *[argc_ 
+ 1]; 
 337     for ( i 
= 0; i 
< argc_
; i
++ ) 
 339         argvGTK
[i
] = wxStrdupA(wxConvUTF8
.cWX2MB(argv_
[i
])); 
 342     argvGTK
[argc_
] = NULL
; 
 347     init_result 
= true;  // is there a _check() version of this? 
 348     gpe_application_init( &argcGTK
, &argvGTK 
); 
 350     init_result 
= gtk_init_check( &argcGTK
, &argvGTK 
); 
 352     wxUpdateLocaleIsUtf8(); 
 354     if ( argcGTK 
!= argc_ 
) 
 356         // we have to drop the parameters which were consumed by GTK+ 
 357         for ( i 
= 0; i 
< argcGTK
; i
++ ) 
 359             while ( strcmp(wxConvUTF8
.cWX2MB(argv_
[i
]), argvGTK
[i
]) != 0 ) 
 361                 memmove(argv_ 
+ i
, argv_ 
+ i 
+ 1, (argc_ 
- i
)*sizeof(*argv_
)); 
 368     //else: gtk_init() didn't modify our parameters 
 371     for ( i 
= 0; i 
< argcGTK
; i
++ ) 
 377 #else // !wxUSE_UNICODE 
 378     // gtk_init() shouldn't actually change argv_ itself (just its contents) so 
 379     // it's ok to pass pointer to it 
 380     init_result 
= gtk_init_check( &argc_
, &argv_ 
); 
 381 #endif // wxUSE_UNICODE/!wxUSE_UNICODE 
 383     // update internal arg[cv] as GTK+ may have removed processed options: 
 389         // if there are still GTK+ standard options unparsed in the command 
 390         // line, it means that they were not syntactically correct and GTK+ 
 391         // already printed a warning on the command line and we should now 
 393         wxArrayString opt
, desc
; 
 394         m_traits
->GetStandardCmdLineOptions(opt
, desc
); 
 396         for ( i 
= 0; i 
< argc_
; i
++ ) 
 398             // leave just the names of the options with values 
 399             const wxString str 
= wxString(argv_
[i
]).BeforeFirst('='); 
 401             for ( size_t j 
= 0; j 
< opt
.size(); j
++ ) 
 403                 // remove the leading spaces from the option string as it does 
 405                 if ( opt
[j
].Trim(false).BeforeFirst('=') == str 
) 
 407                     // a GTK+ option can be left on the command line only if 
 408                     // there was an error in (or before, in another standard 
 409                     // options) it, so abort, just as we do if incorrect 
 410                     // program option is given 
 411                     wxLogError(_("Invalid GTK+ command line option, use \"%s --help\""), 
 421         wxLogError(_("Unable to initialize GTK+, is DISPLAY set properly?")); 
 425     // we can not enter threads before gtk_init is done 
 429     wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding()); 
 432     // make sure GtkWidget type is loaded, idle hooks need it 
 433     g_type_class_ref(GTK_TYPE_WIDGET
); 
 439 void wxApp::CleanUp() 
 441     if (m_idleSourceId 
!= 0) 
 442         g_source_remove(m_idleSourceId
); 
 444     // release reference acquired by Initialize() 
 445     g_type_class_unref(g_type_class_peek(GTK_TYPE_WIDGET
)); 
 449     wxAppBase::CleanUp(); 
 452 void wxApp::WakeUpIdle() 
 455     wxMutexLocker 
lock(m_idleMutex
); 
 457     if (m_idleSourceId 
== 0) 
 458         m_idleSourceId 
= g_idle_add_full(G_PRIORITY_LOW
, wxapp_idle_callback
, NULL
, NULL
); 
 461 // Checking for pending events requires first removing our idle source, 
 462 // otherwise it will cause the check to always return true. 
 463 bool wxApp::EventsPending() 
 466     wxMutexLocker 
lock(m_idleMutex
); 
 468     if (m_idleSourceId 
!= 0) 
 470         g_source_remove(m_idleSourceId
); 
 474     return gtk_events_pending() != 0; 
 477 void wxApp::OnAssertFailure(const wxChar 
*file
, 
 483     // there is no need to do anything if asserts are disabled in this build 
 486     // block wx idle events while assert dialog is showing 
 489     wxAppBase::OnAssertFailure(file
, line
, func
, cond
, msg
); 
 491     m_isInAssert 
= false; 
 492 #else // !wxDEBUG_LEVEL 
 498 #endif // wxDEBUG_LEVEL/!wxDEBUG_LEVEL 
 502 void wxGUIAppTraits::MutexGuiEnter() 
 507 void wxGUIAppTraits::MutexGuiLeave() 
 511 #endif // wxUSE_THREADS 
 513 #if wxUSE_LIBHILDON || wxUSE_LIBHILDON2 
 514 // Maemo-specific method: get the main program object 
 515 HildonProgram 
*wxApp::GetHildonProgram() 
 517     return hildon_program_get_instance(); 
 520 #endif // wxUSE_LIBHILDON || wxUSE_LIBHILDON2