]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/app.cpp
added support for column images under MSW
[wxWidgets.git] / src / gtk / app.cpp
index b452afc77adb23d03d08a6114623c815917e7099..8502f2a279105cffa2b66fbd0fb0c1bf89d25247 100644 (file)
@@ -49,9 +49,10 @@ wxAppInitializerFunction wxAppBase::m_appInitFn = (wxAppInitializerFunction) NUL
 
 extern bool g_isIdle;
 
 
 extern bool g_isIdle;
 
-bool g_mainThreadLocked = FALSE;
+bool   g_mainThreadLocked = FALSE;
+gint   g_pendingTag = 0;
 
 
-GtkWidget *wxRootWindow = (GtkWidget*) NULL;
+static GtkWidget *gs_RootWindow = (GtkWidget*) NULL;
 
 //-----------------------------------------------------------------------------
 // local functions
 
 //-----------------------------------------------------------------------------
 // local functions
@@ -59,6 +60,7 @@ GtkWidget *wxRootWindow = (GtkWidget*) NULL;
 
 /* forward declaration */
 gint   wxapp_idle_callback( gpointer WXUNUSED(data) );
 
 /* forward declaration */
 gint   wxapp_idle_callback( gpointer WXUNUSED(data) );
+gint   wxapp_pending_callback( gpointer WXUNUSED(data) );
 void   wxapp_install_idle_handler();
 
 #if wxUSE_THREADS
 void   wxapp_install_idle_handler();
 
 #if wxUSE_THREADS
@@ -78,43 +80,67 @@ void wxExit()
 // wxYield
 //-----------------------------------------------------------------------------
 
 // wxYield
 //-----------------------------------------------------------------------------
 
+static bool gs_inYield = FALSE;
+
 bool wxYield()
 {
 bool wxYield()
 {
-    bool has_idle = (wxTheApp->m_idleTag != 0);
-
-    if (has_idle)
+#if wxUSE_THREADS
+    if ( !wxThread::IsMain() )
     {
     {
-        /* We need to temporarily remove idle callbacks or the loop will
-           never finish. */
-        gtk_idle_remove( wxTheApp->m_idleTag );
-        wxTheApp->m_idleTag = 0;
+        // can't call gtk_main_iteration() from other threads like this
+        return TRUE;
     }
     }
+#endif // wxUSE_THREADS
 
 
-    while (gtk_events_pending())
-        gtk_main_iteration();
+#ifdef __WXDEBUG__
+    if (gs_inYield)
+        wxFAIL_MSG( wxT("wxYield called recursively" ) );
+#endif
 
 
-    if (has_idle)
+    gs_inYield = TRUE;
+
+    if (!g_isIdle)
     {
     {
-        /* re-add idle handler (very low priority) */
-        wxTheApp->m_idleTag = gtk_idle_add_priority( 1000, wxapp_idle_callback, (gpointer) NULL );
+        // We need to remove idle callbacks or the loop will
+        // never finish.
+        gtk_idle_remove( wxTheApp->m_idleTag );
+        wxTheApp->m_idleTag = 0;
+        g_isIdle = TRUE;
     }
 
     // disable log flushing from here because a call to wxYield() shouldn't
     // normally result in message boxes popping up &c
     wxLog::Suspend();
 
     }
 
     // disable log flushing from here because a call to wxYield() shouldn't
     // normally result in message boxes popping up &c
     wxLog::Suspend();
 
+    while (gtk_events_pending())
+        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) */
     /* 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) */
-    while (wxTheApp->ProcessIdle())
-        ;
+    while (wxTheApp->ProcessIdle()) { }
 
     // let the logs be flashed again
     wxLog::Resume();
 
 
     // let the logs be flashed again
     wxLog::Resume();
 
+    gs_inYield = FALSE;
+
     return TRUE;
 }
 
     return TRUE;
 }
 
+//-----------------------------------------------------------------------------
+// wxYieldIfNeeded
+// Like wxYield, but fails silently if the yield is recursive.
+//-----------------------------------------------------------------------------
+
+bool wxYieldIfNeeded()
+{
+    if (gs_inYield)
+        return FALSE;
+
+    return wxYield();
+}
+
 //-----------------------------------------------------------------------------
 // wxWakeUpIdle
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // wxWakeUpIdle
 //-----------------------------------------------------------------------------
@@ -139,7 +165,7 @@ void wxWakeUpIdle()
 // local functions
 //-----------------------------------------------------------------------------
 
 // local functions
 //-----------------------------------------------------------------------------
 
-gint wxapp_idle_callback( gpointer WXUNUSED(data) )
+gint wxapp_pending_callback( gpointer WXUNUSED(data) )
 {
     if (!wxTheApp) return TRUE;
 
 {
     if (!wxTheApp) return TRUE;
 
@@ -148,31 +174,73 @@ gint wxapp_idle_callback( gpointer WXUNUSED(data) )
     // thread so we must lock it here ourselves
     gdk_threads_enter();
 
     // thread so we must lock it here ourselves
     gdk_threads_enter();
 
-    /* we don't want any more idle events until the next event is
-       sent to wxGTK */
-    gtk_idle_remove( wxTheApp->m_idleTag );
-    wxTheApp->m_idleTag = 0;
+    // Sent idle event to all who request them
+    wxTheApp->ProcessPendingEvents();
+
+    g_pendingTag = 0;
+
+    /* flush the logged messages if any */
+#if wxUSE_LOG
+    wxLog::FlushActive();
+#endif // wxUSE_LOG
+
+    // Release lock again
+    gdk_threads_leave();
 
 
-    /* indicate that we are now in idle mode - even so deeply
+    // Return FALSE to indicate that no more idle events are
+    // to be sent (single shot instead of continuous stream)
+    return FALSE;
+}
+
+gint wxapp_idle_callback( gpointer WXUNUSED(data) )
+{
+    if (!wxTheApp)
+        return TRUE;
+
+#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 TRUE;
+    }
+#endif // __WXDEBUG__
+
+    // 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();
+
+    /* Indicate that we are now in idle mode - even so deeply
        in idle mode that we don't get any idle events anymore.
        this is like wxMSW where an idle event is sent only
        once each time after the event queue has been completely
        emptied */
     g_isIdle = TRUE;
        in idle mode that we don't get any idle events anymore.
        this is like wxMSW where an idle event is sent only
        once each time after the event queue has been completely
        emptied */
     g_isIdle = TRUE;
+    wxTheApp->m_idleTag = 0;
 
 
-    /* sent idle event to all who request them */
-    while (wxTheApp->ProcessIdle()) { }
+    // Sent idle event to all who request them as long as they do
+    while (wxTheApp->ProcessIdle())
+        ;
 
 
-    // release lock again
+    // Release lock again
     gdk_threads_leave();
 
     gdk_threads_leave();
 
-    return TRUE;
+    // Return FALSE to indicate that no more idle events are
+    // to be sent (single shot instead of continuous stream)
+    return FALSE;
 }
 
 void wxapp_install_idle_handler()
 {
     wxASSERT_MSG( wxTheApp->m_idleTag == 0, wxT("attempt to install idle handler twice") );
 
 }
 
 void wxapp_install_idle_handler()
 {
     wxASSERT_MSG( wxTheApp->m_idleTag == 0, wxT("attempt to install idle handler twice") );
 
+    g_isIdle = FALSE;
+
+    if (g_pendingTag == 0)
+        g_pendingTag = gtk_idle_add_priority( 900, wxapp_pending_callback, (gpointer) NULL );
+
     /* This routine gets called by all event handlers
        indicating that the idle is over. It may also
        get called from other thread for sending events
     /* This routine gets called by all event handlers
        indicating that the idle is over. It may also
        get called from other thread for sending events
@@ -180,14 +248,18 @@ void wxapp_install_idle_handler()
        idle time). Very low priority. */
 
     wxTheApp->m_idleTag = gtk_idle_add_priority( 1000, wxapp_idle_callback, (gpointer) NULL );
        idle time). Very low priority. */
 
     wxTheApp->m_idleTag = gtk_idle_add_priority( 1000, wxapp_idle_callback, (gpointer) NULL );
-
-    g_isIdle = FALSE;
 }
 
 #if wxUSE_THREADS
 
 }
 
 #if wxUSE_THREADS
 
+static int g_threadUninstallLevel = 0;
+
 void wxapp_install_thread_wakeup()
 {
 void wxapp_install_thread_wakeup()
 {
+    g_threadUninstallLevel++;
+
+    if (g_threadUninstallLevel != 1) return;
+
     if (wxTheApp->m_wakeUpTimerTag) return;
 
     wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 50, wxapp_wakeup_timerout_callback, (gpointer) NULL );
     if (wxTheApp->m_wakeUpTimerTag) return;
 
     wxTheApp->m_wakeUpTimerTag = gtk_timeout_add( 50, wxapp_wakeup_timerout_callback, (gpointer) NULL );
@@ -195,6 +267,10 @@ void wxapp_install_thread_wakeup()
 
 void wxapp_uninstall_thread_wakeup()
 {
 
 void wxapp_uninstall_thread_wakeup()
 {
+    g_threadUninstallLevel--;
+
+    if (g_threadUninstallLevel != 0) return;
+
     if (!wxTheApp->m_wakeUpTimerTag) return;
 
     gtk_timeout_remove( wxTheApp->m_wakeUpTimerTag );
     if (!wxTheApp->m_wakeUpTimerTag) return;
 
     gtk_timeout_remove( wxTheApp->m_wakeUpTimerTag );
@@ -245,12 +321,13 @@ END_EVENT_TABLE()
 
 wxApp::wxApp()
 {
 
 wxApp::wxApp()
 {
-    wxTheApp = this;
-
-    m_topWindow = (wxWindow *) NULL;
-    m_exitOnFrameDelete = TRUE;
+    m_initialized = FALSE;
+#ifdef __WXDEBUG__
+    m_isInAssert = FALSE;
+#endif // __WXDEBUG__
 
 
-    m_idleTag = gtk_idle_add_priority( 1000, wxapp_idle_callback, (gpointer) NULL );
+    m_idleTag = 0;
+    wxapp_install_idle_handler();
 
 #if wxUSE_THREADS
     m_wakeUpTimerTag = 0;
 
 #if wxUSE_THREADS
     m_wakeUpTimerTag = 0;
@@ -258,8 +335,6 @@ wxApp::wxApp()
 #endif
 
     m_colorCube = (unsigned char*) NULL;
 #endif
 
     m_colorCube = (unsigned char*) NULL;
-
-    m_useBestVisual = FALSE;
 }
 
 wxApp::~wxApp()
 }
 
 wxApp::~wxApp()
@@ -275,6 +350,9 @@ wxApp::~wxApp()
 
 bool wxApp::OnInitGui()
 {
 
 bool wxApp::OnInitGui()
 {
+    if ( !wxAppBase::OnInitGui() )
+        return FALSE;
+
     GdkVisual *visual = gdk_visual_get_system();
 
     /* on some machines, the default visual is just 256 colours, so
     GdkVisual *visual = gdk_visual_get_system();
 
     /* on some machines, the default visual is just 256 colours, so
@@ -390,11 +468,6 @@ void wxApp::OnIdle( wxIdleEvent &event )
         event.RequestMore(TRUE);
 
     s_inOnIdle = FALSE;
         event.RequestMore(TRUE);
 
     s_inOnIdle = FALSE;
-
-    /* flush the logged messages if any */
-#if wxUSE_LOG
-    wxLog::FlushActive();
-#endif // wxUSE_LOG
 }
 
 bool wxApp::SendIdleEvents()
 }
 
 bool wxApp::SendIdleEvents()
@@ -489,6 +562,10 @@ bool wxApp::Initialize()
     wxClassInfo::InitializeClasses();
 
     wxSystemSettings::Init();
     wxClassInfo::InitializeClasses();
 
     wxSystemSettings::Init();
+    
+#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.
 
     // 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.
@@ -566,6 +643,19 @@ void wxApp::CleanUp()
 #endif // wxUSE_LOG
 }
 
 #endif // wxUSE_LOG
 }
 
+//-----------------------------------------------------------------------------
+// Access to the root window global
+//-----------------------------------------------------------------------------
+
+GtkWidget* wxGetRootWindow()
+{
+    if (gs_RootWindow == NULL) {
+        gs_RootWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+        gtk_widget_realize( gs_RootWindow );
+    }
+    return gs_RootWindow;
+}
+
 //-----------------------------------------------------------------------------
 // wxEntry
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // wxEntry
 //-----------------------------------------------------------------------------
@@ -578,7 +668,7 @@ int wxEntryStart( int argc, char *argv[] )
    if ((gtk_major_version == 1) &&
         (gtk_minor_version == 2) &&
         (gtk_micro_version < 4))
    if ((gtk_major_version == 1) &&
         (gtk_minor_version == 2) &&
         (gtk_micro_version < 4))
-     {
+    {
         printf( "wxWindows warning: GUI threading disabled due to outdated GTK version\n" );
     }
     else
         printf( "wxWindows warning: GUI threading disabled due to outdated GTK version\n" );
     }
     else
@@ -589,11 +679,14 @@ int wxEntryStart( int argc, char *argv[] )
 
     gtk_set_locale();
 
 
     gtk_set_locale();
 
+    // We should have the wxUSE_WCHAR_T test on the _outside_
+#if wxUSE_WCHAR_T
 #if defined(__WXGTK20__)
     // gtk+ 2.0 supports Unicode through UTF-8 strings
     wxConvCurrent = &wxConvUTF8;
 #if defined(__WXGTK20__)
     // gtk+ 2.0 supports Unicode through UTF-8 strings
     wxConvCurrent = &wxConvUTF8;
-#elif wxUSE_WCHAR_T
+#else
     if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
     if (!wxOKlibc()) wxConvCurrent = &wxConvLocal;
+#endif
 #else
     if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL;
 #endif
 #else
     if (!wxOKlibc()) wxConvCurrent = (wxMBConv*) NULL;
 #endif
@@ -621,8 +714,7 @@ int wxEntryInitGui()
     if ( !wxTheApp->OnInitGui() )
         retValue = -1;
 
     if ( !wxTheApp->OnInitGui() )
         retValue = -1;
 
-    wxRootWindow = gtk_window_new( GTK_WINDOW_TOPLEVEL );
-    gtk_widget_realize( wxRootWindow );
+    wxGetRootWindow();
 
     return retValue;
 }
 
     return retValue;
 }
@@ -775,3 +867,17 @@ wxApp::GetStdIcon(int which) const
             return wxIcon(error_xpm);
     }
 }
             return wxIcon(error_xpm);
     }
 }
+
+#ifdef __WXDEBUG__
+
+void wxApp::OnAssert(const wxChar *file, int line, const wxChar *msg)
+{
+    m_isInAssert = TRUE;
+
+    wxAppBase::OnAssert(file, line, msg);
+
+    m_isInAssert = FALSE;
+}
+
+#endif // __WXDEBUG__
+